12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068230692307023071230722307323074230752307623077230782307923080230812308223083230842308523086230872308823089230902309123092230932309423095230962309723098230992310023101231022310323104231052310623107231082310923110231112311223113231142311523116231172311823119231202312123122231232312423125231262312723128231292313023131231322313323134231352313623137231382313923140231412314223143231442314523146231472314823149231502315123152231532315423155231562315723158231592316023161231622316323164231652316623167231682316923170231712317223173231742317523176231772317823179231802318123182231832318423185231862318723188231892319023191231922319323194231952319623197231982319923200232012320223203232042320523206232072320823209232102321123212232132321423215232162321723218232192322023221232222322323224232252322623227232282322923230232312323223233232342323523236232372323823239232402324123242232432324423245232462324723248232492325023251232522325323254232552325623257232582325923260232612326223263232642326523266232672326823269232702327123272232732327423275232762327723278232792328023281232822328323284232852328623287232882328923290232912329223293232942329523296232972329823299233002330123302233032330423305233062330723308233092331023311233122331323314233152331623317233182331923320233212332223323233242332523326233272332823329233302333123332233332333423335233362333723338233392334023341233422334323344233452334623347233482334923350233512335223353233542335523356233572335823359233602336123362233632336423365233662336723368233692337023371233722337323374233752337623377233782337923380233812338223383233842338523386233872338823389233902339123392233932339423395233962339723398233992340023401234022340323404234052340623407234082340923410234112341223413234142341523416234172341823419234202342123422234232342423425234262342723428234292343023431234322343323434234352343623437234382343923440234412344223443234442344523446234472344823449234502345123452234532345423455234562345723458234592346023461234622346323464234652346623467234682346923470234712347223473234742347523476234772347823479234802348123482234832348423485234862348723488234892349023491234922349323494234952349623497234982349923500235012350223503235042350523506235072350823509235102351123512235132351423515235162351723518235192352023521235222352323524235252352623527235282352923530235312353223533235342353523536235372353823539235402354123542235432354423545235462354723548235492355023551235522355323554235552355623557235582355923560235612356223563235642356523566235672356823569235702357123572235732357423575235762357723578235792358023581235822358323584235852358623587235882358923590235912359223593235942359523596235972359823599236002360123602236032360423605236062360723608236092361023611236122361323614236152361623617236182361923620236212362223623236242362523626236272362823629236302363123632236332363423635236362363723638236392364023641236422364323644236452364623647236482364923650236512365223653236542365523656236572365823659236602366123662236632366423665236662366723668236692367023671236722367323674236752367623677236782367923680236812368223683236842368523686236872368823689236902369123692236932369423695236962369723698236992370023701237022370323704237052370623707237082370923710237112371223713237142371523716237172371823719237202372123722237232372423725237262372723728237292373023731237322373323734237352373623737237382373923740237412374223743237442374523746237472374823749237502375123752237532375423755237562375723758237592376023761237622376323764237652376623767237682376923770237712377223773237742377523776237772377823779237802378123782237832378423785237862378723788237892379023791237922379323794237952379623797237982379923800238012380223803238042380523806238072380823809238102381123812238132381423815238162381723818238192382023821238222382323824238252382623827238282382923830238312383223833238342383523836238372383823839238402384123842238432384423845238462384723848238492385023851238522385323854238552385623857238582385923860238612386223863238642386523866238672386823869238702387123872238732387423875238762387723878238792388023881238822388323884238852388623887238882388923890238912389223893238942389523896238972389823899239002390123902239032390423905239062390723908239092391023911239122391323914239152391623917239182391923920239212392223923239242392523926239272392823929239302393123932239332393423935239362393723938239392394023941239422394323944239452394623947239482394923950239512395223953239542395523956239572395823959239602396123962239632396423965239662396723968239692397023971239722397323974239752397623977239782397923980239812398223983239842398523986239872398823989239902399123992239932399423995239962399723998239992400024001240022400324004240052400624007240082400924010240112401224013240142401524016240172401824019240202402124022240232402424025240262402724028240292403024031240322403324034240352403624037240382403924040240412404224043240442404524046240472404824049240502405124052240532405424055240562405724058240592406024061240622406324064240652406624067240682406924070240712407224073240742407524076240772407824079240802408124082240832408424085240862408724088240892409024091240922409324094240952409624097240982409924100241012410224103241042410524106241072410824109241102411124112241132411424115241162411724118241192412024121241222412324124241252412624127241282412924130241312413224133241342413524136241372413824139241402414124142241432414424145241462414724148241492415024151241522415324154241552415624157241582415924160241612416224163241642416524166241672416824169241702417124172241732417424175241762417724178241792418024181241822418324184241852418624187241882418924190241912419224193241942419524196241972419824199242002420124202242032420424205242062420724208242092421024211242122421324214242152421624217242182421924220242212422224223242242422524226242272422824229242302423124232242332423424235242362423724238242392424024241242422424324244242452424624247242482424924250242512425224253242542425524256242572425824259242602426124262242632426424265242662426724268242692427024271242722427324274242752427624277242782427924280242812428224283242842428524286242872428824289242902429124292242932429424295242962429724298242992430024301243022430324304243052430624307243082430924310243112431224313243142431524316243172431824319243202432124322243232432424325243262432724328243292433024331243322433324334243352433624337243382433924340243412434224343243442434524346243472434824349243502435124352243532435424355243562435724358243592436024361243622436324364243652436624367243682436924370243712437224373243742437524376243772437824379243802438124382243832438424385243862438724388243892439024391243922439324394243952439624397243982439924400244012440224403244042440524406244072440824409244102441124412244132441424415244162441724418244192442024421244222442324424244252442624427244282442924430244312443224433244342443524436244372443824439244402444124442244432444424445244462444724448244492445024451244522445324454244552445624457244582445924460244612446224463244642446524466244672446824469244702447124472244732447424475244762447724478244792448024481244822448324484244852448624487244882448924490244912449224493244942449524496244972449824499245002450124502245032450424505245062450724508245092451024511245122451324514245152451624517245182451924520245212452224523245242452524526245272452824529245302453124532245332453424535245362453724538245392454024541245422454324544245452454624547245482454924550245512455224553245542455524556245572455824559245602456124562245632456424565245662456724568245692457024571245722457324574245752457624577245782457924580245812458224583245842458524586245872458824589245902459124592245932459424595245962459724598245992460024601246022460324604246052460624607246082460924610246112461224613246142461524616246172461824619246202462124622246232462424625246262462724628246292463024631246322463324634246352463624637246382463924640246412464224643246442464524646246472464824649246502465124652246532465424655246562465724658246592466024661246622466324664246652466624667246682466924670246712467224673246742467524676246772467824679246802468124682246832468424685246862468724688246892469024691246922469324694246952469624697246982469924700247012470224703247042470524706247072470824709247102471124712247132471424715247162471724718247192472024721247222472324724247252472624727247282472924730247312473224733247342473524736247372473824739247402474124742247432474424745247462474724748247492475024751247522475324754247552475624757247582475924760247612476224763247642476524766247672476824769247702477124772247732477424775247762477724778247792478024781247822478324784247852478624787247882478924790247912479224793247942479524796247972479824799248002480124802248032480424805248062480724808248092481024811248122481324814248152481624817248182481924820248212482224823248242482524826248272482824829248302483124832248332483424835248362483724838248392484024841248422484324844248452484624847248482484924850248512485224853248542485524856248572485824859248602486124862248632486424865248662486724868248692487024871248722487324874248752487624877248782487924880248812488224883248842488524886248872488824889248902489124892248932489424895248962489724898248992490024901249022490324904249052490624907249082490924910249112491224913249142491524916249172491824919249202492124922249232492424925249262492724928249292493024931249322493324934249352493624937249382493924940249412494224943249442494524946249472494824949249502495124952249532495424955249562495724958249592496024961249622496324964249652496624967249682496924970249712497224973249742497524976249772497824979249802498124982249832498424985249862498724988249892499024991249922499324994249952499624997249982499925000250012500225003250042500525006250072500825009250102501125012250132501425015250162501725018250192502025021250222502325024250252502625027250282502925030250312503225033250342503525036250372503825039250402504125042250432504425045250462504725048250492505025051250522505325054250552505625057250582505925060250612506225063250642506525066250672506825069250702507125072250732507425075250762507725078250792508025081250822508325084250852508625087250882508925090250912509225093250942509525096250972509825099251002510125102251032510425105251062510725108251092511025111251122511325114251152511625117251182511925120251212512225123251242512525126251272512825129251302513125132251332513425135251362513725138251392514025141251422514325144251452514625147251482514925150251512515225153251542515525156251572515825159251602516125162251632516425165251662516725168251692517025171251722517325174251752517625177251782517925180251812518225183251842518525186251872518825189251902519125192251932519425195251962519725198251992520025201252022520325204252052520625207252082520925210252112521225213252142521525216252172521825219252202522125222252232522425225252262522725228252292523025231252322523325234252352523625237252382523925240252412524225243252442524525246252472524825249252502525125252252532525425255252562525725258252592526025261252622526325264252652526625267252682526925270252712527225273252742527525276252772527825279252802528125282252832528425285252862528725288252892529025291252922529325294252952529625297252982529925300253012530225303253042530525306253072530825309253102531125312253132531425315253162531725318253192532025321253222532325324253252532625327253282532925330253312533225333253342533525336253372533825339253402534125342253432534425345253462534725348253492535025351253522535325354253552535625357253582535925360253612536225363253642536525366253672536825369253702537125372253732537425375253762537725378253792538025381253822538325384253852538625387253882538925390253912539225393253942539525396253972539825399254002540125402254032540425405254062540725408254092541025411254122541325414254152541625417254182541925420254212542225423254242542525426254272542825429254302543125432254332543425435254362543725438254392544025441254422544325444254452544625447254482544925450254512545225453254542545525456254572545825459254602546125462254632546425465254662546725468254692547025471254722547325474254752547625477254782547925480254812548225483254842548525486254872548825489254902549125492254932549425495254962549725498254992550025501255022550325504255052550625507255082550925510255112551225513255142551525516255172551825519255202552125522255232552425525255262552725528255292553025531255322553325534255352553625537255382553925540255412554225543255442554525546255472554825549255502555125552255532555425555255562555725558255592556025561255622556325564255652556625567255682556925570255712557225573255742557525576255772557825579255802558125582255832558425585255862558725588255892559025591255922559325594255952559625597255982559925600256012560225603256042560525606256072560825609256102561125612256132561425615256162561725618256192562025621256222562325624256252562625627256282562925630256312563225633256342563525636256372563825639256402564125642256432564425645256462564725648256492565025651256522565325654256552565625657256582565925660256612566225663256642566525666256672566825669256702567125672256732567425675256762567725678256792568025681256822568325684256852568625687256882568925690256912569225693256942569525696256972569825699257002570125702257032570425705257062570725708257092571025711257122571325714257152571625717257182571925720257212572225723257242572525726257272572825729257302573125732257332573425735257362573725738257392574025741257422574325744257452574625747257482574925750257512575225753257542575525756257572575825759257602576125762257632576425765257662576725768257692577025771257722577325774257752577625777257782577925780257812578225783257842578525786257872578825789257902579125792257932579425795257962579725798257992580025801258022580325804258052580625807258082580925810258112581225813258142581525816258172581825819258202582125822258232582425825258262582725828258292583025831258322583325834258352583625837258382583925840258412584225843258442584525846258472584825849258502585125852258532585425855258562585725858258592586025861258622586325864258652586625867258682586925870258712587225873258742587525876258772587825879258802588125882258832588425885258862588725888258892589025891258922589325894258952589625897258982589925900259012590225903259042590525906259072590825909259102591125912259132591425915259162591725918259192592025921259222592325924259252592625927259282592925930259312593225933259342593525936259372593825939259402594125942259432594425945259462594725948259492595025951259522595325954259552595625957259582595925960259612596225963259642596525966259672596825969259702597125972259732597425975259762597725978259792598025981259822598325984259852598625987259882598925990259912599225993259942599525996259972599825999260002600126002260032600426005260062600726008260092601026011260122601326014260152601626017260182601926020260212602226023260242602526026260272602826029260302603126032260332603426035260362603726038260392604026041260422604326044260452604626047260482604926050260512605226053260542605526056260572605826059260602606126062260632606426065260662606726068260692607026071260722607326074260752607626077260782607926080260812608226083260842608526086260872608826089260902609126092260932609426095260962609726098260992610026101261022610326104261052610626107261082610926110261112611226113261142611526116261172611826119261202612126122261232612426125261262612726128261292613026131261322613326134261352613626137261382613926140261412614226143261442614526146261472614826149261502615126152261532615426155261562615726158261592616026161261622616326164261652616626167261682616926170261712617226173261742617526176261772617826179261802618126182261832618426185261862618726188261892619026191261922619326194261952619626197261982619926200262012620226203262042620526206262072620826209262102621126212262132621426215262162621726218262192622026221262222622326224262252622626227262282622926230262312623226233262342623526236262372623826239262402624126242262432624426245262462624726248262492625026251262522625326254262552625626257262582625926260262612626226263262642626526266262672626826269262702627126272262732627426275262762627726278262792628026281262822628326284262852628626287262882628926290262912629226293262942629526296262972629826299263002630126302263032630426305263062630726308263092631026311263122631326314263152631626317263182631926320263212632226323263242632526326263272632826329263302633126332263332633426335263362633726338263392634026341263422634326344263452634626347263482634926350263512635226353263542635526356263572635826359263602636126362263632636426365263662636726368263692637026371263722637326374263752637626377263782637926380263812638226383263842638526386263872638826389263902639126392263932639426395263962639726398263992640026401264022640326404264052640626407264082640926410264112641226413264142641526416264172641826419264202642126422264232642426425264262642726428264292643026431264322643326434264352643626437264382643926440264412644226443264442644526446264472644826449264502645126452264532645426455264562645726458264592646026461264622646326464264652646626467264682646926470264712647226473264742647526476264772647826479264802648126482264832648426485264862648726488264892649026491264922649326494264952649626497264982649926500265012650226503265042650526506265072650826509265102651126512265132651426515265162651726518265192652026521265222652326524265252652626527265282652926530265312653226533265342653526536265372653826539265402654126542265432654426545265462654726548265492655026551265522655326554265552655626557265582655926560265612656226563265642656526566265672656826569265702657126572265732657426575265762657726578265792658026581265822658326584265852658626587265882658926590265912659226593265942659526596265972659826599266002660126602266032660426605266062660726608266092661026611266122661326614266152661626617266182661926620266212662226623266242662526626266272662826629266302663126632266332663426635266362663726638266392664026641266422664326644266452664626647266482664926650266512665226653266542665526656266572665826659266602666126662266632666426665266662666726668266692667026671266722667326674266752667626677266782667926680266812668226683266842668526686266872668826689266902669126692266932669426695266962669726698266992670026701267022670326704267052670626707267082670926710267112671226713267142671526716267172671826719267202672126722267232672426725267262672726728267292673026731267322673326734267352673626737267382673926740267412674226743267442674526746267472674826749267502675126752267532675426755267562675726758267592676026761267622676326764267652676626767267682676926770267712677226773267742677526776267772677826779267802678126782267832678426785267862678726788267892679026791267922679326794267952679626797267982679926800268012680226803268042680526806268072680826809268102681126812268132681426815268162681726818268192682026821268222682326824268252682626827268282682926830268312683226833268342683526836268372683826839268402684126842268432684426845268462684726848268492685026851268522685326854268552685626857268582685926860268612686226863268642686526866268672686826869268702687126872268732687426875268762687726878268792688026881268822688326884268852688626887268882688926890268912689226893268942689526896268972689826899269002690126902269032690426905269062690726908269092691026911269122691326914269152691626917269182691926920269212692226923269242692526926269272692826929269302693126932269332693426935269362693726938269392694026941269422694326944269452694626947269482694926950269512695226953269542695526956269572695826959269602696126962269632696426965269662696726968269692697026971269722697326974269752697626977269782697926980269812698226983269842698526986269872698826989269902699126992269932699426995269962699726998269992700027001270022700327004270052700627007270082700927010270112701227013270142701527016270172701827019270202702127022270232702427025270262702727028270292703027031270322703327034270352703627037270382703927040270412704227043270442704527046270472704827049270502705127052270532705427055270562705727058270592706027061270622706327064270652706627067270682706927070270712707227073270742707527076270772707827079270802708127082270832708427085270862708727088270892709027091270922709327094270952709627097270982709927100271012710227103271042710527106271072710827109271102711127112271132711427115271162711727118271192712027121271222712327124271252712627127271282712927130271312713227133271342713527136271372713827139271402714127142271432714427145271462714727148271492715027151271522715327154271552715627157271582715927160271612716227163271642716527166271672716827169271702717127172271732717427175271762717727178271792718027181271822718327184271852718627187271882718927190271912719227193271942719527196271972719827199272002720127202272032720427205272062720727208272092721027211272122721327214272152721627217272182721927220272212722227223272242722527226272272722827229272302723127232272332723427235272362723727238272392724027241272422724327244272452724627247272482724927250272512725227253272542725527256272572725827259272602726127262272632726427265272662726727268272692727027271272722727327274272752727627277272782727927280272812728227283272842728527286272872728827289272902729127292272932729427295272962729727298272992730027301273022730327304273052730627307273082730927310273112731227313273142731527316273172731827319273202732127322273232732427325273262732727328273292733027331273322733327334273352733627337273382733927340273412734227343273442734527346273472734827349273502735127352273532735427355273562735727358273592736027361273622736327364273652736627367273682736927370273712737227373273742737527376273772737827379273802738127382273832738427385273862738727388273892739027391273922739327394273952739627397273982739927400274012740227403274042740527406274072740827409274102741127412274132741427415274162741727418274192742027421274222742327424274252742627427274282742927430274312743227433274342743527436274372743827439274402744127442274432744427445274462744727448274492745027451274522745327454274552745627457274582745927460274612746227463274642746527466274672746827469274702747127472274732747427475274762747727478274792748027481274822748327484274852748627487274882748927490274912749227493274942749527496274972749827499275002750127502275032750427505275062750727508275092751027511275122751327514275152751627517275182751927520275212752227523275242752527526275272752827529275302753127532275332753427535275362753727538275392754027541275422754327544275452754627547275482754927550275512755227553275542755527556275572755827559275602756127562275632756427565275662756727568275692757027571275722757327574275752757627577275782757927580275812758227583275842758527586275872758827589275902759127592275932759427595275962759727598275992760027601276022760327604276052760627607276082760927610276112761227613276142761527616276172761827619276202762127622276232762427625276262762727628276292763027631276322763327634276352763627637276382763927640276412764227643276442764527646276472764827649276502765127652276532765427655276562765727658276592766027661276622766327664276652766627667276682766927670276712767227673276742767527676276772767827679276802768127682276832768427685276862768727688276892769027691276922769327694276952769627697276982769927700277012770227703277042770527706277072770827709277102771127712277132771427715277162771727718277192772027721277222772327724277252772627727277282772927730277312773227733277342773527736277372773827739277402774127742277432774427745277462774727748277492775027751277522775327754277552775627757277582775927760277612776227763277642776527766277672776827769277702777127772277732777427775277762777727778277792778027781277822778327784277852778627787277882778927790277912779227793277942779527796277972779827799278002780127802278032780427805278062780727808278092781027811278122781327814278152781627817278182781927820278212782227823278242782527826278272782827829278302783127832278332783427835278362783727838278392784027841278422784327844278452784627847278482784927850278512785227853278542785527856278572785827859278602786127862278632786427865278662786727868278692787027871278722787327874278752787627877278782787927880278812788227883278842788527886278872788827889278902789127892278932789427895278962789727898278992790027901279022790327904279052790627907279082790927910279112791227913279142791527916279172791827919279202792127922279232792427925279262792727928279292793027931279322793327934279352793627937279382793927940279412794227943279442794527946279472794827949279502795127952279532795427955279562795727958279592796027961279622796327964279652796627967279682796927970279712797227973279742797527976279772797827979279802798127982279832798427985279862798727988279892799027991279922799327994279952799627997279982799928000280012800228003280042800528006280072800828009280102801128012280132801428015280162801728018280192802028021280222802328024280252802628027280282802928030280312803228033280342803528036280372803828039280402804128042280432804428045280462804728048280492805028051280522805328054280552805628057280582805928060280612806228063280642806528066280672806828069280702807128072280732807428075280762807728078280792808028081280822808328084280852808628087280882808928090280912809228093280942809528096280972809828099281002810128102281032810428105281062810728108281092811028111281122811328114281152811628117281182811928120281212812228123281242812528126281272812828129281302813128132281332813428135281362813728138281392814028141281422814328144281452814628147281482814928150281512815228153281542815528156281572815828159281602816128162281632816428165281662816728168281692817028171281722817328174281752817628177281782817928180281812818228183281842818528186281872818828189281902819128192281932819428195281962819728198281992820028201282022820328204282052820628207282082820928210282112821228213282142821528216282172821828219282202822128222282232822428225282262822728228282292823028231282322823328234282352823628237282382823928240282412824228243282442824528246282472824828249282502825128252282532825428255282562825728258282592826028261282622826328264282652826628267282682826928270282712827228273282742827528276282772827828279282802828128282282832828428285282862828728288282892829028291282922829328294282952829628297282982829928300283012830228303283042830528306283072830828309283102831128312283132831428315283162831728318283192832028321283222832328324283252832628327283282832928330283312833228333283342833528336283372833828339283402834128342283432834428345283462834728348283492835028351283522835328354283552835628357283582835928360283612836228363283642836528366283672836828369283702837128372283732837428375283762837728378283792838028381283822838328384283852838628387283882838928390283912839228393283942839528396283972839828399284002840128402284032840428405284062840728408284092841028411284122841328414284152841628417284182841928420284212842228423284242842528426284272842828429284302843128432284332843428435284362843728438284392844028441284422844328444284452844628447284482844928450284512845228453284542845528456284572845828459284602846128462284632846428465284662846728468284692847028471284722847328474284752847628477284782847928480284812848228483284842848528486284872848828489284902849128492284932849428495284962849728498284992850028501285022850328504285052850628507285082850928510285112851228513285142851528516285172851828519285202852128522285232852428525285262852728528285292853028531285322853328534285352853628537285382853928540285412854228543285442854528546285472854828549285502855128552285532855428555285562855728558285592856028561285622856328564285652856628567285682856928570285712857228573285742857528576285772857828579285802858128582285832858428585285862858728588285892859028591285922859328594285952859628597285982859928600286012860228603286042860528606286072860828609286102861128612286132861428615286162861728618286192862028621286222862328624286252862628627286282862928630286312863228633286342863528636286372863828639286402864128642286432864428645286462864728648286492865028651286522865328654286552865628657286582865928660286612866228663286642866528666286672866828669286702867128672286732867428675286762867728678286792868028681286822868328684286852868628687286882868928690286912869228693286942869528696286972869828699287002870128702287032870428705287062870728708287092871028711287122871328714287152871628717287182871928720287212872228723287242872528726287272872828729287302873128732287332873428735287362873728738287392874028741287422874328744287452874628747287482874928750287512875228753287542875528756287572875828759287602876128762287632876428765287662876728768287692877028771287722877328774287752877628777287782877928780287812878228783287842878528786287872878828789287902879128792287932879428795287962879728798287992880028801288022880328804288052880628807288082880928810288112881228813288142881528816288172881828819288202882128822288232882428825288262882728828288292883028831288322883328834288352883628837288382883928840288412884228843288442884528846288472884828849288502885128852288532885428855288562885728858288592886028861288622886328864288652886628867288682886928870288712887228873288742887528876288772887828879288802888128882288832888428885288862888728888288892889028891288922889328894288952889628897288982889928900289012890228903289042890528906289072890828909289102891128912289132891428915289162891728918289192892028921289222892328924289252892628927289282892928930289312893228933289342893528936289372893828939289402894128942289432894428945289462894728948289492895028951289522895328954289552895628957289582895928960289612896228963289642896528966289672896828969289702897128972289732897428975289762897728978289792898028981289822898328984289852898628987289882898928990289912899228993289942899528996289972899828999290002900129002290032900429005290062900729008290092901029011290122901329014290152901629017290182901929020290212902229023290242902529026290272902829029290302903129032290332903429035290362903729038290392904029041290422904329044290452904629047290482904929050290512905229053290542905529056290572905829059290602906129062290632906429065290662906729068290692907029071290722907329074290752907629077290782907929080290812908229083290842908529086290872908829089290902909129092290932909429095290962909729098290992910029101291022910329104291052910629107291082910929110291112911229113291142911529116291172911829119291202912129122291232912429125291262912729128291292913029131291322913329134291352913629137291382913929140291412914229143291442914529146291472914829149291502915129152291532915429155291562915729158291592916029161291622916329164291652916629167291682916929170291712917229173291742917529176291772917829179291802918129182291832918429185291862918729188291892919029191291922919329194291952919629197291982919929200292012920229203292042920529206292072920829209292102921129212292132921429215292162921729218292192922029221292222922329224292252922629227292282922929230292312923229233292342923529236292372923829239292402924129242292432924429245292462924729248292492925029251292522925329254292552925629257292582925929260292612926229263292642926529266292672926829269292702927129272292732927429275292762927729278292792928029281292822928329284292852928629287292882928929290292912929229293292942929529296292972929829299293002930129302293032930429305293062930729308293092931029311293122931329314293152931629317293182931929320293212932229323293242932529326293272932829329293302933129332293332933429335293362933729338293392934029341293422934329344293452934629347293482934929350293512935229353293542935529356293572935829359293602936129362293632936429365293662936729368293692937029371293722937329374293752937629377293782937929380293812938229383293842938529386293872938829389293902939129392293932939429395293962939729398293992940029401294022940329404294052940629407294082940929410294112941229413294142941529416294172941829419294202942129422294232942429425294262942729428294292943029431294322943329434294352943629437294382943929440294412944229443294442944529446294472944829449294502945129452294532945429455294562945729458294592946029461294622946329464294652946629467294682946929470294712947229473294742947529476294772947829479294802948129482294832948429485294862948729488294892949029491294922949329494294952949629497294982949929500295012950229503295042950529506295072950829509295102951129512295132951429515295162951729518295192952029521295222952329524295252952629527295282952929530295312953229533295342953529536295372953829539295402954129542295432954429545295462954729548295492955029551295522955329554295552955629557295582955929560295612956229563295642956529566295672956829569295702957129572295732957429575295762957729578295792958029581295822958329584295852958629587295882958929590295912959229593295942959529596295972959829599296002960129602296032960429605296062960729608296092961029611296122961329614296152961629617296182961929620296212962229623296242962529626296272962829629296302963129632296332963429635296362963729638296392964029641296422964329644296452964629647296482964929650296512965229653296542965529656296572965829659296602966129662296632966429665296662966729668296692967029671296722967329674296752967629677296782967929680296812968229683296842968529686296872968829689296902969129692296932969429695296962969729698296992970029701297022970329704297052970629707297082970929710297112971229713297142971529716297172971829719297202972129722297232972429725297262972729728297292973029731297322973329734297352973629737297382973929740297412974229743297442974529746297472974829749297502975129752297532975429755297562975729758297592976029761297622976329764297652976629767297682976929770297712977229773297742977529776297772977829779297802978129782297832978429785297862978729788297892979029791297922979329794297952979629797297982979929800298012980229803298042980529806298072980829809298102981129812298132981429815298162981729818298192982029821298222982329824298252982629827298282982929830298312983229833298342983529836298372983829839298402984129842298432984429845298462984729848298492985029851298522985329854298552985629857298582985929860298612986229863298642986529866298672986829869298702987129872298732987429875298762987729878298792988029881298822988329884298852988629887298882988929890298912989229893298942989529896298972989829899299002990129902299032990429905299062990729908299092991029911299122991329914299152991629917299182991929920299212992229923299242992529926299272992829929299302993129932299332993429935299362993729938299392994029941299422994329944299452994629947299482994929950299512995229953299542995529956299572995829959299602996129962299632996429965299662996729968299692997029971299722997329974299752997629977299782997929980299812998229983299842998529986299872998829989299902999129992299932999429995299962999729998299993000030001300023000330004300053000630007300083000930010300113001230013300143001530016300173001830019300203002130022300233002430025300263002730028300293003030031300323003330034300353003630037300383003930040300413004230043300443004530046300473004830049300503005130052300533005430055300563005730058300593006030061300623006330064300653006630067300683006930070300713007230073300743007530076300773007830079300803008130082300833008430085300863008730088300893009030091300923009330094300953009630097300983009930100301013010230103301043010530106301073010830109301103011130112301133011430115301163011730118301193012030121301223012330124301253012630127301283012930130301313013230133301343013530136301373013830139301403014130142301433014430145301463014730148301493015030151301523015330154301553015630157301583015930160301613016230163301643016530166301673016830169301703017130172301733017430175301763017730178301793018030181301823018330184301853018630187301883018930190301913019230193301943019530196301973019830199302003020130202302033020430205302063020730208302093021030211302123021330214302153021630217302183021930220302213022230223302243022530226302273022830229302303023130232302333023430235302363023730238302393024030241302423024330244302453024630247302483024930250302513025230253302543025530256302573025830259302603026130262302633026430265302663026730268302693027030271302723027330274302753027630277302783027930280302813028230283302843028530286302873028830289302903029130292302933029430295302963029730298302993030030301303023030330304303053030630307303083030930310303113031230313303143031530316303173031830319303203032130322303233032430325303263032730328303293033030331303323033330334303353033630337303383033930340303413034230343303443034530346303473034830349303503035130352303533035430355303563035730358303593036030361303623036330364303653036630367303683036930370303713037230373303743037530376303773037830379303803038130382303833038430385303863038730388303893039030391303923039330394303953039630397303983039930400304013040230403304043040530406304073040830409304103041130412304133041430415304163041730418304193042030421304223042330424304253042630427304283042930430304313043230433304343043530436304373043830439304403044130442304433044430445304463044730448304493045030451304523045330454304553045630457304583045930460304613046230463304643046530466304673046830469304703047130472304733047430475304763047730478304793048030481304823048330484304853048630487304883048930490304913049230493304943049530496304973049830499305003050130502305033050430505305063050730508305093051030511305123051330514305153051630517305183051930520305213052230523305243052530526305273052830529305303053130532305333053430535305363053730538305393054030541305423054330544305453054630547305483054930550305513055230553305543055530556305573055830559305603056130562305633056430565305663056730568305693057030571305723057330574305753057630577305783057930580305813058230583305843058530586305873058830589305903059130592305933059430595305963059730598305993060030601306023060330604306053060630607306083060930610306113061230613306143061530616306173061830619306203062130622306233062430625306263062730628306293063030631306323063330634306353063630637306383063930640306413064230643306443064530646306473064830649306503065130652306533065430655306563065730658306593066030661306623066330664306653066630667306683066930670306713067230673306743067530676306773067830679306803068130682306833068430685306863068730688306893069030691306923069330694306953069630697306983069930700307013070230703307043070530706307073070830709307103071130712307133071430715307163071730718307193072030721307223072330724307253072630727307283072930730307313073230733307343073530736307373073830739307403074130742307433074430745307463074730748307493075030751307523075330754307553075630757307583075930760307613076230763307643076530766307673076830769307703077130772307733077430775307763077730778307793078030781307823078330784307853078630787307883078930790307913079230793307943079530796307973079830799308003080130802308033080430805308063080730808308093081030811308123081330814308153081630817308183081930820308213082230823308243082530826308273082830829308303083130832308333083430835308363083730838308393084030841308423084330844308453084630847308483084930850308513085230853308543085530856308573085830859308603086130862308633086430865308663086730868308693087030871308723087330874308753087630877308783087930880308813088230883308843088530886308873088830889308903089130892308933089430895308963089730898308993090030901309023090330904309053090630907309083090930910309113091230913309143091530916309173091830919309203092130922309233092430925309263092730928309293093030931309323093330934309353093630937309383093930940309413094230943309443094530946309473094830949309503095130952309533095430955309563095730958309593096030961309623096330964309653096630967309683096930970309713097230973309743097530976309773097830979309803098130982309833098430985309863098730988309893099030991309923099330994309953099630997309983099931000310013100231003310043100531006310073100831009310103101131012310133101431015310163101731018310193102031021310223102331024310253102631027310283102931030310313103231033310343103531036310373103831039310403104131042310433104431045310463104731048310493105031051310523105331054310553105631057310583105931060310613106231063310643106531066310673106831069310703107131072310733107431075310763107731078310793108031081310823108331084310853108631087310883108931090310913109231093310943109531096310973109831099311003110131102311033110431105311063110731108311093111031111311123111331114311153111631117311183111931120311213112231123311243112531126311273112831129311303113131132311333113431135311363113731138311393114031141311423114331144311453114631147311483114931150311513115231153311543115531156311573115831159311603116131162311633116431165311663116731168311693117031171311723117331174311753117631177311783117931180311813118231183311843118531186311873118831189311903119131192311933119431195311963119731198311993120031201312023120331204312053120631207312083120931210312113121231213312143121531216312173121831219312203122131222312233122431225312263122731228312293123031231312323123331234312353123631237312383123931240312413124231243312443124531246312473124831249312503125131252312533125431255312563125731258312593126031261312623126331264312653126631267312683126931270312713127231273312743127531276312773127831279312803128131282312833128431285312863128731288312893129031291312923129331294312953129631297312983129931300313013130231303313043130531306313073130831309313103131131312313133131431315313163131731318313193132031321313223132331324313253132631327313283132931330313313133231333313343133531336313373133831339313403134131342313433134431345313463134731348313493135031351313523135331354313553135631357313583135931360313613136231363313643136531366313673136831369313703137131372313733137431375313763137731378313793138031381313823138331384313853138631387313883138931390313913139231393313943139531396313973139831399314003140131402314033140431405314063140731408314093141031411314123141331414314153141631417314183141931420314213142231423314243142531426314273142831429314303143131432314333143431435314363143731438314393144031441314423144331444314453144631447314483144931450314513145231453314543145531456314573145831459314603146131462314633146431465314663146731468314693147031471314723147331474314753147631477314783147931480314813148231483314843148531486314873148831489314903149131492314933149431495314963149731498314993150031501315023150331504315053150631507315083150931510315113151231513315143151531516315173151831519315203152131522315233152431525315263152731528315293153031531315323153331534315353153631537315383153931540315413154231543315443154531546315473154831549315503155131552315533155431555315563155731558315593156031561315623156331564315653156631567315683156931570315713157231573315743157531576315773157831579315803158131582315833158431585315863158731588315893159031591315923159331594315953159631597315983159931600316013160231603316043160531606316073160831609316103161131612316133161431615316163161731618316193162031621316223162331624316253162631627316283162931630316313163231633316343163531636316373163831639316403164131642316433164431645316463164731648316493165031651316523165331654316553165631657316583165931660316613166231663316643166531666316673166831669316703167131672316733167431675316763167731678316793168031681316823168331684316853168631687316883168931690316913169231693316943169531696316973169831699317003170131702317033170431705317063170731708317093171031711317123171331714317153171631717317183171931720317213172231723317243172531726317273172831729317303173131732317333173431735317363173731738317393174031741317423174331744317453174631747317483174931750317513175231753317543175531756317573175831759317603176131762317633176431765317663176731768317693177031771317723177331774317753177631777317783177931780317813178231783317843178531786317873178831789317903179131792317933179431795317963179731798317993180031801318023180331804318053180631807318083180931810318113181231813318143181531816318173181831819318203182131822318233182431825318263182731828318293183031831318323183331834318353183631837318383183931840318413184231843318443184531846318473184831849318503185131852318533185431855318563185731858318593186031861318623186331864318653186631867318683186931870318713187231873318743187531876318773187831879318803188131882318833188431885318863188731888318893189031891318923189331894318953189631897318983189931900319013190231903 |
- /* onsenui v2.10.10 - 2019-07-29 */
-
- (function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
- typeof define === 'function' && define.amd ? define(factory) :
- (global.ons = factory());
- }(this, (function () { 'use strict';
-
- var onsElements = {};
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * Add vendor prefix.
- *
- * @param {String} name
- * @return {String}
- */
- var prefix = function () {
- var styles = window.getComputedStyle(document.documentElement, '');
- var prefix = (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/) || styles.OLink === '' && ['', 'o'])[1];
-
- return function (name) {
- return '-' + prefix + '-' + util$1.hyphenate(name);
- };
- }();
-
- /**
- * Minimal utility library for manipulating element's style.
- * Set element's style.
- *
- * @param {Element} element
- * @param {Object} styles
- * @return {Element}
- */
- var styler = function styler(element, style) {
- Object.keys(style).forEach(function (key) {
- if (key in element.style) {
- element.style[key] = style[key];
- } else if (prefix(key) in element.style) {
- element.style[prefix(key)] = style[key];
- } else {
- util$1.warn('No such style property: ' + key);
- }
- });
- return element;
- };
-
- /**
- * @param {Element} element
- * @param {String} styles Space-separated CSS properties to remove
- */
- styler.clear = function (element) {
- var styles = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
-
- var clearlist = styles.split(/\s+/).reduce(function (r, s) {
- return r.concat([util$1.hyphenate(s), prefix(s)]);
- }, []),
- keys = [];
-
- var _loop = function _loop(i) {
- var key = element.style[i];
- if (clearlist.length === 0 || clearlist.some(function (s) {
- return key.indexOf(s) === 0;
- })) {
- keys.push(key); // Store the key to fix Safari style indexes
- }
- };
-
- for (var i = element.style.length - 1; i >= 0; i--) {
- _loop(i);
- }
-
- keys.forEach(function (key) {
- return element.style[key] = '';
- });
- element.getAttribute('style') === '' && element.removeAttribute('style');
- };
-
- var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
- return typeof obj;
- } : function (obj) {
- return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
- };
-
-
-
-
-
-
-
-
-
-
-
- var classCallCheck = function (instance, Constructor) {
- if (!(instance instanceof Constructor)) {
- throw new TypeError("Cannot call a class as a function");
- }
- };
-
- var createClass = function () {
- function defineProperties(target, props) {
- for (var i = 0; i < props.length; i++) {
- var descriptor = props[i];
- descriptor.enumerable = descriptor.enumerable || false;
- descriptor.configurable = true;
- if ("value" in descriptor) descriptor.writable = true;
- Object.defineProperty(target, descriptor.key, descriptor);
- }
- }
-
- return function (Constructor, protoProps, staticProps) {
- if (protoProps) defineProperties(Constructor.prototype, protoProps);
- if (staticProps) defineProperties(Constructor, staticProps);
- return Constructor;
- };
- }();
-
-
-
-
-
- var defineProperty = function (obj, key, value) {
- if (key in obj) {
- Object.defineProperty(obj, key, {
- value: value,
- enumerable: true,
- configurable: true,
- writable: true
- });
- } else {
- obj[key] = value;
- }
-
- return obj;
- };
-
- var _extends = Object.assign || function (target) {
- for (var i = 1; i < arguments.length; i++) {
- var source = arguments[i];
-
- for (var key in source) {
- if (Object.prototype.hasOwnProperty.call(source, key)) {
- target[key] = source[key];
- }
- }
- }
-
- return target;
- };
-
- var get = function get(object, property, receiver) {
- if (object === null) object = Function.prototype;
- var desc = Object.getOwnPropertyDescriptor(object, property);
-
- if (desc === undefined) {
- var parent = Object.getPrototypeOf(object);
-
- if (parent === null) {
- return undefined;
- } else {
- return get(parent, property, receiver);
- }
- } else if ("value" in desc) {
- return desc.value;
- } else {
- var getter = desc.get;
-
- if (getter === undefined) {
- return undefined;
- }
-
- return getter.call(receiver);
- }
- };
-
- var inherits = function (subClass, superClass) {
- if (typeof superClass !== "function" && superClass !== null) {
- throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
- }
-
- subClass.prototype = Object.create(superClass && superClass.prototype, {
- constructor: {
- value: subClass,
- enumerable: false,
- writable: true,
- configurable: true
- }
- });
- if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
- };
-
-
-
-
-
-
-
-
-
- var objectWithoutProperties = function (obj, keys) {
- var target = {};
-
- for (var i in obj) {
- if (keys.indexOf(i) >= 0) continue;
- if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
- target[i] = obj[i];
- }
-
- return target;
- };
-
- var possibleConstructorReturn = function (self, call) {
- if (!self) {
- throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
- }
-
- return call && (typeof call === "object" || typeof call === "function") ? call : self;
- };
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- var toConsumableArray = function (arr) {
- if (Array.isArray(arr)) {
- for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
-
- return arr2;
- } else {
- return Array.from(arr);
- }
- };
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- // Save HTMLElement object before Custom Elements polyfill patch global HTMLElement.
- var NativeHTMLElement = window.HTMLElement;
-
- /**
- * @object ons.platform
- * @category util
- * @description
- * [en]Utility methods to detect current platform.[/en]
- * [ja]現在実行されているプラットフォームを検知するためのユーティリティメソッドを収めたオブジェクトです。[/ja]
- */
-
- var Platform = function () {
-
- /**
- * All elements will be rendered as if the app was running on this platform.
- * @type {String}
- */
- function Platform() {
- classCallCheck(this, Platform);
-
- this._selectedPlatform = null;
- this._ignorePlatformSelect = false;
- }
-
- /**
- * @method select
- * @signature select(platform)
- * @param {string} platform Name of the platform.
- * [en]Possible values are: "opera", "firefox", "safari", "chrome", "ie", "android", "blackberry", "ios" or "wp".[/en]
- * [ja]"opera", "firefox", "safari", "chrome", "ie", "android", "blackberry", "ios", "wp"のいずれかを指定します。[/ja]
- * @description
- * [en]Sets the platform used to render the elements. Useful for testing.[/en]
- * [ja]要素を描画するために利用するプラットフォーム名を設定します。テストに便利です。[/ja]
- */
-
-
- createClass(Platform, [{
- key: 'select',
- value: function select(platform) {
- if (typeof platform === 'string') {
- this._selectedPlatform = platform.trim().toLowerCase();
- }
- }
- }, {
- key: '_getSelectedPlatform',
- value: function _getSelectedPlatform() {
- return this._ignorePlatformSelect ? null : this._selectedPlatform;
- }
- }, {
- key: '_runOnActualPlatform',
- value: function _runOnActualPlatform(fn) {
- this._ignorePlatformSelect = true;
- var result = fn();
- this._ignorePlatformSelect = false;
-
- return result;
- }
-
- //----------------
- // General
- //----------------
- /**
- * @method isWebView
- * @signature isWebView()
- * @description
- * [en]Returns whether app is running in Cordova.[/en]
- * [ja]Cordova内で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isWebView',
- value: function isWebView() {
- if (document.readyState === 'loading' || document.readyState == 'uninitialized') {
- throw new Error('isWebView() method is available after dom contents loaded.');
- }
-
- return !!(window.cordova || window.phonegap || window.PhoneGap);
- }
-
- //----------------
- // iOS devices
- //----------------
- /**
- * @method isIPhone
- * @signature isIPhone()
- * @description
- * [en]Returns whether the device is iPhone.[/en]
- * [ja]iPhone上で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isIPhone',
- value: function isIPhone() {
- return (/iPhone/i.test(navigator.userAgent)
- );
- }
-
- /**
- * @method isIPhoneX
- * @signature isIPhoneX()
- * @description
- * [en]Returns whether the device is iPhone X, XS, XS Max, or XR.[/en]
- * [ja]iPhone X や XS、XS Max、または XR 上で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isIPhoneX',
- value: function isIPhoneX() {
- // iOS WebViews on the same iOS version have the same user agent.
- // We cannot avoid using window.screen.
- // We also cannot use cordova-plugin-device since its behavior is different between simulators and real devices.
- // This works well both in iOS Safari and (UI|WK)WebView of iPhone X.
- return this.isIPhone() && (window.screen.width === 375 && window.screen.height === 812 || // X, XS portrait
- window.screen.width === 812 && window.screen.height === 375 || // X, XS landscape
- window.screen.width === 414 && window.screen.height === 896 || // XS Max, XR portrait
- window.screen.width === 896 && window.screen.height === 414); // XS Max, XR landscape
- }
-
- /**
- * @method isIPad
- * @signature isIPad()
- * @description
- * [en]Returns whether the device is iPad.[/en]
- * [ja]iPad上で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isIPad',
- value: function isIPad() {
- return (/iPad/i.test(navigator.userAgent)
- );
- }
-
- /**
- * @return {Boolean}
- */
-
- }, {
- key: 'isIPod',
- value: function isIPod() {
- return (/iPod/i.test(navigator.userAgent)
- );
- }
-
- //----------------
- // iOS versions
- //----------------
- /**
- * @method isIOS
- * @signature isIOS([forceActualPlatform])
- * @param {Boolean} forceActualPlatform
- * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
- * [ja][/ja]
- * @description
- * [en]Returns whether the OS is iOS. By default will return manually selected platform if it is set.[/en]
- * [ja]iOS上で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isIOS',
- value: function isIOS(forceActualPlatform) {
- if (!forceActualPlatform && this._getSelectedPlatform()) {
- return this._getSelectedPlatform() === 'ios';
- }
-
- if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) {
- return (/iOS/i.test(device.platform)
- );
- } else {
- return (/iPhone|iPad|iPod/i.test(navigator.userAgent)
- );
- }
- }
-
- /**
- * @method isIOS7above
- * @signature isIOS7above()
- * @description
- * [en]Returns whether the iOS version is 7 or above.[/en]
- * [ja]iOS7以上で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isIOS7above',
- value: function isIOS7above() {
- if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) {
- return (/iOS/i.test(device.platform) && parseInt(device.version.split('.')[0]) >= 7
- );
- } else if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {
- var ver = (navigator.userAgent.match(/\b[0-9]+_[0-9]+(?:_[0-9]+)?\b/) || [''])[0].replace(/_/g, '.');
- return parseInt(ver.split('.')[0]) >= 7;
- }
- return false;
- }
-
- //----------------
- // iOS browsers
- //----------------
- /**
- * @method isIOSSafari
- * @signature isIOSSafari()
- * @description
- * [en]Returns whether app is running in iOS Safari.[/en]
- * [ja]iOS Safariで実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isIOSSafari',
- value: function isIOSSafari() {
- var navigator = window.navigator;
- var ua = navigator.userAgent;
-
- return !!(this.isIOS() && ua.indexOf('Safari') !== -1 && ua.indexOf('Version') !== -1 && !navigator.standalone);
- }
-
- /**
- * @method isWKWebView
- * @signature isWKWebView()
- * @description
- * [en]Returns whether app is running in WKWebView.[/en]
- * [ja]WKWebViewで実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isWKWebView',
- value: function isWKWebView() {
- var lte9 = /constructor/i.test(NativeHTMLElement);
- return !!(this.isIOS() && window.webkit && window.webkit.messageHandlers && window.indexedDB && !lte9);
- }
-
- /**
- * @method isUIWebView
- * @signature isUIWebView()
- * @description
- * [en]Returns whether app is running in UIWebView.[/en]
- * [ja]UIWebViewで実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isUIWebView',
- value: function isUIWebView() {
- return !!(this.isIOS() && !this.isIOSSafari() && !this.isWKWebView());
- }
-
- //----------------
- // Android devices
- //----------------
- /**
- * @method isAndroidPhone
- * @signature isAndroidPhone()
- * @description
- * [en]Returns whether the device is Android phone.[/en]
- * [ja]Android携帯上で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isAndroidPhone',
- value: function isAndroidPhone() {
- return (/Android/i.test(navigator.userAgent) && /Mobile/i.test(navigator.userAgent)
- );
- }
-
- /**
- * @method isAndroidTablet
- * @signature isAndroidTablet()
- * @description
- * [en]Returns whether the device is Android tablet.[/en]
- * [ja]Androidタブレット上で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isAndroidTablet',
- value: function isAndroidTablet() {
- return (/Android/i.test(navigator.userAgent) && !/Mobile/i.test(navigator.userAgent)
- );
- }
-
- //----------------
- // Android versions
- //----------------
- /**
- * @method isAndroid
- * @signature isAndroid([forceActualPlatform])
- * @param {Boolean} forceActualPlatform
- * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
- * [ja][/ja]
- * @description
- * [en]Returns whether the OS is Android. By default will return manually selected platform if it is set.[/en]
- * [ja]Android上で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isAndroid',
- value: function isAndroid(forceActualPlatform) {
- if (!forceActualPlatform && this._getSelectedPlatform()) {
- return this._getSelectedPlatform() === 'android';
- }
-
- if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) {
- return (/Android/i.test(device.platform)
- );
- } else {
- return (/Android/i.test(navigator.userAgent)
- );
- }
- }
-
- //----------------
- // Other devices
- //----------------
- /**
- * @method isWP
- * @signature isWP([forceActualPlatform])
- * @param {Boolean} forceActualPlatform
- * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
- * [ja][/ja]
- * @description
- * [en]Returns whether the OS is Windows phone. By default will return manually selected platform if it is set.[/en]
- * [ja][/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isWP',
- value: function isWP(forceActualPlatform) {
- if (!forceActualPlatform && this._getSelectedPlatform()) {
- return this._getSelectedPlatform() === 'wp';
- }
-
- if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) {
- return (/Win32NT|WinCE/i.test(device.platform)
- );
- } else {
- return (/Windows Phone|IEMobile|WPDesktop/i.test(navigator.userAgent)
- );
- }
- }
-
- /**
- * @method isBlackBerry
- * @signature isBlackBerry([forceActualPlatform])
- * @param {Boolean} forceActualPlatform
- * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
- * [ja][/ja]
- * @description
- * [en]Returns whether the device is BlackBerry. By default will return manually selected platform if it is set.[/en]
- * [ja]BlackBerry上で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isBlackBerry',
- value: function isBlackBerry(forceActualPlatform) {
- if (!forceActualPlatform && this._getSelectedPlatform()) {
- return this._getSelectedPlatform() === 'blackberry';
- }
-
- if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) {
- return (/BlackBerry/i.test(device.platform)
- );
- } else {
- return (/BlackBerry|RIM Tablet OS|BB10/i.test(navigator.userAgent)
- );
- }
- }
-
- //----------------
- // Other browsers
- //----------------
- /**
- * @method isOpera
- * @signature isOpera([forceActualPlatform])
- * @param {Boolean} forceActualPlatform
- * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
- * [ja][/ja]
- * @description
- * [en]Returns whether the browser is Opera. By default will return manually selected platform if it is set.[/en]
- * [ja]Opera上で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isOpera',
- value: function isOpera(forceActualPlatform) {
- if (!forceActualPlatform && this._getSelectedPlatform()) {
- return this._getSelectedPlatform() === 'opera';
- }
-
- return !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
- }
-
- /**
- * @method isFirefox
- * @signature isFirefox([forceActualPlatform])
- * @param {Boolean} forceActualPlatform
- * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
- * [ja][/ja]
- * @description
- * [en]Returns whether the browser is Firefox. By default will return manually selected platform if it is set.[/en]
- * [ja]Firefox上で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isFirefox',
- value: function isFirefox(forceActualPlatform) {
- if (!forceActualPlatform && this._getSelectedPlatform()) {
- return this._getSelectedPlatform() === 'firefox';
- }
-
- return typeof InstallTrigger !== 'undefined';
- }
-
- /**
- * @method isSafari
- * @signature isSafari([forceActualPlatform])
- * @param {Boolean} forceActualPlatform
- * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
- * [ja][/ja]
- * @description
- * [en]Returns whether the browser is Safari. By default will return manually selected platform if it is set.[/en]
- * [ja]Safari上で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isSafari',
- value: function isSafari(forceActualPlatform) {
- if (!forceActualPlatform && this._getSelectedPlatform()) {
- return this._getSelectedPlatform() === 'safari';
- }
-
- return Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0 || function (p) {
- return p.toString() === '[object SafariRemoteNotification]';
- }(!window['safari'] || safari.pushNotification);
- }
-
- /**
- * @method isChrome
- * @signature isChrome([forceActualPlatform])
- * @param {Boolean} forceActualPlatform
- * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
- * [ja][/ja]
- * @description
- * [en]Returns whether the browser is Chrome. By default will return manually selected platform if it is set.[/en]
- * [ja]Chrome上で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isChrome',
- value: function isChrome(forceActualPlatform) {
- if (!forceActualPlatform && this._getSelectedPlatform()) {
- return this._getSelectedPlatform() === 'chrome';
- }
-
- return !!window.chrome && !(!!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) && !(navigator.userAgent.indexOf(' Edge/') >= 0);
- }
-
- /**
- * @method isIE
- * @signature isIE([forceActualPlatform])
- * @param {Boolean} forceActualPlatform
- * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
- * [ja][/ja]
- * @description
- * [en]Returns whether the browser is Internet Explorer. By default will return manually selected platform if it is set.[/en]
- * [ja]Internet Explorer上で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isIE',
- value: function isIE(forceActualPlatform) {
- if (!forceActualPlatform && this._getSelectedPlatform()) {
- return this._getSelectedPlatform() === 'ie';
- }
-
- return false || !!document.documentMode;
- }
-
- /**
- * @method isEdge
- * @signature isEdge([forceActualPlatform])
- * @param {Boolean} forceActualPlatform
- * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
- * [ja][/ja]
- * @description
- * [en]Returns whether the browser is Edge. By default will return manually selected platform if it is set.[/en]
- * [ja]Edge上で実行されているかどうかを返します。[/ja]
- * @return {Boolean}
- */
-
- }, {
- key: 'isEdge',
- value: function isEdge(forceActualPlatform) {
- if (!forceActualPlatform && this._getSelectedPlatform()) {
- return this._getSelectedPlatform() === 'edge';
- }
-
- return navigator.userAgent.indexOf(' Edge/') >= 0;
- }
-
- //----------------
- // Utility functions
- //----------------
- /**
- * @return {String}
- */
-
- }, {
- key: 'getMobileOS',
- value: function getMobileOS() {
- if (this.isAndroid()) {
- return 'android';
- } else if (this.isIOS()) {
- return 'ios';
- } else if (this.isWP()) {
- return 'wp';
- } else {
- return 'other';
- }
- }
-
- /**
- * @return {String}
- */
-
- }, {
- key: 'getIOSDevice',
- value: function getIOSDevice() {
- if (this.isIPhone()) {
- return 'iphone';
- } else if (this.isIPad()) {
- return 'ipad';
- } else if (this.isIPod()) {
- return 'ipod';
- } else {
- return 'na';
- }
- }
- }]);
- return Platform;
- }();
-
- var platform = new Platform();
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var error = function error(message) {
- return util$1.throw('In PageAttributeExpression: ' + message);
- };
-
- var pageAttributeExpression = {
- _variables: {},
-
- /**
- * Define a variable.
- *
- * @param {String} name Name of the variable
- * @param {String|Function} value Value of the variable. Can be a string or a function. The function must return a string.
- * @param {Boolean} overwrite If this value is false, an error will be thrown when trying to define a variable that has already been defined.
- */
- defineVariable: function defineVariable(name, value) {
- var overwrite = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
-
- if (typeof name !== 'string') {
- error('Variable name must be a string');
- } else if (typeof value !== 'string' && typeof value !== 'function') {
- error('Variable value must be a string or a function');
- } else if (this._variables.hasOwnProperty(name) && !overwrite) {
- error('"' + name + '" is already defined');
- }
- this._variables[name] = value;
- },
-
- /**
- * Get a variable.
- *
- * @param {String} name Name of the variable.
- * @return {String|Function|null}
- */
- getVariable: function getVariable(name) {
- if (!this._variables.hasOwnProperty(name)) {
- return null;
- }
-
- return this._variables[name];
- },
-
- /**
- * Remove a variable.
- *
- * @param {String} name Name of the varaible.
- */
- removeVariable: function removeVariable(name) {
- delete this._variables[name];
- },
-
- /**
- * Get all variables.
- *
- * @return {Object}
- */
- getAllVariables: function getAllVariables() {
- return this._variables;
- },
- _parsePart: function _parsePart(part) {
- var c = void 0,
- inInterpolation = false,
- currentIndex = 0;
-
- var tokens = [];
-
- if (part.length === 0) {
- error('Unable to parse empty string');
- }
-
- for (var i = 0; i < part.length; i++) {
- c = part.charAt(i);
-
- if (c === '$' && part.charAt(i + 1) === '{') {
- if (inInterpolation) {
- error('Nested interpolation not supported');
- }
-
- var token = part.substring(currentIndex, i);
- if (token.length > 0) {
- tokens.push(part.substring(currentIndex, i));
- }
-
- currentIndex = i;
- inInterpolation = true;
- } else if (c === '}') {
- if (!inInterpolation) {
- error('} must be preceeded by ${');
- }
-
- var _token = part.substring(currentIndex, i + 1);
- if (_token.length > 0) {
- tokens.push(part.substring(currentIndex, i + 1));
- }
-
- currentIndex = i + 1;
- inInterpolation = false;
- }
- }
-
- if (inInterpolation) {
- error('Unterminated interpolation');
- }
-
- tokens.push(part.substring(currentIndex, part.length));
-
- return tokens;
- },
- _replaceToken: function _replaceToken(token) {
- var re = /^\${(.*?)}$/,
- match = token.match(re);
-
- if (match) {
- var name = match[1].trim();
- var variable = this.getVariable(name);
-
- if (variable === null) {
- error('Variable "' + name + '" does not exist');
- } else if (typeof variable === 'string') {
- return variable;
- } else {
- var rv = variable();
-
- if (typeof rv !== 'string') {
- error('Must return a string');
- }
-
- return rv;
- }
- } else {
- return token;
- }
- },
- _replaceTokens: function _replaceTokens(tokens) {
- return tokens.map(this._replaceToken.bind(this));
- },
- _parseExpression: function _parseExpression(expression) {
- return expression.split(',').map(function (part) {
- return part.trim();
- }).map(this._parsePart.bind(this)).map(this._replaceTokens.bind(this)).map(function (part) {
- return part.join('');
- });
- },
-
- /**
- * Evaluate an expression.
- *
- * @param {String} expression An page attribute expression.
- * @return {Array}
- */
- evaluate: function evaluate(expression) {
- if (!expression) {
- return [];
- }
-
- return this._parseExpression(expression);
- }
- };
-
- // Define default variables.
- pageAttributeExpression.defineVariable('mobileOS', platform.getMobileOS());
- pageAttributeExpression.defineVariable('iOSDevice', platform.getIOSDevice());
- pageAttributeExpression.defineVariable('runtime', function () {
- return platform.isWebView() ? 'cordova' : 'browser';
- });
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var internal$1 = {};
-
- internal$1.config = {
- autoStatusBarFill: true,
- animationsDisabled: false,
- warningsDisabled: false
- };
-
- internal$1.nullElement = window.document.createElement('div');
-
- /**
- * @return {Boolean}
- */
- internal$1.isEnabledAutoStatusBarFill = function () {
- return !!internal$1.config.autoStatusBarFill;
- };
-
- /**
- * @param {String} html
- * @return {String}
- */
- internal$1.normalizePageHTML = function (html) {
- return ('' + html).trim();
- };
-
- internal$1.waitDOMContentLoaded = function (callback) {
- if (window.document.readyState === 'loading' || window.document.readyState == 'uninitialized') {
- var wrappedCallback = function wrappedCallback() {
- callback();
- window.document.removeEventListener('DOMContentLoaded', wrappedCallback);
- };
- window.document.addEventListener('DOMContentLoaded', wrappedCallback);
- } else {
- setImmediate(callback);
- }
- };
-
- internal$1.autoStatusBarFill = function (action) {
- var onReady = function onReady() {
- if (internal$1.shouldFillStatusBar()) {
- action();
- }
- document.removeEventListener('deviceready', onReady);
- };
-
- if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object') {
- document.addEventListener('deviceready', onReady);
- } else if (['complete', 'interactive'].indexOf(document.readyState) === -1) {
- internal$1.waitDOMContentLoaded(onReady);
- } else {
- onReady();
- }
- };
-
- internal$1.shouldFillStatusBar = function () {
- return internal$1.isEnabledAutoStatusBarFill() && (platform.isWebView() && platform.isIOS7above() && !platform.isIPhoneX() || document.body.querySelector('.ons-status-bar-mock.ios'));
- };
-
- internal$1.templateStore = {
- _storage: {},
-
- /**
- * @param {String} key
- * @return {String/null} template
- */
- get: function get$$1(key) {
- return internal$1.templateStore._storage[key] || null;
- },
-
-
- /**
- * @param {String} key
- * @param {String} template
- */
- set: function set$$1(key, template) {
- internal$1.templateStore._storage[key] = template;
- }
- };
-
- window.document.addEventListener('_templateloaded', function (e) {
- if (e.target.nodeName.toLowerCase() === 'ons-template') {
- internal$1.templateStore.set(e.templateId, e.template);
- }
- }, false);
-
- internal$1.waitDOMContentLoaded(function () {
- register('script[type="text/ons-template"]');
- register('script[type="text/template"]');
- register('script[type="text/ng-template"]');
- register('template');
-
- function register(query) {
- var templates = window.document.querySelectorAll(query);
- for (var i = 0; i < templates.length; i++) {
- internal$1.templateStore.set(templates[i].getAttribute('id'), templates[i].textContent || templates[i].content);
- }
- }
- });
-
- /**
- * @param {String} page
- * @return {Promise}
- */
- internal$1.getTemplateHTMLAsync = function (page) {
- return new Promise(function (resolve, reject) {
- internal$1.waitDOMContentLoaded(function () {
- var cache = internal$1.templateStore.get(page);
- if (cache) {
- if (cache instanceof DocumentFragment) {
- return resolve(cache);
- }
-
- var html = typeof cache === 'string' ? cache : cache[1];
- return resolve(internal$1.normalizePageHTML(html));
- }
-
- var local = window.document.getElementById(page);
- if (local) {
- var _html = local.textContent || local.content;
- return resolve(_html);
- }
-
- var xhr = new XMLHttpRequest();
- xhr.open('GET', page, true);
- xhr.onload = function () {
- var html = xhr.responseText;
- if (xhr.status >= 400 && xhr.status < 600) {
- reject(html);
- } else {
- // Refresh script tags
- var fragment = util$1.createFragment(html);
- util$1.arrayFrom(fragment.querySelectorAll('script')).forEach(function (el) {
- var script = document.createElement('script');
- script.type = el.type || 'text/javascript';
- script.appendChild(document.createTextNode(el.text || el.textContent || el.innerHTML));
- el.parentNode.replaceChild(script, el);
- });
-
- internal$1.templateStore.set(page, fragment);
- resolve(fragment);
- }
- };
- xhr.onerror = function () {
- util$1.throw('Page template not found: ' + page);
- };
- xhr.send(null);
- });
- });
- };
-
- /**
- * @param {String} page
- * @return {Promise}
- */
- internal$1.getPageHTMLAsync = function (page) {
- var pages = pageAttributeExpression.evaluate(page);
-
- var getPage = function getPage(page) {
- if (typeof page !== 'string') {
- return Promise.reject('Must specify a page.');
- }
-
- return internal$1.getTemplateHTMLAsync(page).catch(function (error) {
- if (pages.length === 0) {
- return Promise.reject(error);
- }
-
- return getPage(pages.shift());
- });
- };
-
- return getPage(pages.shift());
- };
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var AnimatorFactory = function () {
-
- /**
- * @param {Object} opts
- * @param {Object} opts.animators The dictionary for animator classes
- * @param {Function} opts.baseClass The base class of animators
- * @param {String} [opts.baseClassName] The name of the base class of animators
- * @param {String} [opts.defaultAnimation] The default animation name
- * @param {Object} [opts.defaultAnimationOptions] The default animation options
- */
- function AnimatorFactory(opts) {
- classCallCheck(this, AnimatorFactory);
-
- this._animators = opts.animators;
- this._baseClass = opts.baseClass;
- this._baseClassName = opts.baseClassName || opts.baseClass.name;
- this._animation = opts.defaultAnimation || 'default';
- this._animationOptions = opts.defaultAnimationOptions || {};
-
- if (!this._animators[this._animation]) {
- util$1.throw('No such animation: ' + this._animation);
- }
- }
-
- /**
- * @param {String} jsonString
- * @return {Object/null}
- */
-
-
- createClass(AnimatorFactory, [{
- key: 'setAnimationOptions',
-
-
- /**
- * @param {Object} options
- */
- value: function setAnimationOptions(options) {
- this._animationOptions = options;
- }
-
- /**
- * @param {Object} options
- * @param {String} [options.animation] The animation name
- * @param {Object} [options.animationOptions] The animation options
- * @param {Object} defaultAnimator The default animator instance
- * @return {Object} An animator instance
- */
-
- }, {
- key: 'newAnimator',
- value: function newAnimator() {
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var defaultAnimator = arguments[1];
-
-
- var animator = null;
-
- if (options.animation instanceof this._baseClass) {
- return options.animation;
- }
-
- var Animator = null;
-
- if (typeof options.animation === 'string') {
- Animator = this._animators[options.animation];
- }
-
- if (!Animator && defaultAnimator) {
- animator = defaultAnimator;
- } else {
- Animator = Animator || this._animators[this._animation];
-
- var animationOpts = util$1.extend({}, this._animationOptions, options.animationOptions || {}, internal$1.config.animationsDisabled ? { duration: 0, delay: 0 } : {});
-
- animator = new Animator(animationOpts);
-
- if (typeof animator === 'function') {
- animator = new animator(animationOpts); // eslint-disable-line new-cap
- }
- }
-
- if (!(animator instanceof this._baseClass)) {
- util$1.throw('"animator" is not an instance of ' + this._baseClassName);
- }
-
- return animator;
- }
- }], [{
- key: 'parseAnimationOptionsString',
- value: function parseAnimationOptionsString(jsonString) {
- try {
- if (typeof jsonString === 'string') {
- var result = util$1.animationOptionsParse(jsonString);
- if ((typeof result === 'undefined' ? 'undefined' : _typeof(result)) === 'object' && result !== null) {
- return result;
- } else {
- console.error('"animation-options" attribute must be a JSON object string: ' + jsonString);
- }
- }
- return {};
- } catch (e) {
- console.error('"animation-options" attribute must be a JSON object string: ' + jsonString);
- return {};
- }
- }
- }]);
- return AnimatorFactory;
- }();
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var autoStyleEnabled = true;
-
- // Modifiers
- var modifiersMap = {
- 'quiet': 'material--flat',
- 'light': 'material--flat',
- 'outline': 'material--flat',
- 'cta': '',
- 'large--quiet': 'material--flat large',
- 'large--cta': 'large',
- 'noborder': '',
- 'tappable': ''
- };
-
- var platforms = {};
-
- platforms.android = function (element) {
-
- var elementName = element.tagName.toLowerCase();
-
- if (!util$1.hasModifier(element, 'material')) {
- var oldModifier = element.getAttribute('modifier') || '';
-
- var newModifier = oldModifier.trim().split(/\s+/).map(function (e) {
- return modifiersMap.hasOwnProperty(e) ? modifiersMap[e] : e;
- });
- newModifier.unshift('material');
-
- element.setAttribute('modifier', newModifier.join(' ').trim());
- }
-
- var elements = ['ons-alert-dialog-button', 'ons-toolbar-button', 'ons-back-button', 'ons-button', 'ons-list-item', 'ons-fab', 'ons-speed-dial', 'ons-speed-dial-item', 'ons-tab'];
-
- // Effects
- if (elements.indexOf(elementName) !== -1 && !element.hasAttribute('ripple') && !element.querySelector('ons-ripple')) {
-
- if (elementName === 'ons-list-item') {
- if (element.hasAttribute('tappable')) {
- element.setAttribute('ripple', '');
- element.removeAttribute('tappable');
- }
- } else {
- element.setAttribute('ripple', '');
- }
- }
- };
-
- platforms.ios = function (element) {
-
- // Modifiers
- if (util$1.removeModifier(element, 'material')) {
- if (util$1.removeModifier(element, 'material--flat')) {
- util$1.addModifier(element, util$1.removeModifier(element, 'large') ? 'large--quiet' : 'quiet');
- }
-
- if (!element.getAttribute('modifier')) {
- element.removeAttribute('modifier');
- }
- }
-
- // Effects
- if (element.hasAttribute('ripple')) {
- if (element.tagName.toLowerCase() === 'ons-list-item') {
- element.setAttribute('tappable', '');
- }
-
- element.removeAttribute('ripple');
- }
- };
-
- var unlocked = {
- android: true
- };
-
- var getPlatform = function getPlatform(element, force) {
- if (autoStyleEnabled && !element.hasAttribute('disable-auto-styling')) {
- var mobileOS = platform.getMobileOS();
- if (platforms.hasOwnProperty(mobileOS) && (unlocked.hasOwnProperty(mobileOS) || force)) {
- return mobileOS;
- }
- }
- return null;
- };
-
- var prepare = function prepare(element, force) {
- var p = getPlatform(element, force);
- p && platforms[p](element);
- };
-
- var mapModifier = function mapModifier(modifier, element, force) {
- if (getPlatform(element, force)) {
- return modifier.split(/\s+/).map(function (m) {
- return modifiersMap.hasOwnProperty(m) ? modifiersMap[m] : m;
- }).join(' ');
- }
- return modifier;
- };
-
- var restoreModifier = function restoreModifier(element) {
- if (getPlatform(element) === 'android') {
- var modifier = element.getAttribute('modifier') || '';
- var newModifier = mapModifier(modifier, element);
-
- if (!/(^|\s+)material($|\s+)/i.test(modifier)) {
- newModifier = 'material ' + newModifier;
- }
-
- if (newModifier !== modifier) {
- element.setAttribute('modifier', newModifier.trim());
- return true;
- }
- }
- return false;
- };
-
- var autoStyle = {
- isEnabled: function isEnabled() {
- return autoStyleEnabled;
- },
- enable: function enable() {
- return autoStyleEnabled = true;
- },
- disable: function disable() {
- return autoStyleEnabled = false;
- },
- prepare: prepare,
- mapModifier: mapModifier,
- getPlatform: getPlatform,
- restoreModifier: restoreModifier
- };
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var ModifierUtil = function () {
- function ModifierUtil() {
- classCallCheck(this, ModifierUtil);
- }
-
- createClass(ModifierUtil, null, [{
- key: 'diff',
-
- /**
- * @param {String} last
- * @param {String} current
- */
- value: function diff(last, current) {
- last = makeDict(('' + last).trim());
- current = makeDict(('' + current).trim());
-
- var removed = Object.keys(last).reduce(function (result, token) {
- if (!current[token]) {
- result.push(token);
- }
- return result;
- }, []);
-
- var added = Object.keys(current).reduce(function (result, token) {
- if (!last[token]) {
- result.push(token);
- }
- return result;
- }, []);
-
- return { added: added, removed: removed };
-
- function makeDict(modifier) {
- var dict = {};
- ModifierUtil.split(modifier).forEach(function (token) {
- return dict[token] = token;
- });
- return dict;
- }
- }
-
- /**
- * @param {Object} diff
- * @param {Array} diff.removed
- * @param {Array} diff.added
- * @param {Object} classList
- * @param {String} template
- */
-
- }, {
- key: 'applyDiffToClassList',
- value: function applyDiffToClassList(diff, classList, template) {
- diff.added.map(function (modifier) {
- return template.replace(/\*/g, modifier);
- }).forEach(function (klass) {
- return klass.split(/\s+/).forEach(function (k) {
- return classList.add(k);
- });
- });
-
- diff.removed.map(function (modifier) {
- return template.replace(/\*/g, modifier);
- }).forEach(function (klass) {
- return klass.split(/\s+/).forEach(function (k) {
- return classList.remove(k);
- });
- });
- }
-
- /**
- * @param {Object} diff
- * @param {Array} diff.removed
- * @param {Array} diff.added
- * @param {HTMLElement} element
- * @param {Object} scheme
- */
-
- }, {
- key: 'applyDiffToElement',
- value: function applyDiffToElement(diff, element, scheme) {
- Object.keys(scheme).forEach(function (selector) {
- var targetElements = !selector || util$1.match(element, selector) ? [element] : Array.prototype.filter.call(element.querySelectorAll(selector), function (targetElement) {
- return !util$1.findParent(targetElement, element.tagName, function (parent) {
- return parent === element;
- });
- });
-
- for (var i = 0; i < targetElements.length; i++) {
- ModifierUtil.applyDiffToClassList(diff, targetElements[i].classList, scheme[selector]);
- }
- });
- }
-
- /**
- * @param {String} last
- * @param {String} current
- * @param {HTMLElement} element
- * @param {Object} scheme
- */
-
- }, {
- key: 'onModifierChanged',
- value: function onModifierChanged(last, current, element, scheme) {
- ModifierUtil.applyDiffToElement(ModifierUtil.diff(last, current), element, scheme);
- autoStyle.restoreModifier(element);
- }
- }, {
- key: 'refresh',
- value: function refresh(element, scheme) {
- ModifierUtil.applyDiffToElement(ModifierUtil.diff('', element.getAttribute('modifier') || ''), element, scheme);
- }
-
- /**
- * @param {HTMLElement} element
- * @param {Object} scheme
- */
-
- }, {
- key: 'initModifier',
- value: function initModifier(element, scheme) {
- var modifier = element.getAttribute('modifier');
- if (typeof modifier !== 'string') {
- return;
- }
-
- ModifierUtil.applyDiffToElement({
- removed: [],
- added: ModifierUtil.split(modifier)
- }, element, scheme);
- }
- }, {
- key: 'split',
- value: function split(modifier) {
- if (typeof modifier !== 'string') {
- return [];
- }
-
- return modifier.trim().split(/ +/).filter(function (token) {
- return token !== '';
- });
- }
-
- /**
- * Add modifier token to an element.
- */
-
- }, {
- key: 'addModifier',
- value: function addModifier(element, modifierToken) {
- if (!element.hasAttribute('modifier')) {
- element.setAttribute('modifier', modifierToken);
- } else {
- var tokens = ModifierUtil.split(element.getAttribute('modifier'));
- if (tokens.indexOf(modifierToken) == -1) {
- tokens.push(modifierToken);
- element.setAttribute('modifier', tokens.join(' '));
- }
- }
- }
-
- /**
- * Remove modifier token from an element.
- */
-
- }, {
- key: 'removeModifier',
- value: function removeModifier(element, modifierToken) {
- if (element.hasAttribute('modifier')) {
- var tokens = ModifierUtil.split(element.getAttribute('modifier'));
- var index = tokens.indexOf(modifierToken);
- if (index !== -1) {
- tokens.splice(index, 1);
- element.setAttribute('modifier', tokens.join(' '));
- }
- }
- }
- }]);
- return ModifierUtil;
- }();
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var util$3 = {
- _ready: false,
-
- _domContentLoaded: false,
-
- _onDOMContentLoaded: function _onDOMContentLoaded() {
- util$3._domContentLoaded = true;
-
- if (platform.isWebView()) {
- window.document.addEventListener('deviceready', function () {
- util$3._ready = true;
- }, false);
- } else {
- util$3._ready = true;
- }
- },
-
- addBackButtonListener: function addBackButtonListener(fn) {
- if (!this._domContentLoaded) {
- throw new Error('This method is available after DOMContentLoaded');
- }
-
- if (this._ready) {
- window.document.addEventListener('backbutton', fn, false);
- } else {
- window.document.addEventListener('deviceready', function () {
- window.document.addEventListener('backbutton', fn, false);
- });
- }
- },
-
- removeBackButtonListener: function removeBackButtonListener(fn) {
- if (!this._domContentLoaded) {
- throw new Error('This method is available after DOMContentLoaded');
- }
-
- if (this._ready) {
- window.document.removeEventListener('backbutton', fn, false);
- } else {
- window.document.addEventListener('deviceready', function () {
- window.document.removeEventListener('backbutton', fn, false);
- });
- }
- }
- };
- window.addEventListener('DOMContentLoaded', function () {
- return util$3._onDOMContentLoaded();
- }, false);
-
- var HandlerRepository = {
- _store: {},
-
- _genId: function () {
- var i = 0;
- return function () {
- return i++;
- };
- }(),
-
- set: function set$$1(element, handler) {
- if (element.dataset.deviceBackButtonHandlerId) {
- this.remove(element);
- }
- var id = element.dataset.deviceBackButtonHandlerId = HandlerRepository._genId();
- this._store[id] = handler;
- },
-
- remove: function remove(element) {
- if (element.dataset.deviceBackButtonHandlerId) {
- delete this._store[element.dataset.deviceBackButtonHandlerId];
- delete element.dataset.deviceBackButtonHandlerId;
- }
- },
-
- get: function get$$1(element) {
- if (!element.dataset.deviceBackButtonHandlerId) {
- return undefined;
- }
-
- var id = element.dataset.deviceBackButtonHandlerId;
-
- if (!this._store[id]) {
- throw new Error();
- }
-
- return this._store[id];
- },
-
- has: function has(element) {
- if (!element.dataset) {
- return false;
- }
-
- var id = element.dataset.deviceBackButtonHandlerId;
-
- return !!this._store[id];
- }
- };
-
- var DeviceBackButtonDispatcher = function () {
- function DeviceBackButtonDispatcher() {
- classCallCheck(this, DeviceBackButtonDispatcher);
-
- this._isEnabled = false;
- this._boundCallback = this._callback.bind(this);
- }
-
- /**
- * Enable to handle 'backbutton' events.
- */
-
-
- createClass(DeviceBackButtonDispatcher, [{
- key: 'enable',
- value: function enable() {
- if (!this._isEnabled) {
- util$3.addBackButtonListener(this._boundCallback);
- this._isEnabled = true;
- }
- }
-
- /**
- * Disable to handle 'backbutton' events.
- */
-
- }, {
- key: 'disable',
- value: function disable() {
- if (this._isEnabled) {
- util$3.removeBackButtonListener(this._boundCallback);
- this._isEnabled = false;
- }
- }
-
- /**
- * Fire a 'backbutton' event manually.
- */
-
- }, {
- key: 'fireDeviceBackButtonEvent',
- value: function fireDeviceBackButtonEvent() {
- var event = document.createEvent('Event');
- event.initEvent('backbutton', true, true);
- document.dispatchEvent(event);
- }
- }, {
- key: '_callback',
- value: function _callback() {
- this._dispatchDeviceBackButtonEvent();
- }
-
- /**
- * @param {HTMLElement} element
- * @param {Function} callback
- */
-
- }, {
- key: 'createHandler',
- value: function createHandler(element, callback) {
- if (!(element instanceof HTMLElement)) {
- throw new Error('element must be an instance of HTMLElement');
- }
-
- if (!(callback instanceof Function)) {
- throw new Error('callback must be an instance of Function');
- }
-
- var handler = {
- _callback: callback,
- _element: element,
-
- disable: function disable() {
- HandlerRepository.remove(element);
- },
-
- setListener: function setListener(callback) {
- this._callback = callback;
- },
-
- enable: function enable() {
- HandlerRepository.set(element, this);
- },
-
- isEnabled: function isEnabled() {
- return HandlerRepository.get(element) === this;
- },
-
- destroy: function destroy() {
- HandlerRepository.remove(element);
- this._callback = this._element = null;
- }
- };
-
- handler.enable();
-
- return handler;
- }
- }, {
- key: '_dispatchDeviceBackButtonEvent',
- value: function _dispatchDeviceBackButtonEvent() {
- var tree = this._captureTree();
-
- var element = this._findHandlerLeafElement(tree);
-
- var handler = HandlerRepository.get(element);
- handler._callback(createEvent(element));
-
- function createEvent(element) {
- return {
- _element: element,
- callParentHandler: function callParentHandler() {
- var parent = this._element.parentNode;
-
- while (parent) {
- handler = HandlerRepository.get(parent);
- if (handler) {
- return handler._callback(createEvent(parent));
- }
- parent = parent.parentNode;
- }
- }
- };
- }
- }
-
- /**
- * @return {Object}
- */
-
- }, {
- key: '_captureTree',
- value: function _captureTree() {
- return createTree(document.body);
-
- function createTree(element) {
- var tree = {
- element: element,
- children: Array.prototype.concat.apply([], arrayOf(element.children).map(function (childElement) {
-
- if (childElement.style.display === 'none' || childElement._isShown === false) {
- return [];
- }
-
- if (childElement.children.length === 0 && !HandlerRepository.has(childElement)) {
- return [];
- }
-
- var result = createTree(childElement);
-
- if (result.children.length === 0 && !HandlerRepository.has(result.element)) {
- return [];
- }
-
- return [result];
- }))
- };
-
- if (!HandlerRepository.has(tree.element)) {
- for (var i = 0; i < tree.children.length; i++) {
- var subTree = tree.children[i];
- if (HandlerRepository.has(subTree.element)) {
- return subTree;
- }
- }
- }
-
- return tree;
- }
-
- function arrayOf(target) {
- var result = [];
- for (var i = 0; i < target.length; i++) {
- result.push(target[i]);
- }
- return result;
- }
- }
-
- /**
- * @param {Object} tree
- * @return {HTMLElement}
- */
-
- }, {
- key: '_findHandlerLeafElement',
- value: function _findHandlerLeafElement(tree) {
- return find(tree);
-
- function find(node) {
- if (node.children.length === 0) {
- return node.element;
- }
-
- if (node.children.length === 1) {
- return find(node.children[0]);
- }
-
- return node.children.map(function (childNode) {
- return childNode.element;
- }).reduce(function (left, right) {
- if (!left) {
- return right;
- }
-
- var leftZ = parseInt(window.getComputedStyle(left, '').zIndex, 10);
- var rightZ = parseInt(window.getComputedStyle(right, '').zIndex, 10);
-
- if (!isNaN(leftZ) && !isNaN(rightZ)) {
- return leftZ > rightZ ? left : right;
- }
-
- throw new Error('Capturing backbutton-handler is failure.');
- }, null);
- }
- }
- }]);
- return DeviceBackButtonDispatcher;
- }();
-
- var deviceBackButtonDispatcher = new DeviceBackButtonDispatcher();
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
- internal$1.AnimatorFactory = AnimatorFactory;
- internal$1.ModifierUtil = ModifierUtil;
- internal$1.dbbDispatcher = deviceBackButtonDispatcher;
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var startsWith = function startsWith(s, c) {
- return s.substr(0, c.length) === c;
- };
- var endsWith = function endsWith(s, c) {
- return s.substr(s.length - c.length, c.length) === c;
- };
- var unwrap = function unwrap(s) {
- return s.slice(1, -1);
- };
- var isObjectString = function isObjectString(s) {
- return startsWith(s, '{') && endsWith(s, '}');
- };
- var isArrayString = function isArrayString(s) {
- return startsWith(s, '[') && endsWith(s, ']');
- };
- var isQuotedString = function isQuotedString(s) {
- return startsWith(s, '\'') && endsWith(s, '\'') || startsWith(s, '"') && endsWith(s, '"');
- };
-
- var error$1 = function error(token, string, originalString) {
- throw new Error('Unexpected token \'' + token + '\' at position ' + (originalString.length - string.length - 1) + ' in string: \'' + originalString + '\'');
- };
-
- var processToken = function processToken(token, string, originalString) {
- if (token === 'true' || token === 'false') {
- return token === 'true';
- } else if (isQuotedString(token)) {
- return unwrap(token);
- } else if (!isNaN(token)) {
- return +token;
- } else if (isObjectString(token)) {
- return parseObject(unwrap(token));
- } else if (isArrayString(token)) {
- return parseArray(unwrap(token));
- } else {
- error$1(token, string, originalString);
- }
- };
-
- var nextToken = function nextToken(string) {
- string = string.trim();
- var limit = string.length;
-
- if (string[0] === ':' || string[0] === ',') {
-
- limit = 1;
- } else if (string[0] === '{' || string[0] === '[') {
-
- var c = string.charCodeAt(0);
- var nestedObject = 1;
- for (var i = 1; i < string.length; i++) {
- if (string.charCodeAt(i) === c) {
- nestedObject++;
- } else if (string.charCodeAt(i) === c + 2) {
- nestedObject--;
- if (nestedObject === 0) {
- limit = i + 1;
- break;
- }
- }
- }
- } else if (string[0] === '\'' || string[0] === '"') {
-
- for (var _i = 1; _i < string.length; _i++) {
- if (string[_i] === string[0]) {
- limit = _i + 1;
- break;
- }
- }
- } else {
-
- for (var _i2 = 1; _i2 < string.length; _i2++) {
- if ([' ', ',', ':'].indexOf(string[_i2]) !== -1) {
- limit = _i2;
- break;
- }
- }
- }
-
- return string.slice(0, limit);
- };
-
- var parseObject = function parseObject(string) {
- var isValidKey = function isValidKey(key) {
- return (/^[A-Z_$][A-Z0-9_$]*$/i.test(key)
- );
- };
-
- string = string.trim();
- var originalString = string;
- var object = {};
- var readingKey = true,
- key = void 0,
- previousToken = void 0,
- token = void 0;
-
- while (string.length > 0) {
- previousToken = token;
- token = nextToken(string);
- string = string.slice(token.length, string.length).trim();
-
- if (token === ':' && (!readingKey || !previousToken || previousToken === ',') || token === ',' && readingKey || token !== ':' && token !== ',' && previousToken && previousToken !== ',' && previousToken !== ':') {
- error$1(token, string, originalString);
- } else if (token === ':' && readingKey && previousToken) {
- previousToken = isQuotedString(previousToken) ? unwrap(previousToken) : previousToken;
- if (isValidKey(previousToken)) {
- key = previousToken;
- readingKey = false;
- } else {
- throw new Error('Invalid key token \'' + previousToken + '\' at position 0 in string: \'' + originalString + '\'');
- }
- } else if (token === ',' && !readingKey && previousToken) {
- object[key] = processToken(previousToken, string, originalString);
- readingKey = true;
- }
- }
-
- if (token) {
- object[key] = processToken(token, string, originalString);
- }
-
- return object;
- };
-
- var parseArray = function parseArray(string) {
- string = string.trim();
- var originalString = string;
- var array = [];
- var previousToken = void 0,
- token = void 0;
-
- while (string.length > 0) {
- previousToken = token;
- token = nextToken(string);
- string = string.slice(token.length, string.length).trim();
-
- if (token === ',' && (!previousToken || previousToken === ',')) {
- error$1(token, string, originalString);
- } else if (token === ',') {
- array.push(processToken(previousToken, string, originalString));
- }
- }
-
- if (token) {
- if (token !== ',') {
- array.push(processToken(token, string, originalString));
- } else {
- error$1(token, string, originalString);
- }
- }
-
- return array;
- };
-
- var parse = function parse(string) {
- string = string.trim();
-
- if (isObjectString(string)) {
- return parseObject(unwrap(string));
- } else if (isArrayString(string)) {
- return parseArray(unwrap(string));
- } else {
- throw new Error('Provided string must be object or array like: ' + string);
- }
- };
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var util$1 = {};
- var errorPrefix = '[Onsen UI]';
-
- util$1.globals = {
- fabOffset: 0,
- errorPrefix: errorPrefix,
- supportsPassive: false
- };
-
- platform._runOnActualPlatform(function () {
- util$1.globals.actualMobileOS = platform.getMobileOS();
- util$1.globals.isUIWebView = platform.isUIWebView();
- util$1.globals.isWKWebView = platform.isWKWebView();
- });
-
- try {
- var opts = Object.defineProperty({}, 'passive', {
- get: function get$$1() {
- util$1.globals.supportsPassive = true;
- }
- });
- window.addEventListener('testPassive', null, opts);
- window.removeEventListener('testPassive', null, opts);
- } catch (e) {
-
- }
-
- /**
- * @param {Element} el Target
- * @param {String} name Event name
- * @param {Function} handler Event handler
- * @param {Object} [opt] Event options (passive, capture...)
- * @param {Boolean} [isGD] If comes from GestureDetector. Just for testing.
- */
- util$1.addEventListener = function (el, name, handler, opt, isGD) {
- el.addEventListener(name, handler, util$1.globals.supportsPassive ? opt : (opt || {}).capture);
- };
- util$1.removeEventListener = function (el, name, handler, opt, isGD) {
- el.removeEventListener(name, handler, util$1.globals.supportsPassive ? opt : (opt || {}).capture);
- };
-
- /**
- * @param {String/Function} query dot class name or node name or matcher function.
- * @return {Function}
- */
- util$1.prepareQuery = function (query) {
- return query instanceof Function ? query : function (element) {
- return util$1.match(element, query);
- };
- };
-
- /**
- * @param {Element} e
- * @param {String/Function} s CSS Selector.
- * @return {Boolean}
- */
- util$1.match = function (e, s) {
- return (e.matches || e.webkitMatchesSelector || e.mozMatchesSelector || e.msMatchesSelector).call(e, s);
- };
-
- /**
- * @param {Element} element
- * @param {String/Function} query dot class name or node name or matcher function.
- * @return {HTMLElement/null}
- */
- util$1.findChild = function (element, query) {
- var match = util$1.prepareQuery(query);
-
- // Caution: `element.children` is `undefined` in some environments if `element` is `svg`
- for (var i = 0; i < element.childNodes.length; i++) {
- var node = element.childNodes[i];
- if (node.nodeType !== Node.ELEMENT_NODE) {
- // process only element nodes
- continue;
- }
- if (match(node)) {
- return node;
- }
- }
- return null;
- };
-
- /**
- * @param {Element} element
- * @param {String/Function} query dot class name or node name or matcher function.
- * @return {HTMLElement/null}
- */
- util$1.findParent = function (element, query, until) {
- var match = util$1.prepareQuery(query);
-
- var parent = element.parentNode;
- for (;;) {
- if (!parent || parent === document || parent instanceof DocumentFragment || until && until(parent)) {
- return null;
- } else if (match(parent)) {
- return parent;
- }
- parent = parent.parentNode;
- }
- };
-
- /**
- * @param {Element} element
- * @return {boolean}
- */
- util$1.isAttached = function (element) {
- return document.body.contains(element);
- };
-
- /**
- * @param {Element} element
- * @return {boolean}
- */
- util$1.hasAnyComponentAsParent = function (element) {
- while (element && document.documentElement !== element) {
- element = element.parentNode;
- if (element && element.nodeName.toLowerCase().match(/(ons-navigator|ons-tabbar|ons-modal)/)) {
- return true;
- }
- }
- return false;
- };
-
- /**
- * @param {Object} element
- * @return {Array}
- */
- util$1.getAllChildNodes = function (element) {
- var _ref;
-
- return (_ref = [element]).concat.apply(_ref, toConsumableArray(Array.from(element.children).map(function (childEl) {
- return util$1.getAllChildNodes(childEl);
- })));
- };
-
- /**
- * @param {Element} element
- * @return {boolean}
- */
- util$1.isPageControl = function (element) {
- return element.nodeName.match(/^ons-(navigator|splitter|tabbar|page)$/i);
- };
-
- /**
- * @param {Element} element
- * @param {String} action to propagate
- */
- util$1.propagateAction = function (element, action) {
- for (var i = 0; i < element.childNodes.length; i++) {
- var child = element.childNodes[i];
- if (child[action] instanceof Function) {
- child[action]();
- } else {
- util$1.propagateAction(child, action);
- }
- }
- };
-
- /**
- * @param {String} string - string to be camelized
- * @return {String} Camelized string
- */
- util$1.camelize = function (string) {
- return string.toLowerCase().replace(/-([a-z])/g, function (m, l) {
- return l.toUpperCase();
- });
- };
-
- /**
- * @param {String} string - string to be hyphenated
- * @return {String} Hyphenated string
- */
- util$1.hyphenate = function (string) {
- return string.replace(/([a-zA-Z])([A-Z])/g, '$1-$2').toLowerCase();
- };
-
- /**
- * @param {String} selector - tag and class only
- * @param {Object} style
- * @param {Element}
- */
- util$1.create = function () {
- var selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
- var style = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- var classList = selector.split('.');
- var element = document.createElement(classList.shift() || 'div');
-
- if (classList.length) {
- element.className = classList.join(' ');
- }
-
- styler(element, style);
-
- return element;
- };
-
- /**
- * @param {String} html
- * @return {Element}
- */
- util$1.createElement = function (html) {
- var wrapper = document.createElement('div');
-
- if (html instanceof DocumentFragment) {
- wrapper.appendChild(document.importNode(html, true));
- } else {
- wrapper.innerHTML = html.trim();
- }
-
- if (wrapper.children.length > 1) {
- util$1.throw('HTML template must contain a single root element');
- }
-
- var element = wrapper.children[0];
- wrapper.children[0].remove();
- return element;
- };
-
- /**
- * @param {String} html
- * @return {HTMLFragment}
- */
- util$1.createFragment = function (html) {
- var template = document.createElement('template');
- template.innerHTML = html;
- return document.importNode(template.content, true);
- };
-
- /*
- * @param {Object} dst Destination object.
- * @param {...Object} src Source object(s).
- * @returns {Object} Reference to `dst`.
- */
- util$1.extend = function (dst) {
- for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
- args[_key - 1] = arguments[_key];
- }
-
- for (var i = 0; i < args.length; i++) {
- if (args[i]) {
- var keys = Object.keys(args[i]);
- for (var j = 0; j < keys.length; j++) {
- var key = keys[j];
- dst[key] = args[i][key];
- }
- }
- }
-
- return dst;
- };
-
- /**
- * @param {Object} arrayLike
- * @return {Array}
- */
- util$1.arrayFrom = function (arrayLike) {
- return Array.prototype.slice.apply(arrayLike);
- };
-
- /**
- * @param {String} jsonString
- * @param {Object} [failSafe]
- * @return {Object}
- */
- util$1.parseJSONObjectSafely = function (jsonString) {
- var failSafe = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- try {
- var result = JSON.parse('' + jsonString);
- if ((typeof result === 'undefined' ? 'undefined' : _typeof(result)) === 'object' && result !== null) {
- return result;
- }
- } catch (e) {
- return failSafe;
- }
- return failSafe;
- };
-
- /**
- * @param {String} path - path such as 'myApp.controllers.data.loadData'
- * @return {Any} - whatever is located at that path
- */
- util$1.findFromPath = function (path) {
- path = path.split('.');
- var el = window,
- key;
- while (key = path.shift()) {
- // eslint-disable-line no-cond-assign
- el = el[key];
- }
- return el;
- };
-
- /**
- * @param {HTMLElement} container - Page or page-container that implements 'topPage'
- * @return {HTMLElement|null} - Visible page element or null if not found.
- */
- util$1.getTopPage = function (container) {
- return container && (container.tagName.toLowerCase() === 'ons-page' ? container : container.topPage) || null;
- };
-
- /**
- * @param {HTMLElement} container - Element where the search begins
- * @return {HTMLElement|null} - Page element that contains the visible toolbar or null.
- */
- util$1.findToolbarPage = function (container) {
- var page = util$1.getTopPage(container);
-
- if (page) {
- if (page._canAnimateToolbar()) {
- return page;
- }
-
- for (var i = 0; i < page._contentElement.children.length; i++) {
- var nextPage = util$1.getTopPage(page._contentElement.children[i]);
- if (nextPage && !/ons-tabbar/i.test(page._contentElement.children[i].tagName)) {
- return util$1.findToolbarPage(nextPage);
- }
- }
- }
-
- return null;
- };
-
- /**
- * @param {Element} element
- * @param {String} eventName
- * @param {Object} [detail]
- * @return {CustomEvent}
- */
- util$1.triggerElementEvent = function (target, eventName) {
- var detail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
-
-
- var event = new CustomEvent(eventName, {
- bubbles: true,
- cancelable: true,
- detail: detail
- });
-
- Object.keys(detail).forEach(function (key) {
- event[key] = detail[key];
- });
-
- target.dispatchEvent(event);
-
- return event;
- };
-
- /**
- * @param {Element} target
- * @param {String} modifierName
- * @return {Boolean}
- */
- util$1.hasModifier = function (target, modifierName) {
- if (!target.hasAttribute('modifier')) {
- return false;
- }
-
- return RegExp('(^|\\s+)' + modifierName + '($|\\s+)', 'i').test(target.getAttribute('modifier'));
- };
-
- /**
- * @param {Element} target
- * @param {String} modifierName
- * @param {Object} options.autoStyle Maps the modifierName to the corresponding styled modifier.
- * @param {Object} options.forceAutoStyle Ignores platform limitation.
- * @return {Boolean} Whether it was added or not.
- */
- util$1.addModifier = function (target, modifierName) {
- var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
-
- if (options.autoStyle) {
- modifierName = autoStyle.mapModifier(modifierName, target, options.forceAutoStyle);
- }
-
- if (util$1.hasModifier(target, modifierName)) {
- return false;
- }
-
- target.setAttribute('modifier', ((target.getAttribute('modifier') || '') + ' ' + modifierName).trim());
- return true;
- };
-
- /**
- * @param {Element} target
- * @param {String} modifierName
- * @param {Object} options.autoStyle Maps the modifierName to the corresponding styled modifier.
- * @param {Object} options.forceAutoStyle Ignores platform limitation.
- * @return {Boolean} Whether it was found or not.
- */
- util$1.removeModifier = function (target, modifierName) {
- var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
-
- if (options.autoStyle) {
- modifierName = autoStyle.mapModifier(modifierName, target, options.forceAutoStyle);
- }
-
- if (!target.getAttribute('modifier') || !util$1.hasModifier(target, modifierName)) {
- return false;
- }
-
- var newModifiers = target.getAttribute('modifier').split(/\s+/).filter(function (m) {
- return m && m !== modifierName;
- });
- newModifiers.length ? target.setAttribute('modifier', newModifiers.join(' ')) : target.removeAttribute('modifier');
- return true;
- };
-
- /**
- * @param {Element} target
- * @param {String} modifierName
- * @param {Boolean} options.force Forces modifier to be added or removed.
- * @param {Object} options.autoStyle Maps the modifierName to the corresponding styled modifier.
- * @param {Boolean} options.forceAutoStyle Ignores platform limitation.
- * @return {Boolean} Whether it was found or not.
- */
- util$1.toggleModifier = function () {
- var options = arguments.length > 2 ? arguments.length <= 2 ? undefined : arguments[2] : {};
- var force = typeof options === 'boolean' ? options : options.force;
-
- var toggle = typeof force === 'boolean' ? force : !util$1.hasModifier.apply(util$1, arguments);
- toggle ? util$1.addModifier.apply(util$1, arguments) : util$1.removeModifier.apply(util$1, arguments);
- };
-
- /**
- * @param {Element} el
- * @param {String} defaultClass
- * @param {Object} scheme
- */
- util$1.restoreClass = function (el, defaultClass, scheme) {
- defaultClass.split(/\s+/).forEach(function (c) {
- return c !== '' && !el.classList.contains(c) && el.classList.add(c);
- });
- el.hasAttribute('modifier') && ModifierUtil.refresh(el, scheme);
- };
-
- // TODO: FIX
- util$1.updateParentPosition = function (el) {
- if (!el._parentUpdated && el.parentElement) {
- if (window.getComputedStyle(el.parentElement).getPropertyValue('position') === 'static') {
- el.parentElement.style.position = 'relative';
- }
- el._parentUpdated = true;
- }
- };
-
- util$1.toggleAttribute = function (element, name, value) {
- if (value) {
- element.setAttribute(name, typeof value === 'boolean' ? '' : value);
- } else {
- element.removeAttribute(name);
- }
- };
-
- util$1.bindListeners = function (element, listenerNames) {
- listenerNames.forEach(function (name) {
- var boundName = name.replace(/^_[a-z]/, '_bound' + name[1].toUpperCase());
- element[boundName] = element[boundName] || element[name].bind(element);
- });
- };
-
- util$1.each = function (obj, f) {
- return Object.keys(obj).forEach(function (key) {
- return f(key, obj[key]);
- });
- };
-
- /**
- * @param {Element} target
- * @param {boolean} hasRipple
- * @param {Object} attrs
- */
- util$1.updateRipple = function (target, hasRipple) {
- var attrs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
-
- if (hasRipple === undefined) {
- hasRipple = target.hasAttribute('ripple');
- }
-
- var rippleElement = util$1.findChild(target, 'ons-ripple');
-
- if (hasRipple) {
- if (!rippleElement) {
- var element = document.createElement('ons-ripple');
- Object.keys(attrs).forEach(function (key) {
- return element.setAttribute(key, attrs[key]);
- });
- target.insertBefore(element, target.firstChild);
- }
- } else if (rippleElement) {
- rippleElement.remove();
- }
- };
-
- /**
- * @param {String}
- * @return {Object}
- */
- util$1.animationOptionsParse = parse;
-
- /**
- * @param {*} value
- */
- util$1.isInteger = function (value) {
- return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;
- };
-
- /**
- * @return {Object} Deferred promise.
- */
- util$1.defer = function () {
- var deferred = {};
- deferred.promise = new Promise(function (resolve, reject) {
- deferred.resolve = resolve;
- deferred.reject = reject;
- });
- return deferred;
- };
-
- /**
- * Show warnings when they are enabled.
- *
- * @param {*} arguments to console.warn
- */
- util$1.warn = function () {
- for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
- args[_key2] = arguments[_key2];
- }
-
- if (!internal$1.config.warningsDisabled) {
- var _console;
-
- (_console = console).warn.apply(_console, [errorPrefix].concat(args));
- }
- };
-
- util$1.throw = function (message) {
- throw new Error(errorPrefix + ' ' + message);
- };
-
- util$1.throwAbstract = function () {
- return util$1.throw('Cannot instantiate abstract class');
- };
- util$1.throwMember = function () {
- return util$1.throw('Class member must be implemented');
- };
- util$1.throwPageLoader = function () {
- return util$1.throw('First parameter should be an instance of PageLoader');
- };
- util$1.throwAnimator = function (el) {
- return util$1.throw('"Animator" param must inherit ' + el + 'Animator');
- };
-
- var prevent = function prevent(e) {
- return e.cancelable && e.preventDefault();
- };
-
- /**
- * Prevent scrolling while draging horizontally on iOS.
- *
- * @param {gd} GestureDetector instance
- */
- util$1.iosPreventScroll = function (gd) {
- if (util$1.globals.actualMobileOS === 'ios') {
- var clean = function clean(e) {
- gd.off('touchmove', prevent);
- gd.off('dragend', clean);
- };
-
- gd.on('touchmove', prevent);
- gd.on('dragend', clean);
- }
- };
-
- /**
- * Prevents scroll in underlying pages on iOS. See #2220 #2274 #1949
- *
- * @param {el} HTMLElement that prevents the events
- * @param {add} Boolean Add or remove event listeners
- */
- util$1.iosPageScrollFix = function (add) {
- // Full fix - May cause issues with UIWebView's momentum scroll
- if (util$1.globals.actualMobileOS === 'ios') {
- document.body.classList.toggle('ons-ios-scroll', add); // Allows custom and localized fixes (#2274)
- if (!util$1.globals.isUIWebView || internal$1.config.forceUIWebViewScrollFix) {
- document.body.classList.toggle('ons-ios-scroll-fix', add);
- }
- }
- };
- util$1.iosMaskScrollFix = function (el, add) {
- // Half fix - only prevents scroll on masks
- if (util$1.globals.isUIWebView) {
- var action = (add ? 'add' : 'remove') + 'EventListener';
- el[action]('touchmove', prevent, false);
- }
- };
-
- /**
- * Distance and deltaTime filter some weird dragstart events that are not fired immediately.
- *
- * @param {event}
- */
- util$1.isValidGesture = function (event) {
- return event.gesture !== undefined && (event.gesture.distance <= 15 || event.gesture.deltaTime <= 100);
- };
-
- util$1.checkMissingImport = function () {
- for (var _len3 = arguments.length, elementNames = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
- elementNames[_key3] = arguments[_key3];
- }
-
- elementNames.forEach(function (name) {
- if (!onsElements[name]) {
- util$1.throw('Ons' + name + ' is required but was not imported (Custom Elements)');
- }
- });
- };
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * Minimal animation library for managing css transition on mobile browsers.
- */
- var TIMEOUT_RATIO = 1.4;
-
- var util$4 = {};
-
- // capitalize string
- util$4.capitalize = function (str) {
- return str.charAt(0).toUpperCase() + str.slice(1);
- };
-
- /**
- * @param {Object} params
- * @param {String} params.property
- * @param {Float} params.duration
- * @param {String} params.timing
- */
- util$4.buildTransitionValue = function (params) {
- params.property = params.property || 'all';
- params.duration = params.duration || 0.4;
- params.timing = params.timing || 'linear';
-
- var props = params.property.split(/ +/);
-
- return props.map(function (prop) {
- return prop + ' ' + params.duration + 's ' + params.timing;
- }).join(', ');
- };
-
- /**
- * Add an event handler on "transitionend" event.
- */
- util$4.onceOnTransitionEnd = function (element, callback) {
- if (!element) {
- return function () {};
- }
-
- var fn = function fn(event) {
- if (element == event.target) {
- event.stopPropagation();
- removeListeners();
-
- callback();
- }
- };
-
- var removeListeners = function removeListeners() {
- util$4._transitionEndEvents.forEach(function (eventName) {
- element.removeEventListener(eventName, fn, false);
- });
- };
-
- util$4._transitionEndEvents.forEach(function (eventName) {
- element.addEventListener(eventName, fn, false);
- });
-
- return removeListeners;
- };
-
- util$4._transitionEndEvents = function () {
-
- if ('ontransitionend' in window) {
- return ['transitionend'];
- }
-
- if ('onwebkittransitionend' in window) {
- return ['webkitTransitionEnd'];
- }
-
- if (util$4.vendorPrefix === 'webkit' || util$4.vendorPrefix === 'o' || util$4.vendorPrefix === 'moz' || util$4.vendorPrefix === 'ms') {
- return [util$4.vendorPrefix + 'TransitionEnd', 'transitionend'];
- }
-
- return [];
- }();
-
- util$4._cssPropertyDict = function () {
- var styles = window.getComputedStyle(document.documentElement, '');
- var dict = {};
- var a = 'A'.charCodeAt(0);
- var z = 'z'.charCodeAt(0);
-
- var upper = function upper(s) {
- return s.substr(1).toUpperCase();
- };
-
- for (var i = 0; i < styles.length; i++) {
-
- var key = styles[i].replace(/^[-]+/, '').replace(/[-][a-z]/g, upper).replace(/^moz/, 'Moz');
-
- if (a <= key.charCodeAt(0) && z >= key.charCodeAt(0)) {
- if (key !== 'cssText' && key !== 'parentText') {
- dict[key] = true;
- }
- }
- }
-
- return dict;
- }();
-
- util$4.hasCssProperty = function (name) {
- return name in util$4._cssPropertyDict;
- };
-
- /**
- * Vendor prefix for css property.
- */
- util$4.vendorPrefix = function () {
- var styles = window.getComputedStyle(document.documentElement, ''),
- pre = (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/) || styles.OLink === '' && ['', 'o'])[1];
- return pre;
- }();
-
- util$4.forceLayoutAtOnce = function (elements, callback) {
- this.batchImmediate(function () {
- elements.forEach(function (element) {
- // force layout
- element.offsetHeight;
- });
- callback();
- });
- };
-
- util$4.batchImmediate = function () {
- var callbacks = [];
-
- return function (callback) {
- if (callbacks.length === 0) {
- setImmediate(function () {
- var concreateCallbacks = callbacks.slice(0);
- callbacks = [];
- concreateCallbacks.forEach(function (callback) {
- callback();
- });
- });
- }
-
- callbacks.push(callback);
- };
- }();
-
- util$4.batchAnimationFrame = function () {
- var callbacks = [];
-
- var raf = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
- setTimeout(callback, 1000 / 60);
- };
-
- return function (callback) {
- if (callbacks.length === 0) {
- raf(function () {
- var concreateCallbacks = callbacks.slice(0);
- callbacks = [];
- concreateCallbacks.forEach(function (callback) {
- callback();
- });
- });
- }
-
- callbacks.push(callback);
- };
- }();
-
- util$4.transitionPropertyName = function () {
- if (util$4.hasCssProperty('transitionDuration')) {
- return 'transition';
- }
-
- if (util$4.hasCssProperty(util$4.vendorPrefix + 'TransitionDuration')) {
- return util$4.vendorPrefix + 'Transition';
- }
-
- throw new Error('Invalid state');
- }();
-
- /**
- * @param {HTMLElement} element
- */
- var Animit = function Animit(element, defaults) {
- if (!(this instanceof Animit)) {
- return new Animit(element, defaults);
- }
-
- if (element instanceof HTMLElement) {
- this.elements = [element];
- } else if (Object.prototype.toString.call(element) === '[object Array]') {
- this.elements = element;
- } else {
- throw new Error('First argument must be an array or an instance of HTMLElement.');
- }
-
- this.defaults = defaults;
- this.transitionQueue = [];
- this.lastStyleAttributeDict = [];
- };
-
- Animit.prototype = {
-
- /**
- * @property {Array}
- */
- transitionQueue: undefined,
-
- /**
- * @property {Array}
- */
- elements: undefined,
-
- /**
- * @property {Object}
- */
- defaults: undefined,
-
- /**
- * Start animation sequence with passed animations.
- *
- * @param {Function} callback
- */
- play: function play(callback) {
- if (typeof callback === 'function') {
- this.transitionQueue.push(function (done) {
- callback();
- done();
- });
- }
-
- this.startAnimation();
-
- return this;
- },
-
- /**
- * Most of the animations follow this default process.
- *
- * @param {from} css or options object containing css
- * @param {to} css or options object containing css
- * @param {delay} delay to wait
- */
- default: function _default(from, to, delay) {
- function step(params, duration, timing) {
- if (params.duration !== undefined) {
- duration = params.duration;
- }
- if (params.timing !== undefined) {
- timing = params.timing;
- }
-
- return {
- css: params.css || params,
- duration: duration,
- timing: timing
- };
- }
-
- return this.saveStyle().queue(step(from, 0, this.defaults.timing)).wait(delay === undefined ? this.defaults.delay : delay).queue(step(to, this.defaults.duration, this.defaults.timing)).restoreStyle();
- },
-
- /**
- * Queue transition animations or other function.
- *
- * e.g. animit(elt).queue({color: 'red'})
- * e.g. animit(elt).queue({color: 'red'}, {duration: 0.4})
- * e.g. animit(elt).queue({css: {color: 'red'}, duration: 0.2})
- *
- * @param {Object|Animit.Transition|Function} transition
- * @param {Object} [options]
- */
- queue: function queue(transition, options) {
- var queue = this.transitionQueue;
-
- if (transition && options) {
- options.css = transition;
- transition = new Animit.Transition(options);
- }
-
- if (!(transition instanceof Function || transition instanceof Animit.Transition)) {
- if (transition.css) {
- transition = new Animit.Transition(transition);
- } else {
- transition = new Animit.Transition({
- css: transition
- });
- }
- }
-
- if (transition instanceof Function) {
- queue.push(transition);
- } else if (transition instanceof Animit.Transition) {
- queue.push(transition.build());
- } else {
- throw new Error('Invalid arguments');
- }
-
- return this;
- },
-
- /**
- * Queue transition animations.
- *
- * @param {Float} seconds
- */
- wait: function wait(seconds) {
- if (seconds > 0) {
- this.transitionQueue.push(function (done) {
- setTimeout(done, 1000 * seconds);
- });
- }
-
- return this;
- },
-
- saveStyle: function saveStyle() {
-
- this.transitionQueue.push(function (done) {
- this.elements.forEach(function (element, index) {
- var css = this.lastStyleAttributeDict[index] = {};
-
- for (var i = 0; i < element.style.length; i++) {
- css[element.style[i]] = element.style[element.style[i]];
- }
- }.bind(this));
- done();
- }.bind(this));
-
- return this;
- },
-
- /**
- * Restore element's style.
- *
- * @param {Object} [options]
- * @param {Float} [options.duration]
- * @param {String} [options.timing]
- * @param {String} [options.transition]
- */
- restoreStyle: function restoreStyle(options) {
- options = options || {};
- var self = this;
-
- if (options.transition && !options.duration) {
- throw new Error('"options.duration" is required when "options.transition" is enabled.');
- }
-
- var transitionName = util$4.transitionPropertyName;
-
- if (options.transition || options.duration && options.duration > 0) {
- var transitionValue = options.transition || 'all ' + options.duration + 's ' + (options.timing || 'linear');
-
- this.transitionQueue.push(function (done) {
- var elements = this.elements;
- var timeoutId;
-
- var clearTransition = function clearTransition() {
- elements.forEach(function (element) {
- element.style[transitionName] = '';
- });
- };
-
- // add "transitionend" event handler
- var removeListeners = util$4.onceOnTransitionEnd(elements[0], function () {
- clearTimeout(timeoutId);
- clearTransition();
- done();
- });
-
- // for fail safe.
- timeoutId = setTimeout(function () {
- removeListeners();
- clearTransition();
- done();
- }, options.duration * 1000 * TIMEOUT_RATIO);
-
- // transition and style settings
- elements.forEach(function (element, index) {
-
- var css = self.lastStyleAttributeDict[index];
-
- if (!css) {
- throw new Error('restoreStyle(): The style is not saved. Invoke saveStyle() before.');
- }
-
- self.lastStyleAttributeDict[index] = undefined;
-
- var name;
- for (var i = 0, len = element.style.length; i < len; i++) {
- name = element.style[i];
- if (css[name] === undefined) {
- css[name] = '';
- }
- }
-
- element.style[transitionName] = transitionValue;
-
- Object.keys(css).forEach(function (key) {
- if (key !== transitionName) {
- element.style[key] = css[key];
- }
- });
-
- element.style[transitionName] = transitionValue;
- });
- });
- } else {
- this.transitionQueue.push(function (done) {
- reset();
- done();
- });
- }
-
- return this;
-
- function reset() {
- // Clear transition animation settings.
- self.elements.forEach(function (element, index) {
- element.style[transitionName] = 'none';
-
- var css = self.lastStyleAttributeDict[index];
-
- if (!css) {
- throw new Error('restoreStyle(): The style is not saved. Invoke saveStyle() before.');
- }
-
- self.lastStyleAttributeDict[index] = undefined;
-
- for (var i = 0, name = ''; i < element.style.length; i++) {
- name = element.style[i];
- if (typeof css[element.style[i]] === 'undefined') {
- css[element.style[i]] = '';
- }
- }
-
- Object.keys(css).forEach(function (key) {
- element.style[key] = css[key];
- });
- });
- }
- },
-
- /**
- * Start animation sequence.
- */
- startAnimation: function startAnimation() {
- this._dequeueTransition();
-
- return this;
- },
-
- _dequeueTransition: function _dequeueTransition() {
- var transition = this.transitionQueue.shift();
- if (this._currentTransition) {
- throw new Error('Current transition exists.');
- }
- this._currentTransition = transition;
- var self = this;
- var called = false;
-
- var done = function done() {
- if (!called) {
- called = true;
- self._currentTransition = undefined;
- self._dequeueTransition();
- } else {
- throw new Error('Invalid state: This callback is called twice.');
- }
- };
-
- if (transition) {
- transition.call(this, done);
- }
- }
-
- };
-
- /**
- * @param {Animit} arguments
- */
- Animit.runAll = function () /* arguments... */{
- for (var i = 0; i < arguments.length; i++) {
- arguments[i].play();
- }
- };
-
- /**
- * @param {Object} options
- * @param {Float} [options.duration]
- * @param {String} [options.property]
- * @param {String} [options.timing]
- */
- Animit.Transition = function (options) {
- this.options = options || {};
- this.options.duration = this.options.duration || 0;
- this.options.timing = this.options.timing || 'linear';
- this.options.css = this.options.css || {};
- this.options.property = this.options.property || 'all';
- };
-
- Animit.Transition.prototype = {
-
- /**
- * @param {HTMLElement} element
- * @return {Function}
- */
- build: function build() {
-
- if (Object.keys(this.options.css).length === 0) {
- throw new Error('options.css is required.');
- }
-
- var css = createActualCssProps(this.options.css);
-
- if (this.options.duration > 0) {
- var transitionValue = util$4.buildTransitionValue(this.options);
- var self = this;
-
- return function (callback) {
- var elements = this.elements;
- var timeout = self.options.duration * 1000 * TIMEOUT_RATIO;
- var timeoutId;
-
- var removeListeners = util$4.onceOnTransitionEnd(elements[0], function () {
- clearTimeout(timeoutId);
- callback();
- });
-
- timeoutId = setTimeout(function () {
- removeListeners();
- callback();
- }, timeout);
-
- elements.forEach(function (element) {
- element.style[util$4.transitionPropertyName] = transitionValue;
-
- Object.keys(css).forEach(function (name) {
- element.style[name] = css[name];
- });
- });
- };
- }
-
- if (this.options.duration <= 0) {
- return function (callback) {
- var elements = this.elements;
-
- elements.forEach(function (element) {
- element.style[util$4.transitionPropertyName] = '';
-
- Object.keys(css).forEach(function (name) {
- element.style[name] = css[name];
- });
- });
-
- if (elements.length > 0) {
- util$4.forceLayoutAtOnce(elements, function () {
- util$4.batchAnimationFrame(callback);
- });
- } else {
- util$4.batchAnimationFrame(callback);
- }
- };
- }
-
- function createActualCssProps(css) {
- var result = {};
-
- Object.keys(css).forEach(function (name) {
- var value = css[name];
-
- if (util$4.hasCssProperty(name)) {
- result[name] = value;
- return;
- }
-
- var prefixed = util$4.vendorPrefix + util$4.capitalize(name);
- if (util$4.hasCssProperty(prefixed)) {
- result[prefixed] = value;
- } else {
- result[prefixed] = value;
- result[name] = value;
- }
- });
-
- return result;
- }
- }
- };
-
- /*
- * Gesture detector library that forked from github.com/EightMedia/hammer.js.
- */
-
- var Event$1;
- var Utils;
- var Detection;
- var PointerEvent;
-
- /**
- * @object ons.GestureDetector
- * @category gesture
- * @description
- * [en]Utility class for gesture detection.[/en]
- * [ja]ジェスチャを検知するためのユーティリティクラスです。[/ja]
- */
-
- /**
- * @method constructor
- * @signature constructor(element[, options])
- * @description
- * [en]Create a new GestureDetector instance.[/en]
- * [ja]GestureDetectorのインスタンスを生成します。[/ja]
- * @param {Element} element
- * [en]Name of the event.[/en]
- * [ja]ジェスチャを検知するDOM要素を指定します。[/ja]
- * @param {Object} [options]
- * [en]Options object.[/en]
- * [ja]オプションを指定します。[/ja]
- * @return {ons.GestureDetector.Instance}
- */
- var GestureDetector = function GestureDetector(element, options) {
- return new GestureDetector.Instance(element, options || {});
- };
-
- /**
- * default settings.
- * more settings are defined per gesture at `/gestures`. Each gesture can be disabled/enabled
- * by setting it's name (like `swipe`) to false.
- * You can set the defaults for all instances by changing this object before creating an instance.
- * @example
- * ````
- * GestureDetector.defaults.drag = false;
- * GestureDetector.defaults.behavior.touchAction = 'pan-y';
- * delete GestureDetector.defaults.behavior.userSelect;
- * ````
- * @property defaults
- * @type {Object}
- */
- GestureDetector.defaults = {
- behavior: {
- // userSelect: 'none', // Also disables selection in `input` children
- touchAction: 'pan-y',
- touchCallout: 'none',
- contentZooming: 'none',
- userDrag: 'none',
- tapHighlightColor: 'rgba(0,0,0,0)'
- }
- };
-
- /**
- * GestureDetector document where the base events are added at
- * @property DOCUMENT
- * @type {HTMLElement}
- * @default window.document
- */
- GestureDetector.DOCUMENT = document;
-
- /**
- * detect support for pointer events
- * @property HAS_POINTEREVENTS
- * @type {Boolean}
- */
- GestureDetector.HAS_POINTEREVENTS = navigator.pointerEnabled || navigator.msPointerEnabled;
-
- /**
- * detect support for touch events
- * @property HAS_TOUCHEVENTS
- * @type {Boolean}
- */
- GestureDetector.HAS_TOUCHEVENTS = 'ontouchstart' in window;
-
- /**
- * detect mobile browsers
- * @property IS_MOBILE
- * @type {Boolean}
- */
- GestureDetector.IS_MOBILE = /mobile|tablet|ip(ad|hone|od)|android|silk/i.test(navigator.userAgent);
-
- /**
- * detect if we want to support mouseevents at all
- * @property NO_MOUSEEVENTS
- * @type {Boolean}
- */
- GestureDetector.NO_MOUSEEVENTS = GestureDetector.HAS_TOUCHEVENTS && GestureDetector.IS_MOBILE || GestureDetector.HAS_POINTEREVENTS;
-
- /**
- * interval in which GestureDetector recalculates current velocity/direction/angle in ms
- * @property CALCULATE_INTERVAL
- * @type {Number}
- * @default 25
- */
- GestureDetector.CALCULATE_INTERVAL = 25;
-
- /**
- * eventtypes per touchevent (start, move, end) are filled by `Event.determineEventTypes` on `setup`
- * the object contains the DOM event names per type (`EVENT_START`, `EVENT_MOVE`, `EVENT_END`)
- * @property EVENT_TYPES
- * @private
- * @writeOnce
- * @type {Object}
- */
- var EVENT_TYPES = {};
-
- /**
- * direction strings, for safe comparisons
- * @property DIRECTION_DOWN|LEFT|UP|RIGHT
- * @final
- * @type {String}
- * @default 'down' 'left' 'up' 'right'
- */
- var DIRECTION_DOWN = GestureDetector.DIRECTION_DOWN = 'down';
- var DIRECTION_LEFT = GestureDetector.DIRECTION_LEFT = 'left';
- var DIRECTION_UP = GestureDetector.DIRECTION_UP = 'up';
- var DIRECTION_RIGHT = GestureDetector.DIRECTION_RIGHT = 'right';
-
- /**
- * pointertype strings, for safe comparisons
- * @property POINTER_MOUSE|TOUCH|PEN
- * @final
- * @type {String}
- * @default 'mouse' 'touch' 'pen'
- */
- var POINTER_MOUSE = GestureDetector.POINTER_MOUSE = 'mouse';
- var POINTER_TOUCH = GestureDetector.POINTER_TOUCH = 'touch';
- var POINTER_PEN = GestureDetector.POINTER_PEN = 'pen';
-
- /**
- * eventtypes
- * @property EVENT_START|MOVE|END|RELEASE|TOUCH
- * @final
- * @type {String}
- * @default 'start' 'change' 'move' 'end' 'release' 'touch'
- */
- var EVENT_START = GestureDetector.EVENT_START = 'start';
- var EVENT_MOVE = GestureDetector.EVENT_MOVE = 'move';
- var EVENT_END = GestureDetector.EVENT_END = 'end';
- var EVENT_RELEASE = GestureDetector.EVENT_RELEASE = 'release';
- var EVENT_TOUCH = GestureDetector.EVENT_TOUCH = 'touch';
-
- /**
- * if the window events are set...
- * @property READY
- * @writeOnce
- * @type {Boolean}
- * @default false
- */
- GestureDetector.READY = false;
-
- /**
- * plugins namespace
- * @property plugins
- * @type {Object}
- */
- GestureDetector.plugins = GestureDetector.plugins || {};
-
- /**
- * gestures namespace
- * see `/gestures` for the definitions
- * @property gestures
- * @type {Object}
- */
- GestureDetector.gestures = GestureDetector.gestures || {};
-
- /**
- * setup events to detect gestures on the document
- * this function is called when creating an new instance
- * @private
- */
- function setup(opts) {
- if (GestureDetector.READY) {
- return;
- }
-
- // find what eventtypes we add listeners to
- Event$1.determineEventTypes();
-
- // Register all gestures inside GestureDetector.gestures
- Utils.each(GestureDetector.gestures, function (gesture) {
- Detection.register(gesture);
- });
-
- // Add touch events on the document
- Event$1.onTouch(GestureDetector.DOCUMENT, EVENT_MOVE, Detection.detect, opts);
- Event$1.onTouch(GestureDetector.DOCUMENT, EVENT_END, Detection.detect, opts);
-
- // GestureDetector is ready...!
- GestureDetector.READY = true;
- }
-
- /**
- * @module GestureDetector
- *
- * @class Utils
- * @static
- */
- Utils = GestureDetector.utils = {
- /**
- * extend method, could also be used for cloning when `dest` is an empty object.
- * changes the dest object
- * @param {Object} dest
- * @param {Object} src
- * @param {Boolean} [merge=false] do a merge
- * @return {Object} dest
- */
- extend: function extend(dest, src, merge) {
- for (var key in src) {
- if (src.hasOwnProperty(key) && (dest[key] === undefined || !merge)) {
- dest[key] = src[key];
- }
- }
- return dest;
- },
-
- /**
- * simple addEventListener wrapper
- * @param {HTMLElement} element
- * @param {String} type
- * @param {Function} handler
- */
- on: function on(element, type, handler, opt) {
- util$1.addEventListener(element, type, handler, opt, true);
- },
-
- /**
- * simple removeEventListener wrapper
- * @param {HTMLElement} element
- * @param {String} type
- * @param {Function} handler
- */
- off: function off(element, type, handler, opt) {
- util$1.removeEventListener(element, type, handler, opt, true);
- },
-
- /**
- * forEach over arrays and objects
- * @param {Object|Array} obj
- * @param {Function} iterator
- * @param {any} iterator.item
- * @param {Number} iterator.index
- * @param {Object|Array} iterator.obj the source object
- * @param {Object} context value to use as `this` in the iterator
- */
- each: function each(obj, iterator, context) {
- var i, len;
-
- // native forEach on arrays
- if ('forEach' in obj) {
- obj.forEach(iterator, context);
- // arrays
- } else if (obj.length !== undefined) {
- for (i = 0, len = obj.length; i < len; i++) {
- if (iterator.call(context, obj[i], i, obj) === false) {
- return;
- }
- }
- // objects
- } else {
- for (i in obj) {
- if (obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj) === false) {
- return;
- }
- }
- }
- },
-
- /**
- * find if a string contains the string using indexOf
- * @param {String} src
- * @param {String} find
- * @return {Boolean} found
- */
- inStr: function inStr(src, find) {
- return src.indexOf(find) > -1;
- },
-
- /**
- * find if a array contains the object using indexOf or a simple polyfill
- * @param {String} src
- * @param {String} find
- * @return {Boolean|Number} false when not found, or the index
- */
- inArray: function inArray(src, find, deep) {
- if (deep) {
- for (var i = 0, len = src.length; i < len; i++) {
- // Array.findIndex
- if (Object.keys(find).every(function (key) {
- return src[i][key] === find[key];
- })) {
- return i;
- }
- }
- return -1;
- }
-
- if (src.indexOf) {
- return src.indexOf(find);
- } else {
- for (var i = 0, len = src.length; i < len; i++) {
- if (src[i] === find) {
- return i;
- }
- }
- return -1;
- }
- },
-
- /**
- * convert an array-like object (`arguments`, `touchlist`) to an array
- * @param {Object} obj
- * @return {Array}
- */
- toArray: function toArray(obj) {
- return Array.prototype.slice.call(obj, 0);
- },
-
- /**
- * find if a node is in the given parent
- * @param {HTMLElement} node
- * @param {HTMLElement} parent
- * @return {Boolean} found
- */
- hasParent: function hasParent(node, parent) {
- while (node) {
- if (node == parent) {
- return true;
- }
- node = node.parentNode;
- }
- return false;
- },
-
- /**
- * get the center of all the touches
- * @param {Array} touches
- * @return {Object} center contains `pageX`, `pageY`, `clientX` and `clientY` properties
- */
- getCenter: function getCenter(touches) {
- var pageX = [],
- pageY = [],
- clientX = [],
- clientY = [],
- min = Math.min,
- max = Math.max;
-
- // no need to loop when only one touch
- if (touches.length === 1) {
- return {
- pageX: touches[0].pageX,
- pageY: touches[0].pageY,
- clientX: touches[0].clientX,
- clientY: touches[0].clientY
- };
- }
-
- Utils.each(touches, function (touch) {
- pageX.push(touch.pageX);
- pageY.push(touch.pageY);
- clientX.push(touch.clientX);
- clientY.push(touch.clientY);
- });
-
- return {
- pageX: (min.apply(Math, pageX) + max.apply(Math, pageX)) / 2,
- pageY: (min.apply(Math, pageY) + max.apply(Math, pageY)) / 2,
- clientX: (min.apply(Math, clientX) + max.apply(Math, clientX)) / 2,
- clientY: (min.apply(Math, clientY) + max.apply(Math, clientY)) / 2
- };
- },
-
- /**
- * calculate the velocity between two points. unit is in px per ms.
- * @param {Number} deltaTime
- * @param {Number} deltaX
- * @param {Number} deltaY
- * @return {Object} velocity `x` and `y`
- */
- getVelocity: function getVelocity(deltaTime, deltaX, deltaY) {
- return {
- x: Math.abs(deltaX / deltaTime) || 0,
- y: Math.abs(deltaY / deltaTime) || 0
- };
- },
-
- /**
- * calculate the angle between two coordinates
- * @param {Touch} touch1
- * @param {Touch} touch2
- * @return {Number} angle
- */
- getAngle: function getAngle(touch1, touch2) {
- var x = touch2.clientX - touch1.clientX,
- y = touch2.clientY - touch1.clientY;
-
- return Math.atan2(y, x) * 180 / Math.PI;
- },
-
- /**
- * do a small comparison to get the direction between two touches.
- * @param {Touch} touch1
- * @param {Touch} touch2
- * @return {String} direction matches `DIRECTION_LEFT|RIGHT|UP|DOWN`
- */
- getDirection: function getDirection(touch1, touch2) {
- var x = Math.abs(touch1.clientX - touch2.clientX),
- y = Math.abs(touch1.clientY - touch2.clientY);
-
- if (x >= y) {
- return touch1.clientX - touch2.clientX > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
- }
- return touch1.clientY - touch2.clientY > 0 ? DIRECTION_UP : DIRECTION_DOWN;
- },
-
- /**
- * calculate the distance between two touches
- * @param {Touch}touch1
- * @param {Touch} touch2
- * @return {Number} distance
- */
- getDistance: function getDistance(touch1, touch2) {
- var x = touch2.clientX - touch1.clientX,
- y = touch2.clientY - touch1.clientY;
-
- return Math.sqrt(x * x + y * y);
- },
-
- /**
- * calculate the scale factor between two touchLists
- * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
- * @param {Array} start array of touches
- * @param {Array} end array of touches
- * @return {Number} scale
- */
- getScale: function getScale(start, end) {
- // need two fingers...
- if (start.length >= 2 && end.length >= 2) {
- return this.getDistance(end[0], end[1]) / this.getDistance(start[0], start[1]);
- }
- return 1;
- },
-
- /**
- * calculate the rotation degrees between two touchLists
- * @param {Array} start array of touches
- * @param {Array} end array of touches
- * @return {Number} rotation
- */
- getRotation: function getRotation(start, end) {
- // need two fingers
- if (start.length >= 2 && end.length >= 2) {
- return this.getAngle(end[1], end[0]) - this.getAngle(start[1], start[0]);
- }
- return 0;
- },
-
- /**
- * find out if the direction is vertical *
- * @param {String} direction matches `DIRECTION_UP|DOWN`
- * @return {Boolean} is_vertical
- */
- isVertical: function isVertical(direction) {
- return direction == DIRECTION_UP || direction == DIRECTION_DOWN;
- },
-
- /**
- * set css properties with their prefixes
- * @param {HTMLElement} element
- * @param {String} prop
- * @param {String} value
- * @param {Boolean} [toggle=true]
- * @return {Boolean}
- */
- setPrefixedCss: function setPrefixedCss(element, prop, value, toggle) {
- var prefixes = ['', 'Webkit', 'Moz', 'O', 'ms'];
- prop = Utils.toCamelCase(prop);
-
- for (var i = 0; i < prefixes.length; i++) {
- var p = prop;
- // prefixes
- if (prefixes[i]) {
- p = prefixes[i] + p.slice(0, 1).toUpperCase() + p.slice(1);
- }
-
- // test the style
- if (p in element.style) {
- element.style[p] = (toggle === null || toggle) && value || '';
- break;
- }
- }
- },
-
- /**
- * toggle browser default behavior by setting css properties.
- * `userSelect='none'` also sets `element.onselectstart` to false
- * `userDrag='none'` also sets `element.ondragstart` to false
- *
- * @param {HtmlElement} element
- * @param {Object} props
- * @param {Boolean} [toggle=true]
- */
- toggleBehavior: function toggleBehavior(element, props, toggle) {
- if (!props || !element || !element.style) {
- return;
- }
-
- // set the css properties
- Utils.each(props, function (value, prop) {
- Utils.setPrefixedCss(element, prop, value, toggle);
- });
-
- var falseFn = toggle && function () {
- return false;
- };
-
- // also the disable onselectstart
- if (props.userSelect == 'none') {
- element.onselectstart = falseFn;
- }
- // and disable ondragstart
- if (props.userDrag == 'none') {
- element.ondragstart = falseFn;
- }
- },
-
- /**
- * convert a string with underscores to camelCase
- * so prevent_default becomes preventDefault
- * @param {String} str
- * @return {String} camelCaseStr
- */
- toCamelCase: function toCamelCase(str) {
- return str.replace(/[_-]([a-z])/g, function (s) {
- return s[1].toUpperCase();
- });
- }
- };
-
- /**
- * @module GestureDetector
- */
- /**
- * @class Event
- * @static
- */
- Event$1 = GestureDetector.event = {
- /**
- * when touch events have been fired, this is true
- * this is used to stop mouse events
- * @property prevent_mouseevents
- * @private
- * @type {Boolean}
- */
- preventMouseEvents: false,
-
- /**
- * if EVENT_START has been fired
- * @property started
- * @private
- * @type {Boolean}
- */
- started: false,
-
- /**
- * when the mouse is hold down, this is true
- * @property should_detect
- * @private
- * @type {Boolean}
- */
- shouldDetect: false,
-
- /**
- * simple event binder with a hook and support for multiple types
- * @param {HTMLElement} element
- * @param {String} type
- * @param {Function} handler
- * @param {Object} [opt]
- * @param {Function} [hook]
- * @param {Object} hook.type
- */
- on: function on(element, type, handler, opt, hook) {
- var types = type.split(' ');
- Utils.each(types, function (type) {
- Utils.on(element, type, handler, opt);
- hook && hook(type);
- });
- },
-
- /**
- * simple event unbinder with a hook and support for multiple types
- * @param {HTMLElement} element
- * @param {String} type
- * @param {Function} handler
- * @param {Object} [opt]
- * @param {Function} [hook]
- * @param {Object} hook.type
- */
- off: function off(element, type, handler, opt, hook) {
- var types = type.split(' ');
- Utils.each(types, function (type) {
- Utils.off(element, type, handler, opt);
- hook && hook(type);
- });
- },
-
- /**
- * the core touch event handler.
- * this finds out if we should to detect gestures
- * @param {HTMLElement} element
- * @param {String} eventType matches `EVENT_START|MOVE|END`
- * @param {Function} handler
- * @return onTouchHandler {Function} the core event handler
- */
- onTouch: function onTouch(element, eventType, handler, opt) {
- var self = this;
-
- var onTouchHandler = function onTouchHandler(ev) {
- var srcType = ev.type.toLowerCase(),
- isPointer = GestureDetector.HAS_POINTEREVENTS,
- isMouse = Utils.inStr(srcType, 'mouse'),
- triggerType;
-
- // if we are in a mouseevent, but there has been a touchevent triggered in this session
- // we want to do nothing. simply break out of the event.
- if (isMouse && self.preventMouseEvents) {
- return;
-
- // mousebutton must be down
- } else if (isMouse && eventType == EVENT_START && ev.button === 0) {
- self.preventMouseEvents = false;
- self.shouldDetect = true;
- } else if (isPointer && eventType == EVENT_START) {
- self.shouldDetect = ev.buttons === 1 || PointerEvent.matchType(POINTER_TOUCH, ev);
- // just a valid start event, but no mouse
- } else if (!isMouse && eventType == EVENT_START) {
- self.preventMouseEvents = true;
- self.shouldDetect = true;
- }
-
- // update the pointer event before entering the detection
- if (isPointer && eventType != EVENT_END) {
- PointerEvent.updatePointer(eventType, ev);
- }
-
- // we are in a touch/down state, so allowed detection of gestures
- if (self.shouldDetect) {
- triggerType = self.doDetect.call(self, ev, eventType, element, handler);
- }
-
- // ...and we are done with the detection
- // so reset everything to start each detection totally fresh
- if (triggerType == EVENT_END) {
- self.preventMouseEvents = false;
- self.shouldDetect = false;
- PointerEvent.reset();
- // update the pointerevent object after the detection
- }
-
- if (isPointer && eventType == EVENT_END) {
- PointerEvent.updatePointer(eventType, ev);
- }
- };
-
- this.on(element, EVENT_TYPES[eventType], onTouchHandler, opt);
- return onTouchHandler;
- },
-
- /**
- * the core detection method
- * this finds out what GestureDetector-touch-events to trigger
- * @param {Object} ev
- * @param {String} eventType matches `EVENT_START|MOVE|END`
- * @param {HTMLElement} element
- * @param {Function} handler
- * @return {String} triggerType matches `EVENT_START|MOVE|END`
- */
- doDetect: function doDetect(ev, eventType, element, handler) {
- var touchList = this.getTouchList(ev, eventType);
- var touchListLength = touchList.length;
- var triggerType = eventType;
- var triggerChange = touchList.trigger; // used by fakeMultitouch plugin
- var changedLength = touchListLength;
-
- // at each touchstart-like event we want also want to trigger a TOUCH event...
- if (eventType == EVENT_START) {
- triggerChange = EVENT_TOUCH;
- // ...the same for a touchend-like event
- } else if (eventType == EVENT_END) {
- triggerChange = EVENT_RELEASE;
-
- // keep track of how many touches have been removed
- changedLength = touchList.length - (ev.changedTouches ? ev.changedTouches.length : 1);
- }
-
- // after there are still touches on the screen,
- // we just want to trigger a MOVE event. so change the START or END to a MOVE
- // but only after detection has been started, the first time we actually want a START
- if (changedLength > 0 && this.started) {
- triggerType = EVENT_MOVE;
- }
-
- // detection has been started, we keep track of this, see above
- this.started = true;
-
- // generate some event data, some basic information
- var evData = this.collectEventData(element, triggerType, touchList, ev);
-
- // trigger the triggerType event before the change (TOUCH, RELEASE) events
- // but the END event should be at last
- if (eventType != EVENT_END) {
- handler.call(Detection, evData);
- }
-
- // trigger a change (TOUCH, RELEASE) event, this means the length of the touches changed
- if (triggerChange) {
- evData.changedLength = changedLength;
- evData.eventType = triggerChange;
-
- handler.call(Detection, evData);
-
- evData.eventType = triggerType;
- delete evData.changedLength;
- }
-
- // trigger the END event
- if (triggerType == EVENT_END) {
- handler.call(Detection, evData);
-
- // ...and we are done with the detection
- // so reset everything to start each detection totally fresh
- this.started = false;
- }
-
- return triggerType;
- },
-
- /**
- * we have different events for each device/browser
- * determine what we need and set them in the EVENT_TYPES constant
- * the `onTouch` method is bind to these properties.
- * @return {Object} events
- */
- determineEventTypes: function determineEventTypes() {
- var types;
- if (GestureDetector.HAS_POINTEREVENTS) {
- if (window.PointerEvent) {
- types = ['pointerdown', 'pointermove', 'pointerup pointercancel lostpointercapture'];
- } else {
- types = ['MSPointerDown', 'MSPointerMove', 'MSPointerUp MSPointerCancel MSLostPointerCapture'];
- }
- } else if (GestureDetector.NO_MOUSEEVENTS) {
- types = ['touchstart', 'touchmove', 'touchend touchcancel'];
- } else {
- types = ['touchstart mousedown', 'touchmove mousemove', 'touchend touchcancel mouseup'];
- }
-
- EVENT_TYPES[EVENT_START] = types[0];
- EVENT_TYPES[EVENT_MOVE] = types[1];
- EVENT_TYPES[EVENT_END] = types[2];
- return EVENT_TYPES;
- },
-
- /**
- * create touchList depending on the event
- * @param {Object} ev
- * @param {String} eventType
- * @return {Array} touches
- */
- getTouchList: function getTouchList(ev, eventType) {
- // get the fake pointerEvent touchlist
- if (GestureDetector.HAS_POINTEREVENTS) {
- return PointerEvent.getTouchList();
- }
-
- // get the touchlist
- if (ev.touches) {
- if (eventType == EVENT_MOVE) {
- return ev.touches;
- }
-
- var identifiers = [];
- var concat = [].concat(Utils.toArray(ev.touches), Utils.toArray(ev.changedTouches));
- var touchList = [];
-
- Utils.each(concat, function (touch) {
- if (Utils.inArray(identifiers, touch.identifier) === -1) {
- touchList.push(touch);
- }
- identifiers.push(touch.identifier);
- });
-
- return touchList;
- }
-
- // make fake touchList from mouse position
- ev.identifier = 1;
- return [ev];
- },
-
- /**
- * collect basic event data
- * @param {HTMLElement} element
- * @param {String} eventType matches `EVENT_START|MOVE|END`
- * @param {Array} touches
- * @param {Object} ev
- * @return {Object} ev
- */
- collectEventData: function collectEventData(element, eventType, touches, ev) {
- // find out pointerType
- var pointerType = POINTER_TOUCH;
- if (Utils.inStr(ev.type, 'mouse') || PointerEvent.matchType(POINTER_MOUSE, ev)) {
- pointerType = POINTER_MOUSE;
- } else if (PointerEvent.matchType(POINTER_PEN, ev)) {
- pointerType = POINTER_PEN;
- }
-
- return {
- center: Utils.getCenter(touches),
- timeStamp: Date.now(),
- target: ev.target,
- touches: touches,
- eventType: eventType,
- pointerType: pointerType,
- srcEvent: ev,
-
- /**
- * prevent the browser default actions
- * mostly used to disable scrolling of the browser
- */
- preventDefault: function preventDefault() {
- var srcEvent = this.srcEvent;
- srcEvent.preventManipulation && srcEvent.preventManipulation();
- srcEvent.preventDefault && srcEvent.preventDefault();
- },
-
- /**
- * stop bubbling the event up to its parents
- */
- stopPropagation: function stopPropagation() {
- this.srcEvent.stopPropagation();
- },
-
- /**
- * immediately stop gesture detection
- * might be useful after a swipe was detected
- * @return {*}
- */
- stopDetect: function stopDetect() {
- return Detection.stopDetect();
- }
- };
- }
- };
-
- /**
- * @module GestureDetector
- *
- * @class PointerEvent
- * @static
- */
- PointerEvent = GestureDetector.PointerEvent = {
- /**
- * holds all pointers, by `identifier`
- * @property pointers
- * @type {Object}
- */
- pointers: {},
-
- /**
- * get the pointers as an array
- * @return {Array} touchlist
- */
- getTouchList: function getTouchList() {
- var touchlist = [];
- // we can use forEach since pointerEvents only is in IE10
- Utils.each(this.pointers, function (pointer) {
- touchlist.push(pointer);
- });
- return touchlist;
- },
-
- /**
- * update the position of a pointer
- * @param {String} eventType matches `EVENT_START|MOVE|END`
- * @param {Object} pointerEvent
- */
- updatePointer: function updatePointer(eventType, pointerEvent) {
- if (eventType == EVENT_END || eventType != EVENT_END && pointerEvent.buttons !== 1) {
- delete this.pointers[pointerEvent.pointerId];
- } else {
- pointerEvent.identifier = pointerEvent.pointerId;
- this.pointers[pointerEvent.pointerId] = pointerEvent;
- }
- },
-
- /**
- * check if ev matches pointertype
- * @param {String} pointerType matches `POINTER_MOUSE|TOUCH|PEN`
- * @param {PointerEvent} ev
- */
- matchType: function matchType(pointerType, ev) {
- if (!ev.pointerType) {
- return false;
- }
-
- var pt = ev.pointerType,
- types = {};
-
- types[POINTER_MOUSE] = pt === (ev.MSPOINTER_TYPE_MOUSE || POINTER_MOUSE);
- types[POINTER_TOUCH] = pt === (ev.MSPOINTER_TYPE_TOUCH || POINTER_TOUCH);
- types[POINTER_PEN] = pt === (ev.MSPOINTER_TYPE_PEN || POINTER_PEN);
- return types[pointerType];
- },
-
- /**
- * reset the stored pointers
- */
- reset: function resetList() {
- this.pointers = {};
- }
- };
-
- /**
- * @module GestureDetector
- *
- * @class Detection
- * @static
- */
- Detection = GestureDetector.detection = {
- // contains all registered GestureDetector.gestures in the correct order
- gestures: [],
-
- // data of the current GestureDetector.gesture detection session
- current: null,
-
- // the previous GestureDetector.gesture session data
- // is a full clone of the previous gesture.current object
- previous: null,
-
- // when this becomes true, no gestures are fired
- stopped: false,
-
- /**
- * start GestureDetector.gesture detection
- * @param {GestureDetector.Instance} inst
- * @param {Object} eventData
- */
- startDetect: function startDetect(inst, eventData) {
- // already busy with a GestureDetector.gesture detection on an element
- if (this.current) {
- return;
- }
-
- this.stopped = false;
-
- // holds current session
- this.current = {
- inst: inst, // reference to GestureDetectorInstance we're working for
- startEvent: Utils.extend({}, eventData), // start eventData for distances, timing etc
- lastEvent: false, // last eventData
- lastCalcEvent: false, // last eventData for calculations.
- futureCalcEvent: false, // last eventData for calculations.
- lastCalcData: {}, // last lastCalcData
- name: '' // current gesture we're in/detected, can be 'tap', 'hold' etc
- };
-
- this.detect(eventData);
- },
-
- /**
- * GestureDetector.gesture detection
- * @param {Object} eventData
- * @return {any}
- */
- detect: function detect(eventData) {
- if (!this.current || this.stopped) {
- return;
- }
-
- // extend event data with calculations about scale, distance etc
- eventData = this.extendEventData(eventData);
-
- // GestureDetector instance and instance options
- var inst = this.current.inst,
- instOptions = inst.options;
-
- // call GestureDetector.gesture handlers
- Utils.each(this.gestures, function triggerGesture(gesture) {
- // only when the instance options have enabled this gesture
- if (!this.stopped && inst.enabled && instOptions[gesture.name]) {
- gesture.handler.call(gesture, eventData, inst);
- }
- }, this);
-
- // store as previous event event
- if (this.current) {
- this.current.lastEvent = eventData;
- }
-
- if (eventData.eventType == EVENT_END) {
- this.stopDetect();
- }
-
- return eventData; // eslint-disable-line consistent-return
- },
-
- /**
- * clear the GestureDetector.gesture vars
- * this is called on endDetect, but can also be used when a final GestureDetector.gesture has been detected
- * to stop other GestureDetector.gestures from being fired
- */
- stopDetect: function stopDetect() {
- // clone current data to the store as the previous gesture
- // used for the double tap gesture, since this is an other gesture detect session
- this.previous = Utils.extend({}, this.current);
-
- // reset the current
- this.current = null;
- this.stopped = true;
- },
-
- /**
- * calculate velocity, angle and direction
- * @param {Object} ev
- * @param {Object} center
- * @param {Number} deltaTime
- * @param {Number} deltaX
- * @param {Number} deltaY
- */
- getCalculatedData: function getCalculatedData(ev, center, deltaTime, deltaX, deltaY) {
- var cur = this.current,
- recalc = false,
- calcEv = cur.lastCalcEvent,
- calcData = cur.lastCalcData;
-
- if (calcEv && ev.timeStamp - calcEv.timeStamp > GestureDetector.CALCULATE_INTERVAL) {
- center = calcEv.center;
- deltaTime = ev.timeStamp - calcEv.timeStamp;
- deltaX = ev.center.clientX - calcEv.center.clientX;
- deltaY = ev.center.clientY - calcEv.center.clientY;
- recalc = true;
- }
-
- if (ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) {
- cur.futureCalcEvent = ev;
- }
-
- if (!cur.lastCalcEvent || recalc) {
- calcData.velocity = Utils.getVelocity(deltaTime, deltaX, deltaY);
- calcData.angle = Utils.getAngle(center, ev.center);
- calcData.direction = Utils.getDirection(center, ev.center);
-
- cur.lastCalcEvent = cur.futureCalcEvent || ev;
- cur.futureCalcEvent = ev;
- }
-
- ev.velocityX = calcData.velocity.x;
- ev.velocityY = calcData.velocity.y;
- ev.interimAngle = calcData.angle;
- ev.interimDirection = calcData.direction;
- },
-
- /**
- * extend eventData for GestureDetector.gestures
- * @param {Object} ev
- * @return {Object} ev
- */
- extendEventData: function extendEventData(ev) {
- var cur = this.current,
- startEv = cur.startEvent,
- lastEv = cur.lastEvent || startEv;
-
- // update the start touchlist to calculate the scale/rotation
- if (ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) {
- startEv.touches = [];
- Utils.each(ev.touches, function (touch) {
- startEv.touches.push({
- clientX: touch.clientX,
- clientY: touch.clientY
- });
- });
- }
-
- var deltaTime = ev.timeStamp - startEv.timeStamp,
- deltaX = ev.center.clientX - startEv.center.clientX,
- deltaY = ev.center.clientY - startEv.center.clientY;
-
- this.getCalculatedData(ev, lastEv.center, deltaTime, deltaX, deltaY);
-
- Utils.extend(ev, {
- startEvent: startEv,
-
- deltaTime: deltaTime,
- deltaX: deltaX,
- deltaY: deltaY,
-
- distance: Utils.getDistance(startEv.center, ev.center),
- angle: Utils.getAngle(startEv.center, ev.center),
- direction: Utils.getDirection(startEv.center, ev.center),
- scale: Utils.getScale(startEv.touches, ev.touches),
- rotation: Utils.getRotation(startEv.touches, ev.touches)
- });
-
- return ev;
- },
-
- /**
- * register new gesture
- * @param {Object} gesture object, see `gestures/` for documentation
- * @return {Array} gestures
- */
- register: function register(gesture) {
- // add an enable gesture options if there is no given
- var options = gesture.defaults || {};
- if (options[gesture.name] === undefined) {
- options[gesture.name] = true;
- }
-
- // extend GestureDetector default options with the GestureDetector.gesture options
- Utils.extend(GestureDetector.defaults, options, true);
-
- // set its index
- gesture.index = gesture.index || 1000;
-
- // add GestureDetector.gesture to the list
- this.gestures.push(gesture);
-
- // sort the list by index
- this.gestures.sort(function (a, b) {
- if (a.index < b.index) {
- return -1;
- }
- if (a.index > b.index) {
- return 1;
- }
- return 0;
- });
-
- return this.gestures;
- }
- };
-
- /**
- * @module GestureDetector
- */
-
- /**
- * create new GestureDetector instance
- * all methods should return the instance itself, so it is chainable.
- *
- * @class Instance
- * @constructor
- * @param {HTMLElement} element
- * @param {Object} [options={}] options are merged with `GestureDetector.defaults`
- * @return {GestureDetector.Instance}
- */
- GestureDetector.Instance = function (element, options) {
- var self = this;
- var listenerOptions = options && options.passive ? { passive: true } : undefined;
-
- // setup GestureDetectorJS window events and register all gestures
- // this also sets up the default options
- setup(listenerOptions);
-
- /**
- * @property element
- * @type {HTMLElement}
- */
- this.element = element;
-
- /**
- * @property enabled
- * @type {Boolean}
- * @protected
- */
- this.enabled = true;
-
- /**
- * options, merged with the defaults
- * options with an _ are converted to camelCase
- * @property options
- * @type {Object}
- */
- Utils.each(options, function (value, name) {
- delete options[name];
- options[Utils.toCamelCase(name)] = value;
- });
-
- this.options = Utils.extend(Utils.extend({}, GestureDetector.defaults), options || {});
- this.options.listenerOptions = listenerOptions;
-
- // add some css to the element to prevent the browser from doing its native behavior
- if (this.options.behavior) {
- Utils.toggleBehavior(this.element, this.options.behavior, true);
- }
-
- /**
- * event start handler on the element to start the detection
- * @property eventStartHandler
- * @type {Object}
- */
- this.eventStartHandler = Event$1.onTouch(element, EVENT_START, function (ev) {
- if (self.enabled && ev.eventType == EVENT_START) {
- Detection.startDetect(self, ev);
- } else if (ev.eventType == EVENT_TOUCH) {
- Detection.detect(ev);
- }
- }, listenerOptions);
-
- /**
- * keep a list of user event handlers which needs to be removed when calling 'dispose'
- * @property eventHandlers
- * @type {Array}
- */
- this.eventHandlers = [];
- };
-
- GestureDetector.Instance.prototype = {
- /**
- * @method on
- * @signature on(gestures, handler)
- * @description
- * [en]Adds an event handler for a gesture. Available gestures are: drag, dragleft, dragright, dragup, dragdown, hold, release, swipe, swipeleft, swiperight, swipeup, swipedown, tap, doubletap, touch, transform, pinch, pinchin, pinchout and rotate. [/en]
- * [ja]ジェスチャに対するイベントハンドラを追加します。指定できるジェスチャ名は、drag dragleft dragright dragup dragdown hold release swipe swipeleft swiperight swipeup swipedown tap doubletap touch transform pinch pinchin pinchout rotate です。[/ja]
- * @param {String} gestures
- * [en]A space separated list of gestures.[/en]
- * [ja]検知するジェスチャ名を指定します。スペースで複数指定することができます。[/ja]
- * @param {Function} handler
- * [en]An event handling function.[/en]
- * [ja]イベントハンドラとなる関数オブジェクトを指定します。[/ja]
- */
- on: function onEvent(gestures, handler, opt) {
- var self = this;
-
- Event$1.on(self.element, gestures, handler, util$1.extend({}, self.options.listenerOptions, opt), function (type) {
- self.eventHandlers.push({ gesture: type, handler: handler });
- });
- return self;
- },
-
- /**
- * @method off
- * @signature off(gestures, handler)
- * @description
- * [en]Remove an event listener.[/en]
- * [ja]イベントリスナーを削除します。[/ja]
- * @param {String} gestures
- * [en]A space separated list of gestures.[/en]
- * [ja]ジェスチャ名を指定します。スペースで複数指定することができます。[/ja]
- * @param {Function} handler
- * [en]An event handling function.[/en]
- * [ja]イベントハンドラとなる関数オブジェクトを指定します。[/ja]
- */
- off: function offEvent(gestures, handler, opt) {
- var self = this;
-
- Event$1.off(self.element, gestures, handler, util$1.extend({}, self.options.listenerOptions, opt), function (type) {
- var index = Utils.inArray(self.eventHandlers, { gesture: type, handler: handler }, true);
- if (index >= 0) {
- self.eventHandlers.splice(index, 1);
- }
- });
- return self;
- },
-
- /**
- * trigger gesture event
- * @method trigger
- * @signature trigger(gesture, eventData)
- * @param {String} gesture
- * @param {Object} [eventData]
- */
- trigger: function triggerEvent(gesture, eventData) {
- // optional
- if (!eventData) {
- eventData = {};
- }
-
- // create DOM event
- var event = GestureDetector.DOCUMENT.createEvent('Event');
- event.initEvent(gesture, true, true);
- event.gesture = eventData;
-
- // trigger on the target if it is in the instance element,
- // this is for event delegation tricks
- var element = this.element;
- if (Utils.hasParent(eventData.target, element)) {
- element = eventData.target;
- }
-
- element.dispatchEvent(event);
- return this;
- },
-
- /**
- * @method enable
- * @signature enable(state)
- * @description
- * [en]Enable or disable gesture detection.[/en]
- * [ja]ジェスチャ検知を有効化/無効化します。[/ja]
- * @param {Boolean} state
- * [en]Specify if it should be enabled or not.[/en]
- * [ja]有効にするかどうかを指定します。[/ja]
- */
- enable: function enable(state) {
- this.enabled = state;
- return this;
- },
-
- /**
- * @method dispose
- * @signature dispose()
- * @description
- * [en]Remove and destroy all event handlers for this instance.[/en]
- * [ja]このインスタンスでのジェスチャの検知や、イベントハンドラを全て解除して廃棄します。[/ja]
- */
- dispose: function dispose() {
- var i, eh;
-
- // undo all changes made by stop_browser_behavior
- Utils.toggleBehavior(this.element, this.options.behavior, false);
-
- // unbind all custom event handlers
- for (i = -1; eh = this.eventHandlers[++i];) {
- // eslint-disable-line no-cond-assign
- Utils.off(this.element, eh.gesture, eh.handler);
- }
-
- this.eventHandlers = [];
-
- // unbind the start event listener
- Event$1.off(this.element, EVENT_TYPES[EVENT_START], this.eventStartHandler);
-
- return null;
- }
- };
-
- /**
- * @module gestures
- */
- /**
- * Move with x fingers (default 1) around on the page.
- * Preventing the default browser behavior is a good way to improve feel and working.
- * ````
- * GestureDetectortime.on("drag", function(ev) {
- * console.log(ev);
- * ev.gesture.preventDefault();
- * });
- * ````
- *
- * @class Drag
- * @static
- */
- /**
- * @event drag
- * @param {Object} ev
- */
- /**
- * @event dragstart
- * @param {Object} ev
- */
- /**
- * @event dragend
- * @param {Object} ev
- */
- /**
- * @event drapleft
- * @param {Object} ev
- */
- /**
- * @event dragright
- * @param {Object} ev
- */
- /**
- * @event dragup
- * @param {Object} ev
- */
- /**
- * @event dragdown
- * @param {Object} ev
- */
-
- /**
- * @param {String} name
- */
- (function (name) {
- var triggered = false;
-
- function dragGesture(ev, inst) {
- var cur = Detection.current;
-
- // max touches
- if (inst.options.dragMaxTouches > 0 && ev.touches.length > inst.options.dragMaxTouches) {
- return;
- }
-
- switch (ev.eventType) {
- case EVENT_START:
- triggered = false;
- break;
-
- case EVENT_MOVE:
- // when the distance we moved is too small we skip this gesture
- // or we can be already in dragging
- if (ev.distance < inst.options.dragMinDistance && cur.name != name) {
- return;
- }
-
- var startCenter = cur.startEvent.center;
-
- // we are dragging!
- if (cur.name != name) {
- cur.name = name;
- if (inst.options.dragDistanceCorrection && ev.distance > 0) {
- // When a drag is triggered, set the event center to dragMinDistance pixels from the original event center.
- // Without this correction, the dragged distance would jumpstart at dragMinDistance pixels instead of at 0.
- // It might be useful to save the original start point somewhere
- var factor = Math.abs(inst.options.dragMinDistance / ev.distance);
- startCenter.pageX += ev.deltaX * factor;
- startCenter.pageY += ev.deltaY * factor;
- startCenter.clientX += ev.deltaX * factor;
- startCenter.clientY += ev.deltaY * factor;
-
- // recalculate event data using new start point
- ev = Detection.extendEventData(ev);
- }
- }
-
- // lock drag to axis?
- if (cur.lastEvent.dragLockToAxis || inst.options.dragLockToAxis && inst.options.dragLockMinDistance <= ev.distance) {
- ev.dragLockToAxis = true;
- }
-
- // keep direction on the axis that the drag gesture started on
- var lastDirection = cur.lastEvent.direction;
- if (ev.dragLockToAxis && lastDirection !== ev.direction) {
- if (Utils.isVertical(lastDirection)) {
- ev.direction = ev.deltaY < 0 ? DIRECTION_UP : DIRECTION_DOWN;
- } else {
- ev.direction = ev.deltaX < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
- }
- }
-
- // first time, trigger dragstart event
- if (!triggered) {
- inst.trigger(name + 'start', ev);
- triggered = true;
- }
-
- // trigger events
- inst.trigger(name, ev);
- inst.trigger(name + ev.direction, ev);
-
- var isVertical = Utils.isVertical(ev.direction);
-
- // block the browser events
- if (inst.options.dragBlockVertical && isVertical || inst.options.dragBlockHorizontal && !isVertical) {
- ev.preventDefault();
- }
- break;
-
- case EVENT_RELEASE:
- if (triggered && ev.changedLength <= inst.options.dragMaxTouches) {
- inst.trigger(name + 'end', ev);
- triggered = false;
- }
- break;
-
- case EVENT_END:
- triggered = false;
- break;
- }
- }
-
- GestureDetector.gestures.Drag = {
- name: name,
- index: 50,
- handler: dragGesture,
- defaults: {
- /**
- * minimal movement that have to be made before the drag event gets triggered
- * @property dragMinDistance
- * @type {Number}
- * @default 10
- */
- dragMinDistance: 10,
-
- /**
- * Set dragDistanceCorrection to true to make the starting point of the drag
- * be calculated from where the drag was triggered, not from where the touch started.
- * Useful to avoid a jerk-starting drag, which can make fine-adjustments
- * through dragging difficult, and be visually unappealing.
- * @property dragDistanceCorrection
- * @type {Boolean}
- * @default true
- */
- dragDistanceCorrection: true,
-
- /**
- * set 0 for unlimited, but this can conflict with transform
- * @property dragMaxTouches
- * @type {Number}
- * @default 1
- */
- dragMaxTouches: 1,
-
- /**
- * prevent default browser behavior when dragging occurs
- * be careful with it, it makes the element a blocking element
- * when you are using the drag gesture, it is a good practice to set this true
- * @property dragBlockHorizontal
- * @type {Boolean}
- * @default false
- */
- dragBlockHorizontal: false,
-
- /**
- * same as `dragBlockHorizontal`, but for vertical movement
- * @property dragBlockVertical
- * @type {Boolean}
- * @default false
- */
- dragBlockVertical: false,
-
- /**
- * dragLockToAxis keeps the drag gesture on the axis that it started on,
- * It disallows vertical directions if the initial direction was horizontal, and vice versa.
- * @property dragLockToAxis
- * @type {Boolean}
- * @default false
- */
- dragLockToAxis: false,
-
- /**
- * drag lock only kicks in when distance > dragLockMinDistance
- * This way, locking occurs only when the distance has become large enough to reliably determine the direction
- * @property dragLockMinDistance
- * @type {Number}
- * @default 25
- */
- dragLockMinDistance: 25
- }
- };
- })('drag');
-
- /**
- * @module gestures
- */
- /**
- * trigger a simple gesture event, so you can do anything in your handler.
- * only usable if you know what your doing...
- *
- * @class Gesture
- * @static
- */
- /**
- * @event gesture
- * @param {Object} ev
- */
- GestureDetector.gestures.Gesture = {
- name: 'gesture',
- index: 1337,
- handler: function releaseGesture(ev, inst) {
- inst.trigger(this.name, ev);
- }
- };
-
- /**
- * @module gestures
- */
- /**
- * Touch stays at the same place for x time
- *
- * @class Hold
- * @static
- */
- /**
- * @event hold
- * @param {Object} ev
- */
-
- /**
- * @param {String} name
- */
- (function (name) {
- var timer;
-
- function holdGesture(ev, inst) {
- var options = inst.options,
- current = Detection.current;
-
- switch (ev.eventType) {
- case EVENT_START:
- clearTimeout(timer);
-
- // set the gesture so we can check in the timeout if it still is
- current.name = name;
-
- // set timer and if after the timeout it still is hold,
- // we trigger the hold event
- timer = setTimeout(function () {
- if (current && current.name == name) {
- inst.trigger(name, ev);
- }
- }, options.holdTimeout);
- break;
-
- case EVENT_MOVE:
- if (ev.distance > options.holdThreshold) {
- clearTimeout(timer);
- }
- break;
-
- case EVENT_RELEASE:
- clearTimeout(timer);
- break;
- }
- }
-
- GestureDetector.gestures.Hold = {
- name: name,
- index: 10,
- defaults: {
- /**
- * @property holdTimeout
- * @type {Number}
- * @default 500
- */
- holdTimeout: 500,
-
- /**
- * movement allowed while holding
- * @property holdThreshold
- * @type {Number}
- * @default 2
- */
- holdThreshold: 2
- },
- handler: holdGesture
- };
- })('hold');
-
- /**
- * @module gestures
- */
- /**
- * when a touch is being released from the page
- *
- * @class Release
- * @static
- */
- /**
- * @event release
- * @param {Object} ev
- */
- GestureDetector.gestures.Release = {
- name: 'release',
- index: Infinity,
- handler: function releaseGesture(ev, inst) {
- if (ev.eventType == EVENT_RELEASE) {
- inst.trigger(this.name, ev);
- }
- }
- };
-
- /**
- * @module gestures
- */
- /**
- * triggers swipe events when the end velocity is above the threshold
- * for best usage, set `preventDefault` (on the drag gesture) to `true`
- * ````
- * GestureDetectortime.on("dragleft swipeleft", function(ev) {
- * console.log(ev);
- * ev.gesture.preventDefault();
- * });
- * ````
- *
- * @class Swipe
- * @static
- */
- /**
- * @event swipe
- * @param {Object} ev
- */
- /**
- * @event swipeleft
- * @param {Object} ev
- */
- /**
- * @event swiperight
- * @param {Object} ev
- */
- /**
- * @event swipeup
- * @param {Object} ev
- */
- /**
- * @event swipedown
- * @param {Object} ev
- */
- GestureDetector.gestures.Swipe = {
- name: 'swipe',
- index: 40,
- defaults: {
- /**
- * @property swipeMinTouches
- * @type {Number}
- * @default 1
- */
- swipeMinTouches: 1,
-
- /**
- * @property swipeMaxTouches
- * @type {Number}
- * @default 1
- */
- swipeMaxTouches: 1,
-
- /**
- * horizontal swipe velocity
- * @property swipeVelocityX
- * @type {Number}
- * @default 0.6
- */
- swipeVelocityX: 0.6,
-
- /**
- * vertical swipe velocity
- * @property swipeVelocityY
- * @type {Number}
- * @default 0.6
- */
- swipeVelocityY: 0.6
- },
-
- handler: function swipeGesture(ev, inst) {
- if (ev.eventType == EVENT_RELEASE) {
- var touches = ev.touches.length,
- options = inst.options;
-
- // max touches
- if (touches < options.swipeMinTouches || touches > options.swipeMaxTouches) {
- return;
- }
-
- // when the distance we moved is too small we skip this gesture
- // or we can be already in dragging
- if (ev.velocityX > options.swipeVelocityX || ev.velocityY > options.swipeVelocityY) {
- // trigger swipe events
- inst.trigger(this.name, ev);
- inst.trigger(this.name + ev.direction, ev);
- }
- }
- }
- };
-
- /**
- * @module gestures
- */
- /**
- * Single tap and a double tap on a place
- *
- * @class Tap
- * @static
- */
- /**
- * @event tap
- * @param {Object} ev
- */
- /**
- * @event doubletap
- * @param {Object} ev
- */
-
- /**
- * @param {String} name
- */
- (function (name) {
- var hasMoved = false;
-
- function tapGesture(ev, inst) {
- var options = inst.options,
- current = Detection.current,
- prev = Detection.previous,
- sincePrev,
- didDoubleTap;
-
- switch (ev.eventType) {
- case EVENT_START:
- hasMoved = false;
- break;
-
- case EVENT_MOVE:
- hasMoved = hasMoved || ev.distance > options.tapMaxDistance;
- break;
-
- case EVENT_END:
- if (!Utils.inStr(ev.srcEvent.type, 'cancel') && ev.deltaTime < options.tapMaxTime && !hasMoved) {
- // previous gesture, for the double tap since these are two different gesture detections
- sincePrev = prev && prev.lastEvent && ev.timeStamp - prev.lastEvent.timeStamp;
- didDoubleTap = false;
-
- // check if double tap
- if (prev && prev.name == name && sincePrev && sincePrev < options.doubleTapInterval && ev.distance < options.doubleTapDistance) {
- inst.trigger('doubletap', ev);
- didDoubleTap = true;
- }
-
- // do a single tap
- if (!didDoubleTap || options.tapAlways) {
- current.name = name;
- inst.trigger(current.name, ev);
- }
- }
- break;
- }
- }
-
- GestureDetector.gestures.Tap = {
- name: name,
- index: 100,
- handler: tapGesture,
- defaults: {
- /**
- * max time of a tap, this is for the slow tappers
- * @property tapMaxTime
- * @type {Number}
- * @default 250
- */
- tapMaxTime: 250,
-
- /**
- * max distance of movement of a tap, this is for the slow tappers
- * @property tapMaxDistance
- * @type {Number}
- * @default 10
- */
- tapMaxDistance: 10,
-
- /**
- * always trigger the `tap` event, even while double-tapping
- * @property tapAlways
- * @type {Boolean}
- * @default true
- */
- tapAlways: true,
-
- /**
- * max distance between two taps
- * @property doubleTapDistance
- * @type {Number}
- * @default 20
- */
- doubleTapDistance: 20,
-
- /**
- * max time between two taps
- * @property doubleTapInterval
- * @type {Number}
- * @default 300
- */
- doubleTapInterval: 300
- }
- };
- })('tap');
-
- /**
- * @module gestures
- */
- /**
- * when a touch is being touched at the page
- *
- * @class Touch
- * @static
- */
- /**
- * @event touch
- * @param {Object} ev
- */
- GestureDetector.gestures.Touch = {
- name: 'touch',
- index: -Infinity,
- defaults: {
- /**
- * call preventDefault at touchstart, and makes the element blocking by disabling the scrolling of the page,
- * but it improves gestures like transforming and dragging.
- * be careful with using this, it can be very annoying for users to be stuck on the page
- * @property preventDefault
- * @type {Boolean}
- * @default false
- */
- preventDefault: false,
-
- /**
- * disable mouse events, so only touch (or pen!) input triggers events
- * @property preventMouse
- * @type {Boolean}
- * @default false
- */
- preventMouse: false
- },
- handler: function touchGesture(ev, inst) {
- if (inst.options.preventMouse && ev.pointerType == POINTER_MOUSE) {
- ev.stopDetect();
- return;
- }
-
- if (inst.options.preventDefault) {
- ev.preventDefault();
- }
-
- if (ev.eventType == EVENT_TOUCH) {
- inst.trigger('touch', ev);
- }
- }
- };
-
- /**
- * @module gestures
- */
- /**
- * User want to scale or rotate with 2 fingers
- * Preventing the default browser behavior is a good way to improve feel and working. This can be done with the
- * `preventDefault` option.
- *
- * @class Transform
- * @static
- */
- /**
- * @event transform
- * @param {Object} ev
- */
- /**
- * @event transformstart
- * @param {Object} ev
- */
- /**
- * @event transformend
- * @param {Object} ev
- */
- /**
- * @event pinchin
- * @param {Object} ev
- */
- /**
- * @event pinchout
- * @param {Object} ev
- */
- /**
- * @event rotate
- * @param {Object} ev
- */
-
- /**
- * @param {String} name
- */
- (function (name) {
- var triggered = false;
-
- function transformGesture(ev, inst) {
- switch (ev.eventType) {
- case EVENT_START:
- triggered = false;
- break;
-
- case EVENT_MOVE:
- // at least multitouch
- if (ev.touches.length < 2) {
- return;
- }
-
- var scaleThreshold = Math.abs(1 - ev.scale);
- var rotationThreshold = Math.abs(ev.rotation);
-
- // when the distance we moved is too small we skip this gesture
- // or we can be already in dragging
- if (scaleThreshold < inst.options.transformMinScale && rotationThreshold < inst.options.transformMinRotation) {
- return;
- }
-
- // we are transforming!
- Detection.current.name = name;
-
- // first time, trigger dragstart event
- if (!triggered) {
- inst.trigger(name + 'start', ev);
- triggered = true;
- }
-
- inst.trigger(name, ev); // basic transform event
-
- // trigger rotate event
- if (rotationThreshold > inst.options.transformMinRotation) {
- inst.trigger('rotate', ev);
- }
-
- // trigger pinch event
- if (scaleThreshold > inst.options.transformMinScale) {
- inst.trigger('pinch', ev);
- inst.trigger('pinch' + (ev.scale < 1 ? 'in' : 'out'), ev);
- }
- break;
-
- case EVENT_RELEASE:
- if (triggered && ev.changedLength < 2) {
- inst.trigger(name + 'end', ev);
- triggered = false;
- }
- break;
- }
- }
-
- GestureDetector.gestures.Transform = {
- name: name,
- index: 45,
- defaults: {
- /**
- * minimal scale factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1
- * @property transformMinScale
- * @type {Number}
- * @default 0.01
- */
- transformMinScale: 0.01,
-
- /**
- * rotation in degrees
- * @property transformMinRotation
- * @type {Number}
- * @default 1
- */
- transformMinRotation: 1
- },
-
- handler: transformGesture
- };
- })('transform');
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var readyMap = void 0;
- var queueMap = void 0;
-
- function isContentReady(element) {
- if (element.childNodes.length > 0) {
- setContentReady(element);
- }
- return readyMap.has(element);
- }
-
- function setContentReady(element) {
- readyMap.set(element, true);
- }
-
- function addCallback(element, fn) {
- if (!queueMap.has(element)) {
- queueMap.set(element, []);
- }
- queueMap.get(element).push(fn);
- }
-
- function consumeQueue(element) {
- var callbacks = queueMap.get(element, []) || [];
- queueMap.delete(element);
- callbacks.forEach(function (callback) {
- return callback();
- });
- }
-
- function contentReady(element) {
- var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {};
-
- if (readyMap === undefined) {
- readyMap = new WeakMap();
- queueMap = new WeakMap();
- }
-
- addCallback(element, fn);
-
- if (isContentReady(element)) {
- consumeQueue(element);
- return;
- }
-
- var observer = new MutationObserver(function (changes) {
- setContentReady(element);
- consumeQueue(element);
- });
- observer.observe(element, { childList: true, characterData: true });
-
- // failback for elements has empty content.
- setImmediate(function () {
- setContentReady(element);
- consumeQueue(element);
- });
- }
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var ToastQueue = function () {
- function ToastQueue() {
- classCallCheck(this, ToastQueue);
-
- this.queue = [];
- }
-
- createClass(ToastQueue, [{
- key: "add",
- value: function add(fn, promise) {
- var _this = this;
-
- this.queue.push(fn);
-
- if (this.queue.length === 1) {
- setImmediate(this.queue[0]);
- }
-
- promise.then(function () {
- _this.queue.shift();
-
- if (_this.queue.length > 0) {
- setTimeout(_this.queue[0], 1000 / 30); // Apply some visual delay
- }
- });
- }
- }]);
- return ToastQueue;
- }();
-
- var ToastQueue$1 = new ToastQueue();
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var _setAttributes = function _setAttributes(element, options) {
- ['id', 'class', 'animation'].forEach(function (a) {
- return options.hasOwnProperty(a) && element.setAttribute(a, options[a]);
- });
-
- if (options.modifier) {
- util$1.addModifier(element, options.modifier);
- }
- };
-
- var _normalizeArguments = function _normalizeArguments(message) {
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
- var defaults$$1 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
-
- options = _extends({}, options);
- typeof message === 'string' ? options.message = message : options = message;
- if (!options || !options.message && !options.messageHTML) {
- util$1.throw('Notifications must contain a message');
- }
-
- if (options.hasOwnProperty('buttonLabels') || options.hasOwnProperty('buttonLabel')) {
- options.buttonLabels = options.buttonLabels || options.buttonLabel;
- if (!Array.isArray(options.buttonLabels)) {
- options.buttonLabels = [options.buttonLabels || ''];
- }
- }
-
- return util$1.extend({
- compile: function compile(param) {
- return param;
- },
- callback: function callback(param) {
- return param;
- },
- animation: 'default',
- cancelable: false,
- primaryButtonIndex: (options.buttonLabels || defaults$$1.buttonLabels || []).length - 1
- }, defaults$$1, options);
- };
-
- /**
- * @object ons.notification
- * @category dialog
- * @tutorial vanilla/Reference/notification
- * @description
- * [en]
- * Utility methods to create different kinds of notifications. There are three methods available:
- *
- * * `ons.notification.alert()`
- * * `ons.notification.confirm()`
- * * `ons.notification.prompt()`
- * * `ons.notification.toast()`
- *
- * It will automatically display a Material Design dialog on Android devices.
- * [/en]
- * [ja]いくつかの種類のアラートダイアログを作成するためのユーティリティメソッドを収めたオブジェクトです。[/ja]
- * @example
- * ons.notification.alert('Hello, world!');
- *
- * ons.notification.confirm('Are you ready?')
- * .then(
- * function(answer) {
- * if (answer === 1) {
- * ons.notification.alert('Let\'s go!');
- * }
- * }
- * );
- *
- * ons.notification.prompt('How old are ?')
- * .then(
- * function(age) {
- * ons.notification.alert('You are ' + age + ' years old.');
- * }
- * );
- */
- var notification = {};
-
- notification._createAlertDialog = function () {
- for (var _len = arguments.length, params = Array(_len), _key = 0; _key < _len; _key++) {
- params[_key] = arguments[_key];
- }
-
- return new Promise(function (resolve) {
- var options = _normalizeArguments.apply(undefined, params);
- util$1.checkMissingImport('AlertDialog', 'AlertDialogButton');
-
- // Prompt input string
- var inputString = '';
- if (options.isPrompt) {
- inputString = '\n <input\n class="text-input text-input--underbar"\n type="' + (options.inputType || 'text') + '"\n placeholder="' + (options.placeholder || '') + '"\n value="' + (options.defaultValue || '') + '"\n style="width: 100%; margin-top: 10px;"\n />\n ';
- }
-
- // Buttons string
- var buttons = '';
- options.buttonLabels.forEach(function (label, index) {
- buttons += '\n <ons-alert-dialog-button\n class="\n ' + (index === options.primaryButtonIndex ? ' alert-dialog-button--primal' : '') + '\n ' + (options.buttonLabels.length <= 2 ? ' alert-dialog-button--rowfooter' : '') + '\n "\n style="position: relative;">\n ' + label + '\n </ons-alert-dialog-button>\n ';
- });
-
- // Dialog Element
- var el = {};
- var _destroyDialog = function _destroyDialog() {
- if (el.dialog.onDialogCancel) {
- el.dialog.removeEventListener('dialog-cancel', el.dialog.onDialogCancel);
- }
-
- Object.keys(el).forEach(function (key) {
- return delete el[key];
- });
- el = null;
-
- if (options.destroy instanceof Function) {
- options.destroy();
- }
- };
-
- el.dialog = document.createElement('ons-alert-dialog');
- el.dialog.innerHTML = '\n <div class="alert-dialog-mask"\n style="\n ' + (options.maskColor ? 'background-color: ' + options.maskColor : '') + '\n "></div>\n <div class="alert-dialog">\n <div class="alert-dialog-container">\n <div class="alert-dialog-title">\n ' + (options.title || '') + '\n </div>\n <div class="alert-dialog-content">\n ' + (options.message || options.messageHTML) + '\n ' + inputString + '\n </div>\n <div class="\n alert-dialog-footer\n ' + (options.buttonLabels.length <= 2 ? ' alert-dialog-footer--rowfooter' : '') + '\n ">\n ' + buttons + '\n </div>\n </div>\n </div>\n ';
- contentReady(el.dialog);
-
- // Set attributes
- _setAttributes(el.dialog, options);
-
- // Prompt events
- if (options.isPrompt && options.submitOnEnter) {
- el.input = el.dialog.querySelector('.text-input');
- el.input.onkeypress = function (event) {
- if (event.keyCode === 13) {
- el.dialog.hide().then(function () {
- if (el) {
- var resolveValue = el.input.value;
- _destroyDialog();
- options.callback(resolveValue);
- resolve(resolveValue);
- }
- });
- }
- };
- }
-
- // Button events
- el.footer = el.dialog.querySelector('.alert-dialog-footer');
- util$1.arrayFrom(el.dialog.querySelectorAll('.alert-dialog-button')).forEach(function (buttonElement, index) {
- buttonElement.onclick = function () {
- el.dialog.hide().then(function () {
- if (el) {
- var resolveValue = index;
- if (options.isPrompt) {
- resolveValue = index === options.primaryButtonIndex ? el.input.value : null;
- }
- el.dialog.remove();
- _destroyDialog();
- options.callback(resolveValue);
- resolve(resolveValue);
- }
- });
- };
-
- el.footer.appendChild(buttonElement);
- });
-
- // Cancel events
- if (options.cancelable) {
- el.dialog.cancelable = true;
- el.dialog.onDialogCancel = function () {
- setImmediate(function () {
- el.dialog.remove();
- _destroyDialog();
- });
- var resolveValue = options.isPrompt ? null : -1;
- options.callback(resolveValue);
- resolve(resolveValue);
- };
- el.dialog.addEventListener('dialog-cancel', el.dialog.onDialogCancel, false);
- }
-
- // Show dialog
- document.body.appendChild(el.dialog);
- options.compile(el.dialog);
- setImmediate(function () {
- el.dialog.show().then(function () {
- if (el.input && options.isPrompt && options.autofocus) {
- var strLength = el.input.value.length;
- el.input.focus();
- el.input.setSelectionRange(strLength, strLength);
- }
- });
- });
- });
- };
-
- /**
- * @method alert
- * @signature alert(message [, options] | options)
- * @return {Promise}
- * [en]Will resolve to the index of the button that was pressed or `-1` when canceled.[/en]
- * [ja][/ja]
- * @param {String} message
- * [en]Notification message. This argument is optional but if it's not defined either `options.message` or `options.messageHTML` must be defined instead.[/en]
- * [ja][/ja]
- * @param {Object} options
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクトです。[/ja]
- * @param {String} [options.message]
- * [en]Notification message.[/en]
- * [ja]アラートダイアログに表示する文字列を指定します。[/ja]
- * @param {String} [options.messageHTML]
- * [en]Notification message in HTML.[/en]
- * [ja]アラートダイアログに表示するHTMLを指定します。[/ja]
- * @param {String | Array} [options.buttonLabels]
- * [en]Labels for the buttons. Default is `"OK"`.[/en]
- * [ja]確認ボタンのラベルを指定します。"OK"がデフォルトです。[/ja]
- * @param {Number} [options.primaryButtonIndex]
- * [en]Index of primary button. Default is the last one.[/en]
- * [ja]プライマリボタンのインデックスを指定します。デフォルトは 0 です。[/ja]
- * @param {Boolean} [options.cancelable]
- * [en]Whether the dialog is cancelable or not. Default is `false`. If the dialog is cancelable it can be closed by clicking the background or pressing the Android back button.[/en]
- * [ja]ダイアログがキャンセル可能かどうかを指定します。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Available animations are `none` and `fade`. Default is `fade`.[/en]
- * [ja]アラートダイアログを表示する際のアニメーション名を指定します。"none", "fade"のいずれかを指定できます。[/ja]
- * @param {String} [options.id]
- * [en]The `<ons-alert-dialog>` element's ID.[/en]
- * [ja]ons-alert-dialog要素のID。[/ja]
- * @param {String} [options.class]
- * [en]The `<ons-alert-dialog>` element's class.[/en]
- * [ja]ons-alert-dialog要素のclass。[/ja]
- * @param {String} [options.title]
- * [en]Dialog title. Default is `"Alert"`.[/en]
- * [ja]アラートダイアログの上部に表示するタイトルを指定します。"Alert"がデフォルトです。[/ja]
- * @param {String} [options.modifier]
- * [en]Modifier for the dialog.[/en]
- * [ja]アラートダイアログのmodifier属性の値を指定します。[/ja]
- * @param {String} [options.maskColor]
- * [en]Color of the background mask. Default is "rgba(0, 0, 0, 0.2)" ("rgba(0, 0, 0, 0.3)" for Material).[/en]
- * [ja]背景のマスクの色を指定します。"rgba(0, 0, 0, 0.2)"がデフォルト値です。[/ja]
- * @param {Function} [options.callback]
- * [en]Function that executes after dialog has been closed.[/en]
- * [ja]アラートダイアログが閉じられた時に呼び出される関数オブジェクトを指定します。[/ja]
- * @description
- * [en]
- * Display an alert dialog to show the user a message.
- *
- * The content of the message can be either simple text or HTML.
- *
- * It can be called in the following ways:
- *
- * ```
- * ons.notification.alert(message, options);
- * ons.notification.alert(options);
- * ```
- *
- * Must specify either `message` or `messageHTML`.
- * [/en]
- * [ja]
- * ユーザーへメッセージを見せるためのアラートダイアログを表示します。
- * 表示するメッセージは、テキストかもしくはHTMLを指定できます。
- * このメソッドの引数には、options.messageもしくはoptions.messageHTMLのどちらかを必ず指定する必要があります。
- * [/ja]
- */
- notification.alert = function (message, options) {
- return notification._createAlertDialog(message, options, {
- buttonLabels: ['OK'],
- title: 'Alert'
- });
- };
-
- /**
- * @method confirm
- * @signature confirm(message [, options] | options)
- * @return {Promise}
- * [en]Will resolve to the index of the button that was pressed or `-1` when canceled.[/en]
- * [ja][/ja]
- * @param {String} message
- * [en]Notification message. This argument is optional but if it's not defined either `options.message` or `options.messageHTML` must be defined instead.[/en]
- * [ja][/ja]
- * @param {Object} options
- * [en]Parameter object.[/en]
- * @param {Array} [options.buttonLabels]
- * [en]Labels for the buttons. Default is `["Cancel", "OK"]`.[/en]
- * [ja]ボタンのラベルの配列を指定します。["Cancel", "OK"]がデフォルトです。[/ja]
- * @param {Number} [options.primaryButtonIndex]
- * [en]Index of primary button. Default is the last one.[/en]
- * [ja]プライマリボタンのインデックスを指定します。デフォルトは 1 です。[/ja]
- * @description
- * [en]
- * Display a dialog to ask the user for confirmation. Extends `alert()` parameters.
- * The default button labels are `"Cancel"` and `"OK"` but they can be customized.
- *
- * It can be called in the following ways:
- *
- * ```
- * ons.notification.confirm(message, options);
- * ons.notification.confirm(options);
- * ```
- *
- * Must specify either `message` or `messageHTML`.
- * [/en]
- * [ja]
- * ユーザに確認を促すダイアログを表示します。
- * デオルとのボタンラベルは、"Cancel"と"OK"ですが、これはこのメソッドの引数でカスタマイズできます。
- * このメソッドの引数には、options.messageもしくはoptions.messageHTMLのどちらかを必ず指定する必要があります。
- * [/ja]
- */
- notification.confirm = function (message, options) {
- return notification._createAlertDialog(message, options, {
- buttonLabels: ['Cancel', 'OK'],
- title: 'Confirm'
- });
- };
-
- /**
- * @method prompt
- * @signature prompt(message [, options] | options)
- * @param {String} message
- * [en]Notification message. This argument is optional but if it's not defined either `options.message` or `options.messageHTML` must be defined instead.[/en]
- * [ja][/ja]
- * @return {Promise}
- * [en]Will resolve to the input value when the dialog is closed or `null` when canceled.[/en]
- * [ja][/ja]
- * @param {Object} options
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクトです。[/ja]
- * @param {String | Array} [options.buttonLabels]
- * [en]Labels for the buttons. Default is `"OK"`.[/en]
- * [ja]確認ボタンのラベルを指定します。"OK"がデフォルトです。[/ja]
- * @param {Number} [options.primaryButtonIndex]
- * [en]Index of primary button. Default is the last one.[/en]
- * [ja]プライマリボタンのインデックスを指定します。デフォルトは 0 です。[/ja]
- * @param {String} [options.placeholder]
- * [en]Placeholder for the text input.[/en]
- * [ja]テキスト欄のプレースホルダに表示するテキストを指定します。[/ja]
- * @param {String} [options.defaultValue]
- * [en]Default value for the text input.[/en]
- * [ja]テキスト欄のデフォルトの値を指定します。[/ja]
- * @param {String} [options.inputType]
- * [en]Type of the input element (`password`, `date`...). Default is `text`.[/en]
- * [ja][/ja]
- * @param {Boolean} [options.autofocus]
- * [en]Autofocus the input element. Default is `true`. In Cordova, `KeyboardDisplayRequiresUserAction` in `config.xml` must be `false` to activate this feature.[/en]
- * [ja]input要素に自動的にフォーカスするかどうかを指定します。デフォルトはtrueです。Cordova環境では、この機能を有効にするためには `config.xml` で `KeyboardDisplayRequiresUserAction` を `false` に設定する必要があります。[/ja]
- * @param {Boolean} [options.submitOnEnter]
- * [en]Submit automatically when enter is pressed. Default is `true`.[/en]
- * [ja]Enterが押された際にそのformをsubmitするかどうかを指定します。デフォルトはtrueです。[/ja]
- * @description
- * [en]
- * Display a dialog with a prompt to ask the user a question. Extends `alert()` parameters.
- *
- * It can be called in the following ways:
- *
- * ```
- * ons.notification.prompt(message, options);
- * ons.notification.prompt(options);
- * ```
- *
- * Must specify either `message` or `messageHTML`.
- * [/en]
- * [ja]
- * ユーザーに入力を促すダイアログを表示します。
- * このメソッドの引数には、options.messageもしくはoptions.messageHTMLのどちらかを必ず指定する必要があります。
- * [/ja]
- */
- notification.prompt = function (message, options) {
- return notification._createAlertDialog(message, options, {
- buttonLabels: ['OK'],
- title: 'Alert',
- isPrompt: true,
- autofocus: true,
- submitOnEnter: true
- });
- };
-
- /**
- * @method toast
- * @signature toast(message [, options] | options)
- * @return {Promise}
- * [en]Will resolve when the toast is hidden.[/en]
- * [ja][/ja]
- * @param {String} message
- * [en]Toast message. This argument is optional but if it's not defined then `options.message` must be defined instead.[/en]
- * [ja][/ja]
- * @param {Object} options
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクトです。[/ja]
- * @param {String} [options.message]
- * [en]Notification message.[/en]
- * [ja]トーストに表示する文字列を指定します。[/ja]
- * @param {String} [options.buttonLabel]
- * [en]Label for the button.[/en]
- * [ja]確認ボタンのラベルを指定します。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Available animations are `none`, `fade`, `ascend`, `lift` and `fall`. Default is `ascend` for Android and `lift` for iOS.[/en]
- * [ja]トーストを表示する際のアニメーション名を指定します。"none", "fade", "ascend", "lift", "fall"のいずれかを指定できます。[/ja]
- * @param {Number} [options.timeout]
- * [en]Number of miliseconds where the toast is visible before hiding automatically.[/en]
- * [ja][/ja]
- * @param {Boolean} [options.force]
- * [en]If `true`, the toast skips the notification queue and is shown immediately. Defaults to `false`.[/en]
- * [ja][/ja]
- * @param {String} [options.id]
- * [en]The `<ons-toast>` element's ID.[/en]
- * [ja]ons-toast要素のID。[/ja]
- * @param {String} [options.class]
- * [en]The `<ons-toast>` element's class.[/en]
- * [ja]ons-toast要素のclass。[/ja]
- * @param {String} [options.modifier]
- * [en]Modifier for the element.[/en]
- * [ja]トーストのmodifier属性の値を指定します。[/ja]
- * @param {Function} [options.callback]
- * [en]Function that executes after toast has been hidden.[/en]
- * [ja]トーストが閉じられた時に呼び出される関数オブジェクトを指定します。[/ja]
- * @description
- * [en]
- * Display a simple notification toast with an optional button that can be used for simple actions.
- *
- * It can be called in the following ways:
- *
- * ```
- * ons.notification.toast(message, options);
- * ons.notification.toast(options);
- * ```
- * [/en]
- * [ja][/ja]
- */
- notification.toast = function (message, options) {
- var promise = new Promise(function (resolve) {
- util$1.checkMissingImport('Toast'); // Throws error, must be inside promise
-
- options = _normalizeArguments(message, options, {
- timeout: 0,
- force: false
- });
-
- var toast = util$1.createElement('\n <ons-toast>\n ' + options.message + '\n ' + (options.buttonLabels ? '<button>' + options.buttonLabels[0] + '</button>' : '') + '\n </ons-toast>\n ');
-
- _setAttributes(toast, options);
-
- var finish = function finish(value) {
- if (toast) {
- toast.hide().then(function () {
- if (toast) {
- toast.remove();
- toast = null;
- options.callback(value);
- resolve(value);
- }
- });
- }
- };
-
- if (options.buttonLabels) {
- util$1.findChild(toast._toast, 'button').onclick = function () {
- return finish(0);
- };
- }
-
- document.body.appendChild(toast);
- options.compile(toast);
-
- var show = function show() {
- toast.parentElement && toast.show(options).then(function () {
- if (options.timeout) {
- setTimeout(function () {
- return finish(-1);
- }, options.timeout);
- }
- });
- };
-
- setImmediate(function () {
- return options.force ? show() : ToastQueue$1.add(show, promise);
- });
- });
-
- return promise;
- };
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- // Validate parameters
- var checkOptions = function checkOptions(options) {
- var err = function err(prop) {
- var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Function';
- return util$1.throw('"options.' + prop + '" must be an instance of ' + type);
- };
- var hasOwnProperty = function hasOwnProperty(prop) {
- return Object.hasOwnProperty.call(options, prop);
- };
- var instanceOf = function instanceOf(prop) {
- var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Function;
- return options[prop] instanceof type;
- };
-
- var b = 'buttons',
- cb = 'callback',
- c = 'compile',
- d = 'destroy';
- (!hasOwnProperty(b) || !instanceOf(b, Array)) && err(b, 'Array');
- hasOwnProperty(cb) && !instanceOf(cb) && err(cb);
- hasOwnProperty(c) && !instanceOf(c) && err(c);
- hasOwnProperty(d) && !instanceOf(d) && err(d);
- };
-
- // Action Sheet
- var actionSheet = (function () {
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- return new Promise(function (resolve) {
- util$1.checkMissingImport('ActionSheet');
- checkOptions(options);
-
- // Main component
- var actionSheet = util$1.createElement('\n <ons-action-sheet\n ' + (options.title ? 'title="' + options.title + '"' : '') + '\n ' + (options.cancelable ? 'cancelable' : '') + '\n ' + (options.modifier ? 'modifier="' + options.modifier + '"' : '') + '\n ' + (options.maskColor ? 'mask-color="' + options.maskColor + '"' : '') + '\n ' + (options.id ? 'id="' + options.id + '"' : '') + '\n ' + (options.class ? 'class="' + options.class + '"' : '') + '\n >\n <div class="action-sheet"></div>\n </ons-action-sheet>\n ');
-
- // Resolve action and clean up
- var finish = function finish(event) {
- var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1;
-
- if (actionSheet) {
- options.destroy && options.destroy(actionSheet);
-
- actionSheet.removeEventListener('dialog-cancel', finish, false);
- actionSheet.remove();
- actionSheet = null;
-
- options.callback && options.callback(index);
- resolve(index);
- }
- };
-
- // Link cancel handler
- actionSheet.addEventListener('dialog-cancel', finish, false);
-
- // Create buttons and link action handler
- var buttons = document.createDocumentFragment();
- options.buttons.forEach(function (item, index) {
- var buttonOptions = typeof item === 'string' ? { label: item } : _extends({}, item);
- if (options.destructive === index) {
- buttonOptions.modifier = (buttonOptions.modifier || '') + ' destructive';
- }
-
- var button = util$1.createElement('\n <ons-action-sheet-button\n ' + (buttonOptions.icon ? 'icon="' + buttonOptions.icon + '"' : '') + '\n ' + (buttonOptions.modifier ? 'modifier="' + buttonOptions.modifier + '"' : '') + '\n >\n ' + buttonOptions.label + '\n </ons-action-sheet-button>\n ');
-
- button.onclick = function (event) {
- return actionSheet.hide().then(function () {
- return finish(event, index);
- });
- };
- buttons.appendChild(button);
- });
-
- // Finish component and attach
- util$1.findChild(actionSheet, '.action-sheet').appendChild(buttons);
- document.body.appendChild(actionSheet);
- options.compile && options.compile(el.dialog);
-
- // Show
- setImmediate(function () {
- return actionSheet.show({
- animation: options.animation,
- animationOptions: options.animationOptions
- });
- });
- });
- });
-
- /**
- * MicroEvent - to make any js object an event emitter (server or browser)
- *
- * - pure javascript - server compatible, browser compatible
- * - dont rely on the browser doms
- * - super simple - you get it immediately, no mystery, no magic involved
- *
- * - create a MicroEventDebug with goodies to debug
- * - make it safer to use
- */
-
- /** NOTE: This library is customized for Onsen UI. */
-
- var MicroEvent = function MicroEvent() {};
- MicroEvent.prototype = {
- on: function on(event, fct) {
- this._events = this._events || {};
- this._events[event] = this._events[event] || [];
- this._events[event].push(fct);
- },
- once: function once(event, fct) {
- var self = this;
- var wrapper = function wrapper() {
- self.off(event, wrapper);
- return fct.apply(null, arguments);
- };
- this.on(event, wrapper);
- },
- off: function off(event, fct) {
- this._events = this._events || {};
- if (event in this._events === false) {
- return;
- }
-
- this._events[event] = this._events[event].filter(function (_fct) {
- if (fct) {
- return fct !== _fct;
- } else {
- return false;
- }
- });
- },
- emit: function emit(event /* , args... */) {
- this._events = this._events || {};
- if (event in this._events === false) {
- return;
- }
- for (var i = 0; i < this._events[event].length; i++) {
- this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1));
- }
- }
- };
-
- /**
- * mixin will delegate all MicroEvent.js function in the destination object
- *
- * - require('MicroEvent').mixin(Foobar) will make Foobar able to use MicroEvent
- *
- * @param {Object} the object which will support MicroEvent
- */
- MicroEvent.mixin = function (destObject) {
- var props = ['on', 'once', 'off', 'emit'];
- for (var i = 0; i < props.length; i++) {
- if (typeof destObject === 'function') {
- destObject.prototype[props[i]] = MicroEvent.prototype[props[i]];
- } else {
- destObject[props[i]] = MicroEvent.prototype[props[i]];
- }
- }
- };
-
- window.MicroEvent = MicroEvent;
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var create = function create() {
-
- /**
- * @object ons.orientation
- * @category util
- * @description
- * [en]Utility methods for orientation detection.[/en]
- * [ja]画面のオリエンテーション検知のためのユーティリティメソッドを収めているオブジェクトです。[/ja]
- */
- var obj = {
- /**
- * @event change
- * @description
- * [en]Fired when the device orientation changes.[/en]
- * [ja]デバイスのオリエンテーションが変化した際に発火します。[/ja]
- * @param {Object} event
- * [en]Event object.[/en]
- * [ja]イベントオブジェクトです。[/ja]
- * @param {Boolean} event.isPortrait
- * [en]Will be true if the current orientation is portrait mode.[/en]
- * [ja]現在のオリエンテーションがportraitの場合にtrueを返します。[/ja]
- */
-
- /**
- * @method on
- * @signature on(eventName, listener)
- * @description
- * [en]Add an event listener.[/en]
- * [ja]イベントリスナーを追加します。[/ja]
- * @param {String} eventName
- * [en]Name of the event.[/en]
- * [ja]イベント名を指定します。[/ja]
- * @param {Function} listener
- * [en]Function to execute when the event is triggered.[/en]
- * [ja]このイベントが発火された際に呼び出される関数オブジェクトを指定します。[/ja]
- */
-
- /**
- * @method once
- * @signature once(eventName, listener)
- * @description
- * [en]Add an event listener that's only triggered once.[/en]
- * [ja]一度だけ呼び出されるイベントリスナーを追加します。[/ja]
- * @param {String} eventName
- * [en]Name of the event.[/en]
- * [ja]イベント名を指定します。[/ja]
- * @param {Function} listener
- * [en]Function to execute when the event is triggered.[/en]
- * [ja]イベントが発火した際に呼び出される関数オブジェクトを指定します。[/ja]
- */
-
- /**
- * @method off
- * @signature off(eventName, [listener])
- * @description
- * [en]Remove an event listener. If the listener is not specified all listeners for the event type will be removed.[/en]
- * [ja]イベントリスナーを削除します。もしイベントリスナーを指定しなかった場合には、そのイベントに紐づく全てのイベントリスナーが削除されます。[/ja]
- * @param {String} eventName
- * [en]Name of the event.[/en]
- * [ja]イベント名を指定します。[/ja]
- * @param {Function} listener
- * [en]Function to execute when the event is triggered.[/en]
- * [ja]削除するイベントリスナーを指定します。[/ja]
- */
-
- // actual implementation to detect if whether current screen is portrait or not
- _isPortrait: false,
-
- /**
- * @method isPortrait
- * @signature isPortrait()
- * @return {Boolean}
- * [en]Will be true if the current orientation is portrait mode.[/en]
- * [ja]オリエンテーションがportraitモードの場合にtrueになります。[/ja]
- * @description
- * [en]Returns whether the current screen orientation is portrait or not.[/en]
- * [ja]オリエンテーションがportraitモードかどうかを返します。[/ja]
- */
- isPortrait: function isPortrait() {
- return this._isPortrait();
- },
-
- /**
- * @method isLandscape
- * @signature isLandscape()
- * @return {Boolean}
- * [en]Will be true if the current orientation is landscape mode.[/en]
- * [ja]オリエンテーションがlandscapeモードの場合にtrueになります。[/ja]
- * @description
- * [en]Returns whether the current screen orientation is landscape or not.[/en]
- * [ja]オリエンテーションがlandscapeモードかどうかを返します。[/ja]
- */
- isLandscape: function isLandscape() {
- return !this.isPortrait();
- },
-
- _init: function _init() {
- document.addEventListener('DOMContentLoaded', this._onDOMContentLoaded.bind(this), false);
-
- if ('orientation' in window) {
- window.addEventListener('orientationchange', this._onOrientationChange.bind(this), false);
- } else {
- window.addEventListener('resize', this._onResize.bind(this), false);
- }
-
- this._isPortrait = function () {
- return window.innerHeight > window.innerWidth;
- };
-
- return this;
- },
-
- _onDOMContentLoaded: function _onDOMContentLoaded() {
- this._installIsPortraitImplementation();
- this.emit('change', { isPortrait: this.isPortrait() });
- },
-
- _installIsPortraitImplementation: function _installIsPortraitImplementation() {
- var isPortrait = window.innerWidth < window.innerHeight;
-
- if (!('orientation' in window)) {
- this._isPortrait = function () {
- return window.innerHeight > window.innerWidth;
- };
- } else if (window.orientation % 180 === 0) {
- this._isPortrait = function () {
- return Math.abs(window.orientation % 180) === 0 ? isPortrait : !isPortrait;
- };
- } else {
- this._isPortrait = function () {
- return Math.abs(window.orientation % 180) === 90 ? isPortrait : !isPortrait;
- };
- }
- },
-
- _onOrientationChange: function _onOrientationChange() {
- var _this = this;
-
- var isPortrait = this._isPortrait();
-
- // Wait for the dimensions to change because
- // of Android inconsistency.
- var nIter = 0;
- var interval = setInterval(function () {
- nIter++;
-
- var w = window.innerWidth;
- var h = window.innerHeight;
-
- if (isPortrait && w <= h || !isPortrait && w >= h) {
- _this.emit('change', { isPortrait: isPortrait });
- clearInterval(interval);
- } else if (nIter === 50) {
- _this.emit('change', { isPortrait: isPortrait });
- clearInterval(interval);
- }
- }, 20);
- },
-
- // Run on not mobile browser.
- _onResize: function _onResize() {
- this.emit('change', { isPortrait: this.isPortrait() });
- }
- };
-
- MicroEvent.mixin(obj);
-
- return obj;
- };
-
- var orientation = create()._init();
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * @object ons.modifier
- * @category visual
- * @description
- * [en]
- * Utility methods to change modifier attributes of Onsen UI elements..
- * [/en]
- * [ja][/ja]
- * @example
- * ons.modifier.add(myOnsInputElement, 'underbar');
- * ons.modifier.toggle(myOnsToastElement, 'custom-modifier');
- *
- */
- var modifier = {
- /**
- * @method add
- * @signature add(element, modifier [, modifier])
- * @description
- * [en]Add the specified modifiers to the element if they are not already included.[/en]
- * [ja][/ja]
- * @param {HTMLElement} element
- * [en]Target element.[/en]
- * [ja][/ja]
- * @param {String} modifier
- * [en]Name of the modifier.[/en]
- * [ja][/ja]
- */
- add: function add(element) {
- for (var _len = arguments.length, modifiers = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
- modifiers[_key - 1] = arguments[_key];
- }
-
- return modifiers.forEach(function (modifier) {
- return util$1.addModifier(element, modifier);
- });
- },
- /**
- * @method remove
- * @signature remove(element, modifier [, modifier])
- * @description
- * [en]Remove the specified modifiers from the element if they are included.[/en]
- * [ja][/ja]
- * @param {HTMLElement} element
- * [en]Target element.[/en]
- * [ja][/ja]
- * @param {String} modifier
- * [en]Name of the modifier.[/en]
- * [ja][/ja]
- */
- remove: function remove(element) {
- for (var _len2 = arguments.length, modifiers = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
- modifiers[_key2 - 1] = arguments[_key2];
- }
-
- return modifiers.forEach(function (modifier) {
- return util$1.removeModifier(element, modifier);
- });
- },
- /**
- * @method contains
- * @signature contains(element, modifier)
- * @description
- * [en]Check whether the specified modifier is included in the element.[/en]
- * [ja][/ja]
- * @param {HTMLElement} element
- * [en]Target element.[/en]
- * [ja][/ja]
- * @param {String} modifier
- * [en]Name of the modifier.[/en]
- * [ja][/ja]
- * @return {Boolean}
- * [en]`true` when the specified modifier is found in the element's `modifier` attribute. `false` otherwise.[/en]
- * [ja][/ja]
- */
- contains: util$1.hasModifier,
- /**
- * @method toggle
- * @signature toggle(element, modifier [, force])
- * @description
- * [en]Toggle the specified modifier.[/en]
- * [ja][/ja]
- * @param {HTMLElement} element
- * [en]Target element.[/en]
- * [ja][/ja]
- * @param {String} modifier
- * [en]Name of the modifier.[/en]
- * [ja][/ja]
- * @param {String} force
- * [en]If it evaluates to true, add specified modifier value, and if it evaluates to false, remove it.[/en]
- * [ja][/ja]
- */
- toggle: util$1.toggleModifier
- };
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var softwareKeyboard = new MicroEvent();
- softwareKeyboard._visible = false;
-
- var onShow = function onShow() {
- softwareKeyboard._visible = true;
- softwareKeyboard.emit('show');
- };
-
- var onHide = function onHide() {
- softwareKeyboard._visible = false;
- softwareKeyboard.emit('hide');
- };
-
- var bindEvents = function bindEvents() {
- if (typeof Keyboard !== 'undefined') {
- // https://github.com/martinmose/cordova-keyboard/blob/95f3da3a38d8f8e1fa41fbf40145352c13535a00/README.md
- Keyboard.onshow = onShow;
- Keyboard.onhide = onHide;
- softwareKeyboard.emit('init', { visible: Keyboard.isVisible });
-
- return true;
- } else if (typeof cordova.plugins !== 'undefined' && typeof cordova.plugins.Keyboard !== 'undefined') {
- // https://github.com/driftyco/ionic-plugins-keyboard/blob/ca27ecf/README.md
- window.addEventListener('native.keyboardshow', onShow);
- window.addEventListener('native.keyboardhide', onHide);
- softwareKeyboard.emit('init', { visible: cordova.plugins.Keyboard.isVisible });
-
- return true;
- }
-
- return false;
- };
-
- var noPluginError = function noPluginError() {
- util$1.warn('ons-keyboard: Cordova Keyboard plugin is not present.');
- };
-
- document.addEventListener('deviceready', function () {
- if (!bindEvents()) {
- if (document.querySelector('[ons-keyboard-active]') || document.querySelector('[ons-keyboard-inactive]')) {
- noPluginError();
- }
-
- softwareKeyboard.on = noPluginError;
- }
- });
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var generateId = function () {
- var i = 0;
- return function () {
- return i++;
- };
- }();
-
- /**
- * Door locking system.
- *
- * @param {Object} [options]
- * @param {Function} [options.log]
- */
-
- var DoorLock = function () {
- function DoorLock() {
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- classCallCheck(this, DoorLock);
-
- this._lockList = [];
- this._waitList = [];
- this._log = options.log || function () {};
- }
-
- /**
- * Register a lock.
- *
- * @return {Function} Callback for unlocking.
- */
-
-
- createClass(DoorLock, [{
- key: 'lock',
- value: function lock() {
- var _this = this;
-
- var unlock = function unlock() {
- _this._unlock(unlock);
- };
- unlock.id = generateId();
- this._lockList.push(unlock);
- this._log('lock: ' + unlock.id);
-
- return unlock;
- }
- }, {
- key: '_unlock',
- value: function _unlock(fn) {
- var index = this._lockList.indexOf(fn);
- if (index === -1) {
- throw new Error('This function is not registered in the lock list.');
- }
-
- this._lockList.splice(index, 1);
- this._log('unlock: ' + fn.id);
-
- this._tryToFreeWaitList();
- }
- }, {
- key: '_tryToFreeWaitList',
- value: function _tryToFreeWaitList() {
- while (!this.isLocked() && this._waitList.length > 0) {
- this._waitList.shift()();
- }
- }
-
- /**
- * Register a callback for waiting unlocked door.
- *
- * @params {Function} callback Callback on unlocking the door completely.
- */
-
- }, {
- key: 'waitUnlock',
- value: function waitUnlock(callback) {
- if (!(callback instanceof Function)) {
- throw new Error('The callback param must be a function.');
- }
-
- if (this.isLocked()) {
- this._waitList.push(callback);
- } else {
- callback();
- }
- }
-
- /**
- * @return {Boolean}
- */
-
- }, {
- key: 'isLocked',
- value: function isLocked() {
- return this._lockList.length > 0;
- }
- }]);
- return DoorLock;
- }();
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
- // Default implementation for global PageLoader.
- function loadPage(_ref, done) {
- var page = _ref.page,
- parent = _ref.parent,
- _ref$params = _ref.params;
-
- internal$1.getPageHTMLAsync(page).then(function (html) {
- var pageElement = util$1.createElement(html);
- parent.appendChild(pageElement);
-
- done(pageElement);
- });
- }
-
- function unloadPage(element) {
- if (element._destroy instanceof Function) {
- element._destroy();
- } else {
- element.remove();
- }
- }
-
- var PageLoader = function () {
- /**
- * @param {Function} [fn] Returns an object that has "element" property and "unload" function.
- */
- function PageLoader(loader, unloader) {
- classCallCheck(this, PageLoader);
-
- this._loader = loader instanceof Function ? loader : loadPage;
- this._unloader = unloader instanceof Function ? unloader : unloadPage;
- }
-
- /**
- * Set internal loader implementation.
- */
-
-
- createClass(PageLoader, [{
- key: 'load',
-
-
- /**
- * @param {any} options.page
- * @param {Element} options.parent A location to load page.
- * @param {Object} [options.params] Extra parameters for ons-page.
- * @param {Function} done Take an object that has "element" property and "unload" function.
- */
- value: function load(_ref2, done) {
- var page = _ref2.page,
- parent = _ref2.parent,
- _ref2$params = _ref2.params,
- params = _ref2$params === undefined ? {} : _ref2$params;
-
- this._loader({ page: page, parent: parent, params: params }, function (pageElement) {
- if (!(pageElement instanceof Element)) {
- throw Error('pageElement must be an instance of Element.');
- }
-
- done(pageElement);
- });
- }
- }, {
- key: 'unload',
- value: function unload(pageElement) {
- if (!(pageElement instanceof Element)) {
- throw Error('pageElement must be an instance of Element.');
- }
-
- this._unloader(pageElement);
- }
- }, {
- key: 'internalLoader',
- set: function set$$1(fn) {
- if (!(fn instanceof Function)) {
- throw Error('First parameter must be an instance of Function');
- }
- this._loader = fn;
- },
- get: function get$$1() {
- return this._loader;
- }
- }]);
- return PageLoader;
- }();
-
- var defaultPageLoader = new PageLoader();
-
- var instantPageLoader = new PageLoader(function (_ref3, done) {
- var page = _ref3.page,
- parent = _ref3.parent,
- _ref3$params = _ref3.params;
-
- var element = util$1.createElement(page.trim());
- parent.appendChild(element);
-
- done(element);
- }, unloadPage);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * @object ons
- * @category util
- * @description
- * [ja]Onsen UIで利用できるグローバルなオブジェクトです。[/ja]
- * [en]A global object that's used in Onsen UI. [/en]
- */
- var ons$1 = {
- animit: Animit,
- defaultPageLoader: defaultPageLoader,
- elements: onsElements,
- GestureDetector: GestureDetector,
- modifier: modifier,
- notification: notification,
- orientation: orientation,
- pageAttributeExpression: pageAttributeExpression,
- PageLoader: PageLoader,
- platform: platform,
- softwareKeyboard: softwareKeyboard,
- _autoStyle: autoStyle,
- _internal: internal$1,
- _readyLock: new DoorLock(),
- _util: util$1
- };
-
- ons$1.platform.select((window.location.search.match(/platform=([\w-]+)/) || [])[1]);
-
- waitDeviceReady();
-
- var readyError = function readyError(after) {
- return util$1.throw('This method must be called ' + (after ? 'after' : 'before') + ' ons.isReady() is true');
- };
-
- /**
- * @method isReady
- * @signature isReady()
- * @return {Boolean}
- * [en]Will be true if Onsen UI is initialized.[/en]
- * [ja]初期化されているかどうかを返します。[/ja]
- * @description
- * [en]Returns true if Onsen UI is initialized.[/en]
- * [ja]Onsen UIがすでに初期化されているかどうかを返すメソッドです。[/ja]
- */
- ons$1.isReady = function () {
- return !ons$1._readyLock.isLocked();
- };
-
- /**
- * @method isWebView
- * @signature isWebView()
- * @return {Boolean}
- * [en]Will be true if the app is running in Cordova.[/en]
- * [ja]Cordovaで実行されている場合にtrueになります。[/ja]
- * @description
- * [en]Returns true if running inside Cordova.[/en]
- * [ja]Cordovaで実行されているかどうかを返すメソッドです。[/ja]
- */
- ons$1.isWebView = ons$1.platform.isWebView;
-
- /**
- * @method ready
- * @signature ready(callback)
- * @description
- * [ja]アプリの初期化に利用するメソッドです。渡された関数は、Onsen UIの初期化が終了している時点で必ず呼ばれます。[/ja]
- * [en]Method used to wait for app initialization. Waits for `DOMContentLoaded` and `deviceready`, when necessary, before executing the callback.[/en]
- * @param {Function} callback
- * [en]Function that executes after Onsen UI has been initialized.[/en]
- * [ja]Onsen UIが初期化が完了した後に呼び出される関数オブジェクトを指定します。[/ja]
- */
- ons$1.ready = function (callback) {
- if (ons$1.isReady()) {
- callback();
- } else {
- ons$1._readyLock.waitUnlock(callback);
- }
- };
-
- /**
- * @method setDefaultDeviceBackButtonListener
- * @signature setDefaultDeviceBackButtonListener(listener)
- * @param {Function} listener
- * [en]Function that executes when device back button is pressed. Must be called on `ons.ready`.[/en]
- * [ja]デバイスのバックボタンが押された時に実行される関数オブジェクトを指定します。[/ja]
- * @description
- * [en]Set default handler for device back button.[/en]
- * [ja]デバイスのバックボタンのためのデフォルトのハンドラを設定します。[/ja]
- */
- ons$1.setDefaultDeviceBackButtonListener = function (listener) {
- if (!ons$1.isReady()) {
- readyError(true);
- }
- ons$1._defaultDeviceBackButtonHandler.setListener(listener);
- };
-
- /**
- * @method disableDeviceBackButtonHandler
- * @signature disableDeviceBackButtonHandler()
- * @description
- * [en]Disable device back button event handler. Must be called on `ons.ready`.[/en]
- * [ja]デバイスのバックボタンのイベントを受け付けないようにします。[/ja]
- */
- ons$1.disableDeviceBackButtonHandler = function () {
- if (!ons$1.isReady()) {
- readyError(true);
- }
- internal$1.dbbDispatcher.disable();
- };
-
- /**
- * @method enableDeviceBackButtonHandler
- * @signature enableDeviceBackButtonHandler()
- * @description
- * [en]Enable device back button event handler. Must be called on `ons.ready`.[/en]
- * [ja]デバイスのバックボタンのイベントを受け付けるようにします。[/ja]
- */
- ons$1.enableDeviceBackButtonHandler = function () {
- if (!ons$1.isReady()) {
- readyError(true);
- }
- internal$1.dbbDispatcher.enable();
- };
-
- ons$1.fireDeviceBackButtonEvent = function () {
- internal$1.dbbDispatcher.fireDeviceBackButtonEvent();
- };
-
- /**
- * @method enableAutoStatusBarFill
- * @signature enableAutoStatusBarFill()
- * @description
- * [en]Enable status bar fill feature on iOS7 and above (except for iPhone X). Must be called before `ons.ready`.[/en]
- * [ja]iOS7以上(iPhone Xは除く)で、ステータスバー部分の高さを自動的に埋める処理を有効にします。[/ja]
- */
- ons$1.enableAutoStatusBarFill = function () {
- if (ons$1.isReady()) {
- readyError(false);
- }
- internal$1.config.autoStatusBarFill = true;
- };
-
- /**
- * @method disableAutoStatusBarFill
- * @signature disableAutoStatusBarFill()
- * @description
- * [en]Disable status bar fill feature on iOS7 and above (except for iPhone X). Must be called before `ons.ready`.[/en]
- * [ja]iOS7以上(iPhone Xは除く)で、ステータスバー部分の高さを自動的に埋める処理を無効にします。[/ja]
- */
- ons$1.disableAutoStatusBarFill = function () {
- if (ons$1.isReady()) {
- readyError(false);
- }
- internal$1.config.autoStatusBarFill = false;
- };
-
- /**
- * @method mockStatusBar
- * @signature mockStatusBar()
- * @description
- * [en]Creates a static element similar to iOS status bar. Only useful for browser testing. Must be called before `ons.ready`.[/en]
- * [ja][/ja]
- */
- ons$1.mockStatusBar = function () {
- if (ons$1.isReady()) {
- readyError(false);
- }
-
- var mock = function mock() {
- if (!document.body.children[0] || !document.body.children[0].classList.contains('ons-status-bar-mock')) {
- var android = platform.isAndroid(),
- i = function i(_i) {
- return '<i class="' + _i.split('-')[0] + ' ' + _i + '"></i>';
- };
- var left = android ? i('zmdi-twitter') + ' ' + i('zmdi-google-play') : 'No SIM ' + i('fa-wifi'),
- center = android ? '' : '12:28 PM',
- right = android ? i('zmdi-network') + ' ' + i('zmdi-wifi') + ' ' + i('zmdi-battery') + ' 12:28 PM' : '80% ' + i('fa-battery-three-quarters');
-
- document.body.insertBefore(util$1.createElement('<div class="ons-status-bar-mock ' + (android ? 'android' : 'ios') + '">' + ('<div>' + left + '</div><div>' + center + '</div><div>' + right + '</div>') + '</div>'), document.body.firstChild);
- }
- };
-
- document.body ? mock() : internal$1.waitDOMContentLoaded(mock);
- };
-
- /**
- * @method disableAnimations
- * @signature disableAnimations()
- * @description
- * [en]Disable all animations. Could be handy for testing and older devices.[/en]
- * [ja]アニメーションを全て無効にします。テストの際に便利です。[/ja]
- */
- ons$1.disableAnimations = function () {
- internal$1.config.animationsDisabled = true;
- };
-
- /**
- * @method enableAnimations
- * @signature enableAnimations()
- * @description
- * [en]Enable animations (default).[/en]
- * [ja]アニメーションを有効にします。[/ja]
- */
- ons$1.enableAnimations = function () {
- internal$1.config.animationsDisabled = false;
- };
-
- ons$1._disableWarnings = function () {
- internal$1.config.warningsDisabled = true;
- };
-
- ons$1._enableWarnings = function () {
- internal$1.config.warningsDisabled = false;
- };
-
- /**
- * @method disableAutoStyling
- * @signature disableAutoStyling()
- * @description
- * [en]Disable automatic styling.[/en]
- * [ja][/ja]
- */
- ons$1.disableAutoStyling = autoStyle.disable;
-
- /**
- * @method enableAutoStyling
- * @signature enableAutoStyling()
- * @description
- * [en]Enable automatic styling based on OS (default).[/en]
- * [ja][/ja]
- */
- ons$1.enableAutoStyling = autoStyle.enable;
-
- /**
- * @method disableIconAutoPrefix
- * @signature disableIconAutoPrefix()
- * @description
- * [en]Disable adding `fa-` prefix automatically to `ons-icon` classes. Useful when including custom icon packs.[/en]
- * [ja][/ja]
- */
- ons$1.disableIconAutoPrefix = function () {
- util$1.checkMissingImport('Icon');
- onsElements.Icon.setAutoPrefix(false);
- };
-
- /**
- * @method forceUIWebViewScrollFix
- * @signature forceUIWebViewScrollFix()
- * @param {Boolean} force Enable or disable the fix.
- * @description
- * [en]Applies a fix for iOS UIWebView which prevents scroll events jumping to pages under the top layer. This may visually affect normal scrolling of UIWebView if you open a dialog/menu before the scroll momentum finished. Disabled by default.[/en]
- * [ja][/ja]
- */
- ons$1.forceUIWebViewScrollFix = function () {
- var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
-
- internal$1.config.forceUIWebViewScrollFix = force;
- };
-
- /**
- * @method forcePlatformStyling
- * @signature forcePlatformStyling(platform)
- * @description
- * [en]Refresh styling for the given platform. Only useful for demos. Use `ons.platform.select(...)` instead for development and production.[/en]
- * [ja][/ja]
- * @param {string} platform New platform to style the elements.
- */
- ons$1.forcePlatformStyling = function (newPlatform) {
- ons$1.enableAutoStyling();
- ons$1.platform.select(newPlatform || 'ios');
-
- ons$1._util.arrayFrom(document.querySelectorAll('*')).forEach(function (element) {
- if (element.tagName.toLowerCase() === 'ons-if') {
- element._platformUpdate();
- } else if (element.tagName.match(/^ons-/i)) {
- autoStyle.prepare(element, true);
- if (element.tagName.toLowerCase() === 'ons-tabbar') {
- element._updatePosition();
- }
- }
- });
- };
-
- /**
- * @method preload
- * @signature preload(templatePaths)
- * @param {String|Array} templatePaths
- * [en]Set of HTML file paths containing 'ons-page' elements.[/en]
- * [ja][/ja]
- * @return {Promise}
- * [en]Promise that resolves when all the templates are cached.[/en]
- * [ja][/ja]
- * @description
- * [en]Separated files need to be requested on demand and this can slightly delay pushing new pages. This method requests and caches templates for later use.[/en]
- * [ja][/ja]
- */
- ons$1.preload = function () {
- var templates = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
-
- return Promise.all((templates instanceof Array ? templates : [templates]).map(function (template) {
- if (typeof template !== 'string') {
- util$1.throw('Expected string arguments but got ' + (typeof template === 'undefined' ? 'undefined' : _typeof(template)));
- }
- return internal$1.getTemplateHTMLAsync(template);
- }));
- };
-
- /**
- * @method createElement
- * @signature createElement(template, options)
- * @param {String} template
- * [en]Either an HTML file path, a `<template>` id or an HTML string such as `'<div id="foo">hoge</div>'`.[/en]
- * [ja][/ja]
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {Boolean|HTMLElement} [options.append]
- * [en]Whether or not the element should be automatically appended to the DOM. Defaults to `false`. If `true` value is given, `document.body` will be used as the target.[/en]
- * [ja][/ja]
- * @param {HTMLElement} [options.insertBefore]
- * [en]Reference node that becomes the next sibling of the new node (`options.append` element).[/en]
- * [ja][/ja]
- * @return {HTMLElement|Promise}
- * [en]If the provided template was an inline HTML string, it returns the new element. Otherwise, it returns a promise that resolves to the new element.[/en]
- * [ja][/ja]
- * @description
- * [en]Create a new element from a template. Both inline HTML and external files are supported although the return value differs.[/en]
- * [ja][/ja]
- */
- ons$1.createElement = function (template) {
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- template = template.trim();
-
- var create = function create(html) {
- var element = ons$1._util.createElement(html);
- element.remove();
-
- if (options.append) {
- var target = options.append instanceof HTMLElement ? options.append : document.body;
- target.insertBefore(element, options.insertBefore || null);
- options.link instanceof Function && options.link(element);
- }
-
- return element;
- };
-
- return template.charAt(0) === '<' ? create(template) : internal$1.getPageHTMLAsync(template).then(create);
- };
-
- /**
- * @method createPopover
- * @signature createPopover(page, [options])
- * @param {String} page
- * [en]Page name. Can be either an HTML file or a <template> containing a <ons-dialog> component.[/en]
- * [ja]pageのURLか、もしくは`<template>`で宣言したテンプレートのid属性の値を指定できます。[/ja]
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {Object} [options.parentScope]
- * [en]Parent scope of the dialog. Used to bind models and access scope methods from the dialog.[/en]
- * [ja]ダイアログ内で利用する親スコープを指定します。ダイアログからモデルやスコープのメソッドにアクセスするのに使います。このパラメータはAngularJSバインディングでのみ利用できます。[/ja]
- * @return {Promise}
- * [en]Promise object that resolves to the popover component object.[/en]
- * [ja]ポップオーバーのコンポーネントオブジェクトを解決するPromiseオブジェクトを返します。[/ja]
- * @description
- * [en]Create a popover instance from a template.[/en]
- * [ja]テンプレートからポップオーバーのインスタンスを生成します。[/ja]
- */
- /**
- * @method createDialog
- * @signature createDialog(page, [options])
- * @param {String} page
- * [en]Page name. Can be either an HTML file or an `<template>` containing a <ons-dialog> component.[/en]
- * [ja]pageのURLか、もしくは`<template>`で宣言したテンプレートのid属性の値を指定できます。[/ja]
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @return {Promise}
- * [en]Promise object that resolves to the dialog component object.[/en]
- * [ja]ダイアログのコンポーネントオブジェクトを解決するPromiseオブジェクトを返します。[/ja]
- * @description
- * [en]Create a dialog instance from a template.[/en]
- * [ja]テンプレートからダイアログのインスタンスを生成します。[/ja]
- */
- /**
- * @method createAlertDialog
- * @signature createAlertDialog(page, [options])
- * @param {String} page
- * [en]Page name. Can be either an HTML file or an `<template>` containing a <ons-alert-dialog> component.[/en]
- * [ja]pageのURLか、もしくは`<template>`で宣言したテンプレートのid属性の値を指定できます。[/ja]
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @return {Promise}
- * [en]Promise object that resolves to the alert dialog component object.[/en]
- * [ja]ダイアログのコンポーネントオブジェクトを解決するPromiseオブジェクトを返します。[/ja]
- * @description
- * [en]Create a alert dialog instance from a template.[/en]
- * [ja]テンプレートからアラートダイアログのインスタンスを生成します。[/ja]
- */
- ons$1.createPopover = ons$1.createDialog = ons$1.createAlertDialog = function (template) {
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
- return ons$1.createElement(template, _extends({ append: true }, options));
- };
-
- /**
- * @method openActionSheet
- * @signature openActionSheet(options)
- * @description
- * [en]Shows an instant Action Sheet and lets the user choose an action.[/en]
- * [ja][/ja]
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {Array} [options.buttons]
- * [en]Represent each button of the action sheet following the specified order. Every item can be either a string label or an object containing `label`, `icon` and `modifier` properties.[/en]
- * [ja][/ja]
- * @param {String} [options.title]
- * [en]Optional title for the action sheet.[/en]
- * [ja][/ja]
- * @param {Number} [options.destructive]
- * [en]Optional index of the "destructive" button (only for iOS). It can be specified in the button array as well.[/en]
- * [ja][/ja]
- * @param {Boolean} [options.cancelable]
- * [en]Whether the action sheet can be canceled by tapping on the background mask or not.[/en]
- * [ja][/ja]
- * @param {String} [options.modifier]
- * [en]Modifier attribute of the action sheet. E.g. `'destructive'`.[/en]
- * [ja][/ja]
- * @param {String} [options.maskColor]
- * [en]Optionally change the background mask color.[/en]
- * [ja][/ja]
- * @param {String} [options.id]
- * [en]The element's id attribute.[/en]
- * [ja][/ja]
- * @param {String} [options.class]
- * [en]The element's class attribute.[/en]
- * [ja][/ja]
- * @return {Promise}
- * [en]Will resolve when the action sheet is closed. The resolve value is either the index of the tapped button or -1 when canceled.[/en]
- * [ja][/ja]
- */
- ons$1.openActionSheet = actionSheet;
-
- /**
- * @method resolveLoadingPlaceholder
- * @signature resolveLoadingPlaceholder(page)
- * @param {String} page
- * [en]Page name. Can be either an HTML file or a `<template>` id.[/en]
- * [ja]pageのURLか、もしくは`<template>`で宣言したテンプレートのid属性の値を指定できます。[/ja]
- * @description
- * [en]If no page is defined for the `ons-loading-placeholder` attribute it will wait for this method being called before loading the page.[/en]
- * [ja]ons-loading-placeholderの属性値としてページが指定されていない場合は、ページロード前に呼ばれるons.resolveLoadingPlaceholder処理が行われるまで表示されません。[/ja]
- */
- ons$1.resolveLoadingPlaceholder = function (page, link) {
- var elements = ons$1._util.arrayFrom(window.document.querySelectorAll('[ons-loading-placeholder]'));
- if (elements.length === 0) {
- util$1.throw('No ons-loading-placeholder exists');
- }
-
- elements.filter(function (element) {
- return !element.getAttribute('page');
- }).forEach(function (element) {
- element.setAttribute('ons-loading-placeholder', page);
- ons$1._resolveLoadingPlaceholder(element, page, link);
- });
- };
-
- ons$1._setupLoadingPlaceHolders = function () {
- ons$1.ready(function () {
- var elements = ons$1._util.arrayFrom(window.document.querySelectorAll('[ons-loading-placeholder]'));
-
- elements.forEach(function (element) {
- var page = element.getAttribute('ons-loading-placeholder');
- if (typeof page === 'string') {
- ons$1._resolveLoadingPlaceholder(element, page);
- }
- });
- });
- };
-
- ons$1._resolveLoadingPlaceholder = function (parent, page) {
- var link = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function (el, done) {
- return done();
- };
-
- page && ons$1.createElement(page).then(function (element) {
- element.style.display = 'none';
- parent.appendChild(element);
- link(element, function () {
- while (parent.firstChild && parent.firstChild !== element) {
- parent.removeChild(parent.firstChild);
- }
- element.style.display = '';
- });
- }).catch(function (error) {
- return Promise.reject('Unabled to resolve placeholder: ' + error);
- });
- };
-
- function waitDeviceReady() {
- var unlockDeviceReady = ons$1._readyLock.lock();
- window.addEventListener('DOMContentLoaded', function () {
- if (ons$1.isWebView()) {
- window.document.addEventListener('deviceready', unlockDeviceReady, false);
- } else {
- unlockDeviceReady();
- }
- }, false);
- }
-
- /**
- * @method getScriptPage
- * @signature getScriptPage()
- * @description
- * [en]Access the last created page from the current `script` scope. Only works inside `<script></script>` tags that are direct children of `ons-page` element. Use this to add lifecycle hooks to a page.[/en]
- * [ja][/ja]
- * @return {HTMLElement}
- * [en]Returns the corresponding page element.[/en]
- * [ja][/ja]
- */
- var getCS = 'currentScript' in document ? function () {
- return document.currentScript;
- } : function () {
- return document.scripts[document.scripts.length - 1];
- };
- ons$1.getScriptPage = function () {
- return getCS() && /ons-page/i.test(getCS().parentElement.tagName) && getCS().parentElement || null;
- };
-
- function createCommonjsModule(fn, module) {
- return module = { exports: {} }, fn(module, module.exports), module.exports;
- }
-
- var fastclick = createCommonjsModule(function (module) {
- (function () {
- function FastClick(layer, options) {
- var oldOnClick;
-
- options = options || {};
-
- /**
- * Whether a click is currently being tracked.
- *
- * @type boolean
- */
- this.trackingClick = false;
-
- /**
- * Timestamp for when click tracking started.
- *
- * @type number
- */
- this.trackingClickStart = 0;
-
- /**
- * The element being tracked for a click.
- *
- * @type EventTarget
- */
- this.targetElement = null;
-
- /**
- * X-coordinate of touch start event.
- *
- * @type number
- */
- this.touchStartX = 0;
-
- /**
- * Y-coordinate of touch start event.
- *
- * @type number
- */
- this.touchStartY = 0;
-
- /**
- * ID of the last touch, retrieved from Touch.identifier.
- *
- * @type number
- */
- this.lastTouchIdentifier = 0;
-
- /**
- * Touchmove boundary, beyond which a click will be cancelled.
- *
- * @type number
- */
- this.touchBoundary = options.touchBoundary || 10;
-
- /**
- * The FastClick layer.
- *
- * @type Element
- */
- this.layer = layer;
-
- /**
- * The minimum time between tap(touchstart and touchend) events
- *
- * @type number
- */
- this.tapDelay = options.tapDelay || 200;
-
- /**
- * The maximum time for a tap
- *
- * @type number
- */
- this.tapTimeout = options.tapTimeout || 700;
-
- if (FastClick.notNeeded(layer)) {
- return;
- }
-
- // Some old versions of Android don't have Function.prototype.bind
- function bind(method, context) {
- return function () {
- return method.apply(context, arguments);
- };
- }
-
- var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'];
- var context = this;
- for (var i = 0, l = methods.length; i < l; i++) {
- context[methods[i]] = bind(context[methods[i]], context);
- }
-
- // Set up event handlers as required
- if (deviceIsAndroid) {
- layer.addEventListener('mouseover', this.onMouse, true);
- layer.addEventListener('mousedown', this.onMouse, true);
- layer.addEventListener('mouseup', this.onMouse, true);
- }
-
- layer.addEventListener('click', this.onClick, true);
- layer.addEventListener('touchstart', this.onTouchStart, false);
- layer.addEventListener('touchmove', this.onTouchMove, false);
- layer.addEventListener('touchend', this.onTouchEnd, false);
- layer.addEventListener('touchcancel', this.onTouchCancel, false);
-
- // Hack is required for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
- // which is how FastClick normally stops click events bubbling to callbacks registered on the FastClick
- // layer when they are cancelled.
- if (!Event.prototype.stopImmediatePropagation) {
- layer.removeEventListener = function (type, callback, capture) {
- var rmv = Node.prototype.removeEventListener;
- if (type === 'click') {
- rmv.call(layer, type, callback.hijacked || callback, capture);
- } else {
- rmv.call(layer, type, callback, capture);
- }
- };
-
- layer.addEventListener = function (type, callback, capture) {
- var adv = Node.prototype.addEventListener;
- if (type === 'click') {
- adv.call(layer, type, callback.hijacked || (callback.hijacked = function (event) {
- if (!event.propagationStopped) {
- callback(event);
- }
- }), capture);
- } else {
- adv.call(layer, type, callback, capture);
- }
- };
- }
-
- // If a handler is already declared in the element's onclick attribute, it will be fired before
- // FastClick's onClick handler. Fix this by pulling out the user-defined handler function and
- // adding it as listener.
- if (typeof layer.onclick === 'function') {
-
- // Android browser on at least 3.2 requires a new reference to the function in layer.onclick
- // - the old one won't work if passed to addEventListener directly.
- oldOnClick = layer.onclick;
- layer.addEventListener('click', function (event) {
- oldOnClick(event);
- }, false);
- layer.onclick = null;
- }
- }
-
- /**
- * Windows Phone 8.1 fakes user agent string to look like Android and iPhone.
- *
- * @type boolean
- */
- var deviceIsWindowsPhone = navigator.userAgent.indexOf("Windows Phone") >= 0;
-
- /**
- * Android requires exceptions.
- *
- * @type boolean
- */
- var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone;
-
- /**
- * iOS requires exceptions.
- *
- * @type boolean
- */
- var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone;
-
- /**
- * iOS 4 requires an exception for select elements.
- *
- * @type boolean
- */
- var deviceIsIOS4 = deviceIsIOS && /OS 4_\d(_\d)?/.test(navigator.userAgent);
-
- /**
- * iOS 6.0-7.* requires the target element to be manually derived
- *
- * @type boolean
- */
- var deviceIsIOSWithBadTarget = deviceIsIOS && /OS [6-7]_\d/.test(navigator.userAgent);
-
- /**
- * BlackBerry requires exceptions.
- *
- * @type boolean
- */
- var deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0;
-
- /**
- * Valid types for text inputs
- *
- * @type array
- */
- var textFields = ['email', 'number', 'password', 'search', 'tel', 'text', 'url'];
-
- /**
- * Determine whether a given element requires a native click.
- *
- * @param {EventTarget|Element} target Target DOM element
- * @returns {boolean} Returns true if the element needs a native click
- */
- FastClick.prototype.needsClick = function (target) {
- switch (target.nodeName.toLowerCase()) {
-
- // Don't send a synthetic click to disabled inputs (issue #62)
- case 'button':
- case 'select':
- case 'textarea':
- if (target.disabled) {
- return true;
- }
-
- break;
- case 'input':
-
- // File inputs need real clicks on iOS 6 due to a browser bug (issue #68)
- if (deviceIsIOS && target.type === 'file' || target.disabled) {
- return true;
- }
-
- break;
- case 'label':
- case 'iframe': // iOS8 homescreen apps can prevent events bubbling into frames
- case 'video':
- return true;
- }
-
- return (/\bneedsclick\b/.test(target.className)
- );
- };
-
- /**
- * Determine whether a given element requires a call to focus to simulate click into element.
- *
- * @param {EventTarget|Element} target Target DOM element
- * @returns {boolean} Returns true if the element requires a call to focus to simulate native click.
- */
- FastClick.prototype.needsFocus = function (target) {
- switch (target.nodeName.toLowerCase()) {
- case 'textarea':
- return true;
- case 'select':
- return !deviceIsAndroid;
- case 'input':
- switch (target.type) {
- case 'button':
- case 'checkbox':
- case 'file':
- case 'image':
- case 'radio':
- case 'submit':
- return false;
- }
-
- // No point in attempting to focus disabled inputs
- return !target.disabled && !target.readOnly;
- default:
- return (/\bneedsfocus\b/.test(target.className)
- );
- }
- };
-
- /**
- * Send a click event to the specified element.
- *
- * @param {EventTarget|Element} targetElement
- * @param {Event} event
- */
- FastClick.prototype.sendClick = function (targetElement, event) {
- var clickEvent, touch;
-
- // On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24)
- if (document.activeElement && document.activeElement !== targetElement) {
- document.activeElement.blur();
- }
-
- touch = event.changedTouches[0];
-
- // Synthesise a click event, with an extra attribute so it can be tracked
- clickEvent = document.createEvent('MouseEvents');
- clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
- clickEvent.forwardedTouchEvent = true;
- targetElement.dispatchEvent(clickEvent);
- };
-
- FastClick.prototype.determineEventType = function (targetElement) {
-
- //Issue #159: Android Chrome Select Box does not open with a synthetic click event
- if (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') {
- return 'mousedown';
- }
-
- return 'click';
- };
-
- /**
- * @param {EventTarget|Element} targetElement
- */
- FastClick.prototype.focus = function (targetElement) {
- var length;
-
- // Issue #160: on iOS 7, some input elements (e.g. date datetime month) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724.
- if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month' && targetElement.type !== 'email' && targetElement.type !== 'number') {
- length = targetElement.value.length;
- targetElement.setSelectionRange(length, length);
- } else {
- targetElement.focus();
- }
- };
-
- /**
- * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it.
- *
- * @param {EventTarget|Element} targetElement
- */
- FastClick.prototype.updateScrollParent = function (targetElement) {
- var scrollParent, parentElement;
-
- scrollParent = targetElement.fastClickScrollParent;
-
- // Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the
- // target element was moved to another parent.
- if (!scrollParent || !scrollParent.contains(targetElement)) {
- parentElement = targetElement;
- do {
- if (parentElement.scrollHeight > parentElement.offsetHeight) {
- scrollParent = parentElement;
- targetElement.fastClickScrollParent = parentElement;
- break;
- }
-
- parentElement = parentElement.parentElement;
- } while (parentElement);
- }
-
- // Always update the scroll top tracker if possible.
- if (scrollParent) {
- scrollParent.fastClickLastScrollTop = scrollParent.scrollTop;
- }
- };
-
- /**
- * @param {EventTarget} targetElement
- * @returns {Element|EventTarget}
- */
- FastClick.prototype.getTargetElementFromEventTarget = function (eventTarget) {
-
- // On some older browsers (notably Safari on iOS 4.1 - see issue #56) the event target may be a text node.
- if (eventTarget.nodeType === Node.TEXT_NODE) {
- return eventTarget.parentNode;
- }
-
- return eventTarget;
- };
-
- /**
- * @param {EventTarget} targetElement
- * @returns {boolean}
- */
- FastClick.prototype.isTextField = function (targetElement) {
- return targetElement.tagName.toLowerCase() === 'textarea' || textFields.indexOf(targetElement.type) !== -1;
- };
-
- /**
- * On touch start, record the position and scroll offset.
- *
- * @param {Event} event
- * @returns {boolean}
- */
- FastClick.prototype.onTouchStart = function (event) {
- var targetElement, touch;
-
- // Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the FastClick element (issue #111).
- if (event.targetTouches.length > 1) {
- return true;
- }
-
- targetElement = this.getTargetElementFromEventTarget(event.target);
- touch = event.targetTouches[0];
-
- // Ignore touches on contenteditable elements to prevent conflict with text selection.
- // (For details: https://github.com/ftlabs/fastclick/pull/211 )
- if (targetElement.isContentEditable) {
- return true;
- }
-
- if (deviceIsIOS) {
- // Ignore touchstart in focused text field
- // Allows normal text selection and commands (select/paste/cut) when a field has focus, while still allowing fast tap-to-focus.
- // Without this fix, user needs to tap-and-hold a text field for context menu, and double-tap to select text doesn't work at all.
- if (targetElement === document.activeElement && this.isTextField(targetElement)) {
- return true;
- }
-
- if (!deviceIsIOS4) {
-
- // Weird things happen on iOS when an alert or confirm dialog is opened from a click event callback (issue #23):
- // when the user next taps anywhere else on the page, new touchstart and touchend events are dispatched
- // with the same identifier as the touch event that previously triggered the click that triggered the alert.
- // Sadly, there is an issue on iOS 4 that causes some normal touch events to have the same identifier as an
- // immediately preceeding touch event (issue #52), so this fix is unavailable on that platform.
- // Issue 120: touch.identifier is 0 when Chrome dev tools 'Emulate touch events' is set with an iOS device UA string,
- // which causes all touch events to be ignored. As this block only applies to iOS, and iOS identifiers are always long,
- // random integers, it's safe to to continue if the identifier is 0 here.
- if (touch.identifier && touch.identifier === this.lastTouchIdentifier) {
- event.preventDefault();
- return false;
- }
-
- this.lastTouchIdentifier = touch.identifier;
-
- // If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and:
- // 1) the user does a fling scroll on the scrollable layer
- // 2) the user stops the fling scroll with another tap
- // then the event.target of the last 'touchend' event will be the element that was under the user's finger
- // when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check
- // is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42).
- this.updateScrollParent(targetElement);
- }
- }
-
- this.trackingClick = true;
- this.trackingClickStart = event.timeStamp;
- this.targetElement = targetElement;
-
- this.touchStartX = touch.pageX;
- this.touchStartY = touch.pageY;
-
- // Prevent phantom clicks on fast double-tap (issue #36)
- if (event.timeStamp - this.lastClickTime < this.tapDelay && event.timeStamp - this.lastClickTime > -1) {
- event.preventDefault();
- }
-
- return true;
- };
-
- /**
- * Based on a touchmove event object, check whether the touch has moved past a boundary since it started.
- *
- * @param {Event} event
- * @returns {boolean}
- */
- FastClick.prototype.touchHasMoved = function (event) {
- var touch = event.changedTouches[0],
- boundary = this.touchBoundary;
-
- if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) {
- return true;
- }
-
- return false;
- };
-
- /**
- * Update the last position.
- *
- * @param {Event} event
- * @returns {boolean}
- */
- FastClick.prototype.onTouchMove = function (event) {
- if (!this.trackingClick) {
- return true;
- }
-
- // If the touch has moved, cancel the click tracking
- if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {
- this.trackingClick = false;
- this.targetElement = null;
- }
-
- return true;
- };
-
- /**
- * Attempt to find the labelled control for the given label element.
- *
- * @param {EventTarget|HTMLLabelElement} labelElement
- * @returns {Element|null}
- */
- FastClick.prototype.findControl = function (labelElement) {
-
- // Fast path for newer browsers supporting the HTML5 control attribute
- if (labelElement.control !== undefined) {
- return labelElement.control;
- }
-
- // All browsers under test that support touch events also support the HTML5 htmlFor attribute
- if (labelElement.htmlFor) {
- return document.getElementById(labelElement.htmlFor);
- }
-
- // If no for attribute exists, attempt to retrieve the first labellable descendant element
- // the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label
- return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea');
- };
-
- /**
- * On touch end, determine whether to send a click event at once.
- *
- * @param {Event} event
- * @returns {boolean}
- */
- FastClick.prototype.onTouchEnd = function (event) {
- var forElement,
- trackingClickStart,
- targetTagName,
- scrollParent,
- touch,
- targetElement = this.targetElement;
-
- if (!this.trackingClick) {
- return true;
- }
-
- // Prevent phantom clicks on fast double-tap (issue #36)
- if (event.timeStamp - this.lastClickTime < this.tapDelay && event.timeStamp - this.lastClickTime > -1) {
- this.cancelNextClick = true;
- return true;
- }
-
- if (event.timeStamp - this.trackingClickStart > this.tapTimeout) {
- return true;
- }
-
- // Reset to prevent wrong click cancel on input (issue #156).
- this.cancelNextClick = false;
-
- this.lastClickTime = event.timeStamp;
-
- trackingClickStart = this.trackingClickStart;
- this.trackingClick = false;
- this.trackingClickStart = 0;
-
- // On some iOS devices, the targetElement supplied with the event is invalid if the layer
- // is performing a transition or scroll, and has to be re-detected manually. Note that
- // for this to function correctly, it must be called *after* the event target is checked!
- // See issue #57; also filed as rdar://13048589 .
- if (deviceIsIOSWithBadTarget) {
- touch = event.changedTouches[0];
-
- // In certain cases arguments of elementFromPoint can be negative, so prevent setting targetElement to null
- targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement;
- targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent;
- }
-
- targetTagName = targetElement.tagName.toLowerCase();
- if (targetTagName === 'label') {
- forElement = this.findControl(targetElement);
- if (forElement) {
- this.focus(targetElement);
- if (deviceIsAndroid) {
- return false;
- }
-
- targetElement = forElement;
- }
- } else if (this.needsFocus(targetElement)) {
-
- // Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through.
- // Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37).
- if (event.timeStamp - trackingClickStart > 100 || deviceIsIOS && window.top !== window && targetTagName === 'input') {
- this.targetElement = null;
- return false;
- }
-
- this.focus(targetElement);
- this.sendClick(targetElement, event);
-
- // Select elements need the event to go through on iOS 4, otherwise the selector menu won't open.
- // Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others)
- if (!deviceIsIOS4 || targetTagName !== 'select') {
- this.targetElement = null;
- event.preventDefault();
- }
-
- return false;
- }
-
- if (deviceIsIOS && !deviceIsIOS4) {
-
- // Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled
- // and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42).
- scrollParent = targetElement.fastClickScrollParent;
- if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {
- return true;
- }
- }
-
- // Prevent the actual click from going though - unless the target node is marked as requiring
- // real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted.
- if (!this.needsClick(targetElement)) {
- event.preventDefault();
- this.sendClick(targetElement, event);
- }
-
- return false;
- };
-
- /**
- * On touch cancel, stop tracking the click.
- *
- * @returns {void}
- */
- FastClick.prototype.onTouchCancel = function () {
- this.trackingClick = false;
- this.targetElement = null;
- };
-
- /**
- * Determine mouse events which should be permitted.
- *
- * @param {Event} event
- * @returns {boolean}
- */
- FastClick.prototype.onMouse = function (event) {
-
- // If a target element was never set (because a touch event was never fired) allow the event
- if (!this.targetElement) {
- return true;
- }
-
- if (event.forwardedTouchEvent) {
- return true;
- }
-
- // Programmatically generated events targeting a specific element should be permitted
- if (!event.cancelable) {
- return true;
- }
-
- // Derive and check the target element to see whether the mouse event needs to be permitted;
- // unless explicitly enabled, prevent non-touch click events from triggering actions,
- // to prevent ghost/doubleclicks.
- if (!this.needsClick(this.targetElement) || this.cancelNextClick) {
-
- // Prevent any user-added listeners declared on FastClick element from being fired.
- if (event.stopImmediatePropagation) {
- event.stopImmediatePropagation();
- } else {
-
- // Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
- event.propagationStopped = true;
- }
-
- // Cancel the event
- event.stopPropagation();
- event.preventDefault();
-
- return false;
- }
-
- // If the mouse event is permitted, return true for the action to go through.
- return true;
- };
-
- /**
- * On actual clicks, determine whether this is a touch-generated click, a click action occurring
- * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or
- * an actual click which should be permitted.
- *
- * @param {Event} event
- * @returns {boolean}
- */
- FastClick.prototype.onClick = function (event) {
- var permitted;
-
- // It's possible for another FastClick-like library delivered with third-party code to fire a click event before FastClick does (issue #44). In that case, set the click-tracking flag back to false and return early. This will cause onTouchEnd to return early.
- if (this.trackingClick) {
- this.targetElement = null;
- this.trackingClick = false;
- return true;
- }
-
- // Very odd behaviour on iOS (issue #18): if a submit element is present inside a form and the user hits enter in the iOS simulator or clicks the Go button on the pop-up OS keyboard the a kind of 'fake' click event will be triggered with the submit-type input element as the target.
- if (event.target.type === 'submit' && event.detail === 0) {
- return true;
- }
-
- permitted = this.onMouse(event);
-
- // Only unset targetElement if the click is not permitted. This will ensure that the check for !targetElement in onMouse fails and the browser's click doesn't go through.
- if (!permitted) {
- this.targetElement = null;
- }
-
- // If clicks are permitted, return true for the action to go through.
- return permitted;
- };
-
- /**
- * Remove all FastClick's event listeners.
- *
- * @returns {void}
- */
- FastClick.prototype.destroy = function () {
- var layer = this.layer;
-
- if (deviceIsAndroid) {
- layer.removeEventListener('mouseover', this.onMouse, true);
- layer.removeEventListener('mousedown', this.onMouse, true);
- layer.removeEventListener('mouseup', this.onMouse, true);
- }
-
- layer.removeEventListener('click', this.onClick, true);
- layer.removeEventListener('touchstart', this.onTouchStart, false);
- layer.removeEventListener('touchmove', this.onTouchMove, false);
- layer.removeEventListener('touchend', this.onTouchEnd, false);
- layer.removeEventListener('touchcancel', this.onTouchCancel, false);
- };
-
- /**
- * Check whether FastClick is needed.
- *
- * @param {Element} layer The layer to listen on
- */
- FastClick.notNeeded = function (layer) {
- var metaViewport;
- var chromeVersion;
- var blackberryVersion;
- var firefoxVersion;
-
- // Devices that don't support touch don't need FastClick
- if (typeof window.ontouchstart === 'undefined') {
- return true;
- }
-
- // Chrome version - zero for other browsers
- chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [, 0])[1];
-
- if (chromeVersion) {
-
- if (deviceIsAndroid) {
- metaViewport = document.querySelector('meta[name=viewport]');
-
- if (metaViewport) {
- // Chrome on Android with user-scalable="no" doesn't need FastClick (issue #89)
- if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
- return true;
- }
- // Chrome 32 and above with width=device-width or less don't need FastClick
- if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) {
- return true;
- }
- }
-
- // Chrome desktop doesn't need FastClick (issue #15)
- } else {
- return true;
- }
- }
-
- if (deviceIsBlackBerry10) {
- blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/);
-
- // BlackBerry 10.3+ does not require Fastclick library.
- // https://github.com/ftlabs/fastclick/issues/251
- if (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) {
- metaViewport = document.querySelector('meta[name=viewport]');
-
- if (metaViewport) {
- // user-scalable=no eliminates click delay.
- if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
- return true;
- }
- // width=device-width (or less than device-width) eliminates click delay.
- if (document.documentElement.scrollWidth <= window.outerWidth) {
- return true;
- }
- }
- }
- }
-
- // IE10 with -ms-touch-action: none or manipulation, which disables double-tap-to-zoom (issue #97)
- if (layer.style.msTouchAction === 'none' || layer.style.touchAction === 'manipulation') {
- return true;
- }
-
- // Firefox version - zero for other browsers
- firefoxVersion = +(/Firefox\/([0-9]+)/.exec(navigator.userAgent) || [, 0])[1];
-
- if (firefoxVersion >= 27) {
- // Firefox 27+ does not have tap delay if the content is not zoomable - https://bugzilla.mozilla.org/show_bug.cgi?id=922896
-
- metaViewport = document.querySelector('meta[name=viewport]');
- if (metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) {
- return true;
- }
- }
-
- // IE11: prefixed -ms-touch-action is no longer supported and it's recomended to use non-prefixed version
- // http://msdn.microsoft.com/en-us/library/windows/apps/Hh767313.aspx
- if (layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') {
- return true;
- }
-
- return false;
- };
-
- /**
- * Factory method for creating a FastClick object
- *
- * @param {Element} layer The layer to listen on
- * @param {Object} [options={}] The options to override the defaults
- */
- FastClick.attach = function (layer, options) {
- return new FastClick(layer, options);
- };
-
- if (typeof undefined === 'function' && _typeof(undefined.amd) === 'object' && undefined.amd) {
-
- // AMD. Register as an anonymous module.
- undefined(function () {
- return FastClick;
- });
- } else if ('object' !== 'undefined' && module.exports) {
- module.exports = FastClick.attach;
- module.exports.FastClick = FastClick;
- } else {
- window.FastClick = FastClick;
- }
- })();
- });
-
- var fastclick_1 = fastclick.FastClick;
-
- // For @onsenui/custom-elements
- if (window.customElements) {
- // even if native CE1 impl exists, use polyfill
- window.customElements.forcePolyfill = true;
- }
-
- var _global = createCommonjsModule(function (module) {
- // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
- var global = module.exports = typeof window != 'undefined' && window.Math == Math ? window : typeof self != 'undefined' && self.Math == Math ? self
- // eslint-disable-next-line no-new-func
- : Function('return this')();
- if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef
- });
-
- var _core = createCommonjsModule(function (module) {
- var core = module.exports = { version: '2.5.1' };
- if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef
- });
-
- var _core_1 = _core.version;
-
- var _isObject = function _isObject(it) {
- return (typeof it === 'undefined' ? 'undefined' : _typeof(it)) === 'object' ? it !== null : typeof it === 'function';
- };
-
- var _anObject = function _anObject(it) {
- if (!_isObject(it)) throw TypeError(it + ' is not an object!');
- return it;
- };
-
- var _fails = function _fails(exec) {
- try {
- return !!exec();
- } catch (e) {
- return true;
- }
- };
-
- // Thank's IE8 for his funny defineProperty
- var _descriptors = !_fails(function () {
- return Object.defineProperty({}, 'a', { get: function get() {
- return 7;
- } }).a != 7;
- });
-
- var document$1 = _global.document;
- // typeof document.createElement is 'object' in old IE
- var is = _isObject(document$1) && _isObject(document$1.createElement);
- var _domCreate = function _domCreate(it) {
- return is ? document$1.createElement(it) : {};
- };
-
- var _ie8DomDefine = !_descriptors && !_fails(function () {
- return Object.defineProperty(_domCreate('div'), 'a', { get: function get() {
- return 7;
- } }).a != 7;
- });
-
- // 7.1.1 ToPrimitive(input [, PreferredType])
-
- // instead of the ES6 spec version, we didn't implement @@toPrimitive case
- // and the second argument - flag - preferred type is a string
- var _toPrimitive = function _toPrimitive(it, S) {
- if (!_isObject(it)) return it;
- var fn, val;
- if (S && typeof (fn = it.toString) == 'function' && !_isObject(val = fn.call(it))) return val;
- if (typeof (fn = it.valueOf) == 'function' && !_isObject(val = fn.call(it))) return val;
- if (!S && typeof (fn = it.toString) == 'function' && !_isObject(val = fn.call(it))) return val;
- throw TypeError("Can't convert object to primitive value");
- };
-
- var dP = Object.defineProperty;
-
- var f = _descriptors ? Object.defineProperty : function defineProperty(O, P, Attributes) {
- _anObject(O);
- P = _toPrimitive(P, true);
- _anObject(Attributes);
- if (_ie8DomDefine) try {
- return dP(O, P, Attributes);
- } catch (e) {/* empty */}
- if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!');
- if ('value' in Attributes) O[P] = Attributes.value;
- return O;
- };
-
- var _objectDp = {
- f: f
- };
-
- var _propertyDesc = function _propertyDesc(bitmap, value) {
- return {
- enumerable: !(bitmap & 1),
- configurable: !(bitmap & 2),
- writable: !(bitmap & 4),
- value: value
- };
- };
-
- var _hide = _descriptors ? function (object, key, value) {
- return _objectDp.f(object, key, _propertyDesc(1, value));
- } : function (object, key, value) {
- object[key] = value;
- return object;
- };
-
- var hasOwnProperty = {}.hasOwnProperty;
- var _has = function _has(it, key) {
- return hasOwnProperty.call(it, key);
- };
-
- var id = 0;
- var px = Math.random();
- var _uid = function _uid(key) {
- return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));
- };
-
- var _redefine = createCommonjsModule(function (module) {
- var SRC = _uid('src');
- var TO_STRING = 'toString';
- var $toString = Function[TO_STRING];
- var TPL = ('' + $toString).split(TO_STRING);
-
- _core.inspectSource = function (it) {
- return $toString.call(it);
- };
-
- (module.exports = function (O, key, val, safe) {
- var isFunction = typeof val == 'function';
- if (isFunction) _has(val, 'name') || _hide(val, 'name', key);
- if (O[key] === val) return;
- if (isFunction) _has(val, SRC) || _hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));
- if (O === _global) {
- O[key] = val;
- } else if (!safe) {
- delete O[key];
- _hide(O, key, val);
- } else if (O[key]) {
- O[key] = val;
- } else {
- _hide(O, key, val);
- }
- // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
- })(Function.prototype, TO_STRING, function toString() {
- return typeof this == 'function' && this[SRC] || $toString.call(this);
- });
- });
-
- var _aFunction = function _aFunction(it) {
- if (typeof it != 'function') throw TypeError(it + ' is not a function!');
- return it;
- };
-
- // optional / simple context binding
-
- var _ctx = function _ctx(fn, that, length) {
- _aFunction(fn);
- if (that === undefined) return fn;
- switch (length) {
- case 1:
- return function (a) {
- return fn.call(that, a);
- };
- case 2:
- return function (a, b) {
- return fn.call(that, a, b);
- };
- case 3:
- return function (a, b, c) {
- return fn.call(that, a, b, c);
- };
- }
- return function () /* ...args */{
- return fn.apply(that, arguments);
- };
- };
-
- var PROTOTYPE = 'prototype';
-
- var $export = function $export(type, name, source) {
- var IS_FORCED = type & $export.F;
- var IS_GLOBAL = type & $export.G;
- var IS_STATIC = type & $export.S;
- var IS_PROTO = type & $export.P;
- var IS_BIND = type & $export.B;
- var target = IS_GLOBAL ? _global : IS_STATIC ? _global[name] || (_global[name] = {}) : (_global[name] || {})[PROTOTYPE];
- var exports = IS_GLOBAL ? _core : _core[name] || (_core[name] = {});
- var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {});
- var key, own, out, exp;
- if (IS_GLOBAL) source = name;
- for (key in source) {
- // contains in native
- own = !IS_FORCED && target && target[key] !== undefined;
- // export native or passed
- out = (own ? target : source)[key];
- // bind timers to global for call from export context
- exp = IS_BIND && own ? _ctx(out, _global) : IS_PROTO && typeof out == 'function' ? _ctx(Function.call, out) : out;
- // extend global
- if (target) _redefine(target, key, out, type & $export.U);
- // export
- if (exports[key] != out) _hide(exports, key, exp);
- if (IS_PROTO && expProto[key] != out) expProto[key] = out;
- }
- };
- _global.core = _core;
- // type bitmap
- $export.F = 1; // forced
- $export.G = 2; // global
- $export.S = 4; // static
- $export.P = 8; // proto
- $export.B = 16; // bind
- $export.W = 32; // wrap
- $export.U = 64; // safe
- $export.R = 128; // real proto method for `library`
- var _export = $export;
-
- var f$2 = {}.propertyIsEnumerable;
-
- var _objectPie = {
- f: f$2
- };
-
- var toString = {}.toString;
-
- var _cof = function _cof(it) {
- return toString.call(it).slice(8, -1);
- };
-
- // fallback for non-array-like ES3 and non-enumerable old V8 strings
-
- // eslint-disable-next-line no-prototype-builtins
- var _iobject = Object('z').propertyIsEnumerable(0) ? Object : function (it) {
- return _cof(it) == 'String' ? it.split('') : Object(it);
- };
-
- // 7.2.1 RequireObjectCoercible(argument)
- var _defined = function _defined(it) {
- if (it == undefined) throw TypeError("Can't call method on " + it);
- return it;
- };
-
- // to indexed object, toObject with fallback for non-array-like ES3 strings
-
-
- var _toIobject = function _toIobject(it) {
- return _iobject(_defined(it));
- };
-
- var gOPD = Object.getOwnPropertyDescriptor;
-
- var f$1 = _descriptors ? gOPD : function getOwnPropertyDescriptor(O, P) {
- O = _toIobject(O);
- P = _toPrimitive(P, true);
- if (_ie8DomDefine) try {
- return gOPD(O, P);
- } catch (e) {/* empty */}
- if (_has(O, P)) return _propertyDesc(!_objectPie.f.call(O, P), O[P]);
- };
-
- var _objectGopd = {
- f: f$1
- };
-
- // Works with __proto__ only. Old v8 can't work with null proto objects.
- /* eslint-disable no-proto */
-
- var check = function check(O, proto) {
- _anObject(O);
- if (!_isObject(proto) && proto !== null) throw TypeError(proto + ": can't set as prototype!");
- };
- var _setProto = {
- set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line
- function (test, buggy, set) {
- try {
- set = _ctx(Function.call, _objectGopd.f(Object.prototype, '__proto__').set, 2);
- set(test, []);
- buggy = !(test instanceof Array);
- } catch (e) {
- buggy = true;
- }
- return function setPrototypeOf(O, proto) {
- check(O, proto);
- if (buggy) O.__proto__ = proto;else set(O, proto);
- return O;
- };
- }({}, false) : undefined),
- check: check
- };
-
- // 19.1.3.19 Object.setPrototypeOf(O, proto)
-
- _export(_export.S, 'Object', { setPrototypeOf: _setProto.set });
-
- var setPrototypeOf = _core.Object.setPrototypeOf;
-
- var SHARED = '__core-js_shared__';
- var store = _global[SHARED] || (_global[SHARED] = {});
- var _shared = function _shared(key) {
- return store[key] || (store[key] = {});
- };
-
- var _wks = createCommonjsModule(function (module) {
- var store = _shared('wks');
-
- var _Symbol = _global.Symbol;
- var USE_SYMBOL = typeof _Symbol == 'function';
-
- var $exports = module.exports = function (name) {
- return store[name] || (store[name] = USE_SYMBOL && _Symbol[name] || (USE_SYMBOL ? _Symbol : _uid)('Symbol.' + name));
- };
-
- $exports.store = store;
- });
-
- // getting tag from 19.1.3.6 Object.prototype.toString()
-
- var TAG = _wks('toStringTag');
- // ES3 wrong here
- var ARG = _cof(function () {
- return arguments;
- }()) == 'Arguments';
-
- // fallback for IE11 Script Access Denied error
- var tryGet = function tryGet(it, key) {
- try {
- return it[key];
- } catch (e) {/* empty */}
- };
-
- var _classof = function _classof(it) {
- var O, T, B;
- return it === undefined ? 'Undefined' : it === null ? 'Null'
- // @@toStringTag case
- : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T
- // builtinTag case
- : ARG ? _cof(O)
- // ES3 arguments fallback
- : (B = _cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;
- };
-
- // 19.1.3.6 Object.prototype.toString()
-
- var test = {};
- test[_wks('toStringTag')] = 'z';
- if (test + '' != '[object z]') {
- _redefine(Object.prototype, 'toString', function toString() {
- return '[object ' + _classof(this) + ']';
- }, true);
- }
-
- // 7.1.4 ToInteger
- var ceil = Math.ceil;
- var floor = Math.floor;
- var _toInteger = function _toInteger(it) {
- return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);
- };
-
- // true -> String#at
- // false -> String#codePointAt
- var _stringAt = function _stringAt(TO_STRING) {
- return function (that, pos) {
- var s = String(_defined(that));
- var i = _toInteger(pos);
- var l = s.length;
- var a, b;
- if (i < 0 || i >= l) return TO_STRING ? '' : undefined;
- a = s.charCodeAt(i);
- return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff ? TO_STRING ? s.charAt(i) : a : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;
- };
- };
-
- var _library = false;
-
- var _iterators = {};
-
- // 7.1.15 ToLength
-
- var min = Math.min;
- var _toLength = function _toLength(it) {
- return it > 0 ? min(_toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991
- };
-
- var max = Math.max;
- var min$1 = Math.min;
- var _toAbsoluteIndex = function _toAbsoluteIndex(index, length) {
- index = _toInteger(index);
- return index < 0 ? max(index + length, 0) : min$1(index, length);
- };
-
- // false -> Array#indexOf
- // true -> Array#includes
-
-
- var _arrayIncludes = function _arrayIncludes(IS_INCLUDES) {
- return function ($this, el, fromIndex) {
- var O = _toIobject($this);
- var length = _toLength(O.length);
- var index = _toAbsoluteIndex(fromIndex, length);
- var value;
- // Array#includes uses SameValueZero equality algorithm
- // eslint-disable-next-line no-self-compare
- if (IS_INCLUDES && el != el) while (length > index) {
- value = O[index++];
- // eslint-disable-next-line no-self-compare
- if (value != value) return true;
- // Array#indexOf ignores holes, Array#includes - not
- } else for (; length > index; index++) {
- if (IS_INCLUDES || index in O) {
- if (O[index] === el) return IS_INCLUDES || index || 0;
- }
- }return !IS_INCLUDES && -1;
- };
- };
-
- var shared = _shared('keys');
-
- var _sharedKey = function _sharedKey(key) {
- return shared[key] || (shared[key] = _uid(key));
- };
-
- var arrayIndexOf = _arrayIncludes(false);
- var IE_PROTO$1 = _sharedKey('IE_PROTO');
-
- var _objectKeysInternal = function _objectKeysInternal(object, names) {
- var O = _toIobject(object);
- var i = 0;
- var result = [];
- var key;
- for (key in O) {
- if (key != IE_PROTO$1) _has(O, key) && result.push(key);
- } // Don't enum bug & hidden keys
- while (names.length > i) {
- if (_has(O, key = names[i++])) {
- ~arrayIndexOf(result, key) || result.push(key);
- }
- }return result;
- };
-
- // IE 8- don't enum bug keys
- var _enumBugKeys = 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'.split(',');
-
- // 19.1.2.14 / 15.2.3.14 Object.keys(O)
-
-
- var _objectKeys = Object.keys || function keys(O) {
- return _objectKeysInternal(O, _enumBugKeys);
- };
-
- var _objectDps = _descriptors ? Object.defineProperties : function defineProperties(O, Properties) {
- _anObject(O);
- var keys = _objectKeys(Properties);
- var length = keys.length;
- var i = 0;
- var P;
- while (length > i) {
- _objectDp.f(O, P = keys[i++], Properties[P]);
- }return O;
- };
-
- var document$2 = _global.document;
- var _html = document$2 && document$2.documentElement;
-
- // 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])
-
-
- var IE_PROTO = _sharedKey('IE_PROTO');
- var Empty = function Empty() {/* empty */};
- var PROTOTYPE$1 = 'prototype';
-
- // Create object with fake `null` prototype: use iframe Object with cleared prototype
- var _createDict = function createDict() {
- // Thrash, waste and sodomy: IE GC bug
- var iframe = _domCreate('iframe');
- var i = _enumBugKeys.length;
- var lt = '<';
- var gt = '>';
- var iframeDocument;
- iframe.style.display = 'none';
- _html.appendChild(iframe);
- iframe.src = 'javascript:'; // eslint-disable-line no-script-url
- // createDict = iframe.contentWindow.Object;
- // html.removeChild(iframe);
- iframeDocument = iframe.contentWindow.document;
- iframeDocument.open();
- iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);
- iframeDocument.close();
- _createDict = iframeDocument.F;
- while (i--) {
- delete _createDict[PROTOTYPE$1][_enumBugKeys[i]];
- }return _createDict();
- };
-
- var _objectCreate = Object.create || function create(O, Properties) {
- var result;
- if (O !== null) {
- Empty[PROTOTYPE$1] = _anObject(O);
- result = new Empty();
- Empty[PROTOTYPE$1] = null;
- // add "__proto__" for Object.getPrototypeOf polyfill
- result[IE_PROTO] = O;
- } else result = _createDict();
- return Properties === undefined ? result : _objectDps(result, Properties);
- };
-
- var def = _objectDp.f;
-
- var TAG$1 = _wks('toStringTag');
-
- var _setToStringTag = function _setToStringTag(it, tag, stat) {
- if (it && !_has(it = stat ? it : it.prototype, TAG$1)) def(it, TAG$1, { configurable: true, value: tag });
- };
-
- var IteratorPrototype = {};
-
- // 25.1.2.1.1 %IteratorPrototype%[@@iterator]()
- _hide(IteratorPrototype, _wks('iterator'), function () {
- return this;
- });
-
- var _iterCreate = function _iterCreate(Constructor, NAME, next) {
- Constructor.prototype = _objectCreate(IteratorPrototype, { next: _propertyDesc(1, next) });
- _setToStringTag(Constructor, NAME + ' Iterator');
- };
-
- // 7.1.13 ToObject(argument)
-
- var _toObject = function _toObject(it) {
- return Object(_defined(it));
- };
-
- // 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O)
-
-
- var IE_PROTO$2 = _sharedKey('IE_PROTO');
- var ObjectProto = Object.prototype;
-
- var _objectGpo = Object.getPrototypeOf || function (O) {
- O = _toObject(O);
- if (_has(O, IE_PROTO$2)) return O[IE_PROTO$2];
- if (typeof O.constructor == 'function' && O instanceof O.constructor) {
- return O.constructor.prototype;
- }return O instanceof Object ? ObjectProto : null;
- };
-
- var ITERATOR = _wks('iterator');
- var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next`
- var FF_ITERATOR = '@@iterator';
- var KEYS = 'keys';
- var VALUES = 'values';
-
- var returnThis = function returnThis() {
- return this;
- };
-
- var _iterDefine = function _iterDefine(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {
- _iterCreate(Constructor, NAME, next);
- var getMethod = function getMethod(kind) {
- if (!BUGGY && kind in proto) return proto[kind];
- switch (kind) {
- case KEYS:
- return function keys() {
- return new Constructor(this, kind);
- };
- case VALUES:
- return function values() {
- return new Constructor(this, kind);
- };
- }return function entries() {
- return new Constructor(this, kind);
- };
- };
- var TAG = NAME + ' Iterator';
- var DEF_VALUES = DEFAULT == VALUES;
- var VALUES_BUG = false;
- var proto = Base.prototype;
- var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];
- var $default = $native || getMethod(DEFAULT);
- var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;
- var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;
- var methods, key, IteratorPrototype;
- // Fix native
- if ($anyNative) {
- IteratorPrototype = _objectGpo($anyNative.call(new Base()));
- if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) {
- // Set @@toStringTag to native iterators
- _setToStringTag(IteratorPrototype, TAG, true);
- // fix for some old engines
- if (!_library && !_has(IteratorPrototype, ITERATOR)) _hide(IteratorPrototype, ITERATOR, returnThis);
- }
- }
- // fix Array#{values, @@iterator}.name in V8 / FF
- if (DEF_VALUES && $native && $native.name !== VALUES) {
- VALUES_BUG = true;
- $default = function values() {
- return $native.call(this);
- };
- }
- // Define iterator
- if ((!_library || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) {
- _hide(proto, ITERATOR, $default);
- }
- // Plug for library
- _iterators[NAME] = $default;
- _iterators[TAG] = returnThis;
- if (DEFAULT) {
- methods = {
- values: DEF_VALUES ? $default : getMethod(VALUES),
- keys: IS_SET ? $default : getMethod(KEYS),
- entries: $entries
- };
- if (FORCED) for (key in methods) {
- if (!(key in proto)) _redefine(proto, key, methods[key]);
- } else _export(_export.P + _export.F * (BUGGY || VALUES_BUG), NAME, methods);
- }
- return methods;
- };
-
- var $at = _stringAt(true);
-
- // 21.1.3.27 String.prototype[@@iterator]()
- _iterDefine(String, 'String', function (iterated) {
- this._t = String(iterated); // target
- this._i = 0; // next index
- // 21.1.5.2.1 %StringIteratorPrototype%.next()
- }, function () {
- var O = this._t;
- var index = this._i;
- var point;
- if (index >= O.length) return { value: undefined, done: true };
- point = $at(O, index);
- this._i += point.length;
- return { value: point, done: false };
- });
-
- // 22.1.3.31 Array.prototype[@@unscopables]
- var UNSCOPABLES = _wks('unscopables');
- var ArrayProto = Array.prototype;
- if (ArrayProto[UNSCOPABLES] == undefined) _hide(ArrayProto, UNSCOPABLES, {});
- var _addToUnscopables = function _addToUnscopables(key) {
- ArrayProto[UNSCOPABLES][key] = true;
- };
-
- var _iterStep = function _iterStep(done, value) {
- return { value: value, done: !!done };
- };
-
- // 22.1.3.4 Array.prototype.entries()
- // 22.1.3.13 Array.prototype.keys()
- // 22.1.3.29 Array.prototype.values()
- // 22.1.3.30 Array.prototype[@@iterator]()
- var es6_array_iterator = _iterDefine(Array, 'Array', function (iterated, kind) {
- this._t = _toIobject(iterated); // target
- this._i = 0; // next index
- this._k = kind; // kind
- // 22.1.5.2.1 %ArrayIteratorPrototype%.next()
- }, function () {
- var O = this._t;
- var kind = this._k;
- var index = this._i++;
- if (!O || index >= O.length) {
- this._t = undefined;
- return _iterStep(1);
- }
- if (kind == 'keys') return _iterStep(0, index);
- if (kind == 'values') return _iterStep(0, O[index]);
- return _iterStep(0, [index, O[index]]);
- }, 'values');
-
- // argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7)
- _iterators.Arguments = _iterators.Array;
-
- _addToUnscopables('keys');
- _addToUnscopables('values');
- _addToUnscopables('entries');
-
- var ITERATOR$1 = _wks('iterator');
- var TO_STRING_TAG = _wks('toStringTag');
- var ArrayValues = _iterators.Array;
-
- var DOMIterables = {
- CSSRuleList: true, // TODO: Not spec compliant, should be false.
- CSSStyleDeclaration: false,
- CSSValueList: false,
- ClientRectList: false,
- DOMRectList: false,
- DOMStringList: false,
- DOMTokenList: true,
- DataTransferItemList: false,
- FileList: false,
- HTMLAllCollection: false,
- HTMLCollection: false,
- HTMLFormElement: false,
- HTMLSelectElement: false,
- MediaList: true, // TODO: Not spec compliant, should be false.
- MimeTypeArray: false,
- NamedNodeMap: false,
- NodeList: true,
- PaintRequestList: false,
- Plugin: false,
- PluginArray: false,
- SVGLengthList: false,
- SVGNumberList: false,
- SVGPathSegList: false,
- SVGPointList: false,
- SVGStringList: false,
- SVGTransformList: false,
- SourceBufferList: false,
- StyleSheetList: true, // TODO: Not spec compliant, should be false.
- TextTrackCueList: false,
- TextTrackList: false,
- TouchList: false
- };
-
- for (var collections = _objectKeys(DOMIterables), i = 0; i < collections.length; i++) {
- var NAME = collections[i];
- var explicit = DOMIterables[NAME];
- var Collection = _global[NAME];
- var proto = Collection && Collection.prototype;
- var key;
- if (proto) {
- if (!proto[ITERATOR$1]) _hide(proto, ITERATOR$1, ArrayValues);
- if (!proto[TO_STRING_TAG]) _hide(proto, TO_STRING_TAG, NAME);
- _iterators[NAME] = ArrayValues;
- if (explicit) for (key in es6_array_iterator) {
- if (!proto[key]) _redefine(proto, key, es6_array_iterator[key], true);
- }
- }
- }
-
- var _redefineAll = function _redefineAll(target, src, safe) {
- for (var key in src) {
- _redefine(target, key, src[key], safe);
- }return target;
- };
-
- var _anInstance = function _anInstance(it, Constructor, name, forbiddenField) {
- if (!(it instanceof Constructor) || forbiddenField !== undefined && forbiddenField in it) {
- throw TypeError(name + ': incorrect invocation!');
- }return it;
- };
-
- // call something on iterator step with safe closing on error
-
- var _iterCall = function _iterCall(iterator, fn, value, entries) {
- try {
- return entries ? fn(_anObject(value)[0], value[1]) : fn(value);
- // 7.4.6 IteratorClose(iterator, completion)
- } catch (e) {
- var ret = iterator['return'];
- if (ret !== undefined) _anObject(ret.call(iterator));
- throw e;
- }
- };
-
- // check on default Array iterator
-
- var ITERATOR$2 = _wks('iterator');
- var ArrayProto$1 = Array.prototype;
-
- var _isArrayIter = function _isArrayIter(it) {
- return it !== undefined && (_iterators.Array === it || ArrayProto$1[ITERATOR$2] === it);
- };
-
- var ITERATOR$3 = _wks('iterator');
-
- var core_getIteratorMethod = _core.getIteratorMethod = function (it) {
- if (it != undefined) return it[ITERATOR$3] || it['@@iterator'] || _iterators[_classof(it)];
- };
-
- var _forOf = createCommonjsModule(function (module) {
- var BREAK = {};
- var RETURN = {};
- var exports = module.exports = function (iterable, entries, fn, that, ITERATOR) {
- var iterFn = ITERATOR ? function () {
- return iterable;
- } : core_getIteratorMethod(iterable);
- var f = _ctx(fn, that, entries ? 2 : 1);
- var index = 0;
- var length, step, iterator, result;
- if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!');
- // fast case for arrays with default iterator
- if (_isArrayIter(iterFn)) for (length = _toLength(iterable.length); length > index; index++) {
- result = entries ? f(_anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);
- if (result === BREAK || result === RETURN) return result;
- } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) {
- result = _iterCall(iterator, f, step.value, entries);
- if (result === BREAK || result === RETURN) return result;
- }
- };
- exports.BREAK = BREAK;
- exports.RETURN = RETURN;
- });
-
- var SPECIES = _wks('species');
-
- var _setSpecies = function _setSpecies(KEY) {
- var C = _global[KEY];
- if (_descriptors && C && !C[SPECIES]) _objectDp.f(C, SPECIES, {
- configurable: true,
- get: function get() {
- return this;
- }
- });
- };
-
- var _meta = createCommonjsModule(function (module) {
- var META = _uid('meta');
-
- var setDesc = _objectDp.f;
- var id = 0;
- var isExtensible = Object.isExtensible || function () {
- return true;
- };
- var FREEZE = !_fails(function () {
- return isExtensible(Object.preventExtensions({}));
- });
- var setMeta = function setMeta(it) {
- setDesc(it, META, { value: {
- i: 'O' + ++id, // object ID
- w: {} // weak collections IDs
- } });
- };
- var fastKey = function fastKey(it, create) {
- // return primitive with prefix
- if (!_isObject(it)) return (typeof it === 'undefined' ? 'undefined' : _typeof(it)) == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
- if (!_has(it, META)) {
- // can't set metadata to uncaught frozen object
- if (!isExtensible(it)) return 'F';
- // not necessary to add metadata
- if (!create) return 'E';
- // add missing metadata
- setMeta(it);
- // return object ID
- }return it[META].i;
- };
- var getWeak = function getWeak(it, create) {
- if (!_has(it, META)) {
- // can't set metadata to uncaught frozen object
- if (!isExtensible(it)) return true;
- // not necessary to add metadata
- if (!create) return false;
- // add missing metadata
- setMeta(it);
- // return hash weak collections IDs
- }return it[META].w;
- };
- // add metadata on freeze-family methods calling
- var onFreeze = function onFreeze(it) {
- if (FREEZE && meta.NEED && isExtensible(it) && !_has(it, META)) setMeta(it);
- return it;
- };
- var meta = module.exports = {
- KEY: META,
- NEED: false,
- fastKey: fastKey,
- getWeak: getWeak,
- onFreeze: onFreeze
- };
- });
-
- var _meta_1 = _meta.KEY;
- var _meta_2 = _meta.NEED;
- var _meta_3 = _meta.fastKey;
- var _meta_4 = _meta.getWeak;
- var _meta_5 = _meta.onFreeze;
-
- var _validateCollection = function _validateCollection(it, TYPE) {
- if (!_isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!');
- return it;
- };
-
- var dP$1 = _objectDp.f;
-
- var fastKey = _meta.fastKey;
-
- var SIZE = _descriptors ? '_s' : 'size';
-
- var getEntry = function getEntry(that, key) {
- // fast case
- var index = fastKey(key);
- var entry;
- if (index !== 'F') return that._i[index];
- // frozen object case
- for (entry = that._f; entry; entry = entry.n) {
- if (entry.k == key) return entry;
- }
- };
-
- var _collectionStrong = {
- getConstructor: function getConstructor(wrapper, NAME, IS_MAP, ADDER) {
- var C = wrapper(function (that, iterable) {
- _anInstance(that, C, NAME, '_i');
- that._t = NAME; // collection type
- that._i = _objectCreate(null); // index
- that._f = undefined; // first entry
- that._l = undefined; // last entry
- that[SIZE] = 0; // size
- if (iterable != undefined) _forOf(iterable, IS_MAP, that[ADDER], that);
- });
- _redefineAll(C.prototype, {
- // 23.1.3.1 Map.prototype.clear()
- // 23.2.3.2 Set.prototype.clear()
- clear: function clear() {
- for (var that = _validateCollection(this, NAME), data = that._i, entry = that._f; entry; entry = entry.n) {
- entry.r = true;
- if (entry.p) entry.p = entry.p.n = undefined;
- delete data[entry.i];
- }
- that._f = that._l = undefined;
- that[SIZE] = 0;
- },
- // 23.1.3.3 Map.prototype.delete(key)
- // 23.2.3.4 Set.prototype.delete(value)
- 'delete': function _delete(key) {
- var that = _validateCollection(this, NAME);
- var entry = getEntry(that, key);
- if (entry) {
- var next = entry.n;
- var prev = entry.p;
- delete that._i[entry.i];
- entry.r = true;
- if (prev) prev.n = next;
- if (next) next.p = prev;
- if (that._f == entry) that._f = next;
- if (that._l == entry) that._l = prev;
- that[SIZE]--;
- }return !!entry;
- },
- // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined)
- // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined)
- forEach: function forEach(callbackfn /* , that = undefined */) {
- _validateCollection(this, NAME);
- var f = _ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3);
- var entry;
- while (entry = entry ? entry.n : this._f) {
- f(entry.v, entry.k, this);
- // revert to the last existing entry
- while (entry && entry.r) {
- entry = entry.p;
- }
- }
- },
- // 23.1.3.7 Map.prototype.has(key)
- // 23.2.3.7 Set.prototype.has(value)
- has: function has(key) {
- return !!getEntry(_validateCollection(this, NAME), key);
- }
- });
- if (_descriptors) dP$1(C.prototype, 'size', {
- get: function get() {
- return _validateCollection(this, NAME)[SIZE];
- }
- });
- return C;
- },
- def: function def(that, key, value) {
- var entry = getEntry(that, key);
- var prev, index;
- // change existing entry
- if (entry) {
- entry.v = value;
- // create new entry
- } else {
- that._l = entry = {
- i: index = fastKey(key, true), // <- index
- k: key, // <- key
- v: value, // <- value
- p: prev = that._l, // <- previous entry
- n: undefined, // <- next entry
- r: false // <- removed
- };
- if (!that._f) that._f = entry;
- if (prev) prev.n = entry;
- that[SIZE]++;
- // add to index
- if (index !== 'F') that._i[index] = entry;
- }return that;
- },
- getEntry: getEntry,
- setStrong: function setStrong(C, NAME, IS_MAP) {
- // add .keys, .values, .entries, [@@iterator]
- // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11
- _iterDefine(C, NAME, function (iterated, kind) {
- this._t = _validateCollection(iterated, NAME); // target
- this._k = kind; // kind
- this._l = undefined; // previous
- }, function () {
- var that = this;
- var kind = that._k;
- var entry = that._l;
- // revert to the last existing entry
- while (entry && entry.r) {
- entry = entry.p;
- } // get next entry
- if (!that._t || !(that._l = entry = entry ? entry.n : that._t._f)) {
- // or finish the iteration
- that._t = undefined;
- return _iterStep(1);
- }
- // return step by kind
- if (kind == 'keys') return _iterStep(0, entry.k);
- if (kind == 'values') return _iterStep(0, entry.v);
- return _iterStep(0, [entry.k, entry.v]);
- }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);
-
- // add [@@species], 23.1.2.2, 23.2.2.2
- _setSpecies(NAME);
- }
- };
-
- var ITERATOR$4 = _wks('iterator');
- var SAFE_CLOSING = false;
-
- try {
- var riter = [7][ITERATOR$4]();
- riter['return'] = function () {
- SAFE_CLOSING = true;
- };
- // eslint-disable-next-line no-throw-literal
-
- } catch (e) {/* empty */}
-
- var _iterDetect = function _iterDetect(exec, skipClosing) {
- if (!skipClosing && !SAFE_CLOSING) return false;
- var safe = false;
- try {
- var arr = [7];
- var iter = arr[ITERATOR$4]();
- iter.next = function () {
- return { done: safe = true };
- };
- arr[ITERATOR$4] = function () {
- return iter;
- };
- exec(arr);
- } catch (e) {/* empty */}
- return safe;
- };
-
- var setPrototypeOf$2 = _setProto.set;
- var _inheritIfRequired = function _inheritIfRequired(that, target, C) {
- var S = target.constructor;
- var P;
- if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && _isObject(P) && setPrototypeOf$2) {
- setPrototypeOf$2(that, P);
- }return that;
- };
-
- var _collection = function _collection(NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {
- var Base = _global[NAME];
- var C = Base;
- var ADDER = IS_MAP ? 'set' : 'add';
- var proto = C && C.prototype;
- var O = {};
- var fixMethod = function fixMethod(KEY) {
- var fn = proto[KEY];
- _redefine(proto, KEY, KEY == 'delete' ? function (a) {
- return IS_WEAK && !_isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
- } : KEY == 'has' ? function has(a) {
- return IS_WEAK && !_isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
- } : KEY == 'get' ? function get(a) {
- return IS_WEAK && !_isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a);
- } : KEY == 'add' ? function add(a) {
- fn.call(this, a === 0 ? 0 : a);return this;
- } : function set(a, b) {
- fn.call(this, a === 0 ? 0 : a, b);return this;
- });
- };
- if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !_fails(function () {
- new C().entries().next();
- }))) {
- // create collection constructor
- C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);
- _redefineAll(C.prototype, methods);
- _meta.NEED = true;
- } else {
- var instance = new C();
- // early implementations not supports chaining
- var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;
- // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false
- var THROWS_ON_PRIMITIVES = _fails(function () {
- instance.has(1);
- });
- // most early implementations doesn't supports iterables, most modern - not close it correctly
- var ACCEPT_ITERABLES = _iterDetect(function (iter) {
- new C(iter);
- }); // eslint-disable-line no-new
- // for early implementations -0 and +0 not the same
- var BUGGY_ZERO = !IS_WEAK && _fails(function () {
- // V8 ~ Chromium 42- fails only with 5+ elements
- var $instance = new C();
- var index = 5;
- while (index--) {
- $instance[ADDER](index, index);
- }return !$instance.has(-0);
- });
- if (!ACCEPT_ITERABLES) {
- C = wrapper(function (target, iterable) {
- _anInstance(target, C, NAME);
- var that = _inheritIfRequired(new Base(), target, C);
- if (iterable != undefined) _forOf(iterable, IS_MAP, that[ADDER], that);
- return that;
- });
- C.prototype = proto;
- proto.constructor = C;
- }
- if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {
- fixMethod('delete');
- fixMethod('has');
- IS_MAP && fixMethod('get');
- }
- if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);
- // weak collections should not contains .clear method
- if (IS_WEAK && proto.clear) delete proto.clear;
- }
-
- _setToStringTag(C, NAME);
-
- O[NAME] = C;
- _export(_export.G + _export.W + _export.F * (C != Base), O);
-
- if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP);
-
- return C;
- };
-
- var SET = 'Set';
-
- // 23.2 Set Objects
- var es6_set = _collection(SET, function (get) {
- return function Set() {
- return get(this, arguments.length > 0 ? arguments[0] : undefined);
- };
- }, {
- // 23.2.3.1 Set.prototype.add(value)
- add: function add(value) {
- return _collectionStrong.def(_validateCollection(this, SET), value = value === 0 ? 0 : value, value);
- }
- }, _collectionStrong);
-
- var _arrayFromIterable = function _arrayFromIterable(iter, ITERATOR) {
- var result = [];
- _forOf(iter, false, result.push, result, ITERATOR);
- return result;
- };
-
- // https://github.com/DavidBruant/Map-Set.prototype.toJSON
-
-
- var _collectionToJson = function _collectionToJson(NAME) {
- return function toJSON() {
- if (_classof(this) != NAME) throw TypeError(NAME + "#toJSON isn't generic");
- return _arrayFromIterable(this);
- };
- };
-
- // https://github.com/DavidBruant/Map-Set.prototype.toJSON
-
-
- _export(_export.P + _export.R, 'Set', { toJSON: _collectionToJson('Set') });
-
- // https://tc39.github.io/proposal-setmap-offrom/
-
-
- var _setCollectionOf = function _setCollectionOf(COLLECTION) {
- _export(_export.S, COLLECTION, { of: function of() {
- var length = arguments.length;
- var A = Array(length);
- while (length--) {
- A[length] = arguments[length];
- }return new this(A);
- } });
- };
-
- // https://tc39.github.io/proposal-setmap-offrom/#sec-set.of
- _setCollectionOf('Set');
-
- // https://tc39.github.io/proposal-setmap-offrom/
-
-
- var _setCollectionFrom = function _setCollectionFrom(COLLECTION) {
- _export(_export.S, COLLECTION, { from: function from(source /* , mapFn, thisArg */) {
- var mapFn = arguments[1];
- var mapping, A, n, cb;
- _aFunction(this);
- mapping = mapFn !== undefined;
- if (mapping) _aFunction(mapFn);
- if (source == undefined) return new this();
- A = [];
- if (mapping) {
- n = 0;
- cb = _ctx(mapFn, arguments[2], 2);
- _forOf(source, false, function (nextItem) {
- A.push(cb(nextItem, n++));
- });
- } else {
- _forOf(source, false, A.push, A);
- }
- return new this(A);
- } });
- };
-
- // https://tc39.github.io/proposal-setmap-offrom/#sec-set.from
- _setCollectionFrom('Set');
-
- var set$1 = _core.Set;
-
- var MAP = 'Map';
-
- // 23.1 Map Objects
- var es6_map = _collection(MAP, function (get) {
- return function Map() {
- return get(this, arguments.length > 0 ? arguments[0] : undefined);
- };
- }, {
- // 23.1.3.6 Map.prototype.get(key)
- get: function get(key) {
- var entry = _collectionStrong.getEntry(_validateCollection(this, MAP), key);
- return entry && entry.v;
- },
- // 23.1.3.9 Map.prototype.set(key, value)
- set: function set(key, value) {
- return _collectionStrong.def(_validateCollection(this, MAP), key === 0 ? 0 : key, value);
- }
- }, _collectionStrong, true);
-
- // https://github.com/DavidBruant/Map-Set.prototype.toJSON
-
-
- _export(_export.P + _export.R, 'Map', { toJSON: _collectionToJson('Map') });
-
- // https://tc39.github.io/proposal-setmap-offrom/#sec-map.of
- _setCollectionOf('Map');
-
- // https://tc39.github.io/proposal-setmap-offrom/#sec-map.from
- _setCollectionFrom('Map');
-
- var map = _core.Map;
-
- // 7.2.2 IsArray(argument)
-
- var _isArray = Array.isArray || function isArray(arg) {
- return _cof(arg) == 'Array';
- };
-
- var SPECIES$1 = _wks('species');
-
- var _arraySpeciesConstructor = function _arraySpeciesConstructor(original) {
- var C;
- if (_isArray(original)) {
- C = original.constructor;
- // cross-realm fallback
- if (typeof C == 'function' && (C === Array || _isArray(C.prototype))) C = undefined;
- if (_isObject(C)) {
- C = C[SPECIES$1];
- if (C === null) C = undefined;
- }
- }return C === undefined ? Array : C;
- };
-
- // 9.4.2.3 ArraySpeciesCreate(originalArray, length)
-
-
- var _arraySpeciesCreate = function _arraySpeciesCreate(original, length) {
- return new (_arraySpeciesConstructor(original))(length);
- };
-
- // 0 -> Array#forEach
- // 1 -> Array#map
- // 2 -> Array#filter
- // 3 -> Array#some
- // 4 -> Array#every
- // 5 -> Array#find
- // 6 -> Array#findIndex
-
-
- var _arrayMethods = function _arrayMethods(TYPE, $create) {
- var IS_MAP = TYPE == 1;
- var IS_FILTER = TYPE == 2;
- var IS_SOME = TYPE == 3;
- var IS_EVERY = TYPE == 4;
- var IS_FIND_INDEX = TYPE == 6;
- var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
- var create = $create || _arraySpeciesCreate;
- return function ($this, callbackfn, that) {
- var O = _toObject($this);
- var self = _iobject(O);
- var f = _ctx(callbackfn, that, 3);
- var length = _toLength(self.length);
- var index = 0;
- var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined;
- var val, res;
- for (; length > index; index++) {
- if (NO_HOLES || index in self) {
- val = self[index];
- res = f(val, index, O);
- if (TYPE) {
- if (IS_MAP) result[index] = res; // map
- else if (res) switch (TYPE) {
- case 3:
- return true; // some
- case 5:
- return val; // find
- case 6:
- return index; // findIndex
- case 2:
- result.push(val); // filter
- } else if (IS_EVERY) return false; // every
- }
- }
- }return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;
- };
- };
-
- var f$3 = Object.getOwnPropertySymbols;
-
- var _objectGops = {
- f: f$3
- };
-
- // 19.1.2.1 Object.assign(target, source, ...)
-
-
- var $assign = Object.assign;
-
- // should work with symbols and should have deterministic property order (V8 bug)
- var _objectAssign = !$assign || _fails(function () {
- var A = {};
- var B = {};
- // eslint-disable-next-line no-undef
- var S = Symbol();
- var K = 'abcdefghijklmnopqrst';
- A[S] = 7;
- K.split('').forEach(function (k) {
- B[k] = k;
- });
- return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;
- }) ? function assign(target, source) {
- // eslint-disable-line no-unused-vars
- var T = _toObject(target);
- var aLen = arguments.length;
- var index = 1;
- var getSymbols = _objectGops.f;
- var isEnum = _objectPie.f;
- while (aLen > index) {
- var S = _iobject(arguments[index++]);
- var keys = getSymbols ? _objectKeys(S).concat(getSymbols(S)) : _objectKeys(S);
- var length = keys.length;
- var j = 0;
- var key;
- while (length > j) {
- if (isEnum.call(S, key = keys[j++])) T[key] = S[key];
- }
- }return T;
- } : $assign;
-
- var getWeak = _meta.getWeak;
-
- var arrayFind = _arrayMethods(5);
- var arrayFindIndex = _arrayMethods(6);
- var id$1 = 0;
-
- // fallback for uncaught frozen keys
- var uncaughtFrozenStore = function uncaughtFrozenStore(that) {
- return that._l || (that._l = new UncaughtFrozenStore());
- };
- var UncaughtFrozenStore = function UncaughtFrozenStore() {
- this.a = [];
- };
- var findUncaughtFrozen = function findUncaughtFrozen(store, key) {
- return arrayFind(store.a, function (it) {
- return it[0] === key;
- });
- };
- UncaughtFrozenStore.prototype = {
- get: function get(key) {
- var entry = findUncaughtFrozen(this, key);
- if (entry) return entry[1];
- },
- has: function has(key) {
- return !!findUncaughtFrozen(this, key);
- },
- set: function set(key, value) {
- var entry = findUncaughtFrozen(this, key);
- if (entry) entry[1] = value;else this.a.push([key, value]);
- },
- 'delete': function _delete(key) {
- var index = arrayFindIndex(this.a, function (it) {
- return it[0] === key;
- });
- if (~index) this.a.splice(index, 1);
- return !!~index;
- }
- };
-
- var _collectionWeak = {
- getConstructor: function getConstructor(wrapper, NAME, IS_MAP, ADDER) {
- var C = wrapper(function (that, iterable) {
- _anInstance(that, C, NAME, '_i');
- that._t = NAME; // collection type
- that._i = id$1++; // collection id
- that._l = undefined; // leak store for uncaught frozen objects
- if (iterable != undefined) _forOf(iterable, IS_MAP, that[ADDER], that);
- });
- _redefineAll(C.prototype, {
- // 23.3.3.2 WeakMap.prototype.delete(key)
- // 23.4.3.3 WeakSet.prototype.delete(value)
- 'delete': function _delete(key) {
- if (!_isObject(key)) return false;
- var data = getWeak(key);
- if (data === true) return uncaughtFrozenStore(_validateCollection(this, NAME))['delete'](key);
- return data && _has(data, this._i) && delete data[this._i];
- },
- // 23.3.3.4 WeakMap.prototype.has(key)
- // 23.4.3.4 WeakSet.prototype.has(value)
- has: function has(key) {
- if (!_isObject(key)) return false;
- var data = getWeak(key);
- if (data === true) return uncaughtFrozenStore(_validateCollection(this, NAME)).has(key);
- return data && _has(data, this._i);
- }
- });
- return C;
- },
- def: function def(that, key, value) {
- var data = getWeak(_anObject(key), true);
- if (data === true) uncaughtFrozenStore(that).set(key, value);else data[that._i] = value;
- return that;
- },
- ufstore: uncaughtFrozenStore
- };
-
- var es6_weakMap = createCommonjsModule(function (module) {
- var each = _arrayMethods(0);
-
- var WEAK_MAP = 'WeakMap';
- var getWeak = _meta.getWeak;
- var isExtensible = Object.isExtensible;
- var uncaughtFrozenStore = _collectionWeak.ufstore;
- var tmp = {};
- var InternalMap;
-
- var wrapper = function wrapper(get) {
- return function WeakMap() {
- return get(this, arguments.length > 0 ? arguments[0] : undefined);
- };
- };
-
- var methods = {
- // 23.3.3.3 WeakMap.prototype.get(key)
- get: function get(key) {
- if (_isObject(key)) {
- var data = getWeak(key);
- if (data === true) return uncaughtFrozenStore(_validateCollection(this, WEAK_MAP)).get(key);
- return data ? data[this._i] : undefined;
- }
- },
- // 23.3.3.5 WeakMap.prototype.set(key, value)
- set: function set(key, value) {
- return _collectionWeak.def(_validateCollection(this, WEAK_MAP), key, value);
- }
- };
-
- // 23.3 WeakMap Objects
- var $WeakMap = module.exports = _collection(WEAK_MAP, wrapper, methods, _collectionWeak, true, true);
-
- // IE11 WeakMap frozen keys fix
- if (_fails(function () {
- return new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7;
- })) {
- InternalMap = _collectionWeak.getConstructor(wrapper, WEAK_MAP);
- _objectAssign(InternalMap.prototype, methods);
- _meta.NEED = true;
- each(['delete', 'has', 'get', 'set'], function (key) {
- var proto = $WeakMap.prototype;
- var method = proto[key];
- _redefine(proto, key, function (a, b) {
- // store frozen objects on internal weakmap shim
- if (_isObject(a) && !isExtensible(a)) {
- if (!this._f) this._f = new InternalMap();
- var result = this._f[key](a, b);
- return key == 'set' ? this : result;
- // store all the rest on native weakmap
- }return method.call(this, a, b);
- });
- });
- }
- });
-
- // https://tc39.github.io/proposal-setmap-offrom/#sec-weakmap.of
- _setCollectionOf('WeakMap');
-
- // https://tc39.github.io/proposal-setmap-offrom/#sec-weakmap.from
- _setCollectionFrom('WeakMap');
-
- var weakMap = _core.WeakMap;
-
- var _createProperty = function _createProperty(object, index, value) {
- if (index in object) _objectDp.f(object, index, _propertyDesc(0, value));else object[index] = value;
- };
-
- _export(_export.S + _export.F * !_iterDetect(function (iter) {
-
- }), 'Array', {
- // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined)
- from: function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {
- var O = _toObject(arrayLike);
- var C = typeof this == 'function' ? this : Array;
- var aLen = arguments.length;
- var mapfn = aLen > 1 ? arguments[1] : undefined;
- var mapping = mapfn !== undefined;
- var index = 0;
- var iterFn = core_getIteratorMethod(O);
- var length, result, step, iterator;
- if (mapping) mapfn = _ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2);
- // if object isn't iterable or it's array with default iterator - use simple case
- if (iterFn != undefined && !(C == Array && _isArrayIter(iterFn))) {
- for (iterator = iterFn.call(O), result = new C(); !(step = iterator.next()).done; index++) {
- _createProperty(result, index, mapping ? _iterCall(iterator, mapfn, [step.value, index], true) : step.value);
- }
- } else {
- length = _toLength(O.length);
- for (result = new C(length); length > index; index++) {
- _createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]);
- }
- }
- result.length = index;
- return result;
- }
- });
-
- var from$1 = _core.Array.from;
-
- var reservedTagList = new Set(['annotation-xml', 'color-profile', 'font-face', 'font-face-src', 'font-face-uri', 'font-face-format', 'font-face-name', 'missing-glyph']);
-
- /**
- * @param {string} localName
- * @returns {boolean}
- */
- function isValidCustomElementName(localName) {
- var reserved = reservedTagList.has(localName);
- var validForm = /^[a-z][.0-9_a-z]*-[\-.0-9_a-z]*$/.test(localName);
- return !reserved && validForm;
- }
-
- /**
- * @private
- * @param {!Node} node
- * @return {boolean}
- */
- function isConnected(node) {
- // Use `Node#isConnected`, if defined.
- var nativeValue = node.isConnected;
- if (nativeValue !== undefined) {
- return nativeValue;
- }
-
- /** @type {?Node|undefined} */
- var current = node;
- while (current && !(current.__CE_isImportDocument || current instanceof Document)) {
- current = current.parentNode || (window.ShadowRoot && current instanceof ShadowRoot ? current.host : undefined);
- }
- return !!(current && (current.__CE_isImportDocument || current instanceof Document));
- }
-
- /**
- * @param {!Node} root
- * @param {!Node} start
- * @return {?Node}
- */
- function nextSiblingOrAncestorSibling(root, start) {
- var node = start;
- while (node && node !== root && !node.nextSibling) {
- node = node.parentNode;
- }
- return !node || node === root ? null : node.nextSibling;
- }
-
- /**
- * @param {!Node} root
- * @param {!Node} start
- * @return {?Node}
- */
- function nextNode(root, start) {
- return start.firstChild ? start.firstChild : nextSiblingOrAncestorSibling(root, start);
- }
-
- /**
- * @param {!Node} root
- * @param {!function(!Element)} callback
- * @param {!Set<Node>=} visitedImports
- */
- function walkDeepDescendantElements(root, callback) {
- var visitedImports = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : new Set();
-
- var node = root;
- while (node) {
- if (node.nodeType === Node.ELEMENT_NODE) {
- var element = /** @type {!Element} */node;
-
- callback(element);
-
- var localName = element.localName;
- if (localName === 'link' && element.getAttribute('rel') === 'import') {
- // If this import (polyfilled or not) has it's root node available,
- // walk it.
- var importNode = /** @type {!Node} */element.import;
- if (importNode instanceof Node && !visitedImports.has(importNode)) {
- // Prevent multiple walks of the same import root.
- visitedImports.add(importNode);
-
- for (var child = importNode.firstChild; child; child = child.nextSibling) {
- walkDeepDescendantElements(child, callback, visitedImports);
- }
- }
-
- // Ignore descendants of import links to prevent attempting to walk the
- // elements created by the HTML Imports polyfill that we just walked
- // above.
- node = nextSiblingOrAncestorSibling(root, element);
- continue;
- } else if (localName === 'template') {
- // Ignore descendants of templates. There shouldn't be any descendants
- // because they will be moved into `.content` during construction in
- // browsers that support template but, in case they exist and are still
- // waiting to be moved by a polyfill, they will be ignored.
- node = nextSiblingOrAncestorSibling(root, element);
- continue;
- }
-
- // Walk shadow roots.
- var shadowRoot = element.__CE_shadowRoot;
- if (shadowRoot) {
- for (var _child = shadowRoot.firstChild; _child; _child = _child.nextSibling) {
- walkDeepDescendantElements(_child, callback, visitedImports);
- }
- }
- }
-
- node = nextNode(root, node);
- }
- }
-
- /**
- * Used to suppress Closure's "Modifying the prototype is only allowed if the
- * constructor is in the same scope" warning without using
- * `@suppress {newCheckTypes, duplicate}` because `newCheckTypes` is too broad.
- *
- * @param {!Object} destination
- * @param {string} name
- * @param {*} value
- */
- function setPropertyUnchecked(destination, name, value) {
- destination[name] = value;
- }
-
- /**
- * @enum {number}
- */
- var CustomElementState = {
- custom: 1,
- failed: 2
- };
-
- var CustomElementInternals = function () {
- function CustomElementInternals() {
- classCallCheck(this, CustomElementInternals);
-
- /** @type {!Map<string, !CustomElementDefinition>} */
- this._localNameToDefinition = new Map();
-
- /** @type {!Map<!Function, !CustomElementDefinition>} */
- this._constructorToDefinition = new Map();
-
- /** @type {!Array<!function(!Node)>} */
- this._patches = [];
-
- /** @type {boolean} */
- this._hasPatches = false;
- }
-
- /**
- * @param {string} localName
- * @param {!CustomElementDefinition} definition
- */
-
-
- createClass(CustomElementInternals, [{
- key: 'setDefinition',
- value: function setDefinition(localName, definition) {
- this._localNameToDefinition.set(localName, definition);
- this._constructorToDefinition.set(definition.constructor, definition);
- }
-
- /**
- * @param {string} localName
- * @return {!CustomElementDefinition|undefined}
- */
-
- }, {
- key: 'localNameToDefinition',
- value: function localNameToDefinition(localName) {
- return this._localNameToDefinition.get(localName);
- }
-
- /**
- * @param {!Function} constructor
- * @return {!CustomElementDefinition|undefined}
- */
-
- }, {
- key: 'constructorToDefinition',
- value: function constructorToDefinition(constructor) {
- return this._constructorToDefinition.get(constructor);
- }
-
- /**
- * @param {!function(!Node)} listener
- */
-
- }, {
- key: 'addPatch',
- value: function addPatch(listener) {
- this._hasPatches = true;
- this._patches.push(listener);
- }
-
- /**
- * @param {!Node} node
- */
-
- }, {
- key: 'patchTree',
- value: function patchTree(node) {
- var _this = this;
-
- if (!this._hasPatches) return;
-
- walkDeepDescendantElements(node, function (element) {
- return _this.patch(element);
- });
- }
-
- /**
- * @param {!Node} node
- */
-
- }, {
- key: 'patch',
- value: function patch(node) {
- if (!this._hasPatches) return;
-
- if (node.__CE_patched) return;
- node.__CE_patched = true;
-
- for (var i = 0; i < this._patches.length; i++) {
- this._patches[i](node);
- }
- }
-
- /**
- * @param {!Node} root
- */
-
- }, {
- key: 'connectTree',
- value: function connectTree(root) {
- var elements = [];
-
- walkDeepDescendantElements(root, function (element) {
- return elements.push(element);
- });
-
- for (var i = 0; i < elements.length; i++) {
- var element = elements[i];
- if (element.__CE_state === CustomElementState.custom) {
- if (isConnected(element)) {
- this.connectedCallback(element);
- }
- } else {
- this.upgradeElement(element);
- }
- }
- }
-
- /**
- * @param {!Node} root
- */
-
- }, {
- key: 'disconnectTree',
- value: function disconnectTree(root) {
- var elements = [];
-
- walkDeepDescendantElements(root, function (element) {
- return elements.push(element);
- });
-
- for (var i = 0; i < elements.length; i++) {
- var element = elements[i];
- if (element.__CE_state === CustomElementState.custom) {
- this.disconnectedCallback(element);
- }
- }
- }
-
- /**
- * Upgrades all uncustomized custom elements at and below a root node for
- * which there is a definition. When custom element reaction callbacks are
- * assumed to be called synchronously (which, by the current DOM / HTML spec
- * definitions, they are *not*), callbacks for both elements customized
- * synchronously by the parser and elements being upgraded occur in the same
- * relative order.
- *
- * NOTE: This function, when used to simulate the construction of a tree that
- * is already created but not customized (i.e. by the parser), does *not*
- * prevent the element from reading the 'final' (true) state of the tree. For
- * example, the element, during truly synchronous parsing / construction would
- * see that it contains no children as they have not yet been inserted.
- * However, this function does not modify the tree, the element will
- * (incorrectly) have children. Additionally, self-modification restrictions
- * for custom element constructors imposed by the DOM spec are *not* enforced.
- *
- *
- * The following nested list shows the steps extending down from the HTML
- * spec's parsing section that cause elements to be synchronously created and
- * upgraded:
- *
- * The "in body" insertion mode:
- * https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
- * - Switch on token:
- * .. other cases ..
- * -> Any other start tag
- * - [Insert an HTML element](below) for the token.
- *
- * Insert an HTML element:
- * https://html.spec.whatwg.org/multipage/syntax.html#insert-an-html-element
- * - Insert a foreign element for the token in the HTML namespace:
- * https://html.spec.whatwg.org/multipage/syntax.html#insert-a-foreign-element
- * - Create an element for a token:
- * https://html.spec.whatwg.org/multipage/syntax.html#create-an-element-for-the-token
- * - Will execute script flag is true?
- * - (Element queue pushed to the custom element reactions stack.)
- * - Create an element:
- * https://dom.spec.whatwg.org/#concept-create-element
- * - Sync CE flag is true?
- * - Constructor called.
- * - Self-modification restrictions enforced.
- * - Sync CE flag is false?
- * - (Upgrade reaction enqueued.)
- * - Attributes appended to element.
- * (`attributeChangedCallback` reactions enqueued.)
- * - Will execute script flag is true?
- * - (Element queue popped from the custom element reactions stack.
- * Reactions in the popped stack are invoked.)
- * - (Element queue pushed to the custom element reactions stack.)
- * - Insert the element:
- * https://dom.spec.whatwg.org/#concept-node-insert
- * - Shadow-including descendants are connected. During parsing
- * construction, there are no shadow-*excluding* descendants.
- * However, the constructor may have validly attached a shadow
- * tree to itself and added descendants to that shadow tree.
- * (`connectedCallback` reactions enqueued.)
- * - (Element queue popped from the custom element reactions stack.
- * Reactions in the popped stack are invoked.)
- *
- * @param {!Node} root
- * @param {!Set<Node>=} visitedImports
- */
-
- }, {
- key: 'patchAndUpgradeTree',
- value: function patchAndUpgradeTree(root) {
- var _this2 = this;
-
- var visitedImports = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Set();
-
- var elements = [];
-
- var gatherElements = function gatherElements(element) {
- if (element.localName === 'link' && element.getAttribute('rel') === 'import') {
- // The HTML Imports polyfill sets a descendant element of the link to
- // the `import` property, specifically this is *not* a Document.
- var importNode = /** @type {?Node} */element.import;
-
- if (importNode instanceof Node && importNode.readyState === 'complete') {
- importNode.__CE_isImportDocument = true;
-
- // Connected links are associated with the registry.
- importNode.__CE_hasRegistry = true;
- } else {
- // If this link's import root is not available, its contents can't be
- // walked. Wait for 'load' and walk it when it's ready.
- element.addEventListener('load', function () {
- var importNode = /** @type {!Node} */element.import;
-
- if (importNode.__CE_documentLoadHandled) return;
- importNode.__CE_documentLoadHandled = true;
-
- importNode.__CE_isImportDocument = true;
-
- // Connected links are associated with the registry.
- importNode.__CE_hasRegistry = true;
-
- // Clone the `visitedImports` set that was populated sync during
- // the `patchAndUpgradeTree` call that caused this 'load' handler to
- // be added. Then, remove *this* link's import node so that we can
- // walk that import again, even if it was partially walked later
- // during the same `patchAndUpgradeTree` call.
- visitedImports.delete(importNode);
-
- _this2.patchAndUpgradeTree(importNode, visitedImports);
- });
- }
- } else {
- elements.push(element);
- }
- };
-
- // `walkDeepDescendantElements` populates (and internally checks against)
- // `visitedImports` when traversing a loaded import.
- walkDeepDescendantElements(root, gatherElements, visitedImports);
-
- if (this._hasPatches) {
- for (var i = 0; i < elements.length; i++) {
- this.patch(elements[i]);
- }
- }
-
- for (var _i = 0; _i < elements.length; _i++) {
- this.upgradeElement(elements[_i]);
- }
- }
-
- /**
- * @param {!Element} element
- */
-
- }, {
- key: 'upgradeElement',
- value: function upgradeElement(element) {
- var currentState = element.__CE_state;
- if (currentState !== undefined) return;
-
- var definition = this.localNameToDefinition(element.localName);
- if (!definition) return;
-
- definition.constructionStack.push(element);
-
- var constructor = definition.constructor;
- try {
- try {
- var result = new constructor();
- if (result !== element) {
- throw new Error('The custom element constructor did not produce the element being upgraded.');
- }
- } finally {
- definition.constructionStack.pop();
- }
- } catch (e) {
- element.__CE_state = CustomElementState.failed;
- throw e;
- }
-
- element.__CE_state = CustomElementState.custom;
- element.__CE_definition = definition;
-
- if (definition.attributeChangedCallback) {
- var observedAttributes = definition.observedAttributes;
- for (var i = 0; i < observedAttributes.length; i++) {
- var name = observedAttributes[i];
- var value = element.getAttribute(name);
- if (value !== null) {
- this.attributeChangedCallback(element, name, null, value, null);
- }
- }
- }
-
- if (isConnected(element)) {
- this.connectedCallback(element);
- }
- }
-
- /**
- * @param {!Element} element
- */
-
- }, {
- key: 'connectedCallback',
- value: function connectedCallback(element) {
- var definition = element.__CE_definition;
- if (definition.connectedCallback) {
- definition.connectedCallback.call(element);
- }
-
- element.__CE_isConnectedCallbackCalled = true;
- }
-
- /**
- * @param {!Element} element
- */
-
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback(element) {
- if (!element.__CE_isConnectedCallbackCalled) {
- this.connectedCallback(element);
- }
-
- var definition = element.__CE_definition;
- if (definition.disconnectedCallback) {
- definition.disconnectedCallback.call(element);
- }
-
- element.__CE_isConnectedCallbackCalled = undefined;
- }
-
- /**
- * @param {!Element} element
- * @param {string} name
- * @param {?string} oldValue
- * @param {?string} newValue
- * @param {?string} namespace
- */
-
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(element, name, oldValue, newValue, namespace) {
- var definition = element.__CE_definition;
- if (definition.attributeChangedCallback && definition.observedAttributes.indexOf(name) > -1) {
- definition.attributeChangedCallback.call(element, name, oldValue, newValue, namespace);
- }
- }
- }]);
- return CustomElementInternals;
- }();
-
- var DocumentConstructionObserver = function () {
- function DocumentConstructionObserver(internals, doc) {
- classCallCheck(this, DocumentConstructionObserver);
-
- /**
- * @type {!CustomElementInternals}
- */
- this._internals = internals;
-
- /**
- * @type {!Document}
- */
- this._document = doc;
-
- /**
- * @type {MutationObserver|undefined}
- */
- this._observer = undefined;
-
- // Simulate tree construction for all currently accessible nodes in the
- // document.
- this._internals.patchAndUpgradeTree(this._document);
-
- if (this._document.readyState === 'loading') {
- this._observer = new MutationObserver(this._handleMutations.bind(this));
-
- // Nodes created by the parser are given to the observer *before* the next
- // task runs. Inline scripts are run in a new task. This means that the
- // observer will be able to handle the newly parsed nodes before the inline
- // script is run.
- this._observer.observe(this._document, {
- childList: true,
- subtree: true
- });
- }
- }
-
- createClass(DocumentConstructionObserver, [{
- key: 'disconnect',
- value: function disconnect() {
- if (this._observer) {
- this._observer.disconnect();
- }
- }
-
- /**
- * @param {!Array<!MutationRecord>} mutations
- */
-
- }, {
- key: '_handleMutations',
- value: function _handleMutations(mutations) {
- // Once the document's `readyState` is 'interactive' or 'complete', all new
- // nodes created within that document will be the result of script and
- // should be handled by patching.
- var readyState = this._document.readyState;
- if (readyState === 'interactive' || readyState === 'complete') {
- this.disconnect();
- }
-
- for (var i = 0; i < mutations.length; i++) {
- var addedNodes = mutations[i].addedNodes;
- for (var j = 0; j < addedNodes.length; j++) {
- var node = addedNodes[j];
- this._internals.patchAndUpgradeTree(node);
- }
- }
- }
- }]);
- return DocumentConstructionObserver;
- }();
-
- /**
- * @template T
- */
- var Deferred = function () {
- function Deferred() {
- var _this = this;
-
- classCallCheck(this, Deferred);
-
- /**
- * @private
- * @type {T|undefined}
- */
- this._value = undefined;
-
- /**
- * @private
- * @type {Function|undefined}
- */
- this._resolve = undefined;
-
- /**
- * @private
- * @type {!Promise<T>}
- */
- this._promise = new Promise(function (resolve) {
- _this._resolve = resolve;
-
- if (_this._value) {
- resolve(_this._value);
- }
- });
- }
-
- /**
- * @param {T} value
- */
-
-
- createClass(Deferred, [{
- key: 'resolve',
- value: function resolve(value) {
- if (this._value) {
- throw new Error('Already resolved.');
- }
-
- this._value = value;
-
- if (this._resolve) {
- this._resolve(value);
- }
- }
-
- /**
- * @return {!Promise<T>}
- */
-
- }, {
- key: 'toPromise',
- value: function toPromise() {
- return this._promise;
- }
- }]);
- return Deferred;
- }();
-
- /**
- * @unrestricted
- */
-
- var CustomElementRegistry = function () {
-
- /**
- * @param {!CustomElementInternals} internals
- */
- function CustomElementRegistry(internals) {
- classCallCheck(this, CustomElementRegistry);
-
- /**
- * @private
- * @type {boolean}
- */
- this._elementDefinitionIsRunning = false;
-
- /**
- * @private
- * @type {!CustomElementInternals}
- */
- this._internals = internals;
-
- /**
- * @private
- * @type {!Map<string, !Deferred<undefined>>}
- */
- this._whenDefinedDeferred = new Map();
-
- /**
- * The default flush callback triggers the document walk synchronously.
- * @private
- * @type {!Function}
- */
- this._flushCallback = function (fn) {
- return fn();
- };
-
- /**
- * @private
- * @type {boolean}
- */
- this._flushPending = false;
-
- /**
- * @private
- * @type {!Array<string>}
- */
- this._unflushedLocalNames = [];
-
- /**
- * @private
- * @type {!DocumentConstructionObserver}
- */
- this._documentConstructionObserver = new DocumentConstructionObserver(internals, document);
- }
-
- /**
- * @param {string} localName
- * @param {!Function} constructor
- */
-
-
- createClass(CustomElementRegistry, [{
- key: 'define',
- value: function define(localName, constructor) {
- var _this = this;
-
- if (!(constructor instanceof Function)) {
- throw new TypeError('Custom element constructors must be functions.');
- }
-
- if (!isValidCustomElementName(localName)) {
- throw new SyntaxError('The element name \'' + localName + '\' is not valid.');
- }
-
- if (this._internals.localNameToDefinition(localName)) {
- throw new Error('A custom element with name \'' + localName + '\' has already been defined.');
- }
-
- if (this._elementDefinitionIsRunning) {
- throw new Error('A custom element is already being defined.');
- }
- this._elementDefinitionIsRunning = true;
-
- var connectedCallback = void 0;
- var disconnectedCallback = void 0;
- var adoptedCallback = void 0;
- var attributeChangedCallback = void 0;
- var observedAttributes = void 0;
- try {
- var getCallback = function getCallback(name) {
- var callbackValue = prototype[name];
- if (callbackValue !== undefined && !(callbackValue instanceof Function)) {
- throw new Error('The \'' + name + '\' callback must be a function.');
- }
- return callbackValue;
- };
-
- /** @type {!Object} */
- var prototype = constructor.prototype;
- if (!(prototype instanceof Object)) {
- throw new TypeError('The custom element constructor\'s prototype is not an object.');
- }
-
- connectedCallback = getCallback('connectedCallback');
- disconnectedCallback = getCallback('disconnectedCallback');
- adoptedCallback = getCallback('adoptedCallback');
- attributeChangedCallback = getCallback('attributeChangedCallback');
- observedAttributes = constructor['observedAttributes'] || [];
- } catch (e) {
- return;
- } finally {
- this._elementDefinitionIsRunning = false;
- }
-
- var definition = {
- localName: localName,
- constructor: constructor,
- connectedCallback: connectedCallback,
- disconnectedCallback: disconnectedCallback,
- adoptedCallback: adoptedCallback,
- attributeChangedCallback: attributeChangedCallback,
- observedAttributes: observedAttributes,
- constructionStack: []
- };
-
- this._internals.setDefinition(localName, definition);
-
- this._unflushedLocalNames.push(localName);
-
- // If we've already called the flush callback and it hasn't called back yet,
- // don't call it again.
- if (!this._flushPending) {
- this._flushPending = true;
- this._flushCallback(function () {
- return _this._flush();
- });
- }
- }
- }, {
- key: '_flush',
- value: function _flush() {
- // If no new definitions were defined, don't attempt to flush. This could
- // happen if a flush callback keeps the function it is given and calls it
- // multiple times.
- if (this._flushPending === false) return;
-
- this._flushPending = false;
- this._internals.patchAndUpgradeTree(document);
-
- while (this._unflushedLocalNames.length > 0) {
- var localName = this._unflushedLocalNames.shift();
- var deferred = this._whenDefinedDeferred.get(localName);
- if (deferred) {
- deferred.resolve(undefined);
- }
- }
- }
-
- /**
- * @param {string} localName
- * @return {Function|undefined}
- */
-
- }, {
- key: 'get',
- value: function get$$1(localName) {
- var definition = this._internals.localNameToDefinition(localName);
- if (definition) {
- return definition.constructor;
- }
-
- return undefined;
- }
-
- /**
- * @param {string} localName
- * @return {!Promise<undefined>}
- */
-
- }, {
- key: 'whenDefined',
- value: function whenDefined(localName) {
- if (!isValidCustomElementName(localName)) {
- return Promise.reject(new SyntaxError('\'' + localName + '\' is not a valid custom element name.'));
- }
-
- var prior = this._whenDefinedDeferred.get(localName);
- if (prior) {
- return prior.toPromise();
- }
-
- var deferred = new Deferred();
- this._whenDefinedDeferred.set(localName, deferred);
-
- var definition = this._internals.localNameToDefinition(localName);
- // Resolve immediately only if the given local name has a definition *and*
- // the full document walk to upgrade elements with that local name has
- // already happened.
- if (definition && this._unflushedLocalNames.indexOf(localName) === -1) {
- deferred.resolve(undefined);
- }
-
- return deferred.toPromise();
- }
- }, {
- key: 'polyfillWrapFlushCallback',
- value: function polyfillWrapFlushCallback(outer) {
- this._documentConstructionObserver.disconnect();
- var inner = this._flushCallback;
- this._flushCallback = function (flush) {
- return outer(function () {
- return inner(flush);
- });
- };
- }
- }]);
- return CustomElementRegistry;
- }();
-
- window['CustomElementRegistry'] = CustomElementRegistry;
- CustomElementRegistry.prototype['define'] = CustomElementRegistry.prototype.define;
- CustomElementRegistry.prototype['get'] = CustomElementRegistry.prototype.get;
- CustomElementRegistry.prototype['whenDefined'] = CustomElementRegistry.prototype.whenDefined;
- CustomElementRegistry.prototype['polyfillWrapFlushCallback'] = CustomElementRegistry.prototype.polyfillWrapFlushCallback;
-
- var Native = {
- Document_createElement: window.Document.prototype.createElement,
- Document_createElementNS: window.Document.prototype.createElementNS,
- Document_importNode: window.Document.prototype.importNode,
- Document_prepend: window.Document.prototype['prepend'],
- Document_append: window.Document.prototype['append'],
- Node_cloneNode: window.Node.prototype.cloneNode,
- Node_appendChild: window.Node.prototype.appendChild,
- Node_insertBefore: window.Node.prototype.insertBefore,
- Node_removeChild: window.Node.prototype.removeChild,
- Node_replaceChild: window.Node.prototype.replaceChild,
- Node_textContent: Object.getOwnPropertyDescriptor(window.Node.prototype, 'textContent'),
- Element_attachShadow: window.Element.prototype['attachShadow'],
- Element_innerHTML: Object.getOwnPropertyDescriptor(window.Element.prototype, 'innerHTML'),
- Element_getAttribute: window.Element.prototype.getAttribute,
- Element_setAttribute: window.Element.prototype.setAttribute,
- Element_removeAttribute: window.Element.prototype.removeAttribute,
- Element_getAttributeNS: window.Element.prototype.getAttributeNS,
- Element_setAttributeNS: window.Element.prototype.setAttributeNS,
- Element_removeAttributeNS: window.Element.prototype.removeAttributeNS,
- Element_insertAdjacentElement: window.Element.prototype['insertAdjacentElement'],
- Element_prepend: window.Element.prototype['prepend'],
- Element_append: window.Element.prototype['append'],
- Element_before: window.Element.prototype['before'],
- Element_after: window.Element.prototype['after'],
- Element_replaceWith: window.Element.prototype['replaceWith'],
- Element_remove: window.Element.prototype['remove'],
- HTMLElement: window.HTMLElement,
- HTMLElement_innerHTML: Object.getOwnPropertyDescriptor(window.HTMLElement.prototype, 'innerHTML'),
- HTMLElement_insertAdjacentElement: window.HTMLElement.prototype['insertAdjacentElement']
- };
-
- /**
- * This class exists only to work around Closure's lack of a way to describe
- * singletons. It represents the 'already constructed marker' used in custom
- * element construction stacks.
- *
- * https://html.spec.whatwg.org/#concept-already-constructed-marker
- */
- var AlreadyConstructedMarker = function AlreadyConstructedMarker() {
- classCallCheck(this, AlreadyConstructedMarker);
- };
-
- var AlreadyConstructedMarker$1 = new AlreadyConstructedMarker();
-
- /**
- * @param {!CustomElementInternals} internals
- */
- var PatchHTMLElement = function (internals) {
- window['HTMLElement'] = function () {
- /**
- * @type {function(new: HTMLElement): !HTMLElement}
- */
- function HTMLElement() {
- // This should really be `new.target` but `new.target` can't be emulated
- // in ES5. Assuming the user keeps the default value of the constructor's
- // prototype's `constructor` property, this is equivalent.
- /** @type {!Function} */
- var constructor = this.constructor;
-
- var definition = internals.constructorToDefinition(constructor);
- if (!definition) {
- throw new Error('The custom element being constructed was not registered with `customElements`.');
- }
-
- var constructionStack = definition.constructionStack;
-
- if (constructionStack.length === 0) {
- var _element = Native.Document_createElement.call(document, definition.localName);
- Object.setPrototypeOf(_element, constructor.prototype);
- _element.__CE_state = CustomElementState.custom;
- _element.__CE_definition = definition;
- internals.patch(_element);
- return _element;
- }
-
- var lastIndex = constructionStack.length - 1;
- var element = constructionStack[lastIndex];
- if (element === AlreadyConstructedMarker$1) {
- throw new Error('The HTMLElement constructor was either called reentrantly for this constructor or called multiple times.');
- }
- constructionStack[lastIndex] = AlreadyConstructedMarker$1;
-
- Object.setPrototypeOf(element, constructor.prototype);
- internals.patch( /** @type {!HTMLElement} */element);
-
- return element;
- }
-
- HTMLElement.prototype = Native.HTMLElement.prototype;
-
- return HTMLElement;
- }();
- };
-
- /**
- * @param {!CustomElementInternals} internals
- * @param {!Object} destination
- * @param {!ParentNodeNativeMethods} builtIn
- */
- var PatchParentNode = function (internals, destination, builtIn) {
- /**
- * @param {...(!Node|string)} nodes
- */
- destination['prepend'] = function () {
- for (var _len = arguments.length, nodes = Array(_len), _key = 0; _key < _len; _key++) {
- nodes[_key] = arguments[_key];
- }
-
- // TODO: Fix this for when one of `nodes` is a DocumentFragment!
- var connectedBefore = /** @type {!Array<!Node>} */nodes.filter(function (node) {
- // DocumentFragments are not connected and will not be added to the list.
- return node instanceof Node && isConnected(node);
- });
-
- builtIn.prepend.apply(this, nodes);
-
- for (var i = 0; i < connectedBefore.length; i++) {
- internals.disconnectTree(connectedBefore[i]);
- }
-
- if (isConnected(this)) {
- for (var _i = 0; _i < nodes.length; _i++) {
- var node = nodes[_i];
- if (node instanceof Element) {
- internals.connectTree(node);
- }
- }
- }
- };
-
- /**
- * @param {...(!Node|string)} nodes
- */
- destination['append'] = function () {
- for (var _len2 = arguments.length, nodes = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
- nodes[_key2] = arguments[_key2];
- }
-
- // TODO: Fix this for when one of `nodes` is a DocumentFragment!
- var connectedBefore = /** @type {!Array<!Node>} */nodes.filter(function (node) {
- // DocumentFragments are not connected and will not be added to the list.
- return node instanceof Node && isConnected(node);
- });
-
- builtIn.append.apply(this, nodes);
-
- for (var i = 0; i < connectedBefore.length; i++) {
- internals.disconnectTree(connectedBefore[i]);
- }
-
- if (isConnected(this)) {
- for (var _i2 = 0; _i2 < nodes.length; _i2++) {
- var node = nodes[_i2];
- if (node instanceof Element) {
- internals.connectTree(node);
- }
- }
- }
- };
- };
-
- /**
- * @param {!CustomElementInternals} internals
- */
- var PatchDocument = function (internals) {
- setPropertyUnchecked(Document.prototype, 'createElement',
- /**
- * @this {Document}
- * @param {string} localName
- * @return {!Element}
- */
- function (localName) {
- // Only create custom elements if this document is associated with the registry.
- if (this.__CE_hasRegistry) {
- var definition = internals.localNameToDefinition(localName);
- if (definition) {
- return new definition.constructor();
- }
- }
-
- var result = /** @type {!Element} */
- Native.Document_createElement.call(this, localName);
- internals.patch(result);
- return result;
- });
-
- setPropertyUnchecked(Document.prototype, 'importNode',
- /**
- * @this {Document}
- * @param {!Node} node
- * @param {boolean=} deep
- * @return {!Node}
- */
- function (node, deep) {
- var clone = Native.Document_importNode.call(this, node, deep);
- // Only create custom elements if this document is associated with the registry.
- if (!this.__CE_hasRegistry) {
- internals.patchTree(clone);
- } else {
- internals.patchAndUpgradeTree(clone);
- }
- return clone;
- });
-
- var NS_HTML = "http://www.w3.org/1999/xhtml";
-
- setPropertyUnchecked(Document.prototype, 'createElementNS',
- /**
- * @this {Document}
- * @param {?string} namespace
- * @param {string} localName
- * @return {!Element}
- */
- function (namespace, localName) {
- // Only create custom elements if this document is associated with the registry.
- if (this.__CE_hasRegistry && (namespace === null || namespace === NS_HTML)) {
- var definition = internals.localNameToDefinition(localName);
- if (definition) {
- return new definition.constructor();
- }
- }
-
- var result = /** @type {!Element} */
- Native.Document_createElementNS.call(this, namespace, localName);
- internals.patch(result);
- return result;
- });
-
- PatchParentNode(internals, Document.prototype, {
- prepend: Native.Document_prepend,
- append: Native.Document_append
- });
- };
-
- /**
- * @param {!CustomElementInternals} internals
- */
- var PatchNode = function (internals) {
- // `Node#nodeValue` is implemented on `Attr`.
- // `Node#textContent` is implemented on `Attr`, `Element`.
-
- setPropertyUnchecked(Node.prototype, 'insertBefore',
- /**
- * @this {Node}
- * @param {!Node} node
- * @param {?Node} refNode
- * @return {!Node}
- */
- function (node, refNode) {
- if (node instanceof DocumentFragment) {
- var insertedNodes = Array.prototype.slice.apply(node.childNodes);
- var _nativeResult = Native.Node_insertBefore.call(this, node, refNode);
-
- // DocumentFragments can't be connected, so `disconnectTree` will never
- // need to be called on a DocumentFragment's children after inserting it.
-
- if (isConnected(this)) {
- for (var i = 0; i < insertedNodes.length; i++) {
- internals.connectTree(insertedNodes[i]);
- }
- }
-
- return _nativeResult;
- }
-
- var nodeWasConnected = isConnected(node);
- var nativeResult = Native.Node_insertBefore.call(this, node, refNode);
-
- if (nodeWasConnected) {
- internals.disconnectTree(node);
- }
-
- if (isConnected(this)) {
- internals.connectTree(node);
- }
-
- return nativeResult;
- });
-
- setPropertyUnchecked(Node.prototype, 'appendChild',
- /**
- * @this {Node}
- * @param {!Node} node
- * @return {!Node}
- */
- function (node) {
- if (node instanceof DocumentFragment) {
- var insertedNodes = Array.prototype.slice.apply(node.childNodes);
- var _nativeResult2 = Native.Node_appendChild.call(this, node);
-
- // DocumentFragments can't be connected, so `disconnectTree` will never
- // need to be called on a DocumentFragment's children after inserting it.
-
- if (isConnected(this)) {
- for (var i = 0; i < insertedNodes.length; i++) {
- internals.connectTree(insertedNodes[i]);
- }
- }
-
- return _nativeResult2;
- }
-
- var nodeWasConnected = isConnected(node);
- var nativeResult = Native.Node_appendChild.call(this, node);
-
- if (nodeWasConnected) {
- internals.disconnectTree(node);
- }
-
- if (isConnected(this)) {
- internals.connectTree(node);
- }
-
- return nativeResult;
- });
-
- setPropertyUnchecked(Node.prototype, 'cloneNode',
- /**
- * @this {Node}
- * @param {boolean=} deep
- * @return {!Node}
- */
- function (deep) {
- var clone = Native.Node_cloneNode.call(this, deep);
- // Only create custom elements if this element's owner document is
- // associated with the registry.
- if (!this.ownerDocument.__CE_hasRegistry) {
- internals.patchTree(clone);
- } else {
- internals.patchAndUpgradeTree(clone);
- }
- return clone;
- });
-
- setPropertyUnchecked(Node.prototype, 'removeChild',
- /**
- * @this {Node}
- * @param {!Node} node
- * @return {!Node}
- */
- function (node) {
- var nodeWasConnected = isConnected(node);
- var nativeResult = Native.Node_removeChild.call(this, node);
-
- if (nodeWasConnected) {
- internals.disconnectTree(node);
- }
-
- return nativeResult;
- });
-
- setPropertyUnchecked(Node.prototype, 'replaceChild',
- /**
- * @this {Node}
- * @param {!Node} nodeToInsert
- * @param {!Node} nodeToRemove
- * @return {!Node}
- */
- function (nodeToInsert, nodeToRemove) {
- if (nodeToInsert instanceof DocumentFragment) {
- var insertedNodes = Array.prototype.slice.apply(nodeToInsert.childNodes);
- var _nativeResult3 = Native.Node_replaceChild.call(this, nodeToInsert, nodeToRemove);
-
- // DocumentFragments can't be connected, so `disconnectTree` will never
- // need to be called on a DocumentFragment's children after inserting it.
-
- if (isConnected(this)) {
- internals.disconnectTree(nodeToRemove);
- for (var i = 0; i < insertedNodes.length; i++) {
- internals.connectTree(insertedNodes[i]);
- }
- }
-
- return _nativeResult3;
- }
-
- var nodeToInsertWasConnected = isConnected(nodeToInsert);
- var nativeResult = Native.Node_replaceChild.call(this, nodeToInsert, nodeToRemove);
- var thisIsConnected = isConnected(this);
-
- if (thisIsConnected) {
- internals.disconnectTree(nodeToRemove);
- }
-
- if (nodeToInsertWasConnected) {
- internals.disconnectTree(nodeToInsert);
- }
-
- if (thisIsConnected) {
- internals.connectTree(nodeToInsert);
- }
-
- return nativeResult;
- });
-
- function patch_textContent(destination, baseDescriptor) {
- Object.defineProperty(destination, 'textContent', {
- enumerable: baseDescriptor.enumerable,
- configurable: true,
- get: baseDescriptor.get,
- set: /** @this {Node} */function set(assignedValue) {
- // If this is a text node then there are no nodes to disconnect.
- if (this.nodeType === Node.TEXT_NODE) {
- baseDescriptor.set.call(this, assignedValue);
- return;
- }
-
- var removedNodes = undefined;
- // Checking for `firstChild` is faster than reading `childNodes.length`
- // to compare with 0.
- if (this.firstChild) {
- // Using `childNodes` is faster than `children`, even though we only
- // care about elements.
- var childNodes = this.childNodes;
- var childNodesLength = childNodes.length;
- if (childNodesLength > 0 && isConnected(this)) {
- // Copying an array by iterating is faster than using slice.
- removedNodes = new Array(childNodesLength);
- for (var i = 0; i < childNodesLength; i++) {
- removedNodes[i] = childNodes[i];
- }
- }
- }
-
- baseDescriptor.set.call(this, assignedValue);
-
- if (removedNodes) {
- for (var _i = 0; _i < removedNodes.length; _i++) {
- internals.disconnectTree(removedNodes[_i]);
- }
- }
- }
- });
- }
-
- if (Native.Node_textContent && Native.Node_textContent.get) {
- patch_textContent(Node.prototype, Native.Node_textContent);
- } else {
- internals.addPatch(function (element) {
- patch_textContent(element, {
- enumerable: true,
- configurable: true,
- // NOTE: This implementation of the `textContent` getter assumes that
- // text nodes' `textContent` getter will not be patched.
- get: /** @this {Node} */function get() {
- /** @type {!Array<string>} */
- var parts = [];
-
- for (var i = 0; i < this.childNodes.length; i++) {
- parts.push(this.childNodes[i].textContent);
- }
-
- return parts.join('');
- },
- set: /** @this {Node} */function set(assignedValue) {
- while (this.firstChild) {
- Native.Node_removeChild.call(this, this.firstChild);
- }
- Native.Node_appendChild.call(this, document.createTextNode(assignedValue));
- }
- });
- });
- }
- };
-
- /**
- * @param {!CustomElementInternals} internals
- * @param {!Object} destination
- * @param {!ChildNodeNativeMethods} builtIn
- */
- var PatchChildNode = function (internals, destination, builtIn) {
- /**
- * @param {...(!Node|string)} nodes
- */
- destination['before'] = function () {
- for (var _len = arguments.length, nodes = Array(_len), _key = 0; _key < _len; _key++) {
- nodes[_key] = arguments[_key];
- }
-
- // TODO: Fix this for when one of `nodes` is a DocumentFragment!
- var connectedBefore = /** @type {!Array<!Node>} */nodes.filter(function (node) {
- // DocumentFragments are not connected and will not be added to the list.
- return node instanceof Node && isConnected(node);
- });
-
- builtIn.before.apply(this, nodes);
-
- for (var i = 0; i < connectedBefore.length; i++) {
- internals.disconnectTree(connectedBefore[i]);
- }
-
- if (isConnected(this)) {
- for (var _i = 0; _i < nodes.length; _i++) {
- var node = nodes[_i];
- if (node instanceof Element) {
- internals.connectTree(node);
- }
- }
- }
- };
-
- /**
- * @param {...(!Node|string)} nodes
- */
- destination['after'] = function () {
- for (var _len2 = arguments.length, nodes = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
- nodes[_key2] = arguments[_key2];
- }
-
- // TODO: Fix this for when one of `nodes` is a DocumentFragment!
- var connectedBefore = /** @type {!Array<!Node>} */nodes.filter(function (node) {
- // DocumentFragments are not connected and will not be added to the list.
- return node instanceof Node && isConnected(node);
- });
-
- builtIn.after.apply(this, nodes);
-
- for (var i = 0; i < connectedBefore.length; i++) {
- internals.disconnectTree(connectedBefore[i]);
- }
-
- if (isConnected(this)) {
- for (var _i2 = 0; _i2 < nodes.length; _i2++) {
- var node = nodes[_i2];
- if (node instanceof Element) {
- internals.connectTree(node);
- }
- }
- }
- };
-
- /**
- * @param {...(!Node|string)} nodes
- */
- destination['replaceWith'] = function () {
- for (var _len3 = arguments.length, nodes = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
- nodes[_key3] = arguments[_key3];
- }
-
- // TODO: Fix this for when one of `nodes` is a DocumentFragment!
- var connectedBefore = /** @type {!Array<!Node>} */nodes.filter(function (node) {
- // DocumentFragments are not connected and will not be added to the list.
- return node instanceof Node && isConnected(node);
- });
-
- var wasConnected = isConnected(this);
-
- builtIn.replaceWith.apply(this, nodes);
-
- for (var i = 0; i < connectedBefore.length; i++) {
- internals.disconnectTree(connectedBefore[i]);
- }
-
- if (wasConnected) {
- internals.disconnectTree(this);
- for (var _i3 = 0; _i3 < nodes.length; _i3++) {
- var node = nodes[_i3];
- if (node instanceof Element) {
- internals.connectTree(node);
- }
- }
- }
- };
-
- destination['remove'] = function () {
- var wasConnected = isConnected(this);
-
- builtIn.remove.call(this);
-
- if (wasConnected) {
- internals.disconnectTree(this);
- }
- };
- };
-
- /**
- * @param {!CustomElementInternals} internals
- */
- var PatchElement = function (internals) {
- if (Native.Element_attachShadow) {
- setPropertyUnchecked(Element.prototype, 'attachShadow',
- /**
- * @this {Element}
- * @param {!{mode: string}} init
- * @return {ShadowRoot}
- */
- function (init) {
- var shadowRoot = Native.Element_attachShadow.call(this, init);
- this.__CE_shadowRoot = shadowRoot;
- return shadowRoot;
- });
- } else {
- console.warn('Custom Elements: `Element#attachShadow` was not patched.');
- }
-
- function patch_innerHTML(destination, baseDescriptor) {
- Object.defineProperty(destination, 'innerHTML', {
- enumerable: baseDescriptor.enumerable,
- configurable: true,
- get: baseDescriptor.get,
- set: /** @this {Element} */function set(htmlString) {
- var _this = this;
-
- var isConnected$$1 = isConnected(this);
-
- // NOTE: In IE11, when using the native `innerHTML` setter, all nodes
- // that were previously descendants of the context element have all of
- // their children removed as part of the set - the entire subtree is
- // 'disassembled'. This work around walks the subtree *before* using the
- // native setter.
- /** @type {!Array<!Element>|undefined} */
- var removedElements = undefined;
- if (isConnected$$1) {
- removedElements = [];
- walkDeepDescendantElements(this, function (element) {
- if (element !== _this) {
- removedElements.push(element);
- }
- });
- }
-
- baseDescriptor.set.call(this, htmlString);
-
- if (removedElements) {
- for (var i = 0; i < removedElements.length; i++) {
- var element = removedElements[i];
- if (element.__CE_state === CustomElementState.custom) {
- internals.disconnectedCallback(element);
- }
- }
- }
-
- // Only create custom elements if this element's owner document is
- // associated with the registry.
- if (!this.ownerDocument.__CE_hasRegistry) {
- internals.patchTree(this);
- } else {
- internals.patchAndUpgradeTree(this);
- }
- return htmlString;
- }
- });
- }
-
- if (Native.Element_innerHTML && Native.Element_innerHTML.get) {
- patch_innerHTML(Element.prototype, Native.Element_innerHTML);
- } else if (Native.HTMLElement_innerHTML && Native.HTMLElement_innerHTML.get) {
- patch_innerHTML(HTMLElement.prototype, Native.HTMLElement_innerHTML);
- } else {
-
- /** @type {HTMLDivElement} */
- var rawDiv = Native.Document_createElement.call(document, 'div');
-
- internals.addPatch(function (element) {
- patch_innerHTML(element, {
- enumerable: true,
- configurable: true,
- // Implements getting `innerHTML` by performing an unpatched `cloneNode`
- // of the element and returning the resulting element's `innerHTML`.
- // TODO: Is this too expensive?
- get: /** @this {Element} */function get() {
- return Native.Node_cloneNode.call(this, true).innerHTML;
- },
- // Implements setting `innerHTML` by creating an unpatched element,
- // setting `innerHTML` of that element and replacing the target
- // element's children with those of the unpatched element.
- set: /** @this {Element} */function set(assignedValue) {
- // NOTE: re-route to `content` for `template` elements.
- // We need to do this because `template.appendChild` does not
- // route into `template.content`.
- /** @type {!Node} */
- var content = this.localName === 'template' ? /** @type {!HTMLTemplateElement} */this.content : this;
- rawDiv.innerHTML = assignedValue;
-
- while (content.childNodes.length > 0) {
- Native.Node_removeChild.call(content, content.childNodes[0]);
- }
- while (rawDiv.childNodes.length > 0) {
- Native.Node_appendChild.call(content, rawDiv.childNodes[0]);
- }
- }
- });
- });
- }
-
- setPropertyUnchecked(Element.prototype, 'setAttribute',
- /**
- * @this {Element}
- * @param {string} name
- * @param {string} newValue
- */
- function (name, newValue) {
- // Fast path for non-custom elements.
- if (this.__CE_state !== CustomElementState.custom) {
- return Native.Element_setAttribute.call(this, name, newValue);
- }
-
- var oldValue = Native.Element_getAttribute.call(this, name);
- Native.Element_setAttribute.call(this, name, newValue);
- newValue = Native.Element_getAttribute.call(this, name);
- internals.attributeChangedCallback(this, name, oldValue, newValue, null);
- });
-
- setPropertyUnchecked(Element.prototype, 'setAttributeNS',
- /**
- * @this {Element}
- * @param {?string} namespace
- * @param {string} name
- * @param {string} newValue
- */
- function (namespace, name, newValue) {
- // Fast path for non-custom elements.
- if (this.__CE_state !== CustomElementState.custom) {
- return Native.Element_setAttributeNS.call(this, namespace, name, newValue);
- }
-
- var oldValue = Native.Element_getAttributeNS.call(this, namespace, name);
- Native.Element_setAttributeNS.call(this, namespace, name, newValue);
- newValue = Native.Element_getAttributeNS.call(this, namespace, name);
- internals.attributeChangedCallback(this, name, oldValue, newValue, namespace);
- });
-
- setPropertyUnchecked(Element.prototype, 'removeAttribute',
- /**
- * @this {Element}
- * @param {string} name
- */
- function (name) {
- // Fast path for non-custom elements.
- if (this.__CE_state !== CustomElementState.custom) {
- return Native.Element_removeAttribute.call(this, name);
- }
-
- var oldValue = Native.Element_getAttribute.call(this, name);
- Native.Element_removeAttribute.call(this, name);
- if (oldValue !== null) {
- internals.attributeChangedCallback(this, name, oldValue, null, null);
- }
- });
-
- setPropertyUnchecked(Element.prototype, 'removeAttributeNS',
- /**
- * @this {Element}
- * @param {?string} namespace
- * @param {string} name
- */
- function (namespace, name) {
- // Fast path for non-custom elements.
- if (this.__CE_state !== CustomElementState.custom) {
- return Native.Element_removeAttributeNS.call(this, namespace, name);
- }
-
- var oldValue = Native.Element_getAttributeNS.call(this, namespace, name);
- Native.Element_removeAttributeNS.call(this, namespace, name);
- // In older browsers, `Element#getAttributeNS` may return the empty string
- // instead of null if the attribute does not exist. For details, see;
- // https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttributeNS#Notes
- var newValue = Native.Element_getAttributeNS.call(this, namespace, name);
- if (oldValue !== newValue) {
- internals.attributeChangedCallback(this, name, oldValue, newValue, namespace);
- }
- });
-
- function patch_insertAdjacentElement(destination, baseMethod) {
- setPropertyUnchecked(destination, 'insertAdjacentElement',
- /**
- * @this {Element}
- * @param {string} where
- * @param {!Element} element
- * @return {?Element}
- */
- function (where, element) {
- var wasConnected = isConnected(element);
- var insertedElement = /** @type {!Element} */
- baseMethod.call(this, where, element);
-
- if (wasConnected) {
- internals.disconnectTree(element);
- }
-
- if (isConnected(insertedElement)) {
- internals.connectTree(element);
- }
- return insertedElement;
- });
- }
-
- if (Native.HTMLElement_insertAdjacentElement) {
- patch_insertAdjacentElement(HTMLElement.prototype, Native.HTMLElement_insertAdjacentElement);
- } else if (Native.Element_insertAdjacentElement) {
- patch_insertAdjacentElement(Element.prototype, Native.Element_insertAdjacentElement);
- } else {
- console.warn('Custom Elements: `Element#insertAdjacentElement` was not patched.');
- }
-
- PatchParentNode(internals, Element.prototype, {
- prepend: Native.Element_prepend,
- append: Native.Element_append
- });
-
- PatchChildNode(internals, Element.prototype, {
- before: Native.Element_before,
- after: Native.Element_after,
- replaceWith: Native.Element_replaceWith,
- remove: Native.Element_remove
- });
- };
-
- /**
- * @license
- * Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
- * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
- * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
- * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
- * Code distributed by Google as part of the polymer project is also
- * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
- */
-
- var priorCustomElements = window['customElements'];
-
- if (!priorCustomElements || priorCustomElements['forcePolyfill'] || typeof priorCustomElements['define'] != 'function' || typeof priorCustomElements['get'] != 'function') {
- /** @type {!CustomElementInternals} */
- var internals = new CustomElementInternals();
-
- PatchHTMLElement(internals);
- PatchDocument(internals);
- PatchNode(internals);
- PatchElement(internals);
-
- // The main document is always associated with the registry.
- document.__CE_hasRegistry = true;
-
- /** @type {!CustomElementRegistry} */
- var customElements$1 = new CustomElementRegistry(internals);
-
- Object.defineProperty(window, 'customElements', {
- configurable: true,
- enumerable: true,
- value: customElements$1
- });
- }
-
- /**
- * @license
- * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
- * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
- * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
- * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
- * Code distributed by Google as part of the polymer project is also
- * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
- */
- // @version 0.7.22
-
- (function (global) {
- if (global.JsMutationObserver) {
- return;
- }
- var registrationsTable = new WeakMap();
- var setImmediate;
- if (/Trident|Edge/.test(navigator.userAgent)) {
- setImmediate = setTimeout;
- } else if (window.setImmediate) {
- setImmediate = window.setImmediate;
- } else {
- var setImmediateQueue = [];
- var sentinel = String(Math.random());
- window.addEventListener("message", function (e) {
- if (e.data === sentinel) {
- var queue = setImmediateQueue;
- setImmediateQueue = [];
- queue.forEach(function (func) {
- func();
- });
- }
- });
- setImmediate = function setImmediate(func) {
- setImmediateQueue.push(func);
- window.postMessage(sentinel, "*");
- };
- }
- var isScheduled = false;
- var scheduledObservers = [];
- function scheduleCallback(observer) {
- scheduledObservers.push(observer);
- if (!isScheduled) {
- isScheduled = true;
- setImmediate(dispatchCallbacks);
- }
- }
- function wrapIfNeeded(node) {
- return window.ShadowDOMPolyfill && window.ShadowDOMPolyfill.wrapIfNeeded(node) || node;
- }
- function dispatchCallbacks() {
- isScheduled = false;
- var observers = scheduledObservers;
- scheduledObservers = [];
- observers.sort(function (o1, o2) {
- return o1.uid_ - o2.uid_;
- });
- var anyNonEmpty = false;
- observers.forEach(function (observer) {
- var queue = observer.takeRecords();
- removeTransientObserversFor(observer);
- if (queue.length) {
- observer.callback_(queue, observer);
- anyNonEmpty = true;
- }
- });
- if (anyNonEmpty) dispatchCallbacks();
- }
- function removeTransientObserversFor(observer) {
- observer.nodes_.forEach(function (node) {
- var registrations = registrationsTable.get(node);
- if (!registrations) return;
- registrations.forEach(function (registration) {
- if (registration.observer === observer) registration.removeTransientObservers();
- });
- });
- }
- function forEachAncestorAndObserverEnqueueRecord(target, callback) {
- for (var node = target; node; node = node.parentNode) {
- var registrations = registrationsTable.get(node);
- if (registrations) {
- for (var j = 0; j < registrations.length; j++) {
- var registration = registrations[j];
- var options = registration.options;
- if (node !== target && !options.subtree) continue;
- var record = callback(options);
- if (record) registration.enqueue(record);
- }
- }
- }
- }
- var uidCounter = 0;
- function JsMutationObserver(callback) {
- this.callback_ = callback;
- this.nodes_ = [];
- this.records_ = [];
- this.uid_ = ++uidCounter;
- }
- JsMutationObserver.prototype = {
- observe: function observe(target, options) {
- target = wrapIfNeeded(target);
- if (!options.childList && !options.attributes && !options.characterData || options.attributeOldValue && !options.attributes || options.attributeFilter && options.attributeFilter.length && !options.attributes || options.characterDataOldValue && !options.characterData) {
- throw new SyntaxError();
- }
- var registrations = registrationsTable.get(target);
- if (!registrations) registrationsTable.set(target, registrations = []);
- var registration;
- for (var i = 0; i < registrations.length; i++) {
- if (registrations[i].observer === this) {
- registration = registrations[i];
- registration.removeListeners();
- registration.options = options;
- break;
- }
- }
- if (!registration) {
- registration = new Registration(this, target, options);
- registrations.push(registration);
- this.nodes_.push(target);
- }
- registration.addListeners();
- },
- disconnect: function disconnect() {
- this.nodes_.forEach(function (node) {
- var registrations = registrationsTable.get(node);
- for (var i = 0; i < registrations.length; i++) {
- var registration = registrations[i];
- if (registration.observer === this) {
- registration.removeListeners();
- registrations.splice(i, 1);
- break;
- }
- }
- }, this);
- this.records_ = [];
- },
- takeRecords: function takeRecords() {
- var copyOfRecords = this.records_;
- this.records_ = [];
- return copyOfRecords;
- }
- };
- function MutationRecord(type, target) {
- this.type = type;
- this.target = target;
- this.addedNodes = [];
- this.removedNodes = [];
- this.previousSibling = null;
- this.nextSibling = null;
- this.attributeName = null;
- this.attributeNamespace = null;
- this.oldValue = null;
- }
- function copyMutationRecord(original) {
- var record = new MutationRecord(original.type, original.target);
- record.addedNodes = original.addedNodes.slice();
- record.removedNodes = original.removedNodes.slice();
- record.previousSibling = original.previousSibling;
- record.nextSibling = original.nextSibling;
- record.attributeName = original.attributeName;
- record.attributeNamespace = original.attributeNamespace;
- record.oldValue = original.oldValue;
- return record;
- }
- var currentRecord, recordWithOldValue;
- function getRecord(type, target) {
- return currentRecord = new MutationRecord(type, target);
- }
- function getRecordWithOldValue(oldValue) {
- if (recordWithOldValue) return recordWithOldValue;
- recordWithOldValue = copyMutationRecord(currentRecord);
- recordWithOldValue.oldValue = oldValue;
- return recordWithOldValue;
- }
- function clearRecords() {
- currentRecord = recordWithOldValue = undefined;
- }
- function recordRepresentsCurrentMutation(record) {
- return record === recordWithOldValue || record === currentRecord;
- }
- function selectRecord(lastRecord, newRecord) {
- if (lastRecord === newRecord) return lastRecord;
- if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord)) return recordWithOldValue;
- return null;
- }
- function Registration(observer, target, options) {
- this.observer = observer;
- this.target = target;
- this.options = options;
- this.transientObservedNodes = [];
- }
- Registration.prototype = {
- enqueue: function enqueue(record) {
- var records = this.observer.records_;
- var length = records.length;
- if (records.length > 0) {
- var lastRecord = records[length - 1];
- var recordToReplaceLast = selectRecord(lastRecord, record);
- if (recordToReplaceLast) {
- records[length - 1] = recordToReplaceLast;
- return;
- }
- } else {
- scheduleCallback(this.observer);
- }
- records[length] = record;
- },
- addListeners: function addListeners() {
- this.addListeners_(this.target);
- },
- addListeners_: function addListeners_(node) {
- var options = this.options;
- if (options.attributes) node.addEventListener("DOMAttrModified", this, true);
- if (options.characterData) node.addEventListener("DOMCharacterDataModified", this, true);
- if (options.childList) node.addEventListener("DOMNodeInserted", this, true);
- if (options.childList || options.subtree) node.addEventListener("DOMNodeRemoved", this, true);
- },
- removeListeners: function removeListeners() {
- this.removeListeners_(this.target);
- },
- removeListeners_: function removeListeners_(node) {
- var options = this.options;
- if (options.attributes) node.removeEventListener("DOMAttrModified", this, true);
- if (options.characterData) node.removeEventListener("DOMCharacterDataModified", this, true);
- if (options.childList) node.removeEventListener("DOMNodeInserted", this, true);
- if (options.childList || options.subtree) node.removeEventListener("DOMNodeRemoved", this, true);
- },
- addTransientObserver: function addTransientObserver(node) {
- if (node === this.target) return;
- this.addListeners_(node);
- this.transientObservedNodes.push(node);
- var registrations = registrationsTable.get(node);
- if (!registrations) registrationsTable.set(node, registrations = []);
- registrations.push(this);
- },
- removeTransientObservers: function removeTransientObservers() {
- var transientObservedNodes = this.transientObservedNodes;
- this.transientObservedNodes = [];
- transientObservedNodes.forEach(function (node) {
- this.removeListeners_(node);
- var registrations = registrationsTable.get(node);
- for (var i = 0; i < registrations.length; i++) {
- if (registrations[i] === this) {
- registrations.splice(i, 1);
- break;
- }
- }
- }, this);
- },
- handleEvent: function handleEvent(e) {
- e.stopImmediatePropagation();
- switch (e.type) {
- case "DOMAttrModified":
- var name = e.attrName;
- var namespace = e.relatedNode.namespaceURI;
- var target = e.target;
- var record = new getRecord("attributes", target);
- record.attributeName = name;
- record.attributeNamespace = namespace;
- var oldValue = e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;
- forEachAncestorAndObserverEnqueueRecord(target, function (options) {
- if (!options.attributes) return;
- if (options.attributeFilter && options.attributeFilter.length && options.attributeFilter.indexOf(name) === -1 && options.attributeFilter.indexOf(namespace) === -1) {
- return;
- }
- if (options.attributeOldValue) return getRecordWithOldValue(oldValue);
- return record;
- });
- break;
-
- case "DOMCharacterDataModified":
- var target = e.target;
- var record = getRecord("characterData", target);
- var oldValue = e.prevValue;
- forEachAncestorAndObserverEnqueueRecord(target, function (options) {
- if (!options.characterData) return;
- if (options.characterDataOldValue) return getRecordWithOldValue(oldValue);
- return record;
- });
- break;
-
- case "DOMNodeRemoved":
- this.addTransientObserver(e.target);
-
- case "DOMNodeInserted":
- var changedNode = e.target;
- var addedNodes, removedNodes;
- if (e.type === "DOMNodeInserted") {
- addedNodes = [changedNode];
- removedNodes = [];
- } else {
- addedNodes = [];
- removedNodes = [changedNode];
- }
- var previousSibling = changedNode.previousSibling;
- var nextSibling = changedNode.nextSibling;
- var record = getRecord("childList", e.target.parentNode);
- record.addedNodes = addedNodes;
- record.removedNodes = removedNodes;
- record.previousSibling = previousSibling;
- record.nextSibling = nextSibling;
- forEachAncestorAndObserverEnqueueRecord(e.relatedNode, function (options) {
- if (!options.childList) return;
- return record;
- });
- }
- clearRecords();
- }
- };
- global.JsMutationObserver = JsMutationObserver;
- if (!global.MutationObserver) {
- global.MutationObserver = JsMutationObserver;
- JsMutationObserver._isPolyfilled = true;
- }
- })(self);
-
- /*
- Copyright (c) 2012 Barnesandnoble.com, llc, Donavon West, and Domenic Denicola
-
- 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 (global, undefined) {
- if (global.setImmediate) {
- return;
- }
-
- var nextHandle = 1; // Spec says greater than zero
- var tasksByHandle = {};
- var currentlyRunningATask = false;
- var doc = global.document;
- var setImmediate;
-
- function addFromSetImmediateArguments(args) {
- tasksByHandle[nextHandle] = partiallyApplied.apply(undefined, args);
- return nextHandle++;
- }
-
- // This function accepts the same arguments as setImmediate, but
- // returns a function that requires no arguments.
- function partiallyApplied(handler) {
- var args = [].slice.call(arguments, 1);
- return function () {
- if (typeof handler === "function") {
- handler.apply(undefined, args);
- } else {
- new Function("" + handler)();
- }
- };
- }
-
- function runIfPresent(handle) {
- // From the spec: "Wait until any invocations of this algorithm started before this one have completed."
- // So if we're currently running a task, we'll need to delay this invocation.
- if (currentlyRunningATask) {
- // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a
- // "too much recursion" error.
- setTimeout(partiallyApplied(runIfPresent, handle), 0);
- } else {
- var task = tasksByHandle[handle];
- if (task) {
- currentlyRunningATask = true;
- try {
- task();
- } finally {
- clearImmediate(handle);
- currentlyRunningATask = false;
- }
- }
- }
- }
-
- function clearImmediate(handle) {
- delete tasksByHandle[handle];
- }
-
- function installNextTickImplementation() {
- setImmediate = function setImmediate() {
- var handle = addFromSetImmediateArguments(arguments);
- process.nextTick(partiallyApplied(runIfPresent, handle));
- return handle;
- };
- }
-
- function canUsePostMessage() {
- // The test against `importScripts` prevents this implementation from being installed inside a web worker,
- // where `global.postMessage` means something completely different and can't be used for this purpose.
- if (global.postMessage && !global.importScripts) {
- var postMessageIsAsynchronous = true;
- var oldOnMessage = global.onmessage;
- global.onmessage = function () {
- postMessageIsAsynchronous = false;
- };
- global.postMessage("", "*");
- global.onmessage = oldOnMessage;
- return postMessageIsAsynchronous;
- }
- }
-
- function installPostMessageImplementation() {
- // Installs an event handler on `global` for the `message` event: see
- // * https://developer.mozilla.org/en/DOM/window.postMessage
- // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages
-
- var messagePrefix = "setImmediate$" + Math.random() + "$";
- var onGlobalMessage = function onGlobalMessage(event) {
- if (event.source === global && typeof event.data === "string" && event.data.indexOf(messagePrefix) === 0) {
- runIfPresent(+event.data.slice(messagePrefix.length));
- }
- };
-
- if (global.addEventListener) {
- global.addEventListener("message", onGlobalMessage, false);
- } else {
- global.attachEvent("onmessage", onGlobalMessage);
- }
-
- setImmediate = function setImmediate() {
- var handle = addFromSetImmediateArguments(arguments);
- global.postMessage(messagePrefix + handle, "*");
- return handle;
- };
- }
-
- function installMessageChannelImplementation() {
- var channel = new MessageChannel();
- channel.port1.onmessage = function (event) {
- var handle = event.data;
- runIfPresent(handle);
- };
-
- setImmediate = function setImmediate() {
- var handle = addFromSetImmediateArguments(arguments);
- channel.port2.postMessage(handle);
- return handle;
- };
- }
-
- function installReadyStateChangeImplementation() {
- var html = doc.documentElement;
- setImmediate = function setImmediate() {
- var handle = addFromSetImmediateArguments(arguments);
- // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
- // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
- var script = doc.createElement("script");
- script.onreadystatechange = function () {
- runIfPresent(handle);
- script.onreadystatechange = null;
- html.removeChild(script);
- script = null;
- };
- html.appendChild(script);
- return handle;
- };
- }
-
- function installSetTimeoutImplementation() {
- setImmediate = function setImmediate() {
- var handle = addFromSetImmediateArguments(arguments);
- setTimeout(partiallyApplied(runIfPresent, handle), 0);
- return handle;
- };
- }
-
- // If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.
- var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);
- attachTo = attachTo && attachTo.setTimeout ? attachTo : global;
-
- // Don't get fooled by e.g. browserify environments.
- if ({}.toString.call(global.process) === "[object process]") {
- // For Node.js before 0.9
- installNextTickImplementation();
- } else if (canUsePostMessage()) {
- // For non-IE10 modern browsers
- installPostMessageImplementation();
- } else if (global.MessageChannel) {
- // For web workers, where supported
- installMessageChannelImplementation();
- } else if (doc && "onreadystatechange" in doc.createElement("script")) {
- // For IE 6–8
- installReadyStateChangeImplementation();
- } else {
- // For older browsers
- installSetTimeoutImplementation();
- }
-
- attachTo.setImmediate = setImmediate;
- attachTo.clearImmediate = clearImmediate;
- })(self);
-
- // Caution:
- // Do not replace this import statement with codes.
- //
- // If you replace this import statement with codes,
- // the codes will be executed after the following polyfills are imported
- // because import statements are hoisted during compilation.
- // Polyfill ECMAScript standard features with global namespace pollution
- // Polyfill Custom Elements v1 with global namespace pollution
- // Polyfill MutationObserver with global namespace pollution
- // Polyfill setImmediate with global namespace pollution
-
- (function () {
- var DEFAULT_VIEWPORT = 'width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no';
-
- var Viewport = {
- ensureViewportElement: function ensureViewportElement() {
- var viewportElement = document.querySelector('meta[name=viewport]');
-
- if (!viewportElement) {
- viewportElement = document.createElement('meta');
- viewportElement.name = 'viewport';
- document.head.appendChild(viewportElement);
- }
-
- return viewportElement;
- },
-
- setup: function setup() {
- var viewportElement = Viewport.ensureViewportElement();
-
- if (!viewportElement) {
- return;
- }
-
- if (!viewportElement.hasAttribute('content')) {
- viewportElement.setAttribute('content', DEFAULT_VIEWPORT);
- }
- }
- };
-
- window.Viewport = Viewport;
- })();
-
- function setup$1(ons) {
- if (window._onsLoaded) {
- ons._util.warn('Onsen UI is loaded more than once.');
- }
- window._onsLoaded = true;
-
- // fastclick
- window.addEventListener('load', function () {
- ons.fastClick = fastclick_1.attach(document.body);
-
- var supportTouchAction = 'touch-action' in document.body.style;
-
- ons.platform._runOnActualPlatform(function () {
- if (ons.platform.isAndroid()) {
- // In Android4.4+, correct viewport settings can remove click delay.
- // So disable FastClick on Android.
- ons.fastClick.destroy();
- } else if (ons.platform.isIOS()) {
- if (supportTouchAction && (ons.platform.isIOSSafari() || ons.platform.isWKWebView())) {
- // If 'touch-action' supported in iOS Safari or WKWebView, disable FastClick.
- ons.fastClick.destroy();
- } else {
- // Do nothing. 'touch-action: manipulation' has no effect on UIWebView.
- }
- }
- });
- }, false);
-
- ons.ready(function () {
- ons.enableDeviceBackButtonHandler();
- ons._defaultDeviceBackButtonHandler = ons._internal.dbbDispatcher.createHandler(window.document.body, function () {
- if (Object.hasOwnProperty.call(navigator, 'app')) {
- navigator.app.exitApp();
- } else {
- console.warn('Could not close the app. Is \'cordova.js\' included?\nError: \'window.navigator.app\' is undefined.');
- }
- });
- document.body._gestureDetector = new ons.GestureDetector(document.body, { passive: true });
-
- // Simulate Device Back Button on ESC press
- if (!ons.platform.isWebView()) {
- document.body.addEventListener('keydown', function (event) {
- if (event.keyCode === 27) {
- ons.fireDeviceBackButtonEvent();
- }
- });
- }
-
- // setup loading placeholder
- ons._setupLoadingPlaceHolders();
- });
-
- // viewport.js
- Viewport.setup();
- }
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- function getElementClass() {
- if (typeof HTMLElement !== 'function') {
- // case of Safari
- var _BaseElement = function _BaseElement() {};
- _BaseElement.prototype = document.createElement('div');
- return _BaseElement;
- } else {
- return HTMLElement;
- }
- }
-
- var BaseElement = function (_getElementClass) {
- inherits(BaseElement, _getElementClass);
-
- function BaseElement() {
- classCallCheck(this, BaseElement);
- return possibleConstructorReturn(this, (BaseElement.__proto__ || Object.getPrototypeOf(BaseElement)).call(this));
- }
-
- return BaseElement;
- }(getElementClass());
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * @element ons-template
- * @category util
- * @description
- * [en]
- * Define a separate HTML fragment and use as a template. These templates can be loaded as pages in `<ons-navigator>`, `<ons-tabbar>` and `<ons-splitter>`. They can also be used to generate dialogs. Since Onsen UI 2.4.0, the native `<template>` element can be used instead of `<ons-template>` for better performance and features. `<ons-template>` is still supported for backward compatibility.
- * [/en]
- * [ja]テンプレートとして使用するためのHTMLフラグメントを定義します。この要素でHTMLを宣言すると、id属性に指定した名前をpageのURLとしてons-navigatorなどのコンポーネントから参照できます。[/ja]
- * @seealso ons-navigator
- * [en]The `<ons-navigator>` component enables stack based navigation.[/en]
- * [ja][/ja]
- * @seealso ons-tabbar
- * [en]The `<ons-tabbar>` component is used to add tab navigation.[/en]
- * [ja][/ja]
- * @seealso ons-splitter
- * [en]The `<ons-splitter>` component can be used to create a draggable menu or column based layout.[/en]
- * [ja][/ja]
- * @example
- * <ons-template id="foobar.html">
- * <ons-page>
- * Page content
- * </ons-page>
- * </ons-template>
- *
- * <ons-navigator page="foobar.html"></ons-navigator>
- */
-
- var TemplateElement = function (_BaseElement) {
- inherits(TemplateElement, _BaseElement);
-
- /**
- * @property template
- * @type {String}
- * @description
- * [en]Template content. This property can not be used with AngularJS bindings.[/en]
- * [ja][/ja]
- */
-
- function TemplateElement() {
- classCallCheck(this, TemplateElement);
-
- var _this = possibleConstructorReturn(this, (TemplateElement.__proto__ || Object.getPrototypeOf(TemplateElement)).call(this));
-
- _this.template = _this.innerHTML;
-
- while (_this.firstChild) {
- _this.removeChild(_this.firstChild);
- }
- return _this;
- }
-
- createClass(TemplateElement, [{
- key: 'connectedCallback',
- value: function connectedCallback() {
- if (this.parentNode) {
- // Note: this.parentNode is not set in some CE0/CE1 polyfills.
- // Show warning when the ons-template is not located just under document.body
- if (this.parentNode !== document.body) {
- // if the parent is not document.body
- util$1.warn('ons-template (id = ' + this.getAttribute('id') + ') must be located just under document.body' + (this.parentNode.outerHTML ? ':\n\n' + this.parentNode.outerHTML : '.'));
- }
- }
-
- var event = new CustomEvent('_templateloaded', { bubbles: true, cancelable: true });
- event.template = this.template;
- event.templateId = this.getAttribute('id');
-
- this.dispatchEvent(event);
- }
- }]);
- return TemplateElement;
- }(BaseElement);
-
- onsElements.Template = TemplateElement;
- customElements.define('ons-template', TemplateElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * @element ons-if
- * @category conditional
- * @tutorial vanilla/Reference/if
- * @description
- * [en]
- * Conditionally display content depending on the platform, device orientation or both.
- *
- * Sometimes it is useful to conditionally hide or show certain components based on platform. When running on iOS the `<ons-if>` element can be used to hide the `<ons-fab>` element.
- * [/en]
- * [ja][/ja]
- * @guide theming.html#cross-platform-styling-autostyling [en]Information about cross platform styling[/en][ja]Information about cross platform styling[/ja]
- * @example
- * <ons-page>
- * <ons-if orientation="landscape">
- * Landscape view!
- * </ons-if>
- * <ons-if platform="android">
- * This is Android.
- * </ons-if>
- * <ons-if platform="ios other">
- * This is not Android.
- * </ons-if>
- * </ons-page>
- */
-
- var IfElement = function (_BaseElement) {
- inherits(IfElement, _BaseElement);
-
- /**
- * @attribute platform
- * @initonly
- * @type {string}
- * @description
- * [en]Space-separated platform names. Possible values are `"ios"`, `"android"`, `"windows"` and `"other"`.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute orientation
- * @type {string}
- * @description
- * [en]Either `"portrait"` or `"landscape"`.[/en]
- * [ja]portraitもしくはlandscapeを指定します[/ja]
- */
-
- function IfElement() {
- classCallCheck(this, IfElement);
-
- var _this = possibleConstructorReturn(this, (IfElement.__proto__ || Object.getPrototypeOf(IfElement)).call(this));
-
- contentReady(_this, function () {
- if (platform._getSelectedPlatform() !== null) {
- _this._platformUpdate();
- } else if (!_this._isAllowedPlatform()) {
- while (_this.childNodes[0]) {
- _this.childNodes[0].remove();
- }
- _this._platformUpdate();
- }
- });
-
- _this._onOrientationChange();
- return _this;
- }
-
- createClass(IfElement, [{
- key: 'connectedCallback',
- value: function connectedCallback() {
- orientation.on('change', this._onOrientationChange.bind(this));
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name) {
- if (name === 'orientation') {
- this._onOrientationChange();
- }
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- orientation.off('change', this._onOrientationChange);
- }
- }, {
- key: '_platformUpdate',
- value: function _platformUpdate() {
- this.style.display = this._isAllowedPlatform() ? '' : 'none';
- }
- }, {
- key: '_isAllowedPlatform',
- value: function _isAllowedPlatform() {
- return !this.getAttribute('platform') || this.getAttribute('platform').split(/\s+/).indexOf(platform.getMobileOS()) >= 0;
- }
- }, {
- key: '_onOrientationChange',
- value: function _onOrientationChange() {
- if (this.hasAttribute('orientation') && this._isAllowedPlatform()) {
- var conditionalOrientation = this.getAttribute('orientation').toLowerCase();
- var currentOrientation = orientation.isPortrait() ? 'portrait' : 'landscape';
-
- this.style.display = conditionalOrientation === currentOrientation ? '' : 'none';
- }
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['orientation'];
- }
- }]);
- return IfElement;
- }(BaseElement);
-
- onsElements.If = IfElement;
- customElements.define('ons-if', IfElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var BaseAnimator = function () {
-
- /**
- * @param {Object} options
- * @param {String} options.timing
- * @param {Number} options.duration
- * @param {Number} options.delay
- */
- function BaseAnimator() {
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- classCallCheck(this, BaseAnimator);
-
- this.timing = options.timing || 'linear';
- this.duration = options.duration || 0;
- this.delay = options.delay || 0;
-
- this.def = {
- timing: this.timing,
- duration: this.duration,
- delay: this.delay
- };
- }
-
- createClass(BaseAnimator, null, [{
- key: 'extend',
- value: function extend() {
- var properties = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
-
- var extendedAnimator = this;
- var newAnimator = function newAnimator() {
- extendedAnimator.apply(this, arguments);
- util$1.extend(this, properties);
- };
-
- newAnimator.prototype = this.prototype;
- return newAnimator;
- }
- }]);
- return BaseAnimator;
- }();
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- // This object should not be exposed to users. Please keep this private.
- var iPhoneXPatch = {};
-
- iPhoneXPatch.isIPhoneXPortraitPatchActive = function () {
- return document.documentElement.getAttribute('onsflag-iphonex-portrait') != null && window.innerWidth < window.innerHeight;
- };
-
- iPhoneXPatch.isIPhoneXLandscapePatchActive = function () {
- // If width === height, treat it as landscape
- return document.documentElement.getAttribute('onsflag-iphonex-landscape') != null && window.innerWidth >= window.innerHeight;
- };
-
- /**
- * Returns the safe area lengths based on the current state of the safe areas.
- */
- iPhoneXPatch.getSafeAreaLengths = function () {
- var safeAreaLengths = void 0;
- if (iPhoneXPatch.isIPhoneXPortraitPatchActive()) {
- safeAreaLengths = {
- top: 44,
- right: 0,
- bottom: 34,
- left: 0
- };
- } else if (iPhoneXPatch.isIPhoneXLandscapePatchActive()) {
- safeAreaLengths = {
- top: 0,
- right: 44,
- bottom: 21,
- left: 44
- };
- } else {
- safeAreaLengths = {
- top: 0,
- right: 0,
- bottom: 0,
- left: 0
- };
- }
-
- return safeAreaLengths;
- };
-
- /**
- * Returns the safe area rect based on the current state of the safe areas.
- */
- iPhoneXPatch.getSafeAreaDOMRect = function () {
- var safeAreaRect = void 0;
- if (iPhoneXPatch.isIPhoneXPortraitPatchActive()) {
- safeAreaRect = {
- x: 0,
- y: 44, /* 0 + 44 (top safe area) */
- width: window.innerWidth,
- height: window.innerHeight - 78 /* height - 44 (top safe area) - 34 (bottom safe area) */
- };
- } else if (iPhoneXPatch.isIPhoneXLandscapePatchActive()) {
- safeAreaRect = {
- x: 44, /* 0 + 44 (left safe area) */
- y: 0,
- width: window.innerWidth - 88, /* width - 44 (left safe area) - 34 (right safe area) */
- height: window.innerHeight - 21 /* height - 21 (bottom safe area) */
- };
- } else {
- safeAreaRect = {
- x: 0,
- y: 0,
- width: window.innerWidth,
- height: window.innerHeight
- };
- }
-
- return _extends({}, safeAreaRect, {
- left: safeAreaRect.x,
- top: safeAreaRect.y,
- right: safeAreaRect.x + safeAreaRect.width,
- bottom: safeAreaRect.y + safeAreaRect.height
- });
- };
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var ActionSheetAnimator = function (_BaseAnimator) {
- inherits(ActionSheetAnimator, _BaseAnimator);
-
- function ActionSheetAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'linear' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.2 : _ref$duration;
-
- classCallCheck(this, ActionSheetAnimator);
- return possibleConstructorReturn(this, (ActionSheetAnimator.__proto__ || Object.getPrototypeOf(ActionSheetAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
- }
-
- /**
- * @param {HTMLElement} dialog
- * @param {Function} done
- */
-
-
- createClass(ActionSheetAnimator, [{
- key: 'show',
- value: function show(dialog, done) {
- done();
- }
-
- /**
- * @param {HTMLElement} dialog
- * @param {Function} done
- */
-
- }, {
- key: 'hide',
- value: function hide(dialog, done) {
- done();
- }
- }]);
- return ActionSheetAnimator;
- }(BaseAnimator);
-
- /**
- * Android style animator for Action Sheet.
- */
- var MDActionSheetAnimator = function (_ActionSheetAnimator) {
- inherits(MDActionSheetAnimator, _ActionSheetAnimator);
-
- function MDActionSheetAnimator() {
- var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref2$timing = _ref2.timing,
- timing = _ref2$timing === undefined ? 'ease' : _ref2$timing,
- _ref2$delay = _ref2.delay,
- delay = _ref2$delay === undefined ? 0 : _ref2$delay,
- _ref2$duration = _ref2.duration,
- duration = _ref2$duration === undefined ? 0.4 : _ref2$duration;
-
- classCallCheck(this, MDActionSheetAnimator);
-
- var _this2 = possibleConstructorReturn(this, (MDActionSheetAnimator.__proto__ || Object.getPrototypeOf(MDActionSheetAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
-
- _this2.maskTiming = 'linear';
- _this2.maskDuration = 0.2;
- return _this2;
- }
-
- /**
- * @param {Object} dialog
- * @param {Function} callback
- */
-
-
- createClass(MDActionSheetAnimator, [{
- key: 'show',
- value: function show(dialog, callback) {
-
- Animit.runAll(Animit(dialog._mask).queue({ opacity: 0 }).wait(this.delay).queue({ opacity: 1.0 }, {
- duration: this.maskDuration,
- timing: this.maskTiming
- }), Animit(dialog._sheet, this.def).default({ transform: 'translate3d(0, 80%, 0)', opacity: 0 }, { transform: 'translate3d(0, 0, 0)', opacity: 1 }).queue(function (done) {
- callback && callback();
- done();
- }));
- }
-
- /**
- * @param {Object} dialog
- * @param {Function} callback
- */
-
- }, {
- key: 'hide',
- value: function hide(dialog, callback) {
- Animit.runAll(Animit(dialog._mask).queue({ opacity: 1 }).wait(this.delay).queue({ opacity: 0 }, {
- duration: this.maskDuration,
- timing: this.maskTiming
- }), Animit(dialog._sheet, this.def).default({ transform: 'translate3d(0, 0, 0)', opacity: 1 }, { transform: 'translate3d(0, 80%, 0)', opacity: 0 }).queue(function (done) {
- callback && callback();
- done();
- }));
- }
- }]);
- return MDActionSheetAnimator;
- }(ActionSheetAnimator);
-
- /**
- * iOS style animator for dialog.
- */
- var IOSActionSheetAnimator = function (_ActionSheetAnimator2) {
- inherits(IOSActionSheetAnimator, _ActionSheetAnimator2);
-
- function IOSActionSheetAnimator() {
- var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref3$timing = _ref3.timing,
- timing = _ref3$timing === undefined ? 'ease' : _ref3$timing,
- _ref3$delay = _ref3.delay,
- delay = _ref3$delay === undefined ? 0 : _ref3$delay,
- _ref3$duration = _ref3.duration,
- duration = _ref3$duration === undefined ? 0.3 : _ref3$duration;
-
- classCallCheck(this, IOSActionSheetAnimator);
-
- var _this3 = possibleConstructorReturn(this, (IOSActionSheetAnimator.__proto__ || Object.getPrototypeOf(IOSActionSheetAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
-
- _this3.maskTiming = 'linear';
- _this3.maskDuration = 0.2;
- if (iPhoneXPatch.isIPhoneXPortraitPatchActive()) {
- _this3.liftAmount = 'calc(100% + 48px)';
- } else if (iPhoneXPatch.isIPhoneXLandscapePatchActive()) {
- _this3.liftAmount = 'calc(100% + 33px)';
- } else {
- _this3.liftAmount = document.body.clientHeight / 2.0 - 1 + 'px'; // avoid Forced Synchronous Layout
- }
- return _this3;
- }
-
- /**
- * @param {Object} dialog
- * @param {Function} callback
- */
-
-
- createClass(IOSActionSheetAnimator, [{
- key: 'show',
- value: function show(dialog, callback) {
- Animit.runAll(Animit(dialog._mask).queue({ opacity: 0 }).wait(this.delay).queue({ opacity: 1 }, {
- duration: this.maskDuration,
- timing: this.maskTiming
- }), Animit(dialog._sheet, this.def).default({ transform: 'translate3d(0, ' + this.liftAmount + ', 0)' }, { transform: 'translate3d(0, 0, 0)' }).queue(function (done) {
- callback && callback();
- done();
- }));
- }
-
- /**
- * @param {Object} dialog
- * @param {Function} callback
- */
-
- }, {
- key: 'hide',
- value: function hide(dialog, callback) {
- Animit.runAll(Animit(dialog._mask).queue({ opacity: 1 }).wait(this.delay).queue({ opacity: 0 }, {
- duration: this.maskDuration,
- timing: this.maskTiming
- }), Animit(dialog._sheet, this.def).default({ transform: 'translate3d(0, 0, 0)' }, { transform: 'translate3d(0, ' + this.liftAmount + ', 0)' }).queue(function (done) {
- callback && callback();
- done();
- }));
- }
- }]);
- return IOSActionSheetAnimator;
- }(ActionSheetAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var BaseDialogElement = function (_BaseElement) {
- inherits(BaseDialogElement, _BaseElement);
- createClass(BaseDialogElement, [{
- key: '_updateAnimatorFactory',
- value: function _updateAnimatorFactory() {
- util$1.throwMember();
- }
- }, {
- key: '_toggleStyle',
- value: function _toggleStyle(shouldShow) {
- this.style.display = shouldShow ? 'block' : 'none';
- }
- }, {
- key: '_scheme',
- get: function get$$1() {
- util$1.throwMember();
- }
- }]);
-
- function BaseDialogElement() {
- classCallCheck(this, BaseDialogElement);
-
- var _this = possibleConstructorReturn(this, (BaseDialogElement.__proto__ || Object.getPrototypeOf(BaseDialogElement)).call(this));
-
- if (_this.constructor === BaseDialogElement) {
- util$1.throwAbstract();
- }
-
- _this._visible = false;
- _this._doorLock = new DoorLock();
- _this._cancel = _this._cancel.bind(_this);
- _this._selfCamelName = util$1.camelize(_this.tagName.slice(4));
- _this._defaultDBB = function (e) {
- return _this.cancelable ? _this._cancel() : e.callParentHandler();
- };
- _this._animatorFactory = _this._updateAnimatorFactory();
- return _this;
- }
-
- createClass(BaseDialogElement, [{
- key: '_cancel',
- value: function _cancel() {
- var _this2 = this;
-
- if (this.cancelable && !this._running) {
- this._running = true;
- this.hide().then(function () {
- _this2._running = false;
- util$1.triggerElementEvent(_this2, 'dialog-cancel');
- }, function () {
- return _this2._running = false;
- });
- }
- }
- }, {
- key: 'show',
- value: function show() {
- for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
- args[_key] = arguments[_key];
- }
-
- return this._setVisible.apply(this, [true].concat(args));
- }
- }, {
- key: 'hide',
- value: function hide() {
- for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
- args[_key2] = arguments[_key2];
- }
-
- return this._setVisible.apply(this, [false].concat(args));
- }
- }, {
- key: 'toggle',
- value: function toggle() {
- for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
- args[_key3] = arguments[_key3];
- }
-
- return this._setVisible.apply(this, [!this.visible].concat(args));
- }
- }, {
- key: '_setVisible',
- value: function _setVisible(shouldShow) {
- var _util$triggerElementE,
- _this3 = this;
-
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- var action = shouldShow ? 'show' : 'hide';
-
- options = _extends({}, options);
- options.animationOptions = util$1.extend(options.animationOptions || {}, AnimatorFactory.parseAnimationOptionsString(this.getAttribute('animation-options')));
-
- var canceled = false;
- util$1.triggerElementEvent(this, 'pre' + action, (_util$triggerElementE = {}, defineProperty(_util$triggerElementE, this._selfCamelName, this), defineProperty(_util$triggerElementE, 'cancel', function cancel() {
- return canceled = true;
- }), _util$triggerElementE));
-
- if (canceled) {
- return Promise.reject('Canceled in pre' + action + ' event.');
- }
-
- return new Promise(function (resolve) {
- _this3._doorLock.waitUnlock(function () {
- var unlock = _this3._doorLock.lock();
- var animator = _this3._animatorFactory.newAnimator(options);
-
- shouldShow && _this3._toggleStyle(true, options);
- _this3._visible = shouldShow;
- util$1.iosPageScrollFix(shouldShow);
-
- contentReady(_this3, function () {
- animator[action](_this3, function () {
- !shouldShow && _this3._toggleStyle(false, options);
-
- unlock();
-
- util$1.propagateAction(_this3, '_' + action);
- util$1.triggerElementEvent(_this3, 'post' + action, defineProperty({}, _this3._selfCamelName, _this3)); // postshow posthide
-
- if (options.callback instanceof Function) {
- options.callback(_this3);
- }
-
- resolve(_this3);
- });
- });
- });
- });
- }
- }, {
- key: '_updateMask',
- value: function _updateMask() {
- var _this4 = this;
-
- contentReady(this, function () {
- if (_this4._mask && _this4.getAttribute('mask-color')) {
- _this4._mask.style.backgroundColor = _this4.getAttribute('mask-color');
- }
- });
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- var _this5 = this;
-
- if (typeof this._defaultDBB === 'function') {
- this.onDeviceBackButton = this._defaultDBB.bind(this);
- }
-
- contentReady(this, function () {
- if (_this5._mask) {
- _this5._mask.addEventListener('click', _this5._cancel, false);
- util$1.iosMaskScrollFix(_this5._mask, true);
- }
- });
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- if (this._backButtonHandler) {
- this._backButtonHandler.destroy();
- this._backButtonHandler = null;
- }
-
- if (this._mask) {
- this._mask.removeEventListener('click', this._cancel, false);
- util$1.iosMaskScrollFix(this._mask, false);
- }
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, this._scheme);
- break;
- case 'animation':
- this._animatorFactory = this._updateAnimatorFactory();
- break;
- case 'mask-color':
- this._updateMask();
- break;
- }
- }
- }, {
- key: 'onDeviceBackButton',
- get: function get$$1() {
- return this._backButtonHandler;
- },
- set: function set$$1(callback) {
- if (this._backButtonHandler) {
- this._backButtonHandler.destroy();
- }
-
- this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, callback);
- }
- }, {
- key: 'visible',
- get: function get$$1() {
- return this._visible;
- }
- }, {
- key: 'disabled',
- set: function set$$1(value) {
- return util$1.toggleAttribute(this, 'disabled', value);
- },
- get: function get$$1() {
- return this.hasAttribute('disabled');
- }
- }, {
- key: 'cancelable',
- set: function set$$1(value) {
- return util$1.toggleAttribute(this, 'cancelable', value);
- },
- get: function get$$1() {
- return this.hasAttribute('cancelable');
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'animation', 'mask-color'];
- }
- }, {
- key: 'events',
- get: function get$$1() {
- return ['preshow', 'postshow', 'prehide', 'posthide', 'dialog-cancel'];
- }
- }]);
- return BaseDialogElement;
- }(BaseElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var scheme = {
- '.action-sheet': 'action-sheet--*',
- '.action-sheet-mask': 'action-sheet-mask--*',
- '.action-sheet-title': 'action-sheet-title--*'
- };
-
- var _animatorDict = {
- 'default': function _default() {
- return platform.isAndroid() ? MDActionSheetAnimator : IOSActionSheetAnimator;
- },
- 'none': ActionSheetAnimator
- };
-
- /**
- * @element ons-action-sheet
- * @category dialog
- * @description
- * [en]
- * Action/bottom sheet that is displayed on top of current screen.
- *
- * This element can either be attached directly to the `<body>` or dynamically created from a template using the `ons.createElement(template, { append: true })` utility function and the `<template>` tag.
- *
- * The action sheet is useful for displaying a list of options and asking the user to make a decision. A `ons-action-sheet-button` is provided for this purpose, although it can contain any type of content.
- *
- * It will automatically be displayed as Material Design (bottom sheet) when running on an Android device.
- * [/en]
- * [ja]
- * アクションシート、もしくはボトムシートを現在のスクリーン上に表示します。
- *
- * この要素は、`<body>`要素に直接アタッチされるか、もしくは`ons.createElement(template, { append: true })`と`<template>`タグを使ってテンプレートから動的に生成されます。
- *
- * アクションシートは、選択肢のリストを表示してユーザーに尋ねるのに便利です。`ons-action-sheet-button`は、この要素の中に置くために提供されていますが、それ以外にも他のどのような要素を含むことができます。
- *
- * Androidデバイスで実行されるときには、自動的にマテリアルデザイン(ボトムシート)として表示されます。
- * [/ja]
- * @modifier material
- * [en]Display a Material Design bottom sheet.[/en]
- * [ja]マテリアルデザインのボトムシートを表示します。[/ja]
- * @tutorial vanilla/reference/action-sheet
- * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
- * @seealso ons-popover
- * [en]`<ons-popover>` component[/en]
- * [ja]ons-popoverコンポーネント[/ja]
- * @seealso ons-modal
- * [en]`<ons-modal>` component[/en]
- * [ja]ons-modalコンポーネント[/ja]
- * @example
- * <ons-action-sheet id="sheet">
- * <ons-action-sheet-button>Label</ons-action-sheet-button>
- * <ons-action-sheet-button>Label</ons-action-sheet-button>
- * </ons-action-sheet>
- *
- * <script>
- * document.getElementById('sheet').show();
- * </script>
- */
-
- var ActionSheetElement = function (_BaseDialogElement) {
- inherits(ActionSheetElement, _BaseDialogElement);
-
- /**
- * @event preshow
- * @description
- * [en]Fired just before the action sheet is displayed.[/en]
- * [ja]ダイアログが表示される直前に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.actionSheet
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- * @param {Function} event.cancel
- * [en]Execute this function to stop the action sheet from being shown.[/en]
- * [ja]この関数を実行すると、ダイアログの表示がキャンセルされます。[/ja]
- */
-
- /**
- * @event postshow
- * @description
- * [en]Fired just after the action sheet is displayed.[/en]
- * [ja]ダイアログが表示された直後に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.actionSheet
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- */
-
- /**
- * @event prehide
- * @description
- * [en]Fired just before the action sheet is hidden.[/en]
- * [ja]ダイアログが隠れる直前に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.actionSheet
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- * @param {Function} event.cancel
- * [en]Execute this function to stop the action sheet from being hidden.[/en]
- * [ja]この関数を実行すると、ダイアログの非表示がキャンセルされます。[/ja]
- */
-
- /**
- * @event posthide
- * @description
- * [en]Fired just after the action sheet is hidden.[/en]
- * [ja]ダイアログが隠れた後に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.actionSheet
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- */
-
- /**
- * @attribute title
- * @type {String}
- * @description
- * [en]Optional title of the action sheet. A new element will be created containing this string.[/en]
- * [ja]アクションシートのタイトルを指定します。ここで指定した文字列を含む新しい要素が作成されます。[/ja]
- */
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the action sheet.[/en]
- * [ja]ダイアログの表現を指定します。[/ja]
- */
-
- /**
- * @attribute cancelable
- * @description
- * [en]If this attribute is set the action sheet can be closed by tapping the background or by pressing the back button on Android devices.[/en]
- * [ja]この属性が設定されると、アクションシートの背景やAndroidデバイスのバックボタンを推すことでアクションシートが閉じるようになります。[/ja]
- */
-
- /**
- * @attribute disabled
- * @description
- * [en]If this attribute is set the action sheet is disabled.[/en]
- * [ja]この属性がある時、ダイアログはdisabled状態になります。[/ja]
- */
-
- /**
- * @attribute animation
- * @type {String}
- * @default default
- * @description
- * [en]The animation used when showing and hiding the action sheet. Can be either `"none"` or `"default"`.[/en]
- * [ja]ダイアログを表示する際のアニメーション名を指定します。"none"もしくは"default"を指定できます。[/ja]
- */
-
- /**
- * @attribute animation-options
- * @type {Expression}
- * @description
- * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`[/ja]
- */
-
- /**
- * @attribute mask-color
- * @type {String}
- * @default rgba(0, 0, 0, 0.2)
- * @description
- * [en]Color of the background mask. Default is `"rgba(0, 0, 0, 0.2)"`.[/en]
- * [ja]背景のマスクの色を指定します。"rgba(0, 0, 0, 0.2)"がデフォルト値です。[/ja]
- */
-
- function ActionSheetElement() {
- classCallCheck(this, ActionSheetElement);
-
- var _this = possibleConstructorReturn(this, (ActionSheetElement.__proto__ || Object.getPrototypeOf(ActionSheetElement)).call(this));
-
- contentReady(_this, function () {
- return _this._compile();
- });
- return _this;
- }
-
- createClass(ActionSheetElement, [{
- key: '_updateAnimatorFactory',
- value: function _updateAnimatorFactory() {
- return new AnimatorFactory({
- animators: _animatorDict,
- baseClass: ActionSheetAnimator,
- baseClassName: 'ActionSheetAnimator',
- defaultAnimation: this.getAttribute('animation')
- });
- }
- }, {
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
-
- this.style.display = 'none';
- this.style.zIndex = 10001;
-
- /* Expected result:
- * <ons-action-sheet>
- * <div class="action-sheet-mask"></div>
- * <div class="action-sheet">
- * <div class="action-sheet-title></div>
- * ...
- * </div>
- * </ons-action-sheet>
- */
-
- if (!this._sheet) {
- var sheet = document.createElement('div');
- sheet.classList.add('action-sheet');
-
- while (this.firstChild) {
- sheet.appendChild(this.firstChild);
- }
-
- this.appendChild(sheet);
- }
-
- if (!this._title && this.hasAttribute('title')) {
- var title = document.createElement('div');
- title.innerHTML = this.getAttribute('title');
- title.classList.add('action-sheet-title');
- this._sheet.insertBefore(title, this._sheet.firstChild);
- }
-
- if (!this._mask) {
- var mask = document.createElement('div');
- mask.classList.add('action-sheet-mask');
- this.insertBefore(mask, this.firstChild);
- }
-
- this._sheet.style.zIndex = 20001;
- this._mask.style.zIndex = 20000;
-
- ModifierUtil.initModifier(this, this._scheme);
- }
- }, {
- key: '_updateTitle',
- value: function _updateTitle() {
- if (this._title) {
- this._title.innerHTML = this.getAttribute('title');
- }
- }
-
- /**
- * @property onDeviceBackButton
- * @type {Object}
- * @description
- * [en]Back-button handler.[/en]
- * [ja]バックボタンハンドラ。[/ja]
- */
-
- /**
- * @method show
- * @signature show([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Available animations are `"none"` and `"slide"`.[/en]
- * [ja]アニメーション名を指定します。"none", "slide"のいずれかを指定します。[/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}` [/ja]
- * @param {Function} [options.callback]
- * [en]This function is called after the action sheet has been revealed.[/en]
- * [ja]ダイアログが表示され終わった後に呼び出される関数オブジェクトを指定します。[/ja]
- * @description
- * [en]Show the action sheet.[/en]
- * [ja]ダイアログを開きます。[/ja]
- * @return {Promise} Resolves to the displayed element.
- */
-
- /**
- * @method hide
- * @signature hide([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Available animations are `"none"` and `"slide"`.[/en]
- * [ja]アニメーション名を指定します。"none", "slide"のいずれかを指定できます。[/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`[/ja]
- * @param {Function} [options.callback]
- * [en]This functions is called after the action sheet has been hidden.[/en]
- * [ja]ダイアログが隠れた後に呼び出される関数オブジェクトを指定します。[/ja]
- * @description
- * [en]Hide the action sheet.[/en]
- * [ja]ダイアログを閉じます。[/ja]
- * @return {Promise}
- * [en]Resolves to the hidden element[/en]
- * [ja]隠れた要素を解決します。[/ja]
- */
-
- /**
- * @property visible
- * @readonly
- * @type {Boolean}
- * @description
- * [en]Whether the action sheet is visible or not.[/en]
- * [ja]要素が見える場合に`true`。[/ja]
- */
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the action sheet is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- /**
- * @property cancelable
- * @type {Boolean}
- * @description
- * [en]Whether the action sheet is cancelable or not. A cancelable action sheet can be closed by tapping the background or by pressing the back button on Android devices.[/en]
- * [ja]アクションシートがキャンセル可能かどうかを設定します。キャンセル可能なアクションシートは、背景をタップしたりAndroidデバイスのバックボタンを推すことで閉じるようになります。[/ja]
- */
-
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- if (name === 'title') {
- this._updateTitle();
- } else {
- get(ActionSheetElement.prototype.__proto__ || Object.getPrototypeOf(ActionSheetElement.prototype), 'attributeChangedCallback', this).call(this, name, last, current);
- }
- }
-
- /**
- * @param {String} name
- * @param {ActionSheetAnimator} Animator
- */
-
- }, {
- key: '_scheme',
- get: function get$$1() {
- return scheme;
- }
- }, {
- key: '_mask',
- get: function get$$1() {
- return util$1.findChild(this, '.action-sheet-mask');
- }
- }, {
- key: '_sheet',
- get: function get$$1() {
- return util$1.findChild(this, '.action-sheet');
- }
- }, {
- key: '_title',
- get: function get$$1() {
- return this.querySelector('.action-sheet-title');
- }
- }], [{
- key: 'registerAnimator',
- value: function registerAnimator(name, Animator) {
- if (!(Animator.prototype instanceof ActionSheetAnimator)) {
- util$1.throwAnimator('ActionSheet');
- }
- _animatorDict[name] = Animator;
- }
- }, {
- key: 'observedAttributes',
- get: function get$$1() {
- return [].concat(toConsumableArray(get(ActionSheetElement.__proto__ || Object.getPrototypeOf(ActionSheetElement), 'observedAttributes', this)), ['title']);
- }
- }, {
- key: 'animators',
- get: function get$$1() {
- return _animatorDict;
- }
- }, {
- key: 'ActionSheetAnimator',
- get: function get$$1() {
- return ActionSheetAnimator;
- }
- }]);
- return ActionSheetElement;
- }(BaseDialogElement);
-
- onsElements.ActionSheet = ActionSheetElement;
- customElements.define('ons-action-sheet', ActionSheetElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var BaseButtonElement = function (_BaseElement) {
- inherits(BaseButtonElement, _BaseElement);
- createClass(BaseButtonElement, [{
- key: '_scheme',
- get: function get$$1() {
- util$1.throwMember();
- }
- }, {
- key: '_defaultClassName',
- get: function get$$1() {
- util$1.throwMember();
- }
- }, {
- key: '_rippleOpt',
- get: function get$$1() {
- return [this];
- }
- }]);
-
- function BaseButtonElement() {
- classCallCheck(this, BaseButtonElement);
-
- var _this = possibleConstructorReturn(this, (BaseButtonElement.__proto__ || Object.getPrototypeOf(BaseButtonElement)).call(this));
-
- if (_this.constructor === BaseButtonElement) {
- util$1.throwAbstract();
- }
-
- contentReady(_this, function () {
- return _this._compile();
- });
- return _this;
- }
-
- createClass(BaseButtonElement, [{
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
-
- this.classList.add(this._defaultClassName);
-
- if (!this._icon && this.hasAttribute('icon')) {
- util$1.checkMissingImport('Icon');
- var icon = util$1.createElement('<ons-icon icon="' + this.getAttribute('icon') + '"></ons-icon>');
- icon.classList.add(this._defaultClassName.replace('button', 'icon'));
- this.insertBefore(icon, this.firstChild);
- }
-
- this._updateRipple();
-
- ModifierUtil.initModifier(this, this._scheme);
- }
- }, {
- key: '_updateIcon',
- value: function _updateIcon() {
- if (this._icon) {
- this._icon.setAttribute('icon', this.getAttribute('icon'));
- }
- }
- }, {
- key: '_updateRipple',
- value: function _updateRipple() {
- this._rippleOpt && util$1.updateRipple.apply(util$1, toConsumableArray(this._rippleOpt));
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'class':
- util$1.restoreClass(this, this._defaultClassName, this._scheme);
- break;
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, this._scheme);
- break;
- case 'icon':
- this._updateIcon();
- break;
- case 'ripple':
- this.classList.contains(this._defaultClassName) && this._updateRipple();
- break;
- }
- }
- }, {
- key: 'disabled',
- set: function set$$1(value) {
- return util$1.toggleAttribute(this, 'disabled', value);
- },
- get: function get$$1() {
- return this.hasAttribute('disabled');
- }
- }, {
- key: '_icon',
- get: function get$$1() {
- return util$1.findChild(this, 'ons-icon');
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'class', 'icon', 'ripple'];
- }
- }]);
- return BaseButtonElement;
- }(BaseElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * @element ons-action-sheet-button
- * @category dialog
- * @modifier destructive
- * [en]Shows a "destructive" button (only for iOS).[/en]
- * [ja]"destructive"なボタンを表示します(iOSでのみ有効)。[/ja]
- * @description
- * [en]Component that represent each button of the action sheet.[/en]
- * [ja]アクションシートに表示される各ボタンを表現するコンポーネントです。[/ja]
- * @seealso ons-action-sheet
- * [en]The `<ons-action-sheet>` component[/en]
- * [ja]ons-action-sheetコンポーネント[/ja]
- * @seealso ons-list-item
- * [en]The `<ons-list-item>` component[/en]
- * [ja]ons-list-itemコンポーネント[/ja]
- * @seealso ons-icon
- * [en]The `<ons-icon>` component[/en]
- * [ja]ons-iconコンポーネント[/ja]
- * @tutorial vanilla/Reference/action-sheet
- * @guide appsize.html#removing-icon-packs [en]Removing icon packs.[/en][ja][/ja]
- * @guide faq.html#how-can-i-use-custom-icon-packs [en]Adding custom icon packs.[/en][ja][/ja]
- * @modifier material
- * [en]Display a Material Design action sheet button.[/en]
- * [ja]マテリアルデザインのアクションシート用のボタンを表示します。[/ja]
- * @example
- * <ons-action-sheet id="sheet">
- * <ons-action-sheet-button>Label</ons-action-sheet-button>
- * <ons-action-sheet-button>Label</ons-action-sheet-button>
- * </ons-action-sheet>
- *
- * <script>
- * document.getElementById('sheet').show();
- * </script>
- */
-
- var ActionSheetButtonElement = function (_BaseButtonElement) {
- inherits(ActionSheetButtonElement, _BaseButtonElement);
-
- function ActionSheetButtonElement() {
- classCallCheck(this, ActionSheetButtonElement);
- return possibleConstructorReturn(this, (ActionSheetButtonElement.__proto__ || Object.getPrototypeOf(ActionSheetButtonElement)).apply(this, arguments));
- }
-
- createClass(ActionSheetButtonElement, [{
- key: '_scheme',
-
-
- /**
- * @attribute icon
- * @type {String}
- * @description
- * [en]Creates an `ons-icon` component with this string. Only visible on Android. Check [See also](#seealso) section for more information.[/en]
- * [ja]`ons-icon`コンポーネントを悪性します。Androidでのみ表示されます。[/ja]
- */
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the action sheet button.[/en]
- * [ja]アクションシートボタンの見た目を設定します。[/ja]
- */
-
- get: function get$$1() {
- return {
- '': 'action-sheet-button--*',
- '.action-sheet-icon': 'action-sheet-icon--*'
- };
- }
- }, {
- key: '_defaultClassName',
- get: function get$$1() {
- return 'action-sheet-button';
- }
- }, {
- key: '_rippleOpt',
- get: function get$$1() {
- return undefined;
- }
- }]);
- return ActionSheetButtonElement;
- }(BaseButtonElement);
-
- onsElements.ActionSheetButton = ActionSheetButtonElement;
- customElements.define('ons-action-sheet-button', ActionSheetButtonElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var AlertDialogAnimator = function (_BaseAnimator) {
- inherits(AlertDialogAnimator, _BaseAnimator);
-
- function AlertDialogAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'linear' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.2 : _ref$duration;
-
- classCallCheck(this, AlertDialogAnimator);
- return possibleConstructorReturn(this, (AlertDialogAnimator.__proto__ || Object.getPrototypeOf(AlertDialogAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
- }
-
- /**
- * @param {HTMLElement} dialog
- * @param {Function} done
- */
-
-
- createClass(AlertDialogAnimator, [{
- key: 'show',
- value: function show(dialog, done) {
- done();
- }
-
- /**
- * @param {HTMLElement} dialog
- * @param {Function} done
- */
-
- }, {
- key: 'hide',
- value: function hide(dialog, done) {
- done();
- }
- }]);
- return AlertDialogAnimator;
- }(BaseAnimator);
-
- /**
- * Android style animator for alert dialog.
- */
- var AndroidAlertDialogAnimator = function (_AlertDialogAnimator) {
- inherits(AndroidAlertDialogAnimator, _AlertDialogAnimator);
-
- function AndroidAlertDialogAnimator() {
- var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref2$timing = _ref2.timing,
- timing = _ref2$timing === undefined ? 'cubic-bezier(.1, .7, .4, 1)' : _ref2$timing,
- _ref2$duration = _ref2.duration,
- duration = _ref2$duration === undefined ? 0.2 : _ref2$duration,
- _ref2$delay = _ref2.delay,
- delay = _ref2$delay === undefined ? 0 : _ref2$delay;
-
- classCallCheck(this, AndroidAlertDialogAnimator);
- return possibleConstructorReturn(this, (AndroidAlertDialogAnimator.__proto__ || Object.getPrototypeOf(AndroidAlertDialogAnimator)).call(this, { duration: duration, timing: timing, delay: delay }));
- }
-
- /**
- * @param {Object} dialog
- * @param {Function} callback
- */
-
-
- createClass(AndroidAlertDialogAnimator, [{
- key: 'show',
- value: function show(dialog, callback) {
- callback = callback ? callback : function () {};
-
- Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 0 }, { opacity: 1 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, -50%, 0) scale3d(.9, .9, 1)', opacity: 0 }, { transform: 'translate3d(-50%, -50%, 0) scale3d(1, 1, 1)', opacity: 1 }).queue(function (done) {
- callback();
- done();
- }));
- }
-
- /**
- * @param {Object} dialog
- * @param {Function} callback
- */
-
- }, {
- key: 'hide',
- value: function hide(dialog, callback) {
- callback = callback ? callback : function () {};
-
- Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 1 }, { opacity: 0 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, -50%, 0) scale3d(1, 1, 1)', opacity: 1 }, { transform: 'translate3d(-50%, -50%, 0) scale3d(.9, .9, 1)', opacity: 0 }).queue(function (done) {
- callback();
- done();
- }));
- }
- }]);
- return AndroidAlertDialogAnimator;
- }(AlertDialogAnimator);
-
- /**
- * iOS style animator for alert dialog.
- */
- var IOSAlertDialogAnimator = function (_AlertDialogAnimator2) {
- inherits(IOSAlertDialogAnimator, _AlertDialogAnimator2);
-
- function IOSAlertDialogAnimator() {
- var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref3$timing = _ref3.timing,
- timing = _ref3$timing === undefined ? 'cubic-bezier(.1, .7, .4, 1)' : _ref3$timing,
- _ref3$duration = _ref3.duration,
- duration = _ref3$duration === undefined ? 0.2 : _ref3$duration,
- _ref3$delay = _ref3.delay,
- delay = _ref3$delay === undefined ? 0 : _ref3$delay;
-
- classCallCheck(this, IOSAlertDialogAnimator);
- return possibleConstructorReturn(this, (IOSAlertDialogAnimator.__proto__ || Object.getPrototypeOf(IOSAlertDialogAnimator)).call(this, { duration: duration, timing: timing, delay: delay }));
- }
-
- /*
- * @param {Object} dialog
- * @param {Function} callback
- */
-
-
- createClass(IOSAlertDialogAnimator, [{
- key: 'show',
- value: function show(dialog, callback) {
- callback = callback ? callback : function () {};
-
- Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 0 }, { opacity: 1 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, -50%, 0) scale3d(1.3, 1.3, 1)', opacity: 0 }, { transform: 'translate3d(-50%, -50%, 0) scale3d(1, 1, 1)', opacity: 1 }).queue(function (done) {
- callback();
- done();
- }));
- }
-
- /**
- * @param {Object} dialog
- * @param {Function} callback
- */
-
- }, {
- key: 'hide',
- value: function hide(dialog, callback) {
- callback = callback ? callback : function () {};
-
- Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 1 }, { opacity: 0 }), Animit(dialog._dialog, this.def).default({ opacity: 1 }, { opacity: 0 }).queue(function (done) {
- callback();
- done();
- }));
- }
- }]);
- return IOSAlertDialogAnimator;
- }(AlertDialogAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var scheme$1 = {
- '.alert-dialog': 'alert-dialog--*',
- '.alert-dialog-container': 'alert-dialog-container--*',
- '.alert-dialog-title': 'alert-dialog-title--*',
- '.alert-dialog-content': 'alert-dialog-content--*',
- '.alert-dialog-footer': 'alert-dialog-footer--*',
- '.alert-dialog-footer--rowfooter': 'alert-dialog-footer--rowfooter--*',
- '.alert-dialog-button--rowfooter': 'alert-dialog-button--rowfooter--*',
- '.alert-dialog-button--primal': 'alert-dialog-button--primal--*',
- '.alert-dialog-button': 'alert-dialog-button--*',
- 'ons-alert-dialog-button': 'alert-dialog-button--*',
- '.alert-dialog-mask': 'alert-dialog-mask--*',
- '.text-input': 'text-input--*'
- };
-
- var _animatorDict$1 = {
- 'none': AlertDialogAnimator,
- 'default': function _default() {
- return platform.isAndroid() ? AndroidAlertDialogAnimator : IOSAlertDialogAnimator;
- },
- 'fade': function fade() {
- return platform.isAndroid() ? AndroidAlertDialogAnimator : IOSAlertDialogAnimator;
- }
- };
-
- /**
- * @element ons-alert-dialog
- * @category dialog
- * @description
- * [en]
- * Alert dialog that is displayed on top of the current screen. Useful for displaying questions, warnings or error messages to the user. The title, content and buttons can be easily customized and it will automatically switch style based on the platform.
- *
- * To use the element it can either be attached directly to the `<body>` element or dynamically created from a template using the `ons.createAlertDialog(template)` utility function and the `<template>` tag.
- * [/en]
- * [ja]
- * 現在のスクリーンの上に表示するアラートダイアログです。ユーザに対する問いかけ、警告、エラーメッセージを表示するのに利用できます。タイトルやコンテンツやボタンは簡単にカスタマイズでき、実行しているプラットフォームに併せてスタイルが自動的に切り替わります。
- * [/ja]
- * @codepen Qwwxyp
- * @tutorial vanilla/Reference/alert-dialog
- * @modifier material
- * [en]Material Design style[/en]
- * [ja]マテリアルデザインのスタイル[/ja]
- * @modifier rowfooter
- * [en]Horizontally aligns the footer buttons.[/en]
- * [ja]フッターの複数のボタンを水平に配置[/ja]
- * @seealso ons-dialog
- * [en]ons-dialog component[/en]
- * [ja]ons-dialogコンポーネント[/ja]
- * @seealso ons-popover
- * [en]ons-popover component[/en]
- * [ja]ons-dialogコンポーネント[/ja]
- * @seealso ons.notification
- * [en]Using ons.notification utility functions.[/en]
- * [ja]アラートダイアログを表示するには、ons.notificationオブジェクトのメソッドを使うこともできます。[/ja]
- * @example
- * <ons-alert-dialog id="alert-dialog">
- * <div class="alert-dialog-title">Warning!</div>
- * <div class="alert-dialog-content">
- * An error has occurred!
- * </div>
- * <div class="alert-dialog-footer">
- * <button id="alert-dialog-button" class="alert-dialog-button">OK</button>
- * </div>
- * </ons-alert-dialog>
- * <script>
- * document.getElementById('alert-dialog').show();
- * </script>
- */
-
- var AlertDialogElement = function (_BaseDialogElement) {
- inherits(AlertDialogElement, _BaseDialogElement);
-
- /**
- * @event preshow
- * @description
- * [en]Fired just before the alert dialog is displayed.[/en]
- * [ja]アラートダイアログが表示される直前に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.alertDialog
- * [en]Alert dialog object.[/en]
- * [ja]アラートダイアログのオブジェクト。[/ja]
- * @param {Function} event.cancel
- * [en]Execute to stop the dialog from showing.[/en]
- * [ja]この関数を実行すると、アラートダイアログの表示を止めます。[/ja]
- */
-
- /**
- * @event postshow
- * @description
- * [en]Fired just after the alert dialog is displayed.[/en]
- * [ja]アラートダイアログが表示された直後に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.alertDialog
- * [en]Alert dialog object.[/en]
- * [ja]アラートダイアログのオブジェクト。[/ja]
- */
-
- /**
- * @event prehide
- * @description
- * [en]Fired just before the alert dialog is hidden.[/en]
- * [ja]アラートダイアログが隠れる直前に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.alertDialog
- * [en]Alert dialog object.[/en]
- * [ja]アラートダイアログのオブジェクト。[/ja]
- * @param {Function} event.cancel
- * [en]Execute to stop the dialog from hiding.[/en]
- * [ja]この関数を実行すると、アラートダイアログが閉じようとするのを止めます。[/ja]
- */
-
- /**
- * @event posthide
- * @description
- * [en]Fired just after the alert dialog is hidden.[/en]
- * [ja]アラートダイアログが隠れた後に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.alertDialog
- * [en]Alert dialog object.[/en]
- * [ja]アラートダイアログのオブジェクト。[/ja]
- */
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the dialog.[/en]
- * [ja]ダイアログの見た目を指定します。[/ja]
- */
-
- /**
- * @attribute cancelable
- * @description
- * [en]If this attribute is set the dialog can be closed by tapping the background or by pressing the back button on Android devices.[/en]
- * [ja]この属性を設定すると、ダイアログの背景をタップしたりAndroidデバイスのバックボタンを押すとダイアログが閉じるようになります。[/ja]
- */
-
- /**
- * @attribute disabled
- * @description
- * [en]If this attribute is set the dialog is disabled.[/en]
- * [ja]この属性がある時、アラートダイアログはdisabled状態になります。[/ja]
- */
-
- /**
- * @attribute animation
- * @type {String}
- * @default default
- * @description
- * [en]The animation used when showing and hiding the dialog. Can be either `"none"` or `"default"`.[/en]
- * [ja]ダイアログを表示する際のアニメーション名を指定します。デフォルトでは"none"か"default"が指定できます。[/ja]
- */
-
- /**
- * @attribute animation-options
- * @type {Expression}
- * @description
- * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。例:{duration: 0.2, delay: 1, timing: 'ease-in'}[/ja]
- */
-
- /**
- * @attribute mask-color
- * @type {String}
- * @default rgba(0, 0, 0, 0.2)
- * @description
- * [en]Color of the background mask. Default is "rgba(0, 0, 0, 0.2)".[/en]
- * [ja]背景のマスクの色を指定します。"rgba(0, 0, 0, 0.2)"がデフォルト値です。[/ja]
- */
-
- function AlertDialogElement() {
- classCallCheck(this, AlertDialogElement);
-
- var _this = possibleConstructorReturn(this, (AlertDialogElement.__proto__ || Object.getPrototypeOf(AlertDialogElement)).call(this));
-
- contentReady(_this, function () {
- return _this._compile();
- });
- return _this;
- }
-
- createClass(AlertDialogElement, [{
- key: '_updateAnimatorFactory',
- value: function _updateAnimatorFactory() {
- return new AnimatorFactory({
- animators: _animatorDict$1,
- baseClass: AlertDialogAnimator,
- baseClassName: 'AlertDialogAnimator',
- defaultAnimation: this.getAttribute('animation')
- });
- }
- }, {
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
-
- this.style.display = 'none';
- this.style.zIndex = 10001;
-
- /**
- * Expected result after compile:
- *
- * <ons-alert-dialog style="none">
- * <div class="alert-dialog-mask"></div>
- * <div class="alert-dialog">
- * <div class="alert-dialog-container">...</div>
- * </div>
- * </ons-alert-dialog>
- */
-
- var content = document.createDocumentFragment();
-
- if (!this._mask && !this._dialog) {
- while (this.firstChild) {
- content.appendChild(this.firstChild);
- }
- }
-
- if (!this._mask) {
- var mask = document.createElement('div');
- mask.classList.add('alert-dialog-mask');
- this.insertBefore(mask, this.children[0]);
- }
-
- if (!this._dialog) {
- var dialog = document.createElement('div');
- dialog.classList.add('alert-dialog');
- this.insertBefore(dialog, null);
- }
-
- if (!util$1.findChild(this._dialog, '.alert-dialog-container')) {
- var container = document.createElement('div');
- container.classList.add('alert-dialog-container');
- this._dialog.appendChild(container);
- }
-
- this._dialog.children[0].appendChild(content);
-
- this._dialog.style.zIndex = 20001;
- this._mask.style.zIndex = 20000;
-
- ModifierUtil.initModifier(this, this._scheme);
- }
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the element is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- /**
- * @property cancelable
- * @type {Boolean}
- * @description
- * [en]Whether the dialog is cancelable or not. A cancelable dialog can be closed by tapping the background or by pressing the back button on Android devices.[/en]
- * [ja]そのダイアログがキャンセル可能かどうかを表します。キャンセル可能なダイアログは、背景をタップするかAndroidデバイスのバックボタンを押すことで閉じることが出来るようになります。[/ja]
- */
-
- /**
- * @method show
- * @signature show([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクトです。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Available animations are `"fade"` and `"none"`.[/en]
- * [ja]アニメーション名を指定します。指定できるのは、"fade", "none"のいずれかです。[/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. <code>{duration: 0.2, delay: 0.4, timing: 'ease-in'}</code> [/ja]
- * @param {Function} [options.callback]
- * [en]Function to execute after the dialog has been revealed.[/en]
- * [ja]ダイアログが表示され終わった時に呼び出されるコールバックを指定します。[/ja]
- * @description
- * [en]Show the alert dialog.[/en]
- * [ja]ダイアログを表示します。[/ja]
- * @return {Promise}
- * [en]A `Promise` object that resolves to the displayed element.[/en]
- * [ja]表示される要素を解決する`Promise`オブジェクトを返します。[/ja]
- */
-
- /**
- * @method hide
- * @signature hide([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Available animations are `"fade"` and `"none"`.[/en]
- * [ja]アニメーション名を指定します。"fade", "none"のいずれかを指定します。[/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. <code>{duration: 0.2, delay: 0.4, timing: 'ease-in'}</code>[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. <code>{duration: 0.2, delay: 0.4, timing: 'ease-in'}</code> [/ja]
- * @param {Function} [options.callback]
- * [en]Function to execute after the dialog has been hidden.[/en]
- * [ja]このダイアログが閉じた時に呼び出されるコールバックを指定します。[/ja]
- * @description
- * [en]Hide the alert dialog.[/en]
- * [ja]ダイアログを閉じます。[/ja]
- * @return {Promise}
- * [en]Resolves to the hidden element[/en]
- * [ja]隠れた要素を解決する`Promise`オブジェクトを返します。[/ja]
- */
-
- /**
- * @property visible
- * @readonly
- * @type {Boolean}
- * @description
- * [en]Whether the dialog is visible or not.[/en]
- * [ja]要素が見える場合に`true`。[/ja]
- */
-
- /**
- * @property onDeviceBackButton
- * @type {Object}
- * @description
- * [en]Back-button handler.[/en]
- * [ja]バックボタンハンドラ。[/ja]
- */
-
- /**
- * @param {String} name
- * @param {DialogAnimator} Animator
- */
-
- }, {
- key: '_scheme',
- get: function get$$1() {
- return scheme$1;
- }
-
- /**
- * @return {Element}
- */
-
- }, {
- key: '_mask',
- get: function get$$1() {
- return util$1.findChild(this, '.alert-dialog-mask');
- }
-
- /**
- * @return {Element}
- */
-
- }, {
- key: '_dialog',
- get: function get$$1() {
- return util$1.findChild(this, '.alert-dialog');
- }
-
- /**
- * @return {Element}
- */
-
- }, {
- key: '_titleElement',
- get: function get$$1() {
- return util$1.findChild(this._dialog.children[0], '.alert-dialog-title');
- }
-
- /**
- * @return {Element}
- */
-
- }, {
- key: '_contentElement',
- get: function get$$1() {
- return util$1.findChild(this._dialog.children[0], '.alert-dialog-content');
- }
- }], [{
- key: 'registerAnimator',
- value: function registerAnimator(name, Animator) {
- if (!(Animator.prototype instanceof AlertDialogAnimator)) {
- util$1.throwAnimator('AlertDialog');
- }
- _animatorDict$1[name] = Animator;
- }
- }, {
- key: 'animators',
- get: function get$$1() {
- return _animatorDict$1;
- }
- }, {
- key: 'AlertDialogAnimator',
- get: function get$$1() {
- return AlertDialogAnimator;
- }
- }]);
- return AlertDialogElement;
- }(BaseDialogElement);
-
- onsElements.AlertDialog = AlertDialogElement;
- customElements.define('ons-alert-dialog', AlertDialogElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * @element ons-alert-dialog-button
- * @modifier material
- * [en]Material Design alert-dialog button.[/en]
- * [ja]マテリアルデザインのボタンを表示します。[/ja]
- * @description
- * [en][/en]
- * [ja][/ja]
- * @seealso ons-alert-dialog
- * [en]The `<ons-alert-dialog>` component displays a alert dialog.[/en]
- * [ja]ons-alert-dialogコンポーネント[/ja]
- * @example
- * <ons-alert-dialog>
- * <div class="alert-dialog-title">Warning!</div>
- * <div class="alert-dialog-content">
- * An error has occurred!
- * </div>
- * <div class="alert-dialog-footer">
- * <alert-dialog-button onclick="app.close()">Cancel</alert-dialog-button>
- * <alert-dialog-button class="alert-dialog-button" onclick="app.close()">OK</alert-dialog-button>
- * </div>
- * </ons-alert-dialog>
- */
-
- var AlertDialogButtonElement = function (_BaseButtonElement) {
- inherits(AlertDialogButtonElement, _BaseButtonElement);
-
- function AlertDialogButtonElement() {
- classCallCheck(this, AlertDialogButtonElement);
- return possibleConstructorReturn(this, (AlertDialogButtonElement.__proto__ || Object.getPrototypeOf(AlertDialogButtonElement)).apply(this, arguments));
- }
-
- createClass(AlertDialogButtonElement, [{
- key: '_scheme',
-
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the button.[/en]
- * [ja]ボタンの表現を指定します。[/ja]
- */
-
- /**
- * @attribute disabled
- * @description
- * [en]Specify if button should be disabled.[/en]
- * [ja]ボタンを無効化する場合は指定してください。[/ja]
- */
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the element is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- get: function get$$1() {
- return { '': 'alert-dialog-button--*' };
- }
- }, {
- key: '_defaultClassName',
- get: function get$$1() {
- return 'alert-dialog-button';
- }
- }, {
- key: '_rippleOpt',
- get: function get$$1() {
- return [this, undefined, { 'modifier': 'light-gray' }];
- }
- }]);
- return AlertDialogButtonElement;
- }(BaseButtonElement);
-
- onsElements.AlertDialogButton = AlertDialogButtonElement;
- customElements.define('ons-alert-dialog-button', AlertDialogButtonElement);
-
- var iosBackButtonIcon = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<svg width=\"13px\" height=\"21px\" viewBox=\"0 0 13 21\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <title>ios-back-button-icon</title>\n <desc>Created with Sketch.</desc>\n <defs></defs>\n <g id=\"toolbar-back-button\" stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n <g id=\"ios\" transform=\"translate(-34.000000, -30.000000)\">\n <polygon id=\"ios-back-button-icon\" points=\"34 40.5 44.5 30 46.5 32 38 40.5 46.5 49 44.5 51\"></polygon>\n </g>\n </g>\n</svg>\n";
-
- var mdBackButtonIcon = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<svg width=\"16px\" height=\"16px\" viewBox=\"0 0 16 16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <title>md-back-button-icon</title>\n <desc>Created with Sketch.</desc>\n <defs></defs>\n <g id=\"toolbar-back-button\" stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n <g id=\"android\" transform=\"translate(-32.000000, -32.000000)\" fill-rule=\"nonzero\">\n <polygon id=\"md-back-button-icon\" points=\"48 39 35.83 39 41.42 33.41 40 32 32 40 40 48 41.41 46.59 35.83 41 48 41\"></polygon>\n </g>\n </g>\n</svg>\n";
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var defaultClassName = 'back-button';
-
- var scheme$2 = {
- '': 'back-button--*',
- '.back-button__icon': 'back-button--*__icon',
- '.back-button__label': 'back-button--*__label'
- };
-
- /**
- * @element ons-back-button
- * @category navigation
- * @description
- * [en]
- * Back button component for `<ons-toolbar>`. Put it in the left part of the `<ons-toolbar>`.
- *
- * It will find the parent `<ons-navigator>` element and pop a page when clicked. This behavior can be overriden by specifying the `onClick` property.
- * [/en]
- * [ja][/ja]
- * @codepen aHmGL
- * @tutorial vanilla/Reference/back-button
- * @modifier material
- * [en]Material Design style[/en]
- * [ja][/ja]
- * @seealso ons-toolbar
- * [en]ons-toolbar component[/en]
- * [ja]ons-toolbarコンポーネント[/ja]
- * @seealso ons-navigator
- * [en]ons-navigator component[/en]
- * [ja]ons-navigatorコンポーネント[/ja]
- * @example
- * <ons-toolbar>
- * <div class="left">
- * <ons-back-button>Back</ons-back-button>
- * </div>
- * <div class="center">
- * Title
- * <div>
- * </ons-toolbar>
- */
-
- var BackButtonElement = function (_BaseElement) {
- inherits(BackButtonElement, _BaseElement);
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the back button.[/en]
- * [ja]バックボタンの見た目を指定します。[/ja]
- */
-
- function BackButtonElement() {
- classCallCheck(this, BackButtonElement);
-
- var _this = possibleConstructorReturn(this, (BackButtonElement.__proto__ || Object.getPrototypeOf(BackButtonElement)).call(this));
-
- contentReady(_this, function () {
- _this._compile();
- });
-
- _this._options = {};
- _this._boundOnClick = _this._onClick.bind(_this);
- return _this;
- }
-
- createClass(BackButtonElement, [{
- key: '_updateIcon',
- value: function _updateIcon() {
- var icon = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : util$1.findChild(this, '.back-button__icon');
-
- icon.innerHTML = autoStyle.getPlatform(this) === 'android' || util$1.hasModifier(this, 'material') ? mdBackButtonIcon : iosBackButtonIcon;
- }
- }, {
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
-
- this.classList.add(defaultClassName);
-
- if (!util$1.findChild(this, '.back-button__label')) {
- var label = util$1.create('span.back-button__label');
-
- while (this.childNodes[0]) {
- label.appendChild(this.childNodes[0]);
- }
- this.appendChild(label);
- }
-
- if (!util$1.findChild(this, '.back-button__icon')) {
- var icon = util$1.create('span.back-button__icon');
- this._updateIcon(icon);
-
- this.insertBefore(icon, this.children[0]);
- }
-
- util$1.updateRipple(this, undefined, { center: '', 'size': 'contain', 'background': 'transparent' });
-
- ModifierUtil.initModifier(this, scheme$2);
- }
-
- /**
- * @property options
- * @type {Object}
- * @description
- * [en]Options object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- */
-
- /**
- * @property options.animation
- * @type {String}
- * @description
- * [en]Animation name. Available animations are "slide", "lift", "fade" and "none".
- * These are platform based animations. For fixed animations, add "-ios" or "-md"
- * suffix to the animation name. E.g. "lift-ios", "lift-md". Defaults values are "slide-ios" and "fade-md".
- * [/en]
- * [ja][/ja]
- */
-
- /**
- * @property options.animationOptions
- * @type {String}
- * @description
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}` [/ja]
- */
-
- /**
- * @property options.callback
- * @type {String}
- * @description
- * [en]Function that is called when the transition has ended.[/en]
- * [ja]このメソッドによる画面遷移が終了した際に呼び出される関数オブジェクトを指定します。[/ja]
- */
-
- }, {
- key: '_onClick',
-
-
- /**
- * @property onClick
- * @type {Function}
- * @description
- * [en]Used to override the default back button behavior.[/en]
- * [ja][/ja]
- */
- value: function _onClick() {
- if (this.onClick) {
- this.onClick.apply(this);
- } else {
- var navigator = util$1.findParent(this, 'ons-navigator');
- if (navigator) {
- navigator.popPage(this.options);
- }
- }
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- this.addEventListener('click', this._boundOnClick, false);
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'class':
- util$1.restoreClass(this, defaultClassName, scheme$2);
- break;
-
- case 'modifier':
- {
- ModifierUtil.onModifierChanged(last, current, this, scheme$2) && this._updateIcon();
- break;
- }
- }
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- this.removeEventListener('click', this._boundOnClick, false);
- }
- }, {
- key: 'show',
- value: function show() {
- this.style.display = 'inline-block';
- }
- }, {
- key: 'hide',
- value: function hide() {
- this.style.display = 'none';
- }
- }, {
- key: 'options',
- get: function get$$1() {
- return this._options;
- },
- set: function set$$1(object) {
- this._options = object;
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'class'];
- }
- }]);
- return BackButtonElement;
- }(BaseElement);
-
- onsElements.BackButton = BackButtonElement;
- customElements.define('ons-back-button', BackButtonElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var defaultClassName$1 = 'bottom-bar';
- var scheme$3 = { '': 'bottom-bar--*' };
-
- /**
- * @element ons-bottom-toolbar
- * @category page
- * @description
- * [en]Toolbar component that is positioned at the bottom of the page. Since bottom toolbars are very versatile elements, `ons-bottom-toolbar` does not provide any specific layout syntax for its children. Modifiers or custom CSS must be used.[/en]
- * [ja]ページ下部に配置されるツールバー用コンポーネントです。[/ja]
- * @modifier transparent
- * [en]Make the toolbar transparent.[/en]
- * [ja]ツールバーの背景を透明にして表示します。[/ja]
- * @modifier aligned
- * [en]Vertically aligns its children and applies flexbox for block elements. `justify-content` CSS rule can be used to change horizontal align.[/en]
- * [ja]ツールバーの背景を透明にして表示します。[/ja]
- * @seealso ons-toolbar [en]ons-toolbar component[/en][ja]ons-toolbarコンポーネント[/ja]
- * @example
- * <ons-bottom-toolbar>
- * Content
- * </ons-bottom-toolbar>
- */
-
- var BottomToolbarElement = function (_BaseElement) {
- inherits(BottomToolbarElement, _BaseElement);
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the toolbar.[/en]
- * [ja]ツールバーの見た目の表現を指定します。[/ja]
- */
-
- function BottomToolbarElement() {
- classCallCheck(this, BottomToolbarElement);
-
- var _this = possibleConstructorReturn(this, (BottomToolbarElement.__proto__ || Object.getPrototypeOf(BottomToolbarElement)).call(this));
-
- _this.classList.add(defaultClassName$1);
- ModifierUtil.initModifier(_this, scheme$3);
- return _this;
- }
-
- createClass(BottomToolbarElement, [{
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'class':
- util$1.restoreClass(this, defaultClassName$1, scheme$3);
- break;
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, scheme$3);
- break;
- }
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'class'];
- }
- }]);
- return BottomToolbarElement;
- }(BaseElement);
-
- onsElements.BottomToolbar = BottomToolbarElement;
- customElements.define('ons-bottom-toolbar', BottomToolbarElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * @element ons-button
- * @category form
- * @modifier outline
- * [en]Button with outline and transparent background[/en]
- * [ja]アウトラインを持ったボタンを表示します。[/ja]
- * @modifier light
- * [en]Button that doesn't stand out.[/en]
- * [ja]目立たないボタンを表示します。[/ja]
- * @modifier quiet
- * [en]Button with no outline and or background..[/en]
- * [ja]枠線や背景が無い文字だけのボタンを表示します。[/ja]
- * @modifier cta
- * [en]Button that really stands out.[/en]
- * [ja]目立つボタンを表示します。[/ja]
- * @modifier large
- * [en]Large button that covers the width of the screen.[/en]
- * [ja]横いっぱいに広がる大きなボタンを表示します。[/ja]
- * @modifier large--quiet
- * [en]Large quiet button.[/en]
- * [ja]横いっぱいに広がるquietボタンを表示します。[/ja]
- * @modifier large--cta
- * [en]Large call to action button.[/en]
- * [ja]横いっぱいに広がるctaボタンを表示します。[/ja]
- * @modifier material
- * [en]Material Design button[/en]
- * [ja]マテリアルデザインのボタン[/ja]
- * @modifier material--flat
- * [en]Material Design flat button[/en]
- * [ja]マテリアルデザインのフラットボタン[/ja]
- * @description
- * [en]
- * Button component. If you want to place a button in a toolbar, use `<ons-toolbar-button>` or `<ons-back-button>` instead.
- *
- * Will automatically display as a Material Design button with a ripple effect on Android.
- * [/en]
- * [ja]ボタン用コンポーネント。ツールバーにボタンを設置する場合は、ons-toolbar-buttonもしくはons-back-buttonコンポーネントを使用します。[/ja]
- * @codepen hLayx
- * @tutorial vanilla/Reference/button
- * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
- * @guide theming.html#cross-platform-styling-autostyling [en]Information about cross platform styling[/en][ja]Information about cross platform styling[/ja]
- * @example
- * <ons-button modifier="large--cta">
- * Tap Me
- * </ons-button>
- */
-
- var ButtonElement = function (_BaseButtonElement) {
- inherits(ButtonElement, _BaseButtonElement);
-
- function ButtonElement() {
- classCallCheck(this, ButtonElement);
- return possibleConstructorReturn(this, (ButtonElement.__proto__ || Object.getPrototypeOf(ButtonElement)).apply(this, arguments));
- }
-
- createClass(ButtonElement, [{
- key: '_scheme',
-
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the button.[/en]
- * [ja]ボタンの表現を指定します。[/ja]
- */
-
- /**
- * @attribute ripple
- * @description
- * [en]If this attribute is defined, the button will have a ripple effect.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute disabled
- * @description
- * [en]Specify if button should be disabled.[/en]
- * [ja]ボタンを無効化する場合は指定します。[/ja]
- */
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the button is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- get: function get$$1() {
- return { '': 'button--*' };
- }
- }, {
- key: '_defaultClassName',
- get: function get$$1() {
- return 'button';
- }
- }]);
- return ButtonElement;
- }(BaseButtonElement);
-
- onsElements.Button = ButtonElement;
- customElements.define('ons-button', ButtonElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var defaultClassName$2 = 'card';
- var scheme$4 = {
- '': 'card--*',
- '.card__title': 'card--*__title',
- '.card__content': 'card--*__content'
- };
-
- /**
- * @element ons-card
- * @category visual
- * @modifier material
- * [en]A card with material design.[/en]
- * [ja]リストの上下のボーダーが無いリストを表示します。[/ja]
- * @description
- * [en]
- * Component to create a card that displays some information.
- *
- * The card may be composed by divs with specially prepared classes `title` and/or `content`. You can also add your own content as you please.[/en]
- * [ja][/ja]
- * @tutorial vanilla/Reference/card
- * @example
- * <ons-card>
- * <p>Some content</p>
- * </ons-card>
- */
-
- var CardElement = function (_BaseElement) {
- inherits(CardElement, _BaseElement);
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the card.[/en]
- * [ja]リストの表現を指定します。[/ja]
- */
-
- function CardElement() {
- classCallCheck(this, CardElement);
-
- var _this = possibleConstructorReturn(this, (CardElement.__proto__ || Object.getPrototypeOf(CardElement)).call(this));
-
- contentReady(_this, function () {
- _this._compile();
- });
- return _this;
- }
-
- createClass(CardElement, [{
- key: '_compile',
- value: function _compile() {
- for (var i = 0; i < this.children.length; i++) {
- var el = this.children[i];
-
- if (el.classList.contains('title')) {
- el.classList.add('card__title');
-
- } else if (el.classList.contains('content')) {
- el.classList.add('card__content');
-
- }
- }
-
- autoStyle.prepare(this);
- this.classList.add(defaultClassName$2);
- ModifierUtil.initModifier(this, scheme$4);
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'class':
- util$1.restoreClass(this, defaultClassName$2, scheme$4);
- break;
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, scheme$4);
- break;
- }
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'class'];
- }
- }]);
- return CardElement;
- }(BaseElement);
-
- onsElements.Card = CardElement;
- customElements.define('ons-card', CardElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var scheme$5 = { '': 'carousel-item--*' };
-
- /**
- * @element ons-carousel-item
- * @category carousel
- * @description
- * [en]
- * Carousel item component. Used as a child of the `<ons-carousel>` element.
- * [/en]
- * [ja][/ja]
- * @codepen xbbzOQ
- * @tutorial vanilla/Reference/carousel
- * @seealso ons-carousel
- * [en]`<ons-carousel>` components[/en]
- * [ja]<ons-carousel>コンポーネント[/ja]
- * @example
- * <ons-carousel style="width: 100%; height: 200px">
- * <ons-carousel-item>
- * ...
- * </ons-carousel-item>
- * <ons-carousel-item>
- * ...
- * </ons-carousel-item>
- * </ons-carousel>
- */
-
- var CarouselItemElement = function (_BaseElement) {
- inherits(CarouselItemElement, _BaseElement);
-
- function CarouselItemElement() {
- classCallCheck(this, CarouselItemElement);
-
- var _this = possibleConstructorReturn(this, (CarouselItemElement.__proto__ || Object.getPrototypeOf(CarouselItemElement)).call(this));
-
- _this.style.width = '100%';
- ModifierUtil.initModifier(_this, scheme$5);
- return _this;
- }
-
- createClass(CarouselItemElement, [{
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- if (name === 'modifier') {
- return ModifierUtil.onModifierChanged(last, current, this, scheme$5);
- }
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier'];
- }
- }]);
- return CarouselItemElement;
- }(BaseElement);
-
- onsElements.CarouselItem = CarouselItemElement;
- customElements.define('ons-carousel-item', CarouselItemElement);
-
- var directionMap = {
- vertical: {
- axis: 'Y',
- size: 'Height',
- dir: ['up', 'down'],
- t3d: ['0px, ', 'px, 0px']
- },
- horizontal: {
- axis: 'X',
- size: 'Width',
- dir: ['left', 'right'],
- t3d: ['', 'px, 0px, 0px']
- }
- };
-
- var Swiper = function () {
- function Swiper(params) {
- var _this = this;
-
- classCallCheck(this, Swiper);
-
- // Parameters
- var FALSE = function FALSE() {
- return false;
- };
- 'getInitialIndex getBubbleWidth isVertical isOverScrollable isCentered\n isAutoScrollable refreshHook preChangeHook postChangeHook overScrollHook'.split(/\s+/).forEach(function (key) {
- return _this[key] = params[key] || FALSE;
- });
-
- this.getElement = params.getElement; // Required
- this.scrollHook = params.scrollHook; // Optional
- this.itemSize = params.itemSize || '100%';
-
- this.getAutoScrollRatio = function () {
- var ratio = params.getAutoScrollRatio && params.getAutoScrollRatio.apply(params, arguments);
- ratio = typeof ratio === 'number' && ratio === ratio ? ratio : .5;
- if (ratio < 0.0 || ratio > 1.0) {
- util$1.throw('Invalid auto-scroll-ratio ' + ratio + '. Must be between 0 and 1');
- }
- return ratio;
- };
-
- // Prevent clicks only on desktop
- this.shouldBlock = util$1.globals.actualMobileOS === 'other';
-
- // Bind handlers
- this.onDragStart = this.onDragStart.bind(this);
- this.onDrag = this.onDrag.bind(this);
- this.onDragEnd = this.onDragEnd.bind(this);
- this.onResize = this.onResize.bind(this);
-
- this._shouldFixScroll = util$1.globals.actualMobileOS === 'ios';
- }
-
- createClass(Swiper, [{
- key: 'init',
- value: function init() {
- var _this2 = this;
-
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- swipeable = _ref.swipeable,
- autoRefresh = _ref.autoRefresh;
-
- this.initialized = true;
- this.target = this.getElement().children[0];
- this.blocker = this.getElement().children[1];
- if (!this.target || !this.blocker) {
- util$1.throw('Expected "target" and "blocker" elements to exist before initializing Swiper');
- }
-
- if (!this.shouldBlock) {
- this.blocker.style.display = 'none';
- }
-
- // Add classes
- this.getElement().classList.add('ons-swiper');
- this.target.classList.add('ons-swiper-target');
- this.blocker.classList.add('ons-swiper-blocker');
-
- // Setup listeners
- this._gestureDetector = new GestureDetector(this.getElement(), { dragMinDistance: 1, dragLockToAxis: true, passive: !this._shouldFixScroll });
- this._mutationObserver = new MutationObserver(function () {
- return _this2.refresh();
- });
- this.updateSwipeable(swipeable);
- this.updateAutoRefresh(autoRefresh);
-
- // Setup initial layout
- this._scroll = this._offset = this._lastActiveIndex = 0;
- this._updateLayout();
- this._setupInitialIndex();
- setImmediate(function () {
- return _this2.initialized && _this2._setupInitialIndex();
- });
-
- // Fix rendering glitch on Android 4.1
- // Fix for iframes where the width is inconsistent at the beginning
- if (window !== window.parent || this.offsetHeight === 0) {
- window.requestAnimationFrame(function () {
- return _this2.initialized && _this2.onResize();
- });
- }
- }
- }, {
- key: 'dispose',
- value: function dispose() {
- this.initialized = false;
- this.updateSwipeable(false);
- this.updateAutoRefresh(false);
-
- this._gestureDetector && this._gestureDetector.dispose();
- this.target = this.blocker = this._gestureDetector = this._mutationObserver = null;
-
- this.setupResize(false);
- }
- }, {
- key: 'onResize',
- value: function onResize() {
- var i = this._scroll / this.targetSize;
- this._reset();
- this.setActiveIndex(i);
- this.refresh();
- }
- }, {
- key: '_calculateItemSize',
- value: function _calculateItemSize() {
- var matches = this.itemSize.match(/^(\d+)(px|%)/);
-
- if (!matches) {
- util$1.throw('Invalid state: swiper\'s size unit must be \'%\' or \'px\'');
- }
-
- var value = parseInt(matches[1], 10);
- return matches[2] === '%' ? Math.round(value / 100 * this.targetSize) : value;
- }
- }, {
- key: '_setupInitialIndex',
- value: function _setupInitialIndex() {
- this._reset();
- this._lastActiveIndex = Math.max(Math.min(Number(this.getInitialIndex()), this.itemCount), 0);
- this._scroll = this._offset + this.itemNumSize * this._lastActiveIndex;
- this._scrollTo(this._scroll);
- }
- }, {
- key: '_setSwiping',
- value: function _setSwiping(toggle) {
- this.target.classList.toggle('swiping', toggle); // Hides everything except shown pages
- }
- }, {
- key: 'setActiveIndex',
- value: function setActiveIndex(index) {
- var _this3 = this;
-
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- this._setSwiping(true);
- index = Math.max(0, Math.min(index, this.itemCount - 1));
- var scroll = Math.max(0, Math.min(this.maxScroll, this._offset + this.itemNumSize * index));
-
- if (platform.isUIWebView()) {
- /* Dirty fix for #2231(https://github.com/OnsenUI/OnsenUI/issues/2231). begin */
- var concat = function concat(arrayOfArray) {
- return Array.prototype.concat.apply([], arrayOfArray);
- };
- var contents = concat(util$1.arrayFrom(this.target.children).map(function (page) {
- return util$1.arrayFrom(page.children).filter(function (child) {
- return child.classList.contains('page__content');
- });
- }));
-
- var map = new Map();
- return new Promise(function (resolve) {
- contents.forEach(function (content) {
- map.set(content, content.getAttribute('class'));
- content.classList.add('page__content--suppress-layer-creation');
- });
- requestAnimationFrame(resolve);
- }).then(function () {
- return _this3._changeTo(scroll, options);
- }).then(function () {
- return new Promise(function (resolve) {
- contents.forEach(function (content) {
- content.setAttribute('class', map.get(content));
- });
- requestAnimationFrame(resolve);
- });
- });
- /* end */
- } else {
- return this._changeTo(scroll, options);
- }
- }
- }, {
- key: 'getActiveIndex',
- value: function getActiveIndex() {
- var scroll = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this._scroll;
-
- scroll -= this._offset;
- var count = this.itemCount,
- size = this.itemNumSize;
-
- if (this.itemNumSize === 0 || !util$1.isInteger(scroll)) {
- return this._lastActiveIndex;
- }
-
- if (scroll <= 0) {
- return 0;
- }
-
- for (var i = 0; i < count; i++) {
- if (size * i <= scroll && size * (i + 1) > scroll) {
- return i;
- }
- }
-
- return count - 1;
- }
- }, {
- key: 'setupResize',
- value: function setupResize(add) {
- window[(add ? 'add' : 'remove') + 'EventListener']('resize', this.onResize, true);
- }
- }, {
- key: 'show',
- value: function show() {
- var _this4 = this;
-
- this.setupResize(true);
- this.onResize();
- setTimeout(function () {
- return _this4.target && _this4.target.classList.add('active');
- }, 1000 / 60); // Hide elements after animations
- }
- }, {
- key: 'hide',
- value: function hide() {
- this.setupResize(false);
- this.target.classList.remove('active'); // Show elements before animations
- }
- }, {
- key: 'updateSwipeable',
- value: function updateSwipeable(shouldUpdate) {
- if (this._gestureDetector) {
- var action = shouldUpdate ? 'on' : 'off';
- this._gestureDetector[action]('drag', this.onDrag);
- this._gestureDetector[action]('dragstart', this.onDragStart);
- this._gestureDetector[action]('dragend', this.onDragEnd);
- }
- }
- }, {
- key: 'updateAutoRefresh',
- value: function updateAutoRefresh(shouldWatch) {
- if (this._mutationObserver) {
- shouldWatch ? this._mutationObserver.observe(this.target, { childList: true }) : this._mutationObserver.disconnect();
- }
- }
- }, {
- key: 'updateItemSize',
- value: function updateItemSize(newSize) {
- this.itemSize = newSize || '100%';
- this.refresh();
- }
- }, {
- key: 'toggleBlocker',
- value: function toggleBlocker(block) {
- this.blocker.style.pointerEvents = block ? 'auto' : 'none';
- }
- }, {
- key: '_canConsumeGesture',
- value: function _canConsumeGesture(gesture) {
- var d = gesture.direction;
- var isFirst = this._scroll === 0 && !this.isOverScrollable();
- var isLast = this._scroll === this.maxScroll && !this.isOverScrollable();
-
- return this.isVertical() ? d === 'down' && !isFirst || d === 'up' && !isLast : d === 'right' && !isFirst || d === 'left' && !isLast;
- }
- }, {
- key: 'onDragStart',
- value: function onDragStart(event) {
- var _this5 = this;
-
- this._ignoreDrag = event.consumed || !util$1.isValidGesture(event);
-
- if (!this._ignoreDrag) {
- var consume = event.consume;
- event.consume = function () {
- consume && consume();_this5._ignoreDrag = true;
- };
-
- if (this._canConsumeGesture(event.gesture)) {
- var startX = event.gesture.center && event.gesture.center.clientX || 0,
- distFromEdge = this.getBubbleWidth() || 0,
- start = function start() {
- consume && consume();
- event.consumed = true;
- _this5._started = true; // Avoid starting drag from outside
- _this5.shouldBlock && _this5.toggleBlocker(true);
- _this5._setSwiping(true);
- util$1.iosPreventScroll(_this5._gestureDetector);
- };
-
- // Let parent elements consume the gesture or consume it right away
- startX < distFromEdge || startX > this.targetSize - distFromEdge ? setImmediate(function () {
- return !_this5._ignoreDrag && start();
- }) : start();
- }
- }
- }
- }, {
- key: 'onDrag',
- value: function onDrag(event) {
- if (!event.gesture || this._ignoreDrag || !this._started) {
- return;
- }
-
- this._continued = true; // Fix for random 'dragend' without 'drag'
- event.stopPropagation();
-
- this._scrollTo(this._scroll - this._getDelta(event), { throttle: true });
- }
- }, {
- key: 'onDragEnd',
- value: function onDragEnd(event) {
- this._started = false;
- if (!event.gesture || this._ignoreDrag || !this._continued) {
- this._ignoreDrag = true; // onDragEnd might fire before onDragStart's setImmediate
- return;
- }
-
- this._continued = false;
- event.stopPropagation();
-
- var scroll = this._scroll - this._getDelta(event);
- var normalizedScroll = this._normalizeScroll(scroll);
- scroll === normalizedScroll ? this._startMomentumScroll(scroll, event) : this._killOverScroll(normalizedScroll);
- this.shouldBlock && this.toggleBlocker(false);
- }
- }, {
- key: '_startMomentumScroll',
- value: function _startMomentumScroll(scroll, event) {
- var velocity = this._getVelocity(event),
- matchesDirection = event.gesture.interimDirection === this.dM.dir[this._getDelta(event) < 0 ? 0 : 1];
-
- var nextScroll = this._getAutoScroll(scroll, velocity, matchesDirection);
- var duration = Math.abs(nextScroll - scroll) / (velocity + 0.01) / 1000;
- duration = Math.min(.25, Math.max(.1, duration));
-
- this._changeTo(nextScroll, { swipe: true, animationOptions: { duration: duration, timing: 'cubic-bezier(.4, .7, .5, 1)' } });
- }
- }, {
- key: '_killOverScroll',
- value: function _killOverScroll(scroll) {
- var _this6 = this;
-
- this._scroll = scroll;
- var direction = this.dM.dir[Number(scroll > 0)];
- var killOverScroll = function killOverScroll() {
- return _this6._changeTo(scroll, { animationOptions: { duration: .4, timing: 'cubic-bezier(.1, .4, .1, 1)' } });
- };
- this.overScrollHook({ direction: direction, killOverScroll: killOverScroll }) || killOverScroll();
- }
- }, {
- key: '_changeTo',
- value: function _changeTo(scroll) {
- var _this7 = this;
-
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- var e = { activeIndex: this.getActiveIndex(scroll), lastActiveIndex: this._lastActiveIndex, swipe: options.swipe || false };
- var change = e.activeIndex !== e.lastActiveIndex;
- var canceled = change ? this.preChangeHook(e) : false;
-
- this._scroll = canceled ? this._offset + e.lastActiveIndex * this.itemNumSize : scroll;
- this._lastActiveIndex = canceled ? e.lastActiveIndex : e.activeIndex;
-
- return this._scrollTo(this._scroll, options).then(function () {
- if (scroll === _this7._scroll && !canceled) {
- _this7._setSwiping(false);
- change && _this7.postChangeHook(e);
- } else if (options.reject) {
- _this7._setSwiping(false);
- return Promise.reject('Canceled');
- }
- });
- }
- }, {
- key: '_scrollTo',
- value: function _scrollTo(scroll) {
- var _this8 = this;
-
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- if (options.throttle) {
- var ratio = 0.35;
- if (scroll < 0) {
- scroll = this.isOverScrollable() ? Math.round(scroll * ratio) : 0;
- } else {
- var maxScroll = this.maxScroll;
- if (maxScroll < scroll) {
- scroll = this.isOverScrollable() ? maxScroll + Math.round((scroll - maxScroll) * ratio) : maxScroll;
- }
- }
- }
-
- var opt = options.animation === 'none' ? {} : options.animationOptions;
- this.scrollHook && this.itemNumSize > 0 && this.scrollHook((scroll / this.itemNumSize).toFixed(2), options.animationOptions || {});
-
- return new Promise(function (resolve) {
- return Animit(_this8.target).queue({ transform: _this8._getTransform(scroll) }, opt).play(resolve);
- });
- }
- }, {
- key: '_getAutoScroll',
- value: function _getAutoScroll(scroll, velocity, matchesDirection) {
- var max = this.maxScroll,
- offset = this._offset,
- size = this.itemNumSize;
-
- if (!this.isAutoScrollable()) {
- return Math.max(0, Math.min(max, scroll));
- }
-
- var arr = [];
- for (var s = offset; s < max; s += size) {
- arr.push(s);
- }
- arr.push(max);
-
- arr = arr.sort(function (left, right) {
- return Math.abs(left - scroll) - Math.abs(right - scroll);
- }).filter(function (item, pos) {
- return !pos || item !== arr[pos - 1];
- });
-
- var result = arr[0];
- var lastScroll = this._lastActiveIndex * size + offset;
- var scrollRatio = Math.abs(scroll - lastScroll) / size;
-
- if (scrollRatio <= this.getAutoScrollRatio(matchesDirection, velocity, size)) {
- result = lastScroll;
- } else {
- if (scrollRatio < 1.0 && arr[0] === lastScroll && arr.length > 1) {
- result = arr[1];
- }
- }
- return Math.max(0, Math.min(max, result));
- }
- }, {
- key: '_reset',
- value: function _reset() {
- this._targetSize = this._itemNumSize = undefined;
- }
- }, {
- key: '_normalizeScroll',
- value: function _normalizeScroll(scroll) {
- return Math.max(Math.min(scroll, this.maxScroll), 0);
- }
- }, {
- key: 'refresh',
- value: function refresh() {
- this._reset();
- this._updateLayout();
-
- if (util$1.isInteger(this._scroll)) {
- var scroll = this._normalizeScroll(this._scroll);
- scroll !== this._scroll ? this._killOverScroll(scroll) : this._changeTo(scroll);
- } else {
- this._setupInitialIndex();
- }
-
- this.refreshHook();
- }
- }, {
- key: '_getDelta',
- value: function _getDelta(event) {
- return event.gesture['delta' + this.dM.axis];
- }
- }, {
- key: '_getVelocity',
- value: function _getVelocity(event) {
- return event.gesture['velocity' + this.dM.axis];
- }
- }, {
- key: '_getTransform',
- value: function _getTransform(scroll) {
- return 'translate3d(' + this.dM.t3d[0] + -scroll + this.dM.t3d[1] + ')';
- }
- }, {
- key: '_updateLayout',
- value: function _updateLayout() {
- this.dM = directionMap[this.isVertical() ? 'vertical' : 'horizontal'];
- this.target.classList.toggle('ons-swiper-target--vertical', this.isVertical());
-
- for (var c = this.target.children[0]; c; c = c.nextElementSibling) {
- c.style[this.dM.size.toLowerCase()] = this.itemSize;
- }
-
- if (this.isCentered()) {
- this._offset = (this.targetSize - this.itemNumSize) / -2 || 0;
- }
- }
- }, {
- key: 'itemCount',
- get: function get$$1() {
- return this.target.children.length;
- }
- }, {
- key: 'itemNumSize',
- get: function get$$1() {
- if (typeof this._itemNumSize !== 'number' || this._itemNumSize !== this._itemNumSize) {
- this._itemNumSize = this._calculateItemSize();
- }
- return this._itemNumSize;
- }
- }, {
- key: 'maxScroll',
- get: function get$$1() {
- var max = this.itemCount * this.itemNumSize - this.targetSize;
- return Math.ceil(max < 0 ? 0 : max); // Need to return an integer value.
- }
- }, {
- key: 'targetSize',
- get: function get$$1() {
- if (!this._targetSize) {
- this._targetSize = this.target['offset' + this.dM.size];
- }
- return this._targetSize;
- }
- }]);
- return Swiper;
- }();
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * @element ons-carousel
- * @category carousel
- * @description
- * [en]
- * Carousel component. A carousel can be used to display several items in the same space.
- *
- * The component supports displaying content both horizontally and vertically. The user can scroll through the items by dragging and it can also be controller programmatically.
- * [/en]
- * [ja][/ja]
- * @codepen xbbzOQ
- * @tutorial vanilla/Reference/carousel
- * @seealso ons-carousel-item
- * [en]`<ons-carousel-item>` component[/en]
- * [ja]ons-carousel-itemコンポーネント[/ja]
- * @example
- * <ons-carousel style="width: 100%; height: 200px">
- * <ons-carousel-item>
- * ...
- * </ons-carousel-item>
- * <ons-carousel-item>
- * ...
- * </ons-carousel-item>
- * </ons-carousel>
- */
-
- var CarouselElement = function (_BaseElement) {
- inherits(CarouselElement, _BaseElement);
-
- /**
- * @event postchange
- * @description
- * [en]Fired just after the current carousel item has changed.[/en]
- * [ja]現在表示しているカルーセルの要素が変わった時に発火します。[/ja]
- * @param {Object} event
- * [en]Event object.[/en]
- * [ja]イベントオブジェクトです。[/ja]
- * @param {Object} event.carousel
- * [en]Carousel object.[/en]
- * [ja]イベントが発火したCarouselオブジェクトです。[/ja]
- * @param {Number} event.activeIndex
- * [en]Current active index.[/en]
- * [ja]現在アクティブになっている要素のインデックス。[/ja]
- * @param {Number} event.lastActiveIndex
- * [en]Previous active index.[/en]
- * [ja]以前アクティブだった要素のインデックス。[/ja]
- */
-
- /**
- * @event refresh
- * @description
- * [en]Fired when the carousel has been refreshed.[/en]
- * [ja]カルーセルが更新された時に発火します。[/ja]
- * @param {Object} event
- * [en]Event object.[/en]
- * [ja]イベントオブジェクトです。[/ja]
- * @param {Object} event.carousel
- * [en]Carousel object.[/en]
- * [ja]イベントが発火したCarouselオブジェクトです。[/ja]
- */
-
- /**
- * @event overscroll
- * @description
- * [en]Fired when the carousel has been overscrolled.[/en]
- * [ja]カルーセルがオーバースクロールした時に発火します。[/ja]
- * @param {Object} event
- * [en]Event object.[/en]
- * [ja]イベントオブジェクトです。[/ja]
- * @param {Object} event.carousel
- * [en]Fired when the carousel has been refreshed.[/en]
- * [ja]カルーセルが更新された時に発火します。[/ja]
- * @param {Number} event.activeIndex
- * [en]Current active index.[/en]
- * [ja]現在アクティブになっている要素のインデックス。[/ja]
- * @param {String} event.direction
- * [en]Can be one of either "up", "down", "left" or "right".[/en]
- * [ja]オーバースクロールされた方向が得られます。"up", "down", "left", "right"のいずれかの方向が渡されます。[/ja]
- * @param {Function} event.waitToReturn
- * [en]Takes a <code>Promise</code> object as an argument. The carousel will not scroll back until the promise has been resolved or rejected.[/en]
- * [ja]この関数はPromiseオブジェクトを引数として受け取ります。渡したPromiseオブジェクトがresolveされるかrejectされるまで、カルーセルはスクロールバックしません。[/ja]
- */
-
- /**
- * @attribute direction
- * @type {String}
- * @description
- * [en]The direction of the carousel. Can be either "horizontal" or "vertical". Default is "horizontal".[/en]
- * [ja]カルーセルの方向を指定します。"horizontal"か"vertical"を指定できます。"horizontal"がデフォルト値です。[/ja]
- */
-
- /**
- * @attribute fullscreen
- * @description
- * [en]If this attribute is set the carousel will cover the whole screen.[/en]
- * [ja]この属性があると、absoluteポジションを使ってカルーセルが自動的に画面いっぱいに広がります。[/ja]
- */
-
- /**
- * @attribute overscrollable
- * @description
- * [en]If this attribute is set the carousel will be scrollable over the edge. It will bounce back when released.[/en]
- * [ja]この属性がある時、タッチやドラッグで端までスクロールした時に、バウンドするような効果が当たります。[/ja]
- */
-
- /**
- * @attribute centered
- * @description
- * [en]If this attribute is set the carousel then the selected item will be in the center of the carousel instead of the beginning. Useful only when the items are smaller than the carousel. [/en]
- * [ja]この属性がある時、選んでいるons-carousel-itemはカルーセルの真ん中へ行きます。項目がカルーセルよりも小さい場合にのみ、これは便利です。[/ja]
- */
-
- /**
- * @attribute item-width
- * @type {String}
- * @description
- * [en]ons-carousel-item's width. Only works when the direction is set to "horizontal".[/en]
- * [ja]ons-carousel-itemの幅を指定します。この属性は、direction属性に"horizontal"を指定した時のみ有効になります。[/ja]
- */
-
- /**
- * @attribute item-height
- * @type {String}
- * @description
- * [en]ons-carousel-item's height. Only works when the direction is set to "vertical".[/en]
- * [ja]ons-carousel-itemの高さを指定します。この属性は、direction属性に"vertical"を指定した時のみ有効になります。[/ja]
- */
-
- /**
- * @attribute auto-scroll
- * @description
- * [en]If this attribute is set the carousel will be automatically scrolled to the closest item border when released.[/en]
- * [ja]この属性がある時、一番近いcarousel-itemの境界まで自動的にスクロールするようになります。[/ja]
- */
-
- /**
- * @attribute auto-scroll-ratio
- * @type {Number}
- * @description
- * [en]A number between 0.0 and 1.0 that specifies how much the user must drag the carousel in order for it to auto scroll to the next item.[/en]
- * [ja]0.0から1.0までの値を指定します。カルーセルの要素をどれぐらいの割合までドラッグすると次の要素に自動的にスクロールするかを指定します。[/ja]
- */
-
- /**
- * @attribute swipeable
- * @description
- * [en]If this attribute is set the carousel can be scrolled by drag or swipe.[/en]
- * [ja]この属性がある時、カルーセルをスワイプやドラッグで移動できるようになります。[/ja]
- */
-
- /**
- * @attribute disabled
- * @description
- * [en]If this attribute is set the carousel is disabled.[/en]
- * [ja]この属性がある時、dragやtouchやswipeを受け付けなくなります。[/ja]
- */
-
- /**
- * @attribute initial-index
- * @initonly
- * @default 0
- * @type {Number}
- * @description
- * [en]Specify the index of the ons-carousel-item to show initially. Default is 0.[/en]
- * [ja]最初に表示するons-carousel-itemを0始まりのインデックスで指定します。デフォルト値は 0 です。[/ja]
- */
-
- /**
- * @attribute auto-refresh
- * @description
- * [en]When this attribute is set the carousel will automatically refresh when the number of child nodes change.[/en]
- * [ja]この属性がある時、子要素の数が変わるとカルーセルは自動的に更新されるようになります。[/ja]
- */
-
- /**
- * @attribute animation
- * @type {String}
- * @description
- * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute animation-options
- * @type {Expression}
- * @description
- * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。例:{duration: 0.2, delay: 1, timing: 'ease-in'}[/ja]
- */
-
- function CarouselElement() {
- classCallCheck(this, CarouselElement);
-
- var _this = possibleConstructorReturn(this, (CarouselElement.__proto__ || Object.getPrototypeOf(CarouselElement)).call(this));
-
- contentReady(_this, function () {
- return _this._compile();
- });
- return _this;
- }
-
- createClass(CarouselElement, [{
- key: '_compile',
- value: function _compile() {
- var target = this.children[0] && this.children[0].tagName !== 'ONS-CAROUSEL-ITEM' && this.children[0] || document.createElement('div');
- if (!target.parentNode) {
- while (this.firstChild) {
- target.appendChild(this.firstChild);
- }
- this.appendChild(target);
- }
-
- !this.children[1] && this.appendChild(document.createElement('div'));
-
- this.appendChild = this.appendChild.bind(target);
- this.insertBefore = this.insertBefore.bind(target);
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- var _this2 = this;
-
- if (!this._swiper) {
- this._swiper = new Swiper({
- getElement: function getElement() {
- return _this2;
- },
- getInitialIndex: function getInitialIndex() {
- return _this2.getAttribute('initial-index');
- },
- getAutoScrollRatio: function getAutoScrollRatio() {
- return _this2.autoScrollRatio;
- },
- isVertical: function isVertical() {
- return _this2.vertical;
- },
- isOverScrollable: function isOverScrollable() {
- return _this2.overscrollable;
- },
- isCentered: function isCentered() {
- return _this2.centered;
- },
- isAutoScrollable: function isAutoScrollable() {
- return _this2.autoScroll;
- },
- itemSize: this.itemSize,
- overScrollHook: this._onOverScroll.bind(this),
- preChangeHook: this._onChange.bind(this, 'prechange'),
- postChangeHook: this._onChange.bind(this, 'postchange'),
- refreshHook: this._onRefresh.bind(this),
- scrollHook: function scrollHook() {
- return _this2._onSwipe && _this2._onSwipe.apply(_this2, arguments);
- }
- });
-
- contentReady(this, function () {
- return _this2._swiper.init({
- swipeable: _this2.hasAttribute('swipeable'),
- autoRefresh: _this2.hasAttribute('auto-refresh')
- });
- });
- }
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- if (this._swiper && this._swiper.initialized) {
- this._swiper.dispose();
- this._swiper = null;
- }
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- if (!this._swiper) {
- return;
- }
-
- switch (name) {
- case 'swipeable':
- this._swiper.updateSwipeable(this.hasAttribute('swipeable'));
- break;
- case 'auto-refresh':
- this._swiper.updateAutoRefresh(this.hasAttribute('auto-refresh'));
- break;
- case 'item-height':
- this.vertical && this._swiper.updateItemSize(this.itemSize);
- break;
- case 'item-width':
- this.vertical || this._swiper.updateItemSize(this.itemSize);
- break;
- case 'direction':
- this._swiper.refresh();
- }
- }
- }, {
- key: '_show',
- value: function _show() {
- this._swiper.show();
- }
- }, {
- key: '_hide',
- value: function _hide() {
- this._swiper.hide();
- }
- }, {
- key: '_onOverScroll',
- value: function _onOverScroll(_ref) {
- var direction = _ref.direction,
- killOverScroll = _ref.killOverScroll;
-
- var waitForAction = false;
- util$1.triggerElementEvent(this, 'overscroll', {
- carousel: this,
- activeIndex: this.getActiveIndex(),
- direction: direction,
- waitToReturn: function waitToReturn(promise) {
- waitForAction = true;
- promise.then(killOverScroll);
- }
- });
-
- return waitForAction;
- }
- }, {
- key: '_onChange',
- value: function _onChange(eventName, _ref2) {
- var activeIndex = _ref2.activeIndex,
- lastActiveIndex = _ref2.lastActiveIndex;
-
- util$1.triggerElementEvent(this, eventName, { carousel: this, activeIndex: activeIndex, lastActiveIndex: lastActiveIndex });
- }
- }, {
- key: '_onRefresh',
- value: function _onRefresh() {
- util$1.triggerElementEvent(this, 'refresh', { carousel: this });
- }
-
- /**
- * @method setActiveIndex
- * @signature setActiveIndex(index, [options])
- * @param {Number} index
- * [en]The index that the carousel should be set to.[/en]
- * [ja]carousel要素のインデックスを指定します。[/ja]
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja][/ja]
- * @param {Function} [options.callback]
- * [en]A function that will be called after the animation is finished.[/en]
- * [ja][/ja]
- * @param {String} [options.animation]
- * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en]
- * [ja][/ja]
- * @param {Object} [options.animationOptions]
- * [en]An object that can be used to specify duration, delay and timing function of the animation.[/en]
- * [ja][/ja]
- * @description
- * [en]Specify the index of the `<ons-carousel-item>` to show.[/en]
- * [ja]表示するons-carousel-itemをindexで指定します。[/ja]
- * @return {Promise}
- * [en]Resolves to the carousel element.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'setActiveIndex',
- value: function setActiveIndex(index) {
- var _this3 = this;
-
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- options = _extends({
- animation: this.getAttribute('animation'),
- animationOptions: this.hasAttribute('animation-options') ? util$1.animationOptionsParse(this.getAttribute('animation-options')) : { duration: .3, timing: 'cubic-bezier(.4, .7, .5, 1)' }
- }, options);
-
- return this._swiper.setActiveIndex(index, options).then(function () {
- options.callback instanceof Function && options.callback(_this3);
- return Promise.resolve(_this3);
- });
- }
-
- /**
- * @method getActiveIndex
- * @signature getActiveIndex()
- * @return {Number}
- * [en]The current carousel item index.[/en]
- * [ja]現在表示しているカルーセル要素のインデックスが返されます。[/ja]
- * @description
- * [en]Returns the index of the currently visible `<ons-carousel-item>`.[/en]
- * [ja]現在表示されているons-carousel-item要素のインデックスを返します。[/ja]
- */
-
- }, {
- key: 'getActiveIndex',
- value: function getActiveIndex() {
- return this._swiper.getActiveIndex();
- }
-
- /**
- * @method next
- * @signature next([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja][/ja]
- * @param {Function} [options.callback]
- * [en]A function that will be executed after the animation has finished.[/en]
- * [ja][/ja]
- * @param {String} [options.animation]
- * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en]
- * [ja][/ja]
- * @param {Object} [options.animationOptions]
- * [en]An object that can be used to specify the duration, delay and timing function of the animation.[/en]
- * [ja][/ja]
- * @return {Promise}
- * [en]Resolves to the carousel element[/en]
- * [ja][/ja]
- * @description
- * [en]Show next `<ons-carousel-item>`.[/en]
- * [ja]次のons-carousel-itemを表示します。[/ja]
- */
-
- }, {
- key: 'next',
- value: function next(options) {
- return this.setActiveIndex(this.getActiveIndex() + 1, options);
- }
-
- /**
- * @method prev
- * @signature prev([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja][/ja]
- * @param {Function} [options.callback]
- * [en]A function that will be executed after the animation has finished.[/en]
- * [ja][/ja]
- * @param {String} [options.animation]
- * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en]
- * [ja][/ja]
- * @param {Object} [options.animationOptions]
- * [en]An object that can be used to specify the duration, delay and timing function of the animation.[/en]
- * [ja][/ja]
- * @return {Promise}
- * [en]Resolves to the carousel element[/en]
- * [ja][/ja]
- * @description
- * [en]Show previous `<ons-carousel-item>`.[/en]
- * [ja]前のons-carousel-itemを表示します。[/ja]
- */
-
- }, {
- key: 'prev',
- value: function prev(options) {
- return this.setActiveIndex(this.getActiveIndex() - 1, options);
- }
-
- /**
- * @method first
- * @signature first()
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja][/ja]
- * @param {Function} [options.callback]
- * [en]A function that will be executed after the animation has finished.[/en]
- * [ja][/ja]
- * @param {String} [options.animation]
- * [en]If this is set to `"none"`, the transitions will not be animated.[/en]
- * [ja][/ja]
- * @param {Object} [options.animationOptions]
- * [en]An object that can be used to specify the duration, delay and timing function of the animation.[/en]
- * [ja][/ja]
- * @return {Promise}
- * [en]Resolves to the carousel element[/en]
- * [ja][/ja]
- * @description
- * [en]Show first `<ons-carousel-item>`.[/en]
- * [ja]最初のons-carousel-itemを表示します。[/ja]
- */
-
- }, {
- key: 'first',
- value: function first(options) {
- return this.setActiveIndex(0, options);
- }
-
- /**
- * @method last
- * @signature last()
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja][/ja]
- * @param {Function} [options.callback]
- * [en]A function that will be executed after the animation has finished.[/en]
- * [ja][/ja]
- * @param {String} [options.animation]
- * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en]
- * [ja][/ja]
- * @param {Object} [options.animationOptions]
- * [en]An object that can be used to specify the duration, delay and timing function of the animation.[/en]
- * [ja][/ja]
- * @return {Promise}
- * [en]Resolves to the carousel element[/en]
- * [ja]Resolves to the carousel element[/ja]
- * @description
- * [en]Show last ons-carousel item.[/en]
- * [ja]最後のons-carousel-itemを表示します。[/ja]
- */
-
- }, {
- key: 'last',
- value: function last(options) {
- this.setActiveIndex(Math.max(this.itemCount - 1, 0), options);
- }
-
- /**
- * @method refresh
- * @signature refresh()
- * @description
- * [en]Update the layout of the carousel. Used when adding `<ons-carousel-items>` dynamically or to automatically adjust the size.[/en]
- * [ja]レイアウトや内部の状態を最新のものに更新します。ons-carousel-itemを動的に増やしたり、ons-carouselの大きさを動的に変える際に利用します。[/ja]
- */
-
- }, {
- key: 'refresh',
- value: function refresh() {
- this._swiper.refresh();
- }
-
- /**
- * @property itemCount
- * @readonly
- * @type {Number}
- * @description
- * [en]The number of carousel items.[/en]
- * [ja]カルーセル要素の数です。[/ja]
- */
-
- }, {
- key: 'itemCount',
- get: function get$$1() {
- return this._swiper.itemCount;
- }
-
- /**
- * @property swipeable
- * @type {Boolean}
- * @description
- * [en]true if the carousel is swipeable.[/en]
- * [ja]swipeableであればtrueを返します。[/ja]
- */
-
- }, {
- key: 'swipeable',
- get: function get$$1() {
- return this.hasAttribute('swipeable');
- },
- set: function set$$1(value) {
- return util$1.toggleAttribute(this, 'swipeable', value);
- }
-
- /**
- * @property onSwipe
- * @type {Function}
- * @description
- * [en]Hook called whenever the user slides the carousel. It gets a decimal index and an animationOptions object as arguments.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'onSwipe',
- get: function get$$1() {
- return this._onSwipe;
- },
- set: function set$$1(value) {
- if (value && !(value instanceof Function)) {
- util$1.throw('"onSwipe" must be a function');
- }
- this._onSwipe = value;
- }
-
- /**
- * @property autoScroll
- * @type {Boolean}
- * @description
- * [en]true if auto scroll is enabled.[/en]
- * [ja]オートスクロールが有効であればtrueを返します。[/ja]
- */
-
- }, {
- key: 'autoScroll',
- get: function get$$1() {
- return this.hasAttribute('auto-scroll');
- },
- set: function set$$1(value) {
- return util$1.toggleAttribute(this, 'auto-scroll', value);
- }
- }, {
- key: 'vertical',
- get: function get$$1() {
- return this.getAttribute('direction') === 'vertical';
- }
- }, {
- key: 'itemSize',
- get: function get$$1() {
- var itemSizeAttr = (this.getAttribute('item-' + (this.vertical ? 'height' : 'width')) || '').trim();
- return itemSizeAttr.match(/^\d+(px|%)$/) ? itemSizeAttr : '100%';
- }
-
- /**
- * @property autoScrollRatio
- * @type {Number}
- * @description
- * [en]The current auto scroll ratio. [/en]
- * [ja]現在のオートスクロールのratio値。[/ja]
- */
-
- }, {
- key: 'autoScrollRatio',
- get: function get$$1() {
- return parseFloat(this.getAttribute('auto-scroll-ratio'));
- },
- set: function set$$1(ratio) {
- this.setAttribute('auto-scroll-ratio', ratio);
- }
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the carousel is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- }, {
- key: 'disabled',
- get: function get$$1() {
- return this.hasAttribute('disabled');
- },
- set: function set$$1(value) {
- return util$1.toggleAttribute(this, 'disabled', value);
- }
-
- /**
- * @property overscrollable
- * @type {Boolean}
- * @description
- * [en]Whether the carousel is overscrollable or not.[/en]
- * [ja]overscrollできればtrueを返します。[/ja]
- */
-
- }, {
- key: 'overscrollable',
- get: function get$$1() {
- return this.hasAttribute('overscrollable');
- },
- set: function set$$1(value) {
- return util$1.toggleAttribute(this, 'overscrollable', value);
- }
-
- /**
- * @property centered
- * @type {Boolean}
- * @description
- * [en]Whether the carousel is centered or not.[/en]
- * [ja]centered状態になっていればtrueを返します。[/ja]
- */
-
- }, {
- key: 'centered',
- get: function get$$1() {
- return this.hasAttribute('centered');
- },
- set: function set$$1(value) {
- return util$1.toggleAttribute(this, 'centered', value);
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['swipeable', 'auto-refresh', 'direction', 'item-height', 'item-width'];
- }
- }, {
- key: 'events',
- get: function get$$1() {
- return ['postchange', 'refresh', 'overscroll'];
- }
- }]);
- return CarouselElement;
- }(BaseElement);
-
- onsElements.Carousel = CarouselElement;
- customElements.define('ons-carousel', CarouselElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * @element ons-col
- * @category grid
- * @description
- * [en]Represents a column in the grid system. Use with `<ons-row>` to layout components.[/en]
- * [ja]グリッドシステムにて列を定義します。ons-rowとともに使用し、コンポーネントのレイアウトに利用します。[/ja]
- * @note
- * [en]For Android 4.3 and earlier, and iOS6 and earlier, when using mixed alignment with ons-row and ons-column, they may not be displayed correctly. You can use only one alignment.[/en]
- * [ja]Android 4.3以前、もしくはiOS 6以前のOSの場合、ons-rowとons-columnを組み合わせた場合に描画が崩れる場合があります。[/ja]
- * @codepen GgujC {wide}
- * @guide theming.html [en]Layouting guide[/en][ja]レイアウト機能[/ja]
- * @seealso ons-row
- * [en]The `<ons-row>` component is the parent of `<ons-col>`.[/en]
- * [ja]ons-rowコンポーネント[/ja]
- * @example
- * <ons-row>
- * <ons-col width="50px"><ons-icon icon="fa-twitter"></ons-icon></ons-col>
- * <ons-col>Text</ons-col>
- * </ons-row>
- */
-
- /**
- * @attribute vertical-align
- * @type {String}
- * @description
- * [en]Vertical alignment of the column. Valid values are "top", "center", and "bottom".[/en]
- * [ja]縦の配置を指定する。"top", "center", "bottom"のいずれかを指定します。[/ja]
- */
-
- /**
- * @attribute width
- * @type {String}
- * @description
- * [en]The width of the column. Valid values are css width values ("10%", "50px").[/en]
- * [ja]カラムの横幅を指定する。パーセントもしくはピクセルで指定します(10%や50px)。[/ja]
- */
-
- var ColElement = function (_BaseElement) {
- inherits(ColElement, _BaseElement);
-
- function ColElement() {
- classCallCheck(this, ColElement);
-
- var _this = possibleConstructorReturn(this, (ColElement.__proto__ || Object.getPrototypeOf(ColElement)).call(this));
-
- if (_this.getAttribute('width')) {
- _this._updateWidth();
- }
- return _this;
- }
-
- createClass(ColElement, [{
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- if (name === 'width') {
- this._updateWidth();
- }
- }
- }, {
- key: '_updateWidth',
- value: function _updateWidth() {
- var width = this.getAttribute('width');
- if (!width) {
- styler.clear(this, 'flex maxWidth');
- } else {
- width = width.trim().match(/^\d+$/) ? width + '%' : width;
-
- styler(this, {
- flex: '0 0 ' + width,
- maxWidth: width
- });
- }
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['width'];
- }
- }]);
- return ColElement;
- }(BaseElement);
-
- onsElements.Col = ColElement;
- customElements.define('ons-col', ColElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var DialogAnimator = function (_BaseAnimator) {
- inherits(DialogAnimator, _BaseAnimator);
-
- function DialogAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'linear' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.2 : _ref$duration;
-
- classCallCheck(this, DialogAnimator);
- return possibleConstructorReturn(this, (DialogAnimator.__proto__ || Object.getPrototypeOf(DialogAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
- }
-
- /**
- * @param {HTMLElement} dialog
- * @param {Function} done
- */
-
-
- createClass(DialogAnimator, [{
- key: 'show',
- value: function show(dialog, done) {
- done();
- }
-
- /**
- * @param {HTMLElement} dialog
- * @param {Function} done
- */
-
- }, {
- key: 'hide',
- value: function hide(dialog, done) {
- done();
- }
- }]);
- return DialogAnimator;
- }(BaseAnimator);
-
- /**
- * Android style animator for dialog.
- */
- var AndroidDialogAnimator = function (_DialogAnimator) {
- inherits(AndroidDialogAnimator, _DialogAnimator);
-
- function AndroidDialogAnimator() {
- var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref2$timing = _ref2.timing,
- timing = _ref2$timing === undefined ? 'ease-in-out' : _ref2$timing,
- _ref2$delay = _ref2.delay,
- delay = _ref2$delay === undefined ? 0 : _ref2$delay,
- _ref2$duration = _ref2.duration,
- duration = _ref2$duration === undefined ? 0.3 : _ref2$duration;
-
- classCallCheck(this, AndroidDialogAnimator);
- return possibleConstructorReturn(this, (AndroidDialogAnimator.__proto__ || Object.getPrototypeOf(AndroidDialogAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
- }
-
- /**
- * @param {Object} dialog
- * @param {Function} callback
- */
-
-
- createClass(AndroidDialogAnimator, [{
- key: 'show',
- value: function show(dialog, callback) {
- callback = callback ? callback : function () {};
-
- Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 0 }, { opacity: 1 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, -60%, 0)', opacity: 0 }, { transform: 'translate3d(-50%, -50%, 0)', opacity: 1 }).queue(function (done) {
- callback();
- done();
- }));
- }
-
- /**
- * @param {Object} dialog
- * @param {Function} callback
- */
-
- }, {
- key: 'hide',
- value: function hide(dialog, callback) {
- callback = callback ? callback : function () {};
-
- Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 1 }, { opacity: 0 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, -50%, 0)', opacity: 1 }, { transform: 'translate3d(-50%, -60%, 0)', opacity: 0 }).queue(function (done) {
- callback();
- done();
- }));
- }
- }]);
- return AndroidDialogAnimator;
- }(DialogAnimator);
-
- /**
- * iOS style animator for dialog.
- */
- var IOSDialogAnimator = function (_DialogAnimator2) {
- inherits(IOSDialogAnimator, _DialogAnimator2);
-
- function IOSDialogAnimator() {
- var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref3$timing = _ref3.timing,
- timing = _ref3$timing === undefined ? 'ease-in-out' : _ref3$timing,
- _ref3$delay = _ref3.delay,
- delay = _ref3$delay === undefined ? 0 : _ref3$delay,
- _ref3$duration = _ref3.duration,
- duration = _ref3$duration === undefined ? 0.2 : _ref3$duration;
-
- classCallCheck(this, IOSDialogAnimator);
-
- var _this3 = possibleConstructorReturn(this, (IOSDialogAnimator.__proto__ || Object.getPrototypeOf(IOSDialogAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
-
- _this3.bodyHeight = document.body.clientHeight; // avoid Forced Synchronous Layout
- return _this3;
- }
-
- /**
- * @param {Object} dialog
- * @param {Function} callback
- */
-
-
- createClass(IOSDialogAnimator, [{
- key: 'show',
- value: function show(dialog, callback) {
- callback = callback ? callback : function () {};
-
- Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 0 }, { opacity: 1 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, ' + (this.bodyHeight / 2.0 - 1) + 'px, 0)' }, { transform: 'translate3d(-50%, -50%, 0)' }).queue(function (done) {
- callback();
- done();
- }));
- }
-
- /**
- * @param {Object} dialog
- * @param {Function} callback
- */
-
- }, {
- key: 'hide',
- value: function hide(dialog, callback) {
- callback = callback ? callback : function () {};
-
- Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 1 }, { opacity: 0 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, -50%, 0)' }, { transform: 'translate3d(-50%, ' + (this.bodyHeight / 2.0 - 1) + 'px, 0)' }).queue(function (done) {
- callback();
- done();
- }));
- }
- }]);
- return IOSDialogAnimator;
- }(DialogAnimator);
-
- /**
- * Slide animator for dialog.
- */
- var SlideDialogAnimator = function (_DialogAnimator3) {
- inherits(SlideDialogAnimator, _DialogAnimator3);
-
- function SlideDialogAnimator() {
- var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref4$timing = _ref4.timing,
- timing = _ref4$timing === undefined ? 'cubic-bezier(.1, .7, .4, 1)' : _ref4$timing,
- _ref4$delay = _ref4.delay,
- delay = _ref4$delay === undefined ? 0 : _ref4$delay,
- _ref4$duration = _ref4.duration,
- duration = _ref4$duration === undefined ? 0.2 : _ref4$duration;
-
- classCallCheck(this, SlideDialogAnimator);
-
- var _this4 = possibleConstructorReturn(this, (SlideDialogAnimator.__proto__ || Object.getPrototypeOf(SlideDialogAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
-
- _this4.bodyHeight = document.body.clientHeight; // avoid Forced Synchronous Layout
- return _this4;
- }
-
- /**
- * @param {Object} dialog
- * @param {Function} callback
- */
-
-
- createClass(SlideDialogAnimator, [{
- key: 'show',
- value: function show(dialog, callback) {
- callback = callback ? callback : function () {};
-
- Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 0 }, { opacity: 1 }), Animit(dialog._dialog, this.def).default(
- // FIXME: This should avoid Forced Synchronous Layout. Otherwise, fade animation of mask will be broken.
- { transform: 'translate3d(-50%, ' + (-(this.bodyHeight / 2.0) + 1 - dialog._dialog.clientHeight) + 'px, 0)' }, { transform: 'translate3d(-50%, -50%, 0)' }).queue(function (done) {
- callback();
- done();
- }));
- }
-
- /**
- * @param {Object} dialog
- * @param {Function} callback
- */
-
- }, {
- key: 'hide',
- value: function hide(dialog, callback) {
- callback = callback ? callback : function () {};
-
- Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 1 }, { opacity: 0 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, -50%, 0)' },
- // FIXME: This should avoid Forced Synchronous Layout. Otherwise, fade animation of mask will be broken.
- { transform: 'translate3d(-50%, ' + (-(this.bodyHeight / 2.0) + 1 - dialog._dialog.clientHeight) + 'px, 0)' }).queue(function (done) {
- callback();
- done();
- }));
- }
- }]);
- return SlideDialogAnimator;
- }(DialogAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var scheme$6 = {
- '.dialog': 'dialog--*',
- '.dialog-container': 'dialog-container--*',
- '.dialog-mask': 'dialog-mask--*'
- };
-
- var _animatorDict$2 = {
- 'default': function _default() {
- return platform.isAndroid() ? AndroidDialogAnimator : IOSDialogAnimator;
- },
- 'slide': SlideDialogAnimator,
- 'none': DialogAnimator
- };
-
- /**
- * @element ons-dialog
- * @category dialog
- * @description
- * [en]
- * Dialog that is displayed on top of current screen. As opposed to the `<ons-alert-dialog>` element, this component can contain any kind of content.
- *
- * To use the element it can either be attached directly to the `<body>` element or dynamically created from a template using the `ons.createDialog(template)` utility function and the `<template>` tag.
- *
- * The dialog is useful for displaying menus, additional information or to ask the user to make a decision.
- *
- * It will automatically be displayed as Material Design when running on an Android device.
- * [/en]
- * [ja][/ja]
- * @modifier material
- * [en]Display a Material Design dialog.[/en]
- * [ja]マテリアルデザインのダイアログを表示します。[/ja]
- * @codepen zxxaGa
- * @tutorial vanilla/Reference/dialog
- * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
- * @seealso ons-alert-dialog
- * [en]`<ons-alert-dialog>` component[/en]
- * [ja]ons-alert-dialogコンポーネント[/ja]
- * @seealso ons-popover
- * [en]`<ons-popover>` component[/en]
- * [ja]ons-popoverコンポーネント[/ja]
- * @seealso ons-modal
- * [en]`<ons-modal>` component[/en]
- * [ja]ons-modalコンポーネント[/ja]
- * @example
- * <ons-dialog id="dialog">
- * <p>This is a dialog!</p>
- * </ons-dialog>
- *
- * <script>
- * document.getElementById('dialog').show();
- * </script>
- */
-
- var DialogElement = function (_BaseDialogElement) {
- inherits(DialogElement, _BaseDialogElement);
-
- /**
- * @event preshow
- * @description
- * [en]Fired just before the dialog is displayed.[/en]
- * [ja]ダイアログが表示される直前に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.dialog
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- * @param {Function} event.cancel
- * [en]Execute this function to stop the dialog from being shown.[/en]
- * [ja]この関数を実行すると、ダイアログの表示がキャンセルされます。[/ja]
- */
-
- /**
- * @event postshow
- * @description
- * [en]Fired just after the dialog is displayed.[/en]
- * [ja]ダイアログが表示された直後に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.dialog
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- */
-
- /**
- * @event prehide
- * @description
- * [en]Fired just before the dialog is hidden.[/en]
- * [ja]ダイアログが隠れる直前に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.dialog
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- * @param {Function} event.cancel
- * [en]Execute this function to stop the dialog from being hidden.[/en]
- * [ja]この関数を実行すると、ダイアログの非表示がキャンセルされます。[/ja]
- */
-
- /**
- * @event posthide
- * @description
- * [en]Fired just after the dialog is hidden.[/en]
- * [ja]ダイアログが隠れた後に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.dialog
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- */
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the dialog.[/en]
- * [ja]ダイアログの表現を指定します。[/ja]
- */
-
- /**
- * @attribute cancelable
- * @description
- * [en]If this attribute is set the dialog can be closed by tapping the background or by pressing the back button on Android devices.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute disabled
- * @description
- * [en]If this attribute is set the dialog is disabled.[/en]
- * [ja]この属性がある時、ダイアログはdisabled状態になります。[/ja]
- */
-
- /**
- * @attribute animation
- * @type {String}
- * @default default
- * @description
- * [en]The animation used when showing and hiding the dialog. Can be either `"none"` or `"default"`.[/en]
- * [ja]ダイアログを表示する際のアニメーション名を指定します。"none"もしくは"default"を指定できます。[/ja]
- */
-
- /**
- * @attribute animation-options
- * @type {Expression}
- * @description
- * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`[/ja]
- */
-
- /**
- * @attribute mask-color
- * @type {String}
- * @default rgba(0, 0, 0, 0.2)
- * @description
- * [en]Color of the background mask. Default is `"rgba(0, 0, 0, 0.2)"`.[/en]
- * [ja]背景のマスクの色を指定します。"rgba(0, 0, 0, 0.2)"がデフォルト値です。[/ja]
- */
-
- function DialogElement() {
- classCallCheck(this, DialogElement);
-
- var _this = possibleConstructorReturn(this, (DialogElement.__proto__ || Object.getPrototypeOf(DialogElement)).call(this));
-
- contentReady(_this, function () {
- return _this._compile();
- });
- return _this;
- }
-
- createClass(DialogElement, [{
- key: '_updateAnimatorFactory',
- value: function _updateAnimatorFactory() {
- return new AnimatorFactory({
- animators: _animatorDict$2,
- baseClass: DialogAnimator,
- baseClassName: 'DialogAnimator',
- defaultAnimation: this.getAttribute('animation')
- });
- }
- }, {
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
-
- this.style.display = 'none';
- this.style.zIndex = 10001;
-
- /* Expected result:
- * <ons-dialog>
- * <div class="dialog-mask"></div>
- * <div class="dialog">
- * <div class="dialog-container">...</div>
- * </div>
- * </ons-dialog>
- */
-
- if (!this._dialog) {
- var dialog = document.createElement('div');
- dialog.classList.add('dialog');
-
- var container = document.createElement('div');
- container.classList.add('dialog-container');
- while (this.firstChild) {
- container.appendChild(this.firstChild);
- }
- dialog.appendChild(container);
-
- this.appendChild(dialog);
- }
-
- if (!this._mask) {
- var mask = document.createElement('div');
- mask.classList.add('dialog-mask');
- this.insertBefore(mask, this.firstChild);
- }
-
- this._dialog.style.zIndex = 20001;
- this._mask.style.zIndex = 20000;
-
- this.setAttribute('status-bar-fill', '');
-
- ModifierUtil.initModifier(this, this._scheme);
- }
-
- /**
- * @property onDeviceBackButton
- * @type {Object}
- * @description
- * [en]Back-button handler.[/en]
- * [ja]バックボタンハンドラ。[/ja]
- */
-
- /**
- * @method show
- * @signature show([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Available animations are `"none"` and `"slide"`.[/en]
- * [ja]アニメーション名を指定します。"none", "slide"のいずれかを指定します。[/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}` [/ja]
- * @param {Function} [options.callback]
- * [en]This function is called after the dialog has been revealed.[/en]
- * [ja]ダイアログが表示され終わった後に呼び出される関数オブジェクトを指定します。[/ja]
- * @description
- * [en]Show the dialog.[/en]
- * [ja]ダイアログを開きます。[/ja]
- * @return {Promise} Resolves to the displayed element.
- */
-
- /**
- * @method hide
- * @signature hide([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Available animations are `"none"` and `"slide"`.[/en]
- * [ja]アニメーション名を指定します。"none", "slide"のいずれかを指定できます。[/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`[/ja]
- * @param {Function} [options.callback]
- * [en]This functions is called after the dialog has been hidden.[/en]
- * [ja]ダイアログが隠れた後に呼び出される関数オブジェクトを指定します。[/ja]
- * @description
- * [en]Hide the dialog.[/en]
- * [ja]ダイアログを閉じます。[/ja]
- * @return {Promise}
- * [en]Resolves to the hidden element[/en]
- * [ja][/ja]
- */
-
- /**
- * @property visible
- * @readonly
- * @type {Boolean}
- * @description
- * [en]Whether the dialog is visible or not.[/en]
- * [ja]要素が見える場合に`true`。[/ja]
- */
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the dialog is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- /**
- * @property cancelable
- * @type {Boolean}
- * @description
- * [en]Whether the dialog is cancelable or not. A cancelable dialog can be closed by tapping the background or by pressing the back button on Android devices.[/en]
- * [ja][/ja]
- */
-
- /**
- * @param {String} name
- * @param {DialogAnimator} Animator
- */
-
- }, {
- key: '_scheme',
- get: function get$$1() {
- return scheme$6;
- }
- }, {
- key: '_mask',
- get: function get$$1() {
- return util$1.findChild(this, '.dialog-mask');
- }
- }, {
- key: '_dialog',
- get: function get$$1() {
- return util$1.findChild(this, '.dialog');
- }
- }], [{
- key: 'registerAnimator',
- value: function registerAnimator(name, Animator) {
- if (!(Animator.prototype instanceof DialogAnimator)) {
- util$1.throwAnimator('Dialog');
- }
- _animatorDict$2[name] = Animator;
- }
- }, {
- key: 'animators',
- get: function get$$1() {
- return _animatorDict$2;
- }
- }, {
- key: 'DialogAnimator',
- get: function get$$1() {
- return DialogAnimator;
- }
- }]);
- return DialogElement;
- }(BaseDialogElement);
-
- onsElements.Dialog = DialogElement;
- customElements.define('ons-dialog', DialogElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
- var defaultClassName$3 = 'fab';
-
- var scheme$7 = {
- '': 'fab--*',
- '.fab__icon': 'fab--*__icon'
- };
-
- /**
- * @element ons-fab
- * @category form
- * @description
- * [en]
- * The Floating action button is a circular button defined in the [Material Design specification](https://www.google.com/design/spec/components/buttons-floating-action-button.html). They are often used to promote the primary action of the app.
- *
- * It can be displayed either as an inline element or in one of the corners. Normally it will be positioned in the lower right corner of the screen.
- * [/en]
- * [ja][/ja]
- * @tutorial vanilla/Reference/fab
- * @modifier mini
- * [en]Makes the `ons-fab` smaller.[/en]
- * [ja][/ja]
- * @guide theming.html#cross-platform-styling-autostyling [en]Information about cross platform styling[/en][ja]Information about cross platform styling[/ja]
- * @seealso ons-speed-dial
- * [en]The `<ons-speed-dial>` component is a Floating action button that displays a menu when tapped.[/en]
- * [ja][/ja]
- */
-
- var FabElement = function (_BaseElement) {
- inherits(FabElement, _BaseElement);
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the button.[/en]
- * [ja]ボタンの表現を指定します。[/ja]
- */
-
- /**
- * @attribute ripple
- * @description
- * [en]If this attribute is defined, the button will have a ripple effect when tapped.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute position
- * @type {String}
- * @description
- * [en]The position of the button. Should be a string like `"bottom right"` or `"top left"`. If this attribute is not defined it will be displayed as an inline element.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute disabled
- * @description
- * [en]Specify if button should be disabled.[/en]
- * [ja]ボタンを無効化する場合は指定します。[/ja]
- */
-
- function FabElement() {
- classCallCheck(this, FabElement);
-
- // The following statements can be executed before contentReady
- // since these do not access the children
- var _this = possibleConstructorReturn(this, (FabElement.__proto__ || Object.getPrototypeOf(FabElement)).call(this));
-
- _this._hide();
- _this.classList.add(defaultClassName$3);
-
- contentReady(_this, function () {
- _this._compile();
- });
- return _this;
- }
-
- createClass(FabElement, [{
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
-
- if (!util$1.findChild(this, '.fab__icon')) {
- var content = document.createElement('span');
- content.classList.add('fab__icon');
-
- util$1.arrayFrom(this.childNodes).forEach(function (element) {
- if (!element.tagName || element.tagName.toLowerCase() !== 'ons-ripple') {
- content.appendChild(element);
- }
- });
- this.appendChild(content);
- }
-
- this._updateRipple();
-
- ModifierUtil.initModifier(this, scheme$7);
-
- this._updatePosition();
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- var _this2 = this;
-
- setImmediate(function () {
- return _this2._show();
- });
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'class':
- util$1.restoreClass(this, defaultClassName$3, scheme$7);
- break;
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, scheme$7);
- break;
- case 'ripple':
- this._updateRipple();
- break;
- case 'position':
- this._updatePosition();
- break;
- }
- }
- }, {
- key: '_show',
- value: function _show() {
- if (!this._manuallyHidden) {
- // if user has not called ons-fab.hide()
- this._toggle(true);
- }
- }
- }, {
- key: '_hide',
- value: function _hide() {
- var _this3 = this;
-
- setImmediate(function () {
- return _this3._toggle(false);
- });
- }
- }, {
- key: '_updateRipple',
- value: function _updateRipple() {
- util$1.updateRipple(this);
- }
- }, {
- key: '_updatePosition',
- value: function _updatePosition() {
- var position = this.getAttribute('position');
- this.classList.remove('fab--top__left', 'fab--bottom__right', 'fab--bottom__left', 'fab--top__right', 'fab--top__center', 'fab--bottom__center');
- switch (position) {
- case 'top right':
- case 'right top':
- this.classList.add('fab--top__right');
- break;
- case 'top left':
- case 'left top':
- this.classList.add('fab--top__left');
- break;
- case 'bottom right':
- case 'right bottom':
- this.classList.add('fab--bottom__right');
- break;
- case 'bottom left':
- case 'left bottom':
- this.classList.add('fab--bottom__left');
- break;
- case 'center top':
- case 'top center':
- this.classList.add('fab--top__center');
- break;
- case 'center bottom':
- case 'bottom center':
- this.classList.add('fab--bottom__center');
- break;
- default:
- break;
- }
- }
-
- /**
- * @method show
- * @signature show()
- * @description
- * [en]Show the floating action button.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'show',
- value: function show() {
- this.toggle(true);
- }
-
- /**
- * @method hide
- * @signature hide()
- * @description
- * [en]Hide the floating action button.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'hide',
- value: function hide() {
- this.toggle(false);
- }
-
- /**
- * @method toggle
- * @signature toggle()
- * @description
- * [en]Toggle the visibility of the button.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'toggle',
- value: function toggle() {
- var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : !this.visible;
-
- this._manuallyHidden = !action;
- this._toggle(action);
- }
- }, {
- key: '_toggle',
- value: function _toggle() {
- var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : !this.visible;
-
- var isBottom = (this.getAttribute('position') || '').indexOf('bottom') >= 0;
- var translate = isBottom ? 'translate3d(0px, -' + (util$1.globals.fabOffset || 0) + 'px, 0px)' : '';
-
- styler(this, { transform: translate + ' scale(' + Number(action) + ')' });
- }
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the element is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- }, {
- key: 'disabled',
- set: function set$$1(value) {
- return util$1.toggleAttribute(this, 'disabled', value);
- },
- get: function get$$1() {
- return this.hasAttribute('disabled');
- }
-
- /**
- * @property visible
- * @readonly
- * @type {Boolean}
- * @description
- * [en]Whether the element is visible or not.[/en]
- * [ja]要素が見える場合に`true`。[/ja]
- */
-
- }, {
- key: 'visible',
- get: function get$$1() {
- return this.style.transform.indexOf('scale(0)') === -1 && this.style.display !== 'none';
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'ripple', 'position', 'class'];
- }
- }]);
- return FabElement;
- }(BaseElement);
-
- onsElements.Fab = FabElement;
- customElements.define('ons-fab', FabElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * @element ons-gesture-detector
- * @category gesture
- * @description
- * [en]
- * Component to detect finger gestures within the wrapped element. Following gestures are supported:
- * - Drag gestures: `drag`, `dragleft`, `dragright`, `dragup`, `dragdown`
- * - Hold gestures: `hold`, `release`
- * - Swipe gestures: `swipe`, `swipeleft`, `swiperight`, `swipeup`, `swipedown`
- * - Tap gestures: `tap`, `doubletap`
- * - Pinch gestures: `pinch`, `pinchin`, `pinchout`
- * - Other gestures: `touch`, `transform`, `rotate`
- * [/en]
- * [ja]要素内のジェスチャー操作を検知します。詳しくはガイドを参照してください。[/ja]
- * @guide features.html#gesture-detection
- * [en]Detecting finger gestures[/en]
- * [ja]ジェスチャー操作の検知[/ja]
- * @example
- * <ons-gesture-detector>
- * <div id="detect-area" style="width: 100px; height: 100px;">
- * Swipe Here
- * </div>
- * </ons-gesture-detector>
- *
- * <script>
- * document.addEventListener('swipeleft', function(event) {
- * if (event.target.matches('#detect-area')) {
- * console.log('Swipe left is detected.');
- * }
- * });
- * </script>
- */
-
- var GestureDetectorElement = function (_BaseElement) {
- inherits(GestureDetectorElement, _BaseElement);
-
- function GestureDetectorElement() {
- classCallCheck(this, GestureDetectorElement);
-
- var _this = possibleConstructorReturn(this, (GestureDetectorElement.__proto__ || Object.getPrototypeOf(GestureDetectorElement)).call(this));
-
- _this._gestureDetector = new GestureDetector(_this, { passive: true });
- return _this;
- }
-
- return GestureDetectorElement;
- }(BaseElement);
-
- onsElements.GestureDetector = GestureDetectorElement;
- customElements.define('ons-gesture-detector', GestureDetectorElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var autoPrefix = 'fa'; // FIXME: To be removed in v3
-
- /**
- * @element ons-icon
- * @category visual
- * @description
- * [en]
- * Displays an icon. The following icon suites are available:
- *
- * * [Font Awesome](https://fortawesome.github.io/Font-Awesome/)
- * * [Ionicons](http://ionicons.com/)
- * * [Material Design Iconic Font](http://zavoloklom.github.io/material-design-iconic-font/)
- * [/en]
- * [ja][/ja]
- * @codepen xAhvg
- * @tutorial vanilla/Reference/icon
- * @guide theming.html#cross-platform-styling-autostyling [en]Information about cross platform styling[/en][ja][/ja]
- * @guide appsize.html#removing-icon-packs [en]Removing icon packs.[/en][ja][/ja]
- * @guide faq.html#how-can-i-use-custom-icon-packs [en]Adding custom icon packs.[/en][ja][/ja]
- * @example
- * <ons-icon
- * icon="md-car"
- * size="20px"
- * style="color: red">
- * </ons-icon>
- *
- * <ons-button>
- * <ons-icon icon="md-car"></ons-icon>
- * Car
- * </ons-button>
- */
-
- var IconElement = function (_BaseElement) {
- inherits(IconElement, _BaseElement);
-
- /**
- * @attribute icon
- * @type {String}
- * @description
- * [en]
- * The icon name. `"md-"` prefix for Material Icons, `"fa-"` for Font Awesome and `"ion-"` prefix for Ionicons.
- *
- * See all available icons on the element description (at the top).
- *
- * Icons can also be styled based on modifier presence. Add comma-separated icons with `"modifierName:"` prefix.
- *
- * The code `<ons-icon icon="ion-edit, material:md-edit"></ons-icon>` will display `"md-edit"` for Material Design and `"ion-edit"` as the default icon.
- *
- * `fa-` prefix is added automatically if none is provided. Check [See also](#seealso) section for more information.
- * [/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute size
- * @type {String}
- * @description
- * [en]
- * The sizes of the icon. Valid values are lg, 2x, 3x, 4x, 5x, or in the size in pixels.
- * Icons can also be styled based on modifier presence. Add comma-separated icons with `"modifierName:"` prefix.
- *
- * The code:
- *
- * ```
- * <ons-icon
- * icon="ion-edit"
- * size="32px, material:24px">
- * </ons-icon>
- * ```
- *
- * will render as a `24px` icon if the `"material"` modifier is present and `32px` otherwise.
- * [/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute rotate
- * @type {Number}
- * @description
- * [en]Number of degrees to rotate the icon. Valid values are 90, 180 and 270.[/en]
- * [ja]アイコンを回転して表示します。90, 180, 270から指定できます。[/ja]
- */
-
- /**
- * @attribute fixed-width
- * @type {Boolean}
- * @default false
- * @description
- * [en]When used in a list, you want the icons to have the same width so that they align vertically by defining this attribute.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute spin
- * @description
- * [en]Specify whether the icon should be spinning.[/en]
- * [ja]アイコンを回転するかどうかを指定します。[/ja]
- */
-
- function IconElement() {
- classCallCheck(this, IconElement);
-
- var _this = possibleConstructorReturn(this, (IconElement.__proto__ || Object.getPrototypeOf(IconElement)).call(this));
-
- contentReady(_this, function () {
- _this._compile();
- });
- return _this;
- }
-
- createClass(IconElement, [{
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- this._cleanClassAttribute(name === 'icon' ? last : this.getAttribute('icon'), name === 'modifier' ? last : undefined);
- this._update();
- }
- }, {
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
- this._update();
- }
- }, {
- key: '_update',
- value: function _update() {
- var _this2 = this;
-
- var _buildClassAndStyle2 = this._buildClassAndStyle(this._parseAttr('icon'), this._parseAttr('size')),
- classList = _buildClassAndStyle2.classList,
- style = _buildClassAndStyle2.style;
-
- util$1.extend(this.style, style);
-
- classList.forEach(function (className) {
- return _this2.classList.add(className);
- });
- }
- }, {
- key: '_parseAttr',
- value: function _parseAttr(attrName) {
- var modifier = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.getAttribute('modifier') || '';
-
- var attr = this.getAttribute(attrName) || attrName || '';
- var parts = attr.split(/\s*,\s*/);
- var def = parts[0];
- var md = parts[1];
- md = (md || '').split(/\s*:\s*/);
-
- return (modifier && RegExp('(^|\\s+)' + md[0] + '($|\\s+)', 'i').test(modifier) ? md[1] : def) || '';
- }
-
- /**
- * Remove unneeded class value.
- */
-
- }, {
- key: '_cleanClassAttribute',
- value: function _cleanClassAttribute(lastIcon, lastModifier) {
- var _this3 = this;
-
- var _prefixIcon2 = this._prefixIcon(this._parseAttr(lastIcon, lastModifier)),
- className = _prefixIcon2.className,
- prefix = _prefixIcon2.prefix;
-
- var customPrefixRE = className !== prefix ? '|' + prefix + '$|' + prefix + '-' : '|' + className + '$' || '';
- var re = new RegExp('^(fa$|fa-|ion-|zmdi$|zmdi-|ons-icon--' + customPrefixRE + ')');
-
- util$1.arrayFrom(this.classList).filter(function (className) {
- return re.test(className);
- }).forEach(function (className) {
- return _this3.classList.remove(className);
- });
- }
- }, {
- key: '_prefixIcon',
- value: function _prefixIcon(iconName) {
- var className = autoPrefix + (autoPrefix ? '-' : '') + iconName;
- return { className: className, prefix: className.split('-')[0] };
- }
- }, {
- key: '_buildClassAndStyle',
- value: function _buildClassAndStyle(iconName, size) {
- var classList = ['ons-icon'];
- var style = {};
-
- // Icon
- if (iconName.indexOf('ion-') === 0) {
- classList.push(iconName);
- classList.push('ons-icon--ion');
- } else if (iconName.indexOf('fa-') === 0) {
- classList.push(iconName);
- // default icon style to Font Awesome Solid if icon style is not specified already
- if (!(this.classList.contains('far') || this.classList.contains('fab') || this.classList.contains('fal'))) {
- classList.push('fa');
- }
- } else if (iconName.indexOf('md-') === 0) {
- classList.push('zmdi');
- classList.push('zmdi-' + iconName.split(/-(.+)?/)[1]);
- } else {
- var _prefixIcon3 = this._prefixIcon(iconName),
- className = _prefixIcon3.className,
- prefix = _prefixIcon3.prefix;
-
- prefix && classList.push(prefix);
- className && classList.push(className);
- }
-
- // Size
- if (size.match(/^[1-5]x|lg$/)) {
- classList.push('ons-icon--' + size);
- this.style.removeProperty('font-size');
- } else {
- style.fontSize = size;
- }
-
- return {
- classList: classList,
- style: style
- };
- }
- }], [{
- key: 'setAutoPrefix',
- value: function setAutoPrefix(prefix) {
- autoPrefix = prefix ? typeof prefix === 'string' && prefix || 'fa' : '';
- }
- }, {
- key: 'observedAttributes',
- get: function get$$1() {
- return ['icon', 'size', 'modifier', 'class'];
- }
- }]);
- return IconElement;
- }(BaseElement);
-
- onsElements.Icon = IconElement;
- customElements.define('ons-icon', IconElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var LazyRepeatDelegate = function () {
- function LazyRepeatDelegate(userDelegate) {
- var templateElement = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
- classCallCheck(this, LazyRepeatDelegate);
-
- if ((typeof userDelegate === 'undefined' ? 'undefined' : _typeof(userDelegate)) !== 'object' || userDelegate === null) {
- util$1.throw('"delegate" parameter must be an object');
- }
- this._userDelegate = userDelegate;
-
- if (!(templateElement instanceof Element) && templateElement !== null) {
- util$1.throw('"templateElement" parameter must be an instance of Element or null');
- }
- this._templateElement = templateElement;
- }
-
- createClass(LazyRepeatDelegate, [{
- key: 'hasRenderFunction',
-
-
- /**
- * @return {Boolean}
- */
- value: function hasRenderFunction() {
- return this._userDelegate._render instanceof Function;
- }
-
- /**
- * @return {void}
- */
-
- }, {
- key: '_render',
- value: function _render() {
- this._userDelegate._render.apply(this._userDelegate, arguments);
- }
-
- /**
- * @param {Number} index
- * @param {Function} done A function that take item object as parameter.
- */
-
- }, {
- key: 'loadItemElement',
- value: function loadItemElement(index, done) {
- if (this._userDelegate.loadItemElement instanceof Function) {
- this._userDelegate.loadItemElement(index, done);
- } else {
- var element = this._userDelegate.createItemContent(index, this._templateElement);
- if (!(element instanceof Element)) {
- util$1.throw('"createItemContent" must return an instance of Element');
- }
-
- done({ element: element });
- }
- }
-
- /**
- * @return {Number}
- */
-
- }, {
- key: 'countItems',
- value: function countItems() {
- var count = this._userDelegate.countItems();
- if (typeof count !== 'number') {
- util$1.throw('"countItems" must return a number');
- }
- return count;
- }
-
- /**
- * @param {Number} index
- * @param {Object} item
- * @param {Element} item.element
- */
-
- }, {
- key: 'updateItem',
- value: function updateItem(index, item) {
- if (this._userDelegate.updateItemContent instanceof Function) {
- this._userDelegate.updateItemContent(index, item);
- }
- }
-
- /**
- * @return {Number}
- */
-
- }, {
- key: 'calculateItemHeight',
- value: function calculateItemHeight(index) {
- if (this._userDelegate.calculateItemHeight instanceof Function) {
- var height = this._userDelegate.calculateItemHeight(index);
-
- if (typeof height !== 'number') {
- util$1.throw('"calculateItemHeight" must return a number');
- }
-
- return height;
- }
-
- return 0;
- }
-
- /**
- * @param {Number} index
- * @param {Object} item
- */
-
- }, {
- key: 'destroyItem',
- value: function destroyItem(index, item) {
- if (this._userDelegate.destroyItem instanceof Function) {
- this._userDelegate.destroyItem(index, item);
- }
- }
-
- /**
- * @return {void}
- */
-
- }, {
- key: 'destroy',
- value: function destroy() {
- if (this._userDelegate.destroy instanceof Function) {
- this._userDelegate.destroy();
- }
-
- this._userDelegate = this._templateElement = null;
- }
- }, {
- key: 'itemHeight',
- get: function get$$1() {
- return this._userDelegate.itemHeight;
- }
- }]);
- return LazyRepeatDelegate;
- }();
-
- /**
- * This class provide core functions for ons-lazy-repeat.
- */
- var LazyRepeatProvider = function () {
-
- /**
- * @param {Element} wrapperElement
- * @param {LazyRepeatDelegate} delegate
- */
- function LazyRepeatProvider(wrapperElement, delegate) {
- classCallCheck(this, LazyRepeatProvider);
-
- if (!(delegate instanceof LazyRepeatDelegate)) {
- util$1.throw('"delegate" parameter must be an instance of LazyRepeatDelegate');
- }
-
- this._wrapperElement = wrapperElement;
- this._delegate = delegate;
- this._insertIndex = this._wrapperElement.children[0] && this._wrapperElement.children[0].tagName === 'ONS-LAZY-REPEAT' ? 1 : 0;
-
- if (wrapperElement.tagName.toLowerCase() === 'ons-list') {
- wrapperElement.classList.add('lazy-list');
- }
-
- this._pageContent = this._findPageContentElement(wrapperElement);
-
- if (!this._pageContent) {
- util$1.throw('LazyRepeat must be descendant of a Page element');
- }
-
- this.lastScrollTop = this._pageContent.scrollTop;
- this.padding = 0;
- this._topPositions = [0];
- this._renderedItems = {};
-
- if (!this._delegate.itemHeight && !this._delegate.calculateItemHeight(0)) {
- this._unknownItemHeight = true;
- }
-
- this._addEventListeners();
- this._onChange();
- }
-
- createClass(LazyRepeatProvider, [{
- key: '_findPageContentElement',
- value: function _findPageContentElement(wrapperElement) {
- var pageContent = util$1.findParent(wrapperElement, '.page__content');
-
- if (pageContent) {
- return pageContent;
- }
-
- var page = util$1.findParent(wrapperElement, 'ons-page');
- if (page) {
- var content = util$1.findChild(page, '.content');
- if (content) {
- return content;
- }
- }
-
- return null;
- }
- }, {
- key: '_checkItemHeight',
- value: function _checkItemHeight(callback) {
- var _this = this;
-
- this._delegate.loadItemElement(0, function (item) {
- if (!_this._unknownItemHeight) {
- util$1.throw('Invalid state');
- }
-
- _this._wrapperElement.appendChild(item.element);
-
- var done = function done() {
- _this._delegate.destroyItem(0, item);
- item.element && item.element.remove();
- delete _this._unknownItemHeight;
- callback();
- };
-
- _this._itemHeight = item.element.offsetHeight;
-
- if (_this._itemHeight > 0) {
- done();
- return;
- }
-
- // retry to measure offset height
- // dirty fix for angular2 directive
- _this._wrapperElement.style.visibility = 'hidden';
- item.element.style.visibility = 'hidden';
-
- setImmediate(function () {
- _this._itemHeight = item.element.offsetHeight;
- if (_this._itemHeight == 0) {
- util$1.throw('Invalid state: "itemHeight" must be greater than zero');
- }
- _this._wrapperElement.style.visibility = '';
- done();
- });
- });
- }
- }, {
- key: '_countItems',
- value: function _countItems() {
- return this._delegate.countItems();
- }
- }, {
- key: '_getItemHeight',
- value: function _getItemHeight(i) {
- // Item is rendered
- if (this._renderedItems.hasOwnProperty(i)) {
- if (!this._renderedItems[i].hasOwnProperty('height')) {
- this._renderedItems[i].height = this._renderedItems[i].element.offsetHeight;
- }
- return this._renderedItems[i].height;
- }
-
- // Item is not rendered, scroll up
- if (this._topPositions[i + 1] && this._topPositions[i]) {
- return this._topPositions[i + 1] - this._topPositions[i];
- }
- // Item is not rendered, scroll down
- return this.staticItemHeight || this._delegate.calculateItemHeight(i);
- }
- }, {
- key: '_calculateRenderedHeight',
- value: function _calculateRenderedHeight() {
- var _this2 = this;
-
- return Object.keys(this._renderedItems).reduce(function (a, b) {
- return a + _this2._getItemHeight(+b);
- }, 0);
- }
- }, {
- key: '_onChange',
- value: function _onChange() {
- this._render();
- }
- }, {
- key: '_lastItemRendered',
- value: function _lastItemRendered() {
- return Math.max.apply(Math, toConsumableArray(Object.keys(this._renderedItems)));
- }
- }, {
- key: '_firstItemRendered',
- value: function _firstItemRendered() {
- return Math.min.apply(Math, toConsumableArray(Object.keys(this._renderedItems)));
- }
- }, {
- key: 'refresh',
- value: function refresh() {
- var forceRender = { forceScrollDown: true };
- var firstItemIndex = this._firstItemRendered();
-
- if (util$1.isInteger(firstItemIndex)) {
- this._wrapperElement.style.height = this._topPositions[firstItemIndex] + this._calculateRenderedHeight() + 'px';
- this.padding = this._topPositions[firstItemIndex];
- forceRender.forceFirstIndex = firstItemIndex;
- }
-
- this._removeAllElements();
- this._render(forceRender);
- this._wrapperElement.style.height = 'inherit';
- }
- }, {
- key: '_render',
- value: function _render() {
- var _this3 = this;
-
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$forceScrollDown = _ref.forceScrollDown,
- forceScrollDown = _ref$forceScrollDown === undefined ? false : _ref$forceScrollDown,
- forceFirstIndex = _ref.forceFirstIndex,
- forceLastIndex = _ref.forceLastIndex;
-
- if (this._unknownItemHeight) {
- return this._checkItemHeight(this._render.bind(this, arguments[0]));
- }
-
- var isScrollUp = !forceScrollDown && this.lastScrollTop > this._pageContent.scrollTop;
- this.lastScrollTop = this._pageContent.scrollTop;
- var keep = {};
-
- var offset = this._wrapperElement.getBoundingClientRect().top;
- var limit = 4 * window.innerHeight - offset;
- var count = this._countItems();
-
- var start = forceFirstIndex || Math.max(0, this._calculateStartIndex(offset) - 30); // Recalculate for 0 or undefined
- var i = start;
-
- for (var top = this._topPositions[i]; i < count && top < limit; i++) {
- if (i >= this._topPositions.length) {
- // perf optimization
- this._topPositions.length += 100;
- }
-
- this._topPositions[i] = top;
- top += this._getItemHeight(i);
- }
-
- if (this._delegate.hasRenderFunction && this._delegate.hasRenderFunction()) {
- return this._delegate._render(start, i, function () {
- _this3.padding = _this3._topPositions[start];
- });
- }
-
- if (isScrollUp) {
- for (var j = i - 1; j >= start; j--) {
- keep[j] = true;
- this._renderElement(j, isScrollUp);
- }
- } else {
- var lastIndex = forceLastIndex || Math.max.apply(Math, [i - 1].concat(toConsumableArray(Object.keys(this._renderedItems)))); // Recalculate for 0 or undefined
- for (var _j = start; _j <= lastIndex; _j++) {
- keep[_j] = true;
- this._renderElement(_j, isScrollUp);
- }
- }
-
- Object.keys(this._renderedItems).forEach(function (key) {
- return keep[key] || _this3._removeElement(key, isScrollUp);
- });
- }
-
- /**
- * @param {Number} index
- * @param {Boolean} isScrollUp
- */
-
- }, {
- key: '_renderElement',
- value: function _renderElement(index, isScrollUp) {
- var _this4 = this;
-
- var item = this._renderedItems[index];
- if (item) {
- this._delegate.updateItem(index, item); // update if it exists
- return;
- }
-
- this._delegate.loadItemElement(index, function (item) {
- if (isScrollUp) {
- _this4._wrapperElement.insertBefore(item.element, _this4._wrapperElement.children[_this4._insertIndex]);
- _this4.padding = _this4._topPositions[index];
- item.height = _this4._topPositions[index + 1] - _this4._topPositions[index];
- } else {
- _this4._wrapperElement.appendChild(item.element);
- }
-
- _this4._renderedItems[index] = item;
- });
- }
-
- /**
- * @param {Number} index
- * @param {Boolean} isScrollUp
- */
-
- }, {
- key: '_removeElement',
- value: function _removeElement(index) {
- var isScrollUp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
-
- index = +index;
- var item = this._renderedItems[index];
- this._delegate.destroyItem(index, item);
-
- if (isScrollUp) {
- this._topPositions[index + 1] = undefined;
- } else {
- this.padding = this.padding + this._getItemHeight(index);
- }
-
- if (item.element.parentElement) {
- item.element.parentElement.removeChild(item.element);
- }
-
- delete this._renderedItems[index];
- }
- }, {
- key: '_removeAllElements',
- value: function _removeAllElements() {
- var _this5 = this;
-
- Object.keys(this._renderedItems).forEach(function (key) {
- return _this5._removeElement(key);
- });
- }
- }, {
- key: '_recalculateTopPositions',
- value: function _recalculateTopPositions(start, end) {
- for (var i = start; i <= end; i++) {
- this._topPositions[i + 1] = this._topPositions[i] + this._getItemHeight(i);
- }
- }
- }, {
- key: '_calculateStartIndex',
- value: function _calculateStartIndex(current) {
- var firstItemIndex = this._firstItemRendered();
- var lastItemIndex = this._lastItemRendered();
-
- // Fix for Safari scroll and Angular 2
- this._recalculateTopPositions(firstItemIndex, lastItemIndex);
-
- var start = 0;
- var end = this._countItems() - 1;
-
- // Binary search for index at top of screen so we can speed up rendering.
- for (;;) {
- var middle = Math.floor((start + end) / 2);
- var value = current + this._topPositions[middle];
-
- if (end < start) {
- return 0;
- } else if (value <= 0 && value + this._getItemHeight(middle) > 0) {
- return middle;
- } else if (isNaN(value) || value >= 0) {
- end = middle - 1;
- } else {
- start = middle + 1;
- }
- }
- }
- }, {
- key: '_debounce',
- value: function _debounce(func, wait, immediate) {
- var timeout = void 0;
- return function () {
- var _this6 = this,
- _arguments = arguments;
-
- var callNow = immediate && !timeout;
- clearTimeout(timeout);
- if (callNow) {
- func.apply(this, arguments);
- } else {
- timeout = setTimeout(function () {
- timeout = null;
- func.apply(_this6, _arguments);
- }, wait);
- }
- };
- }
- }, {
- key: '_doubleFireOnTouchend',
- value: function _doubleFireOnTouchend() {
- this._render();
- this._debounce(this._render.bind(this), 100);
- }
- }, {
- key: '_addEventListeners',
- value: function _addEventListeners() {
- util$1.bindListeners(this, ['_onChange', '_doubleFireOnTouchend']);
-
- if (platform.isIOS()) {
- this._boundOnChange = this._debounce(this._boundOnChange, 30);
- }
-
- this._pageContent.addEventListener('scroll', this._boundOnChange, true);
-
- if (platform.isIOS()) {
- util$1.addEventListener(this._pageContent, 'touchmove', this._boundOnChange, { capture: true, passive: true });
- this._pageContent.addEventListener('touchend', this._boundDoubleFireOnTouchend, true);
- }
-
- window.document.addEventListener('resize', this._boundOnChange, true);
- }
- }, {
- key: '_removeEventListeners',
- value: function _removeEventListeners() {
- this._pageContent.removeEventListener('scroll', this._boundOnChange, true);
-
- if (platform.isIOS()) {
- util$1.removeEventListener(this._pageContent, 'touchmove', this._boundOnChange, { capture: true, passive: true });
- this._pageContent.removeEventListener('touchend', this._boundDoubleFireOnTouchend, true);
- }
-
- window.document.removeEventListener('resize', this._boundOnChange, true);
- }
- }, {
- key: 'destroy',
- value: function destroy() {
- this._removeAllElements();
- this._delegate.destroy();
- this._parentElement = this._delegate = this._renderedItems = null;
- this._removeEventListeners();
- }
- }, {
- key: 'padding',
- get: function get$$1() {
- return parseInt(this._wrapperElement.style.paddingTop, 10);
- },
- set: function set$$1(newValue) {
- this._wrapperElement.style.paddingTop = newValue + 'px';
- }
- }, {
- key: 'staticItemHeight',
- get: function get$$1() {
- return this._delegate.itemHeight || this._itemHeight;
- }
- }]);
- return LazyRepeatProvider;
- }();
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
- /**
- * @element ons-lazy-repeat
- * @category list
- * @description
- * [en]
- * Using this component a list with millions of items can be rendered without a drop in performance.
- * It does that by "lazily" loading elements into the DOM when they come into view and
- * removing items from the DOM when they are not visible.
- * [/en]
- * [ja]
- * このコンポーネント内で描画されるアイテムのDOM要素の読み込みは、画面に見えそうになった時まで自動的に遅延され、
- * 画面から見えなくなった場合にはその要素は動的にアンロードされます。
- * このコンポーネントを使うことで、パフォーマンスを劣化させること無しに巨大な数の要素を描画できます。
- * [/ja]
- * @codepen QwrGBm
- * @tutorial vanilla/Reference/lazy-repeat
- * @seealso ons-list
- * [en]The `<ons-list>` element is used to render a list.[/en]
- * [ja]`<ons-list>`要素はリストを描画するのに使われます。[/ja]
- * @example
- * <script>
- * window.addEventListener('load', function() {
- * var lazyRepeat = document.querySelector('#list');
- * lazyRepeat.delegate = {
- * createItemContent: function(i, template) {
- * var dom = template.cloneNode(true);
- * dom.innerText = i;
- *
- * return dom;
- * },
- * countItems: function() {
- * return 10000000;
- * },
- * destroyItem: function(index, item) {
- * console.log('Destroyed item with index: ' + index);
- * }
- * };
- * });
- * </script>
- *
- * <ons-list id="list">
- * <ons-lazy-repeat>
- * <ons-list-item></ons-list-item>
- * </ons-lazy-repeat>
- * </ons-list>
- */
-
- var LazyRepeatElement = function (_BaseElement) {
- inherits(LazyRepeatElement, _BaseElement);
-
- function LazyRepeatElement() {
- classCallCheck(this, LazyRepeatElement);
- return possibleConstructorReturn(this, (LazyRepeatElement.__proto__ || Object.getPrototypeOf(LazyRepeatElement)).apply(this, arguments));
- }
-
- createClass(LazyRepeatElement, [{
- key: 'connectedCallback',
- value: function connectedCallback() {
- // not very good idea and also not documented
- if (this.hasAttribute('delegate')) {
- this.delegate = window[this.getAttribute('delegate')];
- }
- }
-
- /**
- * @property delegate
- * @type {Object}
- * @description
- * [en]Specify a delegate object to load and unload item elements.[/en]
- * [ja]要素のロード、アンロードなどの処理を委譲するオブジェクトを指定します。[/ja]
- */
-
- /**
- * @property delegate.createItemContent
- * @type {Function}
- * @description
- * [en]
- * This function should return a `HTMLElement`.
- *
- * To help rendering the element, the current index and a template is supplied as arguments. The template is the initial content of the `<ons-lazy-repeat>` element.
- * [/en]
- * [ja]
- * この関数は`HTMLElement`を返してください。
- * 要素を生成しやすくするために、現在のアイテムのインデックスとテンプレートが引数に渡されます。
- * このテンプレートは、`<ons-lazy-repeat>`要素のコンテンツが渡されます。
- * [/ja]
- */
-
- /**
- * @property delegate.countItems
- * @type {Function}
- * @description
- * [en]Should return the number of items in the list.[/en]
- * [ja]リスト内のアイテム数を返してください。[/ja]
- */
-
- /**
- * @property delegate.calculateItemHeight
- * @type {Function}
- * @description
- * [en]
- * Should return the height of an item. The index is provided as an argument.
- *
- * This is important when rendering lists where the items have different height.
- *
- * The function is optional and if it isn't present the height of the first item will be automatically calculated and used for all other items.
- * [/en]
- * [ja]
- * アイテムの高さ(ピクセル)を返してください。アイテムのインデックス値は引数で渡されます。
- * この関数は、それぞれのアイムが違った高さを持つリストをレンダリングする際に重要です。
- * この関数はオプショナルです。もしこの関数が無い場合には、
- * 最初のアイテムの高さが他のすべてのアイテムの高さとして利用されます。
- * [/ja]
- */
-
- /**
- * @property delegate.destroyItem
- * @type {Function}
- * @description
- * [en]
- * This function is used called when an item is removed from the DOM. The index and DOM element is provided as arguments.
- *
- * The function is optional but may be important in order to avoid memory leaks.
- * [/en]
- * [ja]
- * この関数は、あるアイテムがDOMツリーから除かれた時に呼び出されます。
- * アイテムのインデックス値とDOM要素が引数として渡されます。
- * この関数はオプショナルですが、各アイテムの後処理が必要な場合にはメモリーリークを避けるために重要です。
- * [/ja]
- */
-
- }, {
- key: 'refresh',
-
-
- /**
- * @method refresh
- * @signature refresh()
- * @description
- * [en]Refresh the list. Use this method when the data has changed.[/en]
- * [ja]リストを更新します。もしデータが変わった場合にはこのメソッドを使ってください。[/ja]
- */
- value: function refresh() {
- this._lazyRepeatProvider && this._lazyRepeatProvider.refresh();
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {}
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- if (this._lazyRepeatProvider) {
- this._lazyRepeatProvider.destroy();
- this._lazyRepeatProvider = null;
- }
- }
- }, {
- key: 'delegate',
- set: function set$$1(userDelegate) {
- this._lazyRepeatProvider && this._lazyRepeatProvider.destroy();
-
- if (!this._templateElement && this.children[0]) {
- this._templateElement = this.removeChild(this.children[0]);
- }
-
- var delegate = new LazyRepeatDelegate(userDelegate, this._templateElement || null);
- this._lazyRepeatProvider = new LazyRepeatProvider(this.parentElement, delegate);
- },
- get: function get$$1() {
- util$1.throw('No delegate getter');
- }
- }]);
- return LazyRepeatElement;
- }(BaseElement);
-
- internal$1.LazyRepeatDelegate = LazyRepeatDelegate;
- internal$1.LazyRepeatProvider = LazyRepeatProvider;
-
- onsElements.LazyRepeat = LazyRepeatElement;
- customElements.define('ons-lazy-repeat', LazyRepeatElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var defaultClassName$4 = 'list-header';
- var scheme$8 = { '': 'list-header--*' };
-
- /**
- * @element ons-list-header
- * @category list
- * @description
- * [en]Header element for list items. Must be put inside the `<ons-list>` component.[/en]
- * [ja]リスト要素に使用するヘッダー用コンポーネント。ons-listと共に使用します。[/ja]
- * @seealso ons-list
- * [en]The `<ons-list>` component[/en]
- * [ja]ons-listコンポーネント[/ja]
- * @seealso ons-list-item
- * [en]The `<ons-list-item>` component[/en]
- * [ja]ons-list-itemコンポーネント[/ja]
- * @codepen yxcCt
- * @tutorial vanilla/Reference/list
- * @modifier material
- * [en]Display a Material Design list header.[/en]
- * [ja][/ja]
- * @example
- * <ons-list>
- * <ons-list-header>Header Text</ons-list-header>
- * <ons-list-item>Item</ons-list-item>
- * <ons-list-item>Item</ons-list-item>
- * </ons-list>
- */
-
- var ListHeaderElement = function (_BaseElement) {
- inherits(ListHeaderElement, _BaseElement);
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the list header.[/en]
- * [ja]ヘッダーの表現を指定します。[/ja]
- */
-
- function ListHeaderElement() {
- classCallCheck(this, ListHeaderElement);
-
- var _this = possibleConstructorReturn(this, (ListHeaderElement.__proto__ || Object.getPrototypeOf(ListHeaderElement)).call(this));
-
- _this._compile();
- return _this;
- }
-
- createClass(ListHeaderElement, [{
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
- this.classList.add(defaultClassName$4);
- ModifierUtil.initModifier(this, scheme$8);
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'class':
- util$1.restoreClass(this, defaultClassName$4, scheme$8);
- break;
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, scheme$8);
- break;
- }
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'class'];
- }
- }]);
- return ListHeaderElement;
- }(BaseElement);
-
- onsElements.ListHeader = ListHeaderElement;
- customElements.define('ons-list-header', ListHeaderElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var defaultClassName$5 = 'list-title';
- var scheme$9 = { '': 'list-title--*' };
-
- /**
- * @element ons-list-title
- * @category list
- * @description
- * [en]Represents a list title.[/en]
- * [ja]リストのタイトルを表現します。[/ja]
- * @example
- * <ons-list-title>List Title</ons-list-title>
- * <ons-list>
- * <ons-list-item>Item</ons-list-item>
- * </ons-list>
- * @modifier material
- * [en]Display a Material Design list title.[/en]
- * [ja][/ja]
- */
-
- var ListTitleElement = function (_BaseElement) {
- inherits(ListTitleElement, _BaseElement);
-
- function ListTitleElement() {
- classCallCheck(this, ListTitleElement);
-
- var _this = possibleConstructorReturn(this, (ListTitleElement.__proto__ || Object.getPrototypeOf(ListTitleElement)).call(this));
-
- _this._compile();
- return _this;
- }
-
- createClass(ListTitleElement, [{
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
- this.classList.add(defaultClassName$5);
- ModifierUtil.initModifier(this, scheme$9);
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'class':
- util$1.restoreClass(this, defaultClassName$5, scheme$9);
- break;
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, scheme$9);
- break;
- }
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'class'];
- }
- }]);
- return ListTitleElement;
- }(BaseElement);
-
- onsElements.ListTitle = ListTitleElement;
- customElements.define('ons-list-title', ListTitleElement);
-
- /*
- Copyright 2013-2018 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
- var ListItemAnimator = function (_BaseAnimator) {
- inherits(ListItemAnimator, _BaseAnimator);
-
- function ListItemAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'linear' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.2 : _ref$duration;
-
- classCallCheck(this, ListItemAnimator);
- return possibleConstructorReturn(this, (ListItemAnimator.__proto__ || Object.getPrototypeOf(ListItemAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
- }
-
- createClass(ListItemAnimator, [{
- key: 'showExpansion',
- value: function showExpansion(listItem, callback) {
- callback();
- }
- }, {
- key: 'hideExpansion',
- value: function hideExpansion(listItem, callback) {
- callback();
- }
- }]);
- return ListItemAnimator;
- }(BaseAnimator);
-
- var SlideListItemAnimator = function (_ListItemAnimator) {
- inherits(SlideListItemAnimator, _ListItemAnimator);
-
- function SlideListItemAnimator() {
- classCallCheck(this, SlideListItemAnimator);
- return possibleConstructorReturn(this, (SlideListItemAnimator.__proto__ || Object.getPrototypeOf(SlideListItemAnimator)).apply(this, arguments));
- }
-
- createClass(SlideListItemAnimator, [{
- key: 'showExpansion',
- value: function showExpansion(listItem, callback) {
- this._animateExpansion(listItem, true, callback);
- }
- }, {
- key: 'hideExpansion',
- value: function hideExpansion(listItem, callback) {
- this._animateExpansion(listItem, false, callback);
- }
- }, {
- key: '_animateExpansion',
- value: function _animateExpansion(listItem, shouldOpen, callback) {
- var _animit;
-
- // To animate the opening of the expansion panel correctly, we need to know its
- // height. To calculate this, we set its height to auto, and then get the computed
- // height and padding. Once this is done, we set the height back to its original value.
- var oldHeight = listItem.expandableContent.style.height;
- var oldDisplay = listItem.expandableContent.style.display;
- listItem.expandableContent.style.height = 'auto';
- listItem.expandableContent.style.display = 'block';
- var computedStyle = window.getComputedStyle(listItem.expandableContent);
-
- var expansionOpenTransition = [{ height: 0, paddingTop: 0, paddingBottom: 0 }, {
- height: computedStyle.height,
- paddingTop: computedStyle.paddingTop,
- paddingBottom: computedStyle.paddingBottom
- }];
- var iconOpenTransition = [{ transform: 'rotate(45deg)' }, { transform: 'rotate(225deg)' }];
-
- // Now that we have the values we need, reset the height back to its original state
- listItem.expandableContent.style.height = oldHeight;
-
- (_animit = Animit(listItem.expandableContent, { duration: this.duration, property: 'height padding-top padding-bottom' })).default.apply(_animit, toConsumableArray(shouldOpen ? expansionOpenTransition : expansionOpenTransition.reverse())).play(function () {
- listItem.expandableContent.style.display = oldDisplay;
- callback && callback();
- });
-
- if (listItem.expandChevron) {
- var _animit2;
-
- (_animit2 = Animit(listItem.expandChevron, { duration: this.duration, property: 'transform' })).default.apply(_animit2, toConsumableArray(shouldOpen ? iconOpenTransition : iconOpenTransition.reverse())).play();
- }
- }
- }]);
- return SlideListItemAnimator;
- }(ListItemAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var defaultClassName$6 = 'list-item';
- var scheme$10 = {
- '.list-item': 'list-item--*',
- '.list-item__left': 'list-item--*__left',
- '.list-item__center': 'list-item--*__center',
- '.list-item__right': 'list-item--*__right',
- '.list-item__label': 'list-item--*__label',
- '.list-item__title': 'list-item--*__title',
- '.list-item__subtitle': 'list-item--*__subtitle',
- '.list-item__thumbnail': 'list-item--*__thumbnail',
- '.list-item__icon': 'list-item--*__icon'
- };
-
- var _animatorDict$3 = {
- 'default': SlideListItemAnimator,
- 'none': ListItemAnimator
- };
-
- /**
- * @element ons-list-item
- * @category list
- * @modifier tappable
- * [en]Make the list item change appearance when it's tapped. On iOS it is better to use the "tappable" and "tap-background-color" attribute for better behavior when scrolling.[/en]
- * [ja]タップやクリックした時に効果が表示されるようになります。[/ja]
- * @modifier chevron
- * [en]Display a chevron at the right end of the list item and make it change appearance when tapped.[/en]
- * [ja][/ja]
- * @modifier longdivider
- * [en]Displays a long horizontal divider between items.[/en]
- * [ja][/ja]
- * @modifier nodivider
- * [en]Removes the divider between list items.[/en]
- * [ja][/ja]
- * @modifier material
- * [en]Display a Material Design list item.[/en]
- * [ja][/ja]
- * @description
- * [en]
- * Component that represents each item in a list. The list item is composed of four parts that are represented with the `left`, `center`, `right` and `expandable-content` classes. These classes can be used to ensure that the content of the list items is properly aligned.
- *
- * ```
- * <ons-list-item>
- * <div class="left">Left</div>
- * <div class="center">Center</div>
- * <div class="right">Right</div>
- * <div class="expandable-content">Expandable content</div>
- * </ons-list-item>
- * ```
- *
- * There are also a number of classes (prefixed with `list-item__*`) that help when putting things like icons and thumbnails into the list items.
- * [/en]
- * [ja][/ja]
- * @seealso ons-list
- * [en]ons-list component[/en]
- * [ja]ons-listコンポーネント[/ja]
- * @seealso ons-list-header
- * [en]ons-list-header component[/en]
- * [ja]ons-list-headerコンポーネント[/ja]
- * @codepen yxcCt
- * @tutorial vanilla/Reference/list
- * @example
- * <ons-list-item>
- * <div class="left">
- * <ons-icon icon="md-face" class="list-item__icon"></ons-icon>
- * </div>
- * <div class="center">
- * <div class="list-item__title">Title</div>
- * <div class="list-item__subtitle">Subtitle</div>
- * </div>
- * <div class="right">
- * <ons-switch></ons-switch>
- * </div>
- * </ons-list-item>
- */
-
- var ListItemElement = function (_BaseElement) {
- inherits(ListItemElement, _BaseElement);
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the list item.[/en]
- * [ja]各要素の表現を指定します。[/ja]
- */
-
- /**
- * @attribute lock-on-drag
- * @type {String}
- * @description
- * [en]Prevent vertical scrolling when the user drags horizontally.[/en]
- * [ja]この属性があると、ユーザーがこの要素を横方向にドラッグしている時に、縦方向のスクロールが起きないようになります。[/ja]
- */
-
- /**
- * @attribute tappable
- * @type {Boolean}
- * @description
- * [en]Makes the element react to taps. `prevent-tap` attribute can be added to child elements like buttons or inputs to prevent this effect. `ons-*` elements are ignored by default.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute tap-background-color
- * @type {Color}
- * @description
- * [en] Changes the background color when tapped. For this to work, the attribute "tappable" needs to be set. The default color is "#d9d9d9". It will display as a ripple effect on Android.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute expandable
- * @type {Boolean}
- * @description
- * [en]Makes the element able to be expanded to reveal extra content. For this to work, the expandable content must be defined in `div.expandable-content`.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute animation
- * @type {String}
- * @default default
- * @description
- * [en]The animation used when showing and hiding the expandable content. Can be either `"default"` or `"none"`.[/en]
- * [ja][/ja]
- */
-
- function ListItemElement() {
- classCallCheck(this, ListItemElement);
-
- var _this = possibleConstructorReturn(this, (ListItemElement.__proto__ || Object.getPrototypeOf(ListItemElement)).call(this));
-
- _this._animatorFactory = _this._updateAnimatorFactory();
- _this.toggleExpansion = _this.toggleExpansion.bind(_this);
-
- // Elements ignored when tapping
- var re = /^ons-(?!col$|row$|if$)/i;
- _this._shouldIgnoreTap = function (e) {
- return e.hasAttribute('prevent-tap') || re.test(e.tagName);
- };
-
- // show and hide functions for Vue hidable mixin
- _this.show = _this.showExpansion;
- _this.hide = _this.hideExpansion;
-
- contentReady(_this, function () {
- _this._compile();
- });
- return _this;
- }
-
- /**
- * Compiles the list item.
- *
- * Various elements are allowed in the body of a list item:
- *
- * - div.left, div.right, and div.center are allowed as direct children
- * - if div.center is not defined, anything that isn't div.left, div.right or div.expandable-content will be put in a div.center
- * - if div.center is defined, anything that isn't div.left, div.right or div.expandable-content will be ignored
- * - if list item has expandable attribute:
- * - div.expandable-content is allowed as a direct child
- * - div.top is allowed as direct child
- * - if div.top is defined, anything that isn't div.expandable-content should be inside div.top - anything else will be ignored
- * - if div.right is not defined, a div.right will be created with a drop-down chevron
- *
- * See the tests for examples.
- */
-
-
- createClass(ListItemElement, [{
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
- this.classList.add(defaultClassName$6);
-
- var top = void 0,
- expandableContent = void 0;
- var topContent = [];
- Array.from(this.childNodes).forEach(function (node) {
- if (node.nodeType !== Node.ELEMENT_NODE) {
- topContent.push(node);
- } else if (node.classList.contains('top')) {
- top = node;
- } else if (node.classList.contains('expandable-content')) {
- expandableContent = node;
- } else {
- topContent.push(node);
- }
-
- if (node.nodeName !== 'ONS-RIPPLE') {
- node.remove();
- }
- });
- topContent = top ? Array.from(top.childNodes) : topContent;
-
- var left = void 0,
- right = void 0,
- center = void 0;
- var centerContent = [];
- topContent.forEach(function (node) {
- if (node.nodeType !== Node.ELEMENT_NODE) {
- centerContent.push(node);
- } else if (node.classList.contains('left')) {
- left = node;
- } else if (node.classList.contains('right')) {
- right = node;
- } else if (node.classList.contains('center')) {
- center = node;
- } else {
- centerContent.push(node);
- }
- });
-
- if (this.hasAttribute('expandable')) {
- this.classList.add('list-item--expandable');
-
- if (!top) {
- top = document.createElement('div');
- top.classList.add('top');
- }
- top.classList.add('list-item__top');
- this.appendChild(top);
- this._top = top;
-
- if (expandableContent) {
- expandableContent.classList.add('list-item__expandable-content');
- this.appendChild(expandableContent);
- }
-
- if (!right) {
- right = document.createElement('div');
- right.classList.add('list-item__right', 'right');
-
- // We cannot use a pseudo-element for this chevron, as we cannot animate it using
- // JS. So, we make a chevron span instead.
- var chevron = document.createElement('span');
- chevron.classList.add('list-item__expand-chevron');
- right.appendChild(chevron);
- }
- } else {
- top = this;
- }
-
- if (!center) {
- center = document.createElement('div');
- center.classList.add('center');
- centerContent.forEach(function (node) {
- return center.appendChild(node);
- });
- }
- center.classList.add('list-item__center');
- top.appendChild(center);
-
- if (left) {
- left.classList.add('list-item__left');
- top.appendChild(left);
- }
- if (right) {
- right.classList.add('list-item__right');
- top.appendChild(right);
- }
-
- util$1.updateRipple(this);
- ModifierUtil.initModifier(this, scheme$10);
- }
-
- /**
- * @method showExpansion
- * @signature showExpansion()
- * @description
- * [en]Show the expandable content if the element is expandable.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'showExpansion',
- value: function showExpansion() {
- var _this2 = this;
-
- if (this.hasAttribute('expandable') && !this._expanding) {
- this.expanded = true;
- this._expanding = true;
-
- var animator = this._animatorFactory.newAnimator();
- animator.showExpansion(this, function () {
- _this2.classList.add('expanded');
- _this2._expanding = false;
- });
- }
- }
-
- /**
- * @method hideExpansion
- * @signature hideExpansion()
- * @description
- * [en]Hide the expandable content if the element expandable.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'hideExpansion',
- value: function hideExpansion() {
- var _this3 = this;
-
- if (this.hasAttribute('expandable') && !this._expanding) {
- this.expanded = false;
- this._expanding = true;
-
- var animator = this._animatorFactory.newAnimator();
- animator.hideExpansion(this, function () {
- _this3.classList.remove('expanded');
- _this3._expanding = false;
- });
- }
- }
- }, {
- key: 'toggleExpansion',
- value: function toggleExpansion() {
- this.classList.contains('expanded') ? this.hideExpansion() : this.showExpansion();
- this.dispatchEvent(new Event('expansion'));
- }
- }, {
- key: '_updateAnimatorFactory',
- value: function _updateAnimatorFactory() {
- return new AnimatorFactory({
- animators: _animatorDict$3,
- baseClass: ListItemAnimator,
- baseClassName: 'ListItemAnimator',
- defaultAnimation: this.getAttribute('animation') || 'default'
- });
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'class':
- util$1.restoreClass(this, defaultClassName$6, scheme$10);
- break;
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, scheme$10);
- break;
- case 'ripple':
- util$1.updateRipple(this);
- break;
- case 'animation':
- this._animatorFactory = this._updateAnimatorFactory();
- break;
- }
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- var _this4 = this;
-
- contentReady(this, function () {
- _this4._setupListeners(true);
- _this4._originalBackgroundColor = _this4.style.backgroundColor;
- _this4.tapped = false;
- });
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- this._setupListeners(false);
- }
- }, {
- key: '_setupListeners',
- value: function _setupListeners(add) {
- var action = (add ? 'add' : 'remove') + 'EventListener';
- util$1[action](this, 'touchstart', this._onTouch, { passive: true });
- util$1[action](this, 'touchmove', this._onRelease, { passive: true });
- this[action]('touchcancel', this._onRelease);
- this[action]('touchend', this._onRelease);
- this[action]('touchleave', this._onRelease);
- this[action]('drag', this._onDrag);
- this[action]('mousedown', this._onTouch);
- this[action]('mouseup', this._onRelease);
- this[action]('mouseout', this._onRelease);
-
- if (this._top) {
- this._top[action]('click', this.toggleExpansion);
- }
- }
- }, {
- key: '_onDrag',
- value: function _onDrag(event) {
- var gesture = event.gesture;
- // Prevent vertical scrolling if the users pans left or right.
- if (this.hasAttribute('lock-on-drag') && ['left', 'right'].indexOf(gesture.direction) > -1) {
- gesture.preventDefault();
- }
- }
- }, {
- key: '_onTouch',
- value: function _onTouch(e) {
- var _this5 = this;
-
- if (this.tapped || this !== e.target && (this._shouldIgnoreTap(e.target) || util$1.findParent(e.target, this._shouldIgnoreTap, function (p) {
- return p === _this5;
- }))) {
- return; // Ignore tap
- }
-
- this.tapped = true;
- var touchStyle = { transition: 'background-color 0.0s linear 0.02s, box-shadow 0.0s linear 0.02s' };
-
- if (this.hasAttribute('tappable')) {
- if (this.style.backgroundColor) {
- this._originalBackgroundColor = this.style.backgroundColor;
- }
-
- touchStyle.backgroundColor = this.getAttribute('tap-background-color') || '#d9d9d9';
- touchStyle.boxShadow = '0px -1px 0px 0px ' + touchStyle.backgroundColor;
- }
-
- styler(this, touchStyle);
- }
- }, {
- key: '_onRelease',
- value: function _onRelease() {
- this.tapped = false;
- this.style.backgroundColor = this._originalBackgroundColor || '';
- styler.clear(this, 'transition boxShadow');
- }
- }, {
- key: 'expandableContent',
- get: function get$$1() {
- return this.querySelector('.list-item__expandable-content');
- }
- }, {
- key: 'expandChevron',
- get: function get$$1() {
- return this.querySelector('.list-item__expand-chevron');
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'class', 'ripple', 'animation'];
- }
- }]);
- return ListItemElement;
- }(BaseElement);
-
- onsElements.ListItem = ListItemElement;
- customElements.define('ons-list-item', ListItemElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var defaultClassName$7 = 'list';
- var scheme$11 = { '': 'list--*' };
-
- /**
- * @element ons-list
- * @category list
- * @modifier inset
- * [en]Inset list that doesn't cover the whole width of the parent.[/en]
- * [ja]親要素の画面いっぱいに広がらないリストを表示します。[/ja]
- * @modifier noborder
- * [en]A list with no borders at the top and bottom.[/en]
- * [ja]リストの上下のボーダーが無いリストを表示します。[/ja]
- * @description
- * [en]Component to define a list, and the container for ons-list-item(s).[/en]
- * [ja]リストを表現するためのコンポーネント。ons-list-itemのコンテナとして使用します。[/ja]
- * @seealso ons-list-item
- * [en]ons-list-item component[/en]
- * [ja]ons-list-itemコンポーネント[/ja]
- * @seealso ons-list-header
- * [en]ons-list-header component[/en]
- * [ja]ons-list-headerコンポーネント[/ja]
- * @seealso ons-lazy-repeat
- * [en]ons-lazy-repeat component[/en]
- * [ja]ons-lazy-repeatコンポーネント[/ja]
- * @codepen yxcCt
- * @tutorial vanilla/Reference/list
- * @example
- * <ons-list>
- * <ons-list-header>Header Text</ons-list-header>
- * <ons-list-item>Item</ons-list-item>
- * <ons-list-item>Item</ons-list-item>
- * </ons-list>
- */
-
- var ListElement = function (_BaseElement) {
- inherits(ListElement, _BaseElement);
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the list.[/en]
- * [ja]リストの表現を指定します。[/ja]
- */
-
- function ListElement() {
- classCallCheck(this, ListElement);
-
- var _this = possibleConstructorReturn(this, (ListElement.__proto__ || Object.getPrototypeOf(ListElement)).call(this));
-
- _this._compile();
- return _this;
- }
-
- createClass(ListElement, [{
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
- this.classList.add(defaultClassName$7);
- ModifierUtil.initModifier(this, scheme$11);
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'class':
- util$1.restoreClass(this, defaultClassName$7, scheme$11);
- break;
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, scheme$11);
- break;
- }
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'class'];
- }
- }]);
- return ListElement;
- }(BaseElement);
-
- onsElements.List = ListElement;
- customElements.define('ons-list', ListElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
- var INPUT_ATTRIBUTES = ['autocapitalize', 'autocomplete', 'autocorrect', 'autofocus', 'disabled', 'inputmode', 'max', 'maxlength', 'min', 'minlength', 'name', 'pattern', 'placeholder', 'readonly', 'required', 'size', 'step', 'validator', 'value'];
-
- var BaseInputElement = function (_BaseElement) {
- inherits(BaseInputElement, _BaseElement);
- createClass(BaseInputElement, [{
- key: '_update',
- value: function _update() {} // Optionally implemented
-
- }, {
- key: '_scheme',
- get: function get$$1() {
- util$1.throwMember();
- }
- }, {
- key: '_template',
- get: function get$$1() {
- util$1.throwMember();
- }
- }, {
- key: 'type',
- get: function get$$1() {
- util$1.throwMember();
- }
- }]);
-
- function BaseInputElement() {
- classCallCheck(this, BaseInputElement);
-
- var _this = possibleConstructorReturn(this, (BaseInputElement.__proto__ || Object.getPrototypeOf(BaseInputElement)).call(this));
-
- if (_this.constructor === BaseInputElement) {
- util$1.throwAbstract();
- }
-
- contentReady(_this, function () {
- return _this._compile();
- });
- _this._boundDelegateEvent = _this._delegateEvent.bind(_this);
- return _this;
- }
-
- createClass(BaseInputElement, [{
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
- this._defaultClassName && this.classList.add(this._defaultClassName);
-
- if (this.children.length !== 0) {
- return;
- }
-
- this.appendChild(util$1.createFragment(this._template));
-
- this._setInputId();
-
- this._updateBoundAttributes();
-
- ModifierUtil.initModifier(this, this._scheme);
- }
- }, {
- key: '_updateBoundAttributes',
- value: function _updateBoundAttributes() {
- var _this2 = this;
-
- INPUT_ATTRIBUTES.forEach(function (attr) {
- if (_this2.hasAttribute(attr)) {
- _this2._input.setAttribute(attr, _this2.getAttribute(attr));
- } else {
- _this2._input.removeAttribute(attr);
- }
- });
-
- this._update();
- }
- }, {
- key: '_delegateEvent',
- value: function _delegateEvent(event) {
- var e = new CustomEvent(event.type, {
- bubbles: false,
- cancelable: true
- });
-
- return this.dispatchEvent(e);
- }
- }, {
- key: '_setInputId',
- value: function _setInputId() {
- if (this.hasAttribute('input-id')) {
- this._input.id = this.getAttribute('input-id');
- }
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- var _this3 = this;
-
- contentReady(this, function () {
- _this3._input.addEventListener('focus', _this3._boundDelegateEvent);
- _this3._input.addEventListener('blur', _this3._boundDelegateEvent);
- });
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- var _this4 = this;
-
- contentReady(this, function () {
- _this4._input.removeEventListener('focus', _this4._boundDelegateEvent);
- _this4._input.removeEventListener('blur', _this4._boundDelegateEvent);
- });
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- var _this5 = this;
-
- switch (name) {
- case 'modifier':
- contentReady(this, function () {
- return ModifierUtil.onModifierChanged(last, current, _this5, _this5._scheme);
- });
- break;
- case 'input-id':
- contentReady(this, function () {
- return _this5._setInputId();
- });
- break;
- case 'class':
- util$1.restoreClass(this, this._defaultClassName, this._scheme);
- break;
- }
-
- if (INPUT_ATTRIBUTES.indexOf(name) >= 0) {
- contentReady(this, function () {
- return _this5._updateBoundAttributes();
- });
- }
- }
- }, {
- key: '_defaultClassName',
- get: function get$$1() {
- return '';
- }
- }, {
- key: '_input',
- get: function get$$1() {
- return this.querySelector('input');
- }
- }, {
- key: 'value',
- get: function get$$1() {
- return this._input === null ? this.getAttribute('value') : this._input.value;
- },
- set: function set$$1(val) {
- var _this6 = this;
-
- contentReady(this, function () {
- if (val instanceof Date) {
- val = val.toISOString().substring(0, 10);
- }
- _this6._input.value = val;
- _this6._update();
- });
- }
- }, {
- key: 'disabled',
- set: function set$$1(value) {
- return util$1.toggleAttribute(this, 'disabled', value);
- },
- get: function get$$1() {
- return this.hasAttribute('disabled');
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'input-id', 'class'].concat(INPUT_ATTRIBUTES);
- }
- }]);
- return BaseInputElement;
- }(BaseElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
- var scheme$12 = {
- '.text-input': 'text-input--*',
- '.text-input__label': 'text-input--*__label'
- };
-
- /**
- * @element ons-input
- * @category form
- * @modifier material
- * [en]Displays a Material Design input.[/en]
- * [ja][/ja]
- * @modifier underbar
- * [en]Displays a horizontal line underneath a text input.[/en]
- * [ja][/ja]
- * @modifier transparent
- * [en]Displays a transparent input. Works for Material Design.[/en]
- * [ja][/ja]
- * @description
- * [en]
- * An input element. The `type` attribute can be used to change the input type. All text input types are supported.
- *
- * The component will automatically render as a Material Design input on Android devices.
- *
- * Most attributes that can be used for a normal `<input>` element can also be used on the `<ons-input>` element.
- * [/en]
- * [ja][/ja]
- * @tutorial vanilla/Reference/input
- * @seealso ons-checkbox
- * [en]The `<ons-checkbox>` element is used to display a checkbox.[/en]
- * [ja][/ja]
- * @seealso ons-radio
- * [en]The `<ons-radio>` element is used to display a radio button.[/en]
- * [ja][/ja]
- * @seealso ons-range
- * [en]The `<ons-range>` element is used to display a range slider.[/en]
- * [ja][/ja]
- * @seealso ons-switch
- * [en]The `<ons-switch>` element is used to display a draggable toggle switch.[/en]
- * [ja][/ja]
- * @seealso ons-select
- * [en]The `<ons-select>` element is used to display a select box.[/en]
- * [ja][/ja]
- * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
- * @example
- * <ons-input placeholder="Username" float></ons-input>
- */
-
- var InputElement = function (_BaseInputElement) {
- inherits(InputElement, _BaseInputElement);
-
- function InputElement() {
- classCallCheck(this, InputElement);
-
- var _this = possibleConstructorReturn(this, (InputElement.__proto__ || Object.getPrototypeOf(InputElement)).call(this));
-
- _this._boundOnInput = _this._update.bind(_this);
- _this._boundOnFocusin = _this._update.bind(_this);
- return _this;
- }
-
- /* Inherited props */
-
- createClass(InputElement, [{
- key: '_update',
- value: function _update() {
- this._updateLabel();
- this._updateLabelClass();
- }
- }, {
- key: '_updateLabel',
-
-
- /* Own props */
-
- value: function _updateLabel() {
- var label = this.getAttribute('placeholder') || '';
-
- if (typeof this._helper.textContent !== 'undefined') {
- this._helper.textContent = label;
- } else {
- this._helper.innerText = label;
- }
- }
- }, {
- key: '_updateLabelClass',
- value: function _updateLabelClass() {
- if (this.value === '') {
- this._helper.classList.remove('text-input--material__label--active');
- } else {
- this._helper.classList.add('text-input--material__label--active');
- }
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- var _this2 = this;
-
- get(InputElement.prototype.__proto__ || Object.getPrototypeOf(InputElement.prototype), 'connectedCallback', this).call(this);
-
- contentReady(this, function () {
- _this2._input.addEventListener('input', _this2._boundOnInput);
- _this2._input.addEventListener('focusin', _this2._boundOnFocusin);
- });
-
- var type = this.getAttribute('type');
- if (['checkbox', 'radio'].indexOf(type) >= 0) {
- util$1.warn('Warn: <ons-input type="' + type + '"> is deprecated since v2.4.0. Use <ons-' + type + '> instead.');
- }
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- var _this3 = this;
-
- get(InputElement.prototype.__proto__ || Object.getPrototypeOf(InputElement.prototype), 'disconnectedCallback', this).call(this);
-
- contentReady(this, function () {
- _this3._input.removeEventListener('input', _this3._boundOnInput);
- _this3._input.removeEventListener('focusin', _this3._boundOnFocusin);
- });
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- var _this4 = this;
-
- switch (name) {
- case 'type':
- contentReady(this, function () {
- return _this4._input.setAttribute('type', _this4.type);
- });
- break;
- default:
- get(InputElement.prototype.__proto__ || Object.getPrototypeOf(InputElement.prototype), 'attributeChangedCallback', this).call(this, name, last, current);
- }
- }
-
- /**
- * @attribute placeholder
- * @type {String}
- * @description
- * [en]Placeholder text. In Material Design, this placeholder will be a floating label.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute float
- * @description
- * [en]If this attribute is present, the placeholder will be animated in Material Design.[/en]
- * [ja]この属性が設定された時、ラベルはアニメーションするようになります。[/ja]
- */
-
- /**
- * @attribute type
- * @type {String}
- * @description
- * [en]
- * Specify the input type. This is the same as the "type" attribute for normal inputs. It expects strict text types such as `text`, `password`, etc. For checkbox, radio button, select or range, please have a look at the corresponding elements.
- *
- * Please take a look at [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-type) for an exhaustive list of possible values. Depending on the platform and browser version some of these might not work.
- * [/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute input-id
- * @type {String}
- * @description
- * [en]Specify the "id" attribute of the inner `<input>` element. This is useful when using `<label for="...">` elements.[/en]
- * [ja][/ja]
- */
-
- /**
- * @property value
- * @type {String}
- * @description
- * [en]The current value of the input.[/en]
- * [ja][/ja]
- */
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the input is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- }, {
- key: '_scheme',
- get: function get$$1() {
- return scheme$12;
- }
- }, {
- key: '_template',
- get: function get$$1() {
- return '\n <input type="' + this.type + '" class="text-input">\n <span class="text-input__label"></span>\n ';
- }
- }, {
- key: 'type',
- get: function get$$1() {
- var type = this.getAttribute('type');
- return ['checkbox', 'radio'].indexOf(type) < 0 && type || 'text';
- }
- }, {
- key: '_helper',
- get: function get$$1() {
- return this.querySelector('span');
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return [].concat(toConsumableArray(get(InputElement.__proto__ || Object.getPrototypeOf(InputElement), 'observedAttributes', this)), ['type']);
- }
- }]);
- return InputElement;
- }(BaseInputElement);
-
- onsElements.Input = InputElement;
- customElements.define('ons-input', InputElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
- var BaseCheckboxElement = function (_BaseInputElement) {
- inherits(BaseCheckboxElement, _BaseInputElement);
-
- function BaseCheckboxElement() {
- classCallCheck(this, BaseCheckboxElement);
-
- var _this = possibleConstructorReturn(this, (BaseCheckboxElement.__proto__ || Object.getPrototypeOf(BaseCheckboxElement)).call(this));
-
- if (_this.constructor === BaseCheckboxElement) {
- util.throwAbstract();
- }
-
- contentReady(_this, function () {
- _this.attributeChangedCallback('checked', null, _this.getAttribute('checked'));
- });
- return _this;
- }
-
- /* Inherited props */
-
- createClass(BaseCheckboxElement, [{
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'checked':
- this.checked = current !== null;
- break;
- default:
- get(BaseCheckboxElement.prototype.__proto__ || Object.getPrototypeOf(BaseCheckboxElement.prototype), 'attributeChangedCallback', this).call(this, name, last, current);
- }
- }
- }, {
- key: '_template',
- get: function get$$1() {
- return '\n <input type="' + this.type + '" class="' + this._defaultClassName + '__input">\n <span class="' + this._defaultClassName + '__checkmark"></span>\n ';
- }
-
- /* Own props */
-
- }, {
- key: '_helper',
- get: function get$$1() {
- return this.querySelector('span');
- }
- }, {
- key: 'checked',
- get: function get$$1() {
- return this._input.checked;
- },
- set: function set$$1(val) {
- var _this2 = this;
-
- contentReady(this, function () {
- _this2._input.checked = val;
- });
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return [].concat(toConsumableArray(get(BaseCheckboxElement.__proto__ || Object.getPrototypeOf(BaseCheckboxElement), 'observedAttributes', this)), ['checked']);
- }
- }]);
- return BaseCheckboxElement;
- }(BaseInputElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
- var scheme$13 = {
- '.checkbox': 'checkbox--*',
- '.checkbox__input': 'checkbox--*__input',
- '.checkbox__checkmark': 'checkbox--*__checkmark'
- };
-
- /**
- * @element ons-checkbox
- * @category form
- * @modifier material
- * [en]Displays a Material Design checkbox.[/en]
- * [ja][/ja]
- * @modifier noborder
- * [en]iOS borderless checkbox.[/en]
- * [ja][/ja]
- * @description
- * [en]
- * A checkbox element. The component will automatically render as a Material Design checkbox on Android devices.
- *
- * Most attributes that can be used for a normal `<input type="checkbox">` element can also be used on the `<ons-checkbox>` element.
- * [/en]
- * [ja][/ja]
- * @tutorial vanilla/Reference/checkbox
- * @seealso ons-switch
- * [en]The `<ons-switch>` element is used to display a draggable toggle switch.[/en]
- * [ja][/ja]
- * @seealso ons-radio
- * [en]The `<ons-radio>` element is used to display a radio button.[/en]
- * [ja][/ja]
- * @seealso ons-input
- * [en]The `<ons-input>` element is used to display a text input.[/en]
- * [ja][/ja]
- * @seealso ons-search-input
- * [en]The `<ons-search-input>` element is used to display a search input.[/en]
- * [ja][/ja]
- * @seealso ons-range
- * [en]The `<ons-range>` element is used to display a range slider.[/en]
- * [ja][/ja]
- * @seealso ons-select
- * [en]The `<ons-select>` element is used to display a select box.[/en]
- * [ja][/ja]
- * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
- * @example
- * <ons-checkbox checked></ons-checkbox>
- */
-
- var CheckboxElement = function (_BaseCheckboxElement) {
- inherits(CheckboxElement, _BaseCheckboxElement);
-
- function CheckboxElement() {
- classCallCheck(this, CheckboxElement);
- return possibleConstructorReturn(this, (CheckboxElement.__proto__ || Object.getPrototypeOf(CheckboxElement)).apply(this, arguments));
- }
-
- createClass(CheckboxElement, [{
- key: '_scheme',
- get: function get$$1() {
- return scheme$13;
- }
- }, {
- key: '_defaultClassName',
- get: function get$$1() {
- return 'checkbox';
- }
- }, {
- key: 'type',
- get: function get$$1() {
- return 'checkbox';
- }
-
- /**
- * @attribute input-id
- * @type {String}
- * @description
- * [en]Specify the "id" attribute of the inner `<input>` element. This is useful when using `<label for="...">` elements.[/en]
- * [ja][/ja]
- */
-
- /**
- * @property value
- * @type {String}
- * @description
- * [en]The current value of the checkbox.[/en]
- * [ja][/ja]
- */
-
- /**
- * @property checked
- * @type {Boolean}
- * @description
- * [en]Whether the checkbox is checked or not.[/en]
- * [ja][/ja]
- */
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the checkbox is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- }]);
- return CheckboxElement;
- }(BaseCheckboxElement);
-
- onsElements.Checkbox = CheckboxElement;
- customElements.define('ons-checkbox', CheckboxElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
- var scheme$14 = {
- '.radio-button': 'radio-button--*',
- '.radio-button__input': 'radio-button--*__input',
- '.radio-button__checkmark': 'radio-button--*__checkmark'
- };
-
- /**
- * @element ons-radio
- * @category form
- * @modifier material
- * [en]Displays a Material Design radio button.[/en]
- * [ja][/ja]
- * @description
- * [en]
- * A radio button element. The component will automatically render as a Material Design radio button on Android devices.
- *
- * Most attributes that can be used for a normal `<input type="radio">` element can also be used on the `<ons-radio>` element.
- * [/en]
- * [ja][/ja]
- * @tutorial vanilla/Reference/radio
- * @seealso ons-select
- * [en]The `<ons-select>` element is used to display a select box.[/en]
- * [ja][/ja]
- * @seealso ons-checkbox
- * [en]The `<ons-checkbox>` element is used to display a checkbox.[/en]
- * [ja][/ja]
- * @seealso ons-switch
- * [en]The `<ons-switch>` element is used to display a draggable toggle switch.[/en]
- * [ja][/ja]
- * @seealso ons-input
- * [en]The `<ons-input>` element is used to display a text input.[/en]
- * [ja][/ja]
- * @seealso ons-search-input
- * [en]The `<ons-search-input>` element is used to display a search input.[/en]
- * [ja][/ja]
- * @seealso ons-range
- * [en]The `<ons-range>` element is used to display a range slider.[/en]
- * [ja][/ja]
- * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
- * @example
- * <ons-radio checked></ons-radio>
- */
-
- var RadioElement = function (_BaseCheckboxElement) {
- inherits(RadioElement, _BaseCheckboxElement);
-
- function RadioElement() {
- classCallCheck(this, RadioElement);
- return possibleConstructorReturn(this, (RadioElement.__proto__ || Object.getPrototypeOf(RadioElement)).apply(this, arguments));
- }
-
- createClass(RadioElement, [{
- key: '_scheme',
- get: function get$$1() {
- return scheme$14;
- }
- }, {
- key: '_defaultClassName',
- get: function get$$1() {
- return 'radio-button';
- }
- }, {
- key: 'type',
- get: function get$$1() {
- return 'radio';
- }
-
- /**
- * @attribute input-id
- * @type {String}
- * @description
- * [en]Specify the "id" attribute of the inner `<input>` element. This is useful when using `<label for="...">` elements.[/en]
- * [ja][/ja]
- */
-
- /**
- * @property value
- * @type {String}
- * @description
- * [en]The current value of the radio button.[/en]
- * [ja][/ja]
- */
-
- /**
- * @property checked
- * @type {Boolean}
- * @description
- * [en]Whether the radio button is checked or not.[/en]
- * [ja][/ja]
- */
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the radio button is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- }]);
- return RadioElement;
- }(BaseCheckboxElement);
-
- onsElements.Radio = RadioElement;
- customElements.define('ons-radio', RadioElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
- var scheme$15 = {
- '.search-input': 'search-input--*'
- };
-
- /**
- * @element ons-search-input
- * @category form
- * @modifier material
- * [en]Displays a Material Design search input.[/en]
- * [ja][/ja]
- * @description
- * [en]
- * A search input element. The component will automatically render as a Material Design search input on Android devices.
- *
- * Most attributes that can be used for a normal `<input>` element can also be used on the `<ons-search-input>` element.
- * [/en]
- * [ja][/ja]
- * @tutorial vanilla/Reference/search-input
- * @seealso ons-input
- * [en]The `<ons-input>` element is used to display a text input.[/en]
- * [ja][/ja]
- * @seealso ons-range
- * [en]The `<ons-range>` element is used to display a range slider.[/en]
- * [ja][/ja]
- * @seealso ons-switch
- * [en]The `<ons-switch>` element is used to display a draggable toggle switch.[/en]
- * [ja][/ja]
- * @seealso ons-select
- * [en]The `<ons-select>` element is used to display a select box.[/en]
- * [ja][/ja]
- * @seealso ons-checkbox
- * [en]The `<ons-checkbox>` element is used to display a checkbox.[/en]
- * [ja][/ja]
- * @seealso ons-radio
- * [en]The `<ons-radio>` element is used to display a radio button.[/en]
- * [ja][/ja]
- * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
- * @example
- * <ons-search-input placeholder="Search"></ons-search-input>
- */
-
- var SearchInputElement = function (_BaseInputElement) {
- inherits(SearchInputElement, _BaseInputElement);
-
- function SearchInputElement() {
- classCallCheck(this, SearchInputElement);
- return possibleConstructorReturn(this, (SearchInputElement.__proto__ || Object.getPrototypeOf(SearchInputElement)).apply(this, arguments));
- }
-
- createClass(SearchInputElement, [{
- key: '_scheme',
- get: function get$$1() {
- return scheme$15;
- }
- }, {
- key: '_template',
- get: function get$$1() {
- return '\n <input type="' + this.type + '" class="search-input">\n ';
- }
- }, {
- key: 'type',
- get: function get$$1() {
- return 'search';
- }
-
- /**
- * @attribute input-id
- * @type {String}
- * @description
- * [en]Specify the "id" attribute of the inner `<input>` element. This is useful when using `<label for="...">` elements.[/en]
- * [ja][/ja]
- */
-
- /**
- * @property value
- * @type {String}
- * @description
- * [en]The current value of the input.[/en]
- * [ja][/ja]
- */
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the input is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- }]);
- return SearchInputElement;
- }(BaseInputElement);
-
- onsElements.SearchInput = SearchInputElement;
- customElements.define('ons-search-input', SearchInputElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var ModalAnimator = function (_BaseAnimator) {
- inherits(ModalAnimator, _BaseAnimator);
-
- /**
- * @param {Object} options
- * @param {String} options.timing
- * @param {Number} options.duration
- * @param {Number} options.delay
- */
- function ModalAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'linear' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.2 : _ref$duration;
-
- classCallCheck(this, ModalAnimator);
- return possibleConstructorReturn(this, (ModalAnimator.__proto__ || Object.getPrototypeOf(ModalAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
- }
-
- /**
- * @param {HTMLElement} modal
- * @param {Function} callback
- */
-
-
- createClass(ModalAnimator, [{
- key: 'show',
- value: function show(modal, callback) {
- callback();
- }
-
- /**
- * @param {HTMLElement} modal
- * @param {Function} callback
- */
-
- }, {
- key: 'hide',
- value: function hide(modal, callback) {
- callback();
- }
- }]);
- return ModalAnimator;
- }(BaseAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * iOS style animator for dialog.
- */
-
- var FadeModalAnimator = function (_ModalAnimator) {
- inherits(FadeModalAnimator, _ModalAnimator);
-
- function FadeModalAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'linear' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.3 : _ref$duration;
-
- classCallCheck(this, FadeModalAnimator);
- return possibleConstructorReturn(this, (FadeModalAnimator.__proto__ || Object.getPrototypeOf(FadeModalAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
- }
-
- /**
- * @param {HTMLElement} modal
- * @param {Function} callback
- */
-
-
- createClass(FadeModalAnimator, [{
- key: 'show',
- value: function show(modal, callback) {
- callback = callback ? callback : function () {};
-
- Animit(modal, this.def).default({ opacity: 0 }, { opacity: 1 }).queue(function (done) {
- callback();
- done();
- }).play();
- }
-
- /**
- * @param {HTMLElement} modal
- * @param {Function} callback
- */
-
- }, {
- key: 'hide',
- value: function hide(modal, callback) {
- callback = callback ? callback : function () {};
-
- Animit(modal, this.def).default({ opacity: 1 }, { opacity: 0 }).queue(function (done) {
- callback();
- done();
- }).play();
- }
- }]);
- return FadeModalAnimator;
- }(ModalAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * iOS style animator for modal.
- */
-
- var LiftModalAnimator = function (_ModalAnimator) {
- inherits(LiftModalAnimator, _ModalAnimator);
-
- function LiftModalAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'cubic-bezier( .1, .7, .1, 1)' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.4 : _ref$duration;
-
- classCallCheck(this, LiftModalAnimator);
- return possibleConstructorReturn(this, (LiftModalAnimator.__proto__ || Object.getPrototypeOf(LiftModalAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
- }
-
- /**
- * @param {HTMLElement} modal
- * @param {Function} callback
- */
-
-
- createClass(LiftModalAnimator, [{
- key: 'show',
- value: function show(modal, callback) {
- callback = callback ? callback : function () {};
-
- Animit(modal, this.def).default({ transform: 'translate3d(0, 100%, 0)' }, { transform: 'translate3d(0, 0, 0)' }).queue(function (done) {
- callback();
- done();
- }).play();
- }
-
- /**
- * @param {HTMLElement} modal
- * @param {Function} callback
- */
-
- }, {
- key: 'hide',
- value: function hide(modal, callback) {
- callback = callback ? callback : function () {};
-
- Animit(modal, this.def).default({ transform: 'translate3d(0, 0, 0)' }, { transform: 'translate3d(0, 100%, 0)' }).queue(function (done) {
- callback();
- done();
- }).play();
- }
- }]);
- return LiftModalAnimator;
- }(ModalAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var scheme$16 = {
- '': 'modal--*',
- 'modal__content': 'modal--*__content'
- };
-
- var defaultClassName$8 = 'modal';
-
- var _animatorDict$4 = {
- 'default': ModalAnimator,
- 'fade': FadeModalAnimator,
- 'lift': LiftModalAnimator,
- 'none': ModalAnimator
- };
-
- /**
- * @element ons-modal
- * @category dialog
- * @description
- * [en]
- * Modal component that masks current screen. Underlying components are not subject to any events while the modal component is shown.
- *
- * This component can be used to block user input while some operation is running or to show some information to the user.
- * [/en]
- * [ja]
- * 画面全体をマスクするモーダル用コンポーネントです。下側にあるコンポーネントは、
- * モーダルが表示されている間はイベント通知が行われません。
- * [/ja]
- * @seealso ons-dialog
- * [en]The `<ons-dialog>` component can be used to create a modal dialog.[/en]
- * [ja][/ja]
- * @codepen devIg
- * @tutorial vanilla/reference/modal
- * @example
- * <ons-modal id="modal">
- * Modal content
- * </ons-modal>
- * <script>
- * var modal = document.getElementById('modal');
- * modal.show();
- * </script>
- */
-
- var ModalElement = function (_BaseDialogElement) {
- inherits(ModalElement, _BaseDialogElement);
-
- /**
- * @event preshow
- * @description
- * [en]Fired just before the modal is displayed.[/en]
- * [ja]モーダルが表示される直前に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.modal
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- * @param {Function} event.cancel
- * [en]Execute this function to stop the modal from being shown.[/en]
- * [ja]この関数を実行すると、ダイアログの表示がキャンセルされます。[/ja]
- */
-
- /**
- * @event postshow
- * @description
- * [en]Fired just after the modal is displayed.[/en]
- * [ja]モーダルが表示された直後に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.modal
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- */
-
- /**
- * @event prehide
- * @description
- * [en]Fired just before the modal is hidden.[/en]
- * [ja]モーダルが隠れる直前に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.modal
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- * @param {Function} event.cancel
- * [en]Execute this function to stop the modal from being hidden.[/en]
- * [ja]この関数を実行すると、ダイアログの非表示がキャンセルされます。[/ja]
- */
-
- /**
- * @event posthide
- * @description
- * [en]Fired just after the modal is hidden.[/en]
- * [ja]モーダルが隠れた後に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.modal
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- */
-
- /**
- * @attribute animation
- * @type {String}
- * @default default
- * @description
- * [en]The animation used when showing and hiding the modal. Can be either `"none"`, `"fade"` or `"lift"`.[/en]
- * [ja]モーダルを表示する際のアニメーション名を指定します。"none"もしくは"fade","lift"を指定できます。[/ja]
- */
-
- /**
- * @attribute animation-options
- * @type {Expression}
- * @description
- * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. <code>{duration: 0.2, delay: 1, timing: 'ease-in'}</code>[/ja]
- */
-
- function ModalElement() {
- classCallCheck(this, ModalElement);
-
- var _this = possibleConstructorReturn(this, (ModalElement.__proto__ || Object.getPrototypeOf(ModalElement)).call(this));
-
- _this._defaultDBB = function () {
- return undefined;
- };
- contentReady(_this, function () {
- return _this._compile();
- });
- return _this;
- }
-
- createClass(ModalElement, [{
- key: '_updateAnimatorFactory',
- value: function _updateAnimatorFactory() {
- return new AnimatorFactory({
- animators: _animatorDict$4,
- baseClass: ModalAnimator,
- baseClassName: 'ModalAnimator',
- defaultAnimation: this.getAttribute('animation')
- });
- }
-
- /**
- * @property onDeviceBackButton
- * @type {Object}
- * @description
- * [en]Back-button handler.[/en]
- * [ja]バックボタンハンドラ。[/ja]
- */
-
- }, {
- key: '_compile',
- value: function _compile() {
- this.style.display = 'none';
- this.style.zIndex = 10001;
- this.classList.add(defaultClassName$8);
-
- if (!util$1.findChild(this, '.modal__content')) {
- var content = document.createElement('div');
- content.classList.add('modal__content');
-
- while (this.childNodes[0]) {
- var node = this.childNodes[0];
- this.removeChild(node);
- content.insertBefore(node, null);
- }
-
- this.appendChild(content);
- }
-
- ModifierUtil.initModifier(this, this._scheme);
- }
- }, {
- key: '_toggleStyle',
- value: function _toggleStyle(shouldShow) {
- this.style.display = shouldShow ? 'table' : 'none';
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- get(ModalElement.prototype.__proto__ || Object.getPrototypeOf(ModalElement.prototype), 'connectedCallback', this).call(this);
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- get(ModalElement.prototype.__proto__ || Object.getPrototypeOf(ModalElement.prototype), 'disconnectedCallback', this).call(this);
- }
-
- /**
- * @property visible
- * @readonly
- * @type {Boolean}
- * @description
- * [en]Whether the element is visible or not.[/en]
- * [ja]要素が見える場合に`true`。[/ja]
- */
-
- /**
- * @method show
- * @signature show([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Available animations are `"none"` and `"fade"`.[/en]
- * [ja]アニメーション名を指定します。"none", "fade"のいずれかを指定します。[/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
- * @param {Function} [options.callback]
- * [en]This function is called after the modal has been revealed.[/en]
- * [ja]モーダルが表示され終わった後に呼び出される関数オブジェクトを指定します。[/ja]
- * @description
- * [en]Show modal.[/en]
- * [ja]モーダルを表示します。[/ja]
- * @return {Promise}
- * [en]Resolves to the displayed element[/en]
- * [ja][/ja]
- */
-
- /**
- * @method toggle
- * @signature toggle([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Available animations are `"none"` and `"fade"`.[/en]
- * [ja]アニメーション名を指定します。"none", "fade"のいずれかを指定します。[/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
- * @param {Function} [options.callback]
- * [en]This function is called after the modal has been revealed.[/en]
- * [ja]モーダルが表示され終わった後に呼び出される関数オブジェクトを指定します。[/ja]
- * @description
- * [en]Toggle modal visibility.[/en]
- * [ja]モーダルの表示を切り替えます。[/ja]
- */
-
- /**
- * @method hide
- * @signature hide([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Available animations are `"none"` and `"fade"`.[/en]
- * [ja]アニメーション名を指定します。"none", "fade"のいずれかを指定します。[/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
- * @param {Function} [options.callback]
- * [en]This function is called after the modal has been revealed.[/en]
- * [ja]モーダルが表示され終わった後に呼び出される関数オブジェクトを指定します。[/ja]
- * @description
- * [en]Hide modal.[/en]
- * [ja]モーダルを非表示にします。[/ja]
- * @return {Promise}
- * [en]Resolves to the hidden element[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- if (name === 'class') {
- util$1.restoreClass(this, defaultClassName$8, scheme$16);
- } else {
- get(ModalElement.prototype.__proto__ || Object.getPrototypeOf(ModalElement.prototype), 'attributeChangedCallback', this).call(this, name, last, current);
- }
- }
-
- /**
- * @param {String} name
- * @param {Function} Animator
- */
-
- }, {
- key: '_scheme',
- get: function get$$1() {
- return scheme$16;
- }
- }], [{
- key: 'registerAnimator',
- value: function registerAnimator(name, Animator) {
- if (!(Animator.prototype instanceof ModalAnimator)) {
- util$1.throwAnimator('Modal');
- }
- _animatorDict$4[name] = Animator;
- }
- }, {
- key: 'observedAttributes',
- get: function get$$1() {
- return [].concat(toConsumableArray(get(ModalElement.__proto__ || Object.getPrototypeOf(ModalElement), 'observedAttributes', this)), ['class']);
- }
- }, {
- key: 'animators',
- get: function get$$1() {
- return _animatorDict$4;
- }
- }, {
- key: 'ModalAnimator',
- get: function get$$1() {
- return ModalAnimator;
- }
- }]);
- return ModalElement;
- }(BaseDialogElement);
-
- onsElements.Modal = ModalElement;
- customElements.define('ons-modal', ModalElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var widthToPx = function widthToPx(width) {
- var _ref = [parseInt(width, 10), /px/.test(width)],
- value = _ref[0],
- px = _ref[1];
-
- return px ? value : Math.round(document.body.offsetWidth * value / 100);
- };
-
- var SwipeReveal = function () {
- function SwipeReveal(params) {
- var _this = this;
-
- classCallCheck(this, SwipeReveal);
-
- 'element ignoreSwipe isInitialState onDragCallback swipeMax swipeMin swipeMid'.split(/\s+/).forEach(function (key) {
- return _this[key] = params[key];
- });
-
- this.elementHandler = params.elementHandler || params.element;
- this.getThreshold = params.getThreshold || function () {
- return .5;
- };
- this.getSide = params.getSide || function () {
- return 'left';
- };
-
- this.handleGesture = this.handleGesture.bind(this);
-
- this._shouldFixScroll = util$1.globals.actualMobileOS === 'ios';
- }
-
- createClass(SwipeReveal, [{
- key: 'update',
- value: function update() {
- var swipeable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.element.hasAttribute('swipeable');
-
- if (!this.gestureDetector) {
- this.gestureDetector = new GestureDetector(this.elementHandler, { dragMinDistance: 1, passive: !this._shouldFixScroll });
- }
-
- var action = swipeable ? 'on' : 'off';
- this.gestureDetector[action]('drag dragstart dragend', this.handleGesture);
- }
- }, {
- key: 'handleGesture',
- value: function handleGesture(e) {
- if (e.gesture) {
- if (e.type === 'dragstart') {
- this.onDragStart(e);
- } else if (!this._ignoreDrag) {
- e.type === 'dragend' ? this.onDragEnd(e) : this.onDrag(e);
- }
- }
- }
- }, {
- key: 'onDragStart',
- value: function onDragStart(event) {
- var _this2 = this;
-
- var getDistance = function getDistance() {
- return _this2.getSide() === 'left' ? event.gesture.center.clientX : window.innerWidth - event.gesture.center.clientX;
- };
- this._ignoreDrag = event.consumed || !util$1.isValidGesture(event) || this.ignoreSwipe(event, getDistance());
-
- if (!this._ignoreDrag) {
- event.consume && event.consume();
- event.consumed = true;
-
- this._width = widthToPx(this.element.style.width || '100%');
- this._startDistance = this._distance = !(this.isInitialState instanceof Function) || this.isInitialState() ? 0 : this._width;
-
- util$1.iosPreventScroll(this.gestureDetector);
- }
- }
- }, {
- key: 'onDrag',
- value: function onDrag(event) {
- event.stopPropagation();
-
- var delta = this.getSide() === 'left' ? event.gesture.deltaX : -event.gesture.deltaX;
- var distance = Math.max(0, Math.min(this._width, this._startDistance + delta));
- if (distance !== this._distance) {
- this._distance = distance;
- this.swipeMid(this._distance, this._width);
- }
- }
- }, {
- key: 'onDragEnd',
- value: function onDragEnd(event) {
- event.stopPropagation();
-
- var direction = event.gesture.interimDirection;
- var isSwipeMax = this.getSide() !== direction && this._distance > this._width * this.getThreshold();
- isSwipeMax ? this.swipeMax() : this.swipeMin();
- }
- }, {
- key: 'dispose',
- value: function dispose() {
- this.gestureDetector && this.gestureDetector.dispose();
- this.gestureDetector = this.element = this.elementHandler = null;
- }
- }]);
- return SwipeReveal;
- }();
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var NavigatorAnimator = function (_BaseAnimator) {
- inherits(NavigatorAnimator, _BaseAnimator);
-
- /**
- * @param {Object} options
- * @param {String} options.timing
- * @param {Number} options.duration
- * @param {Number} options.delay
- */
- function NavigatorAnimator(options) {
- classCallCheck(this, NavigatorAnimator);
-
- options = util$1.extend({
- timing: 'linear',
- duration: '0.4',
- delay: '0'
- }, options || {});
-
- return possibleConstructorReturn(this, (NavigatorAnimator.__proto__ || Object.getPrototypeOf(NavigatorAnimator)).call(this, options));
- }
-
- createClass(NavigatorAnimator, [{
- key: 'push',
- value: function push(enterPage, leavePage, callback) {
- callback();
- }
- }, {
- key: 'pop',
- value: function pop(enterPage, leavePage, callback) {
- callback();
- }
- }, {
- key: 'block',
- value: function block(page) {
- var blocker = util$1.createElement('\n <div style="position: absolute; background-color: transparent; width: 100%; height: 100%; z-index: 100000"></div>\n ');
- page.parentNode.appendChild(blocker);
- return function () {
- return blocker.remove();
- };
- }
- }]);
- return NavigatorAnimator;
- }(BaseAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * Abstract swipe animator for iOS navigator transition.
- */
-
- var IOSSwipeNavigatorAnimator = function (_NavigatorAnimator) {
- inherits(IOSSwipeNavigatorAnimator, _NavigatorAnimator);
- createClass(IOSSwipeNavigatorAnimator, null, [{
- key: 'swipeable',
- get: function get$$1() {
- return true;
- }
- }]);
-
- function IOSSwipeNavigatorAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
-
- var _ref$durationRestore = _ref.durationRestore,
- durationRestore = _ref$durationRestore === undefined ? 0.1 : _ref$durationRestore,
- _ref$durationSwipe = _ref.durationSwipe,
- durationSwipe = _ref$durationSwipe === undefined ? 0.15 : _ref$durationSwipe,
- _ref$timingSwipe = _ref.timingSwipe,
- timingSwipe = _ref$timingSwipe === undefined ? 'linear' : _ref$timingSwipe,
- rest = objectWithoutProperties(_ref, ['durationRestore', 'durationSwipe', 'timingSwipe']);
- classCallCheck(this, IOSSwipeNavigatorAnimator);
-
- var _this = possibleConstructorReturn(this, (IOSSwipeNavigatorAnimator.__proto__ || Object.getPrototypeOf(IOSSwipeNavigatorAnimator)).call(this, _extends({}, rest)));
-
- if (_this.constructor === IOSSwipeNavigatorAnimator) {
- util$1.throwAbstract();
- }
-
- _this.durationRestore = durationRestore;
- _this.durationSwipe = durationSwipe;
- _this.timingSwipe = timingSwipe;
-
- _this.optSwipe = { timing: timingSwipe, duration: durationSwipe };
- _this.optRestore = { timing: timingSwipe, duration: durationRestore };
-
- _this.swipeShadow = util$1.createElement('<div style="position: absolute; height: 100%; width: 12px; right: 100%; top: 0; bottom: 0; z-index: -1;' + 'background: linear-gradient(to right, transparent 0, rgba(0,0,0,.04) 40%, rgba(0,0,0,.12) 80%, rgba(0,0,0,.16) 100%);"></div>');
-
- _this.isDragStart = true;
- return _this;
- }
-
- createClass(IOSSwipeNavigatorAnimator, [{
- key: '_decompose',
- value: function _decompose() {
- util$1.throwMember();
- }
- }, {
- key: '_shouldAnimateToolbar',
- value: function _shouldAnimateToolbar() {
- util$1.throwMember();
- }
- }, {
- key: '_calculateDelta',
- value: function _calculateDelta() {
- util$1.throwMember();
- }
- }, {
- key: '_dragStartSetup',
- value: function _dragStartSetup(enterPage, leavePage) {
- this.isDragStart = false;
-
- // Avoid content clicks
- this.unblock = get(IOSSwipeNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(IOSSwipeNavigatorAnimator.prototype), 'block', this).call(this, leavePage);
-
- // Mask
- enterPage.parentElement.insertBefore(this.backgroundMask, enterPage);
-
- // Decomposition
- this.target = {
- enter: util$1.findToolbarPage(enterPage) || enterPage,
- leave: util$1.findToolbarPage(leavePage) || leavePage
- };
- this.decomp = {
- enter: this._decompose(this.target.enter),
- leave: this._decompose(this.target.leave)
- };
-
- // Animation values
- this.delta = this._calculateDelta(leavePage, this.decomp.leave);
- this.shouldAnimateToolbar = this._shouldAnimateToolbar(this.target.enter, this.target.leave);
-
- // Shadow && styles
- if (this.shouldAnimateToolbar) {
- this.swipeShadow.style.top = this.decomp.leave.toolbar.offsetHeight + 'px';
- this.target.leave.appendChild(this.swipeShadow);
- this._saveStyle(this.target.enter, this.target.leave);
- } else {
- leavePage.appendChild(this.swipeShadow);
- this._saveStyle(enterPage, leavePage);
- }
- leavePage.classList.add('overflow-visible');
- this.overflowElement = leavePage;
- this.decomp.leave.content.classList.add('content-swiping');
- }
- }, {
- key: 'translate',
- value: function translate(distance, maxWidth, enterPage, leavePage) {
- this.isSwiping = true;
-
- if (enterPage.style.display === 'none') {
- enterPage.style.display = '';
- }
-
- if (this.isDragStart) {
- this.maxWidth = maxWidth;
- this._dragStartSetup(enterPage, leavePage);
- }
-
- var swipeRatio = (distance - maxWidth) / maxWidth;
-
- if (this.shouldAnimateToolbar) {
-
- Animit.runAll(
-
- /* Enter page */
-
- Animit([this.decomp.enter.content, this.decomp.enter.bottomToolbar, this.decomp.enter.background]).queue({
- transform: 'translate3d(' + swipeRatio * 25 + '%, 0, 0)',
- opacity: 1 + swipeRatio * 10 / 100 // 0.9 -> 1
- }), Animit(this.decomp.enter.toolbarCenter).queue({
- transform: 'translate3d(' + this.delta.title * swipeRatio + 'px, 0, 0)',
- opacity: 1 + swipeRatio // 0 -> 1
- }), Animit(this.decomp.enter.backButtonLabel).queue({
- opacity: 1 + swipeRatio * 10 / 100, // 0.9 -> 1
- transform: 'translate3d(' + this.delta.label * swipeRatio + 'px, 0, 0)'
- }), Animit(this.decomp.enter.other).queue({
- opacity: 1 + swipeRatio // 0 -> 1
- }),
-
- /* Leave page */
-
- Animit([this.decomp.leave.content, this.decomp.leave.bottomToolbar, this.decomp.leave.background, this.swipeShadow]).queue({
- transform: 'translate3d(' + distance + 'px, 0, 0)'
- }), Animit(this.decomp.leave.toolbar).queue({
- opacity: -1 * swipeRatio // 1 -> 0
- }), Animit(this.decomp.leave.toolbarCenter).queue({
- transform: 'translate3d(' + (1 + swipeRatio) * 125 + '%, 0, 0)'
- }), Animit(this.decomp.leave.backButtonLabel).queue({
- opacity: -1 * swipeRatio, // 1 -> 0
- transform: 'translate3d(' + this.delta.title * (1 + swipeRatio) + 'px, 0, 0)'
- }),
-
- /* Other */
-
- Animit(this.swipeShadow).queue({
- opacity: -1 * swipeRatio // 1 -> 0
- }));
- } else {
- Animit.runAll(Animit(leavePage).queue({
- transform: 'translate3d(' + distance + 'px, 0, 0)'
- }), Animit(enterPage).queue({
- transform: 'translate3d(' + swipeRatio * 25 + '%, 0, 0)',
- opacity: 1 + swipeRatio * 10 / 100 // 0.9 -> 1
- }), Animit(this.swipeShadow).queue({
- opacity: -1 * swipeRatio // 1 -> 0
- }));
- }
- }
- }, {
- key: 'restore',
- value: function restore(enterPage, leavePage, callback) {
- var _this2 = this;
-
- if (this.isDragStart) {
- return;
- }
-
- if (this.shouldAnimateToolbar) {
-
- Animit.runAll(
-
- /* Enter page */
-
- Animit([this.decomp.enter.content, this.decomp.enter.bottomToolbar, this.decomp.enter.background]).queue({
- transform: 'translate3d(-25%, 0, 0)',
- opacity: 0.9
- }, this.optRestore), Animit(this.decomp.enter.toolbarCenter).queue({
- transform: 'translate3d(-' + this.delta.title + 'px, 0, 0)',
- transition: 'opacity ' + this.durationRestore + 's linear, transform ' + this.durationRestore + 's ' + this.timingSwipe,
- opacity: 0
- }), Animit(this.decomp.enter.backButtonLabel).queue({
- transform: 'translate3d(-' + this.delta.label + 'px, 0, 0)'
- }, this.optRestore), Animit(this.decomp.enter.other).queue({
- opacity: 0
- }, this.optRestore),
-
- /* Leave page */
-
- Animit([this.decomp.leave.content, this.decomp.leave.bottomToolbar, this.decomp.leave.background, this.swipeShadow]).queue({
- transform: 'translate3d(0, 0, 0)'
- }, this.optRestore), Animit(this.decomp.leave.toolbar).queue({
- opacity: 1
- }, this.optRestore), Animit(this.decomp.leave.toolbarCenter).queue({
- transform: 'translate3d(0, 0, 0)'
- }, this.optRestore), Animit(this.decomp.leave.backButtonLabel).queue({
- opacity: 1,
- transform: 'translate3d(0, 0, 0)',
- transition: 'opacity ' + this.durationRestore + 's linear, transform ' + this.durationRestore + 's ' + this.timingSwipe
- }),
-
- /* Other */
-
- Animit(this.swipeShadow).queue({
- opacity: 0
- }, this.optRestore).queue(function (done) {
- _this2._reset(_this2.target.enter, _this2.target.leave);
- enterPage.style.display = 'none';
- callback && callback();
- done();
- }));
- } else {
- Animit.runAll(Animit(enterPage).queue({
- transform: 'translate3D(-25%, 0, 0)',
- opacity: 0.9
- }, this.optRestore), Animit(leavePage).queue({
- transform: 'translate3D(0, 0, 0)'
- }, this.optRestore).queue(function (done) {
- _this2._reset(enterPage, leavePage);
- enterPage.style.display = 'none';
- callback && callback();
- done();
- }));
- }
- }
- }, {
- key: 'popSwipe',
- value: function popSwipe(enterPage, leavePage, callback) {
- var _this3 = this;
-
- if (this.isDragStart) {
- return;
- }
-
- if (this.shouldAnimateToolbar) {
-
- Animit.runAll(
-
- /* Enter page */
-
- Animit([this.decomp.enter.content, this.decomp.enter.bottomToolbar, this.decomp.enter.background]).queue({
- transform: 'translate3d(0, 0, 0)',
- opacity: 1
- }, this.optSwipe), Animit(this.decomp.enter.toolbarCenter).queue({
- transform: 'translate3d(0, 0, 0)',
- transition: 'opacity ' + this.durationSwipe + 's linear, transform ' + this.durationSwipe + 's ' + this.timingSwipe,
- opacity: 1
- }), Animit(this.decomp.enter.backButtonLabel).queue({
- transform: 'translate3d(0, 0, 0)'
- }, this.optSwipe), Animit(this.decomp.enter.other).queue({
- opacity: 1
- }, this.optSwipe),
-
- /* Leave page */
-
- Animit([this.decomp.leave.content, this.decomp.leave.bottomToolbar, this.decomp.leave.background]).queue({
- transform: 'translate3d(100%, 0, 0)'
- }, this.optSwipe), Animit(this.decomp.leave.toolbar).queue({
- opacity: 0
- }, this.optSwipe), Animit(this.decomp.leave.toolbarCenter).queue({
- transform: 'translate3d(125%, 0, 0)'
- }, this.optSwipe), Animit(this.decomp.leave.backButtonLabel).queue({
- opacity: 0,
- transform: 'translate3d(' + this.delta.title + 'px, 0, 0)',
- transition: 'opacity ' + this.durationSwipe + 's linear, transform ' + this.durationSwipe + 's ' + this.timingSwipe
- }),
-
- /* Other */
-
- Animit(this.swipeShadow).queue({
- opacity: 0,
- transform: 'translate3d(' + this.maxWidth + 'px, 0, 0)'
- }, this.optSwipe).queue(function (done) {
- _this3._reset(_this3.target.enter, _this3.target.leave);
- callback && callback();
- done();
- }));
- } else {
- Animit.runAll(Animit(enterPage).queue({
- transform: 'translate3D(0, 0, 0)',
- opacity: 1.0
- }, this.optSwipe), Animit(leavePage).queue({
- transform: 'translate3D(100%, 0, 0)'
- }, this.optSwipe).queue(function (done) {
- _this3._reset(enterPage, leavePage);
- callback && callback();
- done();
- }));
- }
- }
- }, {
- key: '_saveStyle',
- value: function _saveStyle() {
- var _this4 = this;
-
- this._savedStyle = new WeakMap();
- var save = function save(el) {
- return _this4._savedStyle.set(el, el.getAttribute('style'));
- };
-
- for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
- args[_key] = arguments[_key];
- }
-
- args.forEach(save);
-
- Object.keys(this.decomp).forEach(function (p) {
- Object.keys(_this4.decomp[p]).forEach(function (k) {
- (_this4.decomp[p][k] instanceof Array ? _this4.decomp[p][k] : [_this4.decomp[p][k]]).forEach(save);
- });
- });
- }
- }, {
- key: '_restoreStyle',
- value: function _restoreStyle() {
- var _this5 = this;
-
- var restore = function restore(el) {
- _this5._savedStyle.get(el) === null ? el.removeAttribute('style') : el.setAttribute('style', _this5._savedStyle.get(el));
- _this5._savedStyle.delete(el);
- };
-
- for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
- args[_key2] = arguments[_key2];
- }
-
- args.forEach(restore);
-
- Object.keys(this.decomp).forEach(function (p) {
- Object.keys(_this5.decomp[p]).forEach(function (k) {
- (_this5.decomp[p][k] instanceof Array ? _this5.decomp[p][k] : [_this5.decomp[p][k]]).forEach(restore);
- });
- });
- }
- }, {
- key: '_reset',
- value: function _reset() {
- this.isSwiping = false;
- this._savedStyle && this._restoreStyle.apply(this, arguments);
- this.unblock && this.unblock();
- this.swipeShadow.remove();
- this.backgroundMask.remove();
- this.overflowElement.classList.remove('overflow-visible');
- this.decomp.leave.content.classList.remove('content-swiping');
- this.decomp = this.target = this.overflowElement = this._savedStyle = null;
- this.isDragStart = true;
- }
- }]);
- return IOSSwipeNavigatorAnimator;
- }(NavigatorAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var translate3d = function translate3d() {
- var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
- var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
- var z = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
- return 'translate3d(' + x + ', ' + y + ', ' + z + ')';
- };
-
- /**
- * Slide animator for navigator transition like iOS's screen slide transition.
- */
-
- var IOSSlideNavigatorAnimator = function (_IOSSwipeNavigatorAni) {
- inherits(IOSSlideNavigatorAnimator, _IOSSwipeNavigatorAni);
-
- function IOSSlideNavigatorAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
-
- var _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'cubic-bezier(0.3, .4, 0, .9)' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.4 : _ref$duration,
- rest = objectWithoutProperties(_ref, ['timing', 'delay', 'duration']);
- classCallCheck(this, IOSSlideNavigatorAnimator);
-
- var _this = possibleConstructorReturn(this, (IOSSlideNavigatorAnimator.__proto__ || Object.getPrototypeOf(IOSSlideNavigatorAnimator)).call(this, _extends({ timing: timing, delay: delay, duration: duration }, rest)));
-
- _this.backgroundMask = util$1.createElement('<div style="position: absolute; width: 100%; height: 100%;' + 'background-color: black; z-index: 2"></div>');
- return _this;
- }
-
- createClass(IOSSlideNavigatorAnimator, [{
- key: '_decompose',
- value: function _decompose(page) {
- var toolbar = page._getToolbarElement();
- var left = toolbar._getToolbarLeftItemsElement();
- var right = toolbar._getToolbarRightItemsElement();
-
- var excludeBackButton = function excludeBackButton(elements) {
- var result = [];
-
- for (var i = 0; i < elements.length; i++) {
- if (elements[i].nodeName.toLowerCase() !== 'ons-back-button') {
- result.push(elements[i]);
- }
- }
-
- return result;
- };
-
- var other = [].concat(left.children.length === 0 ? left : excludeBackButton(left.children)).concat(right.children.length === 0 ? right : excludeBackButton(right.children));
-
- return {
- toolbarCenter: toolbar._getToolbarCenterItemsElement(),
- backButtonIcon: toolbar._getToolbarBackButtonIconElement(),
- backButtonLabel: toolbar._getToolbarBackButtonLabelElement(),
- other: other,
- content: page._getContentElement(),
- background: page._getBackgroundElement(),
- toolbar: toolbar,
- bottomToolbar: page._getBottomToolbarElement()
- };
- }
- }, {
- key: '_shouldAnimateToolbar',
- value: function _shouldAnimateToolbar(enterPage, leavePage) {
- var toolbars = enterPage._canAnimateToolbar() && leavePage._canAnimateToolbar();
-
- var enterToolbar = enterPage._getToolbarElement();
- var leaveToolbar = leavePage._getToolbarElement();
-
- var isStatic = enterToolbar.hasAttribute('static') || leaveToolbar.hasAttribute('static');
- var isMaterial = util$1.hasModifier(enterToolbar, 'material') || util$1.hasModifier(leaveToolbar, 'material');
- var isTransparent = util$1.hasModifier(enterToolbar, 'transparent') || util$1.hasModifier(leaveToolbar, 'transparent');
-
- return toolbars && !isStatic && !isMaterial && !isTransparent;
- }
- }, {
- key: '_calculateDelta',
- value: function _calculateDelta(element, decomposition) {
- var title = void 0,
- label = void 0;
-
- var pageRect = element.getBoundingClientRect();
- if (decomposition.backButtonLabel.classList.contains('back-button__label')) {
- var labelRect = decomposition.backButtonLabel.getBoundingClientRect();
- title = Math.round(pageRect.width / 2 - labelRect.width / 2 - labelRect.left);
- } else {
- title = Math.round(pageRect.width / 2 * 0.6);
- }
-
- if (decomposition.backButtonIcon.classList.contains('back-button__icon')) {
- label = decomposition.backButtonIcon.getBoundingClientRect().right - 2;
- }
-
- return { title: title, label: label };
- }
-
- /**
- * @param {Object} enterPage
- * @param {Object} leavePage
- * @param {Function} callback
- */
-
- }, {
- key: 'push',
- value: function push(enterPage, leavePage, callback) {
- var _this2 = this;
-
- this.backgroundMask.remove();
- leavePage.parentNode.insertBefore(this.backgroundMask, leavePage);
-
- var unblock = get(IOSSlideNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(IOSSlideNavigatorAnimator.prototype), 'block', this).call(this, enterPage);
-
- contentReady(enterPage, function () {
- var enterPageTarget = util$1.findToolbarPage(enterPage) || enterPage;
- var leavePageTarget = util$1.findToolbarPage(leavePage) || leavePage;
- var enterPageDecomposition = _this2._decompose(enterPageTarget);
- var leavePageDecomposition = _this2._decompose(leavePageTarget);
-
- var delta = _this2._calculateDelta(leavePage, enterPageDecomposition);
-
- var shouldAnimateToolbar = _this2._shouldAnimateToolbar(enterPageTarget, leavePageTarget);
-
- if (shouldAnimateToolbar) {
-
- Animit.runAll(Animit([enterPageDecomposition.content, enterPageDecomposition.bottomToolbar, enterPageDecomposition.background], _this2.def).default({ transform: translate3d('100%') }, { transform: translate3d() }), Animit(enterPageDecomposition.toolbar, _this2.def).default({ opacity: 0 }, { opacity: 1 }), Animit(enterPageDecomposition.toolbarCenter, _this2.def).default({ transform: translate3d('125%'), opacity: 1 }, { transform: translate3d(), opacity: 1 }), Animit(enterPageDecomposition.backButtonLabel, _this2.def).default({ transform: translate3d(delta.title + 'px'), opacity: 0 }, {
- transform: translate3d(),
- opacity: 1,
- transition: 'opacity ' + _this2.duration + 's linear, transform ' + _this2.duration + 's ' + _this2.timing
- }), Animit(enterPageDecomposition.other, _this2.def).default({ opacity: 0 }, { css: { opacity: 1 }, timing: 'linear' }), Animit([leavePageDecomposition.content, leavePageDecomposition.bottomToolbar, leavePageDecomposition.background], _this2.def).default({ transform: translate3d(), opacity: 1 }, { transform: translate3d('-25%'), opacity: 0.9 }).queue(function (done) {
- _this2.backgroundMask.remove();
- unblock();
- callback();
- done();
- }), Animit(leavePageDecomposition.toolbarCenter, _this2.def).default({ transform: translate3d(), opacity: 1 }, {
- transform: translate3d('-' + delta.title + 'px'),
- opacity: 0,
- transition: 'opacity ' + _this2.duration + 's linear, transform ' + _this2.duration + 's ' + _this2.timing
- }), Animit(leavePageDecomposition.backButtonLabel, _this2.def).default({ transform: translate3d(), opacity: 1 }, { transform: translate3d('-' + delta.label + 'px'), opacity: 0 }), Animit(leavePageDecomposition.other, _this2.def).default({ opacity: 1 }, { css: { opacity: 0 }, timing: 'linear' }));
- } else {
-
- Animit.runAll(Animit(enterPage, _this2.def).default({ transform: translate3d('100%') }, { transform: translate3d() }), Animit(leavePage, _this2.def).default({ transform: translate3d(), opacity: 1 }, { transform: translate3d('-25%'), opacity: .9 }).queue(function (done) {
- _this2.backgroundMask.remove();
- unblock();
- callback();
- done();
- }));
- }
- });
- }
-
- /**
- * @param {Object} enterPage
- * @param {Object} leavePage
- * @param {Function} callback
- */
-
- }, {
- key: 'pop',
- value: function pop(enterPage, leavePage, callback) {
- var _this3 = this;
-
- if (this.isSwiping) {
- return this.popSwipe(enterPage, leavePage, callback);
- }
-
- this.backgroundMask.remove();
- enterPage.parentNode.insertBefore(this.backgroundMask, enterPage);
-
- var unblock = get(IOSSlideNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(IOSSlideNavigatorAnimator.prototype), 'block', this).call(this, enterPage);
-
- var enterPageTarget = util$1.findToolbarPage(enterPage) || enterPage;
- var leavePageTarget = util$1.findToolbarPage(leavePage) || leavePage;
- var enterPageDecomposition = this._decompose(enterPageTarget);
- var leavePageDecomposition = this._decompose(leavePageTarget);
-
- var delta = this._calculateDelta(leavePage, leavePageDecomposition);
-
- var shouldAnimateToolbar = this._shouldAnimateToolbar(enterPageTarget, leavePageTarget);
-
- if (shouldAnimateToolbar) {
- Animit.runAll(Animit([enterPageDecomposition.content, enterPageDecomposition.bottomToolbar, enterPageDecomposition.background], this.def).default({ transform: translate3d('-25%'), opacity: .9 }, { transform: translate3d(), opacity: 1 }), Animit(enterPageDecomposition.toolbarCenter, this.def).default({ transform: translate3d('-' + delta.title + 'px'), opacity: 0 }, {
- transform: translate3d(),
- opacity: 1,
- transition: 'opacity ' + this.duration + 's linear, transform ' + this.duration + 's ' + this.timing
- }), Animit(enterPageDecomposition.backButtonLabel, this.def).default({ transform: translate3d('-' + delta.label + 'px') }, { transform: translate3d() }), Animit(enterPageDecomposition.other, this.def).default({ opacity: 0 }, { css: { opacity: 1 }, timing: 'linear' }), Animit([leavePageDecomposition.content, leavePageDecomposition.bottomToolbar, leavePageDecomposition.background], this.def).default({ transform: translate3d() }, { transform: translate3d('100%') }).wait(0).queue(function (done) {
- _this3.backgroundMask.remove();
- unblock();
- callback();
- done();
- }), Animit(leavePageDecomposition.toolbar, this.def).default({ opacity: 1 }, { opacity: 0 }), Animit(leavePageDecomposition.toolbarCenter, this.def).default({ transform: translate3d() }, { transform: translate3d('125%') }), Animit(leavePageDecomposition.backButtonLabel, this.def).default({ transform: translate3d(), opacity: 1 }, {
- transform: translate3d(delta.title + 'px'),
- opacity: 0,
- transition: 'opacity ' + this.duration + 's linear, transform ' + this.duration + 's ' + this.timing
- }));
- } else {
- Animit.runAll(Animit(enterPage, this.def).default({ transform: translate3d('-25%'), opacity: .9 }, { transform: translate3d(), opacity: 1 }), Animit(leavePage, this.def).default({ transform: translate3d() }, { transform: translate3d('100%') }).queue(function (done) {
- _this3.backgroundMask.remove();
- unblock();
- callback();
- done();
- }));
- }
- }
- }]);
- return IOSSlideNavigatorAnimator;
- }(IOSSwipeNavigatorAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * Lift screen transition.
- */
-
- var IOSLiftNavigatorAnimator = function (_NavigatorAnimator) {
- inherits(IOSLiftNavigatorAnimator, _NavigatorAnimator);
-
- function IOSLiftNavigatorAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'cubic-bezier(.1, .7, .1, 1)' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.4 : _ref$duration;
-
- classCallCheck(this, IOSLiftNavigatorAnimator);
-
- var _this = possibleConstructorReturn(this, (IOSLiftNavigatorAnimator.__proto__ || Object.getPrototypeOf(IOSLiftNavigatorAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
-
- _this.backgroundMask = util$1.createElement('<div style="position: absolute; width: 100%; height: 100%;' + 'background: linear-gradient(black, white);"></div>');
- return _this;
- }
-
- /**
- * @param {Object} enterPage
- * @param {Object} leavePage
- * @param {Function} callback
- */
-
-
- createClass(IOSLiftNavigatorAnimator, [{
- key: 'push',
- value: function push(enterPage, leavePage, callback) {
- var _this2 = this;
-
- this.backgroundMask.remove();
- leavePage.parentNode.insertBefore(this.backgroundMask, leavePage);
-
- var unblock = get(IOSLiftNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(IOSLiftNavigatorAnimator.prototype), 'block', this).call(this, enterPage);
-
- Animit.runAll(Animit(enterPage, this.def).default({ transform: 'translate3D(0, 100%, 0)' }, { transform: 'translate3D(0, 0, 0)' }), Animit(leavePage, this.def).default({ transform: 'translate3D(0, 0, 0)', opacity: 1 }, { transform: 'translate3D(0, -10%, 0)', opacity: .9 }).queue(function (done) {
- _this2.backgroundMask.remove();
- unblock();
- callback();
- done();
- }));
- }
-
- /**
- * @param {Object} enterPage
- * @param {Object} leavePage
- * @param {Function} callback
- */
-
- }, {
- key: 'pop',
- value: function pop(enterPage, leavePage, callback) {
- var _this3 = this;
-
- this.backgroundMask.remove();
- enterPage.parentNode.insertBefore(this.backgroundMask, enterPage);
-
- var unblock = get(IOSLiftNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(IOSLiftNavigatorAnimator.prototype), 'block', this).call(this, enterPage);
-
- Animit.runAll(Animit(enterPage, this.def).default({ transform: 'translate3D(0, -43px, 0)', opacity: .9 }, { transform: 'translate3D(0, 0, 0)', opacity: 1 }).queue(function (done) {
- _this3.backgroundMask.remove();
- unblock();
- callback();
- done();
- }), Animit(leavePage, this.def).default({ transform: 'translate3D(0, 0, 0)' }, { transform: 'translate3D(0, 100%, 0)' }));
- }
- }]);
- return IOSLiftNavigatorAnimator;
- }(NavigatorAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var transform = 'translate3d(0, 0, 0)';
-
- /**
- * Fade-in screen transition.
- */
-
- var IOSFadeNavigatorAnimator = function (_NavigatorAnimator) {
- inherits(IOSFadeNavigatorAnimator, _NavigatorAnimator);
-
- function IOSFadeNavigatorAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'linear' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.4 : _ref$duration;
-
- classCallCheck(this, IOSFadeNavigatorAnimator);
- return possibleConstructorReturn(this, (IOSFadeNavigatorAnimator.__proto__ || Object.getPrototypeOf(IOSFadeNavigatorAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
- }
-
- /**
- * @param {Object} enterPage
- * @param {Object} leavePage
- * @param {Function} callback
- */
-
-
- createClass(IOSFadeNavigatorAnimator, [{
- key: 'push',
- value: function push(enterPage, leavePage, callback) {
- var unblock = get(IOSFadeNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(IOSFadeNavigatorAnimator.prototype), 'block', this).call(this, enterPage);
-
- Animit.runAll(Animit(enterPage, this.def).default({ transform: transform, opacity: 0 }, { transform: transform, opacity: 1 }).queue(function (done) {
- unblock();
- callback();
- done();
- }));
- }
-
- /**
- * @param {Object} enterPage
- * @param {Object} leavePage
- * @param {Function} done
- */
-
- }, {
- key: 'pop',
- value: function pop(enterPage, leavePage, callback) {
- var unblock = get(IOSFadeNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(IOSFadeNavigatorAnimator.prototype), 'block', this).call(this, enterPage);
-
- Animit.runAll(Animit(leavePage, this.def).default({ transform: transform, opacity: 1 }, { transform: transform, opacity: 0 }).queue(function (done) {
- unblock();
- callback();
- done();
- }));
- }
- }]);
- return IOSFadeNavigatorAnimator;
- }(NavigatorAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * Slide animator for navigator transition.
- */
-
- var MDSlideNavigatorAnimator = function (_NavigatorAnimator) {
- inherits(MDSlideNavigatorAnimator, _NavigatorAnimator);
-
- function MDSlideNavigatorAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'cubic-bezier(.1, .7, .4, 1)' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.3 : _ref$duration;
-
- classCallCheck(this, MDSlideNavigatorAnimator);
-
- var _this = possibleConstructorReturn(this, (MDSlideNavigatorAnimator.__proto__ || Object.getPrototypeOf(MDSlideNavigatorAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
-
- _this.blackMaskOpacity = 0.4;
- _this.backgroundMask = util$1.createElement('<div style="position: absolute; width: 100%; height: 100%; z-index: 2;' + 'background-color: black; opacity: 0;"></div>');
- return _this;
- }
-
- /**
- * @param {Object} enterPage
- * @param {Object} leavePage
- * @param {Function} callback
- */
-
-
- createClass(MDSlideNavigatorAnimator, [{
- key: 'push',
- value: function push(enterPage, leavePage, callback) {
- var _this2 = this;
-
- this.backgroundMask.remove();
- leavePage.parentElement.insertBefore(this.backgroundMask, leavePage.nextSibling);
-
- var unblock = get(MDSlideNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(MDSlideNavigatorAnimator.prototype), 'block', this).call(this, enterPage);
-
- Animit.runAll(Animit(this.backgroundMask, this.def).default({ transform: 'translate3d(0, 0, 0)', opacity: 0 }, { opacity: this.blackMaskOpacity }).queue(function (done) {
- _this2.backgroundMask.remove();
- done();
- }), Animit(enterPage, this.def).default({ transform: 'translate3d(100%, 0, 0)' }, { transform: 'translate3d(0, 0, 0)' }), Animit(leavePage, this.def).default({ transform: 'translate3d(0, 0, 0)' }, { transform: 'translate3d(-45%, 0, 0)' }).queue(function (done) {
- unblock();
- callback();
- done();
- }));
- }
-
- /**
- * @param {Object} enterPage
- * @param {Object} leavePage
- * @param {Function} callback
- */
-
- }, {
- key: 'pop',
- value: function pop(enterPage, leavePage, callback) {
- var _this3 = this;
-
- this.backgroundMask.remove();
- enterPage.parentNode.insertBefore(this.backgroundMask, enterPage.nextSibling);
-
- var unblock = get(MDSlideNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(MDSlideNavigatorAnimator.prototype), 'block', this).call(this, enterPage);
-
- Animit.runAll(Animit(this.backgroundMask, this.def).default({ transform: 'translate3d(0, 0, 0)', opacity: this.blackMaskOpacity }, { opacity: 0 }).queue(function (done) {
- _this3.backgroundMask.remove();
- done();
- }), Animit(enterPage, this.def).default({ transform: 'translate3d(-45%, 0, 0)', opacity: .9 }, { transform: 'translate3d(0, 0, 0)', opacity: 1 }), Animit(leavePage, this.def).default({ transform: 'translate3d(0, 0, 0)' }, { transform: 'translate3d(100%, 0, 0)' }).queue(function (done) {
- unblock();
- callback();
- done();
- }));
- }
- }]);
- return MDSlideNavigatorAnimator;
- }(NavigatorAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * Lift screen transition.
- */
-
- var MDLiftNavigatorAnimator = function (_NavigatorAnimator) {
- inherits(MDLiftNavigatorAnimator, _NavigatorAnimator);
-
- function MDLiftNavigatorAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'cubic-bezier(.1, .7, .1, 1)' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0.05 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.4 : _ref$duration;
-
- classCallCheck(this, MDLiftNavigatorAnimator);
-
- var _this = possibleConstructorReturn(this, (MDLiftNavigatorAnimator.__proto__ || Object.getPrototypeOf(MDLiftNavigatorAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
-
- _this.backgroundMask = util$1.createElement('<div style="position: absolute; width: 100%; height: 100%;' + 'background-color: black;"></div>');
- return _this;
- }
-
- /**
- * @param {Object} enterPage
- * @param {Object} leavePage
- * @param {Function} callback
- */
-
-
- createClass(MDLiftNavigatorAnimator, [{
- key: 'push',
- value: function push(enterPage, leavePage, callback) {
- var _this2 = this;
-
- this.backgroundMask.remove();
- leavePage.parentNode.insertBefore(this.backgroundMask, leavePage);
-
- var unblock = get(MDLiftNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(MDLiftNavigatorAnimator.prototype), 'block', this).call(this, enterPage);
-
- var maskClear = Animit(this.backgroundMask).wait(this.delay + this.duration).queue(function (done) {
- _this2.backgroundMask.remove();
- done();
- });
-
- Animit.runAll(maskClear, Animit(enterPage, this.def).default({ transform: 'translate3d(0, 100%, 0)' }, { transform: 'translate3d(0, 0, 0)' }), Animit(leavePage, this.def).default({ opacity: 1 }, { opacity: .4 }).queue(function (done) {
- unblock();
- callback();
- done();
- }));
- }
-
- /**
- * @param {Object} enterPage
- * @param {Object} leavePage
- * @param {Function} callback
- */
-
- }, {
- key: 'pop',
- value: function pop(enterPage, leavePage, callback) {
- var _this3 = this;
-
- this.backgroundMask.remove();
- enterPage.parentNode.insertBefore(this.backgroundMask, enterPage);
-
- var unblock = get(MDLiftNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(MDLiftNavigatorAnimator.prototype), 'block', this).call(this, enterPage);
-
- Animit.runAll(Animit(this.backgroundMask).wait(this.delay + this.duration).queue(function (done) {
- _this3.backgroundMask.remove();
- done();
- }), Animit(enterPage, this.def).default({ opacity: .4 }, { opacity: 1 }).queue(function (done) {
- unblock();
- callback();
- done();
- }), Animit(leavePage, this.def).default({ transform: 'translate3d(0, 0, 0)' }, { transform: 'translate3d(0, 100%, 0)' }));
- }
- }]);
- return MDLiftNavigatorAnimator;
- }(NavigatorAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * Fade-in + Lift screen transition.
- */
-
- var MDFadeNavigatorAnimator = function (_NavigatorAnimator) {
- inherits(MDFadeNavigatorAnimator, _NavigatorAnimator);
-
- function MDFadeNavigatorAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'cubic-bezier(0.4, 0, 0.2, 1)' : _ref$timing,
- _ref$timingPop = _ref.timingPop,
- timingPop = _ref$timingPop === undefined ? 'cubic-bezier(0.4, 0, 1, 1)' : _ref$timingPop,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.2 : _ref$duration;
-
- classCallCheck(this, MDFadeNavigatorAnimator);
-
- var _this = possibleConstructorReturn(this, (MDFadeNavigatorAnimator.__proto__ || Object.getPrototypeOf(MDFadeNavigatorAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
-
- _this.timingPop = timingPop;
- return _this;
- }
-
- /**
- * @param {Object} enterPage
- * @param {Object} leavePage
- * @param {Function} callback
- */
-
-
- createClass(MDFadeNavigatorAnimator, [{
- key: 'push',
- value: function push(enterPage, leavePage, callback) {
- var unblock = get(MDFadeNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(MDFadeNavigatorAnimator.prototype), 'block', this).call(this, enterPage);
-
- Animit.runAll(Animit(enterPage, this.def).default({ transform: 'translate3D(0, 42px, 0)', opacity: 0 }, { transform: 'translate3D(0, 0, 0)', opacity: 1 }).queue(function (done) {
- unblock();
- callback();
- done();
- }));
- }
-
- /**
- * @param {Object} enterPage
- * @param {Object} leavePage
- * @param {Function} done
- */
-
- }, {
- key: 'pop',
- value: function pop(enterPage, leavePage, callback) {
- var unblock = get(MDFadeNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(MDFadeNavigatorAnimator.prototype), 'block', this).call(this, enterPage);
-
- Animit.runAll(Animit(leavePage, this.def).default({ transform: 'translate3D(0, 0, 0)', opacity: 1 }, { css: { transform: 'translate3D(0, 38px, 0)', opacity: 0 }, timing: this.timingPop }).queue(function (done) {
- unblock();
- callback();
- done();
- }));
- }
- }]);
- return MDFadeNavigatorAnimator;
- }(NavigatorAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var NoneNavigatorAnimator = function (_NavigatorAnimator) {
- inherits(NoneNavigatorAnimator, _NavigatorAnimator);
-
- function NoneNavigatorAnimator(options) {
- classCallCheck(this, NoneNavigatorAnimator);
- return possibleConstructorReturn(this, (NoneNavigatorAnimator.__proto__ || Object.getPrototypeOf(NoneNavigatorAnimator)).call(this, options));
- }
-
- createClass(NoneNavigatorAnimator, [{
- key: 'push',
- value: function push(enterPage, leavePage, callback) {
- callback();
- }
- }, {
- key: 'pop',
- value: function pop(enterPage, leavePage, callback) {
- callback();
- }
- }]);
- return NoneNavigatorAnimator;
- }(NavigatorAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var _animatorDict$5 = {
- 'default': function _default() {
- return platform.isAndroid() ? MDFadeNavigatorAnimator : IOSSlideNavigatorAnimator;
- },
- 'slide': function slide() {
- return platform.isAndroid() ? MDSlideNavigatorAnimator : IOSSlideNavigatorAnimator;
- },
- 'lift': function lift() {
- return platform.isAndroid() ? MDLiftNavigatorAnimator : IOSLiftNavigatorAnimator;
- },
- 'fade': function fade() {
- return platform.isAndroid() ? MDFadeNavigatorAnimator : IOSFadeNavigatorAnimator;
- },
- 'slide-ios': IOSSlideNavigatorAnimator,
- 'slide-md': MDSlideNavigatorAnimator,
- 'lift-ios': IOSLiftNavigatorAnimator,
- 'lift-md': MDLiftNavigatorAnimator,
- 'fade-ios': IOSFadeNavigatorAnimator,
- 'fade-md': MDFadeNavigatorAnimator,
- 'none': NoneNavigatorAnimator
- };
-
- var rewritables = {
- /**
- * @param {Element} navigatorSideElement
- * @param {Function} callback
- */
- ready: function ready(navigatorElement, callback) {
- callback();
- }
- };
-
- var verifyPageElement = function verifyPageElement(el) {
- return el.nodeName !== 'ONS-PAGE' && util$1.throw('Only page elements can be children of navigator');
- };
-
- /**
- * @element ons-navigator
- * @category navigation
- * @description
- * [en]
- * A component that provides page stack management and navigation. Stack navigation is the most common navigation pattern for mobile apps.
- *
- * When a page is pushed on top of the stack it is displayed with a transition animation. When the user returns to the previous page the top page will be popped from the top of the stack and hidden with an opposite transition animation.
- * [/en]
- * [ja][/ja]
- * @codepen yrhtv
- * @tutorial vanilla/Reference/navigator
- * @guide lifecycle.html#events
- * [en]Overview of page events[/en]
- * [ja]Overview of page events[/ja]
- * @seealso ons-toolbar
- * [en]The `<ons-toolbar>` component is used to display a toolbar on the top of a page.[/en]
- * [ja][/ja]
- * @seealso ons-back-button
- * [en]The `<ons-back-button>` component lets the user return to the previous page.[/en]
- * [ja][/ja]
- * @example
- * <ons-navigator id="navigator">
- * <ons-page>
- * <ons-toolbar>
- * <div class="center">
- * Title
- * </div>
- * </ons-toolbar>
- * <p>
- * <ons-button
- * onclick="document.getElementById('navigator').pushPage('page.html')">
- * Push page
- * </ons-button>
- * </p>
- * </ons-page>
- * </ons-navigator>
- *
- * <template id="page.html">
- * <ons-page>
- * <ons-toolbar>
- * <div class="left">
- * <ons-back-button>Back</ons-back-button>
- * </div>
- * <div class="center">
- * Another page
- * </div>
- * </ons-toolbar>
- * </ons-page>
- * </template>
- */
-
- var NavigatorElement = function (_BaseElement) {
- inherits(NavigatorElement, _BaseElement);
- createClass(NavigatorElement, [{
- key: 'animatorFactory',
-
-
- /**
- * @attribute page
- * @initonly
- * @type {String}
- * @description
- * [en]First page to show when navigator is initialized.[/en]
- * [ja]ナビゲーターが初期化された時に表示するページを指定します。[/ja]
- */
-
- /**
- * @attribute swipeable
- * @type {Boolean}
- * @description
- * [en]Enable iOS "swipe to pop" feature.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute swipe-target-width
- * @type {String}
- * @default 20px
- * @description
- * [en]The width of swipeable area calculated from the edge (in pixels). Use this to enable swipe only when the finger touch on the screen edge.[/en]
- * [ja]スワイプの判定領域をピクセル単位で指定します。画面の端から指定した距離に達するとページが表示されます。[/ja]
- */
-
- /**
- * @attribute swipe-threshold
- * @type {Number}
- * @default 0.2
- * @description
- * [en]Specify how much the page needs to be swiped before popping. A value between `0` and `1`.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute animation
- * @type {String}
- * @default default
- * @description
- * [en]
- * Animation name. Available animations are `"slide"`, `"lift"`, `"fade"` and `"none"`.
- *
- * These are platform based animations. For fixed animations, add `"-ios"` or `"-md"` suffix to the animation name. E.g. `"lift-ios"`, `"lift-md"`. Defaults values are `"slide-ios"` and `"fade-md"` depending on the platform.
- * [/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute animation-options
- * @type {Expression}
- * @description
- * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`[/en]
- * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`[/ja]
- */
-
- /**
- * @event prepush
- * @description
- * [en]Fired just before a page is pushed.[/en]
- * [ja]pageがpushされる直前に発火されます。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.navigator
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- * @param {Object} event.currentPage
- * [en]Current page object.[/en]
- * [ja]現在のpageオブジェクト。[/ja]
- * @param {Function} event.cancel
- * [en]Call this function to cancel the push.[/en]
- * [ja]この関数を呼び出すと、push処理がキャンセルされます。[/ja]
- */
-
- /**
- * @event prepop
- * @description
- * [en]Fired just before a page is popped.[/en]
- * [ja]pageがpopされる直前に発火されます。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.navigator
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- * @param {Object} event.currentPage
- * [en]Current page object.[/en]
- * [ja]現在のpageオブジェクト。[/ja]
- * @param {Function} event.cancel
- * [en]Call this function to cancel the pop.[/en]
- * [ja]この関数を呼び出すと、pageのpopがキャンセルされます。[/ja]
- */
-
- /**
- * @event postpush
- * @description
- * [en]Fired just after a page is pushed.[/en]
- * [ja]pageがpushされてアニメーションが終了してから発火されます。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.navigator
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- * @param {Object} event.enterPage
- * [en]Object of the next page.[/en]
- * [ja]pushされたpageオブジェクト。[/ja]
- * @param {Object} event.leavePage
- * [en]Object of the previous page.[/en]
- * [ja]以前のpageオブジェクト。[/ja]
- */
-
- /**
- * @event postpop
- * @description
- * [en]Fired just after a page is popped.[/en]
- * [ja]pageがpopされてアニメーションが終わった後に発火されます。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.navigator
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- * @param {Object} event.enterPage
- * [en]Object of the next page.[/en]
- * [ja]popされて表示されるページのオブジェクト。[/ja]
- * @param {Object} event.leavePage
- * [en]Object of the previous page.[/en]
- * [ja]popされて消えるページのオブジェクト。[/ja]
- */
-
- get: function get$$1() {
- return this._animatorFactory;
- }
- }]);
-
- function NavigatorElement() {
- classCallCheck(this, NavigatorElement);
-
- var _this = possibleConstructorReturn(this, (NavigatorElement.__proto__ || Object.getPrototypeOf(NavigatorElement)).call(this));
-
- _this._isRunning = false;
- _this._initialized = false;
- _this._pageLoader = defaultPageLoader;
- _this._pageMap = new WeakMap();
-
- _this._updateAnimatorFactory();
- return _this;
- }
-
- /**
- * @property pageLoader
- * @type {PageLoader}
- * @description
- * [en]PageLoader instance. It can be overriden to change the way pages are loaded by this element. Useful for lib developers.[/en]
- * [ja]PageLoaderインスタンスを格納しています。[/ja]
- */
-
-
- createClass(NavigatorElement, [{
- key: '_getPageTarget',
- value: function _getPageTarget() {
- return this._page || this.getAttribute('page');
- }
-
- /**
- * @property page
- * @type {*}
- * @description
- * [en]Specify the page to be loaded during initialization. This value takes precedence over the `page` attribute. Useful for lib developers.[/en]
- * [ja]初期化時に読み込むページを指定します。`page`属性で指定した値よりも`page`プロパティに指定した値を優先します。[/ja]
- */
-
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- var _this2 = this;
-
- this.onDeviceBackButton = this._onDeviceBackButton.bind(this);
-
- if (!platform.isAndroid() || this.getAttribute('swipeable') === 'force') {
- var swipeAnimator = void 0;
-
- this._swipe = new SwipeReveal({
- element: this,
- getThreshold: function getThreshold() {
- return Math.max(0.2, parseFloat(_this2.getAttribute('swipe-threshold')) || 0);
- },
-
- swipeMax: function swipeMax() {
- _this2._onSwipe && _this2._onSwipe(1, { duration: swipeAnimator.durationSwipe, timing: swipeAnimator.timingSwipe });
- _this2[_this2.swipeMax ? 'swipeMax' : 'popPage']({ animator: swipeAnimator });
- swipeAnimator = null;
- },
- swipeMid: function swipeMid(distance, width) {
- _this2._onSwipe && _this2._onSwipe(distance / width);
- swipeAnimator.translate(distance, width, _this2.topPage.previousElementSibling, _this2.topPage);
- },
- swipeMin: function swipeMin() {
- _this2._onSwipe && _this2._onSwipe(0, { duration: swipeAnimator.durationRestore, timing: swipeAnimator.timingSwipe });
- swipeAnimator.restore(_this2.topPage.previousElementSibling, _this2.topPage);
- swipeAnimator = null;
- },
-
- ignoreSwipe: function ignoreSwipe(event, distance) {
- // Basic conditions
- if (!_this2._isRunning && _this2.children.length > 1) {
-
- // Area or directional issues
- var area = parseInt(_this2.getAttribute('swipe-target-width') || 25, 10);
- if (event.gesture.direction === 'right' && area > distance) {
-
- // Swipes on ons-back-button and its children
- var isBB = function isBB(el) {
- return (/ons-back-button/i.test(el.tagName)
- );
- };
- if (!isBB(event.target) && !util$1.findParent(event.target, isBB, function (p) {
- return (/ons-page/i.test(p.tagName)
- );
- })) {
-
- // Animator is swipeable
- var animation = (_this2.topPage.pushedOptions || {}).animation || _this2.animatorFactory._animation;
- var Animator = _animatorDict$5[animation] instanceof Function ? _animatorDict$5[animation].call() : _animatorDict$5[animation];
-
- if (typeof Animator !== 'undefined' && Animator.swipeable) {
- swipeAnimator = new Animator(); // Prepare for the swipe
- return false;
- }
- }
- }
- }
-
- return true; // Ignore swipe
- }
- });
-
- this.attributeChangedCallback('swipeable');
- }
-
- if (this._initialized) {
- return;
- }
-
- this._initialized = true;
-
- var deferred = util$1.defer();
- this.loaded = deferred.promise;
-
- rewritables.ready(this, function () {
- var show = !util$1.hasAnyComponentAsParent(_this2);
- var options = { animation: 'none', show: show };
-
- if (_this2.pages.length === 0 && _this2._getPageTarget()) {
- _this2.pushPage(_this2._getPageTarget(), options).then(function () {
- return deferred.resolve();
- });
- } else if (_this2.pages.length > 0) {
- for (var i = 0; i < _this2.pages.length; i++) {
- verifyPageElement(_this2.pages[i]);
- }
-
- if (_this2.topPage) {
- contentReady(_this2.topPage, function () {
- return setTimeout(function () {
- deferred.resolve();
- show && _this2.topPage._show();
- _this2._updateLastPageBackButton();
- }, 0);
- });
- }
- } else {
- contentReady(_this2, function () {
- if (_this2.pages.length === 0 && _this2._getPageTarget()) {
- _this2.pushPage(_this2._getPageTarget(), options).then(function () {
- return deferred.resolve();
- });
- } else {
- deferred.resolve();
- }
- });
- }
- });
- }
- }, {
- key: '_updateAnimatorFactory',
- value: function _updateAnimatorFactory() {
- this._animatorFactory = new AnimatorFactory({
- animators: _animatorDict$5,
- baseClass: NavigatorAnimator,
- baseClassName: 'NavigatorAnimator',
- defaultAnimation: this.getAttribute('animation')
- });
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- this._backButtonHandler.destroy();
- this._backButtonHandler = null;
-
- this._swipe && this._swipe.dispose();
- this._swipe = null;
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'animation':
- this._updateAnimatorFactory();
- break;
- case 'swipeable':
- this._swipe && this._swipe.update();
- break;
- }
- }
-
- /**
- * @method popPage
- * @signature popPage([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {String} [options.animation]
- * [en]
- * Animation name. Available animations are `"slide"`, `"lift"`, `"fade"` and `"none"`.
- *
- * These are platform based animations. For fixed animations, add `"-ios"` or `"-md"` suffix to the animation name. E.g. `"lift-ios"`, `"lift-md"`. Defaults values are `"slide-ios"` and `"fade-md"`.
- * [/en]
- * [ja][/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
- * @param {Function} [options.callback]
- * [en]Function that is called when the transition has ended.[/en]
- * [ja]このメソッドによる画面遷移が終了した際に呼び出される関数オブジェクトを指定します。[/ja]
- * @param {Object} [options.data]
- * [en]Custom data that will be stored in the new page element.[/en]
- * [ja][/ja]
- * @param {Number} [options.times]
- * [en]Number of pages to be popped. Only one animation will be shown.[/en]
- * [ja][/ja]
- * @return {Promise}
- * [en]Promise which resolves to the revealed page.[/en]
- * [ja]明らかにしたページを解決するPromiseを返します。[/ja]
- * @description
- * [en]Pops the current page from the page stack. The previous page will be displayed.[/en]
- * [ja]現在表示中のページをページスタックから取り除きます。一つ前のページに戻ります。[/ja]
- */
-
- }, {
- key: 'popPage',
- value: function popPage() {
- var _this3 = this;
-
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
-
- var _preparePageAndOption = this._preparePageAndOptions(null, options);
-
- options = _preparePageAndOption.options;
-
-
- if (util$1.isInteger(options.times) && options.times > 1) {
- this._removePages(options.times);
- }
-
- var popUpdate = function popUpdate() {
- return new Promise(function (resolve) {
- _this3._pageLoader.unload(_this3.pages[_this3.pages.length - 1]);
- resolve();
- });
- };
-
- return this._popPage(options, popUpdate);
- }
- }, {
- key: '_popPage',
- value: function _popPage(options) {
- var _this4 = this;
-
- var update = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {
- return Promise.resolve();
- };
-
- if (this._isRunning) {
- return Promise.reject('popPage is already running.');
- }
-
- if (this.pages.length <= 1) {
- return Promise.reject('ons-navigator\'s page stack is empty.');
- }
-
- if (this._emitPrePopEvent()) {
- return Promise.reject('Canceled in prepop event.');
- }
-
- var length = this.pages.length;
-
- this._isRunning = true;
-
- this.pages[length - 2].updateBackButton(length - 2 > 0);
-
- return new Promise(function (resolve) {
- var leavePage = _this4.pages[length - 1];
- var enterPage = _this4.pages[length - 2];
-
- options = util$1.extend({}, _this4.options || {}, leavePage.pushedOptions || {}, options);
-
- if (options.data) {
- enterPage.data = util$1.extend({}, enterPage.data || {}, options.data || {});
- }
-
- var done = function done() {
- update().then(function () {
- _this4._isRunning = false;
-
- enterPage._show();
- util$1.triggerElementEvent(_this4, 'postpop', { leavePage: leavePage, enterPage: enterPage, navigator: _this4 });
-
- options.callback && options.callback(enterPage);
-
- resolve(enterPage);
- });
- };
-
- leavePage._hide();
- enterPage.style.display = '';
-
- var animator = options.animator || _this4._animatorFactory.newAnimator(options);
- animator.pop(_this4.pages[length - 2], _this4.pages[length - 1], done);
- }).catch(function () {
- return _this4._isRunning = false;
- });
- }
-
- /**
- * @method pushPage
- * @signature pushPage(page, [options])
- * @param {String} page
- * [en]Page URL. Can be either a HTML document or a template defined with the `<template>` tag.[/en]
- * [ja]pageのURLか、もしくは`<template>`で宣言したテンプレートのid属性の値を指定できます。[/ja]
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {String} [options.page]
- * [en]Page URL. Only necessary if `page` parameter is null or undefined.[/en]
- * [ja][/ja]
- * @param {String} [options.pageHTML]
- * [en]HTML code that will be computed as a new page. Overwrites `page` parameter.[/en]
- * [ja][/ja]
- * @param {String} [options.animation]
- * [en]
- * Animation name. Available animations are `"slide"`, `"lift"`, `"fade"` and `"none"`.
- *
- * These are platform based animations. For fixed animations, add `"-ios"` or `"-md"` suffix to the animation name. E.g. `"lift-ios"`, `"lift-md"`. Defaults values are `"slide-ios"` and `"fade-md"`.
- * [/en]
- * [ja][/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}` [/ja]
- * @param {Function} [options.callback]
- * [en]Function that is called when the transition has ended.[/en]
- * [ja]pushPage()による画面遷移が終了した時に呼び出される関数オブジェクトを指定します。[/ja]
- * @param {Object} [options.data]
- * [en]Custom data that will be stored in the new page element.[/en]
- * [ja][/ja]
- * @return {Promise}
- * [en]Promise which resolves to the pushed page.[/en]
- * [ja]追加したページを解決するPromiseを返します。[/ja]
- * @description
- * [en]Pushes the specified page into the stack.[/en]
- * [ja]指定したpageを新しいページスタックに追加します。新しいページが表示されます。[/ja]
- */
-
- }, {
- key: 'pushPage',
- value: function pushPage(page) {
- var _this5 = this;
-
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- var _preparePageAndOption2 = this._preparePageAndOptions(page, options);
-
- page = _preparePageAndOption2.page;
- options = _preparePageAndOption2.options;
-
-
- var prepare = function prepare(pageElement) {
- verifyPageElement(pageElement);
- _this5._pageMap.set(pageElement, page);
- pageElement = util$1.extend(pageElement, {
- data: options.data
- });
- pageElement.style.visibility = 'hidden';
- };
-
- if (options.pageHTML) {
- return this._pushPage(options, function () {
- return new Promise(function (resolve) {
- instantPageLoader.load({ page: options.pageHTML, parent: _this5, params: options.data }, function (pageElement) {
- prepare(pageElement);
- resolve();
- });
- });
- });
- }
-
- return this._pushPage(options, function () {
- return new Promise(function (resolve) {
- _this5._pageLoader.load({ page: page, parent: _this5, params: options.data }, function (pageElement) {
- prepare(pageElement);
- resolve();
- });
- });
- });
- }
- }, {
- key: '_pushPage',
- value: function _pushPage() {
- var _this6 = this;
-
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var update = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {
- return Promise.resolve();
- };
-
- if (this._isRunning) {
- return Promise.reject('pushPage is already running.');
- }
-
- if (this._emitPrePushEvent()) {
- return Promise.reject('Canceled in prepush event.');
- }
-
- this._isRunning = true;
-
- var animationOptions = AnimatorFactory.parseAnimationOptionsString(this.getAttribute('animation-options'));
- options = util$1.extend({}, this.options || {}, { animationOptions: animationOptions }, options);
-
- var animator = this._animatorFactory.newAnimator(options);
-
- return update().then(function () {
- var pageLength = _this6.pages.length;
-
- var enterPage = _this6.pages[pageLength - 1];
- var leavePage = options.leavePage || _this6.pages[pageLength - 2];
-
- verifyPageElement(enterPage);
-
- enterPage.updateBackButton(pageLength > (options._replacePage ? 2 : 1));
-
- enterPage.pushedOptions = util$1.extend({}, enterPage.pushedOptions || {}, options || {});
- enterPage.data = util$1.extend({}, enterPage.data || {}, options.data || {});
- enterPage.unload = enterPage.unload || options.unload;
-
- return new Promise(function (resolve) {
- var done = function done() {
- _this6._isRunning = false;
-
- options.show !== false && setImmediate(function () {
- return enterPage._show();
- });
- util$1.triggerElementEvent(_this6, 'postpush', { leavePage: leavePage, enterPage: enterPage, navigator: _this6 });
-
- if (leavePage) {
- leavePage.style.display = 'none';
- }
-
- options.callback && options.callback(enterPage);
-
- resolve(enterPage);
- };
-
- enterPage.style.visibility = '';
- if (leavePage) {
- leavePage._hide();
- animator.push(enterPage, leavePage, done);
- } else {
- done();
- }
- });
- }).catch(function (error) {
- _this6._isRunning = false;
- throw error;
- });
- }
-
- /**
- * @method replacePage
- * @signature replacePage(page, [options])
- * @return {Promise}
- * [en]Promise which resolves to the new page.[/en]
- * [ja]新しいページを解決するPromiseを返します。[/ja]
- * @description
- * [en]Replaces the current top page with the specified one. Extends `pushPage()` parameters.[/en]
- * [ja]現在表示中のページをを指定したページに置き換えます。[/ja]
- */
-
- }, {
- key: 'replacePage',
- value: function replacePage(page) {
- var _this7 = this;
-
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- return this.pushPage(page, options).then(function (resolvedValue) {
- if (_this7.pages.length > 1) {
- _this7._pageLoader.unload(_this7.pages[_this7.pages.length - 2]);
- }
- _this7._updateLastPageBackButton();
-
- return Promise.resolve(resolvedValue);
- });
- }
-
- /**
- * @method insertPage
- * @signature insertPage(index, page, [options])
- * @param {Number} index
- * [en]The index where it should be inserted.[/en]
- * [ja]スタックに挿入する位置のインデックスを指定します。[/ja]
- * @return {Promise}
- * [en]Promise which resolves to the inserted page.[/en]
- * [ja]指定したページを解決するPromiseを返します。[/ja]
- * @description
- * [en]Insert the specified page into the stack with at a position defined by the `index` argument. Extends `pushPage()` parameters.[/en]
- * [ja]指定したpageをページスタックのindexで指定した位置に追加します。[/ja]
- */
-
- }, {
- key: 'insertPage',
- value: function insertPage(index, page) {
- var _this8 = this;
-
- var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
-
- var _preparePageAndOption3 = this._preparePageAndOptions(page, options);
-
- page = _preparePageAndOption3.page;
- options = _preparePageAndOption3.options;
-
- index = this._normalizeIndex(index);
-
- if (index >= this.pages.length) {
- return this.pushPage(page, options);
- }
-
- page = typeof options.pageHTML === 'string' ? options.pageHTML : page;
- var loader = typeof options.pageHTML === 'string' ? instantPageLoader : this._pageLoader;
-
- return new Promise(function (resolve) {
- loader.load({ page: page, parent: _this8 }, function (pageElement) {
- verifyPageElement(pageElement);
- _this8._pageMap.set(pageElement, page);
- pageElement = util$1.extend(pageElement, {
- data: options.data,
- pushedOptions: options
- });
-
- options.animationOptions = util$1.extend({}, AnimatorFactory.parseAnimationOptionsString(_this8.getAttribute('animation-options')), options.animationOptions || {});
-
- pageElement.style.display = 'none';
- _this8.insertBefore(pageElement, _this8.pages[index]);
- _this8.topPage.updateBackButton(true);
-
- setTimeout(function () {
- pageElement = null;
- resolve(_this8.pages[index]);
- }, 1000 / 60);
- });
- });
- }
-
- /**
- * @method removePage
- * @signature removePage(index, [options])
- * @param {Number} index
- * [en]The index where it should be removed.[/en]
- * [ja]スタックから削除するページのインデックスを指定します。[/ja]
- * @return {Promise}
- * [en]Promise which resolves to the revealed page.[/en]
- * [ja]削除によって表示されたページを解決するPromiseを返します。[/ja]
- * @description
- * [en]Remove the specified page at a position in the stack defined by the `index` argument. Extends `popPage()` parameters.[/en]
- * [ja]指定したインデックスにあるページを削除します。[/ja]
- */
-
- }, {
- key: 'removePage',
- value: function removePage(index) {
- var _this9 = this;
-
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- index = this._normalizeIndex(index);
-
- if (index < this.pages.length - 1) {
- return new Promise(function (resolve) {
- var leavePage = _this9.pages[index];
- var enterPage = _this9.topPage;
-
- _this9._pageMap.delete(leavePage);
- _this9._pageLoader.unload(leavePage);
- if (_this9.pages.length === 1) {
- // edge case
- _this9.topPage.updateBackButton(false);
- }
-
- resolve(enterPage);
- });
- } else {
- return this.popPage(options);
- }
- }
-
- /**
- * @method resetToPage
- * @signature resetToPage(page, [options])
- * @return {Promise}
- * [en]Promise which resolves to the new top page.[/en]
- * [ja]新しいトップページを解決するPromiseを返します。[/ja]
- * @param {Boolean} [options.pop]
- * [en]Performs 'pop' effect if `true` instead of 'push' or none. This also sets `options.animation` value to `default` instead of `none`.[/en]
- * [ja][/ja]
- * @description
- * [en]Clears page stack and adds the specified page to the stack. Extends `pushPage()` parameters.[/en]
- * [ja]ページスタックをリセットし、指定したページを表示します。[/ja]
- */
-
- }, {
- key: 'resetToPage',
- value: function resetToPage(page) {
- var _this10 = this;
-
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- var _preparePageAndOption4 = this._preparePageAndOptions(page, options);
-
- page = _preparePageAndOption4.page;
- options = _preparePageAndOption4.options;
-
-
- if (!options.animator && !options.animation && !options.pop) {
- options.animation = 'none';
- }
-
- if (!options.page && !options.pageHTML && this._getPageTarget()) {
- page = options.page = this._getPageTarget();
- }
-
- if (options.pop) {
- this._removePages();
- return this.insertPage(0, page, { data: options.data }).then(function () {
- return _this10.popPage(options);
- });
- }
-
- // Tip: callback runs before resolved promise
- var callback = options.callback;
- options.callback = function (newPage) {
- _this10._removePages();
- newPage.updateBackButton(false);
- callback && callback(newPage);
- };
-
- return this.pushPage(page, options);
- }
-
- /**
- * @method bringPageTop
- * @signature bringPageTop(item, [options])
- * @param {String|Number} item
- * [en]Page URL or index of an existing page in navigator's stack.[/en]
- * [ja]ページのURLかもしくはons-navigatorのページスタックのインデックス値を指定します。[/ja]
- * @return {Promise}
- * [en]Promise which resolves to the new top page.[/en]
- * [ja]新しいトップページを解決するPromiseを返します。[/ja]
- * @description
- * [en]Brings the given page to the top of the page stack if it already exists or pushes it into the stack if doesn't. Extends `pushPage()` parameters.[/en]
- * [ja]指定したページをページスタックの一番上に移動します。もし指定したページが無かった場合新しくpushされます。[/ja]
- */
-
- }, {
- key: 'bringPageTop',
- value: function bringPageTop(item) {
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- if (['number', 'string'].indexOf(typeof item === 'undefined' ? 'undefined' : _typeof(item)) === -1) {
- util$1.throw('First argument must be a page name or the index of an existing page. You supplied ' + item);
- }
- var index = typeof item === 'number' ? this._normalizeIndex(item) : this._lastIndexOfPage(item);
- var page = this.pages[index];
-
- if (index < 0) {
- return this.pushPage(item, options);
- }
-
- var _preparePageAndOption5 = this._preparePageAndOptions(page, options);
-
- options = _preparePageAndOption5.options;
-
-
- if (index === this.pages.length - 1) {
- return Promise.resolve(page);
- }
- if (!page) {
- util$1.throw('Failed to find item ' + item);
- }
- if (this._isRunning) {
- return Promise.reject('pushPage is already running.');
- }
- if (this._emitPrePushEvent()) {
- return Promise.reject('Canceled in prepush event.');
- }
-
- page.style.display = '';
- page.style.visibility = 'hidden';
- page.parentNode.appendChild(page);
- return this._pushPage(options);
- }
- }, {
- key: '_preparePageAndOptions',
- value: function _preparePageAndOptions(page) {
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) != 'object') {
- util$1.throw('options must be an object. You supplied ' + options);
- }
-
- if ((page === null || page === undefined) && options.page) {
- page = options.page;
- }
-
- options = util$1.extend({}, this.options || {}, options, { page: page });
-
- return { page: page, options: options };
- }
- }, {
- key: '_removePages',
- value: function _removePages(times) {
- var pages = this.pages;
- var until = times === undefined ? 0 : pages.length - times;
- until = until < 0 ? 1 : until;
-
- for (var i = pages.length - 2; i >= until; i--) {
- this._pageMap.delete(pages[i]);
- this._pageLoader.unload(pages[i]);
- }
- }
- }, {
- key: '_updateLastPageBackButton',
- value: function _updateLastPageBackButton() {
- var index = this.pages.length - 1;
- if (index >= 0) {
- this.pages[index].updateBackButton(index > 0);
- }
- }
- }, {
- key: '_normalizeIndex',
- value: function _normalizeIndex(index) {
- return index >= 0 ? index : Math.abs(this.pages.length + index) % this.pages.length;
- }
- }, {
- key: '_onDeviceBackButton',
- value: function _onDeviceBackButton(event) {
- if (this.pages.length > 1) {
- this.popPage();
- } else {
- event.callParentHandler();
- }
- }
- }, {
- key: '_lastIndexOfPage',
- value: function _lastIndexOfPage(pageName) {
- var index = void 0;
- for (index = this.pages.length - 1; index >= 0; index--) {
- if (pageName === this._pageMap.get(this.pages[index])) {
- break;
- }
- }
- return index;
- }
- }, {
- key: '_emitPreEvent',
- value: function _emitPreEvent(name) {
- var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- var isCanceled = false;
-
- util$1.triggerElementEvent(this, 'pre' + name, util$1.extend({
- navigator: this,
- currentPage: this.pages[this.pages.length - 1],
- cancel: function cancel() {
- return isCanceled = true;
- }
- }, data));
-
- return isCanceled;
- }
- }, {
- key: '_emitPrePushEvent',
- value: function _emitPrePushEvent() {
- return this._emitPreEvent('push');
- }
- }, {
- key: '_emitPrePopEvent',
- value: function _emitPrePopEvent() {
- var l = this.pages.length;
- return this._emitPreEvent('pop', {
- leavePage: this.pages[l - 1],
- enterPage: this.pages[l - 2]
- });
- }
-
- // TODO: 書き直す
-
- }, {
- key: '_createPageElement',
- value: function _createPageElement(templateHTML) {
- var pageElement = util$1.createElement(internal$1.normalizePageHTML(templateHTML));
- verifyPageElement(pageElement);
- return pageElement;
- }
-
- /**
- * @property onDeviceBackButton
- * @type {Object}
- * @description
- * [en]Back-button handler.[/en]
- * [ja]バックボタンハンドラ。[/ja]
- */
-
- }, {
- key: '_show',
- value: function _show() {
- var _this11 = this;
-
- this.loaded.then(function () {
- return _this11.topPage && _this11.topPage._show();
- });
- }
- }, {
- key: '_hide',
- value: function _hide() {
- this.topPage && this.topPage._hide();
- }
- }, {
- key: '_destroy',
- value: function _destroy() {
- for (var i = this.pages.length - 1; i >= 0; i--) {
- this._pageLoader.unload(this.pages[i]);
- }
-
- this.remove();
- }
-
- /**
- * @param {String} name
- * @param {Function} Animator
- */
-
- }, {
- key: 'pageLoader',
- get: function get$$1() {
- return this._pageLoader;
- },
- set: function set$$1(pageLoader) {
- if (!(pageLoader instanceof PageLoader)) {
- util$1.throwPageLoader();
- }
- this._pageLoader = pageLoader;
- }
- }, {
- key: 'page',
- get: function get$$1() {
- return this._page;
- },
- set: function set$$1(page) {
- this._page = page;
- }
- }, {
- key: 'onDeviceBackButton',
- get: function get$$1() {
- return this._backButtonHandler;
- },
- set: function set$$1(callback) {
- if (this._backButtonHandler) {
- this._backButtonHandler.destroy();
- }
-
- this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, callback);
- }
-
- /**
- * @property topPage
- * @readonly
- * @type {HTMLElement}
- * @description
- * [en]Current top page element. Use this method to access options passed by `pushPage()`-like methods.[/en]
- * [ja]現在のページを取得します。pushPage()やresetToPage()メソッドの引数を取得できます。[/ja]
- */
-
- }, {
- key: 'topPage',
- get: function get$$1() {
- var last = this.lastElementChild;
- while (last && last.tagName !== 'ONS-PAGE') {
- last = last.previousElementSibling;
- }
- return last;
- }
-
- /**
- * @property pages
- * @readonly
- * @type {Array}
- * @description
- * [en]Copy of the navigator's page stack.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'pages',
- get: function get$$1() {
- return util$1.arrayFrom(this.children).filter(function (element) {
- return element.tagName === 'ONS-PAGE';
- });
- }
-
- /**
- * @property onSwipe
- * @type {Function}
- * @description
- * [en]Hook called whenever the user slides the navigator (swipe-to-pop). It gets a decimal ratio (0-1) and an animationOptions object as arguments.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'onSwipe',
- get: function get$$1() {
- return this._onSwipe;
- },
- set: function set$$1(value) {
- if (value && !(value instanceof Function)) {
- util$1.throw('"onSwipe" must be a function');
- }
- this._onSwipe = value;
- }
-
- /**
- * @property options
- * @type {Object}
- * @description
- * [en]Default options object. Attributes have priority over this property.[/en]
- * [ja][/ja]
- */
-
- /**
- * @property options.animation
- * @type {String}
- * @description
- * [en]
- * Animation name. Available animations are `"slide"`, `"lift"`, `"fade"` and `"none"`.
- * These are platform based animations. For fixed animations, add `"-ios"` or `"-md"` suffix to the animation name. E.g. `"lift-ios"`, `"lift-md"`. Defaults values are `"slide-ios"` and `"fade-md"`.
- * [/en]
- * [ja][/ja]
- */
-
- /**
- * @property options.animationOptions
- * @type {String}
- * @description
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}` [/ja]
- */
-
- /**
- * @property options.callback
- * @type {String}
- * @description
- * [en]Function that is called when the transition has ended.[/en]
- * [ja]このメソッドによる画面遷移が終了した際に呼び出される関数オブジェクトを指定します。[/ja]
- */
-
- }, {
- key: 'options',
- get: function get$$1() {
- return this._options;
- },
- set: function set$$1(object) {
- this._options = object;
- }
- }, {
- key: '_isRunning',
- set: function set$$1(value) {
- this.setAttribute('_is-running', value ? 'true' : 'false');
- },
- get: function get$$1() {
- return JSON.parse(this.getAttribute('_is-running'));
- }
- }], [{
- key: 'registerAnimator',
- value: function registerAnimator(name, Animator) {
- if (!(Animator.prototype instanceof NavigatorAnimator)) {
- util$1.throwAnimator('Navigator');
- }
-
- _animatorDict$5[name] = Animator;
- }
- }, {
- key: 'observedAttributes',
- get: function get$$1() {
- return ['animation', 'swipeable'];
- }
- }, {
- key: 'animators',
- get: function get$$1() {
- return _animatorDict$5;
- }
- }, {
- key: 'NavigatorAnimator',
- get: function get$$1() {
- return NavigatorAnimator;
- }
- }, {
- key: 'events',
- get: function get$$1() {
- return ['prepush', 'postpush', 'prepop', 'postpop'];
- }
- }, {
- key: 'rewritables',
- get: function get$$1() {
- return rewritables;
- }
- }]);
- return NavigatorElement;
- }(BaseElement);
-
- onsElements.Navigator = NavigatorElement;
- customElements.define('ons-navigator', NavigatorElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var defaultClassName$10 = 'toolbar';
-
- var scheme$18 = {
- '': 'toolbar--*',
- '.toolbar__left': 'toolbar--*__left',
- '.toolbar__center': 'toolbar--*__center',
- '.toolbar__right': 'toolbar--*__right'
- };
-
- /**
- * @element ons-toolbar
- * @category page
- * @modifier material
- * [en]Material Design toolbar.[/en]
- * [ja][/ja]
- * @modifier transparent
- * [en]Transparent toolbar.[/en]
- * [ja]透明な背景を持つツールバーを表示します。[/ja]
- * @modifier cover-content
- * [en]Displays the toolbar on top of the page's content. Should be combined with `transparent` modifier.[/en]
- * [ja][/ja]
- * @modifier noshadow
- * [en]Toolbar without shadow.[/en]
- * [ja]ツールバーに影を付けずに表示します。[/ja]
- * @description
- * [en]
- * Toolbar component that can be used with navigation.
- *
- * Left, center and right containers can be specified by class names.
- *
- * This component will automatically display as a Material Design toolbar when running on Android devices.
- * [/en]
- * [ja]ナビゲーションで使用するツールバー用コンポーネントです。クラス名により、左、中央、右のコンテナを指定できます。[/ja]
- * @codepen aHmGL
- * @tutorial vanilla/Reference/toolbar
- * @guide compilation.html#toolbar-compilation [en]Adding a toolbar[/en][ja]ツールバーの追加[/ja]
- * @seealso ons-bottom-toolbar
- * [en]The `<ons-bottom-toolbar>` displays a toolbar on the bottom of the page.[/en]
- * [ja]ons-bottom-toolbarコンポーネント[/ja]
- * @seealso ons-back-button
- * [en]The `<ons-back-button>` component displays a back button inside the toolbar.[/en]
- * [ja]ons-back-buttonコンポーネント[/ja]
- * @seealso ons-toolbar-button
- * [en]The `<ons-toolbar-button>` component displays a toolbar button inside the toolbar.[/en]
- * [ja]ons-toolbar-buttonコンポーネント[/ja]
- * @example
- * <ons-page>
- * <ons-toolbar>
- * <div class="left">
- * <ons-back-button>
- * Back
- * </ons-back-button>
- * </div>
- * <div class="center">
- * Title
- * </div>
- * <div class="right">
- * <ons-toolbar-button>
- * <ons-icon icon="md-menu"></ons-icon>
- * </ons-toolbar-button>
- * </div>
- * </ons-toolbar>
- * </ons-page>
- */
-
- var ToolbarElement = function (_BaseElement) {
- inherits(ToolbarElement, _BaseElement);
-
- /**
- * @attribute inline
- * @initonly
- * @description
- * [en]Display the toolbar as an inline element.[/en]
- * [ja]ツールバーをインラインに置きます。スクロール領域内にそのまま表示されます。[/ja]
- */
-
- /**
- * @attribute static
- * @description
- * [en]Static toolbars are not animated by `ons-navigator` when pushing or popping pages. This can be useful to improve performance in some situations.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute modifier
- * @description
- * [en]The appearance of the toolbar.[/en]
- * [ja]ツールバーの表現を指定します。[/ja]
- */
-
- function ToolbarElement() {
- classCallCheck(this, ToolbarElement);
-
- var _this = possibleConstructorReturn(this, (ToolbarElement.__proto__ || Object.getPrototypeOf(ToolbarElement)).call(this));
-
- contentReady(_this, function () {
- _this._compile();
- });
- return _this;
- }
-
- createClass(ToolbarElement, [{
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'class':
- util$1.restoreClass(this, defaultClassName$10, scheme$18);
- break;
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, scheme$18);
- break;
- }
- }
-
- /**
- * @method setVisibility
- * @signature setVisibility(visible)
- * @param {Boolean} visible
- * [en]Set to true to show the toolbar, false to hide it[/en]
- * [ja][/ja]
- * @description
- * [en]Shows the toolbar if visible is true, otherwise hides it.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'setVisibility',
- value: function setVisibility(visible) {
- var _this2 = this;
-
- contentReady(this, function () {
- _this2.style.display = visible ? '' : 'none';
-
- if (_this2.parentNode) {
- var siblingBackground = util$1.findChild(_this2.parentNode, '.page__background');
- if (siblingBackground) {
- siblingBackground.style.top = visible ? null : 0;
- }
-
- var siblingContent = util$1.findChild(_this2.parentNode, '.page__content');
- if (siblingContent) {
- siblingContent.style.top = visible ? null : 0;
- }
- }
- });
- }
-
- /**
- * @method show
- * @signature show()
- * @description
- * [en]Show the toolbar.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'show',
- value: function show() {
- this.setVisibility(true);
- }
-
- /**
- * @method hide
- * @signature hide()
- * @description
- * [en]Hide the toolbar.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'hide',
- value: function hide() {
- this.setVisibility(false);
- }
-
- /**
- * @return {HTMLElement}
- */
-
- }, {
- key: '_getToolbarLeftItemsElement',
- value: function _getToolbarLeftItemsElement() {
- return this.querySelector('.left') || internal$1.nullElement;
- }
-
- /**
- * @return {HTMLElement}
- */
-
- }, {
- key: '_getToolbarCenterItemsElement',
- value: function _getToolbarCenterItemsElement() {
- return this.querySelector('.center') || internal$1.nullElement;
- }
-
- /**
- * @return {HTMLElement}
- */
-
- }, {
- key: '_getToolbarRightItemsElement',
- value: function _getToolbarRightItemsElement() {
- return this.querySelector('.right') || internal$1.nullElement;
- }
-
- /**
- * @return {HTMLElement}
- */
-
- }, {
- key: '_getToolbarBackButtonLabelElement',
- value: function _getToolbarBackButtonLabelElement() {
- return this.querySelector('ons-back-button .back-button__label') || internal$1.nullElement;
- }
-
- /**
- * @return {HTMLElement}
- */
-
- }, {
- key: '_getToolbarBackButtonIconElement',
- value: function _getToolbarBackButtonIconElement() {
- return this.querySelector('ons-back-button .back-button__icon') || internal$1.nullElement;
- }
- }, {
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
- this.classList.add(defaultClassName$10);
- this._ensureToolbarItemElements();
- ModifierUtil.initModifier(this, scheme$18);
- }
- }, {
- key: '_ensureToolbarItemElements',
- value: function _ensureToolbarItemElements() {
- for (var i = this.childNodes.length - 1; i >= 0; i--) {
- // case of not element
- if (this.childNodes[i].nodeType != 1) {
- this.removeChild(this.childNodes[i]);
- }
- }
-
- var center = this._ensureToolbarElement('center');
- center.classList.add('toolbar__title');
-
- if (this.children.length !== 1 || !this.children[0].classList.contains('center')) {
- var left = this._ensureToolbarElement('left');
- var right = this._ensureToolbarElement('right');
-
- if (this.children[0] !== left || this.children[1] !== center || this.children[2] !== right) {
- this.appendChild(left);
- this.appendChild(center);
- this.appendChild(right);
- }
- }
- }
- }, {
- key: '_ensureToolbarElement',
- value: function _ensureToolbarElement(name) {
- if (util$1.findChild(this, '.toolbar__' + name)) {
- var _element = util$1.findChild(this, '.toolbar__' + name);
- _element.classList.add(name);
- return _element;
- }
-
- var element = util$1.findChild(this, '.' + name) || util$1.create('.' + name);
- element.classList.add('toolbar__' + name);
-
- return element;
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'class'];
- }
- }]);
- return ToolbarElement;
- }(BaseElement);
-
- onsElements.Toolbar = ToolbarElement;
- customElements.define('ons-toolbar', ToolbarElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var defaultClassName$9 = 'page';
- var scheme$17 = {
- '': 'page--*',
- '.page__content': 'page--*__content',
- '.page__background': 'page--*__background'
- };
-
- /**
- * @element ons-page
- * @category page
- * @modifier material
- * [en]Material Design style[/en]
- * [ja][/ja]
- * @description
- * [en]
- * This component defines the root of each page. If the content is large it will become scrollable.
- *
- * A navigation bar can be added to the top of the page using the `<ons-toolbar>` element.
- * [/en]
- * [ja]ページ定義のためのコンポーネントです。このコンポーネントの内容はスクロールが許可されます。[/ja]
- * @tutorial vanilla/Reference/page
- * @guide lifecycle.html#events
- * [en]Overview of page events[/en]
- * [ja]Overview of page events[/ja]
- * @guide fundamentals.html#managing-pages
- * [en]Managing multiple pages[/en]
- * [ja]複数のページを管理する[/ja]
- * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
- * @seealso ons-toolbar
- * [en]Use the `<ons-toolbar>` element to add a navigation bar to the top of the page.[/en]
- * [ja][/ja]
- * @example
- * <ons-page>
- * <ons-toolbar>
- * <div class="left">
- * <ons-back-button>Back</ons-back-button>
- * </div>
- * <div class="center">Title</div>
- * <div class="right">
- * <ons-toolbar-button>
- * <ons-icon icon="md-menu"></ons-icon>
- * </ons-toolbar-button>
- * </div>
- * </ons-toolbar>
- *
- * <p>Page content</p>
- * </ons-page>
- *
- * @example
- * <script>
- * myApp.handler = function(done) {
- * loadMore().then(done);
- * }
- * </script>
- *
- * <ons-page on-infinite-scroll="myApp.handler">
- * <ons-toolbar>
- * <div class="center">List</div>
- * </ons-toolbar>
- *
- * <ons-list>
- * <ons-list-item>#1</ons-list-item>
- * <ons-list-item>#2</ons-list-item>
- * <ons-list-item>#3</ons-list-item>
- * ...
- * </ons-list>
- * </ons-page>
- */
-
- var PageElement = function (_BaseElement) {
- inherits(PageElement, _BaseElement);
-
- /**
- * @event init
- * @description
- * [en]Fired right after the page is attached.[/en]
- * [ja]ページがアタッチされた後に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- */
-
- /**
- * @event show
- * @description
- * [en]Fired right after the page is shown.[/en]
- * [ja]ページが表示された後に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- */
-
- /**
- * @event hide
- * @description
- * [en]Fired right after the page is hidden.[/en]
- * [ja]ページが隠れた後に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- */
-
- /**
- * @event destroy
- * @description
- * [en]Fired right before the page is destroyed.[/en]
- * [ja]ページが破棄される前に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- */
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]Specify modifier name to specify custom styles.[/en]
- * [ja]スタイル定義をカスタマイズするための名前を指定します。[/ja]
- */
-
- /**
- * @attribute on-infinite-scroll
- * @type {String}
- * @description
- * [en]Path of the function to be executed on infinite scrolling. Example: `app.loadData`. The function receives a done callback that must be called when it's finished.[/en]
- * [ja][/ja]
- */
-
- function PageElement() {
- classCallCheck(this, PageElement);
-
- var _this = possibleConstructorReturn(this, (PageElement.__proto__ || Object.getPrototypeOf(PageElement)).call(this));
-
- _this._deriveHooks();
-
- _this._defaultClassName = defaultClassName$9;
- _this.classList.add(defaultClassName$9);
-
- _this._initialized = false;
-
- contentReady(_this, function () {
- _this._compile();
-
- _this._isShown = false;
- _this._contentElement = _this._getContentElement();
- _this._backgroundElement = _this._getBackgroundElement();
- });
- return _this;
- }
-
- createClass(PageElement, [{
- key: '_compile',
- value: function _compile() {
- var _this2 = this;
-
- autoStyle.prepare(this);
-
- var toolbar = util$1.findChild(this, 'ons-toolbar');
-
- var background = util$1.findChild(this, '.page__background') || util$1.findChild(this, '.background') || document.createElement('div');
- background.classList.add('page__background');
- this.insertBefore(background, !toolbar && this.firstChild || toolbar && toolbar.nextSibling);
-
- var content = util$1.findChild(this, '.page__content') || util$1.findChild(this, '.content') || document.createElement('div');
- content.classList.add('page__content');
- if (!content.parentElement) {
- util$1.arrayFrom(this.childNodes).forEach(function (node) {
- if (node.nodeType !== 1 || _this2._elementShouldBeMoved(node)) {
- content.appendChild(node); // Can trigger detached connectedCallbacks
- }
- });
- }
-
- this._tryToFillStatusBar(content); // Must run before child pages try to fill status bar.
- this.insertBefore(content, background.nextSibling); // Can trigger attached connectedCallbacks
-
- if ((!toolbar || !util$1.hasModifier(toolbar, 'transparent')) && content.children.length === 1 && util$1.isPageControl(content.children[0])) {
- this._defaultClassName += ' page--wrapper';
- this.attributeChangedCallback('class');
- }
-
- var bottomToolbar = util$1.findChild(this, 'ons-bottom-toolbar');
- if (bottomToolbar) {
- this._defaultClassName += ' page-with-bottom-toolbar';
- this.attributeChangedCallback('class');
- }
-
- ModifierUtil.initModifier(this, scheme$17);
- }
- }, {
- key: '_elementShouldBeMoved',
- value: function _elementShouldBeMoved(el) {
- if (el.classList.contains('page__background')) {
- return false;
- }
- var tagName = el.tagName.toLowerCase();
- if (tagName === 'ons-fab') {
- return !el.hasAttribute('position');
- }
- var fixedElements = ['script', 'ons-toolbar', 'ons-bottom-toolbar', 'ons-modal', 'ons-speed-dial', 'ons-dialog', 'ons-alert-dialog', 'ons-popover', 'ons-action-sheet'];
- return el.hasAttribute('inline') || fixedElements.indexOf(tagName) === -1;
- }
- }, {
- key: '_tryToFillStatusBar',
- value: function _tryToFillStatusBar() {
- var _this3 = this;
-
- var content = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this._contentElement;
-
- internal$1.autoStatusBarFill(function () {
- util$1.toggleAttribute(_this3, 'status-bar-fill', !util$1.findParent(_this3, function (e) {
- return e.hasAttribute('status-bar-fill');
- }) // Not already filled
- && (_this3._canAnimateToolbar(content) || !util$1.findChild(content, util$1.isPageControl)) // Has toolbar or cannot delegate
- );
- });
- }
- }, {
- key: '_canAnimateToolbar',
- value: function _canAnimateToolbar() {
- var content = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this._contentElement;
-
- if (util$1.findChild(this, 'ons-toolbar')) {
- return true;
- }
-
- return !!util$1.findChild(content, function (el) {
- return util$1.match(el, 'ons-toolbar') && !el.hasAttribute('inline');
- });
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- var _this4 = this;
-
- if (!util$1.isAttached(this)) {
- // Avoid detached calls
- return;
- }
-
- contentReady(this, function () {
- _this4._tryToFillStatusBar(); // Ensure status bar when the element was compiled before connected
-
- if (_this4.hasAttribute('on-infinite-scroll')) {
- _this4.attributeChangedCallback('on-infinite-scroll', null, _this4.getAttribute('on-infinite-scroll'));
- }
-
- if (!_this4._initialized) {
- _this4._initialized = true;
-
- setImmediate(function () {
- _this4.onInit && _this4.onInit();
- util$1.triggerElementEvent(_this4, 'init');
- });
-
- if (!util$1.hasAnyComponentAsParent(_this4)) {
- setImmediate(function () {
- return _this4._show();
- });
- }
- }
- });
- }
- }, {
- key: 'updateBackButton',
- value: function updateBackButton(show) {
- if (this.backButton) {
- show ? this.backButton.show() : this.backButton.hide();
- }
- }
- }, {
- key: '_onScroll',
- value: function _onScroll() {
- var _this5 = this;
-
- var c = this._contentElement,
- overLimit = (c.scrollTop + c.clientHeight) / c.scrollHeight >= this._infiniteScrollLimit;
-
- if (this._onInfiniteScroll && !this._loadingContent && overLimit) {
- this._loadingContent = true;
- this._onInfiniteScroll(function () {
- return _this5._loadingContent = false;
- });
- }
- }
-
- /**
- * @property onDeviceBackButton
- * @type {Object}
- * @description
- * [en]Back-button handler.[/en]
- * [ja]バックボタンハンドラ。[/ja]
- */
-
- }, {
- key: '_getContentElement',
- value: function _getContentElement() {
- var result = util$1.findChild(this, '.page__content');
- if (result) {
- return result;
- }
- util$1.throw('Fail to get ".page__content" element');
- }
- }, {
- key: '_getBackgroundElement',
- value: function _getBackgroundElement() {
- var result = util$1.findChild(this, '.page__background');
- if (result) {
- return result;
- }
- util$1.throw('Fail to get ".page__background" element');
- }
- }, {
- key: '_getBottomToolbarElement',
- value: function _getBottomToolbarElement() {
- return util$1.findChild(this, 'ons-bottom-toolbar') || internal$1.nullElement;
- }
- }, {
- key: '_getToolbarElement',
- value: function _getToolbarElement() {
- return util$1.findChild(this, 'ons-toolbar') || document.createElement('ons-toolbar');
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- var _this6 = this;
-
- switch (name) {
- case 'class':
- util$1.restoreClass(this, this._defaultClassName, scheme$17);
- break;
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, scheme$17);
- break;
- case 'on-infinite-scroll':
- if (current === null) {
- this.onInfiniteScroll = null;
- } else {
- this.onInfiniteScroll = function (done) {
- var f = util$1.findFromPath(current);
- _this6.onInfiniteScroll = f;
- f(done);
- };
- }
- break;
- }
- }
- }, {
- key: '_show',
- value: function _show() {
- if (!this._isShown && util$1.isAttached(this)) {
- this._isShown = true;
- this.setAttribute('shown', '');
- this.onShow && this.onShow();
- util$1.triggerElementEvent(this, 'show');
- util$1.propagateAction(this, '_show');
- }
- }
- }, {
- key: '_hide',
- value: function _hide() {
- if (this._isShown) {
- this._isShown = false;
- this.removeAttribute('shown');
- this.onHide && this.onHide();
- util$1.triggerElementEvent(this, 'hide');
- util$1.propagateAction(this, '_hide');
- }
- }
- }, {
- key: '_destroy',
- value: function _destroy() {
- this._hide();
-
- this.onDestroy && this.onDestroy();
- util$1.triggerElementEvent(this, 'destroy');
-
- if (this.onDeviceBackButton) {
- this.onDeviceBackButton.destroy();
- }
-
- util$1.propagateAction(this, '_destroy');
-
- this.remove();
- }
- }, {
- key: '_deriveHooks',
- value: function _deriveHooks() {
- var _this7 = this;
-
- this.constructor.events.forEach(function (event) {
- var key = 'on' + event.charAt(0).toUpperCase() + event.slice(1);
- Object.defineProperty(_this7, key, {
- configurable: true,
- enumerable: true,
- get: function get$$1() {
- return _this7['_' + key];
- },
- set: function set$$1(value) {
- if (!(value instanceof Function)) {
- util$1.throw('"' + key + '" hook must be a function');
- }
- _this7['_' + key] = value.bind(_this7);
- }
- });
- });
- }
- }, {
- key: 'name',
- set: function set$$1(str) {
- this.setAttribute('name', str);
- },
- get: function get$$1() {
- return this.getAttribute('name');
- }
- }, {
- key: 'backButton',
- get: function get$$1() {
- return this.querySelector('ons-back-button');
- }
-
- /**
- * @property onInfiniteScroll
- * @description
- * [en]Function to be executed when scrolling to the bottom of the page. The function receives a done callback as an argument that must be called when it's finished.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'onInfiniteScroll',
- set: function set$$1(value) {
- var _this8 = this;
-
- if (value && !(value instanceof Function)) {
- util$1.throw('"onInfiniteScroll" must be function or null');
- }
-
- contentReady(this, function () {
- if (!value) {
- _this8._contentElement.removeEventListener('scroll', _this8._boundOnScroll);
- } else if (!_this8._onInfiniteScroll) {
- _this8._infiniteScrollLimit = 0.9;
- _this8._boundOnScroll = _this8._onScroll.bind(_this8);
- setImmediate(function () {
- return _this8._contentElement.addEventListener('scroll', _this8._boundOnScroll);
- });
- }
- _this8._onInfiniteScroll = value;
- });
- },
- get: function get$$1() {
- return this._onInfiniteScroll;
- }
- }, {
- key: 'onDeviceBackButton',
- get: function get$$1() {
- return this._backButtonHandler;
- },
- set: function set$$1(callback) {
- if (this._backButtonHandler) {
- this._backButtonHandler.destroy();
- }
-
- this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, callback);
- }
- }, {
- key: 'scrollTop',
- get: function get$$1() {
- return this._contentElement.scrollTop;
- },
- set: function set$$1(newValue) {
- this._contentElement.scrollTop = newValue;
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'on-infinite-scroll', 'class'];
- }
- }, {
- key: 'events',
- get: function get$$1() {
- return ['init', 'show', 'hide', 'destroy'];
- }
-
- /**
- * @property data
- * @type {*}
- * @description
- * [en]User's custom data passed to `pushPage()`-like methods.[/en]
- * [ja][/ja]
- */
-
- }]);
- return PageElement;
- }(BaseElement);
-
- onsElements.Page = PageElement;
- customElements.define('ons-page', PageElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
- var PopoverAnimator = function (_BaseAnimator) {
- inherits(PopoverAnimator, _BaseAnimator);
-
- /**
- * @param {Object} options
- * @param {String} options.timing
- * @param {Number} options.duration
- * @param {Number} options.delay
- */
- function PopoverAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'cubic-bezier(.1, .7, .4, 1)' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.2 : _ref$duration;
-
- classCallCheck(this, PopoverAnimator);
- return possibleConstructorReturn(this, (PopoverAnimator.__proto__ || Object.getPrototypeOf(PopoverAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
- }
-
- createClass(PopoverAnimator, [{
- key: 'show',
- value: function show(popover, callback) {
- callback();
- }
- }, {
- key: 'hide',
- value: function hide(popover, callback) {
- callback();
- }
- }, {
- key: '_animate',
- value: function _animate(element, _ref2) {
- var from = _ref2.from,
- to = _ref2.to,
- options = _ref2.options,
- callback = _ref2.callback,
- _ref2$restore = _ref2.restore,
- restore = _ref2$restore === undefined ? false : _ref2$restore,
- animation = _ref2.animation;
-
- options = util$1.extend({}, this.options, options);
-
- if (animation) {
- from = animation.from;
- to = animation.to;
- }
-
- animation = Animit(element);
- if (restore) {
- animation = animation.saveStyle();
- }
- animation = animation.queue(from).wait(this.delay).queue({
- css: to,
- duration: this.duration,
- timing: this.timing
- });
- if (restore) {
- animation = animation.restoreStyle();
- }
- if (callback) {
- animation = animation.queue(function (done) {
- callback();
- done();
- });
- }
- return animation;
- }
- }, {
- key: '_animateAll',
- value: function _animateAll(element, animations) {
- var _this2 = this;
-
- Object.keys(animations).forEach(function (key) {
- return _this2._animate(element[key], animations[key]).play();
- });
- }
- }]);
- return PopoverAnimator;
- }(BaseAnimator);
-
- var fade = {
- out: {
- from: { opacity: 1.0 },
- to: { opacity: 0 }
- },
- in: {
- from: { opacity: 0 },
- to: { opacity: 1.0 }
- }
- };
-
- var MDFadePopoverAnimator = function (_PopoverAnimator) {
- inherits(MDFadePopoverAnimator, _PopoverAnimator);
-
- function MDFadePopoverAnimator() {
- classCallCheck(this, MDFadePopoverAnimator);
- return possibleConstructorReturn(this, (MDFadePopoverAnimator.__proto__ || Object.getPrototypeOf(MDFadePopoverAnimator)).apply(this, arguments));
- }
-
- createClass(MDFadePopoverAnimator, [{
- key: 'show',
- value: function show(popover, callback) {
- this._animateAll(popover, {
- _mask: fade.in,
- _popover: { animation: fade.in, restore: true, callback: callback }
- });
- }
- }, {
- key: 'hide',
- value: function hide(popover, callback) {
- this._animateAll(popover, {
- _mask: fade.out,
- _popover: { animation: fade.out, restore: true, callback: callback }
- });
- }
- }]);
- return MDFadePopoverAnimator;
- }(PopoverAnimator);
-
- var IOSFadePopoverAnimator = function (_MDFadePopoverAnimato) {
- inherits(IOSFadePopoverAnimator, _MDFadePopoverAnimato);
-
- function IOSFadePopoverAnimator() {
- classCallCheck(this, IOSFadePopoverAnimator);
- return possibleConstructorReturn(this, (IOSFadePopoverAnimator.__proto__ || Object.getPrototypeOf(IOSFadePopoverAnimator)).apply(this, arguments));
- }
-
- createClass(IOSFadePopoverAnimator, [{
- key: 'show',
- value: function show(popover, callback) {
- this._animateAll(popover, {
- _mask: fade.in,
- _popover: {
- from: {
- transform: 'scale3d(1.3, 1.3, 1.0)',
- opacity: 0
- },
- to: {
- transform: 'scale3d(1.0, 1.0, 1.0)',
- opacity: 1.0
- },
- restore: true,
- callback: callback
- }
- });
- }
- }]);
- return IOSFadePopoverAnimator;
- }(MDFadePopoverAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var scheme$19 = {
- '.popover': 'popover--*',
- '.popover-mask': 'popover-mask--*',
- '.popover__content': 'popover--*__content',
- '.popover__arrow': 'popover--*__arrow'
- };
-
- var _animatorDict$6 = {
- 'default': function _default() {
- return platform.isAndroid() ? MDFadePopoverAnimator : IOSFadePopoverAnimator;
- },
- 'none': PopoverAnimator,
- 'fade-ios': IOSFadePopoverAnimator,
- 'fade-md': MDFadePopoverAnimator
- };
-
- var positions = {
- up: 'bottom',
- left: 'right',
- down: 'top',
- right: 'left'
- };
-
- /**
- * @element ons-popover
- * @category dialog
- * @description
- * [en]
- * A component that displays a popover next to an element. The popover can be used to display extra information about a component or a tooltip.
- *
- * To use the element it can either be attached directly to the `<body>` element or dynamically created from a template using the `ons.createPopover(template)` utility function and the `<template>` tag.
- *
- * Another common way to use the popover is to display a menu when a button on the screen is tapped. For Material Design, popover looks exactly as a dropdown menu.
- * [/en]
- * [ja]ある要素を対象とするポップオーバーを表示するコンポーネントです。[/ja]
- * @codepen ZYYRKo
- * @tutorial vanilla/Reference/popover
- * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
- * @example
- * <ons-button onclick="showPopover(this)">
- * Click me!
- * </ons-button>
- *
- * <ons-popover direction="down" id="popover">
- * <p>This is a popover!</p>
- * </ons-popover>
- *
- * <script>
- * var showPopover = function(element) {
- * var popover = document.getElementById('popover');
- * popover.show(element);
- * };
- * </script>
- */
-
- var PopoverElement = function (_BaseDialogElement) {
- inherits(PopoverElement, _BaseDialogElement);
-
- /**
- * @event preshow
- * @description
- * [en]Fired just before the popover is displayed.[/en]
- * [ja]ポップオーバーが表示される直前に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.popover
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- * @param {Function} event.cancel
- * [en]Call this function to stop the popover from being shown.[/en]
- * [ja]この関数を呼び出すと、ポップオーバーの表示がキャンセルされます。[/ja]
- */
-
- /**
- * @event postshow
- * @description
- * [en]Fired just after the popover is displayed.[/en]
- * [ja]ポップオーバーが表示された直後に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.popover
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- */
-
- /**
- * @event prehide
- * @description
- * [en]Fired just before the popover is hidden.[/en]
- * [ja]ポップオーバーが隠れる直前に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.popover
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- * @param {Function} event.cancel
- * [en]Call this function to stop the popover from being hidden.[/en]
- * [ja]この関数を呼び出すと、ポップオーバーが隠れる処理をキャンセルします。[/ja]
- */
-
- /**
- * @event posthide
- * @description
- * [en]Fired just after the popover is hidden.[/en]
- * [ja]ポップオーバーが隠れた後に発火します。[/ja]
- * @param {Object} event [en]Event object.[/en]
- * @param {Object} event.popover
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- */
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the popover.[/en]
- * [ja]ポップオーバーの表現を指定します。[/ja]
- */
-
- /**
- * @attribute direction
- * @type {String}
- * @description
- * [en]
- * A space separated list of directions. If more than one direction is specified,
- * it will be chosen automatically. Valid directions are `"up"`, `"down"`, `"left"` and `"right"`.
- * [/en]
- * [ja]
- * ポップオーバーを表示する方向を空白区切りで複数指定できます。
- * 指定できる方向は、"up", "down", "left", "right"の4つです。空白区切りで複数指定することもできます。
- * 複数指定された場合、対象とする要素に合わせて指定した値から自動的に選択されます。
- * [/ja]
- */
-
- /**
- * @attribute cancelable
- * @description
- * [en]If this attribute is set the popover can be closed by tapping the background or by pressing the back button.[/en]
- * [ja]この属性があると、ポップオーバーが表示された時に、背景やバックボタンをタップした時にをポップオーバー閉じます。[/ja]
- */
-
- /**
- * @attribute cover-target
- * @description
- * [en]If set the popover will cover the target on the screen.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute animation
- * @type {String}
- * @description
- * [en]The animation used when showing an hiding the popover. Can be either `"none"`, `"default"`, `"fade-ios"` or `"fade-md"`.[/en]
- * [ja]ポップオーバーを表示する際のアニメーション名を指定します。[/ja]
- */
-
- /**
- * @attribute animation-options
- * @type {Expression}
- * @description
- * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. {duration: 0.2, delay: 1, timing: 'ease-in'}[/ja]
- */
-
- /**
- * @attribute mask-color
- * @type {Color}
- * @description
- * [en]Color of the background mask. Default is `"rgba(0, 0, 0, 0.2)"`.[/en]
- * [ja]背景のマスクの色を指定します。デフォルトは"rgba(0, 0, 0, 0.2)"です。[/ja]
- */
-
- function PopoverElement() {
- classCallCheck(this, PopoverElement);
-
- var _this = possibleConstructorReturn(this, (PopoverElement.__proto__ || Object.getPrototypeOf(PopoverElement)).call(this));
-
- _this._boundOnChange = _this._onChange.bind(_this);
-
- contentReady(_this, function () {
- _this._compile();
- _this.style.display = 'none';
- });
- return _this;
- }
-
- createClass(PopoverElement, [{
- key: '_updateAnimatorFactory',
- value: function _updateAnimatorFactory() {
- return new AnimatorFactory({
- animators: _animatorDict$6,
- baseClass: PopoverAnimator,
- baseClassName: 'PopoverAnimator',
- defaultAnimation: this.getAttribute('animation') || 'default'
- });
- }
- }, {
- key: '_toggleStyle',
- value: function _toggleStyle(shouldShow) {
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- if (shouldShow) {
- this.style.display = 'block';
- this._currentTarget = options.target;
- this._positionPopover(options.target);
- } else {
- this.style.display = 'none';
- this._clearStyles();
- }
- }
- }, {
- key: '_positionPopover',
- value: function _positionPopover(target) {
- var radius = this._radius,
- contentElement = this._content,
- margin = this._margin;
-
- var safeAreaLengths = iPhoneXPatch.getSafeAreaLengths();
- var safeAreaRect = iPhoneXPatch.getSafeAreaDOMRect();
- var targetRect = target.getBoundingClientRect();
- var isMD = util$1.hasModifier(this, 'material');
- var cover = isMD && this.hasAttribute('cover-target');
- var parent = util$1.findParent(this, 'ons-page') || document.body;
- var parentDimensions = parent.getBoundingClientRect();
- var maxPositions = {
- top: Math.max(parentDimensions.top, safeAreaRect.top),
- left: Math.max(parentDimensions.left, safeAreaRect.left),
- bottom: Math.min(parentDimensions.bottom, safeAreaRect.bottom),
- right: Math.min(parentDimensions.right, safeAreaRect.right)
- };
-
- // Distance from each side of the safe area (with margin) to the target element
- var targetDistance = {
- top: targetRect.top - (maxPositions.top + margin),
- left: targetRect.left - (maxPositions.left + margin),
- bottom: maxPositions.bottom - margin - targetRect.bottom,
- right: maxPositions.right - margin - targetRect.right
- };
-
- // Distance from each side of the safe area (with margin) to the geometric center of the target element
- var targetCenterDistanceFrom = {
- top: targetRect.top + Math.round(targetRect.height / 2) - (maxPositions.top + margin),
- left: targetRect.left + Math.round(targetRect.width / 2) - (maxPositions.left + margin),
- bottom: maxPositions.bottom - margin - targetRect.bottom + Math.round(targetRect.height / 2),
- right: maxPositions.right - margin - targetRect.right + Math.round(targetRect.width / 2)
- };
-
- var _calculateDirections2 = this._calculateDirections(targetDistance),
- vertical = _calculateDirections2.vertical,
- primaryDirection = _calculateDirections2.primary,
- secondaryDirection = _calculateDirections2.secondary;
-
- this._currentDirection = primaryDirection;
- util$1.addModifier(this, primaryDirection);
-
- var sizeName = vertical ? 'width' : 'height';
- // Get .popover__content size
- var contentSize = function (style) {
- return {
- width: parseInt(style.getPropertyValue('width'), 10),
- height: parseInt(style.getPropertyValue('height'), 10)
- };
- }(window.getComputedStyle(contentElement));
-
- // Setting .popover position.
- var targetAndArrowLength = cover ? 0 : (vertical ? targetRect.height : targetRect.width) + (isMD ? 0 : 14);
- var primaryOffset = Math.max(safeAreaLengths[primaryDirection] + margin, safeAreaLengths[primaryDirection] + margin + targetDistance[primaryDirection] + targetAndArrowLength);
- var secondaryOffset = Math.max(safeAreaLengths[secondaryDirection] + margin, safeAreaLengths[secondaryDirection] + margin + targetCenterDistanceFrom[secondaryDirection] - contentSize[sizeName] / 2);
- this._popover.style[primaryDirection] = primaryOffset + 'px';
- this._popover.style[secondaryDirection] = secondaryOffset + 'px';
-
- // Setting .popover__arrow position.
- this._arrow.style[secondaryDirection] = Math.max(radius, safeAreaLengths[secondaryDirection] + margin + targetCenterDistanceFrom[secondaryDirection] - secondaryOffset) + 'px';
- }
- }, {
- key: '_calculateDirections',
- value: function _calculateDirections(distance) {
- var options = (this.getAttribute('direction') || 'up down left right').split(/\s+/).map(function (e) {
- return positions[e];
- });
- var primary = options.sort(function (a, b) {
- return distance[a] - distance[b];
- })[0];
- var vertical = 'top' == primary || 'bottom' == primary;
- var secondary = void 0;
-
- if (vertical) {
- secondary = distance.left < distance.right ? 'left' : 'right';
- } else {
- secondary = distance.top < distance.bottom ? 'top' : 'bottom';
- }
-
- return { vertical: vertical, primary: primary, secondary: secondary };
- }
- }, {
- key: '_clearStyles',
- value: function _clearStyles() {
- var _this2 = this;
-
- this._currentDirection = null;
- ['top', 'bottom', 'left', 'right'].forEach(function (e) {
- _this2._arrow.style[e] = _this2._content.style[e] = _this2._popover.style[e] = '';
- util$1.removeModifier(_this2, e);
- });
- }
- }, {
- key: '_onChange',
- value: function _onChange() {
- var _this3 = this;
-
- setImmediate(function () {
- if (_this3._currentTarget) {
- _this3._positionPopover(_this3._currentTarget);
- }
- });
- }
- }, {
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
-
- if (this._popover && this._mask) {
- return;
- }
-
- var hasDefaultContainer = this._popover && this._content;
-
- if (hasDefaultContainer) {
-
- if (!this._mask) {
- var mask = document.createElement('div');
- mask.classList.add('popover-mask');
- this.insertBefore(mask, this.firstChild);
- }
-
- if (!this._arrow) {
- var arrow = document.createElement('div');
- arrow.classList.add('popover__arrow');
- this._popover.appendChild(arrow);
- }
- } else {
-
- var template = util$1.createFragment('\n <div class="popover-mask"></div>\n <div class="popover">\n <div class="popover__content"></div>\n <div class="popover__arrow"></div>\n </div>\n ');
- var content = template.querySelector('.popover__content');
-
- while (this.childNodes[0]) {
- content.appendChild(this.childNodes[0]);
- }
-
- this.appendChild(template);
- }
-
- // FIXME!
- if (this.hasAttribute('style')) {
- this._popover.setAttribute('style', this.getAttribute('style'));
- this.removeAttribute('style');
- }
-
- ModifierUtil.initModifier(this, this._scheme);
- }
-
- /**
- * @method show
- * @signature show(target, [options])
- * @param {String|Event|HTMLElement} target
- * [en]Target element. Can be either a CSS selector, an event object or a DOM element. It can be also provided as 'options.target' instead. [/en]
- * [ja]ポップオーバーのターゲットとなる要素を指定します。CSSセレクタかeventオブジェクトかDOM要素のいずれかを渡せます。[/ja]
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Use one of `"fade-ios"`, `"fade-md"`, `"none"` and `"default"`.[/en]
- * [ja]アニメーション名を指定します。"fade-ios", "fade-md", "none", "default"のいずれかを指定できます。[/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
- * @param {Function} [options.callback]
- * [en]This function is called after the popover has been revealed.[/en]
- * [ja]ポップオーバーが表示され終わった後に呼び出される関数オブジェクトを指定します。[/ja]
- * @description
- * [en]Open the popover and point it at a target. The target can be either an event, a CSS selector or a DOM element..[/en]
- * [ja]対象とする要素にポップオーバーを表示します。target引数には、$eventオブジェクトやDOMエレメントやCSSセレクタを渡すことが出来ます。[/ja]
- * @return {Promise}
- * [en]Resolves to the displayed element[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'show',
- value: function show(target) {
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- // Copy options and include options.target
- if (target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && !(target instanceof Event) && !(target instanceof HTMLElement)) {
- options = _extends({}, target);
- } else {
- options = _extends({}, options, { target: target });
- }
-
- if (typeof options.target === 'string') {
- options.target = document.querySelector(options.target);
- } else if (options.target instanceof Event) {
- options.target = options.target.target;
- }
-
- if (!(options.target instanceof HTMLElement)) {
- util$1.throw('Invalid target type or undefined');
- }
-
- return get(PopoverElement.prototype.__proto__ || Object.getPrototypeOf(PopoverElement.prototype), 'show', this).call(this, options);
- }
-
- /**
- * @method hide
- * @signature hide([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Use one of `"fade-ios"`, `"fade-md"`, `"none"` and `"default"`.[/en]
- * [ja]アニメーション名を指定します。"fade-ios", "fade-md", "none", "default"のいずれかを指定できます。[/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
- * @param {Function} [options.callback]
- * [en]This functions is called after the popover has been hidden.[/en]
- * [ja]ポップオーバーが隠れた後に呼び出される関数オブジェクトを指定します。[/ja]
- * @description
- * [en]Close the popover.[/en]
- * [ja]ポップオーバーを閉じます。[/ja]
- * @return {Promise}
- * [en]Resolves to the hidden element[/en]
- * [ja][/ja]
- */
-
- /**
- * @property visible
- * @readonly
- * @type {Boolean}
- * @description
- * [en]Whether the element is visible or not.[/en]
- * [ja]要素が見える場合に`true`。[/ja]
- */
-
- /**
- * @property cancelable
- * @type {Boolean}
- * @description
- * [en]
- * A boolean value that specifies whether the popover is cancelable or not.
- *
- * When the popover is cancelable it can be closed by tapping the background or by pressing the back button on Android devices.
- * [/en]
- * [ja][/ja]
- */
-
- /**
- * @property onDeviceBackButton
- * @type {Object}
- * @description
- * [en]Back-button handler.[/en]
- * [ja]バックボタンハンドラ。[/ja]
- */
-
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- var _this4 = this;
-
- get(PopoverElement.prototype.__proto__ || Object.getPrototypeOf(PopoverElement.prototype), 'connectedCallback', this).call(this);
-
- window.addEventListener('resize', this._boundOnChange, false);
- this._margin = this._margin || parseInt(window.getComputedStyle(this).getPropertyValue('top'));
- this._margin = this._margin || 6; // Fix for iframes
-
- contentReady(this, function () {
- _this4._radius = parseInt(window.getComputedStyle(_this4._content).getPropertyValue('border-top-left-radius'));
- });
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- get(PopoverElement.prototype.__proto__ || Object.getPrototypeOf(PopoverElement.prototype), 'disconnectedCallback', this).call(this);
- window.removeEventListener('resize', this._boundOnChange, false);
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- if (name === 'direction') {
- return this._boundOnChange();
- } else if (name === 'modifier') {
- this._currentDirection && util$1.addModifier(this, this._currentDirection);
- }
- get(PopoverElement.prototype.__proto__ || Object.getPrototypeOf(PopoverElement.prototype), 'attributeChangedCallback', this).call(this, name, last, current);
- }
-
- /**
- * @param {String} name
- * @param {PopoverAnimator} Animator
- */
-
- }, {
- key: '_scheme',
- get: function get$$1() {
- return scheme$19;
- }
- }, {
- key: '_mask',
- get: function get$$1() {
- return util$1.findChild(this, '.popover-mask');
- }
- }, {
- key: '_popover',
- get: function get$$1() {
- return util$1.findChild(this, '.popover');
- }
- }, {
- key: '_content',
- get: function get$$1() {
- return util$1.findChild(this._popover, '.popover__content');
- }
- }, {
- key: '_arrow',
- get: function get$$1() {
- return util$1.findChild(this._popover, '.popover__arrow');
- }
- }], [{
- key: 'registerAnimator',
- value: function registerAnimator(name, Animator) {
- if (!(Animator.prototype instanceof PopoverAnimator)) {
- util$1.throwAnimator('Popover');
- }
- _animatorDict$6[name] = Animator;
- }
- }, {
- key: 'observedAttributes',
- get: function get$$1() {
- return [].concat(toConsumableArray(get(PopoverElement.__proto__ || Object.getPrototypeOf(PopoverElement), 'observedAttributes', this)), ['direction']);
- }
- }, {
- key: 'animators',
- get: function get$$1() {
- return _animatorDict$6;
- }
- }, {
- key: 'PopoverAnimator',
- get: function get$$1() {
- return PopoverAnimator;
- }
- }]);
- return PopoverElement;
- }(BaseDialogElement);
-
- onsElements.Popover = PopoverElement;
- customElements.define('ons-popover', PopoverElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var scheme$20 = {
- '.progress-bar': 'progress-bar--*',
- '.progress-bar__primary': 'progress-bar--*__primary',
- '.progress-bar__secondary': 'progress-bar--*__secondary'
- };
-
- var template = util$1.createElement('\n <div class="progress-bar">\n <div class="progress-bar__secondary"></div>\n <div class="progress-bar__primary"></div>\n </div>\n');
-
- var INDET = 'indeterminate';
-
- /**
- * @element ons-progress-bar
- * @category visual
- * @modifier material
- * [en]Display a Material Design progress bar.[/en]
- * [ja]マテリアルデザインのスタイルでプログレスバーを表示します。[/ja]
- * @description
- * [en]
- * The component is used to display a linear progress bar. It can either display a progress bar that shows the user how much of a task has been completed. In the case where the percentage is not known it can be used to display an animated progress bar so the user can see that an operation is in progress.
- * [/en]
- * [ja][/ja]
- * @codepen zvQbGj
- * @tutorial vanilla/Reference/progress
- * @seealso ons-progress-circular
- * [en]The `<ons-progress-circular>` component displays a circular progress indicator.[/en]
- * [ja][/ja]
- * @example
- * <ons-progress-bar
- * value="55"
- * secondary-value="87">
- * </ons-progress-bar>
- *
- * <ons-progress-bar
- * indeterminate>
- * </ons-progress-bar>
- */
-
- var ProgressBarElement = function (_BaseElement) {
- inherits(ProgressBarElement, _BaseElement);
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]Change the appearance of the progress indicator.[/en]
- * [ja]プログレスインジケータの見た目を変更します。[/ja]
- */
-
- /**
- * @attribute value
- * @type {Number}
- * @description
- * [en]Current progress. Should be a value between 0 and 100.[/en]
- * [ja]現在の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
- */
-
- /**
- * @attribute secondary-value
- * @type {Number}
- * @description
- * [en]Current secondary progress. Should be a value between 0 and 100.[/en]
- * [ja]現在の2番目の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
- */
-
- /**
- * @attribute indeterminate
- * @description
- * [en]If this attribute is set, an infinite looping animation will be shown.[/en]
- * [ja]この属性が設定された場合、ループするアニメーションが表示されます。[/ja]
- */
-
- function ProgressBarElement() {
- classCallCheck(this, ProgressBarElement);
-
- var _this = possibleConstructorReturn(this, (ProgressBarElement.__proto__ || Object.getPrototypeOf(ProgressBarElement)).call(this));
-
- contentReady(_this, function () {
- return _this._compile();
- });
- return _this;
- }
-
- createClass(ProgressBarElement, [{
- key: '_compile',
- value: function _compile() {
- if (!this._isCompiled()) {
- this._template = template.cloneNode(true);
- } else {
- this._template = util$1.findChild(this, '.progress-bar');
- }
-
- this._primary = util$1.findChild(this._template, '.progress-bar__primary');
- this._secondary = util$1.findChild(this._template, '.progress-bar__secondary');
-
- this._updateDeterminate();
- this._updateValue();
-
- this.appendChild(this._template);
-
- autoStyle.prepare(this);
- ModifierUtil.initModifier(this, scheme$20);
- }
- }, {
- key: '_isCompiled',
- value: function _isCompiled() {
- if (!util$1.findChild(this, '.progress-bar')) {
- return false;
- }
-
- var barElement = util$1.findChild(this, '.progress-bar');
-
- if (!util$1.findChild(barElement, '.progress-bar__secondary')) {
- return false;
- }
-
- if (!util$1.findChild(barElement, '.progress-bar__primary')) {
- return false;
- }
-
- return true;
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- if (name === 'modifier') {
- ModifierUtil.onModifierChanged(last, current, this, scheme$20);
- this.hasAttribute(INDET) && this._updateDeterminate();
- } else if (name === 'value' || name === 'secondary-value') {
- this._updateValue();
- } else if (name === INDET) {
- this._updateDeterminate();
- }
- }
- }, {
- key: '_updateDeterminate',
- value: function _updateDeterminate() {
- var _this2 = this;
-
- contentReady(this, function () {
- return util$1.toggleModifier(_this2, INDET, { force: _this2.hasAttribute(INDET) });
- });
- }
- }, {
- key: '_updateValue',
- value: function _updateValue() {
- var _this3 = this;
-
- contentReady(this, function () {
- _this3._primary.style.width = _this3.hasAttribute('value') ? _this3.getAttribute('value') + '%' : '0%';
- _this3._secondary.style.width = _this3.hasAttribute('secondary-value') ? _this3.getAttribute('secondary-value') + '%' : '0%';
- });
- }
-
- /**
- * @property value
- * @type {Number}
- * @description
- * [en]Current progress. Should be a value between 0 and 100.[/en]
- * [ja]現在の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
- */
-
- }, {
- key: 'value',
- set: function set$$1(value) {
- if (typeof value !== 'number' || value < 0 || value > 100) {
- util$1.throw('Invalid value');
- }
-
- this.setAttribute('value', Math.floor(value));
- },
- get: function get$$1() {
- return parseInt(this.getAttribute('value') || '0');
- }
-
- /**
- * @property secondaryValue
- * @type {Number}
- * @description
- * [en]Current secondary progress. Should be a value between 0 and 100.[/en]
- * [ja]現在の2番目の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
- */
-
- }, {
- key: 'secondaryValue',
- set: function set$$1(value) {
- if (typeof value !== 'number' || value < 0 || value > 100) {
- util$1.throw('Invalid value');
- }
-
- this.setAttribute('secondary-value', Math.floor(value));
- },
- get: function get$$1() {
- return parseInt(this.getAttribute('secondary-value') || '0');
- }
-
- /**
- * @property indeterminate
- * @type {Boolean}
- * @description
- * [en]If this property is `true`, an infinite looping animation will be shown.[/en]
- * [ja]この属性が設定された場合、ループするアニメーションが表示されます。[/ja]
- */
-
- }, {
- key: 'indeterminate',
- set: function set$$1(value) {
- if (value) {
- this.setAttribute(INDET, '');
- } else {
- this.removeAttribute(INDET);
- }
- },
- get: function get$$1() {
- return this.hasAttribute(INDET);
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'value', 'secondary-value', INDET];
- }
- }]);
- return ProgressBarElement;
- }(BaseElement);
-
- onsElements.ProgressBar = ProgressBarElement;
- customElements.define('ons-progress-bar', ProgressBarElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var scheme$21 = {
- '.progress-circular': 'progress-circular--*',
- '.progress-circular__background': 'progress-circular--*__background',
- '.progress-circular__primary': 'progress-circular--*__primary',
- '.progress-circular__secondary': 'progress-circular--*__secondary'
- };
-
- var template$1 = util$1.createElement('\n <svg class="progress-circular">\n <circle class="progress-circular__background" />\n <circle class="progress-circular__secondary" cx="50%" cy="50%" r="40%" />\n <circle class="progress-circular__primary" cx="50%" cy="50%" r="40%" />\n </svg>\n');
-
- var INDET$1 = 'indeterminate';
-
- /**
- * @element ons-progress-circular
- * @category visual
- * @description
- * [en]
- * This component displays a circular progress indicator. It can either be used to show how much of a task has been completed or to show a looping animation to indicate that an operation is currently running.
- * [/en]
- * [ja][/ja]
- * @codepen EVzMjR
- * @tutorial vanilla/Reference/progress-circular
- * @seealso ons-progress-bar
- * [en]The `<ons-progress-bar>` component displays a bar progress indicator.[/en]
- * [ja][/ja]
- * @example
- * <ons-progress-circular
- * value="55"
- * secondary-value="87">
- * </ons-progress-circular>
- *
- * <ons-progress-circular
- * indeterminate>
- * </ons-progress-circular>
- */
-
- var ProgressCircularElement = function (_BaseElement) {
- inherits(ProgressCircularElement, _BaseElement);
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]Change the appearance of the progress indicator.[/en]
- * [ja]プログレスインジケータの見た目を変更します。[/ja]
- */
-
- /**
- * @attribute value
- * @type {Number}
- * @description
- * [en]Current progress. Should be a value between 0 and 100.[/en]
- * [ja]現在の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
- */
-
- /**
- * @attribute secondary-value
- * @type {Number}
- * @description
- * [en]Current secondary progress. Should be a value between 0 and 100.[/en]
- * [ja]現在の2番目の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
- */
-
- /**
- * @attribute indeterminate
- * @description
- * [en]If this attribute is set, an infinite looping animation will be shown.[/en]
- * [ja]この属性が設定された場合、ループするアニメーションが表示されます。[/ja]
- */
-
- function ProgressCircularElement() {
- classCallCheck(this, ProgressCircularElement);
-
- var _this = possibleConstructorReturn(this, (ProgressCircularElement.__proto__ || Object.getPrototypeOf(ProgressCircularElement)).call(this));
-
- contentReady(_this, function () {
- return _this._compile();
- });
- return _this;
- }
-
- createClass(ProgressCircularElement, [{
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- if (name === 'modifier') {
- ModifierUtil.onModifierChanged(last, current, this, scheme$21);
- this.hasAttribute(INDET$1) && this._updateDeterminate();
- } else if (name === 'value' || name === 'secondary-value') {
- this._updateValue();
- } else if (name === INDET$1) {
- this._updateDeterminate();
- }
- }
- }, {
- key: '_updateDeterminate',
- value: function _updateDeterminate() {
- var _this2 = this;
-
- contentReady(this, function () {
- return util$1.toggleModifier(_this2, INDET$1, { force: _this2.hasAttribute(INDET$1) });
- });
- }
- }, {
- key: '_updateValue',
- value: function _updateValue() {
- var _this3 = this;
-
- if (this.hasAttribute('value')) {
- contentReady(this, function () {
- var per = Math.ceil(_this3.getAttribute('value') * 251.32 * 0.01);
- _this3._primary.style['stroke-dasharray'] = per + '%, 251.32%';
- });
- }
- if (this.hasAttribute('secondary-value')) {
- contentReady(this, function () {
- var per = Math.ceil(_this3.getAttribute('secondary-value') * 251.32 * 0.01);
- _this3._secondary.style.display = null;
- _this3._secondary.style['stroke-dasharray'] = per + '%, 251.32%';
- });
- } else {
- contentReady(this, function () {
- _this3._secondary.style.display = 'none';
- });
- }
- }
-
- /**
- * @property value
- * @type {Number}
- * @description
- * [en]Current progress. Should be a value between 0 and 100.[/en]
- * [ja]現在の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
- */
-
- }, {
- key: '_compile',
- value: function _compile() {
- if (this._isCompiled()) {
- this._template = util$1.findChild(this, '.progress-circular');
- } else {
- this._template = template$1.cloneNode(true);
- }
-
- this._primary = util$1.findChild(this._template, '.progress-circular__primary');
- this._secondary = util$1.findChild(this._template, '.progress-circular__secondary');
-
- this._updateDeterminate();
- this._updateValue();
-
- this.appendChild(this._template);
-
- autoStyle.prepare(this);
- ModifierUtil.initModifier(this, scheme$21);
- }
- }, {
- key: '_isCompiled',
- value: function _isCompiled() {
- if (!util$1.findChild(this, '.progress-circular')) {
- return false;
- }
-
- var svg = util$1.findChild(this, '.progress-circular');
-
- if (!util$1.findChild(svg, '.progress-circular__secondary')) {
- return false;
- }
-
- if (!util$1.findChild(svg, '.progress-circular__primary')) {
- return false;
- }
-
- return true;
- }
- }, {
- key: 'value',
- set: function set$$1(value) {
- if (typeof value !== 'number' || value < 0 || value > 100) {
- util$1.throw('Invalid value');
- }
-
- this.setAttribute('value', Math.floor(value));
- },
- get: function get$$1() {
- return parseInt(this.getAttribute('value') || '0');
- }
-
- /**
- * @property secondaryValue
- * @type {Number}
- * @description
- * [en]Current secondary progress. Should be a value between 0 and 100.[/en]
- * [ja]現在の2番目の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
- */
-
- }, {
- key: 'secondaryValue',
- set: function set$$1(value) {
- if (typeof value !== 'number' || value < 0 || value > 100) {
- util$1.throw('Invalid value');
- }
-
- this.setAttribute('secondary-value', Math.floor(value));
- },
- get: function get$$1() {
- return parseInt(this.getAttribute('secondary-value') || '0');
- }
-
- /**
- * @property indeterminate
- * @type {Boolean}
- * @description
- * [en]If this property is `true`, an infinite looping animation will be shown.[/en]
- * [ja]この属性が設定された場合、ループするアニメーションが表示されます。[/ja]
- */
-
- }, {
- key: 'indeterminate',
- set: function set$$1(value) {
- if (value) {
- this.setAttribute(INDET$1, '');
- } else {
- this.removeAttribute(INDET$1);
- }
- },
- get: function get$$1() {
- return this.hasAttribute(INDET$1);
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'value', 'secondary-value', INDET$1];
- }
- }]);
- return ProgressCircularElement;
- }(BaseElement);
-
- onsElements.ProgressCircular = ProgressCircularElement;
- customElements.define('ons-progress-circular', ProgressCircularElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var STATE_INITIAL = 'initial';
- var STATE_PREACTION = 'preaction';
- var STATE_ACTION = 'action';
-
- var throwType = function throwType(el, type) {
- return util$1.throw('"' + el + '" must be ' + type);
- };
-
- /**
- * @element ons-pull-hook
- * @category control
- * @description
- * [en]
- * Component that adds **Pull to refresh** functionality to an `<ons-page>` element.
- *
- * It can be used to perform a task when the user pulls down at the top of the page. A common usage is to refresh the data displayed in a page.
- * [/en]
- * [ja][/ja]
- * @codepen WbJogM
- * @tutorial vanilla/Reference/pull-hook
- * @example
- * <ons-page>
- * <ons-pull-hook>
- * Release to refresh
- * </ons-pull-hook>
- * </ons-page>
- *
- * <script>
- * document.querySelector('ons-pull-hook').onAction = function(done) {
- * setTimeout(done, 1000);
- * };
- * </script>
- */
-
- var PullHookElement = function (_BaseElement) {
- inherits(PullHookElement, _BaseElement);
-
- /**
- * @event changestate
- * @description
- * [en]Fired when the state is changed. The state can be either "initial", "preaction" or "action".[/en]
- * [ja]コンポーネントの状態が変わった場合に発火します。状態は、"initial", "preaction", "action"のいずれかです。[/ja]
- * @param {Object} event
- * [en]Event object.[/en]
- * [ja]イベントオブジェクト。[/ja]
- * @param {Object} event.pullHook
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- * @param {String} event.state
- * [en]Current state.[/en]
- * [ja]現在の状態名を参照できます。[/ja]
- */
-
- /**
- * @attribute disabled
- * @description
- * [en]If this attribute is set the "pull-to-refresh" functionality is disabled.[/en]
- * [ja]この属性がある時、disabled状態になりアクションが実行されなくなります[/ja]
- */
-
- /**
- * @attribute height
- * @type {String}
- * @description
- * [en]Specify the height of the component. When pulled down further than this value it will switch to the "preaction" state. The default value is "64px".[/en]
- * [ja]コンポーネントの高さを指定します。この高さ以上にpull downすると"preaction"状態に移行します。デフォルトの値は"64px"です。[/ja]
- */
-
- /**
- * @attribute threshold-height
- * @type {String}
- * @description
- * [en]Specify the threshold height. The component automatically switches to the "action" state when pulled further than this value. The default value is "96px". A negative value will disable this property. If this value is lower than the height, it will skip "preaction" state.[/en]
- * [ja]閾値となる高さを指定します。この値で指定した高さよりもpull downすると、このコンポーネントは自動的に"action"状態に移行します。[/ja]
- */
-
- /**
- * @attribute fixed-content
- * @description
- * [en]If this attribute is set the content of the page will not move when pulling.[/en]
- * [ja]この属性がある時、プルフックが引き出されている時にもコンテンツは動きません。[/ja]
- */
-
- function PullHookElement() {
- classCallCheck(this, PullHookElement);
-
- var _this = possibleConstructorReturn(this, (PullHookElement.__proto__ || Object.getPrototypeOf(PullHookElement)).call(this));
-
- _this._shouldFixScroll = util$1.globals.isUIWebView;
-
- _this._onDrag = _this._onDrag.bind(_this);
- _this._onDragStart = _this._onDragStart.bind(_this);
- _this._onDragEnd = _this._onDragEnd.bind(_this);
- _this._onScroll = _this._onScroll.bind(_this);
-
- _this._setState(STATE_INITIAL, true);
- _this._hide(); // Fix for transparent toolbar transitions
- return _this;
- }
-
- createClass(PullHookElement, [{
- key: '_setStyle',
- value: function _setStyle() {
- var height = this.height + 'px';
- styler(this, { height: height, lineHeight: height });
- this.style.display === '' && this._show();
- }
- }, {
- key: '_onScroll',
- value: function _onScroll(event) {
- var element = this._pageElement;
-
- if (element.scrollTop < 0) {
- element.scrollTop = 0;
- }
- }
- }, {
- key: '_canConsumeGesture',
- value: function _canConsumeGesture(gesture) {
- return gesture.direction === 'up' || gesture.direction === 'down';
- }
- }, {
- key: '_onDragStart',
- value: function _onDragStart(event) {
- var _this2 = this;
-
- if (!event.gesture || this.disabled) {
- return;
- }
-
- var tapY = event.gesture.center.clientY + this._pageElement.scrollTop;
- var maxY = window.innerHeight;
- // Only use drags that start near the pullHook to reduce flickerings
- var draggableAreaRatio = this._shouldFixScroll ? .8 : 1;
-
- this._ignoreDrag = event.consumed || tapY > maxY * draggableAreaRatio;
-
- if (!this._ignoreDrag) {
- var consume = event.consume;
- event.consume = function () {
- consume && consume();
- _this2._ignoreDrag = true;
- // This elements resizes .page__content so it is safer
- // to hide it when other components are dragged.
- _this2._hide();
- };
-
- if (this._canConsumeGesture(event.gesture)) {
- consume && consume();
- event.consumed = true;
- this._show(); // Not enough due to 'dragLockAxis'
- }
- }
-
- this._startScroll = this._pageElement.scrollTop;
- }
- }, {
- key: '_onDrag',
- value: function _onDrag(event) {
- var _this3 = this;
-
- if (!event.gesture || this.disabled || this._ignoreDrag || !this._canConsumeGesture(event.gesture)) {
- return;
- }
-
- // Necessary due to 'dragLockAxis' (25px)
- if (this.style.display === 'none') {
- this._show();
- }
-
- event.stopPropagation();
-
- var tapY = event.gesture.center.clientY + this._pageElement.scrollTop;
- var maxY = window.innerHeight;
-
- // Hack to make it work on Android 4.4 WebView and iOS UIWebView. Scrolls manually
- // near the top of the page so there will be no inertial scroll when scrolling down.
- // Allowing default scrolling will kill all 'touchmove' events.
- if (this._shouldFixScroll) {
- this._pageElement.scrollTop = this._startScroll - event.gesture.deltaY;
- // Allow inertia when scrolling down below 50% of the view to reduce flickerings
- if (event.gesture.interimDirection !== 'up' || tapY <= maxY * .5) {
- event.gesture.preventDefault();
- }
- }
-
- var scroll = Math.max(event.gesture.deltaY - this._startScroll, 0);
- if (scroll !== this._currentTranslation) {
-
- var th = this.thresholdHeight;
- if (th > 0 && scroll >= th) {
- event.gesture.stopDetect();
- setImmediate(function () {
- return _this3._finish();
- });
- } else if (scroll >= this.height) {
- this._setState(STATE_PREACTION);
- } else {
- this._setState(STATE_INITIAL);
- }
-
- this._translateTo(scroll);
- }
- }
- }, {
- key: '_onDragEnd',
- value: function _onDragEnd(event) {
- if (!event.gesture || this.disabled || this._ignoreDrag) {
- return;
- }
-
- event.stopPropagation();
-
- if (this._currentTranslation > 0) {
- var scroll = this._currentTranslation;
-
- if (scroll > this.height) {
- this._finish();
- } else {
- this._translateTo(0, { animate: true });
- }
- }
- }
-
- /**
- * @property onAction
- * @type {Function}
- * @description
- * [en]This will be called in the `action` state if it exists. The function will be given a `done` callback as it's first argument.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: '_finish',
- value: function _finish() {
- var _this4 = this;
-
- this._setState(STATE_ACTION);
- this._translateTo(this.height, { animate: true });
- var action = this.onAction || function (done) {
- return done();
- };
- action(function () {
- _this4._translateTo(0, { animate: true });
- _this4._setState(STATE_INITIAL);
- });
- }
-
- /**
- * @property height
- * @type {Number}
- * @description
- * [en]The height of the pull hook in pixels. The default value is `64px`.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: '_setState',
- value: function _setState(state, noEvent) {
- var lastState = this.state;
-
- this.setAttribute('state', state);
-
- if (!noEvent && lastState !== this.state) {
- util$1.triggerElementEvent(this, 'changestate', {
- pullHook: this,
- state: state,
- lastState: lastState
- });
- }
- }
-
- /**
- * @property state
- * @readonly
- * @type {String}
- * @description
- * [en]Current state of the element.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: '_show',
- value: function _show() {
- var _this5 = this;
-
- // Run asyncrhonously to avoid conflicts with Animit's style clean
- setImmediate(function () {
- _this5.style.display = '';
- if (_this5._pageElement) {
- _this5._pageElement.style.marginTop = '-' + _this5.height + 'px';
- }
- });
- }
- }, {
- key: '_hide',
- value: function _hide() {
- this.style.display = 'none';
- if (this._pageElement) {
- this._pageElement.style.marginTop = '';
- }
- }
-
- /**
- * @param {Number} scroll
- * @param {Object} options
- * @param {Function} [options.callback]
- */
-
- }, {
- key: '_translateTo',
- value: function _translateTo(scroll) {
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- if (this._currentTranslation == 0 && scroll == 0) {
- return;
- }
-
- this._currentTranslation = scroll;
- var opt = options.animate ? { duration: .3, timing: 'cubic-bezier(.1, .7, .1, 1)' } : {};
- this._onPull && this._onPull((scroll / this.height).toFixed(2), opt);
- var scrollElement = this.hasAttribute('fixed-content') ? this : this._pageElement;
-
- Animit(scrollElement).queue({ transform: 'translate3d(0px, ' + scroll + 'px, 0px)' }, opt).play(function () {
- scroll === 0 && styler.clear(scrollElement, 'transition transform');
- options.callback instanceof Function && options.callback();
- });
- }
- }, {
- key: '_disableDragLock',
- value: function _disableDragLock() {
- // e2e tests need it
- this._dragLockDisabled = true;
- this._setupListeners(true);
- }
- }, {
- key: '_setupListeners',
- value: function _setupListeners(add) {
- var _this6 = this;
-
- var scrollToggle = function scrollToggle(action) {
- return _this6._pageElement[action + 'EventListener']('scroll', _this6._onScroll, false);
- };
- var gdToggle = function gdToggle(action) {
- var passive = { passive: true };
- _this6._gestureDetector[action]('drag', _this6._onDrag, passive);
- _this6._gestureDetector[action]('dragstart', _this6._onDragStart, passive);
- _this6._gestureDetector[action]('dragend', _this6._onDragEnd, passive);
- };
-
- if (this._gestureDetector) {
- gdToggle('off');
- this._gestureDetector.dispose();
- this._gestureDetector = null;
- }
- scrollToggle('remove');
-
- if (add) {
- this._gestureDetector = new GestureDetector(this._pageElement, {
- dragMinDistance: 1,
- dragDistanceCorrection: false,
- dragLockToAxis: !this._dragLockDisabled,
- passive: !this._shouldFixScroll
- });
-
- gdToggle('on');
- scrollToggle('add');
- }
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- this._currentTranslation = 0;
- this._pageElement = this.parentNode;
-
- this._setupListeners(true);
- this._setStyle();
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- this._hide();
- this._setupListeners(false);
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- if (name === 'height' && this._pageElement) {
- this._setStyle();
- }
- }
- }, {
- key: 'onAction',
- get: function get$$1() {
- return this._onAction;
- },
- set: function set$$1(value) {
- if (value && !(value instanceof Function)) {
- throwType('onAction', 'function or null');
- }
- this._onAction = value;
- }
-
- /**
- * @property onPull
- * @type {Function}
- * @description
- * [en]Hook called whenever the user pulls the element. It gets the pulled distance ratio (scroll / height) and an animationOptions object as arguments.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'onPull',
- get: function get$$1() {
- return this._onPull;
- },
- set: function set$$1(value) {
- if (value && !(value instanceof Function)) {
- throwType('onPull', 'function or null');
- }
- this._onPull = value;
- }
- }, {
- key: 'height',
- set: function set$$1(value) {
- if (!util$1.isInteger(value)) {
- throwType('height', 'integer');
- }
-
- this.setAttribute('height', value + 'px');
- },
- get: function get$$1() {
- return parseInt(this.getAttribute('height') || '64', 10);
- }
-
- /**
- * @property thresholdHeight
- * @type {Number}
- * @description
- * [en]The thresholdHeight of the pull hook in pixels. The default value is `96px`.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'thresholdHeight',
- set: function set$$1(value) {
- if (!util$1.isInteger(value)) {
- throwType('thresholdHeight', 'integer');
- }
-
- this.setAttribute('threshold-height', value + 'px');
- },
- get: function get$$1() {
- return parseInt(this.getAttribute('threshold-height') || '96', 10);
- }
- }, {
- key: 'state',
- get: function get$$1() {
- return this.getAttribute('state');
- }
-
- /**
- * @property pullDistance
- * @readonly
- * @type {Number}
- * @description
- * [en]The current number of pixels the pull hook has moved.[/en]
- * [ja]現在のプルフックが引き出された距離をピクセル数。[/ja]
- */
-
- }, {
- key: 'pullDistance',
- get: function get$$1() {
- return this._currentTranslation;
- }
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the element is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- }, {
- key: 'disabled',
- set: function set$$1(value) {
- return util$1.toggleAttribute(this, 'disabled', value);
- },
- get: function get$$1() {
- return this.hasAttribute('disabled');
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['height'];
- }
- }, {
- key: 'events',
- get: function get$$1() {
- return ['changestate'];
- }
- }]);
- return PullHookElement;
- }(BaseElement);
-
- onsElements.PullHook = PullHookElement;
- customElements.define('ons-pull-hook', PullHookElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
- var scheme$22 = {
- '': 'range--*',
- '.range__input': 'range--*__input',
- '.range__focus-ring': 'range--*__focus-ring'
- };
-
- var activeClassToken = 'range__input--active';
-
- /**
- * @element ons-range
- * @category form
- * @modifier material
- * [en]Material Design slider[/en]
- * [ja][/ja]
- * @description
- * [en]
- * Range input component. Used to display a draggable slider.
- *
- * Works very similar to the `<input type="range">` element.
- * [/en]
- * [ja][/ja]
- * @codepen xZQomM
- * @tutorial vanilla/Reference/range
- * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
- * @seealso ons-input
- * [en]The `<ons-input>` component is used to display text inputs, radio buttons and checkboxes.[/en]
- * [ja][/ja]
- * @example
- * <ons-range value="20"></ons-range>
- * <ons-range modifier="material" value="10"></range>
- */
-
- var RangeElement = function (_BaseInputElement) {
- inherits(RangeElement, _BaseInputElement);
-
- function RangeElement() {
- classCallCheck(this, RangeElement);
-
- var _this = possibleConstructorReturn(this, (RangeElement.__proto__ || Object.getPrototypeOf(RangeElement)).call(this));
-
- _this._onMouseDown = _this._onMouseDown.bind(_this);
- _this._onMouseUp = _this._onMouseUp.bind(_this);
- _this._onTouchStart = _this._onTouchStart.bind(_this);
- _this._onTouchEnd = _this._onTouchEnd.bind(_this);
- _this._onInput = _this._update.bind(_this);
- _this._onDragstart = _this._onDragstart.bind(_this);
- _this._onDragend = _this._onDragend.bind(_this);
- return _this;
- }
-
- createClass(RangeElement, [{
- key: '_compile',
- value: function _compile() {
- get(RangeElement.prototype.__proto__ || Object.getPrototypeOf(RangeElement.prototype), '_compile', this).call(this);
- this._updateDisabled(this.hasAttribute('disabled'));
- }
-
- /* Inherited props */
-
- }, {
- key: '_update',
- value: function _update() {
- var input = this._input;
- var focusRing = this._focusRing;
-
- input.style.backgroundSize = 100 * this._ratio + '% 2px';
- focusRing.value = this.value;
-
- // NOTE: "_zero" attribute is used for CSS styling.
- if (input.min === '' && input.value === '0' || input.min === input.value) {
- input.setAttribute('_zero', '');
- } else {
- input.removeAttribute('_zero');
- }
-
- ['min', 'max'].forEach(function (attr) {
- return focusRing[attr] = input[attr];
- });
- }
- }, {
- key: '_onMouseDown',
-
-
- /* Own props */
-
- value: function _onMouseDown(e) {
- var _this2 = this;
-
- this._input.classList.add(activeClassToken);
- setImmediate(function () {
- return _this2._input.focus();
- });
- }
- }, {
- key: '_onTouchStart',
- value: function _onTouchStart(e) {
- this._onMouseDown();
- }
- }, {
- key: '_onMouseUp',
- value: function _onMouseUp(e) {
- this._input.classList.remove(activeClassToken);
- }
- }, {
- key: '_onTouchEnd',
- value: function _onTouchEnd(e) {
- this._onMouseUp(e);
- }
- }, {
- key: '_onDragstart',
- value: function _onDragstart(e) {
- e.consumed = true;
- e.gesture.stopPropagation();
- this._input.classList.add(activeClassToken);
- this.addEventListener('drag', this._onDrag);
- }
- }, {
- key: '_onDrag',
- value: function _onDrag(e) {
- e.stopPropagation();
- }
- }, {
- key: '_onDragend',
- value: function _onDragend(e) {
- this._input.classList.remove(activeClassToken);
- this.removeEventListener('drag', this._onDrag);
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- if (name === 'disabled') {
- this._updateDisabled(current);
- }
- get(RangeElement.prototype.__proto__ || Object.getPrototypeOf(RangeElement.prototype), 'attributeChangedCallback', this).call(this, name, last, current);
- }
-
- /**
- * @param {boolean} disabled
- */
-
- }, {
- key: '_updateDisabled',
- value: function _updateDisabled(disabled) {
- if (disabled) {
- this.classList.add('range--disabled');
- } else {
- this.classList.remove('range--disabled');
- }
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- this._setupListeners(true);
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- this._setupListeners(false);
- }
- }, {
- key: '_setupListeners',
- value: function _setupListeners(add) {
- var action = (add ? 'add' : 'remove') + 'EventListener';
- util$1[action](this, 'touchstart', this._onTouchStart, { passive: true });
- this[action]('mousedown', this._onMouseDown);
- this[action]('mouseup', this._onMouseUp);
- this[action]('touchend', this._onTouchEnd);
- this[action]('dragstart', this._onDragstart);
- this[action]('dragend', this._onDragend);
- this[action]('input', this._onInput);
- }
-
- /**
- * @attribute disabled
- * @description
- * [en]Whether the element is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the element is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- /**
- * @property value
- * @type {Number}
- * @description
- * [en]Current value.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: '_scheme',
- get: function get$$1() {
- return scheme$22;
- }
- }, {
- key: '_template',
- get: function get$$1() {
- return '\n <input type="' + this.type + '" class="' + this._defaultClassName + '__input">\n <input type="range" class="range__focus-ring" tabIndex="-1">\n ';
- }
- }, {
- key: '_defaultClassName',
- get: function get$$1() {
- return 'range';
- }
- }, {
- key: 'type',
- get: function get$$1() {
- return 'range';
- }
- }, {
- key: '_focusRing',
- get: function get$$1() {
- return this.children[1];
- }
- }, {
- key: '_ratio',
- get: function get$$1() {
- // Returns the current ratio.
- var min = this._input.min === '' ? 0 : parseInt(this._input.min);
- var max = this._input.max === '' ? 100 : parseInt(this._input.max);
-
- return (this.value - min) / (max - min);
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['disabled'].concat(toConsumableArray(BaseInputElement.observedAttributes));
- }
- }]);
- return RangeElement;
- }(BaseInputElement);
-
- onsElements.Range = RangeElement;
- customElements.define('ons-range', RangeElement);
-
- /*
- Copyright 2013-2016 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * @class AnimatorCSS - implementation of Animator class using css transitions
- */
-
- var AnimatorCSS = function () {
- createClass(AnimatorCSS, [{
- key: 'animate',
-
-
- /**
- * @method animate
- * @desc main animation function
- * @param {Element} element
- * @param {Object} finalCSS
- * @param {number} [duration=200] - duration in milliseconds
- * @return {Object} result
- * @return {Function} result.then(callback) - sets a callback to be executed after the animation has stopped
- * @return {Function} result.stop(options) - stops the animation; if options.stopNext is true then it doesn't call the callback
- * @return {Function} result.finish(ms) - finishes the animation in the specified time in milliseconds
- * @return {Function} result.speed(ms) - sets the animation speed so that it finishes as if the original duration was the one specified here
- * @example
- * ````
- * var result = animator.animate(el, {opacity: 0.5}, 1000);
- *
- * el.addEventListener('click', function(e){
- * result.speed(200).then(function(){
- * console.log('done');
- * });
- * }, 300);
- * ````
- */
- value: function animate(el, final) {
- var duration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 200;
-
- var start = new Date().getTime(),
- initial = {},
- stopped = false,
- next = false,
- timeout = false,
- properties = Object.keys(final);
-
- var updateStyles = function updateStyles() {
- var s = window.getComputedStyle(el);
- properties.forEach(s.getPropertyValue.bind(s));
- s = el.offsetHeight;
- };
-
- var result = {
- stop: function stop() {
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
-
- timeout && clearTimeout(timeout);
- var k = Math.min(1, (new Date().getTime() - start) / duration);
- properties.forEach(function (i) {
- el.style[i] = (1 - k) * initial[i] + k * final[i] + (i == 'opacity' ? '' : 'px');
- });
- el.style.transitionDuration = '0s';
-
- if (options.stopNext) {
- next = false;
- } else if (!stopped) {
- stopped = true;
- next && next();
- }
- return result;
- },
- then: function then(cb) {
- next = cb;
- if (stopped) {
- next && next();
- }
- return result;
- },
- speed: function speed(newDuration) {
- if (internal$1.config.animationsDisabled) {
- newDuration = 0;
- }
- if (!stopped) {
- timeout && clearTimeout(timeout);
-
- var passed = new Date().getTime() - start;
- var k = passed / duration;
- var remaining = newDuration * (1 - k);
-
- properties.forEach(function (i) {
- el.style[i] = (1 - k) * initial[i] + k * final[i] + (i == 'opacity' ? '' : 'px');
- });
-
- updateStyles();
-
- start = el.speedUpTime;
- duration = remaining;
-
- el.style.transitionDuration = duration / 1000 + 's';
-
- properties.forEach(function (i) {
- el.style[i] = final[i] + (i == 'opacity' ? '' : 'px');
- });
-
- timeout = setTimeout(result.stop, remaining);
- }
- return result;
- },
- finish: function finish() {
- var milliseconds = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 50;
-
- var k = (new Date().getTime() - start) / duration;
-
- result.speed(milliseconds / (1 - k));
- return result;
- }
- };
-
- if (el.hasAttribute('disabled') || stopped || internal$1.config.animationsDisabled) {
- return result;
- }
-
- var style = window.getComputedStyle(el);
- properties.forEach(function (e) {
- var v = parseFloat(style.getPropertyValue(e));
- initial[e] = isNaN(v) ? 0 : v;
- });
-
- if (!stopped) {
- el.style.transitionProperty = properties.join(',');
- el.style.transitionDuration = duration / 1000 + 's';
-
- properties.forEach(function (e) {
- el.style[e] = final[e] + (e == 'opacity' ? '' : 'px');
- });
- }
-
- timeout = setTimeout(result.stop, duration);
- this._onStopAnimations(el, result.stop);
-
- return result;
- }
- }]);
-
- function AnimatorCSS() {
- classCallCheck(this, AnimatorCSS);
-
- this._queue = [];
- this._index = 0;
- }
-
- createClass(AnimatorCSS, [{
- key: '_onStopAnimations',
- value: function _onStopAnimations(el, listener) {
- var queue = this._queue;
- var i = this._index++;
- queue[el] = queue[el] || [];
- queue[el][i] = function (options) {
- delete queue[el][i];
- if (queue[el] && queue[el].length == 0) {
- delete queue[el];
- }
- return listener(options);
- };
- }
-
- /**
- * @method stopAnimations
- * @desc stops active animations on a specified element
- * @param {Element|Array} element - element or array of elements
- * @param {Object} [options={}]
- * @param {Boolean} [options.stopNext] - the callbacks after the animations won't be called if this option is true
- */
-
- }, {
- key: 'stopAnimations',
- value: function stopAnimations(el) {
- var _this = this;
-
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- if (Array.isArray(el)) {
- return el.forEach(function (el) {
- _this.stopAnimations(el, options);
- });
- }
-
- (this._queue[el] || []).forEach(function (e) {
- e(options || {});
- });
- }
-
- /**
- * @method stopAll
- * @desc stops all active animations
- * @param {Object} [options={}]
- * @param {Boolean} [options.stopNext] - the callbacks after the animations won't be called if this option is true
- */
-
- }, {
- key: 'stopAll',
- value: function stopAll() {
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
-
- this.stopAnimations(Object.keys(this._queue), options);
- }
-
- /**
- * @method fade
- * @desc fades the element (short version for animate(el, {opacity: 0}))
- * @param {Element} element
- * @param {number} [duration=200]
- */
-
- }, {
- key: 'fade',
- value: function fade(el) {
- var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;
-
- return this.animate(el, { opacity: 0 }, duration);
- }
- }]);
- return AnimatorCSS;
- }();
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var defaultClassName$11 = 'ripple';
- var scheme$23 = {
- '': 'ripple--*',
- '.ripple__wave': 'ripple--*__wave',
- '.ripple__background': 'ripple--*__background'
- };
-
- /**
- * @element ons-ripple
- * @category visual
- * @description
- * [en]
- * Adds a Material Design "ripple" effect to an element. The ripple effect will spread from the position where the user taps.
- *
- * Some elements such as `<ons-button>` and `<ons-fab>` support a `ripple` attribute.
- * [/en]
- * [ja]マテリアルデザインのリップル効果をDOM要素に追加します。[/ja]
- * @codepen wKQWdZ
- * @tutorial vanilla/Reference/ripple
- * @modifier light-gray
- * [en]Change the color of effects to light gray.[/en]
- * [ja]エフェクトの色が明るい灰色になります。[/ja]
- * @guide theming.html#cross-platform-styling-autostyling
- * [en]Cross platform styling[/en]
- * [ja]Cross platform styling[/ja]
- * @example
- * <div class="my-div">
- * <ons-ripple></ons-ripple>
- * </div>
- *
- * @example
- * <ons-button ripple>Click me!</ons-button>
- */
-
- var RippleElement = function (_BaseElement) {
- inherits(RippleElement, _BaseElement);
-
- /**
- * @attribute color
- * @type {String}
- * @description
- * [en]Color of the ripple effect.[/en]
- * [ja]リップルエフェクトの色を指定します。[/ja]
- */
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the ripple effect.[/en]
- * [ja]エフェクトの表現を指定します。[/ja]
- */
-
- /**
- * @attribute background
- * @type {String}
- * @description
- * [en]Color of the background.[/en]
- * [ja]背景の色を設定します。[/ja]
- */
-
- /**
- * @attribute size
- * @type {String}
- * @description
- * [en]Sizing of the wave on ripple effect. Set "cover" or "contain". Default is "cover".[/en]
- * [ja]エフェクトのサイズを指定します。"cover"もしくは"contain"を指定します。デフォルトは"cover"です。[/ja]
- */
-
- /**
- * @attribute center
- * @type {Boolean}
- * @description
- * [en]If this attribute presents, change the position of wave effect to center of the target element.[/en]
- * [ja]この要素を設定すると、エフェクトの位置が要素の真ん中から始まります。[/ja]
- */
-
- /**
- * @attribute disabled
- * @description
- * [en]If this attribute is set, the ripple effect will be disabled.[/en]
- * [ja]この属性が設定された場合、リップルエフェクトは無効になります。[/ja]
- */
-
- function RippleElement() {
- classCallCheck(this, RippleElement);
-
- var _this = possibleConstructorReturn(this, (RippleElement.__proto__ || Object.getPrototypeOf(RippleElement)).call(this));
-
- _this._onTap = _this._onTap.bind(_this);
- _this._onHold = _this._onHold.bind(_this);
- _this._onDragStart = _this._onDragStart.bind(_this);
- _this._onRelease = _this._onRelease.bind(_this);
-
- contentReady(_this, function () {
- return _this._compile();
- });
-
- _this._animator = new AnimatorCSS();
-
- ['color', 'center', 'start-radius', 'background', 'modifier'].forEach(function (e) {
- _this.attributeChangedCallback(e, null, _this.getAttribute(e));
- });
- return _this;
- }
-
- createClass(RippleElement, [{
- key: '_compile',
- value: function _compile() {
- this.classList.add(defaultClassName$11);
-
- this._wave = this.getElementsByClassName('ripple__wave')[0];
- this._background = this.getElementsByClassName('ripple__background')[0];
-
- if (!(this._background && this._wave)) {
- this._wave = util$1.create('.ripple__wave');
- this._background = util$1.create('.ripple__background');
-
- this.appendChild(this._wave);
- this.appendChild(this._background);
- }
-
- ModifierUtil.initModifier(this, scheme$23);
- }
- }, {
- key: '_getEffectSize',
- value: function _getEffectSize() {
- var sizes = ['cover', 'contain'];
- if (this.hasAttribute('size')) {
- var size = this.getAttribute('size');
- if (sizes.indexOf(size) !== -1) {
- return size;
- }
- }
-
- return 'cover';
- }
- }, {
- key: '_calculateCoords',
- value: function _calculateCoords(e) {
- var x = void 0,
- y = void 0,
- h = void 0,
- w = void 0,
- r = void 0;
- var b = this.getBoundingClientRect();
- var size = this._getEffectSize();
- var error = function error() {
- return util$1.throw('Ripple invalid state');
- };
-
- if (this._center) {
- x = b.width / 2;
- y = b.height / 2;
-
- if (size === 'cover') {
- r = Math.sqrt(x * x + y * y);
- } else if (size === 'contain') {
- r = Math.min(x, y);
- } else {
- error();
- }
- } else {
- x = (typeof e.clientX === 'number' ? e.clientX : e.changedTouches[0].clientX) - b.left;
- y = (typeof e.clientY === 'number' ? e.clientY : e.changedTouches[0].clientY) - b.top;
- h = Math.max(y, b.height - y);
- w = Math.max(x, b.width - x);
-
- if (size === 'cover') {
- r = Math.sqrt(h * h + w * w);
- } else if (size === 'contain') {
- r = Math.min(Math.round(h / 2), Math.round(w / 2));
- } else {
- error();
- }
- }
-
- return { x: x, y: y, r: r };
- }
- }, {
- key: '_rippleAnimation',
- value: function _rippleAnimation(e) {
- var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 300;
- var _animator = this._animator,
- _wave = this._wave,
- _background = this._background,
- _minR = this._minR;
-
- var _calculateCoords2 = this._calculateCoords(e),
- x = _calculateCoords2.x,
- y = _calculateCoords2.y,
- r = _calculateCoords2.r;
-
- _animator.stopAll({ stopNext: 1 });
- _animator.animate(_background, { opacity: 1 }, duration);
-
- util$1.extend(_wave.style, {
- opacity: 1,
- top: y - _minR + 'px',
- left: x - _minR + 'px',
- width: 2 * _minR + 'px',
- height: 2 * _minR + 'px'
- });
-
- return _animator.animate(_wave, {
- top: y - r,
- left: x - r,
- height: 2 * r,
- width: 2 * r
- }, duration);
- }
- }, {
- key: '_updateParent',
- value: function _updateParent() {
- if (!this._parentUpdated && this.parentNode) {
- var computedStyle = window.getComputedStyle(this.parentNode);
- if (computedStyle.getPropertyValue('position') === 'static') {
- this.parentNode.style.position = 'relative';
- }
- this._parentUpdated = true;
- }
- }
- }, {
- key: '_onTap',
- value: function _onTap(e) {
- var _this2 = this;
-
- if (!this.disabled && !e.ripple) {
- e.ripple = true;
- this._updateParent();
- this._rippleAnimation(e.gesture.srcEvent).then(function () {
- _this2._animator.fade(_this2._wave);
- _this2._animator.fade(_this2._background);
- });
- }
- }
- }, {
- key: '_onHold',
- value: function _onHold(e) {
- if (!this.disabled && !e.ripple) {
- e.ripple = true;
- this._updateParent();
- this._holding = this._rippleAnimation(e.gesture.srcEvent, 2000);
- document.addEventListener('release', this._onRelease);
- }
- }
- }, {
- key: '_onRelease',
- value: function _onRelease(e) {
- var _this3 = this;
-
- if (this._holding && !e.ripple) {
- e.ripple = true;
- this._holding.speed(300).then(function () {
- _this3._animator.stopAll({ stopNext: true });
- _this3._animator.fade(_this3._wave);
- _this3._animator.fade(_this3._background);
- });
-
- this._holding = false;
- }
-
- document.removeEventListener('release', this._onRelease);
- }
- }, {
- key: '_onDragStart',
- value: function _onDragStart(e) {
- if (this._holding) {
- return this._onRelease(e);
- }
- if (['left', 'right'].indexOf(e.gesture.direction) != -1) {
- this._onTap(e);
- }
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- this._parentNode = this.parentNode;
-
- if (internal$1.config.animationsDisabled) {
- this.disabled = true;
- } else {
- this._parentNode.addEventListener('tap', this._onTap);
- this._parentNode.addEventListener('hold', this._onHold);
- this._parentNode.addEventListener('dragstart', this._onDragStart);
- }
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- var pn = this._parentNode || this.parentNode;
- pn.removeEventListener('tap', this._onTap);
- pn.removeEventListener('hold', this._onHold);
- pn.removeEventListener('dragstart', this._onDragStart);
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- var _this4 = this;
-
- switch (name) {
-
- case 'class':
- util$1.restoreClass(this, defaultClassName$11, scheme$23);
- break;
-
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, scheme$23);
- break;
-
- case 'start-radius':
- this._minR = Math.max(0, parseFloat(current) || 0);
- break;
-
- case 'color':
- if (current) {
- contentReady(this, function () {
- _this4._wave.style.background = current;
- if (!_this4.hasAttribute('background')) {
- _this4._background.style.background = current;
- }
- });
- }
- break;
-
- case 'background':
- if (current || last) {
- if (current === 'none') {
- contentReady(this, function () {
- _this4._background.setAttribute('disabled', 'disabled');
- _this4._background.style.background = 'transparent';
- });
- } else {
- contentReady(this, function () {
- if (_this4._background.hasAttribute('disabled')) {
- _this4._background.removeAttribute('disabled');
- }
- _this4._background.style.background = current;
- });
- }
- }
- break;
-
- case 'center':
- if (name === 'center') {
- this._center = current != null && current != 'false';
- }
- break;
-
- }
- }
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the element is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- }, {
- key: 'disabled',
- set: function set$$1(value) {
- return util$1.toggleAttribute(this, 'disabled', value);
- },
- get: function get$$1() {
- return this.hasAttribute('disabled');
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['start-radius', 'color', 'background', 'center', 'class', 'modifier'];
- }
- }]);
- return RippleElement;
- }(BaseElement);
-
- onsElements.Ripple = RippleElement;
- customElements.define('ons-ripple', RippleElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * @element ons-row
- * @category grid
- * @description
- * [en]Represents a row in the grid system. Use with `<ons-col>` to layout components.[/en]
- * [ja]グリッドシステムにて行を定義します。ons-colとともに使用し、コンポーネントの配置に使用します。[/ja]
- * @codepen GgujC {wide}
- * @guide features.html
- * [en]Layouting guide[/en]
- * [ja]レイアウト調整[/ja]
- * @seealso ons-col
- * [en]The `<ons-col>` component is used as children of `<ons-row>`.[/en]
- * [ja]ons-colコンポーネント[/ja]
- * @note
- * [en]For Android 4.3 and earlier, and iOS6 and earlier, when using mixed alignment with ons-row and ons-col, they may not be displayed correctly. You can use only one vertical-align.[/en]
- * [ja]Android 4.3以前、もしくはiOS 6以前のOSの場合、ons-rowとons-colを組み合わせてそれぞれのons-col要素のvertical-align属性の値に別々の値を指定すると、描画が崩れる場合があります。vertical-align属性の値には一つの値だけを指定できます。[/ja]
- * @example
- * <ons-row>
- * <ons-col width="50px"><ons-icon icon="fa-twitter"></ons-icon></ons-col>
- * <ons-col>Text</ons-col>
- * </ons-row>
- */
-
- /**
- * @attribute vertical-align
- * @type {String}
- * @description
- * [en]Short hand attribute for aligning vertically. Valid values are top, bottom, and center.[/en]
- * [ja]縦に整列するために指定します。top、bottom、centerのいずれかを指定できます。[/ja]
- */
-
- var RowElement = function (_BaseElement) {
- inherits(RowElement, _BaseElement);
-
- function RowElement() {
- classCallCheck(this, RowElement);
- return possibleConstructorReturn(this, (RowElement.__proto__ || Object.getPrototypeOf(RowElement)).apply(this, arguments));
- }
-
- return RowElement;
- }(BaseElement);
-
- onsElements.Row = RowElement;
- customElements.define('ons-row', RowElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var defaultClassName$12 = 'segment';
- var scheme$24 = {
- '': 'segment--*',
- '.segment__item': 'segment--*__item',
- '.segment__input': 'segment--*__input',
- '.segment__button': 'segment--*__button'
- };
-
- var generateId$1 = function () {
- var i = 0;
- return function () {
- return 'ons-segment-gen-' + i++;
- };
- }();
-
- /**
- * @element ons-segment
- * @category control
- * @modifier material
- * [en]Material Design segment[/en]
- * [ja][/ja]
- * @description
- * [en]
- * Segment component. Use this component to have a button bar with automatic styles that switch on click of another button.
- *
- * Will automatically display as a Material Design segment on Android.
- * [/en]
- * [ja][/ja]
- * @codepen hLayx
- * @tutorial vanilla/Reference/segment
- * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
- * @guide theming.html#cross-platform-styling-autostyling [en]Information about cross platform styling[/en][ja]Information about cross platform styling[/ja]
- * @example
- * <ons-segment>
- * <ons-button>Label 1</ons-button>
- * <ons-button>Label 2</ons-button>
- * <ons-button>Label 3</ons-button>
- * </ons-segment>
- */
-
- var SegmentElement = function (_BaseElement) {
- inherits(SegmentElement, _BaseElement);
-
- /**
- * @event postchange
- * @description
- * [en]Fires after the active button is changed.[/en]
- * [ja][/ja]
- * @param {Object} event
- * [en]Event object.[/en]
- * [ja][/ja]
- * @param {Number} event.index
- * [en]Tapped button index.[/en]
- * [ja][/ja]
- * @param {Object} event.segmentItem
- * [en]Segment item object.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the segment.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute tabbar-id
- * @initonly
- * @type {String}
- * @description
- * [en]ID of the tabbar element to "connect" to the segment. Must be inside the same page.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute active-index
- * @initonly
- * @default 0
- * @type {Number}
- * @description
- * [en]Index of the first active button, only works if there is no connected tabbar (in which case the active tab sets the active button).[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute disabled
- * @description
- * [en]Specify if segment should be disabled.[/en]
- * [ja]ボタンを無効化する場合は指定します。[/ja]
- */
-
- function SegmentElement() {
- classCallCheck(this, SegmentElement);
-
- var _this = possibleConstructorReturn(this, (SegmentElement.__proto__ || Object.getPrototypeOf(SegmentElement)).call(this));
-
- _this._segmentId = generateId$1();
- _this._tabbar = null;
- _this._onChange = _this._onChange.bind(_this);
- _this._onTabbarPreChange = _this._onTabbarPreChange.bind(_this);
-
- contentReady(_this, function () {
- _this._compile();
- setImmediate(function () {
- return _this._lastActiveIndex = _this._tabbar ? _this._tabbar.getActiveTabIndex() : _this.getActiveButtonIndex();
- });
- });
- return _this;
- }
-
- createClass(SegmentElement, [{
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
- this.classList.add(defaultClassName$12);
-
- for (var index = this.children.length - 1; index >= 0; index--) {
- var item = this.children[index];
- item.classList.add('segment__item');
-
- var input = util$1.findChild(item, '.segment__input') || util$1.create('input.segment__input');
- input.type = 'radio';
- input.value = index;
- input.name = input.name || this._segmentId;
- input.checked = !this.hasAttribute('tabbar-id') && index === (parseInt(this.getAttribute('active-index')) || 0);
-
- var button = util$1.findChild(item, '.segment__button') || util$1.create('.segment__button');
- if (button.parentElement !== item) {
- while (item.firstChild) {
- button.appendChild(item.firstChild);
- }
- }
-
- item.appendChild(input);
- item.appendChild(button);
- }
-
- ModifierUtil.initModifier(this, scheme$24);
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- var _this2 = this;
-
- contentReady(this, function () {
- if (_this2.hasAttribute('tabbar-id')) {
- var page = util$1.findParent(_this2, 'ons-page');
- _this2._tabbar = page && page.querySelector('#' + _this2.getAttribute('tabbar-id'));
- if (!_this2._tabbar || _this2._tabbar.tagName !== 'ONS-TABBAR') {
- util$1.throw('No tabbar with id ' + _this2.getAttribute('tabbar-id') + ' was found.');
- }
-
- _this2._tabbar.setAttribute('hide-tabs', '');
- setImmediate(function () {
- return _this2._setChecked(_this2._tabbar.getActiveTabIndex());
- });
-
- _this2._tabbar.addEventListener('prechange', _this2._onTabbarPreChange);
- }
- });
-
- this.addEventListener('change', this._onChange);
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- var _this3 = this;
-
- contentReady(this, function () {
- if (_this3._tabbar) {
- _this3._tabbar.removeEventListener('prechange', _this3._onTabbarPreChange);
- _this3._tabbar = null;
- }
- });
- this.removeEventListener('change', this._onChange);
- }
- }, {
- key: '_setChecked',
- value: function _setChecked(index) {
- this.children[index].firstElementChild.checked = true;
- }
-
- /**
- * @method setActiveButton
- * @signature setActiveButton(index, [options])
- * @param {Number} index
- * [en]Button index.[/en]
- * [ja][/ja]
- * @param {Object} [options]
- * [en]Parameter object, works only if there is a connected tabbar. Supports the same options as `ons-tabbar`'s `setActiveTab` method.[/en]
- * [ja][/ja]
- * @description
- * [en]Make button with the specified index active. If there is a connected tabbar it shows the corresponding tab page. In this case animations and their options can be specified by the second parameter.[/en]
- * [ja][/ja]
- * @return {Promise}
- * [en]Resolves to the selected index or to the new page element if there is a connected tabbar.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'setActiveButton',
- value: function setActiveButton(index, options) {
- if (this._tabbar) {
- return this._tabbar.setActiveTab(index, options);
- }
-
- this._setChecked(index);
- this._postChange(index);
- return Promise.resolve(index);
- }
-
- /**
- * @method getActiveButtonIndex
- * @signature getActiveButtonIndex()
- * @return {Number}
- * [en]The index of the currently active button.[/en]
- * [ja][/ja]
- * @description
- * [en]Returns button index of current active button. If active button is not found, returns -1.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'getActiveButtonIndex',
- value: function getActiveButtonIndex() {
- for (var i = this.children.length - 1; i >= 0; i--) {
- // Array.findIndex
- if (this.children[i].firstElementChild.checked) {
- return i;
- }
- }
- return -1;
- }
- }, {
- key: '_onChange',
- value: function _onChange(event) {
- event.stopPropagation();
- this._tabbar ? this._tabbar.setActiveTab(this.getActiveButtonIndex(), { reject: false }) : this._postChange(this.getActiveButtonIndex());
- }
- }, {
- key: '_onTabbarPreChange',
- value: function _onTabbarPreChange(event) {
- var _this4 = this;
-
- setImmediate(function () {
- if (!event.detail.canceled) {
- _this4._setChecked(event.index);
- _this4._postChange(event.index);
- }
- });
- }
- }, {
- key: '_postChange',
- value: function _postChange(index) {
- util$1.triggerElementEvent(this, 'postchange', {
- index: index,
- activeIndex: index,
- lastActiveIndex: this._lastActiveIndex,
- segmentItem: this.children[index]
- });
- this._lastActiveIndex = index;
- }
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the segment is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'class':
- util$1.restoreClass(this, defaultClassName$12, scheme$24);
- break;
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, scheme$24);
- break;
- }
- }
- }, {
- key: 'disabled',
- set: function set$$1(value) {
- return util$1.toggleAttribute(this, 'disabled', value);
- },
- get: function get$$1() {
- return this.hasAttribute('disabled');
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['class', 'modifier'];
- }
- }, {
- key: 'events',
- get: function get$$1() {
- return ['postchange'];
- }
- }]);
- return SegmentElement;
- }(BaseElement);
-
- onsElements.Segment = SegmentElement;
- customElements.define('ons-segment', SegmentElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var scheme$25 = {
- '': 'select-* select--*',
- '.select-input': 'select-input--*'
- };
-
- var defaultClassName$13 = 'select';
-
- var INPUT_ATTRIBUTES$1 = ['autofocus', 'disabled', 'form', 'multiple', 'name', 'required', 'size'];
-
- /**
- * @element ons-select
- * @category form
- * @modifier material
- * [en]Displays a Material Design select input.[/en]
- * [ja][/ja]
- * @modifier underbar
- * [en]Displays a horizontal line underneath a select input.[/en]
- * [ja][/ja]
- * @description
- * [en]
- * Select component. If you want to place a select with an ID of `my-id` on a page, use `<ons-select select-id="my-id">`.
- *
- * The component will automatically display as a Material Design select on Android.
- *
- * Most attributes that can be used for a normal `<select>` element can also be used on the `<ons-select>` element.
- * [/en]
- * [ja]セレクトボックスを表示するコンポーネントです。`select` 要素に使用できる属性の多くが `ons-select` 要素でも利用できます。[/ja]
- * @codepen hLayx
- * @tutorial vanilla/Reference/select
- * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
- * @guide theming.html#cross-platform-styling-autostyling [en]Information about cross platform styling[/en][ja]Information about cross platform styling[/ja]
- * @example
- * <ons-select>
- * <option value="1">1</option>
- * <option value="2">2nd</option>
- * <option value="3">3rd option</option>
- * </ons-select>
- */
-
- var SelectElement = function (_BaseElement) {
- inherits(SelectElement, _BaseElement);
-
- /**
- * @attribute autofocus
- * @type {Boolean}
- * @default false
- * @description
- * [en]Element automatically gains focus on page load.[/en]
- * [ja]ページロード時にこのセレクトボックスにフォーカスが移るようにします。[/ja]
- */
-
- /**
- * @attribute disabled
- * @type {Boolean}
- * @default false
- * @description
- * [en]Specify if select input should be disabled.[/en]
- * [ja]このセレクトボックスを無効化する場合に指定します。[/ja]
- */
-
- /**
- * @attribute form
- * @type {String}
- * @description
- * [en]Associate a select element to an existing form on the page, even if not nested.[/en]
- * [ja]このセレクトボックスを、指定した `form` 要素に紐付けます。セレクトボックスを `form` 要素の外側に配置する際に使用します。[/ja]
- */
-
- /**
- * @attribute multiple
- * @type {Boolean}
- * @default false
- * @description
- * [en]If this attribute is defined, multiple options can be selected at once.[/en]
- * [ja]選択肢の複数選択を有効にします。[/ja]
- */
-
- /**
- * @attribute name
- * @type {String}
- * @description
- * [en]Name the select element, useful for instance if it is part of a form.[/en]
- * [ja]このセレクトボックスの名前を指定します。通常 `form` 要素と共に使用します。[/ja]
- */
-
- /**
- * @attribute required
- * @type {Boolean}
- * @description
- * [en]Make the select input required for submitting the form it is part of.[/en]
- * [ja]このセレクトボックスを入力必須にする場合に指定します。通常 `form` 要素と共に使用します。[/ja]
- */
-
- /**
- * @attribute select-id
- * @type {String}
- * @description
- * [en]ID given to the inner select, useful for dynamic manipulation.[/en]
- * [ja]このセレクトボックスが内部に持つ select 要素に与える ID を指定します。セレクトボックスの内容を動的に変更する必要がある場合に使用します。[/ja]
- */
-
- /**
- * @attribute size
- * @type {Number}
- * @default 1
- * @description
- * [en]How many options are displayed; if there are more than the size then a scroll appears to navigate them.[/en]
- * [ja]一度に表示する選択肢の個数を指定します。選択肢がこの属性で指定した個数よりも多い場合、スクロールが有効になります。[/ja]
- */
-
- function SelectElement() {
- classCallCheck(this, SelectElement);
-
- var _this = possibleConstructorReturn(this, (SelectElement.__proto__ || Object.getPrototypeOf(SelectElement)).call(this));
-
- contentReady(_this, function () {
- return _this._compile();
- });
-
- _this._deriveGetters();
- return _this;
- }
-
- createClass(SelectElement, [{
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- var _this2 = this;
-
- switch (name) {
- case 'class':
- util$1.restoreClass(this, defaultClassName$13, scheme$25);
- break;
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, scheme$25);
- break;
- }
-
- if (INPUT_ATTRIBUTES$1.indexOf(name) >= 0) {
- contentReady(this, function () {
- return _this2._updateBoundAttributes();
- });
- }
- }
- }, {
- key: '_updateBoundAttributes',
- value: function _updateBoundAttributes() {
- var _this3 = this;
-
- INPUT_ATTRIBUTES$1.forEach(function (attr) {
- if (_this3.hasAttribute(attr)) {
- _this3._select.setAttribute(attr, _this3.getAttribute(attr));
- } else {
- _this3._select.removeAttribute(attr);
- }
- });
- }
-
- /**
- * @property length
- * @description
- * [en]Number of options in the select box.[/en]
- * [ja]このセレクトボックスに含まれる選択肢の個数を返します。 `select` 要素[/ja]
- */
-
- /**
- * @property options
- * @description
- * [en]Several options for handling the select DOM object.[/en]
- * [ja]このセレクトボックスに含まれる `option` 要素の配列を返します。[/ja]
- */
-
- /**
- * @property selectedIndex
- * @description
- * [en]Index of the currently selected option.[/en]
- * [ja]現在選択されている選択肢のインデックスを返します。[/ja]
- */
-
- /**
- * @property value
- * @description
- * [en]Value of the currently selected option.[/en]
- * [ja]現在選択されている選択肢の値を返します。[/ja]
- */
-
- }, {
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
-
- this.classList.add(defaultClassName$13);
- var sel = this._select || document.createElement('select');
- if (!sel.id && this.hasAttribute('select-id')) {
- sel.id = this.getAttribute('select-id');
- }
- sel.classList.add('select-input');
- if (!this._select) {
- util$1.arrayFrom(this.childNodes).forEach(function (element) {
- return sel.appendChild(element);
- });
- this.appendChild(sel);
- }
-
- ModifierUtil.initModifier(this, scheme$25);
- }
- }, {
- key: '_deriveGetters',
- value: function _deriveGetters() {
- var _this4 = this;
-
- ['disabled', 'length', 'multiple', 'name', 'options', 'selectedIndex', 'size', 'value', 'form', 'type'].forEach(function (key) {
- Object.defineProperty(_this4, key, {
- configurable: true,
- enumerable: true,
- get: function get$$1() {
- return _this4._select[key];
- },
- set: ['form', 'type'].indexOf(key) === -1 ? function (value) {
- return contentReady(_this4, function () {
- return _this4._select[key] = value;
- });
- } : undefined
- });
- });
- }
- }, {
- key: 'add',
- value: function add(option) {
- var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
-
- this._select.add(option, index);
- }
- }, {
- key: 'remove',
- value: function remove(index) {
- this._select.remove(index);
- }
- }, {
- key: '_select',
- get: function get$$1() {
- return this.querySelector('select');
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'class'].concat(INPUT_ATTRIBUTES$1);
- }
- }]);
- return SelectElement;
- }(BaseElement);
-
- onsElements.Select = SelectElement;
- customElements.define('ons-select', SelectElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
- var defaultClassName$14 = 'fab fab--mini speed-dial__item';
-
- var scheme$26 = {
- '': 'fab--* speed-dial__item--*'
- };
-
- /**
- * @element ons-speed-dial-item
- * @category control
- * @description
- * [en]
- * This component displays the child elements of the Material Design Speed dial component.
- * [/en]
- * [ja]
- * Material DesignのSpeed dialの子要素を表現する要素です。
- * [/ja]
- * @codepen dYQYLg
- * @tutorial vanilla/Reference/speed-dial
- * @seealso ons-speed-dial
- * [en]The `<ons-speed-dial>` component.[/en]
- * [ja]ons-speed-dialコンポーネント[/ja]
- * @seealso ons-fab
- * [en]ons-fab component[/en]
- * [ja]ons-fabコンポーネント[/ja]
- * @example
- * <ons-speed-dial position="left bottom">
- * <ons-fab>
- * <ons-icon icon="fa-twitter"></ons-icon>
- * </ons-fab>
- * <ons-speed-dial-item>A</ons-speed-dial-item>
- * <ons-speed-dial-item>B</ons-speed-dial-item>
- * <ons-speed-dial-item>C</ons-speed-dial-item>
- * </ons-speed-dial>
- */
-
- var SpeedDialItemElement = function (_BaseElement) {
- inherits(SpeedDialItemElement, _BaseElement);
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the component.[/en]
- * [ja]このコンポーネントの表現を指定します。[/ja]
- */
-
- /**
- * @attribute ripple
- * @description
- * [en]If this attribute is defined, the button will have a ripple effect when tapped.[/en]
- * [ja][/ja]
- */
-
- function SpeedDialItemElement() {
- classCallCheck(this, SpeedDialItemElement);
-
- var _this = possibleConstructorReturn(this, (SpeedDialItemElement.__proto__ || Object.getPrototypeOf(SpeedDialItemElement)).call(this));
-
- _this._compile();
- _this._boundOnClick = _this._onClick.bind(_this);
- return _this;
- }
-
- createClass(SpeedDialItemElement, [{
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'class':
- util$1.restoreClass(this, defaultClassName$14, scheme$26);
- break;
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, scheme$26);
- util$1.addModifier(this, 'mini');
- break;
- case 'ripple':
- this._updateRipple();
- }
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- this.addEventListener('click', this._boundOnClick, false);
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- this.removeEventListener('click', this._boundOnClick, false);
- }
- }, {
- key: '_updateRipple',
- value: function _updateRipple() {
- util$1.updateRipple(this);
- }
- }, {
- key: '_onClick',
- value: function _onClick(e) {
- e.stopPropagation();
- }
- }, {
- key: '_compile',
- value: function _compile() {
- var _this2 = this;
-
- autoStyle.prepare(this);
-
- defaultClassName$14.split(/\s+/).forEach(function (token) {
- return _this2.classList.add(token);
- });
-
- util$1.addModifier(this, 'mini');
- this._updateRipple();
-
- ModifierUtil.initModifier(this, scheme$26);
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'ripple', 'class'];
- }
- }]);
- return SpeedDialItemElement;
- }(BaseElement);
-
- onsElements.SpeedDialItem = SpeedDialItemElement;
- customElements.define('ons-speed-dial-item', SpeedDialItemElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
- var defaultClassName$15 = 'speed-dial';
- var scheme$27 = {
- '': 'speed-dial--*'
- };
-
- /**
- * @element ons-speed-dial
- * @category control
- * @description
- * [en]
- * Element that displays a Material Design Speed Dialog component. It is useful when there are more than one primary action that can be performed in a page.
- *
- * The Speed dial looks like a `<ons-fab>` element but will expand a menu when tapped.
- * [/en]
- * [ja][/ja]
- * @codepen dYQYLg
- * @tutorial vanilla/Reference/speed-dial
- * @seealso ons-speed-dial-item
- * [en]The `<ons-speed-dial-item>` represents a menu item.[/en]
- * [ja]ons-speed-dial-itemコンポーネント[/ja]
- * @seealso ons-fab
- * [en]ons-fab component[/en]
- * [ja]ons-fabコンポーネント[/ja]
- * @example
- * <ons-speed-dial position="left bottom">
- * <ons-fab>
- * <ons-icon icon="fa-twitter"></ons-icon>
- * </ons-fab>
- * <ons-speed-dial-item>A</ons-speed-dial-item>
- * <ons-speed-dial-item>B</ons-speed-dial-item>
- * <ons-speed-dial-item>C</ons-speed-dial-item>
- * </ons-speed-dial>
- */
-
- var SpeedDialElement = function (_BaseElement) {
- inherits(SpeedDialElement, _BaseElement);
-
- /**
- * @event open
- * @description
- * [en]Fired when the menu items are shown.[/en]
- * [ja][/ja]
- */
-
- /**
- * @event close
- * @description
- * [en]Fired when the menu items are hidden.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the component.[/en]
- * [ja]このコンポーネントの表現を指定します。[/ja]
- */
-
- /**
- * @attribute ripple
- * @description
- * [en]If this attribute is defined, the button will have a ripple effect when tapped.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute position
- * @type {String}
- * @description
- * [en]
- * Specify the vertical and horizontal position of the component.
- * I.e. to display it in the top right corner specify "right top".
- * Choose from "right", "left", "top" and "bottom".
- * [/en]
- * [ja]
- * この要素を表示する左右と上下の位置を指定します。
- * 例えば、右上に表示する場合には"right top"を指定します。
- * 左右と上下の位置の指定には、rightとleft、topとbottomがそれぞれ指定できます。
- * [/ja]
- */
-
- /**
- * @attribute direction
- * @type {String}
- * @description
- * [en]Specify the direction the items are displayed. Possible values are "up", "down", "left" and "right".[/en]
- * [ja]
- * 要素が表示する方向を指定します。up, down, left, rightが指定できます。
- * [/ja]
- */
-
- /**
- * @attribute disabled
- * @description
- * [en]Specify if button should be disabled.[/en]
- * [ja]無効化する場合に指定します。[/ja]
- */
-
- function SpeedDialElement() {
- classCallCheck(this, SpeedDialElement);
-
- var _this = possibleConstructorReturn(this, (SpeedDialElement.__proto__ || Object.getPrototypeOf(SpeedDialElement)).call(this));
-
- contentReady(_this, function () {
- _this._compile();
- });
-
- _this._itemShown = false;
- _this._boundOnClick = _this._onClick.bind(_this);
- return _this;
- }
-
- createClass(SpeedDialElement, [{
- key: '_compile',
- value: function _compile() {
- this.classList.add(defaultClassName$15);
- autoStyle.prepare(this);
- this._updateRipple();
- ModifierUtil.initModifier(this, scheme$27);
-
- if (this.hasAttribute('direction')) {
- this._updateDirection(this.getAttribute('direction'));
- } else {
- this._updateDirection('up');
- }
-
- this._updatePosition();
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- var _this2 = this;
-
- switch (name) {
- case 'class':
- util$1.restoreClass(this, defaultClassName$15, scheme$27);
- break;
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, scheme$27);
- break;
- case 'ripple':
- contentReady(this, function () {
- return _this2._updateRipple();
- });
- break;
- case 'direction':
- contentReady(this, function () {
- return _this2._updateDirection(current);
- });
- break;
- case 'position':
- contentReady(this, function () {
- return _this2._updatePosition();
- });
- break;
- }
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- this.addEventListener('click', this._boundOnClick, false);
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- this.removeEventListener('click', this._boundOnClick, false);
- }
- }, {
- key: '_onClick',
- value: function _onClick(e) {
- if (this.onClick) {
- this.onClick.apply(this);
- return Promise.resolve();
- } else if (!this.disabled && this.visible) {
- return this.toggleItems();
- }
- }
- }, {
- key: '_show',
- value: function _show() {
- if (!this.inline) {
- return this.show();
- }
- return Promise.resolve();
- }
- }, {
- key: '_hide',
- value: function _hide() {
- var _this3 = this;
-
- return new Promise(function (resolve) {
- if (!_this3.inline) {
- setImmediate(function () {
- return _this3.hide().then(resolve);
- });
- } else {
- resolve();
- }
- });
- }
- }, {
- key: '_updateRipple',
- value: function _updateRipple() {
- if (this._fab) {
- this.hasAttribute('ripple') ? this._fab.setAttribute('ripple', '') : this._fab.removeAttribute('ripple');
- }
- }
- }, {
- key: '_updateDirection',
- value: function _updateDirection(direction) {
- var children = this.items;
- for (var i = 0; i < children.length; i++) {
- styler(children[i], {
- transitionDelay: 25 * i + 'ms',
- bottom: 'auto',
- right: 'auto',
- top: 'auto',
- left: 'auto'
- });
- }
- switch (direction) {
- case 'up':
- for (var _i = 0; _i < children.length; _i++) {
- children[_i].style.bottom = 72 + 56 * _i + 'px';
- children[_i].style.right = '8px';
- }
- break;
- case 'down':
- for (var _i2 = 0; _i2 < children.length; _i2++) {
- children[_i2].style.top = 72 + 56 * _i2 + 'px';
- children[_i2].style.left = '8px';
- }
- break;
- case 'left':
- for (var _i3 = 0; _i3 < children.length; _i3++) {
- children[_i3].style.top = '8px';
- children[_i3].style.right = 72 + 56 * _i3 + 'px';
- }
- break;
- case 'right':
- for (var _i4 = 0; _i4 < children.length; _i4++) {
- children[_i4].style.top = '8px';
- children[_i4].style.left = 72 + 56 * _i4 + 'px';
- }
- break;
- default:
- util$1.throw('Argument must be one of up, down, left or right.');
- }
- }
- }, {
- key: '_updatePosition',
- value: function _updatePosition() {
- var position = this.getAttribute('position');
- this.classList.remove('fab--top__left', 'fab--bottom__right', 'fab--bottom__left', 'fab--top__right', 'fab--top__center', 'fab--bottom__center');
- switch (position) {
- case 'top right':
- case 'right top':
- this.classList.add('fab--top__right');
- break;
- case 'top left':
- case 'left top':
- this.classList.add('fab--top__left');
- break;
- case 'bottom right':
- case 'right bottom':
- this.classList.add('fab--bottom__right');
- break;
- case 'bottom left':
- case 'left bottom':
- this.classList.add('fab--bottom__left');
- break;
- case 'center top':
- case 'top center':
- this.classList.add('fab--top__center');
- break;
- case 'center bottom':
- case 'bottom center':
- this.classList.add('fab--bottom__center');
- break;
- default:
- break;
- }
- }
- }, {
- key: '_getTranslate',
- value: function _getTranslate() {
- var isBottom = (this.getAttribute('position') || '').indexOf('bottom') >= 0;
- var translate = isBottom ? 'translate3d(0px, -' + (util$1.globals.fabOffset || 0) + 'px, 0px) ' : '';
- return translate;
- }
-
- /**
- * @method show
- * @signature show()
- * @description
- * [en]Show the speed dial.[/en]
- * [ja]Speed dialを表示します。[/ja]
- */
-
- }, {
- key: 'show',
- value: function show() {
- this._fab.show();
- styler(this, { transform: this._getTranslate });
- return Promise.resolve();
- }
-
- /**
- * @method hide
- * @signature hide()
- * @description
- * [en]Hide the speed dial.[/en]
- * [ja]Speed dialを非表示にします。[/ja]
- */
-
- }, {
- key: 'hide',
- value: function hide() {
- var _this4 = this;
-
- return this.hideItems().then(function () {
- return _this4._fab.hide();
- });
- }
-
- /**
- * @method showItems
- * @signature showItems()
- * @description
- * [en]Show the speed dial items.[/en]
- * [ja]Speed dialの子要素を表示します。[/ja]
- */
-
- }, {
- key: 'showItems',
- value: function showItems() {
- if (this.hasAttribute('direction')) {
- this._updateDirection(this.getAttribute('direction'));
- } else {
- this._updateDirection('up');
- }
-
- var totalDelay = 0;
- if (!this._itemShown) {
- var children = this.items;
- for (var i = 0; i < children.length; i++) {
- var delay = 25 * i;
- totalDelay += delay;
- styler(children[i], {
- transform: 'scale(1)',
- transitionDelay: delay + 'ms'
- });
- }
- totalDelay += 50;
-
- this._itemShown = true;
- util$1.triggerElementEvent(this, 'open');
- }
-
- var deferred = util$1.defer();
- setTimeout(deferred.resolve, totalDelay);
- return deferred.promise;
- }
-
- /**
- * @method hideItems
- * @signature hideItems()
- * @description
- * [en]Hide the speed dial items.[/en]
- * [ja]Speed dialの子要素を非表示にします。[/ja]
- */
-
- }, {
- key: 'hideItems',
- value: function hideItems() {
- var totalDelay = 0;
- if (this._itemShown) {
- var children = this.items;
- for (var i = 0; i < children.length; i++) {
- var delay = 25 * (children.length - i);
- totalDelay += delay;
- styler(children[i], {
- transform: 'scale(0)',
- transitionDelay: delay + 'ms'
- });
- }
- totalDelay += 50;
-
- this._itemShown = false;
- util$1.triggerElementEvent(this, 'close');
- }
-
- var deferred = util$1.defer();
- setTimeout(deferred.resolve, totalDelay);
- return deferred.promise;
- }
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the element is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- }, {
- key: 'isOpen',
-
-
- /**
- * @method isOpen
- * @signature isOpen()
- * @description
- * [en]Returns whether the menu is open or not.[/en]
- * [ja][/ja]
- */
- value: function isOpen() {
- return this._itemShown;
- }
-
- /**
- * @method toggle
- * @signature toggle()
- * @description
- * [en]Toggle visibility.[/en]
- * [ja]Speed dialの表示非表示を切り替えます。[/ja]
- */
-
- }, {
- key: 'toggle',
- value: function toggle() {
- return this.visible ? this.hide() : this.show();
- }
-
- /**
- * @method toggleItems
- * @signature toggleItems()
- * @description
- * [en]Toggle item visibility.[/en]
- * [ja]Speed dialの子要素の表示非表示を切り替えます。[/ja]
- */
-
- }, {
- key: 'toggleItems',
- value: function toggleItems() {
- return this.isOpen() ? this.hideItems() : this.showItems();
- }
- }, {
- key: 'items',
- get: function get$$1() {
- return util$1.arrayFrom(this.querySelectorAll('ons-speed-dial-item'));
- }
- }, {
- key: '_fab',
- get: function get$$1() {
- return util$1.findChild(this, 'ons-fab');
- }
- }, {
- key: 'disabled',
- set: function set$$1(value) {
- if (value) {
- this.hideItems();
- }
- util$1.arrayFrom(this.children).forEach(function (e) {
- util$1.match(e, '.fab') && util$1.toggleAttribute(e, 'disabled', value);
- });
-
- return util$1.toggleAttribute(this, 'disabled', value);
- },
- get: function get$$1() {
- return this.hasAttribute('disabled');
- }
-
- /**
- * @property inline
- * @readonly
- * @type {Boolean}
- * @description
- * [en]Whether the element is inline or not.[/en]
- * [ja]インライン要素の場合に`true`。[/ja]
- */
-
- }, {
- key: 'inline',
- get: function get$$1() {
- return this.hasAttribute('inline');
- }
-
- /**
- * @property visible
- * @readonly
- * @type {Boolean}
- * @description
- * [en]Whether the element is visible or not.[/en]
- * [ja]要素が見える場合に`true`。[/ja]
- */
-
- }, {
- key: 'visible',
- get: function get$$1() {
- return this._fab.visible && this.style.display !== 'none';
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['class', 'modifier', 'ripple', 'direction', 'position'];
- }
- }, {
- key: 'events',
- get: function get$$1() {
- return ['open', 'close'];
- }
- }]);
- return SpeedDialElement;
- }(BaseElement);
-
- onsElements.SpeedDial = SpeedDialElement;
- customElements.define('ons-speed-dial', SpeedDialElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var rewritables$1 = {
- /**
- * @param {Element} element
- * @param {Function} callback
- */
- ready: function ready(element, callback) {
- setImmediate(callback);
- }
- };
-
- /**
- * @element ons-splitter-content
- * @category menu
- * @description
- * [en]
- * The `<ons-splitter-content>` element is used as a child element of `<ons-splitter>`.
- *
- * It contains the main content of the page while `<ons-splitter-side>` contains the list.
- * [/en]
- * [ja]ons-splitter-content要素は、ons-splitter要素の子要素として利用します。[/ja]
- * @codepen rOQOML
- * @tutorial vanilla/Reference/splitter
- * @guide fundamentals.html#managing-pages
- * [en]Managing multiple pages.[/en]
- * [ja]複数のページを管理する[/ja]
- * @seealso ons-splitter
- * [en]The `<ons-splitter>` component is the parent element.[/en]
- * [ja]ons-splitterコンポーネント[/ja]
- * @seealso ons-splitter-side
- * [en]The `<ons-splitter-side>` component contains the menu.[/en]
- * [ja]ons-splitter-sideコンポーネント[/ja]
- * @example
- * <ons-splitter>
- * <ons-splitter-content>
- * ...
- * </ons-splitter-content>
- *
- * <ons-splitter-side side="left" width="80%" collapse>
- * ...
- * </ons-splitter-side>
- * </ons-splitter>
- */
-
- var SplitterContentElement = function (_BaseElement) {
- inherits(SplitterContentElement, _BaseElement);
-
- /**
- * @attribute page
- * @type {String}
- * @description
- * [en]
- * The url of the content page. If this attribute is used the content will be loaded from a `<template>` tag or a remote file.
- *
- * It is also possible to put `<ons-page>` element as a child of the element.
- * [/en]
- * [ja]ons-splitter-content要素に表示するページのURLを指定します。[/ja]
- */
-
- function SplitterContentElement() {
- classCallCheck(this, SplitterContentElement);
-
- var _this = possibleConstructorReturn(this, (SplitterContentElement.__proto__ || Object.getPrototypeOf(SplitterContentElement)).call(this));
-
- _this._page = null;
- _this._pageLoader = defaultPageLoader;
-
- contentReady(_this, function () {
- rewritables$1.ready(_this, function () {
- var page = _this._getPageTarget();
-
- if (page) {
- _this.load(page);
- }
- });
- });
- return _this;
- }
-
- createClass(SplitterContentElement, [{
- key: 'connectedCallback',
- value: function connectedCallback() {
- if (!util$1.match(this.parentNode, 'ons-splitter')) {
- util$1.throw('"ons-splitter-content" must have "ons-splitter" as parent');
- }
- }
- }, {
- key: '_getPageTarget',
- value: function _getPageTarget() {
- return this._page || this.getAttribute('page');
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {}
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {}
-
- /**
- * @property page
- * @type {HTMLElement}
- * @description
- * [en]The page to load in the splitter content.[/en]
- * [ja]この要素内に表示するページを指定します。[/ja]
- */
-
- }, {
- key: 'load',
-
-
- /**
- * @method load
- * @signature load(page, [options])
- * @param {String} page, [options]
- * [en]Page URL. Can be either an HTML document or an `<template>` id.[/en]
- * [ja]pageのURLか、`<template>`で宣言したテンプレートのid属性の値を指定します。[/ja]
- * @param {Object} [options]
- * @param {Function} [options.callback]
- * @description
- * [en]Show the page specified in `page` in the content.[/en]
- * [ja]指定したURLをメインページを読み込みます。[/ja]
- * @return {Promise}
- * [en]Resolves to the new `<ons-page>` element[/en]
- * [ja]`<ons-page>`要素を解決するPromiseオブジェクトを返します。[/ja]
- */
- value: function load(page) {
- var _this2 = this;
-
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- this._page = page;
- var callback = options.callback || function () {};
-
- return new Promise(function (resolve) {
- var oldContent = _this2._content || null;
-
- _this2._pageLoader.load({ page: page, parent: _this2 }, function (pageElement) {
- if (oldContent) {
- _this2._pageLoader.unload(oldContent);
- oldContent = null;
- }
-
- setImmediate(function () {
- return _this2._show();
- });
-
- callback(pageElement);
- resolve(pageElement);
- });
- });
- }
- }, {
- key: '_show',
- value: function _show() {
- if (this._content) {
- this._content._show();
- }
- }
- }, {
- key: '_hide',
- value: function _hide() {
- if (this._content) {
- this._content._hide();
- }
- }
- }, {
- key: '_destroy',
- value: function _destroy() {
- if (this._content) {
- this._pageLoader.unload(this._content);
- }
- this.remove();
- }
- }, {
- key: 'page',
- get: function get$$1() {
- return this._page;
- }
-
- /**
- * @param {*} page
- */
- ,
- set: function set$$1(page) {
- this._page = page;
- }
- }, {
- key: '_content',
- get: function get$$1() {
- return this.children[0];
- }
-
- /**
- * @property pageLoader
- * @type {Function}
- * @description
- * [en]Page element loaded in the splitter content.[/en]
- * [ja]この要素内に表示するページを指定します。[/ja]
- */
-
- }, {
- key: 'pageLoader',
- get: function get$$1() {
- return this._pageLoader;
- },
- set: function set$$1(loader) {
- if (!(loader instanceof PageLoader)) {
- util$1.throwPageLoader();
- }
- this._pageLoader = loader;
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return [];
- }
- }, {
- key: 'rewritables',
- get: function get$$1() {
- return rewritables$1;
- }
- }]);
- return SplitterContentElement;
- }(BaseElement);
-
- onsElements.SplitterContent = SplitterContentElement;
- customElements.define('ons-splitter-content', SplitterContentElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var SplitterMaskElement = function (_BaseElement) {
- inherits(SplitterMaskElement, _BaseElement);
-
- function SplitterMaskElement() {
- classCallCheck(this, SplitterMaskElement);
-
- var _this = possibleConstructorReturn(this, (SplitterMaskElement.__proto__ || Object.getPrototypeOf(SplitterMaskElement)).call(this));
-
- _this._boundOnClick = _this._onClick.bind(_this);
- contentReady(_this, function () {
- if (_this.parentNode._sides.every(function (side) {
- return side.mode === 'split';
- })) {
- _this.setAttribute('style', 'display: none !important');
- }
- });
- return _this;
- }
-
- createClass(SplitterMaskElement, [{
- key: '_onClick',
- value: function _onClick(event) {
- if (this.onClick instanceof Function) {
- this.onClick();
- } else if (util$1.match(this.parentNode, 'ons-splitter')) {
- this.parentNode._sides.forEach(function (side) {
- return side.close('left').catch(function () {});
- });
- }
- event.stopPropagation();
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {}
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- this.addEventListener('click', this._boundOnClick);
- util$1.iosMaskScrollFix(this, true);
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- this.removeEventListener('click', this._boundOnClick);
- util$1.iosMaskScrollFix(this, false);
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return [];
- }
- }]);
- return SplitterMaskElement;
- }(BaseElement);
-
- onsElements.SplitterMask = SplitterMaskElement;
- customElements.define('ons-splitter-mask', SplitterMaskElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var SplitterAnimator$1 = function (_BaseAnimator) {
- inherits(SplitterAnimator, _BaseAnimator);
-
- function SplitterAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'cubic-bezier(.1, .7, .1, 1)' : _ref$timing,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.3 : _ref$duration,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay;
-
- classCallCheck(this, SplitterAnimator);
- return possibleConstructorReturn(this, (SplitterAnimator.__proto__ || Object.getPrototypeOf(SplitterAnimator)).call(this, { timing: timing, duration: duration, delay: delay }));
- }
-
- createClass(SplitterAnimator, [{
- key: 'updateOptions',
- value: function updateOptions() {
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
-
- util$1.extend(this, {
- timing: this.timing, duration: this.duration, delay: this.delay
- }, options);
- }
-
- /**
- * @param {Element} sideElement
- */
-
- }, {
- key: 'activate',
- value: function activate(sideElement) {
- var _this2 = this;
-
- var splitter = sideElement.parentNode;
-
- contentReady(splitter, function () {
- _this2._side = sideElement;
- _this2._oppositeSide = splitter.right !== sideElement && splitter.right || splitter.left !== sideElement && splitter.left;
- _this2._content = splitter.content;
- _this2._mask = splitter.mask;
- });
- }
- }, {
- key: 'deactivate',
- value: function deactivate() {
- this.clearTransition();
- this._mask && this.clearMask();
- this._content = this._side = this._oppositeSide = this._mask = null;
- }
- }, {
- key: 'clearTransition',
- value: function clearTransition() {
- var _this3 = this;
-
- 'side mask content'.split(/\s+/).forEach(function (e) {
- return _this3['_' + e] && styler.clear(_this3['_' + e], 'transform transition');
- });
- }
- }, {
- key: 'clearMask',
- value: function clearMask() {
- // Check if the other side needs the mask before clearing
- if (!this._oppositeSide || this._oppositeSide.mode === 'split' || !this._oppositeSide.isOpen) {
- this._mask.style.opacity = '';
- this._mask.style.display = 'none';
- }
- }
-
- /**
- * @param {Number} distance
- */
-
- }, {
- key: 'translate',
- value: function translate(distance) {}
-
- /**
- * @param {Function} done
- */
-
- }, {
- key: 'open',
- value: function open(done) {
- done();
- }
-
- /**
- * @param {Function} done
- */
-
- }, {
- key: 'close',
- value: function close(done) {
- done();
- }
- }, {
- key: 'minus',
- get: function get$$1() {
- return this._side.side === 'right' ? '-' : '';
- }
- }]);
- return SplitterAnimator;
- }(BaseAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var OverlaySplitterAnimator = function (_SplitterAnimator) {
- inherits(OverlaySplitterAnimator, _SplitterAnimator);
-
- function OverlaySplitterAnimator() {
- classCallCheck(this, OverlaySplitterAnimator);
- return possibleConstructorReturn(this, (OverlaySplitterAnimator.__proto__ || Object.getPrototypeOf(OverlaySplitterAnimator)).apply(this, arguments));
- }
-
- createClass(OverlaySplitterAnimator, [{
- key: 'translate',
- value: function translate(distance) {
- this._mask.style.display = 'block'; // Avoid content clicks
-
- Animit(this._side).queue({
- transform: 'translate3d(' + (this.minus + distance) + 'px, 0, 0)'
- }).play();
- }
-
- /**
- * @param {Function} done
- */
-
- }, {
- key: 'open',
- value: function open(done) {
- Animit.runAll(Animit(this._side).wait(this.delay).queue({
- transform: 'translate3d(' + this.minus + '100%, 0, 0)'
- }, this.def).queue(function (callback) {
- callback();
- done && done();
- }), Animit(this._mask).wait(this.delay).queue({
- display: 'block'
- }).queue({
- opacity: '1'
- }, {
- duration: this.duration,
- timing: 'linear'
- }));
- }
-
- /**
- * @param {Function} done
- */
-
- }, {
- key: 'close',
- value: function close(done) {
-
- Animit.runAll(Animit(this._side).wait(this.delay).queue({
- transform: 'translate3d(0, 0, 0)'
- }, this.def).queue(function (callback) {
- done && done();
- callback();
- }), Animit(this._mask).wait(this.delay).queue({
- opacity: '0'
- }, {
- duration: this.duration,
- timing: 'linear'
- }).queue({
- display: 'none'
- }));
- }
- }]);
- return OverlaySplitterAnimator;
- }(SplitterAnimator$1);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var PushSplitterAnimator = function (_SplitterAnimator) {
- inherits(PushSplitterAnimator, _SplitterAnimator);
-
- function PushSplitterAnimator() {
- classCallCheck(this, PushSplitterAnimator);
- return possibleConstructorReturn(this, (PushSplitterAnimator.__proto__ || Object.getPrototypeOf(PushSplitterAnimator)).apply(this, arguments));
- }
-
- createClass(PushSplitterAnimator, [{
- key: '_getSlidingElements',
- value: function _getSlidingElements() {
- var slidingElements = [this._side, this._content];
- if (this._oppositeSide && this._oppositeSide.mode === 'split') {
- slidingElements.push(this._oppositeSide);
- }
-
- return slidingElements;
- }
- }, {
- key: 'translate',
- value: function translate(distance) {
- if (!this._slidingElements) {
- this._slidingElements = this._getSlidingElements();
- }
-
- this._mask.style.display = 'block'; // Avoid content clicks
-
- Animit(this._slidingElements).queue({
- transform: 'translate3d(' + (this.minus + distance) + 'px, 0, 0)'
- }).play();
- }
-
- /**
- * @param {Function} done
- */
-
- }, {
- key: 'open',
- value: function open(done) {
- var _this2 = this;
-
- var max = this._side.offsetWidth;
- this._slidingElements = this._getSlidingElements();
-
- Animit.runAll(Animit(this._slidingElements).wait(this.delay).queue({
- transform: 'translate3d(' + (this.minus + max) + 'px, 0, 0)'
- }, this.def).queue(function (callback) {
- _this2._slidingElements = null;
- callback();
- done && done();
- }), Animit(this._mask).wait(this.delay).queue({
- display: 'block'
- }));
- }
-
- /**
- * @param {Function} done
- */
-
- }, {
- key: 'close',
- value: function close(done) {
- var _this3 = this;
-
- this._slidingElements = this._getSlidingElements();
-
- Animit.runAll(Animit(this._slidingElements).wait(this.delay).queue({
- transform: 'translate3d(0, 0, 0)'
- }, this.def).queue(function (callback) {
- _this3._slidingElements = null;
- get(PushSplitterAnimator.prototype.__proto__ || Object.getPrototypeOf(PushSplitterAnimator.prototype), 'clearTransition', _this3).call(_this3);
- done && done();
- callback();
- }), Animit(this._mask).wait(this.delay).queue({
- display: 'none'
- }));
- }
- }]);
- return PushSplitterAnimator;
- }(SplitterAnimator$1);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var RevealSplitterAnimator = function (_SplitterAnimator) {
- inherits(RevealSplitterAnimator, _SplitterAnimator);
-
- function RevealSplitterAnimator() {
- classCallCheck(this, RevealSplitterAnimator);
- return possibleConstructorReturn(this, (RevealSplitterAnimator.__proto__ || Object.getPrototypeOf(RevealSplitterAnimator)).apply(this, arguments));
- }
-
- createClass(RevealSplitterAnimator, [{
- key: '_getSlidingElements',
- value: function _getSlidingElements() {
- var slidingElements = [this._content, this._mask];
- if (this._oppositeSide && this._oppositeSide.mode === 'split') {
- slidingElements.push(this._oppositeSide);
- }
-
- return slidingElements;
- }
- }, {
- key: 'activate',
- value: function activate(sideElement) {
- get(RevealSplitterAnimator.prototype.__proto__ || Object.getPrototypeOf(RevealSplitterAnimator.prototype), 'activate', this).call(this, sideElement);
- if (sideElement.mode === 'collapse') {
- this._setStyles(sideElement);
- }
- }
- }, {
- key: 'deactivate',
- value: function deactivate() {
- this._side && this._unsetStyles(this._side);
- get(RevealSplitterAnimator.prototype.__proto__ || Object.getPrototypeOf(RevealSplitterAnimator.prototype), 'deactivate', this).call(this);
- }
- }, {
- key: '_setStyles',
- value: function _setStyles(sideElement) {
- styler(sideElement, {
- left: sideElement.side === 'right' ? 'auto' : 0,
- right: sideElement.side === 'right' ? 0 : 'auto',
- zIndex: 0,
- backgroundColor: 'black',
- transform: this._generateBehindPageStyle(0).container.transform,
- display: 'none'
- });
-
- var splitter = sideElement.parentElement;
- contentReady(splitter, function () {
- return splitter.content && styler(splitter.content, { boxShadow: '0 0 12px 0 rgba(0, 0, 0, 0.2)' });
- });
- }
- }, {
- key: '_unsetStyles',
- value: function _unsetStyles(sideElement) {
- styler.clear(sideElement, 'left right zIndex backgroundColor display');
- if (sideElement._content) {
- sideElement._content.style.opacity = '';
- }
-
- // Check if the other side needs the common styles
- if (!this._oppositeSide || this._oppositeSide.mode === 'split') {
- sideElement.parentElement.content && styler.clear(sideElement.parentElement.content, 'boxShadow');
- }
- }
- }, {
- key: '_generateBehindPageStyle',
- value: function _generateBehindPageStyle(distance) {
- var max = this.maxWidth;
-
- var behindDistance = (distance - max) / max * 10;
- behindDistance = isNaN(behindDistance) ? 0 : Math.max(Math.min(behindDistance, 0), -10);
-
- var behindTransform = 'translate3d(' + (this.minus ? -1 : 1) * behindDistance + '%, 0, 0)';
- var opacity = 1 + behindDistance / 100;
-
- return {
- content: {
- opacity: opacity
- },
- container: {
- transform: behindTransform
- }
- };
- }
- }, {
- key: 'translate',
- value: function translate(distance) {
- this._side.style.display = '';
- this._side.style.zIndex = 1;
- this.maxWidth = this.maxWidth || this._getMaxWidth();
- var menuStyle = this._generateBehindPageStyle(Math.min(distance, this.maxWidth));
-
- if (!this._slidingElements) {
- this._slidingElements = this._getSlidingElements();
- }
-
- this._mask.style.display = 'block'; // Avoid content clicks
-
- Animit.runAll(Animit(this._slidingElements).queue({
- transform: 'translate3d(' + (this.minus + distance) + 'px, 0, 0)'
- }), Animit(this._side._content).queue(menuStyle.content), Animit(this._side).queue(menuStyle.container));
- }
-
- /**
- * @param {Function} done
- */
-
- }, {
- key: 'open',
- value: function open(done) {
- var _this2 = this;
-
- this._side.style.display = '';
- this._side.style.zIndex = 1;
- this.maxWidth = this.maxWidth || this._getMaxWidth();
- var menuStyle = this._generateBehindPageStyle(this.maxWidth);
- this._slidingElements = this._getSlidingElements();
-
- setTimeout(function () {
- // Fix: Time to update previous translate3d after changing style.display
- Animit.runAll(Animit(_this2._slidingElements).wait(_this2.delay).queue({
- transform: 'translate3d(' + (_this2.minus + _this2.maxWidth) + 'px, 0, 0)'
- }, _this2.def), Animit(_this2._mask).wait(_this2.delay).queue({
- display: 'block'
- }), Animit(_this2._side._content).wait(_this2.delay).queue(menuStyle.content, _this2.def), Animit(_this2._side).wait(_this2.delay).queue(menuStyle.container, _this2.def).queue(function (callback) {
- _this2._slidingElements = null;
- callback();
- done && done();
- }));
- }, 1000 / 60);
- }
-
- /**
- * @param {Function} done
- */
-
- }, {
- key: 'close',
- value: function close(done) {
- var _this3 = this;
-
- var menuStyle = this._generateBehindPageStyle(0);
- this._slidingElements = this._getSlidingElements();
-
- Animit.runAll(Animit(this._slidingElements).wait(this.delay).queue({
- transform: 'translate3d(0, 0, 0)'
- }, this.def), Animit(this._mask).wait(this.delay).queue({
- display: 'none'
- }), Animit(this._side._content).wait(this.delay).queue(menuStyle.content, this.def), Animit(this._side).wait(this.delay).queue(menuStyle.container, this.def).queue(function (callback) {
- _this3._slidingElements = null;
- _this3._side.style.zIndex = 0;
- _this3._side.style.display = 'none';
- _this3._side._content.style.opacity = '';
- done && done();
- callback();
- }));
- }
- }, {
- key: '_getMaxWidth',
- value: function _getMaxWidth() {
- return this._side.offsetWidth;
- }
- }]);
- return RevealSplitterAnimator;
- }(SplitterAnimator$1);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var _animatorDict$7 = {
- default: OverlaySplitterAnimator,
- overlay: OverlaySplitterAnimator,
- push: PushSplitterAnimator,
- reveal: RevealSplitterAnimator
- };
-
- /**
- * @element ons-splitter
- * @category menu
- * @description
- * [en]
- * A component that enables responsive layout by implementing both a two-column layout and a sliding menu layout.
- *
- * It can be configured to automatically expand into a column layout on large screens and collapse the menu on smaller screens. When the menu is collapsed the user can open it by swiping.
- * [/en]
- * [ja][/ja]
- * @codepen rOQOML
- * @tutorial vanilla/Reference/splitter
- * @guide fundamentals.html#managing-pages
- * [en]Managing multiple pages.[/en]
- * [ja]複数のページを管理する[/ja]
- * @seealso ons-splitter-content
- * [en]The `<ons-splitter-content>` component contains the main content of the page.[/en]
- * [ja]ons-splitter-contentコンポーネント[/ja]
- * @seealso ons-splitter-side
- * [en]The `<ons-splitter-side>` component contains the menu.[/en]
- * [ja]ons-splitter-sideコンポーネント[/ja]
- * @example
- * <ons-splitter id="splitter">
- * <ons-splitter-content>
- * ...
- * </ons-splitter-content>
- *
- * <ons-splitter-side side="left" width="80%" collapse swipeable>
- * ...
- * </ons-splitter-side>
- * </ons-splitter>
- *
- * <script>
- * var splitter = document.getElementById('splitter');
- * splitter.left.open();
- * </script>
- */
-
- var SplitterElement = function (_BaseElement) {
- inherits(SplitterElement, _BaseElement);
- createClass(SplitterElement, [{
- key: '_getSide',
- value: function _getSide(side) {
- var element = util$1.findChild(this, function (e) {
- return util$1.match(e, 'ons-splitter-side') && e.getAttribute('side') === side;
- });
- return element;
- }
-
- /**
- * @property left
- * @readonly
- * @type {HTMLElement}
- * @description
- * [en]Left `<ons-splitter-side>` element.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: '_onDeviceBackButton',
- value: function _onDeviceBackButton(event) {
- this._sides.some(function (s) {
- return s.isOpen ? s.close() : false;
- }) || event.callParentHandler();
- }
- }, {
- key: '_onModeChange',
- value: function _onModeChange(e) {
- var _this2 = this;
-
- if (e.target.parentNode) {
- contentReady(this, function () {
- _this2._layout();
- });
- }
- }
- }, {
- key: '_layout',
- value: function _layout() {
- var _this3 = this;
-
- this._sides.forEach(function (side) {
- if (_this3.content) {
- _this3.content.style[side.side] = side.mode === 'split' ? side.style.width : 0;
- }
- });
- }
- }, {
- key: 'left',
- get: function get$$1() {
- return this._getSide('left');
- }
- /**
- * @property right
- * @readonly
- * @type {HTMLElement}
- * @description
- * [en]Right `<ons-splitter-side>` element.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'right',
- get: function get$$1() {
- return this._getSide('right');
- }
-
- /**
- * @property side
- * @readonly
- * @type {HTMLElement}
- * @description
- * [en]First `<ons-splitter-side>` element regardless the actual side.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'side',
- get: function get$$1() {
- return util$1.findChild(this, 'ons-splitter-side');
- }
- }, {
- key: '_sides',
- get: function get$$1() {
- return [this.left, this.right].filter(function (e) {
- return e;
- });
- }
- /**
- * @property content
- * @readonly
- * @type {HTMLElement}
- * @description
- * [en]The `<ons-splitter-content>` element.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'content',
- get: function get$$1() {
- return util$1.findChild(this, 'ons-splitter-content');
- }
- }, {
- key: 'topPage',
- get: function get$$1() {
- return this.content._content;
- }
- }, {
- key: 'mask',
- get: function get$$1() {
- return util$1.findChild(this, 'ons-splitter-mask');
- }
-
- /**
- * @property onDeviceBackButton
- * @type {Object}
- * @description
- * [en]Back-button handler.[/en]
- * [ja]バックボタンハンドラ。[/ja]
- */
-
- }, {
- key: 'onDeviceBackButton',
- get: function get$$1() {
- return this._backButtonHandler;
- },
- set: function set$$1(callback) {
- if (this._backButtonHandler) {
- this._backButtonHandler.destroy();
- }
-
- this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, callback);
- }
- }]);
-
- function SplitterElement() {
- classCallCheck(this, SplitterElement);
-
- var _this = possibleConstructorReturn(this, (SplitterElement.__proto__ || Object.getPrototypeOf(SplitterElement)).call(this));
-
- _this._onModeChange = _this._onModeChange.bind(_this);
-
- contentReady(_this, function () {
- !_this.mask && _this.appendChild(document.createElement('ons-splitter-mask'));
- _this._layout();
- });
- return _this;
- }
-
- createClass(SplitterElement, [{
- key: 'connectedCallback',
- value: function connectedCallback() {
- this.onDeviceBackButton = this._onDeviceBackButton.bind(this);
- this.addEventListener('modechange', this._onModeChange, false);
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- this._backButtonHandler.destroy();
- this._backButtonHandler = null;
- this.removeEventListener('modechange', this._onModeChange, false);
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {}
- }, {
- key: '_show',
- value: function _show() {
- util$1.propagateAction(this, '_show');
- }
- }, {
- key: '_hide',
- value: function _hide() {
- util$1.propagateAction(this, '_hide');
- }
- }, {
- key: '_destroy',
- value: function _destroy() {
- util$1.propagateAction(this, '_destroy');
- this.remove();
- }
- }], [{
- key: 'registerAnimator',
- value: function registerAnimator(name, Animator) {
- if (!(Animator instanceof SplitterAnimator)) {
- util$1.throwAnimator('Splitter');
- }
- _animatorDict$7[name] = Animator;
- }
- }, {
- key: 'SplitterAnimator',
- get: function get$$1() {
- return SplitterAnimator;
- }
- }, {
- key: 'animators',
- get: function get$$1() {
- return _animatorDict$7;
- }
- }]);
- return SplitterElement;
- }(BaseElement);
-
- onsElements.Splitter = SplitterElement;
- customElements.define('ons-splitter', SplitterElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var SPLIT_MODE = 'split';
- var COLLAPSE_MODE = 'collapse';
- var CLOSED_STATE = 'closed';
- var OPEN_STATE = 'open';
- var CHANGING_STATE = 'changing';
-
- var rewritables$2 = {
- /**
- * @param {Element} splitterSideElement
- * @param {Function} callback
- */
- ready: function ready(splitterSideElement, callback) {
- setImmediate(callback);
- }
- };
-
- var CollapseDetection = function () {
- function CollapseDetection(element, target) {
- classCallCheck(this, CollapseDetection);
-
- this._element = element;
- this._onChange = this._onChange.bind(this);
- target && this.changeTarget(target);
- }
-
- createClass(CollapseDetection, [{
- key: 'changeTarget',
- value: function changeTarget(target) {
- this.disable();
- this._target = target;
- if (target) {
- this._orientation = ['portrait', 'landscape'].indexOf(target) !== -1;
- this.activate();
- }
- }
- }, {
- key: '_match',
- value: function _match(value) {
- if (this._orientation) {
- return this._target === (value.isPortrait ? 'portrait' : 'landscape');
- }
- return value.matches;
- }
- }, {
- key: '_onChange',
- value: function _onChange(value) {
- this._element._updateMode(this._match(value) ? COLLAPSE_MODE : SPLIT_MODE);
- }
- }, {
- key: 'activate',
- value: function activate() {
- if (this._orientation) {
- orientation.on('change', this._onChange);
- this._onChange({ isPortrait: orientation.isPortrait() });
- } else {
- this._queryResult = window.matchMedia(this._target);
- this._queryResult.addListener(this._onChange);
- this._onChange(this._queryResult);
- }
- }
- }, {
- key: 'disable',
- value: function disable() {
- if (this._orientation) {
- orientation.off('change', this._onChange);
- } else if (this._queryResult) {
- this._queryResult.removeListener(this._onChange);
- this._queryResult = null;
- }
- }
- }]);
- return CollapseDetection;
- }();
-
- /**
- * @element ons-splitter-side
- * @category menu
- * @description
- * [en]
- * The `<ons-splitter-side>` element is used as a child element of `<ons-splitter>`.
- *
- * It will be displayed on either the left or right side of the `<ons-splitter-content>` element.
- *
- * It supports two modes: collapsed and split. When it's in collapsed mode it will be hidden from view and can be displayed when the user swipes the screen or taps a button. In split mode the element is always shown. It can be configured to automatically switch between the two modes depending on the screen size.
- * [/en]
- * [ja]ons-splitter-side要素は、ons-splitter要素の子要素として利用します。[/ja]
- * @codepen rOQOML
- * @tutorial vanilla/Reference/splitter
- * @guide fundamentals.html#managing-pages
- * [en]Managing multiple pages.[/en]
- * [ja]複数のページを管理する[/ja]
- * @seealso ons-splitter
- * [en]The `<ons-splitter>` is the parent component.[/en]
- * [ja]ons-splitterコンポーネント[/ja]
- * @seealso ons-splitter-content
- * [en]The `<ons-splitter-content>` component contains the main content of the page.[/en]
- * [ja]ons-splitter-contentコンポーネント[/ja]
- * @example
- * <ons-splitter>
- * <ons-splitter-content>
- * ...
- * </ons-splitter-content>
- *
- * <ons-splitter-side side="left" width="80%" collapse>
- * ...
- * </ons-splitter-side>
- * </ons-splitter>
- */
-
- var SplitterSideElement = function (_BaseElement) {
- inherits(SplitterSideElement, _BaseElement);
-
- /**
- * @event modechange
- * @description
- * [en]Fired just after the component's mode changes.[/en]
- * [ja]この要素のモードが変化した際に発火します。[/ja]
- * @param {Object} event
- * [en]Event object.[/en]
- * [ja]イベントオブジェクトです。[/ja]
- * @param {Object} event.side
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- * @param {String} event.mode
- * [en]Returns the current mode. Can be either `"collapse"` or `"split"`.[/en]
- * [ja]現在のモードを返します。[/ja]
- */
-
- /**
- * @event preopen
- * @description
- * [en]Fired just before the sliding menu is opened.[/en]
- * [ja]スライディングメニューが開く前に発火します。[/ja]
- * @param {Object} event
- * [en]Event object.[/en]
- * [ja]イベントオブジェクトです。[/ja]
- * @param {Function} event.cancel
- * [en]Call to cancel opening sliding menu.[/en]
- * [ja]スライディングメニューが開くのをキャンセルします。[/ja]
- * @param {Object} event.side
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- */
-
- /**
- * @event postopen
- * @description
- * [en]Fired just after the sliding menu is opened.[/en]
- * [ja]スライディングメニューが開いた後に発火します。[/ja]
- * @param {Object} event
- * [en]Event object.[/en]
- * [ja]イベントオブジェクトです。[/ja]
- * @param {Object} event.side
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- */
-
- /**
- * @event preclose
- * @description
- * [en]Fired just before the sliding menu is closed.[/en]
- * [ja]スライディングメニューが閉じる前に発火します。[/ja]
- * @param {Object} event
- * [en]Event object.[/en]
- * [ja]イベントオブジェクトです。[/ja]
- * @param {Object} event.side
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- * @param {Function} event.cancel
- * [en]Call to cancel opening sliding-menu.[/en]
- * [ja]スライディングメニューが閉じるのをキャンセルします。[/ja]
- */
-
- /**
- * @event postclose
- * @description
- * [en]Fired just after the sliding menu is closed.[/en]
- * [ja]スライディングメニューが閉じた後に発火します。[/ja]
- * @param {Object} event
- * [en]Event object.[/en]
- * [ja]イベントオブジェクトです。[/ja]
- * @param {Object} event.side
- * [en]Component object.[/en]
- * [ja]コンポーネントのオブジェクト。[/ja]
- */
-
- /**
- * @attribute animation
- * @type {String}
- * @default default
- * @description
- * [en]Specify the animation. Use one of `overlay`, `push`, `reveal` or `default`.[/en]
- * [ja]アニメーションを指定します。"overlay", "push", "reveal", "default"のいずれかを指定できます。[/ja]
- */
-
- /**
- * @attribute animation-options
- * @type {Expression}
- * @description
- * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. {duration: 0.2, delay: 1, timing: 'ease-in'}[/ja]
- */
-
- /**
- * @attribute open-threshold
- * @type {Number}
- * @default 0.3
- * @description
- * [en]Specify how much the menu needs to be swiped before opening. A value between `0` and `1`.[/en]
- * [ja]どのくらいスワイプすればスライディングメニューを開くかどうかの割合を指定します。0から1の間の数値を指定します。スワイプの距離がここで指定した数値掛けるこの要素の幅よりも大きければ、スワイプが終わった時にこの要素を開きます。デフォルトは0.3です。[/ja]
- */
-
- /**
- * @attribute collapse
- * @type {String}
- * @description
- * [en]
- * Specify the collapse behavior. Valid values are `"portrait"`, `"landscape"` or a media query.
- * The strings `"portrait"` and `"landscape"` means the view will collapse when device is in landscape or portrait orientation.
- * If the value is a media query, the view will collapse when the media query resolves to `true`.
- * If the value is not defined, the view always be in `"collapse"` mode.
- * [/en]
- * [ja]
- * 左側のページを非表示にする条件を指定します。portrait, landscape、width #pxもしくはメディアクエリの指定が可能です。
- * portraitもしくはlandscapeを指定すると、デバイスの画面が縦向きもしくは横向きになった時に適用されます。
- * メディアクエリを指定すると、指定したクエリに適合している場合に適用されます。
- * 値に何も指定しない場合には、常にcollapseモードになります。
- * [/ja]
- */
-
- /**
- * @attribute swipe-target-width
- * @type {String}
- * @description
- * [en]The width of swipeable area calculated from the edge (in pixels). Use this to enable swipe only when the finger touch on the screen edge.[/en]
- * [ja]スワイプの判定領域をピクセル単位で指定します。画面の端から指定した距離に達するとページが表示されます。[/ja]
- */
-
- /**
- * @attribute width
- * @type {String}
- * @description
- * [en]Can be specified in either pixels or as a percentage, e.g. `90%` or `200px`.[/en]
- * [ja]この要素の横幅を指定します。pxと%での指定が可能です。eg. 90%, 200px[/ja]
- */
-
- /**
- * @attribute side
- * @type {String}
- * @default left
- * @description
- * [en]Specify which side of the screen the `<ons-splitter-side>` element is located. Possible values are `"left"` and `"right"`.[/en]
- * [ja]この要素が左か右かを指定します。指定できる値は"left"か"right"のみです。[/ja]
- */
-
- /**
- * @attribute mode
- * @type {String}
- * @description
- * [en]Current mode. Possible values are `"collapse"` or `"split"`. This attribute is read only.[/en]
- * [ja]現在のモードが設定されます。"collapse"もしくは"split"が指定されます。この属性は読み込み専用です。[/ja]
- */
-
- /**
- * @attribute page
- * @initonly
- * @type {String}
- * @description
- * [en]The URL of the menu page.[/en]
- * [ja]ons-splitter-side要素に表示するページのURLを指定します。[/ja]
- */
-
- /**
- * @attribute swipeable
- * @type {Boolean}
- * @description
- * [en]Whether to enable swipe interaction on collapse mode.[/en]
- * [ja]collapseモード時にスワイプ操作を有効にする場合に指定します。[/ja]
- */
-
- function SplitterSideElement() {
- classCallCheck(this, SplitterSideElement);
-
- var _this = possibleConstructorReturn(this, (SplitterSideElement.__proto__ || Object.getPrototypeOf(SplitterSideElement)).call(this));
-
- _this._page = null;
- _this._state = CLOSED_STATE;
- _this._lock = new DoorLock();
- _this._pageLoader = defaultPageLoader;
- _this._collapseDetection = new CollapseDetection(_this);
-
- _this._animatorFactory = new AnimatorFactory({
- animators: SplitterElement.animators,
- baseClass: SplitterAnimator$1,
- baseClassName: 'SplitterAnimator',
- defaultAnimation: _this.getAttribute('animation')
- });
-
- contentReady(_this, function () {
- // These attributes are used early by the parent element
- _this.attributeChangedCallback('width');
- if (!_this.hasAttribute('side')) {
- _this.setAttribute('side', 'left');
- }
-
- rewritables$2.ready(_this, function () {
- var page = _this._page || _this.getAttribute('page');
- page && _this.load(page);
- });
- });
- return _this;
- }
-
- createClass(SplitterSideElement, [{
- key: 'connectedCallback',
- value: function connectedCallback() {
- var _this2 = this;
-
- if (!util$1.match(this.parentNode, 'ons-splitter')) {
- util$1.throw('Parent must be an ons-splitter element');
- }
-
- this._swipe = new SwipeReveal({
- element: this,
- elementHandler: this.parentElement,
- swipeMax: function swipeMax() {
- _this2._onSwipe && _this2._onSwipe(1, _this2._animationOpt);
- _this2.open();
- },
- swipeMid: function swipeMid(distance, width) {
- _this2._onSwipe && _this2._onSwipe(distance / width);
- _this2._animator.translate(distance);
- },
- swipeMin: function swipeMin() {
- _this2._onSwipe && _this2._onSwipe(0, _this2._animationOpt);
- _this2.close();
- },
- getThreshold: function getThreshold() {
- return Math.max(0, Math.min(1, parseFloat(_this2.getAttribute('open-threshold')) || 0.3));
- },
- getSide: function getSide() {
- return _this2.side;
- },
- isInitialState: function isInitialState() {
- var closed = _this2._state === CLOSED_STATE;
- _this2._state = CHANGING_STATE;
- return closed;
- },
- ignoreSwipe: function ignoreSwipe(event, distance) {
- var isOpen = _this2.isOpen;
- var validDrag = function validDrag(d) {
- return _this2.side === 'left' ? d === 'left' && isOpen || d === 'right' && !isOpen : d === 'left' && !isOpen || d === 'right' && isOpen;
- };
-
- var area = Math.max(0, parseInt(_this2.getAttribute('swipe-target-width'), 10) || 0);
-
- return _this2._mode === SPLIT_MODE || _this2._lock.isLocked() || _this2._isOtherSideOpen() || !validDrag(event.gesture.direction) || !isOpen && area !== 0 && distance > area;
- }
- });
-
- this.attributeChangedCallback('swipeable');
-
- contentReady(this, function () {
- _this2.constructor.observedAttributes.forEach(function (attr) {
- return _this2.attributeChangedCallback(attr, null, _this2.getAttribute(attr));
- });
- });
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- this._swipe && this._swipe.dispose();
- this._animator = this._animationOpt = this._swipe = null;
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'swipeable':
- this._swipe && this._swipe.update();
- break;
- case 'width':
- current = this.getAttribute('width'); // Sometimes undefined. CE bug?
- this.style.width = /^\d+(px|%)$/.test(current) ? current : '80%';
- break;
- default:
- this[util$1.camelize('_update-' + name)](current);
- }
- }
- }, {
- key: '_emitEvent',
- value: function _emitEvent(name) {
- if (name.slice(0, 3) !== 'pre') {
- return util$1.triggerElementEvent(this, name, { side: this });
- }
- var isCanceled = false;
-
- util$1.triggerElementEvent(this, name, {
- side: this,
- cancel: function cancel() {
- return isCanceled = true;
- }
- });
-
- return isCanceled;
- }
- }, {
- key: '_isOtherSideOpen',
- value: function _isOtherSideOpen() {
- var _this3 = this;
-
- return !!util$1.findChild(this.parentElement, function (el) {
- return el instanceof _this3.constructor && el !== _this3 && el._mode === COLLAPSE_MODE && el.isOpen;
- });
- }
- }, {
- key: '_updateCollapse',
- value: function _updateCollapse() {
- var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('collapse');
-
- if (value === null || value === 'split') {
- this._collapseDetection.disable();
- return this._updateMode(SPLIT_MODE);
- }
- if (value === '' || value === 'collapse') {
- this._collapseDetection.disable();
- return this._updateMode(COLLAPSE_MODE);
- }
-
- this._collapseDetection.changeTarget(value);
- }
- }, {
- key: '_updateMode',
- value: function _updateMode(mode) {
- if (mode !== this._mode) {
- this._mode = mode;
- this.setAttribute('mode', mode); // readonly attribute for the users
-
- if (mode === SPLIT_MODE) {
- this._animator && this._animator.deactivate();
- this._state = CLOSED_STATE;
- } else {
- this._animator && this._animator.activate(this);
- this._state === OPEN_STATE && this._animator.open();
- }
-
- util$1.triggerElementEvent(this, 'modechange', { side: this, mode: mode });
- }
- }
- }, {
- key: '_updateAnimation',
- value: function _updateAnimation() {
- var animation = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('animation');
-
- if (this.parentNode) {
- this._animator && this._animator.deactivate();
- this._animator = this._animatorFactory.newAnimator({ animation: animation });
- this._animator.activate(this);
- this._animationOpt = {
- timing: this._animator.duration,
- duration: this._animator.duration
- };
- }
- }
- }, {
- key: '_updateAnimationOptions',
- value: function _updateAnimationOptions() {
- var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('animation-options');
-
- this._animator.updateOptions(AnimatorFactory.parseAnimationOptionsString(value));
- }
-
- /**
- * @property page
- * @type {*}
- * @description
- * [en]Page location to load in the splitter side.[/en]
- * [ja]この要素内に表示するページを指定します。[/ja]
- */
-
- }, {
- key: 'open',
-
-
- /**
- * @method open
- * @signature open([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {Function} [options.callback]
- * [en]This function will be called after the menu has been opened.[/en]
- * [ja]メニューが開いた後に呼び出される関数オブジェクトを指定します。[/ja]
- * @description
- * [en]Open menu in collapse mode.[/en]
- * [ja]collapseモードになっているons-splitter-side要素を開きます。[/ja]
- * @return {Promise}
- * [en]Resolves to the splitter side element or false if not in collapse mode[/en]
- * [ja][/ja]
- */
- value: function open(options) {
- return this.toggle(options, true);
- }
-
- /**
- * @method close
- * @signature close([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {Function} [options.callback]
- * [en]This function will be called after the menu has been closed.[/en]
- * [ja]メニューが閉じた後に呼び出される関数オブジェクトを指定します。[/ja]
- * @description
- * [en]Close menu in collapse mode.[/en]
- * [ja]collapseモードになっているons-splitter-side要素を閉じます。[/ja]
- * @return {Promise}
- * [en]Resolves to the splitter side element or false if not in collapse mode[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'close',
- value: function close(options) {
- return this.toggle(options, false);
- }
-
- /**
- * @method toggle
- * @signature toggle([options])
- * @param {Object} [options]
- * @description
- * [en]Opens if it's closed. Closes if it's open.[/en]
- * [ja]開けている場合は要素を閉じますそして開けている場合は要素を開きます。[/ja]
- * @return {Promise}
- * [en]Resolves to the splitter side element or false if not in collapse mode[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'toggle',
- value: function toggle() {
- var _this4 = this;
-
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var force = arguments[1];
-
- var shouldOpen = typeof force === 'boolean' ? force : !this.isOpen;
- var action = shouldOpen ? 'open' : 'close';
- var FINAL_STATE = shouldOpen ? OPEN_STATE : CLOSED_STATE;
-
- if (this._mode === SPLIT_MODE) {
- return Promise.resolve(false);
- }
- if (this._state === FINAL_STATE) {
- return Promise.resolve(this);
- }
- if (this._lock.isLocked()) {
- return Promise.reject('Another splitter-side action is already running.');
- }
- if (shouldOpen && this._isOtherSideOpen()) {
- return Promise.reject('Another menu is already open.');
- }
- if (this._emitEvent('pre' + action)) {
- return Promise.reject('Canceled in pre' + action + ' event.');
- }
-
- var unlock = this._lock.lock();
- this._state = CHANGING_STATE;
-
- if (options.animation) {
- this._updateAnimation(options.animation);
- }
-
- return new Promise(function (resolve) {
- _this4._animator[action](function () {
- util$1.iosPageScrollFix(shouldOpen);
- _this4._state = FINAL_STATE;
- unlock();
- _this4._emitEvent('post' + action);
- options.callback instanceof Function && options.callback(_this4);
- resolve(_this4);
- });
- });
- }
-
- /**
- * @method load
- * @signature load(page, [options])
- * @param {String} page
- * [en]Page URL. Can be either an HTML document or a `<template>`.[/en]
- * [ja]pageのURLか、`<template>`で宣言したテンプレートのid属性の値を指定します。[/ja]
- * @param {Object} [options]
- * @param {Function} [options.callback]
- * @description
- * [en]Show the page specified in pageUrl in the right section[/en]
- * [ja]指定したURLをメインページを読み込みます。[/ja]
- * @return {Promise}
- * [en]Resolves to the new page element[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'load',
- value: function load(page) {
- var _this5 = this;
-
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- this._page = page;
- var callback = options.callback || function () {};
-
- return new Promise(function (resolve) {
- var oldContent = _this5._content || null;
-
- _this5._pageLoader.load({ page: page, parent: _this5 }, function (pageElement) {
- if (oldContent) {
- _this5._pageLoader.unload(oldContent);
- oldContent = null;
- }
-
- setImmediate(function () {
- return _this5._show();
- });
-
- callback(pageElement);
- resolve(pageElement);
- });
- });
- }
- }, {
- key: '_show',
- value: function _show() {
- if (this._content) {
- this._content._show();
- }
- }
- }, {
- key: '_hide',
- value: function _hide() {
- if (this._content) {
- this._content._hide();
- }
- }
- }, {
- key: '_destroy',
- value: function _destroy() {
- if (this._content) {
- this._pageLoader.unload(this._content);
- }
- this.remove();
- }
- }, {
- key: 'side',
- get: function get$$1() {
- return this.getAttribute('side') === 'right' ? 'right' : 'left';
- }
- }, {
- key: 'page',
- get: function get$$1() {
- return this._page;
- }
-
- /**
- * @param {*} page
- */
- ,
- set: function set$$1(page) {
- this._page = page;
- }
- }, {
- key: '_content',
- get: function get$$1() {
- return this.children[0];
- }
-
- /**
- * @property pageLoader
- * @description
- * [en][/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'pageLoader',
- get: function get$$1() {
- return this._pageLoader;
- },
- set: function set$$1(loader) {
- if (!(loader instanceof PageLoader)) {
- util$1.throwPageLoader();
- }
- this._pageLoader = loader;
- }
-
- /**
- * @property mode
- * @readonly
- * @type {String}
- * @description
- * [en]Current mode. Possible values are "split", "collapse", "closed", "open" or "changing".[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'mode',
- get: function get$$1() {
- return this._mode;
- }
-
- /**
- * @property onSwipe
- * @type {Function}
- * @description
- * [en]Hook called whenever the user slides the splitter. It gets a decimal ratio (0-1) and an animationOptions object as arguments.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'onSwipe',
- get: function get$$1() {
- return this._onSwipe;
- },
- set: function set$$1(value) {
- if (value && !(value instanceof Function)) {
- util$1.throw('"onSwipe" must be a function');
- }
- this._onSwipe = value;
- }
-
- /**
- * @property isOpen
- * @type {Boolean}
- * @readonly
- * @description
- * [en]This value is `true` when the menu is open.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'isOpen',
- get: function get$$1() {
- return this._mode === COLLAPSE_MODE && this._state !== CLOSED_STATE;
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['animation', 'width', 'collapse', 'swipeable', 'animation-options'];
- }
- }, {
- key: 'events',
- get: function get$$1() {
- return ['preopen', 'postopen', 'preclose', 'postclose', 'modechange'];
- }
- }, {
- key: 'rewritables',
- get: function get$$1() {
- return rewritables$2;
- }
- }]);
- return SplitterSideElement;
- }(BaseElement);
-
- onsElements.SplitterSide = SplitterSideElement;
- customElements.define('ons-splitter-side', SplitterSideElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var scheme$28 = {
- '': 'switch--*',
- '.switch__input': 'switch--*__input',
- '.switch__handle': 'switch--*__handle',
- '.switch__toggle': 'switch--*__toggle'
- };
-
- var locations = {
- ios: [1, 21],
- material: [0, 16]
- };
-
- /**
- * @element ons-switch
- * @category form
- * @description
- * [en]
- * Switch component. The switch can be toggled both by dragging and tapping.
- *
- * Will automatically displays a Material Design switch on Android devices.
- * [/en]
- * [ja]スイッチを表示するコンポーネントです。[/ja]
- * @modifier material
- * [en]Material Design switch[/en]
- * [ja][/ja]
- * @codepen LpXZQQ
- * @tutorial vanilla/Reference/switch
- * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
- * @example
- * <ons-switch checked></ons-switch>
- * <ons-switch disabled></ons-switch>
- * <ons-switch modifier="material"></ons-switch>
- */
-
- var SwitchElement = function (_BaseCheckboxElement) {
- inherits(SwitchElement, _BaseCheckboxElement);
-
- function SwitchElement() {
- classCallCheck(this, SwitchElement);
-
- var _this = possibleConstructorReturn(this, (SwitchElement.__proto__ || Object.getPrototypeOf(SwitchElement)).call(this));
-
- contentReady(_this, function () {
- _this.attributeChangedCallback('modifier', null, _this.getAttribute('modifier'));
- });
-
- _this._onChange = _this._onChange.bind(_this);
- _this._onRelease = _this._onRelease.bind(_this);
- _this._lastTimeStamp = 0;
- return _this;
- }
-
- createClass(SwitchElement, [{
- key: '_getPosition',
-
-
- /* Own props */
-
- value: function _getPosition(e) {
- var l = this._locations;
- return Math.min(l[1], Math.max(l[0], this._startX + e.gesture.deltaX));
- }
- }, {
- key: '_emitChangeEvent',
- value: function _emitChangeEvent() {
- util$1.triggerElementEvent(this, 'change', {
- value: this.checked,
- switch: this,
- isInteractive: true
- });
- }
- }, {
- key: '_onChange',
- value: function _onChange(event) {
- if (event && event.stopPropagation) {
- event.stopPropagation();
- }
-
- this._emitChangeEvent();
- }
- }, {
- key: '_onClick',
- value: function _onClick(ev) {
- if (ev.target.classList.contains(this.defaultElementClass + '__touch') || ev.timeStamp - this._lastTimeStamp < 50 // Prevent second click triggered by <label>
- ) {
- ev.preventDefault();
- }
- this._lastTimeStamp = ev.timeStamp;
- }
- }, {
- key: '_onHold',
- value: function _onHold(e) {
- if (!this.disabled) {
- ModifierUtil.addModifier(this, 'active');
- document.addEventListener('release', this._onRelease);
- }
- }
- }, {
- key: '_onDragStart',
- value: function _onDragStart(e) {
- if (this.disabled || ['left', 'right'].indexOf(e.gesture.direction) === -1) {
- ModifierUtil.removeModifier(this, 'active');
- return;
- }
-
- e.consumed = true;
-
- ModifierUtil.addModifier(this, 'active');
- this._startX = this._locations[this.checked ? 1 : 0]; // - e.gesture.deltaX;
-
- this.addEventListener('drag', this._onDrag);
- document.addEventListener('release', this._onRelease);
- }
- }, {
- key: '_onDrag',
- value: function _onDrag(e) {
- e.stopPropagation();
- this._handle.style.left = this._getPosition(e) + 'px';
- }
- }, {
- key: '_onRelease',
- value: function _onRelease(e) {
- var l = this._locations;
- var position = this._getPosition(e);
- var previousValue = this.checked;
-
- this.checked = position >= (l[0] + l[1]) / 2;
-
- if (this.checked !== previousValue) {
- this._emitChangeEvent();
- }
-
- this.removeEventListener('drag', this._onDrag);
- document.removeEventListener('release', this._onRelease);
-
- this._handle.style.left = '';
- ModifierUtil.removeModifier(this, 'active');
- }
- }, {
- key: 'click',
- value: function click() {
- var ev = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
-
- if (!this.disabled) {
- this.checked = !this.checked;
- this._emitChangeEvent();
- this._lastTimeStamp = ev.timeStamp || 0;
- }
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- var _this2 = this;
-
- contentReady(this, function () {
- _this2._input.addEventListener('change', _this2._onChange);
- });
-
- this.addEventListener('dragstart', this._onDragStart);
- this.addEventListener('hold', this._onHold);
- this.addEventListener('tap', this.click);
- this.addEventListener('click', this._onClick);
- this._gestureDetector = new GestureDetector(this, { dragMinDistance: 1, holdTimeout: 251, passive: true });
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- var _this3 = this;
-
- contentReady(this, function () {
- _this3._input.removeEventListener('change', _this3._onChange);
- });
-
- this.removeEventListener('dragstart', this._onDragStart);
- this.removeEventListener('hold', this._onHold);
- this.removeEventListener('tap', this.click);
- this.removeEventListener('click', this._onClick);
- if (this._gestureDetector) {
- this._gestureDetector.dispose();
- }
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- if (name === 'modifier') {
- var md = (current || '').indexOf('material') !== -1;
- this._locations = locations[md ? 'material' : 'ios'];
- }
-
- get(SwitchElement.prototype.__proto__ || Object.getPrototypeOf(SwitchElement.prototype), 'attributeChangedCallback', this).call(this, name, last, current);
- }
-
- /**
- * @event change
- * @description
- * [en]Fired when the switch is toggled.[/en]
- * [ja]ON/OFFが変わった時に発火します。[/ja]
- * @param {Object} event
- * [en]Event object.[/en]
- * [ja]イベントオブジェクト。[/ja]
- * @param {Object} event.switch
- * [en]Switch object.[/en]
- * [ja]イベントが発火したSwitchオブジェクトを返します。[/ja]
- * @param {Boolean} event.value
- * [en]Current value.[/en]
- * [ja]現在の値を返します。[/ja]
- * @param {Boolean} event.isInteractive
- * [en]True if the change was triggered by the user clicking on the switch.[/en]
- * [ja]タップやクリックなどのユーザの操作によって変わった場合にはtrueを返します。[/ja]
- */
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the switch.[/en]
- * [ja]スイッチの表現を指定します。[/ja]
- */
-
- /**
- * @attribute disabled
- * @description
- * [en]Whether the switch is be disabled.[/en]
- * [ja]スイッチを無効の状態にする場合に指定します。[/ja]
- */
-
- /**
- * @attribute checked
- * @description
- * [en]Whether the switch is checked.[/en]
- * [ja]スイッチがONの状態にするときに指定します。[/ja]
- */
-
- /**
- * @attribute input-id
- * @type {String}
- * @description
- * [en]Specify the `id` attribute of the inner `<input>` element. This is useful when using `<label for="...">` elements.[/en]
- * [ja][/ja]
- */
-
- /**
- * @property checked
- * @type {Boolean}
- * @description
- * [en]This value is `true` if the switch is checked.[/en]
- * [ja]スイッチがONの場合に`true`。[/ja]
- */
-
- /**
- * @property value
- * @type {String}
- * @description
- * [en]The current value of the input.[/en]
- * [ja][/ja]
- */
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the element is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- /**
- * @property checkbox
- * @readonly
- * @type {HTMLElement}
- * @description
- * [en]The underlying checkbox element.[/en]
- * [ja]コンポーネント内部のcheckbox要素になります。[/ja]
- */
-
- }, {
- key: '_scheme',
- get: function get$$1() {
- return scheme$28;
- }
- }, {
- key: '_defaultClassName',
- get: function get$$1() {
- return 'switch';
- }
- }, {
- key: '_template',
- get: function get$$1() {
- return '\n <input type="' + this.type + '" class="' + this._defaultClassName + '__input">\n <div class="' + this._defaultClassName + '__toggle">\n <div class="' + this._defaultClassName + '__handle">\n <div class="' + this._defaultClassName + '__touch"></div>\n </div>\n </div>\n ';
- }
- }, {
- key: 'type',
- get: function get$$1() {
- return 'checkbox';
- }
- }, {
- key: '_handle',
- get: function get$$1() {
- return this.querySelector('.' + this._defaultClassName + '__handle');
- }
- }, {
- key: 'checkbox',
- get: function get$$1() {
- return this._input;
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return [].concat(toConsumableArray(get(SwitchElement.__proto__ || Object.getPrototypeOf(SwitchElement), 'observedAttributes', this)), ['modifier']);
- }
- }]);
- return SwitchElement;
- }(BaseCheckboxElement);
-
- onsElements.Switch = SwitchElement;
- customElements.define('ons-switch', SwitchElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var scheme$30 = {
- '.tabbar__content': 'tabbar--*__content',
- '.tabbar__border': 'tabbar--*__border',
- '.tabbar': 'tabbar--*'
- };
-
- var rewritables$3 = {
- /**
- * @param {Element} tabbarElement
- * @param {Function} callback
- */
- ready: function ready(tabbarElement, callback) {
- callback();
- }
- };
-
- var lerp = function lerp(x0, x1, t) {
- return (1 - t) * x0 + t * x1;
- };
-
- /**
- * @element ons-tabbar
- * @category tabbar
- * @description
- * [en]A component to display a tab bar on the bottom of a page. Used with `<ons-tab>` to manage pages using tabs.[/en]
- * [ja]タブバーをページ下部に表示するためのコンポーネントです。ons-tabと組み合わせて使うことで、ページを管理できます。[/ja]
- * @codepen pGuDL
- * @tutorial vanilla/Reference/tabbar
- * @modifier material
- * [en]A tabbar in Material Design.[/en]
- * [ja][/ja]
- * @modifier autogrow
- * [en]Tabs automatically grow depending on their content instead of having a fixed width.[/en]
- * [ja][/ja]
- * @modifier top-border
- * [en]Shows a static border-bottom in tabs for iOS top tabbars.[/en]
- * [ja][/ja]
- * @guide fundamentals.html#managing-pages
- * [en]Managing multiple pages.[/en]
- * [ja]複数のページを管理する[/ja]
- * @seealso ons-tab
- * [en]The `<ons-tab>` component.[/en]
- * [ja]ons-tabコンポーネント[/ja]
- * @seealso ons-page
- * [en]The `<ons-page>` component.[/en]
- * [ja]ons-pageコンポーネント[/ja]
- * @example
- * <ons-tabbar>
- * <ons-tab
- * page="home.html"
- * label="Home"
- * active>
- * </ons-tab>
- * <ons-tab
- * page="settings.html"
- * label="Settings"
- * active>
- * </ons-tab>
- * </ons-tabbar>
- *
- * <template id="home.html">
- * ...
- * </template>
- *
- * <template id="settings.html">
- * ...
- * </template>
- */
-
- var TabbarElement = function (_BaseElement) {
- inherits(TabbarElement, _BaseElement);
-
- /**
- * @event prechange
- * @description
- * [en]Fires just before the tab is changed.[/en]
- * [ja]アクティブなタブが変わる前に発火します。[/ja]
- * @param {Object} event
- * [en]Event object.[/en]
- * [ja]イベントオブジェクト。[/ja]
- * @param {Number} event.index
- * [en]Current index.[/en]
- * [ja]現在アクティブになっているons-tabのインデックスを返します。[/ja]
- * @param {Object} event.tabItem
- * [en]Tab item object.[/en]
- * [ja]tabItemオブジェクト。[/ja]
- * @param {Function} event.cancel
- * [en]Call this function to cancel the change event.[/en]
- * [ja]この関数を呼び出すと、アクティブなタブの変更がキャンセルされます。[/ja]
- */
-
- /**
- * @event postchange
- * @description
- * [en]Fires just after the tab is changed.[/en]
- * [ja]アクティブなタブが変わった後に発火します。[/ja]
- * @param {Object} event
- * [en]Event object.[/en]
- * [ja]イベントオブジェクト。[/ja]
- * @param {Number} event.index
- * [en]Current index.[/en]
- * [ja]現在アクティブになっているons-tabのインデックスを返します。[/ja]
- * @param {Object} event.tabItem
- * [en]Tab item object.[/en]
- * [ja]tabItemオブジェクト。[/ja]
- */
-
- /**
- * @event reactive
- * @description
- * [en]Fires if the already open tab is tapped again.[/en]
- * [ja]すでにアクティブになっているタブがもう一度タップやクリックされた場合に発火します。[/ja]
- * @param {Object} event
- * [en]Event object.[/en]
- * [ja]イベントオブジェクト。[/ja]
- * @param {Number} event.index
- * [en]Current index.[/en]
- * [ja]現在アクティブになっているons-tabのインデックスを返します。[/ja]
- * @param {Object} event.tabItem
- * [en]Tab item object.[/en]
- * [ja]tabItemオブジェクト。[/ja]
- */
-
- /**
- * @attribute animation
- * @type {String}
- * @default none
- * @description
- * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute animation-options
- * @type {Expression}
- * @description
- * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. {duration: 0.2, delay: 1, timing: 'ease-in'}[/ja]
- */
-
- /**
- * @attribute position
- * @initonly
- * @type {String}
- * @default bottom
- * @description
- * [en]Tabbar's position. Available values are `"bottom"` and `"top"`. Use `"auto"` to choose position depending on platform (bottom for iOS flat design, top for Material Design).[/en]
- * [ja]タブバーの位置を指定します。"bottom"もしくは"top"を選択できます。デフォルトは"bottom"です。[/ja]
- */
-
- /**
- * @attribute swipeable
- * @description
- * [en]If this attribute is set the tab bar can be scrolled by drag or swipe.[/en]
- * [ja]この属性がある時、タブバーをスワイプやドラッグで移動できるようになります。[/ja]
- */
-
- /**
- * @attribute ignore-edge-width
- * @type {Number}
- * @default 20
- * @description
- * [en]Distance in pixels from both edges. Swiping on these areas will prioritize parent components such as `ons-splitter` or `ons-navigator`.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute hide-tabs
- * @description
- * [en]Whether to hide the tabs.[/en]
- * [ja]タブを非表示にする場合に指定します。[/ja]
- */
-
- /**
- * @attribute tab-border
- * @description
- * [en]If this attribute is set the tabs show a dynamic bottom border. Only works for iOS flat design since the border is always visible in Material Design.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the tabbar.[/en]
- * [ja]タブバーの表現を指定します。[/ja]
- */
-
- function TabbarElement() {
- classCallCheck(this, TabbarElement);
-
- var _this = possibleConstructorReturn(this, (TabbarElement.__proto__ || Object.getPrototypeOf(TabbarElement)).call(this));
-
- _this._loadInactive = util$1.defer(); // Improves #2324
- contentReady(_this, function () {
- return _this._compile();
- });
- return _this;
- }
-
- createClass(TabbarElement, [{
- key: 'connectedCallback',
- value: function connectedCallback() {
- var _this2 = this;
-
- if (!this._swiper) {
- this._swiper = new Swiper({
- getElement: function getElement() {
- return _this2._contentElement;
- },
- getInitialIndex: function getInitialIndex() {
- return _this2.getAttribute('activeIndex') || _this2.getAttribute('active-index');
- },
- getAutoScrollRatio: this._getAutoScrollRatio.bind(this),
- getBubbleWidth: function getBubbleWidth() {
- return parseInt(_this2.getAttribute('ignore-edge-width') || 25, 10);
- },
- isAutoScrollable: function isAutoScrollable() {
- return true;
- },
- preChangeHook: this._onPreChange.bind(this),
- postChangeHook: this._onPostChange.bind(this),
- refreshHook: this._onRefresh.bind(this),
- scrollHook: this._onScroll.bind(this)
- });
-
- contentReady(this, function () {
- _this2._tabbarBorder = util$1.findChild(_this2._tabbarElement, '.tabbar__border');
- _this2._swiper.init({ swipeable: _this2.hasAttribute('swipeable') });
- });
- }
-
- contentReady(this, function () {
- _this2._updatePosition();
-
- if (!util$1.findParent(_this2, 'ons-page', function (p) {
- return p === document.body;
- })) {
- _this2._show(); // This tabbar is the top component
- }
- });
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- if (this._swiper && this._swiper.initialized) {
- this._swiper.dispose();
- this._swiper = null;
- this._tabbarBorder = null;
- this._tabsRect = null;
- }
- }
- }, {
- key: '_normalizeEvent',
- value: function _normalizeEvent(event) {
- return _extends({}, event, { index: event.activeIndex, tabItem: this.tabs[event.activeIndex] });
- }
- }, {
- key: '_onPostChange',
- value: function _onPostChange(event) {
- event = this._normalizeEvent(event);
- util$1.triggerElementEvent(this, 'postchange', event);
- var page = event.tabItem.pageElement;
- page && page._show();
- }
- }, {
- key: '_onPreChange',
- value: function _onPreChange(event) {
- event = this._normalizeEvent(event);
- event.cancel = function () {
- return event.canceled = true;
- };
-
- util$1.triggerElementEvent(this, 'prechange', event);
-
- if (!event.canceled) {
- var _event = event,
- activeIndex = _event.activeIndex,
- lastActiveIndex = _event.lastActiveIndex;
-
- var tabs = this.tabs;
-
- tabs[activeIndex].setActive(true);
- if (lastActiveIndex >= 0) {
- var prevTab = tabs[lastActiveIndex];
- prevTab.setActive(false);
- prevTab.pageElement && prevTab.pageElement._hide();
- }
- }
-
- return event.canceled;
- }
- }, {
- key: '_onScroll',
- value: function _onScroll(index) {
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- if (this._tabbarBorder) {
- this._tabbarBorder.style.transition = 'all ' + (options.duration || 0) + 's ' + (options.timing || '');
-
- if (this._autogrow && this._tabsRect.length > 0) {
- var a = Math.floor(index),
- b = Math.ceil(index),
- r = index % 1;
- this._tabbarBorder.style.width = lerp(this._tabsRect[a].width, this._tabsRect[b].width, r) + 'px';
- this._tabbarBorder.style.transform = 'translate3d(' + lerp(this._tabsRect[a].left, this._tabsRect[b].left, r) + 'px, 0, 0)';
- } else {
- this._tabbarBorder.style.transform = 'translate3d(' + index * 100 + '%, 0, 0)';
- }
- }
-
- this._onSwipe && this._onSwipe(index, options);
- }
- }, {
- key: '_onRefresh',
- value: function _onRefresh() {
- this._autogrow = util$1.hasModifier(this, 'autogrow');
- this._tabsRect = this.tabs.map(function (tab) {
- return tab.getBoundingClientRect();
- });
- if (this._tabbarBorder) {
- this._tabbarBorder.style.display = this.hasAttribute('tab-border') || util$1.hasModifier(this, 'material') ? 'block' : 'none';
- var index = this.getActiveTabIndex();
- if (this._tabsRect.length > 0 && index >= 0) {
- this._tabbarBorder.style.width = this._tabsRect[index].width + 'px';
- }
- }
- }
- }, {
- key: '_getAutoScrollRatio',
- value: function _getAutoScrollRatio(matches, velocity, size) {
- var ratio = .6; // Base ratio
- var modifier = size / 300 * (matches ? -1 : 1); // Based on screen size
- return Math.min(1, Math.max(0, ratio + velocity * modifier));
- }
- }, {
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
-
- var content = this._contentElement || util$1.create('.tabbar__content');
- content.classList.add('ons-tabbar__content');
- var tabbar = this._tabbarElement || util$1.create('.tabbar');
- tabbar.classList.add('ons-tabbar__footer');
-
- if (!tabbar.parentNode) {
- while (this.firstChild) {
- tabbar.appendChild(this.firstChild);
- }
- }
-
- var activeIndex = Number(this.getAttribute('activeIndex')); // 0 by default
- if (tabbar.children.length > activeIndex && !util$1.findChild(tabbar, '[active]')) {
- tabbar.children[activeIndex].setAttribute('active', '');
- }
-
- this._tabbarBorder = util$1.findChild(tabbar, '.tabbar__border') || util$1.create('.tabbar__border');
- tabbar.appendChild(this._tabbarBorder);
- tabbar.classList.add('ons-swiper-tabbar'); // Hides material border
-
- !content.children[0] && content.appendChild(document.createElement('div'));
- !content.children[1] && content.appendChild(document.createElement('div'));
- content.appendChild = content.appendChild.bind(content.children[0]);
- content.insertBefore = content.insertBefore.bind(content.children[0]);
-
- this.appendChild(content);
- this.appendChild(tabbar); // Triggers ons-tab connectedCallback
-
- ModifierUtil.initModifier(this, scheme$30);
- }
- }, {
- key: '_updatePosition',
- value: function _updatePosition() {
- var _this3 = this;
-
- var position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('position');
-
- var top = this._top = position === 'top' || position === 'auto' && util$1.hasModifier(this, 'material');
- var action = top ? util$1.addModifier : util$1.removeModifier;
-
- action(this, 'top');
-
- var page = util$1.findParent(this, 'ons-page');
- if (page) {
- contentReady(page, function () {
- var p = 0;
- if (page.children[0] && util$1.match(page.children[0], 'ons-toolbar')) {
- action(page.children[0], 'noshadow');
- p = 1; // Visual fix for some devices
- }
-
- var content = page._getContentElement();
- var cs = window.getComputedStyle(page._getContentElement(), null);
-
- _this3.style.top = top ? parseInt(cs.getPropertyValue('padding-top'), 10) - p + 'px' : '';
-
- // Refresh content top - Fix for iOS 8
- content.style.top = cs.top;
- content.style.top = '';
- });
- }
-
- internal$1.autoStatusBarFill(function () {
- var filled = util$1.findParent(_this3, function (e) {
- return e.hasAttribute('status-bar-fill');
- });
- util$1.toggleAttribute(_this3, 'status-bar-fill', top && !filled);
- });
- }
- }, {
- key: 'setActiveTab',
-
-
- /**
- * @method setActiveTab
- * @signature setActiveTab(index, [options])
- * @param {Number} index
- * [en]Tab index.[/en]
- * [ja]タブのインデックスを指定します。[/ja]
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {Function} [options.callback]
- * [en]Function that runs when the new page has loaded.[/en]
- * [ja][/ja]
- * @param {String} [options.animation]
- * [en]If this option is "none", the transition won't slide.[/en]
- * [ja][/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
- * @description
- * [en]Show specified tab page. Animations and their options can be specified by the second parameter.[/en]
- * [ja]指定したインデックスのタブを表示します。アニメーションなどのオプションを指定できます。[/ja]
- * @return {Promise}
- * [en]A promise that resolves to the new page element.[/en]
- * [ja][/ja]
- */
- value: function setActiveTab(nextIndex) {
- var _this4 = this;
-
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- var prevIndex = this.getActiveTabIndex();
- var prevTab = this.tabs[prevIndex],
- nextTab = this.tabs[nextIndex];
-
- if (!nextTab) {
- return Promise.reject('Specified index does not match any tab.');
- }
-
- if (nextIndex === prevIndex) {
- util$1.triggerElementEvent(this, 'reactive', { index: nextIndex, activeIndex: nextIndex, tabItem: nextTab });
- return Promise.resolve(nextTab.pageElement);
- }
-
- // FIXME: nextTab.loaded is broken in Zone.js promises (Angular2)
- var nextPage = nextTab.pageElement;
- return (nextPage ? Promise.resolve(nextPage) : nextTab.loaded).then(function (nextPage) {
- return _this4._swiper.setActiveIndex(nextIndex, _extends({
- reject: true
- }, options, {
- animation: prevTab && nextPage ? options.animation || _this4.getAttribute('animation') : 'none',
- animationOptions: util$1.extend({ duration: .3, timing: 'cubic-bezier(.4, .7, .5, 1)' }, _this4.hasAttribute('animation-options') ? util$1.animationOptionsParse(_this4.getAttribute('animation-options')) : {}, options.animationOptions || {})
- })).then(function () {
- options.callback instanceof Function && options.callback(nextPage);
- return nextPage;
- });
- });
- }
-
- /**
- * @method setTabbarVisibility
- * @signature setTabbarVisibility(visible)
- * @param {Boolean} visible
- * @description
- * [en]Used to hide or show the tab bar.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'setTabbarVisibility',
- value: function setTabbarVisibility(visible) {
- var _this5 = this;
-
- contentReady(this, function () {
- _this5._contentElement.style[_this5._top ? 'top' : 'bottom'] = visible ? '' : '0px';
- _this5._tabbarElement.style.display = visible ? '' : 'none';
- visible && _this5._onRefresh();
- });
- }
- }, {
- key: 'show',
- value: function show() {
- this.setTabbarVisibility(true);
- }
- }, {
- key: 'hide',
- value: function hide() {
- this.setTabbarVisibility(false);
- }
-
- /**
- * @property visible
- * @readonly
- * @type {Boolean}
- * @description
- * [en]Whether the tabbar is visible or not.[/en]
- * [ja]タブバーが見える場合に`true`。[/ja]
- */
-
- }, {
- key: 'getActiveTabIndex',
-
-
- /**
- * @method getActiveTabIndex
- * @signature getActiveTabIndex()
- * @return {Number}
- * [en]The index of the currently active tab.[/en]
- * [ja]現在アクティブになっているタブのインデックスを返します。[/ja]
- * @description
- * [en]Returns tab index on current active tab. If active tab is not found, returns -1.[/en]
- * [ja]現在アクティブになっているタブのインデックスを返します。現在アクティブなタブがない場合には-1を返します。[/ja]
- */
- value: function getActiveTabIndex() {
- var tabs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.tabs;
-
- for (var i = 0; i < tabs.length; i++) {
- if (tabs[i] && tabs[i].tagName === 'ONS-TAB' && tabs[i].isActive()) {
- return i;
- }
- }
- return -1;
- }
- }, {
- key: '_show',
- value: function _show() {
- var _this6 = this;
-
- this._swiper.show();
-
- setImmediate(function () {
- var tabs = _this6.tabs;
- var activeIndex = _this6.getActiveTabIndex(tabs);
- _this6._loadInactive.resolve();
- if (tabs.length > 0 && activeIndex >= 0) {
- tabs[activeIndex].loaded.then(function (el) {
- return el && setImmediate(function () {
- return el._show();
- });
- });
- }
- });
- }
- }, {
- key: '_hide',
- value: function _hide() {
- this._swiper.hide();
- var topPage = this.topPage;
- topPage && topPage._hide();
- }
- }, {
- key: '_destroy',
- value: function _destroy() {
- this.tabs.forEach(function (tab) {
- return tab.remove();
- });
- this.remove();
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- if (name === 'modifier') {
- ModifierUtil.onModifierChanged(last, current, this, scheme$30);
- var isTop = function isTop(m) {
- return (/(^|\s+)top($|\s+)/i.test(m)
- );
- };
- isTop(last) !== isTop(current) && this._updatePosition();
- } else if (name === 'position') {
- util$1.isAttached(this) && this._updatePosition();
- } else if (name === 'swipeable') {
- this._swiper && this._swiper.updateSwipeable(this.hasAttribute('swipeable'));
- } else if (name === 'hide-tabs') {
- this.setTabbarVisibility(!this.hasAttribute('hide-tabs') || current === 'false');
- }
- }
- }, {
- key: '_tabbarElement',
- get: function get$$1() {
- return util$1.findChild(this, '.tabbar');
- }
- }, {
- key: '_contentElement',
- get: function get$$1() {
- return util$1.findChild(this, '.tabbar__content');
- }
- }, {
- key: '_targetElement',
- get: function get$$1() {
- var content = this._contentElement;
- return content && content.children[0] || null;
- }
- }, {
- key: 'topPage',
- get: function get$$1() {
- var tabs = this.tabs,
- index = this.getActiveTabIndex();
- return tabs[index] ? tabs[index].pageElement || this.pages[0] || null : null;
- }
- }, {
- key: 'pages',
- get: function get$$1() {
- return util$1.arrayFrom(this._targetElement.children);
- }
- }, {
- key: 'tabs',
- get: function get$$1() {
- return Array.prototype.filter.call(this._tabbarElement.children, function (e) {
- return e.tagName === 'ONS-TAB';
- });
- }
- }, {
- key: 'visible',
- get: function get$$1() {
- return this._tabbarElement.style.display !== 'none';
- }
-
- /**
- * @property swipeable
- * @type {Boolean}
- * @description
- * [en]Enable swipe interaction.[/en]
- * [ja]swipeableであればtrueを返します。[/ja]
- */
-
- }, {
- key: 'swipeable',
- get: function get$$1() {
- return this.hasAttribute('swipeable');
- },
- set: function set$$1(value) {
- return util$1.toggleAttribute(this, 'swipeable', value);
- }
-
- /**
- * @property onSwipe
- * @type {Function}
- * @description
- * [en]Hook called whenever the user slides the tabbar. It gets a decimal index and an animationOptions object as arguments.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'onSwipe',
- get: function get$$1() {
- return this._onSwipe;
- },
- set: function set$$1(value) {
- if (value && !(value instanceof Function)) {
- util$1.throw('"onSwipe" must be a function');
- }
- this._onSwipe = value;
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'position', 'swipeable', 'tab-border', 'hide-tabs'];
- }
- }, {
- key: 'rewritables',
- get: function get$$1() {
- return rewritables$3;
- }
- }, {
- key: 'events',
- get: function get$$1() {
- return ['prechange', 'postchange', 'reactive'];
- }
- }]);
- return TabbarElement;
- }(BaseElement);
-
- onsElements.Tabbar = TabbarElement;
- customElements.define('ons-tabbar', TabbarElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var defaultClassName$16 = 'tabbar__item';
-
- var scheme$29 = {
- '': 'tabbar--*__item',
- '.tabbar__button': 'tabbar--*__button'
- };
-
- /**
- * @element ons-tab
- * @category tabbar
- * @description
- * [en]Represents a tab inside tab bar. Each `<ons-tab>` represents a page.[/en]
- * [ja]
- * タブバーに配置される各アイテムのコンポーネントです。それぞれのons-tabはページを表します。
- * ons-tab要素の中には、タブに表示されるコンテンツを直接記述することが出来ます。
- * [/ja]
- * @codepen pGuDL
- * @tutorial vanilla/Reference/tabbar
- * @guide fundamentals.html#managing-pages
- * [en]Managing multiple pages.[/en]
- * [ja]複数のページを管理する[/ja]]
- * @guide appsize.html#removing-icon-packs [en]Removing icon packs.[/en][ja][/ja]
- * @guide faq.html#how-can-i-use-custom-icon-packs [en]Adding custom icon packs.[/en][ja][/ja]
- * @seealso ons-tabbar
- * [en]ons-tabbar component[/en]
- * [ja]ons-tabbarコンポーネント[/ja]
- * @seealso ons-page
- * [en]ons-page component[/en]
- * [ja]ons-pageコンポーネント[/ja]
- * @seealso ons-icon
- * [en]ons-icon component[/en]
- * [ja]ons-iconコンポーネント[/ja]
- * @example
- * <ons-tabbar>
- * <ons-tab
- * page="home.html"
- * label="Home"
- * active>
- * </ons-tab>
- * <ons-tab
- * page="settings.html"
- * label="Settings"
- * active>
- * </ons-tab>
- * </ons-tabbar>
- *
- * <template id="home.html">
- * ...
- * </template>
- *
- * <template id="settings.html">
- * ...
- * </template>
-
- */
-
- var TabElement = function (_BaseElement) {
- inherits(TabElement, _BaseElement);
-
- /**
- * @attribute page
- * @initonly
- * @type {String}
- * @description
- * [en]The page that is displayed when the tab is tapped.[/en]
- * [ja]ons-tabが参照するページへのURLを指定します。[/ja]
- */
-
- /**
- * @attribute icon
- * @type {String}
- * @description
- * [en]
- * The icon name for the tab. Can specify the same icon name as `<ons-icon>`. Check [See also](#seealso) section for more information.
- * [/en]
- * [ja]
- * アイコン名を指定します。ons-iconと同じアイコン名を指定できます。
- * 個別にアイコンをカスタマイズする場合は、background-imageなどのCSSスタイルを用いて指定できます。
- * [/ja]
- */
-
- /**
- * @attribute active-icon
- * @type {String}
- * @description
- * [en]The name of the icon when the tab is active.[/en]
- * [ja]アクティブの際のアイコン名を指定します。[/ja]
- */
-
- /**
- * @attribute label
- * @type {String}
- * @description
- * [en]The label of the tab item.[/en]
- * [ja]アイコン下に表示されるラベルを指定します。[/ja]
- */
-
- /**
- * @attribute badge
- * @type {String}
- * @description
- * [en]Display a notification badge on top of the tab.[/en]
- * [ja]バッジに表示する内容を指定します。[/ja]
- */
-
- /**
- * @attribute active
- * @description
- * [en]This attribute should be set to the tab that is active by default.[/en]
- * [ja][/ja]
- */
-
- function TabElement() {
- classCallCheck(this, TabElement);
-
- var _this = possibleConstructorReturn(this, (TabElement.__proto__ || Object.getPrototypeOf(TabElement)).call(this));
-
- if (['label', 'icon', 'badge'].some(_this.hasAttribute.bind(_this))) {
- _this._compile();
- } else {
- contentReady(_this, function () {
- return _this._compile();
- });
- }
-
- _this._pageLoader = defaultPageLoader;
- _this._onClick = _this._onClick.bind(_this);
- return _this;
- }
-
- createClass(TabElement, [{
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
- this.classList.add(defaultClassName$16);
-
- if (this._button) {
- return;
- }
-
- var button = util$1.create('button.tabbar__button');
- while (this.childNodes[0]) {
- button.appendChild(this.childNodes[0]);
- }
-
- var input = util$1.create('input', { display: 'none' });
- input.type = 'radio';
-
- this.appendChild(input);
- this.appendChild(button);
-
- this._updateButtonContent();
- ModifierUtil.initModifier(this, scheme$29);
- this._updateRipple();
- }
- }, {
- key: '_updateRipple',
- value: function _updateRipple() {
- this._button && util$1.updateRipple(this._button, this.hasAttribute('ripple'));
- }
- }, {
- key: '_updateButtonContent',
- value: function _updateButtonContent() {
- var _this2 = this;
-
- var button = this._button;
-
- var iconWrapper = this._icon;
- if (this.hasAttribute('icon')) {
- iconWrapper = iconWrapper || util$1.createElement('<div class="tabbar__icon"><ons-icon></ons-icon></div>');
- var icon = iconWrapper.children[0];
- var fix = function (last) {
- return function () {
- return icon.attributeChangedCallback('icon', last, _this2.getAttribute('icon'));
- };
- }(icon.getAttribute('icon'));
- icon.setAttribute('icon', this.getAttribute(this.isActive() ? 'active-icon' : 'icon'));
- iconWrapper.parentElement !== button && button.insertBefore(iconWrapper, button.firstChild);
-
- // dirty fix for https://github.com/OnsenUI/OnsenUI/issues/1654
- icon.attributeChangedCallback instanceof Function ? fix() : setImmediate(function () {
- return icon.attributeChangedCallback instanceof Function && fix();
- });
- } else {
- iconWrapper && iconWrapper.remove();
- }
-
- ['label', 'badge'].forEach(function (attr, index) {
- var prop = _this2.querySelector('.tabbar__' + attr);
- if (_this2.hasAttribute(attr)) {
- prop = prop || util$1.create('.tabbar__' + attr + (attr === 'badge' ? ' notification' : ''));
- prop.textContent = _this2.getAttribute(attr);
- prop.parentElement !== button && button.appendChild(prop);
- } else {
- prop && prop.remove();
- }
- });
- }
- }, {
- key: '_onClick',
- value: function _onClick() {
- if (this.onClick instanceof Function) {
- this.onClick();
- } else {
- this._tabbar.setActiveTab(this.index, { reject: false });
- }
- }
- }, {
- key: 'setActive',
- value: function setActive() {
- var active = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
-
- this._input.checked = active;
- this.classList.toggle('active', active);
- util$1.toggleAttribute(this, 'active', active);
-
- if (this.hasAttribute('icon') && this.hasAttribute('active-icon')) {
- this._icon.children[0].setAttribute('icon', this.getAttribute(active ? 'active-icon' : 'icon'));
- }
- }
- }, {
- key: '_loadPageElement',
- value: function _loadPageElement(parent, page) {
- var _this3 = this;
-
- this._hasLoaded = true;
-
- return new Promise(function (resolve) {
- _this3._pageLoader.load({ parent: parent, page: page }, function (pageElement) {
- parent.replaceChild(pageElement, parent.children[_this3.index]); // Ensure position
- _this3._loadedPage = pageElement;
- resolve(pageElement);
- });
- });
- }
- }, {
- key: 'isActive',
-
-
- /**
- * @return {Boolean}
- */
- value: function isActive() {
- return this.classList.contains('active');
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- this.removeEventListener('click', this._onClick, false);
- if (this._loadedPage) {
- this._hasLoaded = false;
- this.loaded = null;
- }
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- var _this4 = this;
-
- this.addEventListener('click', this._onClick, false);
-
- if (!util$1.isAttached(this) || this.loaded) {
- return; // ons-tabbar compilation may trigger this
- }
-
- var deferred = util$1.defer();
- this.loaded = deferred.promise;
-
- contentReady(this, function () {
- var index = _this4.index;
- var tabbar = _this4._tabbar;
- if (!tabbar) {
- util$1.throw('Tab elements must be children of Tabbar');
- }
-
- if (tabbar.hasAttribute('modifier')) {
- util$1.addModifier(_this4, tabbar.getAttribute('modifier'));
- }
-
- if (!_this4._hasLoaded) {
- if (_this4.hasAttribute('active')) {
- _this4.setActive(true);
- tabbar.setAttribute('activeIndex', index);
- }
-
- if (index === tabbar.tabs.length - 1) {
- tabbar._onRefresh();
- setImmediate(function () {
- return tabbar._onRefresh();
- });
- }
-
- TabbarElement.rewritables.ready(tabbar, function () {
- var pageTarget = _this4.page || _this4.getAttribute('page');
- if (!_this4.pageElement && pageTarget) {
- var parentTarget = tabbar._targetElement;
- var dummyPage = util$1.create('div', { height: '100%', width: '100%', visibility: 'hidden' });
- parentTarget.insertBefore(dummyPage, parentTarget.children[index]); // Ensure position
-
- var load = function load() {
- return _this4._loadPageElement(parentTarget, pageTarget).then(deferred.resolve);
- };
- return _this4.isActive() ? load() : tabbar._loadInactive.promise.then(load);
- }
-
- return deferred.resolve(_this4.pageElement);
- });
- }
- });
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- var _this5 = this;
-
- switch (name) {
- case 'class':
- util$1.restoreClass(this, defaultClassName$16, scheme$29);
- break;
- case 'modifier':
- contentReady(this, function () {
- return ModifierUtil.onModifierChanged(last, current, _this5, scheme$29);
- });
- break;
- case 'ripple':
- contentReady(this, function () {
- return _this5._updateRipple();
- });
- break;
- case 'icon':
- case 'label':
- case 'badge':
- contentReady(this, function () {
- return _this5._updateButtonContent();
- });
- break;
- case 'page':
- this.page = current || '';
- break;
- }
- }
- }, {
- key: 'pageLoader',
- set: function set$$1(loader) {
- if (!(loader instanceof PageLoader)) {
- util$1.throwPageLoader();
- }
- this._pageLoader = loader;
- },
- get: function get$$1() {
- return this._pageLoader;
- }
- }, {
- key: '_input',
- get: function get$$1() {
- return util$1.findChild(this, 'input');
- }
- }, {
- key: '_button',
- get: function get$$1() {
- return util$1.findChild(this, '.tabbar__button');
- }
- }, {
- key: '_icon',
- get: function get$$1() {
- return this.querySelector('.tabbar__icon');
- }
- }, {
- key: '_tabbar',
- get: function get$$1() {
- return util$1.findParent(this, 'ons-tabbar');
- }
- }, {
- key: 'index',
- get: function get$$1() {
- return Array.prototype.indexOf.call(this.parentElement.children, this);
- }
- }, {
- key: 'pageElement',
- get: function get$$1() {
- // It has been loaded by ons-tab
- if (this._loadedPage) {
- return this._loadedPage;
- }
- // Manually attached to DOM, 1 per tab
- var tabbar = this._tabbar;
- if (tabbar.pages.length === tabbar.tabs.length) {
- return tabbar.pages[this.index];
- }
- // Loaded in another way
- return null;
- }
- }], [{
- key: 'observedAttributes',
- get: function get$$1() {
- return ['modifier', 'ripple', 'icon', 'label', 'page', 'badge', 'class'];
- }
- }]);
- return TabElement;
- }(BaseElement);
-
- onsElements.Tab = TabElement;
- customElements.define('ons-tab', TabElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var ToastAnimator = function (_BaseAnimator) {
- inherits(ToastAnimator, _BaseAnimator);
-
- /**
- * @param {Object} options
- * @param {String} options.timing
- * @param {Number} options.duration
- * @param {Number} options.delay
- */
- function ToastAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'linear' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.2 : _ref$duration;
-
- classCallCheck(this, ToastAnimator);
- return possibleConstructorReturn(this, (ToastAnimator.__proto__ || Object.getPrototypeOf(ToastAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
- }
-
- /**
- * @param {HTMLElement} modal
- * @param {Function} callback
- */
-
-
- createClass(ToastAnimator, [{
- key: 'show',
- value: function show(modal, callback) {
- callback();
- }
-
- /**
- * @param {HTMLElement} modal
- * @param {Function} callback
- */
-
- }, {
- key: 'hide',
- value: function hide(modal, callback) {
- callback();
- }
- }]);
- return ToastAnimator;
- }(BaseAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * iOS style animator for dialog.
- */
-
- var FadeToastAnimator = function (_ToastAnimator) {
- inherits(FadeToastAnimator, _ToastAnimator);
-
- function FadeToastAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'linear' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.3 : _ref$duration;
-
- classCallCheck(this, FadeToastAnimator);
- return possibleConstructorReturn(this, (FadeToastAnimator.__proto__ || Object.getPrototypeOf(FadeToastAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
- }
-
- /**
- * @param {HTMLElement} toast
- * @param {Function} callback
- */
-
-
- createClass(FadeToastAnimator, [{
- key: 'show',
- value: function show(toast, callback) {
- callback = callback ? callback : function () {};
-
- Animit(toast, this.def).default({ opacity: 0 }, { opacity: 1 }).queue(function (done) {
- callback();
- done();
- }).play();
- }
-
- /**
- * @param {HTMLElement} toast
- * @param {Function} callback
- */
-
- }, {
- key: 'hide',
- value: function hide(toast, callback) {
- callback = callback ? callback : function () {};
-
- Animit(toast, this.def).default({ opacity: 1 }, { opacity: 0 }).queue(function (done) {
- callback();
- done();
- }).play();
- }
- }]);
- return FadeToastAnimator;
- }(ToastAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * Ascend Toast Animator.
- */
-
- var AscendToastAnimator = function (_ToastAnimator) {
- inherits(AscendToastAnimator, _ToastAnimator);
-
- function AscendToastAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'ease' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.25 : _ref$duration;
-
- classCallCheck(this, AscendToastAnimator);
-
- var _this = possibleConstructorReturn(this, (AscendToastAnimator.__proto__ || Object.getPrototypeOf(AscendToastAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
-
- _this.messageDelay = _this.duration * 0.4 + _this.delay; // Delay message opacity change
- if (platform.isAndroid()) {
- _this.ascension = 48; // Toasts are always 1 line
- } else {
- if (iPhoneXPatch.isIPhoneXPortraitPatchActive()) {
- _this.ascension = 98; // 64 + 34
- } else if (iPhoneXPatch.isIPhoneXLandscapePatchActive()) {
- _this.ascension = 85; // 64 + 21
- } else {
- _this.ascension = 64;
- }
- }
- return _this;
- }
-
- /**
- * @param {HTMLElement} toast
- * @param {Function} callback
- */
-
-
- createClass(AscendToastAnimator, [{
- key: 'show',
- value: function show(toast, callback) {
- toast = toast._toast;
- util$1.globals.fabOffset = this.ascension;
-
- Animit.runAll(Animit(toast, this.def).default({ transform: 'translate3d(0, ' + this.ascension + 'px, 0)' }, { transform: 'translate3d(0, 0, 0)' }).queue(function (done) {
- callback && callback();
- done();
- }), Animit(this._getFabs()).wait(this.delay).queue({ transform: 'translate3d(0, -' + this.ascension + 'px, 0) scale(1)' }, this.def), Animit(util$1.arrayFrom(toast.children), this.def).default({ opacity: 0 }, { opacity: 1 }));
- }
-
- /**
- * @param {HTMLElement} toast
- * @param {Function} callback
- */
-
- }, {
- key: 'hide',
- value: function hide(toast, callback) {
- toast = toast._toast;
- util$1.globals.fabOffset = 0;
-
- Animit.runAll(Animit(toast, this.def).default({ transform: 'translate3d(0, 0, 0)' }, { transform: 'translate3d(0, ' + this.ascension + 'px, 0)' }).queue(function (done) {
- callback && callback();
- done();
- }), Animit(this._getFabs(), this.def).wait(this.delay).queue({ transform: 'translate3d(0, 0, 0) scale(1)' }, this.def), Animit(util$1.arrayFrom(toast.children), this.def).default({ opacity: 1 }, { opacity: 0 }));
- }
- }, {
- key: '_getFabs',
- value: function _getFabs() {
- return util$1.arrayFrom(document.querySelectorAll('ons-fab[position~=bottom], ons-speed-dial[position~=bottom]')).filter(function (fab) {
- return fab.visible;
- });
- }
- }]);
- return AscendToastAnimator;
- }(ToastAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * Lift-fade Toast Animator
- */
-
- var LiftToastAnimator = function (_ToastAnimator) {
- inherits(LiftToastAnimator, _ToastAnimator);
-
- function LiftToastAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'ease' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.35 : _ref$duration;
-
- classCallCheck(this, LiftToastAnimator);
-
- var _this = possibleConstructorReturn(this, (LiftToastAnimator.__proto__ || Object.getPrototypeOf(LiftToastAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
-
- _this.bodyHeight = document.body.clientHeight; // avoid Forced Synchronous Layout
- if (iPhoneXPatch.isIPhoneXPortraitPatchActive()) {
- _this.liftAmount = 'calc(100% + 34px)';
- } else if (iPhoneXPatch.isIPhoneXLandscapePatchActive()) {
- _this.liftAmount = 'calc(100% + 21px)';
- } else {
- _this.liftAmount = '100%';
- }
- return _this;
- }
-
- /**
- * @param {HTMLElement} toast
- * @param {Function} callback
- */
-
-
- createClass(LiftToastAnimator, [{
- key: 'show',
- value: function show(toast, callback) {
- toast = toast._toast;
-
- Animit.runAll(Animit(toast, this.def).default({ transform: 'translate3d(0, ' + this.liftAmount + ', 0)', opacity: 0 }, { transform: 'translate3d(0, 0, 0)', opacity: 1 }).queue(function (done) {
- callback && callback();
- done();
- }));
- }
-
- /**
- * @param {HTMLElement} toast
- * @param {Function} callback
- */
-
- }, {
- key: 'hide',
- value: function hide(toast, callback) {
- toast = toast._toast;
-
- Animit.runAll(Animit(toast, this.def).default({ transform: 'translate3d(0, 0, 0)', opacity: 1 }, { transform: 'translate3d(0, ' + this.liftAmount + ', 0)', opacity: 0 }).queue(function (done) {
- callback && callback();
- done();
- }));
- }
- }, {
- key: '_updatePosition',
- value: function _updatePosition(toast) {
- if (parseInt(toast.style.top, 10) === 0) {
- toast.style.top = toast.style.bottom = '';
- }
- }
- }]);
- return LiftToastAnimator;
- }(ToastAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * Fall-fade Toast Animator
- */
-
- var FallToastAnimator = function (_ToastAnimator) {
- inherits(FallToastAnimator, _ToastAnimator);
-
- function FallToastAnimator() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$timing = _ref.timing,
- timing = _ref$timing === undefined ? 'ease' : _ref$timing,
- _ref$delay = _ref.delay,
- delay = _ref$delay === undefined ? 0 : _ref$delay,
- _ref$duration = _ref.duration,
- duration = _ref$duration === undefined ? 0.35 : _ref$duration;
-
- classCallCheck(this, FallToastAnimator);
-
- var _this = possibleConstructorReturn(this, (FallToastAnimator.__proto__ || Object.getPrototypeOf(FallToastAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
-
- if (iPhoneXPatch.isIPhoneXPortraitPatchActive()) {
- _this.fallAmount = 'calc(-100% - 44px)';
- } else {
- _this.fallAmount = '-100%';
- }
- return _this;
- }
-
- /**
- * @param {HTMLElement} toast
- * @param {Function} callback
- */
-
-
- createClass(FallToastAnimator, [{
- key: 'show',
- value: function show(toast, callback) {
- toast = toast._toast;
- this._updatePosition(toast);
-
- Animit.runAll(Animit(toast, this.def).default({ transform: 'translate3d(0, ' + this.fallAmount + ', 0)', opacity: 0 }, { transform: 'translate3d(0, 0, 0)', opacity: 1 }).queue(function (done) {
- callback && callback();
- done();
- }));
- }
-
- /**
- * @param {HTMLElement} toast
- * @param {Function} callback
- */
-
- }, {
- key: 'hide',
- value: function hide(toast, callback) {
- var _this2 = this;
-
- toast = toast._toast;
- this._updatePosition(toast);
-
- Animit.runAll(Animit(toast, this.def).default({ transform: 'translate3d(0, 0, 0)', opacity: 1 }, { transform: 'translate3d(0, ' + this.fallAmount + ', 0)', opacity: 0 }).queue(function (done) {
- _this2._updatePosition(toast, true);
- callback && callback();
- done();
- }));
- }
- }, {
- key: '_updatePosition',
- value: function _updatePosition(toast, cleanUp) {
- var correctTop = void 0;
- if (iPhoneXPatch.isIPhoneXPortraitPatchActive()) {
- correctTop = '44px';
- } else {
- correctTop = '0';
- }
-
- if (toast.style.top !== correctTop) {
- toast.style.top = correctTop;
- toast.style.bottom = 'initial';
- }
- }
- }]);
- return FallToastAnimator;
- }(ToastAnimator);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- var scheme$31 = {
- '.toast': 'toast--*',
- '.toast__message': 'toast--*__message',
- '.toast__button': 'toast--*__button'
- };
-
- var defaultClassName$17 = 'toast';
-
- var _animatorDict$8 = {
- 'default': platform.isAndroid() ? AscendToastAnimator : LiftToastAnimator,
- 'fade': FadeToastAnimator,
- 'ascend': AscendToastAnimator,
- 'lift': LiftToastAnimator,
- 'fall': FallToastAnimator,
- 'none': ToastAnimator
- };
-
- /**
- * @element ons-toast
- * @category dialog
- * @description
- * [en]
- * The Toast or Snackbar component is useful for displaying dismissable information or simple actions at (normally) the bottom of the page.
- *
- * This component does not block user input, allowing the app to continue its flow. For simple toasts, consider `ons.notification.toast` instead.
- * [/en]
- * [ja][/ja]
- * @tutorial vanilla/Reference/toast
- * @seealso ons-alert-dialog
- * [en]The `<ons-alert-dialog>` component is preferred for displaying undismissable information.[/en]
- * [ja][/ja]
- */
-
- var ToastElement = function (_BaseDialogElement) {
- inherits(ToastElement, _BaseDialogElement);
-
- /**
- * @attribute animation
- * @type {String}
- * @default default
- * @description
- * [en]The animation used when showing and hiding the toast. Can be either `"default"`, `"ascend"` (Android), `"lift"` (iOS), `"fall"`, `"fade"` or `"none"`.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute animation-options
- * @type {Expression}
- * @description
- * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. <code>{duration: 0.2, delay: 1, timing: 'ease-in'}</code>[/ja]
- */
-
- function ToastElement() {
- classCallCheck(this, ToastElement);
-
- var _this = possibleConstructorReturn(this, (ToastElement.__proto__ || Object.getPrototypeOf(ToastElement)).call(this));
-
- _this._defaultDBB = null;
- contentReady(_this, function () {
- return _this._compile();
- });
- return _this;
- }
-
- createClass(ToastElement, [{
- key: '_updateAnimatorFactory',
- value: function _updateAnimatorFactory() {
- // Reset position style
- this._toast && (this._toast.style.top = this._toast.style.bottom = '');
-
- return new AnimatorFactory({
- animators: _animatorDict$8,
- baseClass: ToastAnimator,
- baseClassName: 'ToastAnimator',
- defaultAnimation: this.getAttribute('animation')
- });
- }
-
- /**
- * @property onDeviceBackButton
- * @type {Object}
- * @description
- * [en]Back-button handler.[/en]
- * [ja]バックボタンハンドラ。[/ja]
- */
-
- }, {
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
-
- this.style.display = 'none';
- this.style.zIndex = 10000; // Lower than dialogs
-
- var messageClassName = 'toast__message';
- var buttonClassName = 'toast__button';
-
- var toast = util$1.findChild(this, '.' + defaultClassName$17);
- if (!toast) {
- toast = document.createElement('div');
- toast.classList.add(defaultClassName$17);
- while (this.childNodes[0]) {
- toast.appendChild(this.childNodes[0]);
- }
- }
-
- var button = util$1.findChild(toast, '.' + buttonClassName);
- if (!button) {
- button = util$1.findChild(toast, function (e) {
- return util$1.match(e, '.button') || util$1.match(e, 'button');
- });
- if (button) {
- button.classList.remove('button');
- button.classList.add(buttonClassName);
- toast.appendChild(button);
- }
- }
-
- if (!util$1.findChild(toast, '.' + messageClassName)) {
- var message = util$1.findChild(toast, '.message');
- if (!message) {
- message = document.createElement('div');
- for (var i = toast.childNodes.length - 1; i >= 0; i--) {
- if (toast.childNodes[i] !== button) {
- message.insertBefore(toast.childNodes[i], message.firstChild);
- }
- }
- }
- message.classList.add(messageClassName);
-
- toast.insertBefore(message, toast.firstChild);
- }
-
- if (toast.parentNode !== this) {
- this.appendChild(toast);
- }
-
- ModifierUtil.initModifier(this, this._scheme);
- }
-
- /**
- * @property visible
- * @readonly
- * @type {Boolean}
- * @description
- * [en]Whether the element is visible or not.[/en]
- * [ja]要素が見える場合に`true`。[/ja]
- */
-
- /**
- * @method show
- * @signature show([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Available animations are `"default"`, `"ascend"` (Android), `"lift"` (iOS), `"fall"`, `"fade"` or `"none"`.[/en]
- * [ja][/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
- * @description
- * [en]Show the element.[/en]
- * [ja][/ja]
- * @return {Promise}
- * [en]Resolves to the displayed element[/en]
- * [ja][/ja]
- */
-
- /**
- * @method toggle
- * @signature toggle([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Available animations are `"default"`, `"ascend"` (Android), `"lift"` (iOS), `"fall"`, `"fade"` or `"none"`.[/en]
- * [ja][/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
- * @description
- * [en]Toggle toast visibility.[/en]
- * [ja][/ja]
- */
-
- /**
- * @method hide
- * @signature hide([options])
- * @param {Object} [options]
- * [en]Parameter object.[/en]
- * [ja]オプションを指定するオブジェクト。[/ja]
- * @param {String} [options.animation]
- * [en]Animation name. Available animations are `"default"`, `"ascend"` (Android), `"lift"` (iOS), `"fall"`, `"fade"` or `"none"`.[/en]
- * [ja][/ja]
- * @param {String} [options.animationOptions]
- * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
- * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
- * @description
- * [en]Hide toast.[/en]
- * [ja][/ja]
- * @return {Promise}
- * [en]Resolves to the hidden element[/en]
- * [ja][/ja]
- */
-
- /**
- * @param {String} name
- * @param {Function} Animator
- */
-
- }, {
- key: '_scheme',
- get: function get$$1() {
- return scheme$31;
- }
- }, {
- key: '_toast',
- get: function get$$1() {
- return util$1.findChild(this, '.' + defaultClassName$17);
- }
- }], [{
- key: 'registerAnimator',
- value: function registerAnimator(name, Animator) {
- if (!(Animator.prototype instanceof ToastAnimator)) {
- util$1.throw('"Animator" param must inherit OnsToastElement.ToastAnimator');
- }
- _animatorDict$8[name] = Animator;
- }
- }, {
- key: 'animators',
- get: function get$$1() {
- return _animatorDict$8;
- }
- }, {
- key: 'ToastAnimator',
- get: function get$$1() {
- return ToastAnimator;
- }
- }]);
- return ToastElement;
- }(BaseDialogElement);
-
- onsElements.Toast = ToastElement;
- customElements.define('ons-toast', ToastElement);
-
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- /**
- * @element ons-toolbar-button
- * @category page
- * @modifier material
- * [en]Material Design toolbar button.[/en]
- * [ja][/ja]
- * @modifier outline
- * [en]A button with an outline.[/en]
- * [ja]アウトラインをもったボタンを表示します。[/ja]
- * @description
- * [en]Button component for ons-toolbar and ons-bottom-toolbar.[/en]
- * [ja]ons-toolbarあるいはons-bottom-toolbarに設置できるボタン用コンポーネントです。[/ja]
- * @codepen aHmGL
- * @tutorial vanilla/Reference/page
- * @guide compilation.html#toolbar-compilation
- * [en]Adding a toolbar[/en]
- * [ja]ツールバーの追加[/ja]
- * @seealso ons-toolbar
- * [en]The `<ons-toolbar>` component displays a navigation bar at the top of a page.[/en]
- * [ja]ons-toolbarコンポーネント[/ja]
- * @seealso ons-back-button
- * [en]The `<ons-back-button>` displays a back button in the navigation bar.[/en]
- * [ja]ons-back-buttonコンポーネント[/ja]
- * @example
- * <ons-toolbar>
- * <div class="left">
- * <ons-toolbar-button>
- * Button
- * </ons-toolbar-button>
- * </div>
- * <div class="center">
- * Title
- * </div>
- * <div class="right">
- * <ons-toolbar-button>
- * <ons-icon icon="ion-navicon" size="28px"></ons-icon>
- * </ons-toolbar-button>
- * </div>
- * </ons-toolbar>
- */
-
- var ToolbarButtonElement = function (_BaseButtonElement) {
- inherits(ToolbarButtonElement, _BaseButtonElement);
-
- function ToolbarButtonElement() {
- classCallCheck(this, ToolbarButtonElement);
- return possibleConstructorReturn(this, (ToolbarButtonElement.__proto__ || Object.getPrototypeOf(ToolbarButtonElement)).apply(this, arguments));
- }
-
- createClass(ToolbarButtonElement, [{
- key: '_scheme',
-
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the button.[/en]
- * [ja]ボタンの表現を指定します。[/ja]
- */
-
- /**
- * @attribute icon
- * @type {String}
- * @description
- * [en]Creates an `ons-icon` component with this string.[/en]
- * [ja]`ons-icon`コンポーネントを悪性します。[/ja]
- */
-
- /**
- * @attribute disabled
- * @description
- * [en]Specify if button should be disabled.[/en]
- * [ja]ボタンを無効化する場合は指定してください。[/ja]
- */
-
- /**
- * @property disabled
- * @type {Boolean}
- * @description
- * [en]Whether the element is disabled or not.[/en]
- * [ja]無効化されている場合に`true`。[/ja]
- */
-
- get: function get$$1() {
- return { '': 'toolbar-button--*' };
- }
- }, {
- key: '_defaultClassName',
- get: function get$$1() {
- return 'toolbar-button';
- }
- }, {
- key: '_rippleOpt',
- get: function get$$1() {
- return [this, undefined, { center: '', 'size': 'contain', 'background': 'transparent' }];
- }
- }]);
- return ToolbarButtonElement;
- }(BaseButtonElement);
-
- onsElements.ToolbarButton = ToolbarButtonElement;
- customElements.define('ons-toolbar-button', ToolbarButtonElement);
-
- // Add and register Custom Elements
- setup$1(ons$1); // Setup initial listeners
- window._superSecretOns = ons$1;
-
- return ons$1;
-
- })));
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib25zZW51aS5qcyIsInNvdXJjZXMiOlsiLi4vLi4vY29yZS9zcmMvb25zL2VsZW1lbnRzLmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL3N0eWxlci5qcyIsIi4uLy4uL2NvcmUvc3JjL29ucy9wbGF0Zm9ybS5qcyIsIi4uLy4uL2NvcmUvc3JjL29ucy9wYWdlLWF0dHJpYnV0ZS1leHByZXNzaW9uLmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL2ludGVybmFsL2ludGVybmFsLmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL2ludGVybmFsL2FuaW1hdG9yLWZhY3RvcnkuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvYXV0b3N0eWxlLmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvaW50ZXJuYWwvZGV2aWNlLWJhY2stYnV0dG9uLWRpc3BhdGNoZXIuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvaW50ZXJuYWwvaW5kZXguanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvYW5pbWF0aW9uLW9wdGlvbnMtcGFyc2VyLmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL3V0aWwuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvYW5pbWl0LmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL2dlc3R1cmUtZGV0ZWN0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvY29udGVudC1yZWFkeS5qcyIsIi4uLy4uL2NvcmUvc3JjL29ucy9pbnRlcm5hbC90b2FzdC1xdWV1ZS5qcyIsIi4uLy4uL2NvcmUvc3JjL29ucy9ub3RpZmljYXRpb24uanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvYWN0aW9uLXNoZWV0LmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL21pY3JvZXZlbnQuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvb3JpZW50YXRpb24uanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvbW9kaWZpZXIuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvc29mdHdhcmUta2V5Ym9hcmQuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvZG9vcmxvY2suanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvcGFnZS1sb2FkZXIuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvaW5kZXguanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvQG9uc2VudWkvZmFzdGNsaWNrL2xpYi9mYXN0Y2xpY2suanMiLCIuLi8uLi9jb3JlL3NyYy9wb2x5ZmlsbHMvcG9seWZpbGwtc3dpdGNoZXMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19nbG9iYWwuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19jb3JlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9faXMtb2JqZWN0LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fYW4tb2JqZWN0LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fZmFpbHMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19kZXNjcmlwdG9ycy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2RvbS1jcmVhdGUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19pZTgtZG9tLWRlZmluZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX3RvLXByaW1pdGl2ZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX29iamVjdC1kcC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX3Byb3BlcnR5LWRlc2MuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19oaWRlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9faGFzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fdWlkLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fcmVkZWZpbmUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19hLWZ1bmN0aW9uLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fY3R4LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fZXhwb3J0LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fb2JqZWN0LXBpZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2NvZi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2lvYmplY3QuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19kZWZpbmVkLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fdG8taW9iamVjdC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX29iamVjdC1nb3BkLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fc2V0LXByb3RvLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lczYub2JqZWN0LnNldC1wcm90b3R5cGUtb2YuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9mbi9vYmplY3Qvc2V0LXByb3RvdHlwZS1vZi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX3NoYXJlZC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX3drcy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2NsYXNzb2YuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzNi5vYmplY3QudG8tc3RyaW5nLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fdG8taW50ZWdlci5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX3N0cmluZy1hdC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2xpYnJhcnkuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19pdGVyYXRvcnMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL190by1sZW5ndGguanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL190by1hYnNvbHV0ZS1pbmRleC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2FycmF5LWluY2x1ZGVzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fc2hhcmVkLWtleS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX29iamVjdC1rZXlzLWludGVybmFsLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fZW51bS1idWcta2V5cy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX29iamVjdC1rZXlzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fb2JqZWN0LWRwcy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2h0bWwuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19vYmplY3QtY3JlYXRlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fc2V0LXRvLXN0cmluZy10YWcuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19pdGVyLWNyZWF0ZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX3RvLW9iamVjdC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX29iamVjdC1ncG8uanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19pdGVyLWRlZmluZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXM2LnN0cmluZy5pdGVyYXRvci5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2FkZC10by11bnNjb3BhYmxlcy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2l0ZXItc3RlcC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXM2LmFycmF5Lml0ZXJhdG9yLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy93ZWIuZG9tLml0ZXJhYmxlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fcmVkZWZpbmUtYWxsLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fYW4taW5zdGFuY2UuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19pdGVyLWNhbGwuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19pcy1hcnJheS1pdGVyLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9jb3JlLmdldC1pdGVyYXRvci1tZXRob2QuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19mb3Itb2YuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19zZXQtc3BlY2llcy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX21ldGEuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL192YWxpZGF0ZS1jb2xsZWN0aW9uLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fY29sbGVjdGlvbi1zdHJvbmcuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19pdGVyLWRldGVjdC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2luaGVyaXQtaWYtcmVxdWlyZWQuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19jb2xsZWN0aW9uLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lczYuc2V0LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fYXJyYXktZnJvbS1pdGVyYWJsZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2NvbGxlY3Rpb24tdG8tanNvbi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXM3LnNldC50by1qc29uLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fc2V0LWNvbGxlY3Rpb24tb2YuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzNy5zZXQub2YuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19zZXQtY29sbGVjdGlvbi1mcm9tLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lczcuc2V0LmZyb20uanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9mbi9zZXQuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzNi5tYXAuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzNy5tYXAudG8tanNvbi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXM3Lm1hcC5vZi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXM3Lm1hcC5mcm9tLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvZm4vbWFwLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9faXMtYXJyYXkuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19hcnJheS1zcGVjaWVzLWNvbnN0cnVjdG9yLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fYXJyYXktc3BlY2llcy1jcmVhdGUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19hcnJheS1tZXRob2RzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fb2JqZWN0LWdvcHMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19vYmplY3QtYXNzaWduLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fY29sbGVjdGlvbi13ZWFrLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lczYud2Vhay1tYXAuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzNy53ZWFrLW1hcC5vZi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXM3LndlYWstbWFwLmZyb20uanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9mbi93ZWFrLW1hcC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2NyZWF0ZS1wcm9wZXJ0eS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXM2LmFycmF5LmZyb20uanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9mbi9hcnJheS9mcm9tLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0BvbnNlbnVpL2N1c3RvbS1lbGVtZW50cy9zcmMvVXRpbGl0aWVzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0BvbnNlbnVpL2N1c3RvbS1lbGVtZW50cy9zcmMvQ3VzdG9tRWxlbWVudFN0YXRlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0BvbnNlbnVpL2N1c3RvbS1lbGVtZW50cy9zcmMvQ3VzdG9tRWxlbWVudEludGVybmFscy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL0RvY3VtZW50Q29uc3RydWN0aW9uT2JzZXJ2ZXIuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvQG9uc2VudWkvY3VzdG9tLWVsZW1lbnRzL3NyYy9EZWZlcnJlZC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL0N1c3RvbUVsZW1lbnRSZWdpc3RyeS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL1BhdGNoL05hdGl2ZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL0FscmVhZHlDb25zdHJ1Y3RlZE1hcmtlci5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL1BhdGNoL0hUTUxFbGVtZW50LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0BvbnNlbnVpL2N1c3RvbS1lbGVtZW50cy9zcmMvUGF0Y2gvSW50ZXJmYWNlL1BhcmVudE5vZGUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvQG9uc2VudWkvY3VzdG9tLWVsZW1lbnRzL3NyYy9QYXRjaC9Eb2N1bWVudC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL1BhdGNoL05vZGUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvQG9uc2VudWkvY3VzdG9tLWVsZW1lbnRzL3NyYy9QYXRjaC9JbnRlcmZhY2UvQ2hpbGROb2RlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0BvbnNlbnVpL2N1c3RvbS1lbGVtZW50cy9zcmMvUGF0Y2gvRWxlbWVudC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL2N1c3RvbS1lbGVtZW50cy5qcyIsIi4uLy4uL2NvcmUvc3JjL3BvbHlmaWxscy9NdXRhdGlvbk9ic2VydmVyQDAuNy4yMi9NdXRhdGlvbk9ic2VydmVyLmpzIiwiLi4vLi4vY29yZS9zcmMvcG9seWZpbGxzL3NldEltbWVkaWF0ZUAxLjAuMittb2Qvc2V0SW1tZWRpYXRlLmpzIiwiLi4vLi4vY29yZS9zcmMvcG9seWZpbGxzL2luZGV4LmpzIiwiLi4vLi4vY29yZS9zcmMvdmVuZG9yL3ZpZXdwb3J0LmpzIiwiLi4vLi4vY29yZS9zcmMvc2V0dXAuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9iYXNlL2Jhc2UtZWxlbWVudC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy10ZW1wbGF0ZS5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1pZi5qcyIsIi4uLy4uL2NvcmUvc3JjL29ucy9iYXNlLWFuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL2lwaG9uZXgtcGF0Y2guanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtYWN0aW9uLXNoZWV0L2FuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvYmFzZS9iYXNlLWRpYWxvZy5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1hY3Rpb24tc2hlZXQvaW5kZXguanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9iYXNlL2Jhc2UtYnV0dG9uLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWFjdGlvbi1zaGVldC1idXR0b24uanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtYWxlcnQtZGlhbG9nL2FuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWFsZXJ0LWRpYWxvZy9pbmRleC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1hbGVydC1kaWFsb2ctYnV0dG9uLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWJhY2stYnV0dG9uLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWJvdHRvbS10b29sYmFyLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWJ1dHRvbi5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1jYXJkLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWNhcm91c2VsLWl0ZW0uanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvaW50ZXJuYWwvc3dpcGVyLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWNhcm91c2VsLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWNvbC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1kaWFsb2cvYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtZGlhbG9nL2luZGV4LmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWZhYi5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1nZXN0dXJlLWRldGVjdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWljb24uanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvaW50ZXJuYWwvbGF6eS1yZXBlYXQuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbGF6eS1yZXBlYXQuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbGlzdC1oZWFkZXIuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbGlzdC10aXRsZS5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1saXN0LWl0ZW0vYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbGlzdC1pdGVtL2luZGV4LmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWxpc3QuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9iYXNlL2Jhc2UtaW5wdXQuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtaW5wdXQuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9iYXNlL2Jhc2UtY2hlY2tib3guanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtY2hlY2tib3guanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtcmFkaW8uanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtc2VhcmNoLWlucHV0LmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLW1vZGFsL2FuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLW1vZGFsL2ZhZGUtYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbW9kYWwvbGlmdC1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1tb2RhbC9pbmRleC5qcyIsIi4uLy4uL2NvcmUvc3JjL29ucy9pbnRlcm5hbC9zd2lwZS1yZXZlYWwuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbmF2aWdhdG9yL2FuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLW5hdmlnYXRvci9pb3Mtc3dpcGUtYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbmF2aWdhdG9yL2lvcy1zbGlkZS1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1uYXZpZ2F0b3IvaW9zLWxpZnQtYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbmF2aWdhdG9yL2lvcy1mYWRlLWFuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLW5hdmlnYXRvci9tZC1zbGlkZS1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1uYXZpZ2F0b3IvbWQtbGlmdC1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1uYXZpZ2F0b3IvbWQtZmFkZS1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1uYXZpZ2F0b3Ivbm9uZS1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1uYXZpZ2F0b3IvaW5kZXguanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtdG9vbGJhci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1wYWdlLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXBvcG92ZXIvYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtcG9wb3Zlci9pbmRleC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1wcm9ncmVzcy1iYXIuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtcHJvZ3Jlc3MtY2lyY3VsYXIuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtcHVsbC1ob29rLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXJhbmdlLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXJpcHBsZS9hbmltYXRvci1jc3MuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtcmlwcGxlL2luZGV4LmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXJvdy5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1zZWdtZW50LmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXNlbGVjdC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1zcGVlZC1kaWFsLWl0ZW0uanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtc3BlZWQtZGlhbC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1zcGxpdHRlci1jb250ZW50LmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXNwbGl0dGVyLW1hc2suanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtc3BsaXR0ZXIvYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtc3BsaXR0ZXIvb3ZlcmxheS1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1zcGxpdHRlci9wdXNoLWFuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXNwbGl0dGVyL3JldmVhbC1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1zcGxpdHRlci9pbmRleC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1zcGxpdHRlci1zaWRlLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXN3aXRjaC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy10YWJiYXIvaW5kZXguanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtdGFiLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXRvYXN0L2FuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXRvYXN0L2ZhZGUtYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtdG9hc3QvYXNjZW5kLWFuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXRvYXN0L2xpZnQtYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtdG9hc3QvZmFsbC1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy10b2FzdC9pbmRleC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy10b29sYmFyLWJ1dHRvbi5qcyIsIi4uLy4uL2NvcmUvc3JjL2luZGV4LnVtZC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCB7IH07XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5cbi8qKlxuICogQWRkIHZlbmRvciBwcmVmaXguXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAqIEByZXR1cm4ge1N0cmluZ31cbiAqL1xuY29uc3QgcHJlZml4ID0gKGZ1bmN0aW9uKCkge1xuICBjb25zdCBzdHlsZXMgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsICcnKTtcbiAgY29uc3QgcHJlZml4ID0gKEFycmF5LnByb3RvdHlwZS5zbGljZVxuICAgIC5jYWxsKHN0eWxlcylcbiAgICAuam9pbignJylcbiAgICAubWF0Y2goLy0obW96fHdlYmtpdHxtcyktLykgfHwgKHN0eWxlcy5PTGluayA9PT0gJycgJiYgWycnLCAnbyddKVxuICApWzFdO1xuXG4gIHJldHVybiBmdW5jdGlvbihuYW1lKSB7XG4gICAgcmV0dXJuICctJyArIHByZWZpeCArICctJyArIHV0aWwuaHlwaGVuYXRlKG5hbWUpO1xuICB9O1xufSkoKTtcblxuXG4vKipcbiAqIE1pbmltYWwgdXRpbGl0eSBsaWJyYXJ5IGZvciBtYW5pcHVsYXRpbmcgZWxlbWVudCdzIHN0eWxlLlxuICogU2V0IGVsZW1lbnQncyBzdHlsZS5cbiAqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdHlsZXNcbiAqIEByZXR1cm4ge0VsZW1lbnR9XG4gKi9cbmNvbnN0IHN0eWxlciA9IGZ1bmN0aW9uKGVsZW1lbnQsIHN0eWxlKSB7XG4gIE9iamVjdC5rZXlzKHN0eWxlKS5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICAgIGlmIChrZXkgaW4gZWxlbWVudC5zdHlsZSkge1xuICAgICAgZWxlbWVudC5zdHlsZVtrZXldID0gc3R5bGVba2V5XTtcbiAgICB9IGVsc2UgaWYgKHByZWZpeChrZXkpIGluIGVsZW1lbnQuc3R5bGUpIHtcbiAgICAgIGVsZW1lbnQuc3R5bGVbcHJlZml4KGtleSldID0gc3R5bGVba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgdXRpbC53YXJuKCdObyBzdWNoIHN0eWxlIHByb3BlcnR5OiAnICsga2V5KTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gZWxlbWVudDtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge1N0cmluZ30gc3R5bGVzIFNwYWNlLXNlcGFyYXRlZCBDU1MgcHJvcGVydGllcyB0byByZW1vdmVcbiAqL1xuc3R5bGVyLmNsZWFyID0gZnVuY3Rpb24oZWxlbWVudCwgc3R5bGVzID0gJycpIHtcbiAgY29uc3QgY2xlYXJsaXN0ID0gc3R5bGVzLnNwbGl0KC9cXHMrLykucmVkdWNlKChyLCBzKSA9PiByLmNvbmNhdChbdXRpbC5oeXBoZW5hdGUocyksIHByZWZpeChzKV0pLCBbXSksXG4gICAga2V5cyA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSBlbGVtZW50LnN0eWxlLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgY29uc3Qga2V5ID0gZWxlbWVudC5zdHlsZVtpXTtcbiAgICBpZiAoY2xlYXJsaXN0Lmxlbmd0aCA9PT0gMCB8fCBjbGVhcmxpc3Quc29tZShzID0+IGtleS5pbmRleE9mKHMpID09PSAwKSkge1xuICAgICAga2V5cy5wdXNoKGtleSk7IC8vIFN0b3JlIHRoZSBrZXkgdG8gZml4IFNhZmFyaSBzdHlsZSBpbmRleGVzXG4gICAgfVxuICB9XG5cbiAga2V5cy5mb3JFYWNoKGtleSA9PiBlbGVtZW50LnN0eWxlW2tleV0gPSAnJyk7XG4gIGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdzdHlsZScpID09PSAnJyAmJiBlbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgnc3R5bGUnKTtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IHN0eWxlcjtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbi8vIFNhdmUgSFRNTEVsZW1lbnQgb2JqZWN0IGJlZm9yZSBDdXN0b20gRWxlbWVudHMgcG9seWZpbGwgcGF0Y2ggZ2xvYmFsIEhUTUxFbGVtZW50LlxuY29uc3QgTmF0aXZlSFRNTEVsZW1lbnQgPSB3aW5kb3cuSFRNTEVsZW1lbnQ7XG5cbi8qKlxuICogQG9iamVjdCBvbnMucGxhdGZvcm1cbiAqIEBjYXRlZ29yeSB1dGlsXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVV0aWxpdHkgbWV0aG9kcyB0byBkZXRlY3QgY3VycmVudCBwbGF0Zm9ybS5bL2VuXVxuICogICBbamFd54++5Zyo5a6f6KGM44GV44KM44Gm44GE44KL44OX44Op44OD44OI44OV44Kp44O844Og44KS5qSc55+l44GZ44KL44Gf44KB44Gu44Om44O844OG44Kj44Oq44OG44Kj44Oh44K944OD44OJ44KS5Y+O44KB44Gf44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAqL1xuY2xhc3MgUGxhdGZvcm0ge1xuXG4gIC8qKlxuICAgKiBBbGwgZWxlbWVudHMgd2lsbCBiZSByZW5kZXJlZCBhcyBpZiB0aGUgYXBwIHdhcyBydW5uaW5nIG9uIHRoaXMgcGxhdGZvcm0uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqL1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLl9zZWxlY3RlZFBsYXRmb3JtID0gbnVsbDtcbiAgICB0aGlzLl9pZ25vcmVQbGF0Zm9ybVNlbGVjdCA9IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2Qgc2VsZWN0XG4gICAqIEBzaWduYXR1cmUgc2VsZWN0KHBsYXRmb3JtKVxuICAgKiBAcGFyYW0gIHtzdHJpbmd9IHBsYXRmb3JtIE5hbWUgb2YgdGhlIHBsYXRmb3JtLlxuICAgKiAgIFtlbl1Qb3NzaWJsZSB2YWx1ZXMgYXJlOiBcIm9wZXJhXCIsIFwiZmlyZWZveFwiLCBcInNhZmFyaVwiLCBcImNocm9tZVwiLCBcImllXCIsIFwiYW5kcm9pZFwiLCBcImJsYWNrYmVycnlcIiwgXCJpb3NcIiBvciBcIndwXCIuWy9lbl1cbiAgICogICBbamFdXCJvcGVyYVwiLCBcImZpcmVmb3hcIiwgXCJzYWZhcmlcIiwgXCJjaHJvbWVcIiwgXCJpZVwiLCBcImFuZHJvaWRcIiwgXCJibGFja2JlcnJ5XCIsIFwiaW9zXCIsIFwid3BcIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TZXRzIHRoZSBwbGF0Zm9ybSB1c2VkIHRvIHJlbmRlciB0aGUgZWxlbWVudHMuIFVzZWZ1bCBmb3IgdGVzdGluZy5bL2VuXVxuICAgKiAgIFtqYV3opoHntKDjgpLmj4/nlLvjgZnjgovjgZ/jgoHjgavliKnnlKjjgZnjgovjg5fjg6njg4Pjg4jjg5Xjgqnjg7zjg6DlkI3jgpLoqK3lrprjgZfjgb7jgZnjgILjg4bjgrnjg4jjgavkvr/liKnjgafjgZnjgIJbL2phXVxuICAgKi9cbiAgc2VsZWN0KHBsYXRmb3JtKSB7XG4gICAgaWYgKHR5cGVvZiBwbGF0Zm9ybSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHRoaXMuX3NlbGVjdGVkUGxhdGZvcm0gPSBwbGF0Zm9ybS50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICBfZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpIHtcbiAgICByZXR1cm4gdGhpcy5faWdub3JlUGxhdGZvcm1TZWxlY3QgPyBudWxsIDogdGhpcy5fc2VsZWN0ZWRQbGF0Zm9ybTtcbiAgfVxuXG4gIF9ydW5PbkFjdHVhbFBsYXRmb3JtKGZuKSB7XG4gICAgdGhpcy5faWdub3JlUGxhdGZvcm1TZWxlY3QgPSB0cnVlO1xuICAgIGNvbnN0IHJlc3VsdCA9IGZuKCk7XG4gICAgdGhpcy5faWdub3JlUGxhdGZvcm1TZWxlY3QgPSBmYWxzZTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gR2VuZXJhbFxuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNXZWJWaWV3XG4gICAqIEBzaWduYXR1cmUgaXNXZWJWaWV3KClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciBhcHAgaXMgcnVubmluZyBpbiBDb3Jkb3ZhLlsvZW5dXG4gICAqICAgW2phXUNvcmRvdmHlhoXjgaflrp/ooYzjgZXjgozjgabjgYTjgovjgYvjganjgYbjgYvjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgaXNXZWJWaWV3KCkge1xuICAgIGlmIChkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnbG9hZGluZycgfHwgZG9jdW1lbnQucmVhZHlTdGF0ZSA9PSAndW5pbml0aWFsaXplZCcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaXNXZWJWaWV3KCkgbWV0aG9kIGlzIGF2YWlsYWJsZSBhZnRlciBkb20gY29udGVudHMgbG9hZGVkLicpO1xuICAgIH1cblxuICAgIHJldHVybiAhISh3aW5kb3cuY29yZG92YSB8fCB3aW5kb3cucGhvbmVnYXAgfHwgd2luZG93LlBob25lR2FwKTtcbiAgfVxuXG4gIC8vLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBpT1MgZGV2aWNlc1xuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNJUGhvbmVcbiAgICogQHNpZ25hdHVyZSBpc0lQaG9uZSgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHdoZXRoZXIgdGhlIGRldmljZSBpcyBpUGhvbmUuWy9lbl1cbiAgICogICBbamFdaVBob25l5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzSVBob25lKCkge1xuICAgIHJldHVybiAvaVBob25lL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGlzSVBob25lWFxuICAgKiBAc2lnbmF0dXJlIGlzSVBob25lWCgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHdoZXRoZXIgdGhlIGRldmljZSBpcyBpUGhvbmUgWCwgWFMsIFhTIE1heCwgb3IgWFIuWy9lbl1cbiAgICogICBbamFdaVBob25lIFgg44KEIFhT44CBWFMgTWF444CB44G+44Gf44GvIFhSIOS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0lQaG9uZVgoKSB7XG4gICAgLy8gaU9TIFdlYlZpZXdzIG9uIHRoZSBzYW1lIGlPUyB2ZXJzaW9uIGhhdmUgdGhlIHNhbWUgdXNlciBhZ2VudC5cbiAgICAvLyBXZSBjYW5ub3QgYXZvaWQgdXNpbmcgd2luZG93LnNjcmVlbi5cbiAgICAvLyBXZSBhbHNvIGNhbm5vdCB1c2UgY29yZG92YS1wbHVnaW4tZGV2aWNlIHNpbmNlIGl0cyBiZWhhdmlvciBpcyBkaWZmZXJlbnQgYmV0d2VlbiBzaW11bGF0b3JzIGFuZCByZWFsIGRldmljZXMuXG4gICAgLy8gVGhpcyB3b3JrcyB3ZWxsIGJvdGggaW4gaU9TIFNhZmFyaSBhbmQgKFVJfFdLKVdlYlZpZXcgb2YgaVBob25lIFguXG4gICAgcmV0dXJuIHRoaXMuaXNJUGhvbmUoKSAmJlxuICAgICAgKHdpbmRvdy5zY3JlZW4ud2lkdGggPT09IDM3NSAmJiB3aW5kb3cuc2NyZWVuLmhlaWdodCA9PT0gODEyIHx8IC8vIFgsIFhTIHBvcnRyYWl0XG4gICAgICAgd2luZG93LnNjcmVlbi53aWR0aCA9PT0gODEyICYmIHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID09PSAzNzUgfHwgLy8gWCwgWFMgbGFuZHNjYXBlXG4gICAgICAgd2luZG93LnNjcmVlbi53aWR0aCA9PT0gNDE0ICYmIHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID09PSA4OTYgfHwgLy8gWFMgTWF4LCBYUiBwb3J0cmFpdFxuICAgICAgIHdpbmRvdy5zY3JlZW4ud2lkdGggPT09IDg5NiAmJiB3aW5kb3cuc2NyZWVuLmhlaWdodCA9PT0gNDE0KTsgLy8gWFMgTWF4LCBYUiBsYW5kc2NhcGVcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGlzSVBhZFxuICAgKiBAc2lnbmF0dXJlIGlzSVBhZCgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHdoZXRoZXIgdGhlIGRldmljZSBpcyBpUGFkLlsvZW5dXG4gICAqICAgW2phXWlQYWTkuIrjgaflrp/ooYzjgZXjgozjgabjgYTjgovjgYvjganjgYbjgYvjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgaXNJUGFkKCkge1xuICAgIHJldHVybiAvaVBhZC9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzSVBvZCgpIHtcbiAgICByZXR1cm4gL2lQb2QvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICB9XG5cbiAgLy8tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIGlPUyB2ZXJzaW9uc1xuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNJT1NcbiAgICogQHNpZ25hdHVyZSBpc0lPUyhbZm9yY2VBY3R1YWxQbGF0Zm9ybV0pXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gZm9yY2VBY3R1YWxQbGF0Zm9ybVxuICAgKiAgIFtlbl1JZiB0cnVlLCBzZWxlY3RlZCBwbGF0Zm9ybSBpcyBpZ25vcmVkIGFuZCB0aGUgYWN0dWFsIHBsYXRmb3JtIGlzIHJldHVybmVkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHdoZXRoZXIgdGhlIE9TIGlzIGlPUy4gQnkgZGVmYXVsdCB3aWxsIHJldHVybiBtYW51YWxseSBzZWxlY3RlZCBwbGF0Zm9ybSBpZiBpdCBpcyBzZXQuWy9lbl1cbiAgICogICBbamFdaU9T5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzSU9TKGZvcmNlQWN0dWFsUGxhdGZvcm0pIHtcbiAgICBpZiAoIWZvcmNlQWN0dWFsUGxhdGZvcm0gJiYgdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpID09PSAnaW9zJztcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGRldmljZSA9PT0gJ29iamVjdCcgJiYgIS9icm93c2VyL2kudGVzdChkZXZpY2UucGxhdGZvcm0pKSB7XG4gICAgICByZXR1cm4gL2lPUy9pLnRlc3QoZGV2aWNlLnBsYXRmb3JtKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIC9pUGhvbmV8aVBhZHxpUG9kL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc0lPUzdhYm92ZVxuICAgKiBAc2lnbmF0dXJlIGlzSU9TN2Fib3ZlKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgaU9TIHZlcnNpb24gaXMgNyBvciBhYm92ZS5bL2VuXVxuICAgKiAgIFtqYV1pT1M35Lul5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzSU9TN2Fib3ZlKCkge1xuICAgIGlmICh0eXBlb2YgZGV2aWNlID09PSAnb2JqZWN0JyAmJiAhL2Jyb3dzZXIvaS50ZXN0KGRldmljZS5wbGF0Zm9ybSkpIHtcbiAgICAgIHJldHVybiAoL2lPUy9pLnRlc3QoZGV2aWNlLnBsYXRmb3JtKSAmJiAocGFyc2VJbnQoZGV2aWNlLnZlcnNpb24uc3BsaXQoJy4nKVswXSkgPj0gNykpO1xuICAgIH0gZWxzZSBpZiAoL2lQaG9uZXxpUGFkfGlQb2QvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpKSB7XG4gICAgICBjb25zdCB2ZXIgPSAobmF2aWdhdG9yLnVzZXJBZ2VudC5tYXRjaCgvXFxiWzAtOV0rX1swLTldKyg/Ol9bMC05XSspP1xcYi8pIHx8IFsnJ10pWzBdLnJlcGxhY2UoL18vZywgJy4nKTtcbiAgICAgIHJldHVybiAocGFyc2VJbnQodmVyLnNwbGl0KCcuJylbMF0pID49IDcpO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gaU9TIGJyb3dzZXJzXG4gIC8vLS0tLS0tLS0tLS0tLS0tLVxuICAvKipcbiAgICogQG1ldGhvZCBpc0lPU1NhZmFyaVxuICAgKiBAc2lnbmF0dXJlIGlzSU9TU2FmYXJpKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciBhcHAgaXMgcnVubmluZyBpbiBpT1MgU2FmYXJpLlsvZW5dXG4gICAqICAgW2phXWlPUyBTYWZhcmnjgaflrp/ooYzjgZXjgozjgabjgYTjgovjgYvjganjgYbjgYvjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgaXNJT1NTYWZhcmkoKSB7XG4gICAgY29uc3QgbmF2aWdhdG9yID0gd2luZG93Lm5hdmlnYXRvcjtcbiAgICBjb25zdCB1YSA9IG5hdmlnYXRvci51c2VyQWdlbnQ7XG5cbiAgICByZXR1cm4gISEodGhpcy5pc0lPUygpICYmIHVhLmluZGV4T2YoJ1NhZmFyaScpICE9PSAtMSAmJiB1YS5pbmRleE9mKCdWZXJzaW9uJykgIT09IC0xICYmICFuYXZpZ2F0b3Iuc3RhbmRhbG9uZSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc1dLV2ViVmlld1xuICAgKiBAc2lnbmF0dXJlIGlzV0tXZWJWaWV3KClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciBhcHAgaXMgcnVubmluZyBpbiBXS1dlYlZpZXcuWy9lbl1cbiAgICogICBbamFdV0tXZWJWaWV344Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzV0tXZWJWaWV3KCkge1xuICAgIGNvbnN0IGx0ZTkgPSAvY29uc3RydWN0b3IvaS50ZXN0KE5hdGl2ZUhUTUxFbGVtZW50KTtcbiAgICByZXR1cm4gISEodGhpcy5pc0lPUygpICYmIHdpbmRvdy53ZWJraXQgJiYgd2luZG93LndlYmtpdC5tZXNzYWdlSGFuZGxlcnMgJiYgd2luZG93LmluZGV4ZWREQiAmJiAhbHRlOSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc1VJV2ViVmlld1xuICAgKiBAc2lnbmF0dXJlIGlzVUlXZWJWaWV3KClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciBhcHAgaXMgcnVubmluZyBpbiBVSVdlYlZpZXcuWy9lbl1cbiAgICogICBbamFdVUlXZWJWaWV344Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzVUlXZWJWaWV3KCkge1xuICAgIHJldHVybiAhISh0aGlzLmlzSU9TKCkgJiYgIXRoaXMuaXNJT1NTYWZhcmkoKSAmJiAhdGhpcy5pc1dLV2ViVmlldygpKTtcbiAgfVxuXG4gIC8vLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBBbmRyb2lkIGRldmljZXNcbiAgLy8tLS0tLS0tLS0tLS0tLS0tXG4gIC8qKlxuICAgKiBAbWV0aG9kIGlzQW5kcm9pZFBob25lXG4gICAqIEBzaWduYXR1cmUgaXNBbmRyb2lkUGhvbmUoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBkZXZpY2UgaXMgQW5kcm9pZCBwaG9uZS5bL2VuXVxuICAgKiAgIFtqYV1BbmRyb2lk5pC65biv5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzQW5kcm9pZFBob25lKCkge1xuICAgIHJldHVybiAvQW5kcm9pZC9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkgJiYgL01vYmlsZS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc0FuZHJvaWRUYWJsZXRcbiAgICogQHNpZ25hdHVyZSBpc0FuZHJvaWRUYWJsZXQoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBkZXZpY2UgaXMgQW5kcm9pZCB0YWJsZXQuWy9lbl1cbiAgICogICBbamFdQW5kcm9pZOOCv+ODluODrOODg+ODiOS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0FuZHJvaWRUYWJsZXQoKSB7XG4gICAgcmV0dXJuIC9BbmRyb2lkL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KSAmJiAhL01vYmlsZS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gIH1cblxuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gQW5kcm9pZCB2ZXJzaW9uc1xuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNBbmRyb2lkXG4gICAqIEBzaWduYXR1cmUgaXNBbmRyb2lkKFtmb3JjZUFjdHVhbFBsYXRmb3JtXSlcbiAgICogQHBhcmFtIHtCb29sZWFufSBmb3JjZUFjdHVhbFBsYXRmb3JtXG4gICAqICAgW2VuXUlmIHRydWUsIHNlbGVjdGVkIHBsYXRmb3JtIGlzIGlnbm9yZWQgYW5kIHRoZSBhY3R1YWwgcGxhdGZvcm0gaXMgcmV0dXJuZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgT1MgaXMgQW5kcm9pZC4gQnkgZGVmYXVsdCB3aWxsIHJldHVybiBtYW51YWxseSBzZWxlY3RlZCBwbGF0Zm9ybSBpZiBpdCBpcyBzZXQuWy9lbl1cbiAgICogICBbamFdQW5kcm9pZOS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0FuZHJvaWQoZm9yY2VBY3R1YWxQbGF0Zm9ybSkge1xuICAgIGlmICghZm9yY2VBY3R1YWxQbGF0Zm9ybSAmJiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkgPT09ICdhbmRyb2lkJztcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGRldmljZSA9PT0gJ29iamVjdCcgJiYgIS9icm93c2VyL2kudGVzdChkZXZpY2UucGxhdGZvcm0pKSB7XG4gICAgICByZXR1cm4gL0FuZHJvaWQvaS50ZXN0KGRldmljZS5wbGF0Zm9ybSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAvQW5kcm9pZC9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gICAgfVxuICB9XG5cbiAgLy8tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIE90aGVyIGRldmljZXNcbiAgLy8tLS0tLS0tLS0tLS0tLS0tXG4gIC8qKlxuICAgKiBAbWV0aG9kIGlzV1BcbiAgICogQHNpZ25hdHVyZSBpc1dQKFtmb3JjZUFjdHVhbFBsYXRmb3JtXSlcbiAgICogQHBhcmFtIHtCb29sZWFufSBmb3JjZUFjdHVhbFBsYXRmb3JtXG4gICAqICAgW2VuXUlmIHRydWUsIHNlbGVjdGVkIHBsYXRmb3JtIGlzIGlnbm9yZWQgYW5kIHRoZSBhY3R1YWwgcGxhdGZvcm0gaXMgcmV0dXJuZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgT1MgaXMgV2luZG93cyBwaG9uZS4gQnkgZGVmYXVsdCB3aWxsIHJldHVybiBtYW51YWxseSBzZWxlY3RlZCBwbGF0Zm9ybSBpZiBpdCBpcyBzZXQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzV1AoZm9yY2VBY3R1YWxQbGF0Zm9ybSkge1xuICAgIGlmICghZm9yY2VBY3R1YWxQbGF0Zm9ybSAmJiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkgPT09ICd3cCc7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBkZXZpY2UgPT09ICdvYmplY3QnICYmICEvYnJvd3Nlci9pLnRlc3QoZGV2aWNlLnBsYXRmb3JtKSkge1xuICAgICAgcmV0dXJuIC9XaW4zMk5UfFdpbkNFL2kudGVzdChkZXZpY2UucGxhdGZvcm0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gL1dpbmRvd3MgUGhvbmV8SUVNb2JpbGV8V1BEZXNrdG9wL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc0JsYWNrQmVycnlcbiAgICogQHNpZ25hdHVyZSBpc0JsYWNrQmVycnkoW2ZvcmNlQWN0dWFsUGxhdGZvcm1dKVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IGZvcmNlQWN0dWFsUGxhdGZvcm1cbiAgICogICBbZW5dSWYgdHJ1ZSwgc2VsZWN0ZWQgcGxhdGZvcm0gaXMgaWdub3JlZCBhbmQgdGhlIGFjdHVhbCBwbGF0Zm9ybSBpcyByZXR1cm5lZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBkZXZpY2UgaXMgQmxhY2tCZXJyeS4gQnkgZGVmYXVsdCB3aWxsIHJldHVybiBtYW51YWxseSBzZWxlY3RlZCBwbGF0Zm9ybSBpZiBpdCBpcyBzZXQuWy9lbl1cbiAgICogICBbamFdQmxhY2tCZXJyeeS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0JsYWNrQmVycnkoZm9yY2VBY3R1YWxQbGF0Zm9ybSkge1xuICAgIGlmICghZm9yY2VBY3R1YWxQbGF0Zm9ybSAmJiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkgPT09ICdibGFja2JlcnJ5JztcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGRldmljZSA9PT0gJ29iamVjdCcgJiYgIS9icm93c2VyL2kudGVzdChkZXZpY2UucGxhdGZvcm0pKSB7XG4gICAgICByZXR1cm4gL0JsYWNrQmVycnkvaS50ZXN0KGRldmljZS5wbGF0Zm9ybSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAvQmxhY2tCZXJyeXxSSU0gVGFibGV0IE9TfEJCMTAvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgIH1cbiAgfVxuXG4gIC8vLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBPdGhlciBicm93c2Vyc1xuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNPcGVyYVxuICAgKiBAc2lnbmF0dXJlIGlzT3BlcmEoW2ZvcmNlQWN0dWFsUGxhdGZvcm1dKVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IGZvcmNlQWN0dWFsUGxhdGZvcm1cbiAgICogICBbZW5dSWYgdHJ1ZSwgc2VsZWN0ZWQgcGxhdGZvcm0gaXMgaWdub3JlZCBhbmQgdGhlIGFjdHVhbCBwbGF0Zm9ybSBpcyByZXR1cm5lZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBicm93c2VyIGlzIE9wZXJhLiBCeSBkZWZhdWx0IHdpbGwgcmV0dXJuIG1hbnVhbGx5IHNlbGVjdGVkIHBsYXRmb3JtIGlmIGl0IGlzIHNldC5bL2VuXVxuICAgKiAgIFtqYV1PcGVyYeS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc09wZXJhKGZvcmNlQWN0dWFsUGxhdGZvcm0pIHtcbiAgICBpZiAoIWZvcmNlQWN0dWFsUGxhdGZvcm0gJiYgdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpID09PSAnb3BlcmEnO1xuICAgIH1cblxuICAgIHJldHVybiAoISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNGaXJlZm94XG4gICAqIEBzaWduYXR1cmUgaXNGaXJlZm94KFtmb3JjZUFjdHVhbFBsYXRmb3JtXSlcbiAgICogQHBhcmFtIHtCb29sZWFufSBmb3JjZUFjdHVhbFBsYXRmb3JtXG4gICAqICAgW2VuXUlmIHRydWUsIHNlbGVjdGVkIHBsYXRmb3JtIGlzIGlnbm9yZWQgYW5kIHRoZSBhY3R1YWwgcGxhdGZvcm0gaXMgcmV0dXJuZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgYnJvd3NlciBpcyBGaXJlZm94LiBCeSBkZWZhdWx0IHdpbGwgcmV0dXJuIG1hbnVhbGx5IHNlbGVjdGVkIHBsYXRmb3JtIGlmIGl0IGlzIHNldC5bL2VuXVxuICAgKiAgIFtqYV1GaXJlZm945LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzRmlyZWZveChmb3JjZUFjdHVhbFBsYXRmb3JtKSB7XG4gICAgaWYgKCFmb3JjZUFjdHVhbFBsYXRmb3JtICYmIHRoaXMuX2dldFNlbGVjdGVkUGxhdGZvcm0oKSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2dldFNlbGVjdGVkUGxhdGZvcm0oKSA9PT0gJ2ZpcmVmb3gnO1xuICAgIH1cblxuICAgIHJldHVybiAodHlwZW9mIEluc3RhbGxUcmlnZ2VyICE9PSAndW5kZWZpbmVkJyk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc1NhZmFyaVxuICAgKiBAc2lnbmF0dXJlIGlzU2FmYXJpKFtmb3JjZUFjdHVhbFBsYXRmb3JtXSlcbiAgICogQHBhcmFtIHtCb29sZWFufSBmb3JjZUFjdHVhbFBsYXRmb3JtXG4gICAqICAgW2VuXUlmIHRydWUsIHNlbGVjdGVkIHBsYXRmb3JtIGlzIGlnbm9yZWQgYW5kIHRoZSBhY3R1YWwgcGxhdGZvcm0gaXMgcmV0dXJuZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgYnJvd3NlciBpcyBTYWZhcmkuIEJ5IGRlZmF1bHQgd2lsbCByZXR1cm4gbWFudWFsbHkgc2VsZWN0ZWQgcGxhdGZvcm0gaWYgaXQgaXMgc2V0LlsvZW5dXG4gICAqICAgW2phXVNhZmFyaeS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc1NhZmFyaShmb3JjZUFjdHVhbFBsYXRmb3JtKSB7XG4gICAgaWYgKCFmb3JjZUFjdHVhbFBsYXRmb3JtICYmIHRoaXMuX2dldFNlbGVjdGVkUGxhdGZvcm0oKSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2dldFNlbGVjdGVkUGxhdGZvcm0oKSA9PT0gJ3NhZmFyaSc7XG4gICAgfVxuXG4gICAgcmV0dXJuIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwod2luZG93LkhUTUxFbGVtZW50KS5pbmRleE9mKCdDb25zdHJ1Y3RvcicpID4gMCkgfHwgKGZ1bmN0aW9uIChwKSB7IHJldHVybiBwLnRvU3RyaW5nKCkgPT09ICdbb2JqZWN0IFNhZmFyaVJlbW90ZU5vdGlmaWNhdGlvbl0nIH0pKCF3aW5kb3dbJ3NhZmFyaSddIHx8IHNhZmFyaS5wdXNoTm90aWZpY2F0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGlzQ2hyb21lXG4gICAqIEBzaWduYXR1cmUgaXNDaHJvbWUoW2ZvcmNlQWN0dWFsUGxhdGZvcm1dKVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IGZvcmNlQWN0dWFsUGxhdGZvcm1cbiAgICogICBbZW5dSWYgdHJ1ZSwgc2VsZWN0ZWQgcGxhdGZvcm0gaXMgaWdub3JlZCBhbmQgdGhlIGFjdHVhbCBwbGF0Zm9ybSBpcyByZXR1cm5lZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBicm93c2VyIGlzIENocm9tZS4gQnkgZGVmYXVsdCB3aWxsIHJldHVybiBtYW51YWxseSBzZWxlY3RlZCBwbGF0Zm9ybSBpZiBpdCBpcyBzZXQuWy9lbl1cbiAgICogICBbamFdQ2hyb21l5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzQ2hyb21lKGZvcmNlQWN0dWFsUGxhdGZvcm0pIHtcbiAgICBpZiAoIWZvcmNlQWN0dWFsUGxhdGZvcm0gJiYgdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpID09PSAnY2hyb21lJztcbiAgICB9XG5cbiAgICByZXR1cm4gKCEhd2luZG93LmNocm9tZSAmJiAhKCEhd2luZG93Lm9wZXJhIHx8IG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignIE9QUi8nKSA+PSAwKSAmJiAhKG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignIEVkZ2UvJykgPj0gMCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNJRVxuICAgKiBAc2lnbmF0dXJlIGlzSUUoW2ZvcmNlQWN0dWFsUGxhdGZvcm1dKVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IGZvcmNlQWN0dWFsUGxhdGZvcm1cbiAgICogICBbZW5dSWYgdHJ1ZSwgc2VsZWN0ZWQgcGxhdGZvcm0gaXMgaWdub3JlZCBhbmQgdGhlIGFjdHVhbCBwbGF0Zm9ybSBpcyByZXR1cm5lZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBicm93c2VyIGlzIEludGVybmV0IEV4cGxvcmVyLiBCeSBkZWZhdWx0IHdpbGwgcmV0dXJuIG1hbnVhbGx5IHNlbGVjdGVkIHBsYXRmb3JtIGlmIGl0IGlzIHNldC5bL2VuXVxuICAgKiAgIFtqYV1JbnRlcm5ldCBFeHBsb3JlcuS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0lFKGZvcmNlQWN0dWFsUGxhdGZvcm0pIHtcbiAgICBpZiAoIWZvcmNlQWN0dWFsUGxhdGZvcm0gJiYgdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpID09PSAnaWUnO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZSB8fCAhIWRvY3VtZW50LmRvY3VtZW50TW9kZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGlzRWRnZVxuICAgKiBAc2lnbmF0dXJlIGlzRWRnZShbZm9yY2VBY3R1YWxQbGF0Zm9ybV0pXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gZm9yY2VBY3R1YWxQbGF0Zm9ybVxuICAgKiAgIFtlbl1JZiB0cnVlLCBzZWxlY3RlZCBwbGF0Zm9ybSBpcyBpZ25vcmVkIGFuZCB0aGUgYWN0dWFsIHBsYXRmb3JtIGlzIHJldHVybmVkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHdoZXRoZXIgdGhlIGJyb3dzZXIgaXMgRWRnZS4gQnkgZGVmYXVsdCB3aWxsIHJldHVybiBtYW51YWxseSBzZWxlY3RlZCBwbGF0Zm9ybSBpZiBpdCBpcyBzZXQuWy9lbl1cbiAgICogICBbamFdRWRnZeS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0VkZ2UoZm9yY2VBY3R1YWxQbGF0Zm9ybSkge1xuICAgIGlmICghZm9yY2VBY3R1YWxQbGF0Zm9ybSAmJiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkgPT09ICdlZGdlJztcbiAgICB9XG5cbiAgICByZXR1cm4gbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgRWRnZS8nKSA+PSAwO1xuICB9XG5cbiAgLy8tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIFV0aWxpdHkgZnVuY3Rpb25zXG4gIC8vLS0tLS0tLS0tLS0tLS0tLVxuICAvKipcbiAgICogQHJldHVybiB7U3RyaW5nfVxuICAgKi9cbiAgZ2V0TW9iaWxlT1MoKSB7XG4gICAgaWYgKHRoaXMuaXNBbmRyb2lkKCkpIHtcbiAgICAgIHJldHVybiAnYW5kcm9pZCc7XG4gICAgfVxuICAgIGVsc2UgaWYgKHRoaXMuaXNJT1MoKSkge1xuICAgICAgcmV0dXJuICdpb3MnO1xuICAgIH1cbiAgICBlbHNlIGlmICh0aGlzLmlzV1AoKSkge1xuICAgICAgcmV0dXJuICd3cCc7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgcmV0dXJuICdvdGhlcic7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge1N0cmluZ31cbiAgICovXG4gIGdldElPU0RldmljZSgpIHtcbiAgICBpZiAodGhpcy5pc0lQaG9uZSgpKSB7XG4gICAgICByZXR1cm4gJ2lwaG9uZSc7XG4gICAgfVxuICAgIGVsc2UgaWYgKHRoaXMuaXNJUGFkKCkpIHtcbiAgICAgIHJldHVybiAnaXBhZCc7XG4gICAgfVxuICAgIGVsc2UgaWYgKHRoaXMuaXNJUG9kKCkpIHtcbiAgICAgIHJldHVybiAnaXBvZCc7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgcmV0dXJuICduYSc7XG4gICAgfVxuICB9XG59XG5cblxuZXhwb3J0IGRlZmF1bHQgbmV3IFBsYXRmb3JtKCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi9wbGF0Zm9ybSc7XG5pbXBvcnQgdXRpbCBmcm9tICcuL3V0aWwnO1xuXG5jb25zdCBlcnJvciA9IG1lc3NhZ2UgPT4gdXRpbC50aHJvdyhgSW4gUGFnZUF0dHJpYnV0ZUV4cHJlc3Npb246ICR7bWVzc2FnZX1gKTtcblxuY29uc3QgcGFnZUF0dHJpYnV0ZUV4cHJlc3Npb24gPSB7XG4gIF92YXJpYWJsZXM6IHt9LFxuXG4gIC8qKlxuICAgKiBEZWZpbmUgYSB2YXJpYWJsZS5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgdmFyaWFibGVcbiAgICogQHBhcmFtIHtTdHJpbmd8RnVuY3Rpb259IHZhbHVlIFZhbHVlIG9mIHRoZSB2YXJpYWJsZS4gQ2FuIGJlIGEgc3RyaW5nIG9yIGEgZnVuY3Rpb24uIFRoZSBmdW5jdGlvbiBtdXN0IHJldHVybiBhIHN0cmluZy5cbiAgICogQHBhcmFtIHtCb29sZWFufSBvdmVyd3JpdGUgSWYgdGhpcyB2YWx1ZSBpcyBmYWxzZSwgYW4gZXJyb3Igd2lsbCBiZSB0aHJvd24gd2hlbiB0cnlpbmcgdG8gZGVmaW5lIGEgdmFyaWFibGUgdGhhdCBoYXMgYWxyZWFkeSBiZWVuIGRlZmluZWQuXG4gICAqL1xuICBkZWZpbmVWYXJpYWJsZTogZnVuY3Rpb24obmFtZSwgdmFsdWUsIG92ZXJ3cml0ZT1mYWxzZSkge1xuICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIGVycm9yKCdWYXJpYWJsZSBuYW1lIG11c3QgYmUgYSBzdHJpbmcnKTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJyAmJiB0eXBlb2YgdmFsdWUgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGVycm9yKCdWYXJpYWJsZSB2YWx1ZSBtdXN0IGJlIGEgc3RyaW5nIG9yIGEgZnVuY3Rpb24nKTtcbiAgICB9XG4gICAgZWxzZSBpZiAodGhpcy5fdmFyaWFibGVzLmhhc093blByb3BlcnR5KG5hbWUpICYmICFvdmVyd3JpdGUpIHtcbiAgICAgIGVycm9yKGBcIiR7bmFtZX1cIiBpcyBhbHJlYWR5IGRlZmluZWRgKTtcbiAgICB9XG4gICAgdGhpcy5fdmFyaWFibGVzW25hbWVdID0gdmFsdWU7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEdldCBhIHZhcmlhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBOYW1lIG9mIHRoZSB2YXJpYWJsZS5cbiAgICogQHJldHVybiB7U3RyaW5nfEZ1bmN0aW9ufG51bGx9XG4gICAqL1xuICBnZXRWYXJpYWJsZTogZnVuY3Rpb24obmFtZSkge1xuICAgIGlmICghdGhpcy5fdmFyaWFibGVzLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fdmFyaWFibGVzW25hbWVdO1xuICB9LFxuXG4gIC8qKlxuICAgKiBSZW1vdmUgYSB2YXJpYWJsZS5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgdmFyYWlibGUuXG4gICAqL1xuICByZW1vdmVWYXJpYWJsZTogZnVuY3Rpb24obmFtZSkge1xuICAgIGRlbGV0ZSB0aGlzLl92YXJpYWJsZXNbbmFtZV07XG4gIH0sXG5cbiAgLyoqXG4gICAqIEdldCBhbGwgdmFyaWFibGVzLlxuICAgKlxuICAgKiBAcmV0dXJuIHtPYmplY3R9XG4gICAqL1xuICBnZXRBbGxWYXJpYWJsZXM6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLl92YXJpYWJsZXM7XG4gIH0sXG4gIF9wYXJzZVBhcnQ6IGZ1bmN0aW9uKHBhcnQpIHtcbiAgICBsZXQgYyxcbiAgICAgIGluSW50ZXJwb2xhdGlvbiA9IGZhbHNlLFxuICAgICAgY3VycmVudEluZGV4ID0gMDtcblxuICAgIGNvbnN0IHRva2VucyA9IFtdO1xuXG4gICAgaWYgKHBhcnQubGVuZ3RoID09PSAwKSB7XG4gICAgICBlcnJvcignVW5hYmxlIHRvIHBhcnNlIGVtcHR5IHN0cmluZycpO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFydC5sZW5ndGg7IGkrKykge1xuICAgICAgYyA9IHBhcnQuY2hhckF0KGkpO1xuXG4gICAgICBpZiAoYyA9PT0gJyQnICYmIHBhcnQuY2hhckF0KGkgKyAxKSA9PT0gJ3snKSB7XG4gICAgICAgIGlmIChpbkludGVycG9sYXRpb24pIHtcbiAgICAgICAgICBlcnJvcignTmVzdGVkIGludGVycG9sYXRpb24gbm90IHN1cHBvcnRlZCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdG9rZW4gPSBwYXJ0LnN1YnN0cmluZyhjdXJyZW50SW5kZXgsIGkpO1xuICAgICAgICBpZiAodG9rZW4ubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHRva2Vucy5wdXNoKHBhcnQuc3Vic3RyaW5nKGN1cnJlbnRJbmRleCwgaSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgY3VycmVudEluZGV4ID0gaTtcbiAgICAgICAgaW5JbnRlcnBvbGF0aW9uID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKGMgPT09ICd9Jykge1xuICAgICAgICBpZiAoIWluSW50ZXJwb2xhdGlvbikge1xuICAgICAgICAgIGVycm9yKCd9IG11c3QgYmUgcHJlY2VlZGVkIGJ5ICR7Jyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB0b2tlbiA9IHBhcnQuc3Vic3RyaW5nKGN1cnJlbnRJbmRleCwgaSArIDEpO1xuICAgICAgICBpZiAodG9rZW4ubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHRva2Vucy5wdXNoKHBhcnQuc3Vic3RyaW5nKGN1cnJlbnRJbmRleCwgaSArIDEpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGN1cnJlbnRJbmRleCA9IGkgKyAxO1xuICAgICAgICBpbkludGVycG9sYXRpb24gPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoaW5JbnRlcnBvbGF0aW9uKSB7XG4gICAgICBlcnJvcignVW50ZXJtaW5hdGVkIGludGVycG9sYXRpb24nKTtcbiAgICB9XG5cbiAgICB0b2tlbnMucHVzaChwYXJ0LnN1YnN0cmluZyhjdXJyZW50SW5kZXgsIHBhcnQubGVuZ3RoKSk7XG5cbiAgICByZXR1cm4gdG9rZW5zO1xuICB9LFxuICBfcmVwbGFjZVRva2VuOiBmdW5jdGlvbih0b2tlbikge1xuICAgIGNvbnN0IHJlID0gL15cXCR7KC4qPyl9JC8sXG4gICAgICBtYXRjaCA9IHRva2VuLm1hdGNoKHJlKTtcblxuICAgIGlmIChtYXRjaCkge1xuICAgICAgY29uc3QgbmFtZSA9IG1hdGNoWzFdLnRyaW0oKTtcbiAgICAgIGNvbnN0IHZhcmlhYmxlID0gdGhpcy5nZXRWYXJpYWJsZShuYW1lKTtcblxuICAgICAgaWYgKHZhcmlhYmxlID09PSBudWxsKSB7XG4gICAgICAgIGVycm9yKGBWYXJpYWJsZSBcIiR7bmFtZX1cIiBkb2VzIG5vdCBleGlzdGApO1xuICAgICAgfVxuICAgICAgZWxzZSBpZiAodHlwZW9mIHZhcmlhYmxlID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gdmFyaWFibGU7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgY29uc3QgcnYgPSB2YXJpYWJsZSgpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgcnYgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgZXJyb3IoJ011c3QgcmV0dXJuIGEgc3RyaW5nJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcnY7XG4gICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgcmV0dXJuIHRva2VuO1xuICAgIH1cbiAgfSxcbiAgX3JlcGxhY2VUb2tlbnM6IGZ1bmN0aW9uKHRva2Vucykge1xuICAgIHJldHVybiB0b2tlbnMubWFwKHRoaXMuX3JlcGxhY2VUb2tlbi5iaW5kKHRoaXMpKTtcbiAgfSxcbiAgX3BhcnNlRXhwcmVzc2lvbjogZnVuY3Rpb24oZXhwcmVzc2lvbikge1xuICAgIHJldHVybiBleHByZXNzaW9uLnNwbGl0KCcsJylcbiAgICAgIC5tYXAoXG4gICAgICAgIGZ1bmN0aW9uKHBhcnQpIHtcbiAgICAgICAgICByZXR1cm4gcGFydC50cmltKCk7XG4gICAgICAgIH1cbiAgICAgIClcbiAgICAgIC5tYXAodGhpcy5fcGFyc2VQYXJ0LmJpbmQodGhpcykpXG4gICAgICAubWFwKHRoaXMuX3JlcGxhY2VUb2tlbnMuYmluZCh0aGlzKSlcbiAgICAgIC5tYXAoKHBhcnQpID0+IHBhcnQuam9pbignJykpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBFdmFsdWF0ZSBhbiBleHByZXNzaW9uLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gZXhwcmVzc2lvbiBBbiBwYWdlIGF0dHJpYnV0ZSBleHByZXNzaW9uLlxuICAgKiBAcmV0dXJuIHtBcnJheX1cbiAgICovXG4gIGV2YWx1YXRlOiBmdW5jdGlvbihleHByZXNzaW9uKSB7XG4gICAgaWYgKCFleHByZXNzaW9uKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX3BhcnNlRXhwcmVzc2lvbihleHByZXNzaW9uKTtcbiAgfVxufTtcblxuLy8gRGVmaW5lIGRlZmF1bHQgdmFyaWFibGVzLlxucGFnZUF0dHJpYnV0ZUV4cHJlc3Npb24uZGVmaW5lVmFyaWFibGUoJ21vYmlsZU9TJywgcGxhdGZvcm0uZ2V0TW9iaWxlT1MoKSk7XG5wYWdlQXR0cmlidXRlRXhwcmVzc2lvbi5kZWZpbmVWYXJpYWJsZSgnaU9TRGV2aWNlJywgcGxhdGZvcm0uZ2V0SU9TRGV2aWNlKCkpO1xucGFnZUF0dHJpYnV0ZUV4cHJlc3Npb24uZGVmaW5lVmFyaWFibGUoJ3J1bnRpbWUnLCAoKSA9PiB7XG4gIHJldHVybiBwbGF0Zm9ybS5pc1dlYlZpZXcoKSA/ICdjb3Jkb3ZhJyA6ICdicm93c2VyJztcbn0pO1xuXG5leHBvcnQgZGVmYXVsdCBwYWdlQXR0cmlidXRlRXhwcmVzc2lvbjtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4uL3V0aWwnO1xuaW1wb3J0IHBsYXRmb3JtIGZyb20gJy4uL3BsYXRmb3JtJztcbmltcG9ydCBwYWdlQXR0cmlidXRlRXhwcmVzc2lvbiBmcm9tICcuLi9wYWdlLWF0dHJpYnV0ZS1leHByZXNzaW9uJztcblxuY29uc3QgaW50ZXJuYWwgPSB7fTtcblxuaW50ZXJuYWwuY29uZmlnID0ge1xuICBhdXRvU3RhdHVzQmFyRmlsbDogdHJ1ZSxcbiAgYW5pbWF0aW9uc0Rpc2FibGVkOiBmYWxzZSxcbiAgd2FybmluZ3NEaXNhYmxlZDogZmFsc2Vcbn07XG5cbmludGVybmFsLm51bGxFbGVtZW50ID0gd2luZG93LmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4vKipcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKi9cbmludGVybmFsLmlzRW5hYmxlZEF1dG9TdGF0dXNCYXJGaWxsID0gKCkgPT4ge1xuICByZXR1cm4gISFpbnRlcm5hbC5jb25maWcuYXV0b1N0YXR1c0JhckZpbGw7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7U3RyaW5nfSBodG1sXG4gKiBAcmV0dXJuIHtTdHJpbmd9XG4gKi9cbmludGVybmFsLm5vcm1hbGl6ZVBhZ2VIVE1MID0gaHRtbCA9PiAoJycgKyBodG1sKS50cmltKCk7XG5cbmludGVybmFsLndhaXRET01Db250ZW50TG9hZGVkID0gY2FsbGJhY2sgPT4ge1xuICBpZiAod2luZG93LmRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdsb2FkaW5nJyB8fCB3aW5kb3cuZG9jdW1lbnQucmVhZHlTdGF0ZSA9PSAndW5pbml0aWFsaXplZCcpIHtcbiAgICBjb25zdCB3cmFwcGVkQ2FsbGJhY2sgPSAoKSA9PiB7XG4gICAgICBjYWxsYmFjaygpO1xuICAgICAgd2luZG93LmRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCB3cmFwcGVkQ2FsbGJhY2spO1xuICAgIH07XG4gICAgd2luZG93LmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCB3cmFwcGVkQ2FsbGJhY2spO1xuICB9IGVsc2Uge1xuICAgIHNldEltbWVkaWF0ZShjYWxsYmFjayk7XG4gIH1cbn07XG5cbmludGVybmFsLmF1dG9TdGF0dXNCYXJGaWxsID0gYWN0aW9uID0+IHtcbiAgY29uc3Qgb25SZWFkeSA9ICgpID0+IHtcbiAgICBpZiAoaW50ZXJuYWwuc2hvdWxkRmlsbFN0YXR1c0JhcigpKSB7XG4gICAgICBhY3Rpb24oKTtcbiAgICB9XG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZGV2aWNlcmVhZHknLCBvblJlYWR5KTtcbiAgfTtcblxuICBpZiAodHlwZW9mIGRldmljZSA9PT0gJ29iamVjdCcpIHtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdkZXZpY2VyZWFkeScsIG9uUmVhZHkpO1xuICB9IGVsc2UgaWYgKFsnY29tcGxldGUnLCAnaW50ZXJhY3RpdmUnXS5pbmRleE9mKGRvY3VtZW50LnJlYWR5U3RhdGUpID09PSAtMSkge1xuICAgIGludGVybmFsLndhaXRET01Db250ZW50TG9hZGVkKG9uUmVhZHkpO1xuICB9IGVsc2Uge1xuICAgIG9uUmVhZHkoKTtcbiAgfVxufTtcblxuaW50ZXJuYWwuc2hvdWxkRmlsbFN0YXR1c0JhciA9ICgpID0+IGludGVybmFsLmlzRW5hYmxlZEF1dG9TdGF0dXNCYXJGaWxsKCkgJiZcbiAgKHBsYXRmb3JtLmlzV2ViVmlldygpICYmIHBsYXRmb3JtLmlzSU9TN2Fib3ZlKCkgJiYgIXBsYXRmb3JtLmlzSVBob25lWCgpIHx8IGRvY3VtZW50LmJvZHkucXVlcnlTZWxlY3RvcignLm9ucy1zdGF0dXMtYmFyLW1vY2suaW9zJykpO1xuXG5pbnRlcm5hbC50ZW1wbGF0ZVN0b3JlID0ge1xuICBfc3RvcmFnZToge30sXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBrZXlcbiAgICogQHJldHVybiB7U3RyaW5nL251bGx9IHRlbXBsYXRlXG4gICAqL1xuICBnZXQoa2V5KSB7XG4gICAgcmV0dXJuIGludGVybmFsLnRlbXBsYXRlU3RvcmUuX3N0b3JhZ2Vba2V5XSB8fCBudWxsO1xuICB9LFxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge1N0cmluZ30ga2V5XG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0ZW1wbGF0ZVxuICAgKi9cbiAgc2V0KGtleSwgdGVtcGxhdGUpIHtcbiAgICBpbnRlcm5hbC50ZW1wbGF0ZVN0b3JlLl9zdG9yYWdlW2tleV0gPSB0ZW1wbGF0ZTtcbiAgfVxufTtcblxud2luZG93LmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ190ZW1wbGF0ZWxvYWRlZCcsIGZ1bmN0aW9uKGUpIHtcbiAgaWYgKGUudGFyZ2V0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdvbnMtdGVtcGxhdGUnKSB7XG4gICAgaW50ZXJuYWwudGVtcGxhdGVTdG9yZS5zZXQoZS50ZW1wbGF0ZUlkLCBlLnRlbXBsYXRlKTtcbiAgfVxufSwgZmFsc2UpO1xuXG5pbnRlcm5hbC53YWl0RE9NQ29udGVudExvYWRlZChmdW5jdGlvbigpIHtcbiAgcmVnaXN0ZXIoJ3NjcmlwdFt0eXBlPVwidGV4dC9vbnMtdGVtcGxhdGVcIl0nKTtcbiAgcmVnaXN0ZXIoJ3NjcmlwdFt0eXBlPVwidGV4dC90ZW1wbGF0ZVwiXScpO1xuICByZWdpc3Rlcignc2NyaXB0W3R5cGU9XCJ0ZXh0L25nLXRlbXBsYXRlXCJdJyk7XG4gIHJlZ2lzdGVyKCd0ZW1wbGF0ZScpO1xuXG4gIGZ1bmN0aW9uIHJlZ2lzdGVyKHF1ZXJ5KSB7XG4gICAgY29uc3QgdGVtcGxhdGVzID0gd2luZG93LmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwocXVlcnkpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGVtcGxhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpbnRlcm5hbC50ZW1wbGF0ZVN0b3JlLnNldCh0ZW1wbGF0ZXNbaV0uZ2V0QXR0cmlidXRlKCdpZCcpLCB0ZW1wbGF0ZXNbaV0udGV4dENvbnRlbnQgfHwgdGVtcGxhdGVzW2ldLmNvbnRlbnQpO1xuICAgIH1cbiAgfVxufSk7XG5cbi8qKlxuICogQHBhcmFtIHtTdHJpbmd9IHBhZ2VcbiAqIEByZXR1cm4ge1Byb21pc2V9XG4gKi9cbmludGVybmFsLmdldFRlbXBsYXRlSFRNTEFzeW5jID0gZnVuY3Rpb24ocGFnZSkge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGludGVybmFsLndhaXRET01Db250ZW50TG9hZGVkKCgpID0+IHtcbiAgICAgIGNvbnN0IGNhY2hlID0gaW50ZXJuYWwudGVtcGxhdGVTdG9yZS5nZXQocGFnZSk7XG4gICAgICBpZiAoY2FjaGUpIHtcbiAgICAgICAgaWYgKGNhY2hlIGluc3RhbmNlb2YgRG9jdW1lbnRGcmFnbWVudCkge1xuICAgICAgICAgIHJldHVybiByZXNvbHZlKGNhY2hlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGh0bWwgPSB0eXBlb2YgY2FjaGUgPT09ICdzdHJpbmcnID8gY2FjaGUgOiBjYWNoZVsxXTtcbiAgICAgICAgcmV0dXJuIHJlc29sdmUoaW50ZXJuYWwubm9ybWFsaXplUGFnZUhUTUwoaHRtbCkpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBsb2NhbCA9IHdpbmRvdy5kb2N1bWVudC5nZXRFbGVtZW50QnlJZChwYWdlKTtcbiAgICAgIGlmIChsb2NhbCkge1xuICAgICAgICBjb25zdCBodG1sID0gbG9jYWwudGV4dENvbnRlbnQgfHwgbG9jYWwuY29udGVudDtcbiAgICAgICAgcmV0dXJuIHJlc29sdmUoaHRtbCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgeGhyLm9wZW4oJ0dFVCcsIHBhZ2UsIHRydWUpO1xuICAgICAgeGhyLm9ubG9hZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjb25zdCBodG1sID0geGhyLnJlc3BvbnNlVGV4dDtcbiAgICAgICAgaWYgKHhoci5zdGF0dXMgPj0gNDAwICYmIHhoci5zdGF0dXMgPCA2MDApIHtcbiAgICAgICAgICByZWplY3QoaHRtbCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gUmVmcmVzaCBzY3JpcHQgdGFnc1xuICAgICAgICAgIGNvbnN0IGZyYWdtZW50ID0gdXRpbC5jcmVhdGVGcmFnbWVudChodG1sKTtcbiAgICAgICAgICB1dGlsLmFycmF5RnJvbShmcmFnbWVudC5xdWVyeVNlbGVjdG9yQWxsKCdzY3JpcHQnKSkuZm9yRWFjaChlbCA9PiB7XG4gICAgICAgICAgICBjb25zdCBzY3JpcHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcbiAgICAgICAgICAgIHNjcmlwdC50eXBlID0gZWwudHlwZSB8fCAndGV4dC9qYXZhc2NyaXB0JztcbiAgICAgICAgICAgIHNjcmlwdC5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShlbC50ZXh0IHx8IGVsLnRleHRDb250ZW50IHx8IGVsLmlubmVySFRNTCkpO1xuICAgICAgICAgICAgZWwucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQoc2NyaXB0LCBlbCk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpbnRlcm5hbC50ZW1wbGF0ZVN0b3JlLnNldChwYWdlLCBmcmFnbWVudCk7XG4gICAgICAgICAgcmVzb2x2ZShmcmFnbWVudCk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICB4aHIub25lcnJvciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB1dGlsLnRocm93KGBQYWdlIHRlbXBsYXRlIG5vdCBmb3VuZDogJHtwYWdlfWApO1xuICAgICAgfTtcbiAgICAgIHhoci5zZW5kKG51bGwpO1xuICAgIH0pO1xuICB9KTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtTdHJpbmd9IHBhZ2VcbiAqIEByZXR1cm4ge1Byb21pc2V9XG4gKi9cbmludGVybmFsLmdldFBhZ2VIVE1MQXN5bmMgPSBmdW5jdGlvbihwYWdlKSB7XG4gIGNvbnN0IHBhZ2VzID0gcGFnZUF0dHJpYnV0ZUV4cHJlc3Npb24uZXZhbHVhdGUocGFnZSk7XG5cbiAgY29uc3QgZ2V0UGFnZSA9IChwYWdlKSA9PiB7XG4gICAgaWYgKHR5cGVvZiBwYWdlICE9PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdNdXN0IHNwZWNpZnkgYSBwYWdlLicpO1xuICAgIH1cblxuICAgIHJldHVybiBpbnRlcm5hbC5nZXRUZW1wbGF0ZUhUTUxBc3luYyhwYWdlKVxuICAgICAgLmNhdGNoKGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIGlmIChwYWdlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3IpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGdldFBhZ2UocGFnZXMuc2hpZnQoKSk7XG4gICAgICB9KTtcbiAgfTtcblxuICByZXR1cm4gZ2V0UGFnZShwYWdlcy5zaGlmdCgpKTtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IGludGVybmFsO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vdXRpbCc7XG5pbXBvcnQgaW50ZXJuYWwgZnJvbSAnLi4vaW50ZXJuYWwnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBbmltYXRvckZhY3Rvcnkge1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0c1xuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cy5hbmltYXRvcnMgVGhlIGRpY3Rpb25hcnkgZm9yIGFuaW1hdG9yIGNsYXNzZXNcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gb3B0cy5iYXNlQ2xhc3MgVGhlIGJhc2UgY2xhc3Mgb2YgYW5pbWF0b3JzXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0cy5iYXNlQ2xhc3NOYW1lXSBUaGUgbmFtZSBvZiB0aGUgYmFzZSBjbGFzcyBvZiBhbmltYXRvcnNcbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRzLmRlZmF1bHRBbmltYXRpb25dIFRoZSBkZWZhdWx0IGFuaW1hdGlvbiBuYW1lXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0cy5kZWZhdWx0QW5pbWF0aW9uT3B0aW9uc10gVGhlIGRlZmF1bHQgYW5pbWF0aW9uIG9wdGlvbnNcbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdHMpIHtcbiAgICB0aGlzLl9hbmltYXRvcnMgPSBvcHRzLmFuaW1hdG9ycztcbiAgICB0aGlzLl9iYXNlQ2xhc3MgPSBvcHRzLmJhc2VDbGFzcztcbiAgICB0aGlzLl9iYXNlQ2xhc3NOYW1lID0gb3B0cy5iYXNlQ2xhc3NOYW1lIHx8IG9wdHMuYmFzZUNsYXNzLm5hbWU7XG4gICAgdGhpcy5fYW5pbWF0aW9uID0gb3B0cy5kZWZhdWx0QW5pbWF0aW9uIHx8ICdkZWZhdWx0JztcbiAgICB0aGlzLl9hbmltYXRpb25PcHRpb25zID0gb3B0cy5kZWZhdWx0QW5pbWF0aW9uT3B0aW9ucyB8fCB7fTtcblxuICAgIGlmICghdGhpcy5fYW5pbWF0b3JzW3RoaXMuX2FuaW1hdGlvbl0pIHtcbiAgICAgIHV0aWwudGhyb3coJ05vIHN1Y2ggYW5pbWF0aW9uOiAnICsgdGhpcy5fYW5pbWF0aW9uKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtTdHJpbmd9IGpzb25TdHJpbmdcbiAgICogQHJldHVybiB7T2JqZWN0L251bGx9XG4gICAqL1xuICBzdGF0aWMgcGFyc2VBbmltYXRpb25PcHRpb25zU3RyaW5nKGpzb25TdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgaWYgKHR5cGVvZiBqc29uU3RyaW5nID09PSAnc3RyaW5nJykge1xuICAgICAgICBjb25zdCByZXN1bHQgPSB1dGlsLmFuaW1hdGlvbk9wdGlvbnNQYXJzZShqc29uU3RyaW5nKTtcbiAgICAgICAgaWYgKHR5cGVvZiByZXN1bHQgPT09ICdvYmplY3QnICYmIHJlc3VsdCAhPT0gbnVsbCkge1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcignXCJhbmltYXRpb24tb3B0aW9uc1wiIGF0dHJpYnV0ZSBtdXN0IGJlIGEgSlNPTiBvYmplY3Qgc3RyaW5nOiAnICsganNvblN0cmluZyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB7fTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdcImFuaW1hdGlvbi1vcHRpb25zXCIgYXR0cmlidXRlIG11c3QgYmUgYSBKU09OIG9iamVjdCBzdHJpbmc6ICcgKyBqc29uU3RyaW5nKTtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICovXG4gIHNldEFuaW1hdGlvbk9wdGlvbnMob3B0aW9ucykge1xuICAgIHRoaXMuX2FuaW1hdGlvbk9wdGlvbnMgPSBvcHRpb25zO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dIFRoZSBhbmltYXRpb24gbmFtZVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc10gVGhlIGFuaW1hdGlvbiBvcHRpb25zXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkZWZhdWx0QW5pbWF0b3IgVGhlIGRlZmF1bHQgYW5pbWF0b3IgaW5zdGFuY2VcbiAgICogQHJldHVybiB7T2JqZWN0fSBBbiBhbmltYXRvciBpbnN0YW5jZVxuICAgKi9cbiAgbmV3QW5pbWF0b3Iob3B0aW9ucyA9IHt9LCBkZWZhdWx0QW5pbWF0b3IpIHtcblxuICAgIGxldCBhbmltYXRvciA9IG51bGw7XG5cbiAgICBpZiAob3B0aW9ucy5hbmltYXRpb24gaW5zdGFuY2VvZiB0aGlzLl9iYXNlQ2xhc3MpIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmFuaW1hdGlvbjtcbiAgICB9XG5cbiAgICBsZXQgQW5pbWF0b3IgPSBudWxsO1xuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLmFuaW1hdGlvbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgIEFuaW1hdG9yID0gdGhpcy5fYW5pbWF0b3JzW29wdGlvbnMuYW5pbWF0aW9uXTtcbiAgICB9XG5cbiAgICBpZiAoIUFuaW1hdG9yICYmIGRlZmF1bHRBbmltYXRvcikge1xuICAgICAgYW5pbWF0b3IgPSBkZWZhdWx0QW5pbWF0b3I7XG4gICAgfSBlbHNlIHtcbiAgICAgIEFuaW1hdG9yID0gQW5pbWF0b3IgfHwgdGhpcy5fYW5pbWF0b3JzW3RoaXMuX2FuaW1hdGlvbl07XG5cbiAgICAgIGNvbnN0IGFuaW1hdGlvbk9wdHMgPSB1dGlsLmV4dGVuZChcbiAgICAgICAge30sXG4gICAgICAgIHRoaXMuX2FuaW1hdGlvbk9wdGlvbnMsXG4gICAgICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyB8fCB7fSxcbiAgICAgICAgaW50ZXJuYWwuY29uZmlnLmFuaW1hdGlvbnNEaXNhYmxlZCA/IHtkdXJhdGlvbjogMCwgZGVsYXk6IDB9IDoge31cbiAgICAgICk7XG5cbiAgICAgIGFuaW1hdG9yID0gbmV3IEFuaW1hdG9yKGFuaW1hdGlvbk9wdHMpO1xuXG4gICAgICBpZiAodHlwZW9mIGFuaW1hdG9yID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGFuaW1hdG9yID0gbmV3IGFuaW1hdG9yKGFuaW1hdGlvbk9wdHMpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5ldy1jYXBcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIShhbmltYXRvciBpbnN0YW5jZW9mIHRoaXMuX2Jhc2VDbGFzcykpIHtcbiAgICAgIHV0aWwudGhyb3coYFwiYW5pbWF0b3JcIiBpcyBub3QgYW4gaW5zdGFuY2Ugb2YgJHt0aGlzLl9iYXNlQ2xhc3NOYW1lfWApO1xuICAgIH1cblxuICAgIHJldHVybiBhbmltYXRvcjtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc1BsYXRmb3JtIGZyb20gJy4vcGxhdGZvcm0nO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi91dGlsJztcblxubGV0IGF1dG9TdHlsZUVuYWJsZWQgPSB0cnVlO1xuXG4vLyBNb2RpZmllcnNcbmNvbnN0IG1vZGlmaWVyc01hcCA9IHtcbiAgJ3F1aWV0JzogJ21hdGVyaWFsLS1mbGF0JyxcbiAgJ2xpZ2h0JzogJ21hdGVyaWFsLS1mbGF0JyxcbiAgJ291dGxpbmUnOiAnbWF0ZXJpYWwtLWZsYXQnLFxuICAnY3RhJzogJycsXG4gICdsYXJnZS0tcXVpZXQnOiAnbWF0ZXJpYWwtLWZsYXQgbGFyZ2UnLFxuICAnbGFyZ2UtLWN0YSc6ICdsYXJnZScsXG4gICdub2JvcmRlcic6ICcnLFxuICAndGFwcGFibGUnOiAnJ1xufTtcblxuY29uc3QgcGxhdGZvcm1zID0ge307XG5cbnBsYXRmb3Jtcy5hbmRyb2lkID0gZWxlbWVudCA9PiB7XG5cbiAgY29uc3QgZWxlbWVudE5hbWUgPSBlbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKTtcblxuICBpZiAoIXV0aWwuaGFzTW9kaWZpZXIoZWxlbWVudCwgJ21hdGVyaWFsJykpIHtcbiAgICBjb25zdCBvbGRNb2RpZmllciA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpIHx8ICcnO1xuXG4gICAgY29uc3QgbmV3TW9kaWZpZXIgPSBvbGRNb2RpZmllci50cmltKCkuc3BsaXQoL1xccysvKS5tYXAoZSA9PiBtb2RpZmllcnNNYXAuaGFzT3duUHJvcGVydHkoZSkgPyBtb2RpZmllcnNNYXBbZV0gOiBlKTtcbiAgICBuZXdNb2RpZmllci51bnNoaWZ0KCdtYXRlcmlhbCcpO1xuXG4gICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJywgbmV3TW9kaWZpZXIuam9pbignICcpLnRyaW0oKSk7XG4gIH1cblxuICBjb25zdCBlbGVtZW50cyA9IFtcbiAgICAnb25zLWFsZXJ0LWRpYWxvZy1idXR0b24nLFxuICAgICdvbnMtdG9vbGJhci1idXR0b24nLFxuICAgICdvbnMtYmFjay1idXR0b24nLFxuICAgICdvbnMtYnV0dG9uJyxcbiAgICAnb25zLWxpc3QtaXRlbScsXG4gICAgJ29ucy1mYWInLFxuICAgICdvbnMtc3BlZWQtZGlhbCcsXG4gICAgJ29ucy1zcGVlZC1kaWFsLWl0ZW0nLFxuICAgICdvbnMtdGFiJ1xuICBdO1xuXG5cbiAgLy8gRWZmZWN0c1xuICBpZiAoZWxlbWVudHMuaW5kZXhPZihlbGVtZW50TmFtZSkgIT09IC0xXG4gICAgJiYgIWVsZW1lbnQuaGFzQXR0cmlidXRlKCdyaXBwbGUnKVxuICAgICYmICFlbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJ29ucy1yaXBwbGUnKSkge1xuXG4gICAgaWYgKGVsZW1lbnROYW1lID09PSAnb25zLWxpc3QtaXRlbScpIHtcbiAgICAgIGlmIChlbGVtZW50Lmhhc0F0dHJpYnV0ZSgndGFwcGFibGUnKSkge1xuICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgncmlwcGxlJywgJycpO1xuICAgICAgICBlbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgndGFwcGFibGUnKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ3JpcHBsZScsICcnKTtcbiAgICB9XG4gIH1cbn07XG5cbnBsYXRmb3Jtcy5pb3MgPSBlbGVtZW50ID0+IHtcblxuIC8vIE1vZGlmaWVyc1xuIGlmICh1dGlsLnJlbW92ZU1vZGlmaWVyKGVsZW1lbnQsICdtYXRlcmlhbCcpKSB7XG4gICBpZiAodXRpbC5yZW1vdmVNb2RpZmllcihlbGVtZW50LCAnbWF0ZXJpYWwtLWZsYXQnKSkge1xuICAgICB1dGlsLmFkZE1vZGlmaWVyKGVsZW1lbnQsICh1dGlsLnJlbW92ZU1vZGlmaWVyKGVsZW1lbnQsICdsYXJnZScpKSA/ICdsYXJnZS0tcXVpZXQnIDogJ3F1aWV0Jyk7XG4gICB9XG5cbiAgIGlmICghZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJykpIHtcbiAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoJ21vZGlmaWVyJyk7XG4gICB9XG4gfVxuXG4gLy8gRWZmZWN0c1xuIGlmIChlbGVtZW50Lmhhc0F0dHJpYnV0ZSgncmlwcGxlJykpIHtcbiAgIGlmIChlbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ29ucy1saXN0LWl0ZW0nKSB7XG4gICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCd0YXBwYWJsZScsICcnKTtcbiAgIH1cblxuICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoJ3JpcHBsZScpO1xuIH1cbn07XG5cbmNvbnN0IHVubG9ja2VkID0ge1xuICBhbmRyb2lkOiB0cnVlXG59O1xuXG5jb25zdCBnZXRQbGF0Zm9ybSA9IChlbGVtZW50LCBmb3JjZSkgPT4ge1xuICBpZiAoYXV0b1N0eWxlRW5hYmxlZCAmJiAhZWxlbWVudC5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGUtYXV0by1zdHlsaW5nJykpIHtcbiAgICBjb25zdCBtb2JpbGVPUyA9IG9uc1BsYXRmb3JtLmdldE1vYmlsZU9TKCk7XG4gICAgaWYgKHBsYXRmb3Jtcy5oYXNPd25Qcm9wZXJ0eShtb2JpbGVPUykgJiYgKHVubG9ja2VkLmhhc093blByb3BlcnR5KG1vYmlsZU9TKSB8fCBmb3JjZSkpIHtcbiAgICAgIHJldHVybiBtb2JpbGVPUztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59O1xuXG5jb25zdCBwcmVwYXJlID0gKGVsZW1lbnQsIGZvcmNlKSA9PiB7XG4gIGNvbnN0IHAgPSBnZXRQbGF0Zm9ybShlbGVtZW50LCBmb3JjZSk7XG4gIHAgJiYgcGxhdGZvcm1zW3BdKGVsZW1lbnQpO1xufTtcblxuY29uc3QgbWFwTW9kaWZpZXIgPSAobW9kaWZpZXIsIGVsZW1lbnQsIGZvcmNlKSA9PiB7XG4gIGlmIChnZXRQbGF0Zm9ybShlbGVtZW50LCBmb3JjZSkpIHtcbiAgICByZXR1cm4gbW9kaWZpZXIuc3BsaXQoL1xccysvKS5tYXAobSA9PiBtb2RpZmllcnNNYXAuaGFzT3duUHJvcGVydHkobSkgPyBtb2RpZmllcnNNYXBbbV0gOiBtKS5qb2luKCcgJyk7XG4gIH1cbiAgcmV0dXJuIG1vZGlmaWVyO1xufTtcblxuY29uc3QgcmVzdG9yZU1vZGlmaWVyID0gZWxlbWVudCA9PiB7XG4gIGlmIChnZXRQbGF0Zm9ybShlbGVtZW50KSA9PT0gJ2FuZHJvaWQnKSB7XG4gICAgY29uc3QgbW9kaWZpZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnbW9kaWZpZXInKSB8fCAnJztcbiAgICBsZXQgbmV3TW9kaWZpZXIgPSBtYXBNb2RpZmllcihtb2RpZmllciwgZWxlbWVudCk7XG5cbiAgICBpZiAoIS8oXnxcXHMrKW1hdGVyaWFsKCR8XFxzKykvaS50ZXN0KG1vZGlmaWVyKSkge1xuICAgICAgbmV3TW9kaWZpZXIgPSAnbWF0ZXJpYWwgJyArIG5ld01vZGlmaWVyO1xuICAgIH1cblxuICAgIGlmIChuZXdNb2RpZmllciAhPT0gbW9kaWZpZXIpIHtcbiAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCdtb2RpZmllcicsIG5ld01vZGlmaWVyLnRyaW0oKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuZXhwb3J0IGRlZmF1bHQge1xuICBpc0VuYWJsZWQ6ICgpID0+IGF1dG9TdHlsZUVuYWJsZWQsXG4gIGVuYWJsZTogKCkgPT4gYXV0b1N0eWxlRW5hYmxlZCA9IHRydWUsXG4gIGRpc2FibGU6ICgpID0+IGF1dG9TdHlsZUVuYWJsZWQgPSBmYWxzZSxcbiAgcHJlcGFyZSxcbiAgbWFwTW9kaWZpZXIsXG4gIGdldFBsYXRmb3JtLFxuICByZXN0b3JlTW9kaWZpZXJcbn07XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi91dGlsLmpzJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vYXV0b3N0eWxlLmpzJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTW9kaWZpZXJVdGlsIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBsYXN0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBjdXJyZW50XG4gICAqL1xuICBzdGF0aWMgZGlmZihsYXN0LCBjdXJyZW50KSB7XG4gICAgbGFzdCA9IG1ha2VEaWN0KCgnJyArIGxhc3QpLnRyaW0oKSk7XG4gICAgY3VycmVudCA9IG1ha2VEaWN0KCgnJyArIGN1cnJlbnQpLnRyaW0oKSk7XG5cbiAgICBjb25zdCByZW1vdmVkID0gT2JqZWN0LmtleXMobGFzdCkucmVkdWNlKChyZXN1bHQsIHRva2VuKSA9PiB7XG4gICAgICBpZiAoIWN1cnJlbnRbdG9rZW5dKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKHRva2VuKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSwgW10pO1xuXG4gICAgY29uc3QgYWRkZWQgPSBPYmplY3Qua2V5cyhjdXJyZW50KS5yZWR1Y2UoKHJlc3VsdCwgdG9rZW4pID0+IHtcbiAgICAgIGlmICghbGFzdFt0b2tlbl0pIHtcbiAgICAgICAgcmVzdWx0LnB1c2godG9rZW4pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LCBbXSk7XG5cbiAgICByZXR1cm4ge2FkZGVkLCByZW1vdmVkfTtcblxuICAgIGZ1bmN0aW9uIG1ha2VEaWN0KG1vZGlmaWVyKSB7XG4gICAgICBjb25zdCBkaWN0ID0ge307XG4gICAgICBNb2RpZmllclV0aWwuc3BsaXQobW9kaWZpZXIpLmZvckVhY2godG9rZW4gPT4gZGljdFt0b2tlbl0gPSB0b2tlbik7XG4gICAgICByZXR1cm4gZGljdDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpZmZcbiAgICogQHBhcmFtIHtBcnJheX0gZGlmZi5yZW1vdmVkXG4gICAqIEBwYXJhbSB7QXJyYXl9IGRpZmYuYWRkZWRcbiAgICogQHBhcmFtIHtPYmplY3R9IGNsYXNzTGlzdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gdGVtcGxhdGVcbiAgICovXG4gIHN0YXRpYyBhcHBseURpZmZUb0NsYXNzTGlzdChkaWZmLCBjbGFzc0xpc3QsIHRlbXBsYXRlKSB7XG4gICAgZGlmZi5hZGRlZFxuICAgICAgLm1hcChtb2RpZmllciA9PiB0ZW1wbGF0ZS5yZXBsYWNlKC9cXCovZywgbW9kaWZpZXIpKVxuICAgICAgLmZvckVhY2goa2xhc3MgPT4ga2xhc3Muc3BsaXQoL1xccysvKS5mb3JFYWNoKGsgPT4gY2xhc3NMaXN0LmFkZChrKSkpO1xuXG4gICAgZGlmZi5yZW1vdmVkXG4gICAgICAubWFwKG1vZGlmaWVyID0+IHRlbXBsYXRlLnJlcGxhY2UoL1xcKi9nLCBtb2RpZmllcikpXG4gICAgICAuZm9yRWFjaChrbGFzcyA9PiBrbGFzcy5zcGxpdCgvXFxzKy8pLmZvckVhY2goayA9PiBjbGFzc0xpc3QucmVtb3ZlKGspKSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpZmZcbiAgICogQHBhcmFtIHtBcnJheX0gZGlmZi5yZW1vdmVkXG4gICAqIEBwYXJhbSB7QXJyYXl9IGRpZmYuYWRkZWRcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge09iamVjdH0gc2NoZW1lXG4gICAqL1xuICBzdGF0aWMgYXBwbHlEaWZmVG9FbGVtZW50KGRpZmYsIGVsZW1lbnQsIHNjaGVtZSkge1xuICAgIE9iamVjdC5rZXlzKHNjaGVtZSkuZm9yRWFjaChzZWxlY3RvciA9PiB7XG4gICAgICBjb25zdCB0YXJnZXRFbGVtZW50cyA9ICFzZWxlY3RvciB8fCB1dGlsLm1hdGNoKGVsZW1lbnQsIHNlbGVjdG9yKVxuICAgICAgICA/IFtlbGVtZW50XVxuICAgICAgICA6IEFycmF5LnByb3RvdHlwZS5maWx0ZXIuY2FsbChcbiAgICAgICAgICAgIGVsZW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvciksXG4gICAgICAgICAgICB0YXJnZXRFbGVtZW50ID0+ICF1dGlsLmZpbmRQYXJlbnQodGFyZ2V0RWxlbWVudCwgZWxlbWVudC50YWdOYW1lLCBwYXJlbnQgPT4gcGFyZW50ID09PSBlbGVtZW50KVxuICAgICAgICAgICk7XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGFyZ2V0RWxlbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgTW9kaWZpZXJVdGlsLmFwcGx5RGlmZlRvQ2xhc3NMaXN0KGRpZmYsIHRhcmdldEVsZW1lbnRzW2ldLmNsYXNzTGlzdCwgc2NoZW1lW3NlbGVjdG9yXSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtTdHJpbmd9IGxhc3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IGN1cnJlbnRcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge09iamVjdH0gc2NoZW1lXG4gICAqL1xuICBzdGF0aWMgb25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgZWxlbWVudCwgc2NoZW1lKSB7XG4gICAgTW9kaWZpZXJVdGlsLmFwcGx5RGlmZlRvRWxlbWVudChNb2RpZmllclV0aWwuZGlmZihsYXN0LCBjdXJyZW50KSwgZWxlbWVudCwgc2NoZW1lKTtcbiAgICBhdXRvU3R5bGUucmVzdG9yZU1vZGlmaWVyKGVsZW1lbnQpO1xuICB9XG5cbiAgc3RhdGljIHJlZnJlc2goZWxlbWVudCwgc2NoZW1lKSB7XG4gICAgTW9kaWZpZXJVdGlsLmFwcGx5RGlmZlRvRWxlbWVudChNb2RpZmllclV0aWwuZGlmZignJywgZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJykgfHwgJycpLCBlbGVtZW50LCBzY2hlbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAgICogQHBhcmFtIHtPYmplY3R9IHNjaGVtZVxuICAgKi9cbiAgc3RhdGljIGluaXRNb2RpZmllcihlbGVtZW50LCBzY2hlbWUpIHtcbiAgICBjb25zdCBtb2RpZmllciA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpO1xuICAgIGlmICh0eXBlb2YgbW9kaWZpZXIgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgTW9kaWZpZXJVdGlsLmFwcGx5RGlmZlRvRWxlbWVudCh7XG4gICAgICByZW1vdmVkOiBbXSxcbiAgICAgIGFkZGVkOiBNb2RpZmllclV0aWwuc3BsaXQobW9kaWZpZXIpXG4gICAgfSwgZWxlbWVudCwgc2NoZW1lKTtcbiAgfVxuXG4gIHN0YXRpYyBzcGxpdChtb2RpZmllcikge1xuICAgIGlmICh0eXBlb2YgbW9kaWZpZXIgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGlmaWVyLnRyaW0oKS5zcGxpdCgvICsvKS5maWx0ZXIodG9rZW4gPT4gdG9rZW4gIT09ICcnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgbW9kaWZpZXIgdG9rZW4gdG8gYW4gZWxlbWVudC5cbiAgICovXG4gIHN0YXRpYyBhZGRNb2RpZmllcihlbGVtZW50LCBtb2RpZmllclRva2VuKSB7XG4gICAgaWYgKCFlbGVtZW50Lmhhc0F0dHJpYnV0ZSgnbW9kaWZpZXInKSkge1xuICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJywgbW9kaWZpZXJUb2tlbik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHRva2VucyA9IE1vZGlmaWVyVXRpbC5zcGxpdChlbGVtZW50LmdldEF0dHJpYnV0ZSgnbW9kaWZpZXInKSk7XG4gICAgICBpZiAodG9rZW5zLmluZGV4T2YobW9kaWZpZXJUb2tlbikgPT0gLTEpIHtcbiAgICAgICAgdG9rZW5zLnB1c2gobW9kaWZpZXJUb2tlbik7XG4gICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCdtb2RpZmllcicsIHRva2Vucy5qb2luKCcgJykpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgbW9kaWZpZXIgdG9rZW4gZnJvbSBhbiBlbGVtZW50LlxuICAgKi9cbiAgc3RhdGljIHJlbW92ZU1vZGlmaWVyKGVsZW1lbnQsIG1vZGlmaWVyVG9rZW4pIHtcbiAgICBpZiAoZWxlbWVudC5oYXNBdHRyaWJ1dGUoJ21vZGlmaWVyJykpIHtcbiAgICAgIGNvbnN0IHRva2VucyA9IE1vZGlmaWVyVXRpbC5zcGxpdChlbGVtZW50LmdldEF0dHJpYnV0ZSgnbW9kaWZpZXInKSk7XG4gICAgICBjb25zdCBpbmRleCA9IHRva2Vucy5pbmRleE9mKG1vZGlmaWVyVG9rZW4pO1xuICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICB0b2tlbnMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJywgdG9rZW5zLmpvaW4oJyAnKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vcGxhdGZvcm0nO1xuXG5jb25zdCB1dGlsID0ge1xuICBfcmVhZHk6IGZhbHNlLFxuXG4gIF9kb21Db250ZW50TG9hZGVkOiBmYWxzZSxcblxuICBfb25ET01Db250ZW50TG9hZGVkOiAoKSA9PiB7XG4gICAgdXRpbC5fZG9tQ29udGVudExvYWRlZCA9IHRydWU7XG5cbiAgICBpZiAocGxhdGZvcm0uaXNXZWJWaWV3KCkpIHtcbiAgICAgIHdpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdkZXZpY2VyZWFkeScsICgpID0+IHtcbiAgICAgICAgdXRpbC5fcmVhZHkgPSB0cnVlO1xuICAgICAgfSwgZmFsc2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICB1dGlsLl9yZWFkeSA9IHRydWU7XG4gICAgfVxuICB9LFxuXG4gIGFkZEJhY2tCdXR0b25MaXN0ZW5lcjogZnVuY3Rpb24oZm4pIHtcbiAgICBpZiAoIXRoaXMuX2RvbUNvbnRlbnRMb2FkZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhpcyBtZXRob2QgaXMgYXZhaWxhYmxlIGFmdGVyIERPTUNvbnRlbnRMb2FkZWQnKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fcmVhZHkpIHtcbiAgICAgIHdpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdiYWNrYnV0dG9uJywgZm4sIGZhbHNlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2luZG93LmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RldmljZXJlYWR5JywgZnVuY3Rpb24oKSB7XG4gICAgICAgIHdpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdiYWNrYnV0dG9uJywgZm4sIGZhbHNlKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSxcblxuICByZW1vdmVCYWNrQnV0dG9uTGlzdGVuZXI6IGZ1bmN0aW9uKGZuKSB7XG4gICAgaWYgKCF0aGlzLl9kb21Db250ZW50TG9hZGVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoaXMgbWV0aG9kIGlzIGF2YWlsYWJsZSBhZnRlciBET01Db250ZW50TG9hZGVkJyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX3JlYWR5KSB7XG4gICAgICB3aW5kb3cuZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignYmFja2J1dHRvbicsIGZuLCBmYWxzZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdkZXZpY2VyZWFkeScsIGZ1bmN0aW9uKCkge1xuICAgICAgICB3aW5kb3cuZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignYmFja2J1dHRvbicsIGZuLCBmYWxzZSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cbn07XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsICgpID0+IHV0aWwuX29uRE9NQ29udGVudExvYWRlZCgpLCBmYWxzZSk7XG5cbmNvbnN0IEhhbmRsZXJSZXBvc2l0b3J5ID0ge1xuICBfc3RvcmU6IHt9LFxuXG4gIF9nZW5JZDogKCgpID0+IHtcbiAgICBsZXQgaSA9IDA7XG4gICAgcmV0dXJuICgpID0+IGkrKztcbiAgfSkoKSxcblxuICBzZXQ6IGZ1bmN0aW9uKGVsZW1lbnQsIGhhbmRsZXIpIHtcbiAgICBpZiAoZWxlbWVudC5kYXRhc2V0LmRldmljZUJhY2tCdXR0b25IYW5kbGVySWQpIHtcbiAgICAgIHRoaXMucmVtb3ZlKGVsZW1lbnQpO1xuICAgIH1cbiAgICBjb25zdCBpZCA9IGVsZW1lbnQuZGF0YXNldC5kZXZpY2VCYWNrQnV0dG9uSGFuZGxlcklkID0gSGFuZGxlclJlcG9zaXRvcnkuX2dlbklkKCk7XG4gICAgdGhpcy5fc3RvcmVbaWRdID0gaGFuZGxlcjtcbiAgfSxcblxuICByZW1vdmU6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICBpZiAoZWxlbWVudC5kYXRhc2V0LmRldmljZUJhY2tCdXR0b25IYW5kbGVySWQpIHtcbiAgICAgIGRlbGV0ZSB0aGlzLl9zdG9yZVtlbGVtZW50LmRhdGFzZXQuZGV2aWNlQmFja0J1dHRvbkhhbmRsZXJJZF07XG4gICAgICBkZWxldGUgZWxlbWVudC5kYXRhc2V0LmRldmljZUJhY2tCdXR0b25IYW5kbGVySWQ7XG4gICAgfVxuICB9LFxuXG4gIGdldDogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgIGlmICghZWxlbWVudC5kYXRhc2V0LmRldmljZUJhY2tCdXR0b25IYW5kbGVySWQpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgaWQgPSBlbGVtZW50LmRhdGFzZXQuZGV2aWNlQmFja0J1dHRvbkhhbmRsZXJJZDtcblxuICAgIGlmICghdGhpcy5fc3RvcmVbaWRdKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fc3RvcmVbaWRdO1xuICB9LFxuXG4gIGhhczogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgIGlmICghZWxlbWVudC5kYXRhc2V0KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaWQgPSBlbGVtZW50LmRhdGFzZXQuZGV2aWNlQmFja0J1dHRvbkhhbmRsZXJJZDtcblxuICAgIHJldHVybiAhIXRoaXMuX3N0b3JlW2lkXTtcbiAgfVxufTtcblxuY2xhc3MgRGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLl9pc0VuYWJsZWQgPSBmYWxzZTtcbiAgICB0aGlzLl9ib3VuZENhbGxiYWNrID0gdGhpcy5fY2FsbGJhY2suYmluZCh0aGlzKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIEVuYWJsZSB0byBoYW5kbGUgJ2JhY2tidXR0b24nIGV2ZW50cy5cbiAgICovXG4gIGVuYWJsZSgpIHtcbiAgICBpZiAoIXRoaXMuX2lzRW5hYmxlZCkge1xuICAgICAgdXRpbC5hZGRCYWNrQnV0dG9uTGlzdGVuZXIodGhpcy5fYm91bmRDYWxsYmFjayk7XG4gICAgICB0aGlzLl9pc0VuYWJsZWQgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNhYmxlIHRvIGhhbmRsZSAnYmFja2J1dHRvbicgZXZlbnRzLlxuICAgKi9cbiAgZGlzYWJsZSgpIHtcbiAgICBpZiAodGhpcy5faXNFbmFibGVkKSB7XG4gICAgICB1dGlsLnJlbW92ZUJhY2tCdXR0b25MaXN0ZW5lcih0aGlzLl9ib3VuZENhbGxiYWNrKTtcbiAgICAgIHRoaXMuX2lzRW5hYmxlZCA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGaXJlIGEgJ2JhY2tidXR0b24nIGV2ZW50IG1hbnVhbGx5LlxuICAgKi9cbiAgZmlyZURldmljZUJhY2tCdXR0b25FdmVudCgpIHtcbiAgICBjb25zdCBldmVudCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdFdmVudCcpO1xuICAgIGV2ZW50LmluaXRFdmVudCgnYmFja2J1dHRvbicsIHRydWUsIHRydWUpO1xuICAgIGRvY3VtZW50LmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICB9XG5cbiAgX2NhbGxiYWNrKCkge1xuICAgIHRoaXMuX2Rpc3BhdGNoRGV2aWNlQmFja0J1dHRvbkV2ZW50KCk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgY3JlYXRlSGFuZGxlcihlbGVtZW50LCBjYWxsYmFjaykge1xuICAgIGlmICghKGVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZWxlbWVudCBtdXN0IGJlIGFuIGluc3RhbmNlIG9mIEhUTUxFbGVtZW50Jyk7XG4gICAgfVxuXG4gICAgaWYgKCEoY2FsbGJhY2sgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY2FsbGJhY2sgbXVzdCBiZSBhbiBpbnN0YW5jZSBvZiBGdW5jdGlvbicpO1xuICAgIH1cblxuICAgIGNvbnN0IGhhbmRsZXIgPSB7XG4gICAgICBfY2FsbGJhY2s6IGNhbGxiYWNrLFxuICAgICAgX2VsZW1lbnQ6IGVsZW1lbnQsXG5cbiAgICAgIGRpc2FibGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICBIYW5kbGVyUmVwb3NpdG9yeS5yZW1vdmUoZWxlbWVudCk7XG4gICAgICB9LFxuXG4gICAgICBzZXRMaXN0ZW5lcjogZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5fY2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICAgIH0sXG5cbiAgICAgIGVuYWJsZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIEhhbmRsZXJSZXBvc2l0b3J5LnNldChlbGVtZW50LCB0aGlzKTtcbiAgICAgIH0sXG5cbiAgICAgIGlzRW5hYmxlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBIYW5kbGVyUmVwb3NpdG9yeS5nZXQoZWxlbWVudCkgPT09IHRoaXM7XG4gICAgICB9LFxuXG4gICAgICBkZXN0cm95OiBmdW5jdGlvbigpIHtcbiAgICAgICAgSGFuZGxlclJlcG9zaXRvcnkucmVtb3ZlKGVsZW1lbnQpO1xuICAgICAgICB0aGlzLl9jYWxsYmFjayA9IHRoaXMuX2VsZW1lbnQgPSBudWxsO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBoYW5kbGVyLmVuYWJsZSgpO1xuXG4gICAgcmV0dXJuIGhhbmRsZXI7XG4gIH1cblxuICBfZGlzcGF0Y2hEZXZpY2VCYWNrQnV0dG9uRXZlbnQoKSB7XG4gICAgY29uc3QgdHJlZSA9IHRoaXMuX2NhcHR1cmVUcmVlKCk7XG5cbiAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5fZmluZEhhbmRsZXJMZWFmRWxlbWVudCh0cmVlKTtcblxuICAgIGxldCBoYW5kbGVyID0gSGFuZGxlclJlcG9zaXRvcnkuZ2V0KGVsZW1lbnQpO1xuICAgIGhhbmRsZXIuX2NhbGxiYWNrKGNyZWF0ZUV2ZW50KGVsZW1lbnQpKTtcblxuICAgIGZ1bmN0aW9uIGNyZWF0ZUV2ZW50KGVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIF9lbGVtZW50OiBlbGVtZW50LFxuICAgICAgICBjYWxsUGFyZW50SGFuZGxlcjogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgbGV0IHBhcmVudCA9IHRoaXMuX2VsZW1lbnQucGFyZW50Tm9kZTtcblxuICAgICAgICAgIHdoaWxlIChwYXJlbnQpIHtcbiAgICAgICAgICAgIGhhbmRsZXIgPSBIYW5kbGVyUmVwb3NpdG9yeS5nZXQocGFyZW50KTtcbiAgICAgICAgICAgIGlmIChoYW5kbGVyKSB7XG4gICAgICAgICAgICAgIHJldHVybiBoYW5kbGVyLl9jYWxsYmFjayhjcmVhdGVFdmVudChwYXJlbnQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBhcmVudCA9IHBhcmVudC5wYXJlbnROb2RlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7T2JqZWN0fVxuICAgKi9cbiAgX2NhcHR1cmVUcmVlKCkge1xuICAgIHJldHVybiBjcmVhdGVUcmVlKGRvY3VtZW50LmJvZHkpO1xuXG4gICAgZnVuY3Rpb24gY3JlYXRlVHJlZShlbGVtZW50KSB7XG4gICAgICBjb25zdCB0cmVlID0ge1xuICAgICAgICBlbGVtZW50OiBlbGVtZW50LFxuICAgICAgICBjaGlsZHJlbjogQXJyYXkucHJvdG90eXBlLmNvbmNhdC5hcHBseShbXSwgYXJyYXlPZihlbGVtZW50LmNoaWxkcmVuKS5tYXAoZnVuY3Rpb24oY2hpbGRFbGVtZW50KSB7XG5cbiAgICAgICAgICBpZiAoY2hpbGRFbGVtZW50LnN0eWxlLmRpc3BsYXkgPT09ICdub25lJyB8fCBjaGlsZEVsZW1lbnQuX2lzU2hvd24gPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGNoaWxkRWxlbWVudC5jaGlsZHJlbi5sZW5ndGggPT09IDAgJiYgIUhhbmRsZXJSZXBvc2l0b3J5LmhhcyhjaGlsZEVsZW1lbnQpKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gY3JlYXRlVHJlZShjaGlsZEVsZW1lbnQpO1xuXG4gICAgICAgICAgaWYgKHJlc3VsdC5jaGlsZHJlbi5sZW5ndGggPT09IDAgJiYgIUhhbmRsZXJSZXBvc2l0b3J5LmhhcyhyZXN1bHQuZWxlbWVudCkpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gW3Jlc3VsdF07XG4gICAgICAgIH0pKVxuICAgICAgfTtcblxuICAgICAgaWYgKCFIYW5kbGVyUmVwb3NpdG9yeS5oYXModHJlZS5lbGVtZW50KSkge1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspe1xuICAgICAgICAgIGNvbnN0IHN1YlRyZWUgPSB0cmVlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgIGlmIChIYW5kbGVyUmVwb3NpdG9yeS5oYXMoc3ViVHJlZS5lbGVtZW50KSkge1xuICAgICAgICAgICAgcmV0dXJuIHN1YlRyZWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0cmVlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFycmF5T2YodGFyZ2V0KSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGFyZ2V0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKHRhcmdldFtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gdHJlZVxuICAgKiBAcmV0dXJuIHtIVE1MRWxlbWVudH1cbiAgICovXG4gIF9maW5kSGFuZGxlckxlYWZFbGVtZW50KHRyZWUpIHtcbiAgICByZXR1cm4gZmluZCh0cmVlKTtcblxuICAgIGZ1bmN0aW9uIGZpbmQobm9kZSkge1xuICAgICAgaWYgKG5vZGUuY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiBub2RlLmVsZW1lbnQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChub2RlLmNoaWxkcmVuLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICByZXR1cm4gZmluZChub2RlLmNoaWxkcmVuWzBdKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5vZGUuY2hpbGRyZW4ubWFwKGZ1bmN0aW9uKGNoaWxkTm9kZSkge1xuICAgICAgICByZXR1cm4gY2hpbGROb2RlLmVsZW1lbnQ7XG4gICAgICB9KS5yZWR1Y2UoZnVuY3Rpb24obGVmdCwgcmlnaHQpIHtcbiAgICAgICAgaWYgKCFsZWZ0KSB7XG4gICAgICAgICAgcmV0dXJuIHJpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbGVmdFogPSBwYXJzZUludCh3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShsZWZ0LCAnJykuekluZGV4LCAxMCk7XG4gICAgICAgIGNvbnN0IHJpZ2h0WiA9IHBhcnNlSW50KHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHJpZ2h0LCAnJykuekluZGV4LCAxMCk7XG5cbiAgICAgICAgaWYgKCFpc05hTihsZWZ0WikgJiYgIWlzTmFOKHJpZ2h0WikpIHtcbiAgICAgICAgICByZXR1cm4gbGVmdFogPiByaWdodFogPyBsZWZ0IDogcmlnaHQ7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhcHR1cmluZyBiYWNrYnV0dG9uLWhhbmRsZXIgaXMgZmFpbHVyZS4nKTtcbiAgICAgIH0sIG51bGwpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBuZXcgRGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIoKTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5pbXBvcnQgaW50ZXJuYWwgZnJvbSAnLi9pbnRlcm5hbCc7XG5pbXBvcnQgQW5pbWF0b3JGYWN0b3J5IGZyb20gJy4vYW5pbWF0b3ItZmFjdG9yeSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4vbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIgZnJvbSAnLi9kZXZpY2UtYmFjay1idXR0b24tZGlzcGF0Y2hlcic7XG5cbmludGVybmFsLkFuaW1hdG9yRmFjdG9yeSA9IEFuaW1hdG9yRmFjdG9yeTtcbmludGVybmFsLk1vZGlmaWVyVXRpbCA9IE1vZGlmaWVyVXRpbDtcbmludGVybmFsLmRiYkRpc3BhdGNoZXIgPSBkZXZpY2VCYWNrQnV0dG9uRGlzcGF0Y2hlcjtcblxuZXhwb3J0IGRlZmF1bHQgaW50ZXJuYWw7XG5cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuY29uc3Qgc3RhcnRzV2l0aCA9IChzLCBjKSA9PiBzLnN1YnN0cigwLCBjLmxlbmd0aCkgPT09IGM7XG5jb25zdCBlbmRzV2l0aCA9IChzLCBjKSA9PiBzLnN1YnN0cihzLmxlbmd0aCAtIGMubGVuZ3RoLCBjLmxlbmd0aCkgPT09IGM7XG5jb25zdCB1bndyYXAgPSBzID0+IHMuc2xpY2UoMSwgLTEpO1xuY29uc3QgaXNPYmplY3RTdHJpbmcgPSBzID0+IHN0YXJ0c1dpdGgocywgJ3snKSAmJiBlbmRzV2l0aChzLCAnfScpO1xuY29uc3QgaXNBcnJheVN0cmluZyA9IHMgPT4gc3RhcnRzV2l0aChzLCAnWycpICYmIGVuZHNXaXRoKHMsICddJyk7XG5jb25zdCBpc1F1b3RlZFN0cmluZyA9IHMgPT4gKHN0YXJ0c1dpdGgocywgJ1xcJycpICYmIGVuZHNXaXRoKHMsICdcXCcnKSkgfHwgKHN0YXJ0c1dpdGgocywgJ1wiJykgJiYgZW5kc1dpdGgocywgJ1wiJykpO1xuXG5jb25zdCBlcnJvciA9ICh0b2tlbiwgc3RyaW5nLCBvcmlnaW5hbFN0cmluZykgPT4ge1xuICB0aHJvdyBuZXcgRXJyb3IoJ1VuZXhwZWN0ZWQgdG9rZW4gXFwnJyArIHRva2VuICsgJ1xcJyBhdCBwb3NpdGlvbiAnICsgKG9yaWdpbmFsU3RyaW5nLmxlbmd0aCAtIHN0cmluZy5sZW5ndGggLSAxKSArICcgaW4gc3RyaW5nOiBcXCcnICsgb3JpZ2luYWxTdHJpbmcgKyAnXFwnJyk7XG59O1xuXG5jb25zdCBwcm9jZXNzVG9rZW4gPSAodG9rZW4sIHN0cmluZywgb3JpZ2luYWxTdHJpbmcpID0+IHtcbiAgaWYgKHRva2VuID09PSAndHJ1ZScgfHwgdG9rZW4gPT09ICdmYWxzZScpIHtcbiAgICByZXR1cm4gdG9rZW4gPT09ICd0cnVlJztcbiAgfSBlbHNlIGlmIChpc1F1b3RlZFN0cmluZyh0b2tlbikpIHtcbiAgICByZXR1cm4gdW53cmFwKHRva2VuKTtcbiAgfSBlbHNlIGlmICghaXNOYU4odG9rZW4pKSB7XG4gICAgcmV0dXJuICsodG9rZW4pO1xuICB9IGVsc2UgaWYgKGlzT2JqZWN0U3RyaW5nKHRva2VuKSkge1xuICAgIHJldHVybiBwYXJzZU9iamVjdCh1bndyYXAodG9rZW4pKTtcbiAgfSBlbHNlIGlmIChpc0FycmF5U3RyaW5nKHRva2VuKSkge1xuICAgIHJldHVybiBwYXJzZUFycmF5KHVud3JhcCh0b2tlbikpO1xuICB9IGVsc2Uge1xuICAgIGVycm9yKHRva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKTtcbiAgfVxufTtcblxuY29uc3QgbmV4dFRva2VuID0gKHN0cmluZykgPT4ge1xuICBzdHJpbmcgPSBzdHJpbmcudHJpbSgpO1xuICBsZXQgbGltaXQgPSBzdHJpbmcubGVuZ3RoO1xuXG4gIGlmIChzdHJpbmdbMF0gPT09ICc6JyB8fCBzdHJpbmdbMF0gPT09ICcsJykge1xuXG4gICAgbGltaXQgPSAxO1xuXG4gIH0gZWxzZSBpZiAoc3RyaW5nWzBdID09PSAneycgfHwgc3RyaW5nWzBdID09PSAnWycpIHtcblxuICAgIGNvbnN0IGMgPSBzdHJpbmcuY2hhckNvZGVBdCgwKTtcbiAgICBsZXQgbmVzdGVkT2JqZWN0ID0gMTtcbiAgICBmb3IgKGxldCBpID0gMTsgaSA8IHN0cmluZy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHN0cmluZy5jaGFyQ29kZUF0KGkpID09PSBjKSB7XG4gICAgICAgIG5lc3RlZE9iamVjdCsrO1xuICAgICAgfSBlbHNlIGlmIChzdHJpbmcuY2hhckNvZGVBdChpKSA9PT0gYyArIDIpIHtcbiAgICAgICAgbmVzdGVkT2JqZWN0LS07XG4gICAgICAgIGlmIChuZXN0ZWRPYmplY3QgPT09IDApIHtcbiAgICAgICAgICBsaW1pdCA9IGkgKyAxO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gIH0gZWxzZSBpZiAoc3RyaW5nWzBdID09PSAnXFwnJyB8fCBzdHJpbmdbMF0gPT09ICdcIicpIHtcblxuICAgIGZvciAobGV0IGkgPSAxOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoc3RyaW5nW2ldID09PSBzdHJpbmdbMF0pIHtcbiAgICAgICAgbGltaXQgPSBpICsgMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gIH0gZWxzZSB7XG5cbiAgICBmb3IgKGxldCBpID0gMTsgaSA8IHN0cmluZy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKFsnICcsICcsJywgJzonXS5pbmRleE9mKHN0cmluZ1tpXSkgIT09IC0xKSB7XG4gICAgICAgIGxpbWl0ID0gaTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gIH1cblxuICByZXR1cm4gc3RyaW5nLnNsaWNlKDAsIGxpbWl0KTtcbn07XG5cbmNvbnN0IHBhcnNlT2JqZWN0ID0gKHN0cmluZykgPT4ge1xuICBjb25zdCBpc1ZhbGlkS2V5ID0ga2V5ID0+IC9eW0EtWl8kXVtBLVowLTlfJF0qJC9pLnRlc3Qoa2V5KTtcblxuICBzdHJpbmcgPSBzdHJpbmcudHJpbSgpO1xuICBjb25zdCBvcmlnaW5hbFN0cmluZyA9IHN0cmluZztcbiAgY29uc3Qgb2JqZWN0ID0ge307XG4gIGxldCByZWFkaW5nS2V5ID0gdHJ1ZSwga2V5LCBwcmV2aW91c1Rva2VuLCB0b2tlbjtcblxuICB3aGlsZSAoc3RyaW5nLmxlbmd0aCA+IDApIHtcbiAgICBwcmV2aW91c1Rva2VuID0gdG9rZW47XG4gICAgdG9rZW4gPSBuZXh0VG9rZW4oc3RyaW5nKTtcbiAgICBzdHJpbmcgPSBzdHJpbmcuc2xpY2UodG9rZW4ubGVuZ3RoLCBzdHJpbmcubGVuZ3RoKS50cmltKCk7XG5cbiAgICBpZiAoKHRva2VuID09PSAnOicgJiYgKCFyZWFkaW5nS2V5IHx8ICFwcmV2aW91c1Rva2VuIHx8IHByZXZpb3VzVG9rZW4gPT09ICcsJykpXG4gICAgICAgfHwgKHRva2VuID09PSAnLCcgJiYgcmVhZGluZ0tleSlcbiAgICAgICB8fCAodG9rZW4gIT09ICc6JyAmJiB0b2tlbiAhPT0gJywnICYmIChwcmV2aW91c1Rva2VuICYmIHByZXZpb3VzVG9rZW4gIT09ICcsJyAmJiBwcmV2aW91c1Rva2VuICE9PSAnOicpKSkge1xuICAgICAgZXJyb3IodG9rZW4sIHN0cmluZywgb3JpZ2luYWxTdHJpbmcpO1xuICAgIH0gZWxzZSBpZiAodG9rZW4gPT09ICc6JyAmJiByZWFkaW5nS2V5ICYmIHByZXZpb3VzVG9rZW4pIHtcbiAgICAgIHByZXZpb3VzVG9rZW4gPSBpc1F1b3RlZFN0cmluZyhwcmV2aW91c1Rva2VuKSA/IHVud3JhcChwcmV2aW91c1Rva2VuKSA6IHByZXZpb3VzVG9rZW47XG4gICAgICBpZiAoaXNWYWxpZEtleShwcmV2aW91c1Rva2VuKSkge1xuICAgICAgICBrZXkgPSBwcmV2aW91c1Rva2VuO1xuICAgICAgICByZWFkaW5nS2V5ID0gZmFsc2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQga2V5IHRva2VuIFxcJycgKyBwcmV2aW91c1Rva2VuICsgJ1xcJyBhdCBwb3NpdGlvbiAwIGluIHN0cmluZzogXFwnJyArIG9yaWdpbmFsU3RyaW5nICsgJ1xcJycpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodG9rZW4gPT09ICcsJyAmJiAhcmVhZGluZ0tleSAmJiBwcmV2aW91c1Rva2VuKSB7XG4gICAgICBvYmplY3Rba2V5XSA9IHByb2Nlc3NUb2tlbihwcmV2aW91c1Rva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKTtcbiAgICAgIHJlYWRpbmdLZXkgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIGlmICh0b2tlbikge1xuICAgIG9iamVjdFtrZXldID0gcHJvY2Vzc1Rva2VuKHRva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKTtcbiAgfVxuXG4gIHJldHVybiBvYmplY3Q7XG59O1xuXG5jb25zdCBwYXJzZUFycmF5ID0gKHN0cmluZykgPT4ge1xuICBzdHJpbmcgPSBzdHJpbmcudHJpbSgpO1xuICBjb25zdCBvcmlnaW5hbFN0cmluZyA9IHN0cmluZztcbiAgY29uc3QgYXJyYXkgPSBbXTtcbiAgbGV0IHByZXZpb3VzVG9rZW4sIHRva2VuO1xuXG4gIHdoaWxlIChzdHJpbmcubGVuZ3RoID4gMCkge1xuICAgIHByZXZpb3VzVG9rZW4gPSB0b2tlbjtcbiAgICB0b2tlbiA9IG5leHRUb2tlbihzdHJpbmcpO1xuICAgIHN0cmluZyA9IHN0cmluZy5zbGljZSh0b2tlbi5sZW5ndGgsIHN0cmluZy5sZW5ndGgpLnRyaW0oKTtcblxuICAgIGlmICh0b2tlbiA9PT0gJywnICYmICghcHJldmlvdXNUb2tlbiB8fCBwcmV2aW91c1Rva2VuID09PSAnLCcpKSB7XG4gICAgICBlcnJvcih0b2tlbiwgc3RyaW5nLCBvcmlnaW5hbFN0cmluZyk7XG4gICAgfSBlbHNlIGlmICh0b2tlbiA9PT0gJywnKSB7XG4gICAgICBhcnJheS5wdXNoKHByb2Nlc3NUb2tlbihwcmV2aW91c1Rva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHRva2VuKSB7XG4gICAgaWYgKHRva2VuICE9PSAnLCcpIHtcbiAgICAgIGFycmF5LnB1c2gocHJvY2Vzc1Rva2VuKHRva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVycm9yKHRva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYXJyYXk7XG59O1xuXG5jb25zdCBwYXJzZSA9IChzdHJpbmcpID0+IHtcbiAgc3RyaW5nID0gc3RyaW5nLnRyaW0oKTtcblxuICBpZiAoaXNPYmplY3RTdHJpbmcoc3RyaW5nKSkge1xuICAgIHJldHVybiBwYXJzZU9iamVjdCh1bndyYXAoc3RyaW5nKSk7XG4gIH0gZWxzZSBpZiAoaXNBcnJheVN0cmluZyhzdHJpbmcpKSB7XG4gICAgcmV0dXJuIHBhcnNlQXJyYXkodW53cmFwKHN0cmluZykpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcignUHJvdmlkZWQgc3RyaW5nIG11c3QgYmUgb2JqZWN0IG9yIGFycmF5IGxpa2U6ICcgKyBzdHJpbmcpO1xuICB9XG59O1xuXG5leHBvcnQgZGVmYXVsdCBwYXJzZTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuL2VsZW1lbnRzJztcbmltcG9ydCBzdHlsZXIgZnJvbSAnLi9zdHlsZXInO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4vaW50ZXJuYWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4vaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgYW5pbWF0aW9uT3B0aW9uc1BhcnNlIGZyb20gJy4vYW5pbWF0aW9uLW9wdGlvbnMtcGFyc2VyJztcbmltcG9ydCBwbGF0Zm9ybSBmcm9tICcuL3BsYXRmb3JtJztcblxuY29uc3QgdXRpbCA9IHt9O1xuY29uc3QgZXJyb3JQcmVmaXggPSAnW09uc2VuIFVJXSc7XG5cbnV0aWwuZ2xvYmFscyA9IHtcbiAgZmFiT2Zmc2V0OiAwLFxuICBlcnJvclByZWZpeCxcbiAgc3VwcG9ydHNQYXNzaXZlOiBmYWxzZVxufTtcblxucGxhdGZvcm0uX3J1bk9uQWN0dWFsUGxhdGZvcm0oKCkgPT4ge1xuICB1dGlsLmdsb2JhbHMuYWN0dWFsTW9iaWxlT1MgPSBwbGF0Zm9ybS5nZXRNb2JpbGVPUygpO1xuICB1dGlsLmdsb2JhbHMuaXNVSVdlYlZpZXcgPSBwbGF0Zm9ybS5pc1VJV2ViVmlldygpO1xuICB1dGlsLmdsb2JhbHMuaXNXS1dlYlZpZXcgPSBwbGF0Zm9ybS5pc1dLV2ViVmlldygpO1xufSk7XG5cbnRyeSB7XG4gIGNvbnN0IG9wdHMgPSBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sICdwYXNzaXZlJywge1xuICAgIGdldCgpIHsgdXRpbC5nbG9iYWxzLnN1cHBvcnRzUGFzc2l2ZSA9IHRydWU7IH1cbiAgfSk7XG4gIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCd0ZXN0UGFzc2l2ZScsIG51bGwsIG9wdHMpO1xuICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigndGVzdFBhc3NpdmUnLCBudWxsLCBvcHRzKTtcbn0gY2F0Y2ggKGUpIHsgbnVsbDsgfVxuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudH0gZWwgVGFyZ2V0XG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBFdmVudCBuYW1lXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBoYW5kbGVyIEV2ZW50IGhhbmRsZXJcbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0XSBFdmVudCBvcHRpb25zIChwYXNzaXZlLCBjYXB0dXJlLi4uKVxuICogQHBhcmFtIHtCb29sZWFufSBbaXNHRF0gSWYgY29tZXMgZnJvbSBHZXN0dXJlRGV0ZWN0b3IuIEp1c3QgZm9yIHRlc3RpbmcuXG4gKi9cbnV0aWwuYWRkRXZlbnRMaXN0ZW5lciA9IChlbCwgbmFtZSwgaGFuZGxlciwgb3B0LCBpc0dEKSA9PiB7XG4gIGVsLmFkZEV2ZW50TGlzdGVuZXIobmFtZSwgaGFuZGxlciwgdXRpbC5nbG9iYWxzLnN1cHBvcnRzUGFzc2l2ZSA/IG9wdCA6IChvcHQgfHwge30pLmNhcHR1cmUpO1xufTtcbnV0aWwucmVtb3ZlRXZlbnRMaXN0ZW5lciA9IChlbCwgbmFtZSwgaGFuZGxlciwgb3B0LCBpc0dEKSA9PiB7XG4gIGVsLnJlbW92ZUV2ZW50TGlzdGVuZXIobmFtZSwgaGFuZGxlciwgdXRpbC5nbG9iYWxzLnN1cHBvcnRzUGFzc2l2ZSA/IG9wdCA6IChvcHQgfHwge30pLmNhcHR1cmUpO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge1N0cmluZy9GdW5jdGlvbn0gcXVlcnkgZG90IGNsYXNzIG5hbWUgb3Igbm9kZSBuYW1lIG9yIG1hdGNoZXIgZnVuY3Rpb24uXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn1cbiAqL1xudXRpbC5wcmVwYXJlUXVlcnkgPSAocXVlcnkpID0+IHtcbiAgcmV0dXJuIHF1ZXJ5IGluc3RhbmNlb2YgRnVuY3Rpb24gPyBxdWVyeSA6IChlbGVtZW50KSA9PiB1dGlsLm1hdGNoKGVsZW1lbnQsIHF1ZXJ5KTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSBlXG4gKiBAcGFyYW0ge1N0cmluZy9GdW5jdGlvbn0gcyBDU1MgU2VsZWN0b3IuXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICovXG51dGlsLm1hdGNoID0gKGUsIHMpID0+IChlLm1hdGNoZXMgfHwgZS53ZWJraXRNYXRjaGVzU2VsZWN0b3IgfHwgZS5tb3pNYXRjaGVzU2VsZWN0b3IgfHwgZS5tc01hdGNoZXNTZWxlY3RvcikuY2FsbChlLCBzKTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7U3RyaW5nL0Z1bmN0aW9ufSBxdWVyeSBkb3QgY2xhc3MgbmFtZSBvciBub2RlIG5hbWUgb3IgbWF0Y2hlciBmdW5jdGlvbi5cbiAqIEByZXR1cm4ge0hUTUxFbGVtZW50L251bGx9XG4gKi9cbnV0aWwuZmluZENoaWxkID0gKGVsZW1lbnQsIHF1ZXJ5KSA9PiB7XG4gIGNvbnN0IG1hdGNoID0gdXRpbC5wcmVwYXJlUXVlcnkocXVlcnkpO1xuXG4gIC8vIENhdXRpb246IGBlbGVtZW50LmNoaWxkcmVuYCBpcyBgdW5kZWZpbmVkYCBpbiBzb21lIGVudmlyb25tZW50cyBpZiBgZWxlbWVudGAgaXMgYHN2Z2BcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBlbGVtZW50LmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBub2RlID0gZWxlbWVudC5jaGlsZE5vZGVzW2ldO1xuICAgIGlmIChub2RlLm5vZGVUeXBlICE9PSBOb2RlLkVMRU1FTlRfTk9ERSkgeyAvLyBwcm9jZXNzIG9ubHkgZWxlbWVudCBub2Rlc1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmIChtYXRjaChub2RlKSkge1xuICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7U3RyaW5nL0Z1bmN0aW9ufSBxdWVyeSBkb3QgY2xhc3MgbmFtZSBvciBub2RlIG5hbWUgb3IgbWF0Y2hlciBmdW5jdGlvbi5cbiAqIEByZXR1cm4ge0hUTUxFbGVtZW50L251bGx9XG4gKi9cbnV0aWwuZmluZFBhcmVudCA9IChlbGVtZW50LCBxdWVyeSwgdW50aWwpID0+IHtcbiAgY29uc3QgbWF0Y2ggPSB1dGlsLnByZXBhcmVRdWVyeShxdWVyeSk7XG5cbiAgbGV0IHBhcmVudCA9IGVsZW1lbnQucGFyZW50Tm9kZTtcbiAgZm9yICg7Oykge1xuICAgIGlmICghcGFyZW50IHx8IHBhcmVudCA9PT0gZG9jdW1lbnQgfHwgcGFyZW50IGluc3RhbmNlb2YgRG9jdW1lbnRGcmFnbWVudCB8fCAodW50aWwgJiYgdW50aWwocGFyZW50KSkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0gZWxzZSBpZiAobWF0Y2gocGFyZW50KSkge1xuICAgICAgcmV0dXJuIHBhcmVudDtcbiAgICB9XG4gICAgcGFyZW50ID0gcGFyZW50LnBhcmVudE5vZGU7XG4gIH1cbn07XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG51dGlsLmlzQXR0YWNoZWQgPSBlbGVtZW50ID0+IGRvY3VtZW50LmJvZHkuY29udGFpbnMoZWxlbWVudCk7XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG51dGlsLmhhc0FueUNvbXBvbmVudEFzUGFyZW50ID0gKGVsZW1lbnQpID0+IHtcbiAgd2hpbGUgKGVsZW1lbnQgJiYgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50ICE9PSBlbGVtZW50KSB7XG4gICAgZWxlbWVudCA9IGVsZW1lbnQucGFyZW50Tm9kZTtcbiAgICBpZiAoZWxlbWVudCAmJiBlbGVtZW50Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkubWF0Y2goLyhvbnMtbmF2aWdhdG9yfG9ucy10YWJiYXJ8b25zLW1vZGFsKS8pKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge09iamVjdH0gZWxlbWVudFxuICogQHJldHVybiB7QXJyYXl9XG4gKi9cbnV0aWwuZ2V0QWxsQ2hpbGROb2RlcyA9IChlbGVtZW50KSA9PiB7XG4gIHJldHVybiBbZWxlbWVudF0uY29uY2F0KFxuICAgIC4uLkFycmF5LmZyb20oZWxlbWVudC5jaGlsZHJlbikubWFwKGNoaWxkRWwgPT4ge1xuICAgICAgcmV0dXJuIHV0aWwuZ2V0QWxsQ2hpbGROb2RlcyhjaGlsZEVsKTtcbiAgICB9KVxuICApO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xudXRpbC5pc1BhZ2VDb250cm9sID0gZWxlbWVudCA9PiBlbGVtZW50Lm5vZGVOYW1lLm1hdGNoKC9eb25zLShuYXZpZ2F0b3J8c3BsaXR0ZXJ8dGFiYmFyfHBhZ2UpJC9pKTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7U3RyaW5nfSBhY3Rpb24gdG8gcHJvcGFnYXRlXG4gKi9cbnV0aWwucHJvcGFnYXRlQWN0aW9uID0gKGVsZW1lbnQsIGFjdGlvbikgPT4ge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnQuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGNoaWxkID0gZWxlbWVudC5jaGlsZE5vZGVzW2ldO1xuICAgIGlmIChjaGlsZFthY3Rpb25dIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIGNoaWxkW2FjdGlvbl0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdXRpbC5wcm9wYWdhdGVBY3Rpb24oY2hpbGQsIGFjdGlvbik7XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7U3RyaW5nfSBzdHJpbmcgLSBzdHJpbmcgdG8gYmUgY2FtZWxpemVkXG4gKiBAcmV0dXJuIHtTdHJpbmd9IENhbWVsaXplZCBzdHJpbmdcbiAqL1xudXRpbC5jYW1lbGl6ZSA9IHN0cmluZyA9PiBzdHJpbmcudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC8tKFthLXpdKS9nLCAobSwgbCkgPT4gbC50b1VwcGVyQ2FzZSgpKTtcblxuLyoqXG4gKiBAcGFyYW0ge1N0cmluZ30gc3RyaW5nIC0gc3RyaW5nIHRvIGJlIGh5cGhlbmF0ZWRcbiAqIEByZXR1cm4ge1N0cmluZ30gSHlwaGVuYXRlZCBzdHJpbmdcbiAqL1xudXRpbC5oeXBoZW5hdGUgPSBzdHJpbmcgPT4gc3RyaW5nLnJlcGxhY2UoLyhbYS16QS1aXSkoW0EtWl0pL2csICckMS0kMicpLnRvTG93ZXJDYXNlKCk7XG5cbi8qKlxuICogQHBhcmFtIHtTdHJpbmd9IHNlbGVjdG9yIC0gdGFnIGFuZCBjbGFzcyBvbmx5XG4gKiBAcGFyYW0ge09iamVjdH0gc3R5bGVcbiAqIEBwYXJhbSB7RWxlbWVudH1cbiAqL1xudXRpbC5jcmVhdGUgPSAoc2VsZWN0b3IgPSAnJywgc3R5bGUgPSB7fSkgPT4ge1xuICBjb25zdCBjbGFzc0xpc3QgPSBzZWxlY3Rvci5zcGxpdCgnLicpO1xuICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChjbGFzc0xpc3Quc2hpZnQoKSB8fCAnZGl2Jyk7XG5cbiAgaWYgKGNsYXNzTGlzdC5sZW5ndGgpIHtcbiAgICBlbGVtZW50LmNsYXNzTmFtZSA9IGNsYXNzTGlzdC5qb2luKCcgJyk7XG4gIH1cblxuICBzdHlsZXIoZWxlbWVudCwgc3R5bGUpO1xuXG4gIHJldHVybiBlbGVtZW50O1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge1N0cmluZ30gaHRtbFxuICogQHJldHVybiB7RWxlbWVudH1cbiAqL1xudXRpbC5jcmVhdGVFbGVtZW50ID0gKGh0bWwpID0+IHtcbiAgY29uc3Qgd3JhcHBlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4gIGlmIChodG1sIGluc3RhbmNlb2YgRG9jdW1lbnRGcmFnbWVudCkge1xuICAgIHdyYXBwZXIuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuaW1wb3J0Tm9kZShodG1sLCB0cnVlKSk7XG4gIH0gZWxzZSB7XG4gICAgd3JhcHBlci5pbm5lckhUTUwgPSBodG1sLnRyaW0oKTtcbiAgfVxuXG4gIGlmICh3cmFwcGVyLmNoaWxkcmVuLmxlbmd0aCA+IDEpIHtcbiAgICB1dGlsLnRocm93KCdIVE1MIHRlbXBsYXRlIG11c3QgY29udGFpbiBhIHNpbmdsZSByb290IGVsZW1lbnQnKVxuICB9XG5cbiAgY29uc3QgZWxlbWVudCA9IHdyYXBwZXIuY2hpbGRyZW5bMF07XG4gIHdyYXBwZXIuY2hpbGRyZW5bMF0ucmVtb3ZlKCk7XG4gIHJldHVybiBlbGVtZW50O1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge1N0cmluZ30gaHRtbFxuICogQHJldHVybiB7SFRNTEZyYWdtZW50fVxuICovXG51dGlsLmNyZWF0ZUZyYWdtZW50ID0gKGh0bWwpID0+IHtcbiAgY29uc3QgdGVtcGxhdGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0ZW1wbGF0ZScpO1xuICB0ZW1wbGF0ZS5pbm5lckhUTUwgPSBodG1sO1xuICByZXR1cm4gZG9jdW1lbnQuaW1wb3J0Tm9kZSh0ZW1wbGF0ZS5jb250ZW50LCB0cnVlKTtcbn07XG5cbi8qXG4gKiBAcGFyYW0ge09iamVjdH0gZHN0IERlc3RpbmF0aW9uIG9iamVjdC5cbiAqIEBwYXJhbSB7Li4uT2JqZWN0fSBzcmMgU291cmNlIG9iamVjdChzKS5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJlZmVyZW5jZSB0byBgZHN0YC5cbiAqL1xudXRpbC5leHRlbmQgPSAoZHN0LCAuLi5hcmdzKSA9PiB7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuICAgIGlmIChhcmdzW2ldKSB7XG4gICAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoYXJnc1tpXSk7XG4gICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGtleXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgY29uc3Qga2V5ID0ga2V5c1tqXTtcbiAgICAgICAgZHN0W2tleV0gPSBhcmdzW2ldW2tleV07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGRzdDtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtPYmplY3R9IGFycmF5TGlrZVxuICogQHJldHVybiB7QXJyYXl9XG4gKi9cbnV0aWwuYXJyYXlGcm9tID0gKGFycmF5TGlrZSkgPT4ge1xuICByZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmFwcGx5KGFycmF5TGlrZSk7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7U3RyaW5nfSBqc29uU3RyaW5nXG4gKiBAcGFyYW0ge09iamVjdH0gW2ZhaWxTYWZlXVxuICogQHJldHVybiB7T2JqZWN0fVxuICovXG51dGlsLnBhcnNlSlNPTk9iamVjdFNhZmVseSA9IChqc29uU3RyaW5nLCBmYWlsU2FmZSA9IHt9KSA9PiB7XG4gIHRyeSB7XG4gICAgY29uc3QgcmVzdWx0ID0gSlNPTi5wYXJzZSgnJyArIGpzb25TdHJpbmcpO1xuICAgIGlmICh0eXBlb2YgcmVzdWx0ID09PSAnb2JqZWN0JyAmJiByZXN1bHQgIT09IG51bGwpIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhaWxTYWZlO1xuICB9XG4gIHJldHVybiBmYWlsU2FmZTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtTdHJpbmd9IHBhdGggLSBwYXRoIHN1Y2ggYXMgJ215QXBwLmNvbnRyb2xsZXJzLmRhdGEubG9hZERhdGEnXG4gKiBAcmV0dXJuIHtBbnl9IC0gd2hhdGV2ZXIgaXMgbG9jYXRlZCBhdCB0aGF0IHBhdGhcbiAqL1xudXRpbC5maW5kRnJvbVBhdGggPSAocGF0aCkgPT4ge1xuICBwYXRoID0gcGF0aC5zcGxpdCgnLicpO1xuICB2YXIgZWwgPSB3aW5kb3csIGtleTtcbiAgd2hpbGUgKGtleSA9IHBhdGguc2hpZnQoKSkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbmQtYXNzaWduXG4gICAgZWwgPSBlbFtrZXldO1xuICB9XG4gIHJldHVybiBlbDtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gY29udGFpbmVyIC0gUGFnZSBvciBwYWdlLWNvbnRhaW5lciB0aGF0IGltcGxlbWVudHMgJ3RvcFBhZ2UnXG4gKiBAcmV0dXJuIHtIVE1MRWxlbWVudHxudWxsfSAtIFZpc2libGUgcGFnZSBlbGVtZW50IG9yIG51bGwgaWYgbm90IGZvdW5kLlxuICovXG51dGlsLmdldFRvcFBhZ2UgPSBjb250YWluZXIgPT4gY29udGFpbmVyICYmIChjb250YWluZXIudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnb25zLXBhZ2UnID8gY29udGFpbmVyIDogY29udGFpbmVyLnRvcFBhZ2UpIHx8IG51bGw7XG5cbi8qKlxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gY29udGFpbmVyIC0gRWxlbWVudCB3aGVyZSB0aGUgc2VhcmNoIGJlZ2luc1xuICogQHJldHVybiB7SFRNTEVsZW1lbnR8bnVsbH0gLSBQYWdlIGVsZW1lbnQgdGhhdCBjb250YWlucyB0aGUgdmlzaWJsZSB0b29sYmFyIG9yIG51bGwuXG4gKi9cbnV0aWwuZmluZFRvb2xiYXJQYWdlID0gY29udGFpbmVyID0+IHtcbiAgY29uc3QgcGFnZSA9IHV0aWwuZ2V0VG9wUGFnZShjb250YWluZXIpO1xuXG4gIGlmIChwYWdlKSB7XG4gICAgaWYgKHBhZ2UuX2NhbkFuaW1hdGVUb29sYmFyKCkpIHtcbiAgICAgIHJldHVybiBwYWdlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFnZS5fY29udGVudEVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IG5leHRQYWdlID0gdXRpbC5nZXRUb3BQYWdlKHBhZ2UuX2NvbnRlbnRFbGVtZW50LmNoaWxkcmVuW2ldKTtcbiAgICAgIGlmIChuZXh0UGFnZSAmJiAhL29ucy10YWJiYXIvaS50ZXN0KHBhZ2UuX2NvbnRlbnRFbGVtZW50LmNoaWxkcmVuW2ldLnRhZ05hbWUpKSB7XG4gICAgICAgIHJldHVybiB1dGlsLmZpbmRUb29sYmFyUGFnZShuZXh0UGFnZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtPYmplY3R9IFtkZXRhaWxdXG4gKiBAcmV0dXJuIHtDdXN0b21FdmVudH1cbiAqL1xudXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50ID0gKHRhcmdldCwgZXZlbnROYW1lLCBkZXRhaWwgPSB7fSkgPT4ge1xuXG4gIGNvbnN0IGV2ZW50ID0gbmV3IEN1c3RvbUV2ZW50KGV2ZW50TmFtZSwge1xuICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgY2FuY2VsYWJsZTogdHJ1ZSxcbiAgICBkZXRhaWw6IGRldGFpbFxuICB9KTtcblxuICBPYmplY3Qua2V5cyhkZXRhaWwpLmZvckVhY2goa2V5ID0+IHtcbiAgICBldmVudFtrZXldID0gZGV0YWlsW2tleV07XG4gIH0pO1xuXG4gIHRhcmdldC5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcblxuICByZXR1cm4gZXZlbnQ7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudH0gdGFyZ2V0XG4gKiBAcGFyYW0ge1N0cmluZ30gbW9kaWZpZXJOYW1lXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICovXG51dGlsLmhhc01vZGlmaWVyID0gKHRhcmdldCwgbW9kaWZpZXJOYW1lKSA9PiB7XG4gIGlmICghdGFyZ2V0Lmhhc0F0dHJpYnV0ZSgnbW9kaWZpZXInKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiBSZWdFeHAoYChefFxcXFxzKykke21vZGlmaWVyTmFtZX0oJHxcXFxccyspYCwgJ2knKS50ZXN0KHRhcmdldC5nZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJykpO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IHRhcmdldFxuICogQHBhcmFtIHtTdHJpbmd9IG1vZGlmaWVyTmFtZVxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMuYXV0b1N0eWxlIE1hcHMgdGhlIG1vZGlmaWVyTmFtZSB0byB0aGUgY29ycmVzcG9uZGluZyBzdHlsZWQgbW9kaWZpZXIuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucy5mb3JjZUF1dG9TdHlsZSBJZ25vcmVzIHBsYXRmb3JtIGxpbWl0YXRpb24uXG4gKiBAcmV0dXJuIHtCb29sZWFufSBXaGV0aGVyIGl0IHdhcyBhZGRlZCBvciBub3QuXG4gKi9cbnV0aWwuYWRkTW9kaWZpZXIgPSAodGFyZ2V0LCBtb2RpZmllck5hbWUsIG9wdGlvbnMgPSB7fSkgPT4ge1xuICBpZiAob3B0aW9ucy5hdXRvU3R5bGUpIHtcbiAgICBtb2RpZmllck5hbWUgPSBhdXRvU3R5bGUubWFwTW9kaWZpZXIobW9kaWZpZXJOYW1lLCB0YXJnZXQsIG9wdGlvbnMuZm9yY2VBdXRvU3R5bGUpO1xuICB9XG5cbiAgaWYgKHV0aWwuaGFzTW9kaWZpZXIodGFyZ2V0LCBtb2RpZmllck5hbWUpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgdGFyZ2V0LnNldEF0dHJpYnV0ZSgnbW9kaWZpZXInLCAoKHRhcmdldC5nZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJykgfHwgJycpICsgJyAnICsgbW9kaWZpZXJOYW1lKS50cmltKCkpO1xuICByZXR1cm4gdHJ1ZTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSB0YXJnZXRcbiAqIEBwYXJhbSB7U3RyaW5nfSBtb2RpZmllck5hbWVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zLmF1dG9TdHlsZSBNYXBzIHRoZSBtb2RpZmllck5hbWUgdG8gdGhlIGNvcnJlc3BvbmRpbmcgc3R5bGVkIG1vZGlmaWVyLlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMuZm9yY2VBdXRvU3R5bGUgSWdub3JlcyBwbGF0Zm9ybSBsaW1pdGF0aW9uLlxuICogQHJldHVybiB7Qm9vbGVhbn0gV2hldGhlciBpdCB3YXMgZm91bmQgb3Igbm90LlxuICovXG51dGlsLnJlbW92ZU1vZGlmaWVyID0gKHRhcmdldCwgbW9kaWZpZXJOYW1lLCBvcHRpb25zID0ge30pID0+IHtcbiAgaWYgKG9wdGlvbnMuYXV0b1N0eWxlKSB7XG4gICAgbW9kaWZpZXJOYW1lID0gYXV0b1N0eWxlLm1hcE1vZGlmaWVyKG1vZGlmaWVyTmFtZSwgdGFyZ2V0LCBvcHRpb25zLmZvcmNlQXV0b1N0eWxlKTtcbiAgfVxuXG4gIGlmICghdGFyZ2V0LmdldEF0dHJpYnV0ZSgnbW9kaWZpZXInKSB8fCAhdXRpbC5oYXNNb2RpZmllcih0YXJnZXQsIG1vZGlmaWVyTmFtZSkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjb25zdCBuZXdNb2RpZmllcnMgPSB0YXJnZXQuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpLnNwbGl0KC9cXHMrLykuZmlsdGVyKG0gPT4gbSAmJiBtICE9PSBtb2RpZmllck5hbWUpO1xuICBuZXdNb2RpZmllcnMubGVuZ3RoID8gdGFyZ2V0LnNldEF0dHJpYnV0ZSgnbW9kaWZpZXInLCBuZXdNb2RpZmllcnMuam9pbignICcpKSA6IHRhcmdldC5yZW1vdmVBdHRyaWJ1dGUoJ21vZGlmaWVyJyk7XG4gIHJldHVybiB0cnVlO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IHRhcmdldFxuICogQHBhcmFtIHtTdHJpbmd9IG1vZGlmaWVyTmFtZVxuICogQHBhcmFtIHtCb29sZWFufSBvcHRpb25zLmZvcmNlIEZvcmNlcyBtb2RpZmllciB0byBiZSBhZGRlZCBvciByZW1vdmVkLlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMuYXV0b1N0eWxlIE1hcHMgdGhlIG1vZGlmaWVyTmFtZSB0byB0aGUgY29ycmVzcG9uZGluZyBzdHlsZWQgbW9kaWZpZXIuXG4gKiBAcGFyYW0ge0Jvb2xlYW59IG9wdGlvbnMuZm9yY2VBdXRvU3R5bGUgSWdub3JlcyBwbGF0Zm9ybSBsaW1pdGF0aW9uLlxuICogQHJldHVybiB7Qm9vbGVhbn0gV2hldGhlciBpdCB3YXMgZm91bmQgb3Igbm90LlxuICovXG51dGlsLnRvZ2dsZU1vZGlmaWVyID0gKC4uLmFyZ3MpID0+IHtcbiAgY29uc3Qgb3B0aW9ucyA9IGFyZ3MubGVuZ3RoID4gMiA/IGFyZ3NbMl0gOiB7fTtcbiAgY29uc3QgZm9yY2UgPSB0eXBlb2Ygb3B0aW9ucyA9PT0gJ2Jvb2xlYW4nID8gb3B0aW9ucyA6IG9wdGlvbnMuZm9yY2U7XG5cbiAgY29uc3QgdG9nZ2xlID0gdHlwZW9mIGZvcmNlID09PSAnYm9vbGVhbicgPyBmb3JjZSA6ICF1dGlsLmhhc01vZGlmaWVyKC4uLmFyZ3MpO1xuICB0b2dnbGUgPyB1dGlsLmFkZE1vZGlmaWVyKC4uLmFyZ3MpIDogdXRpbC5yZW1vdmVNb2RpZmllciguLi5hcmdzKVxufTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsXG4gKiBAcGFyYW0ge1N0cmluZ30gZGVmYXVsdENsYXNzXG4gKiBAcGFyYW0ge09iamVjdH0gc2NoZW1lXG4gKi9cbnV0aWwucmVzdG9yZUNsYXNzID0gKGVsLCBkZWZhdWx0Q2xhc3MsIHNjaGVtZSkgPT4ge1xuICBkZWZhdWx0Q2xhc3Muc3BsaXQoL1xccysvKS5mb3JFYWNoKGMgPT4gYyAhPT0gJycgJiYgIWVsLmNsYXNzTGlzdC5jb250YWlucyhjKSAmJiBlbC5jbGFzc0xpc3QuYWRkKGMpKTtcbiAgZWwuaGFzQXR0cmlidXRlKCdtb2RpZmllcicpICYmIE1vZGlmaWVyVXRpbC5yZWZyZXNoKGVsLCBzY2hlbWUpO1xufVxuXG4vLyBUT0RPOiBGSVhcbnV0aWwudXBkYXRlUGFyZW50UG9zaXRpb24gPSAoZWwpID0+IHtcbiAgaWYgKCFlbC5fcGFyZW50VXBkYXRlZCAmJiBlbC5wYXJlbnRFbGVtZW50KSB7XG4gICAgaWYgKHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsLnBhcmVudEVsZW1lbnQpLmdldFByb3BlcnR5VmFsdWUoJ3Bvc2l0aW9uJykgPT09ICdzdGF0aWMnKSB7XG4gICAgICBlbC5wYXJlbnRFbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gJ3JlbGF0aXZlJztcbiAgICB9XG4gICAgZWwuX3BhcmVudFVwZGF0ZWQgPSB0cnVlO1xuICB9XG59O1xuXG51dGlsLnRvZ2dsZUF0dHJpYnV0ZSA9IChlbGVtZW50LCBuYW1lLCB2YWx1ZSkgPT4ge1xuICBpZiAodmFsdWUpIHtcbiAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShuYW1lLCB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJyA/ICcnIDogdmFsdWUpO1xuICB9IGVsc2Uge1xuICAgIGVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKG5hbWUpO1xuICB9XG59O1xuXG51dGlsLmJpbmRMaXN0ZW5lcnMgPSAoZWxlbWVudCwgbGlzdGVuZXJOYW1lcykgPT4ge1xuICBsaXN0ZW5lck5hbWVzLmZvckVhY2gobmFtZSA9PiB7XG4gICAgY29uc3QgYm91bmROYW1lID0gbmFtZS5yZXBsYWNlKC9eX1thLXpdLywgJ19ib3VuZCcgKyBuYW1lWzFdLnRvVXBwZXJDYXNlKCkpO1xuICAgIGVsZW1lbnRbYm91bmROYW1lXSA9IGVsZW1lbnRbYm91bmROYW1lXSB8fCBlbGVtZW50W25hbWVdLmJpbmQoZWxlbWVudCk7XG4gIH0pO1xufTtcblxudXRpbC5lYWNoID0gKG9iaiwgZikgPT4gT2JqZWN0LmtleXMob2JqKS5mb3JFYWNoKGtleSA9PiBmKGtleSwgb2JqW2tleV0pKTtcblxuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudH0gdGFyZ2V0XG4gKiBAcGFyYW0ge2Jvb2xlYW59IGhhc1JpcHBsZVxuICogQHBhcmFtIHtPYmplY3R9IGF0dHJzXG4gKi9cbnV0aWwudXBkYXRlUmlwcGxlID0gKHRhcmdldCwgaGFzUmlwcGxlLCBhdHRycyA9IHt9KSA9PiB7XG4gIGlmIChoYXNSaXBwbGUgPT09IHVuZGVmaW5lZCkge1xuICAgIGhhc1JpcHBsZSA9IHRhcmdldC5oYXNBdHRyaWJ1dGUoJ3JpcHBsZScpO1xuICB9XG5cbiAgY29uc3QgcmlwcGxlRWxlbWVudCA9IHV0aWwuZmluZENoaWxkKHRhcmdldCwgJ29ucy1yaXBwbGUnKTtcblxuICBpZiAoaGFzUmlwcGxlKSB7XG4gICAgaWYgKCFyaXBwbGVFbGVtZW50KSB7XG4gICAgICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnb25zLXJpcHBsZScpO1xuICAgICAgT2JqZWN0LmtleXMoYXR0cnMpLmZvckVhY2goa2V5ID0+IGVsZW1lbnQuc2V0QXR0cmlidXRlKGtleSwgYXR0cnNba2V5XSkpO1xuICAgICAgdGFyZ2V0Lmluc2VydEJlZm9yZShlbGVtZW50LCB0YXJnZXQuZmlyc3RDaGlsZCk7XG4gICAgfVxuICB9IGVsc2UgaWYgKHJpcHBsZUVsZW1lbnQpIHtcbiAgICByaXBwbGVFbGVtZW50LnJlbW92ZSgpO1xuICB9XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7U3RyaW5nfVxuICogQHJldHVybiB7T2JqZWN0fVxuICovXG51dGlsLmFuaW1hdGlvbk9wdGlvbnNQYXJzZSA9IGFuaW1hdGlvbk9wdGlvbnNQYXJzZTtcblxuLyoqXG4gKiBAcGFyYW0geyp9IHZhbHVlXG4gKi9cbnV0aWwuaXNJbnRlZ2VyID0gKHZhbHVlKSA9PiB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInICYmXG4gICAgaXNGaW5pdGUodmFsdWUpICYmXG4gICAgTWF0aC5mbG9vcih2YWx1ZSkgPT09IHZhbHVlO1xufTtcblxuLyoqXG4gKiBAcmV0dXJuIHtPYmplY3R9IERlZmVycmVkIHByb21pc2UuXG4gKi9cbnV0aWwuZGVmZXIgPSAoKSA9PiB7XG4gIGNvbnN0IGRlZmVycmVkID0ge307XG4gIGRlZmVycmVkLnByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgZGVmZXJyZWQucmVzb2x2ZSA9IHJlc29sdmU7XG4gICAgZGVmZXJyZWQucmVqZWN0ID0gcmVqZWN0O1xuICB9KTtcbiAgcmV0dXJuIGRlZmVycmVkO1xufTtcblxuLyoqXG4gKiBTaG93IHdhcm5pbmdzIHdoZW4gdGhleSBhcmUgZW5hYmxlZC5cbiAqXG4gKiBAcGFyYW0geyp9IGFyZ3VtZW50cyB0byBjb25zb2xlLndhcm5cbiAqL1xudXRpbC53YXJuID0gKC4uLmFyZ3MpID0+IHtcbiAgaWYgKCFpbnRlcm5hbC5jb25maWcud2FybmluZ3NEaXNhYmxlZCkge1xuICAgIGNvbnNvbGUud2FybihlcnJvclByZWZpeCwgLi4uYXJncyk7XG4gIH1cbn07XG5cbnV0aWwudGhyb3cgPSAobWVzc2FnZSkgPT4ge1xuICB0aHJvdyBuZXcgRXJyb3IoYCR7ZXJyb3JQcmVmaXh9ICR7bWVzc2FnZX1gKTtcbn07XG5cbnV0aWwudGhyb3dBYnN0cmFjdCA9ICgpID0+IHV0aWwudGhyb3coJ0Nhbm5vdCBpbnN0YW50aWF0ZSBhYnN0cmFjdCBjbGFzcycpO1xudXRpbC50aHJvd01lbWJlciA9ICgpID0+IHV0aWwudGhyb3coJ0NsYXNzIG1lbWJlciBtdXN0IGJlIGltcGxlbWVudGVkJyk7XG51dGlsLnRocm93UGFnZUxvYWRlciA9ICgpID0+IHV0aWwudGhyb3coJ0ZpcnN0IHBhcmFtZXRlciBzaG91bGQgYmUgYW4gaW5zdGFuY2Ugb2YgUGFnZUxvYWRlcicpO1xudXRpbC50aHJvd0FuaW1hdG9yID0gKGVsKSA9PiB1dGlsLnRocm93KGBcIkFuaW1hdG9yXCIgcGFyYW0gbXVzdCBpbmhlcml0ICR7ZWx9QW5pbWF0b3JgKTtcblxuXG5jb25zdCBwcmV2ZW50ID0gZSA9PiBlLmNhbmNlbGFibGUgJiYgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4vKipcbiAqIFByZXZlbnQgc2Nyb2xsaW5nIHdoaWxlIGRyYWdpbmcgaG9yaXpvbnRhbGx5IG9uIGlPUy5cbiAqXG4gKiBAcGFyYW0ge2dkfSBHZXN0dXJlRGV0ZWN0b3IgaW5zdGFuY2VcbiAqL1xudXRpbC5pb3NQcmV2ZW50U2Nyb2xsID0gZ2QgPT4ge1xuICBpZiAodXRpbC5nbG9iYWxzLmFjdHVhbE1vYmlsZU9TID09PSAnaW9zJykge1xuICAgIGNvbnN0IGNsZWFuID0gKGUpID0+IHtcbiAgICAgIGdkLm9mZigndG91Y2htb3ZlJywgcHJldmVudCk7XG4gICAgICBnZC5vZmYoJ2RyYWdlbmQnLCBjbGVhbik7XG4gICAgfTtcblxuICAgIGdkLm9uKCd0b3VjaG1vdmUnLCBwcmV2ZW50KTtcbiAgICBnZC5vbignZHJhZ2VuZCcsIGNsZWFuKTtcbiAgfVxufTtcblxuLyoqXG4gKiBQcmV2ZW50cyBzY3JvbGwgaW4gdW5kZXJseWluZyBwYWdlcyBvbiBpT1MuIFNlZSAjMjIyMCAjMjI3NCAjMTk0OVxuICpcbiAqIEBwYXJhbSB7ZWx9IEhUTUxFbGVtZW50IHRoYXQgcHJldmVudHMgdGhlIGV2ZW50c1xuICogQHBhcmFtIHthZGR9IEJvb2xlYW4gQWRkIG9yIHJlbW92ZSBldmVudCBsaXN0ZW5lcnNcbiAqL1xudXRpbC5pb3NQYWdlU2Nyb2xsRml4ID0gKGFkZCkgPT4geyAvLyBGdWxsIGZpeCAtIE1heSBjYXVzZSBpc3N1ZXMgd2l0aCBVSVdlYlZpZXcncyBtb21lbnR1bSBzY3JvbGxcbiAgaWYgKHV0aWwuZ2xvYmFscy5hY3R1YWxNb2JpbGVPUyA9PT0gJ2lvcycpIHtcbiAgICBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC50b2dnbGUoJ29ucy1pb3Mtc2Nyb2xsJywgYWRkKTsgLy8gQWxsb3dzIGN1c3RvbSBhbmQgbG9jYWxpemVkIGZpeGVzICgjMjI3NClcbiAgICBpZiAoIXV0aWwuZ2xvYmFscy5pc1VJV2ViVmlldyB8fCBpbnRlcm5hbC5jb25maWcuZm9yY2VVSVdlYlZpZXdTY3JvbGxGaXgpIHtcbiAgICAgIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LnRvZ2dsZSgnb25zLWlvcy1zY3JvbGwtZml4JywgYWRkKTtcbiAgICB9XG4gIH1cbn07XG51dGlsLmlvc01hc2tTY3JvbGxGaXggPSAoZWwsIGFkZCkgPT4geyAvLyBIYWxmIGZpeCAtIG9ubHkgcHJldmVudHMgc2Nyb2xsIG9uIG1hc2tzXG4gIGlmICh1dGlsLmdsb2JhbHMuaXNVSVdlYlZpZXcpIHtcbiAgICBjb25zdCBhY3Rpb24gPSAoYWRkID8gJ2FkZCcgOiAncmVtb3ZlJykgKyAnRXZlbnRMaXN0ZW5lcic7XG4gICAgZWxbYWN0aW9uXSgndG91Y2htb3ZlJywgcHJldmVudCwgZmFsc2UpO1xuICB9XG59O1xuXG4vKipcbiAqIERpc3RhbmNlIGFuZCBkZWx0YVRpbWUgZmlsdGVyIHNvbWUgd2VpcmQgZHJhZ3N0YXJ0IGV2ZW50cyB0aGF0IGFyZSBub3QgZmlyZWQgaW1tZWRpYXRlbHkuXG4gKlxuICogQHBhcmFtIHtldmVudH1cbiAqL1xudXRpbC5pc1ZhbGlkR2VzdHVyZSA9IGV2ZW50ID0+IGV2ZW50Lmdlc3R1cmUgIT09IHVuZGVmaW5lZCAmJiAoZXZlbnQuZ2VzdHVyZS5kaXN0YW5jZSA8PSAxNSB8fCBldmVudC5nZXN0dXJlLmRlbHRhVGltZSA8PSAxMDApO1xuXG51dGlsLmNoZWNrTWlzc2luZ0ltcG9ydCA9ICguLi5lbGVtZW50TmFtZXMpID0+IHtcbiAgZWxlbWVudE5hbWVzLmZvckVhY2gobmFtZSA9PiB7XG4gICAgaWYgKCFvbnNFbGVtZW50c1tuYW1lXSkge1xuICAgICAgdXRpbC50aHJvdyhgT25zJHtuYW1lfSBpcyByZXF1aXJlZCBidXQgd2FzIG5vdCBpbXBvcnRlZCAoQ3VzdG9tIEVsZW1lbnRzKWApO1xuICAgIH1cbiAgfSk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHV0aWw7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5cbi8qKlxuICogTWluaW1hbCBhbmltYXRpb24gbGlicmFyeSBmb3IgbWFuYWdpbmcgY3NzIHRyYW5zaXRpb24gb24gbW9iaWxlIGJyb3dzZXJzLlxuICovXG4ndXNlIHN0cmljdCc7XG5cbnZhciBUSU1FT1VUX1JBVElPID0gMS40O1xuXG52YXIgdXRpbCA9IHtcbn07XG5cbi8vIGNhcGl0YWxpemUgc3RyaW5nXG51dGlsLmNhcGl0YWxpemUgPSBmdW5jdGlvbihzdHIpIHtcbiAgcmV0dXJuIHN0ci5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHN0ci5zbGljZSgxKTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtPYmplY3R9IHBhcmFtc1xuICogQHBhcmFtIHtTdHJpbmd9IHBhcmFtcy5wcm9wZXJ0eVxuICogQHBhcmFtIHtGbG9hdH0gcGFyYW1zLmR1cmF0aW9uXG4gKiBAcGFyYW0ge1N0cmluZ30gcGFyYW1zLnRpbWluZ1xuICovXG51dGlsLmJ1aWxkVHJhbnNpdGlvblZhbHVlID0gZnVuY3Rpb24ocGFyYW1zKSB7XG4gIHBhcmFtcy5wcm9wZXJ0eSA9IHBhcmFtcy5wcm9wZXJ0eSB8fCAnYWxsJztcbiAgcGFyYW1zLmR1cmF0aW9uID0gcGFyYW1zLmR1cmF0aW9uIHx8IDAuNDtcbiAgcGFyYW1zLnRpbWluZyA9IHBhcmFtcy50aW1pbmcgfHwgJ2xpbmVhcic7XG5cbiAgdmFyIHByb3BzID0gcGFyYW1zLnByb3BlcnR5LnNwbGl0KC8gKy8pO1xuXG4gIHJldHVybiBwcm9wcy5tYXAoZnVuY3Rpb24ocHJvcCkge1xuICAgIHJldHVybiBwcm9wICsgJyAnICsgcGFyYW1zLmR1cmF0aW9uICsgJ3MgJyArIHBhcmFtcy50aW1pbmc7XG4gIH0pLmpvaW4oJywgJyk7XG59O1xuXG4vKipcbiAqIEFkZCBhbiBldmVudCBoYW5kbGVyIG9uIFwidHJhbnNpdGlvbmVuZFwiIGV2ZW50LlxuICovXG51dGlsLm9uY2VPblRyYW5zaXRpb25FbmQgPSBmdW5jdGlvbihlbGVtZW50LCBjYWxsYmFjaykge1xuICBpZiAoIWVsZW1lbnQpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7fTtcbiAgfVxuXG4gIHZhciBmbiA9IGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgaWYgKGVsZW1lbnQgPT0gZXZlbnQudGFyZ2V0KSB7XG4gICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgIHJlbW92ZUxpc3RlbmVycygpO1xuXG4gICAgICBjYWxsYmFjaygpO1xuICAgIH1cbiAgfTtcblxuICB2YXIgcmVtb3ZlTGlzdGVuZXJzID0gZnVuY3Rpb24oKSB7XG4gICAgdXRpbC5fdHJhbnNpdGlvbkVuZEV2ZW50cy5mb3JFYWNoKGZ1bmN0aW9uKGV2ZW50TmFtZSkge1xuICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgZm4sIGZhbHNlKTtcbiAgICB9KTtcbiAgfTtcblxuICB1dGlsLl90cmFuc2l0aW9uRW5kRXZlbnRzLmZvckVhY2goZnVuY3Rpb24oZXZlbnROYW1lKSB7XG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgZm4sIGZhbHNlKTtcbiAgfSk7XG5cbiAgcmV0dXJuIHJlbW92ZUxpc3RlbmVycztcbn07XG5cbnV0aWwuX3RyYW5zaXRpb25FbmRFdmVudHMgPSAoZnVuY3Rpb24oKSB7XG5cbiAgaWYgKCdvbnRyYW5zaXRpb25lbmQnIGluIHdpbmRvdykge1xuICAgIHJldHVybiBbJ3RyYW5zaXRpb25lbmQnXTtcbiAgfVxuXG4gIGlmICgnb253ZWJraXR0cmFuc2l0aW9uZW5kJyBpbiB3aW5kb3cpIHtcbiAgICByZXR1cm4gWyd3ZWJraXRUcmFuc2l0aW9uRW5kJ107XG4gIH1cblxuICBpZiAodXRpbC52ZW5kb3JQcmVmaXggPT09ICd3ZWJraXQnIHx8IHV0aWwudmVuZG9yUHJlZml4ID09PSAnbycgfHwgdXRpbC52ZW5kb3JQcmVmaXggPT09ICdtb3onIHx8IHV0aWwudmVuZG9yUHJlZml4ID09PSAnbXMnKSB7XG4gICAgcmV0dXJuIFt1dGlsLnZlbmRvclByZWZpeCArICdUcmFuc2l0aW9uRW5kJywgJ3RyYW5zaXRpb25lbmQnXTtcbiAgfVxuXG4gIHJldHVybiBbXTtcbn0pKCk7XG5cbnV0aWwuX2Nzc1Byb3BlcnR5RGljdCA9IChmdW5jdGlvbigpIHtcbiAgdmFyIHN0eWxlcyA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgJycpO1xuICB2YXIgZGljdCA9IHt9O1xuICB2YXIgYSA9ICdBJy5jaGFyQ29kZUF0KDApO1xuICB2YXIgeiA9ICd6Jy5jaGFyQ29kZUF0KDApO1xuXG4gIHZhciB1cHBlciA9IGZ1bmN0aW9uKHMpIHtcbiAgICByZXR1cm4gcy5zdWJzdHIoMSkudG9VcHBlckNhc2UoKTtcbiAgfTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0eWxlcy5sZW5ndGg7IGkrKykge1xuXG4gICAgdmFyIGtleSA9IHN0eWxlc1tpXVxuICAgIC5yZXBsYWNlKC9eWy1dKy8sICcnKVxuICAgIC5yZXBsYWNlKC9bLV1bYS16XS9nLCB1cHBlcilcbiAgICAucmVwbGFjZSgvXm1vei8sICdNb3onKTtcblxuICAgIGlmIChhIDw9IGtleS5jaGFyQ29kZUF0KDApICYmIHogPj0ga2V5LmNoYXJDb2RlQXQoMCkpIHtcbiAgICAgIGlmIChrZXkgIT09ICdjc3NUZXh0JyAmJiBrZXkgIT09ICdwYXJlbnRUZXh0Jykge1xuICAgICAgICBkaWN0W2tleV0gPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBkaWN0O1xufSkoKTtcblxudXRpbC5oYXNDc3NQcm9wZXJ0eSA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgcmV0dXJuIG5hbWUgaW4gdXRpbC5fY3NzUHJvcGVydHlEaWN0O1xufTtcblxuLyoqXG4gKiBWZW5kb3IgcHJlZml4IGZvciBjc3MgcHJvcGVydHkuXG4gKi9cbnV0aWwudmVuZG9yUHJlZml4ID0gKGZ1bmN0aW9uKCkge1xuICB2YXIgc3R5bGVzID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LCAnJyksXG4gICAgcHJlID0gKEFycmF5LnByb3RvdHlwZS5zbGljZVxuICAgICAgLmNhbGwoc3R5bGVzKVxuICAgICAgLmpvaW4oJycpXG4gICAgICAubWF0Y2goLy0obW96fHdlYmtpdHxtcyktLykgfHwgKHN0eWxlcy5PTGluayA9PT0gJycgJiYgWycnLCAnbyddKVxuICAgIClbMV07XG4gICAgcmV0dXJuIHByZTtcbn0pKCk7XG5cbnV0aWwuZm9yY2VMYXlvdXRBdE9uY2UgPSBmdW5jdGlvbihlbGVtZW50cywgY2FsbGJhY2spIHtcbiAgdGhpcy5iYXRjaEltbWVkaWF0ZShmdW5jdGlvbigpIHtcbiAgICBlbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgIC8vIGZvcmNlIGxheW91dFxuICAgICAgZWxlbWVudC5vZmZzZXRIZWlnaHQ7XG4gICAgfSk7XG4gICAgY2FsbGJhY2soKTtcbiAgfSk7XG59O1xuXG51dGlsLmJhdGNoSW1tZWRpYXRlID0gKGZ1bmN0aW9uKCkge1xuICB2YXIgY2FsbGJhY2tzID0gW107XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgaWYgKGNhbGxiYWNrcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHNldEltbWVkaWF0ZShmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGNvbmNyZWF0ZUNhbGxiYWNrcyA9IGNhbGxiYWNrcy5zbGljZSgwKTtcbiAgICAgICAgY2FsbGJhY2tzID0gW107XG4gICAgICAgIGNvbmNyZWF0ZUNhbGxiYWNrcy5mb3JFYWNoKGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjYWxsYmFja3MucHVzaChjYWxsYmFjayk7XG4gIH07XG59KSgpO1xuXG51dGlsLmJhdGNoQW5pbWF0aW9uRnJhbWUgPSAoZnVuY3Rpb24oKSB7XG4gIHZhciBjYWxsYmFja3MgPSBbXTtcblxuICB2YXIgcmFmID0gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSB8fFxuICAgIHdpbmRvdy53ZWJraXRSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubW96UmVxdWVzdEFuaW1hdGlvbkZyYW1lIHx8XG4gICAgd2luZG93Lm9SZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubXNSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICBmdW5jdGlvbihjYWxsYmFjaykge1xuICAgIHNldFRpbWVvdXQoY2FsbGJhY2ssIDEwMDAgLyA2MCk7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgaWYgKGNhbGxiYWNrcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJhZihmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGNvbmNyZWF0ZUNhbGxiYWNrcyA9IGNhbGxiYWNrcy5zbGljZSgwKTtcbiAgICAgICAgY2FsbGJhY2tzID0gW107XG4gICAgICAgIGNvbmNyZWF0ZUNhbGxiYWNrcy5mb3JFYWNoKGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjYWxsYmFja3MucHVzaChjYWxsYmFjayk7XG4gIH07XG59KSgpO1xuXG51dGlsLnRyYW5zaXRpb25Qcm9wZXJ0eU5hbWUgPSAoZnVuY3Rpb24oKSB7XG4gIGlmICh1dGlsLmhhc0Nzc1Byb3BlcnR5KCd0cmFuc2l0aW9uRHVyYXRpb24nKSkge1xuICAgIHJldHVybiAndHJhbnNpdGlvbic7XG4gIH1cblxuICBpZiAodXRpbC5oYXNDc3NQcm9wZXJ0eSh1dGlsLnZlbmRvclByZWZpeCArICdUcmFuc2l0aW9uRHVyYXRpb24nKSkge1xuICAgIHJldHVybiB1dGlsLnZlbmRvclByZWZpeCArICdUcmFuc2l0aW9uJztcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBzdGF0ZScpO1xufSkoKTtcblxuXG4vKipcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAqL1xudmFyIEFuaW1pdCA9IGZ1bmN0aW9uKGVsZW1lbnQsIGRlZmF1bHRzKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBBbmltaXQpKSB7XG4gICAgcmV0dXJuIG5ldyBBbmltaXQoZWxlbWVudCwgZGVmYXVsdHMpO1xuICB9XG5cbiAgaWYgKGVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgIHRoaXMuZWxlbWVudHMgPSBbZWxlbWVudF07XG4gIH0gZWxzZSBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGVsZW1lbnQpID09PSAnW29iamVjdCBBcnJheV0nKSB7XG4gICAgdGhpcy5lbGVtZW50cyA9IGVsZW1lbnQ7XG5cbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZpcnN0IGFyZ3VtZW50IG11c3QgYmUgYW4gYXJyYXkgb3IgYW4gaW5zdGFuY2Ugb2YgSFRNTEVsZW1lbnQuJyk7XG4gIH1cblxuICB0aGlzLmRlZmF1bHRzID0gZGVmYXVsdHM7XG4gIHRoaXMudHJhbnNpdGlvblF1ZXVlID0gW107XG4gIHRoaXMubGFzdFN0eWxlQXR0cmlidXRlRGljdCA9IFtdO1xufTtcblxuQW5pbWl0LnByb3RvdHlwZSA9IHtcblxuICAvKipcbiAgICogQHByb3BlcnR5IHtBcnJheX1cbiAgICovXG4gIHRyYW5zaXRpb25RdWV1ZTogdW5kZWZpbmVkLFxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkge0FycmF5fVxuICAgKi9cbiAgZWxlbWVudHM6IHVuZGVmaW5lZCxcblxuICAvKipcbiAgICogQHByb3BlcnR5IHtPYmplY3R9XG4gICAqL1xuICBkZWZhdWx0czogdW5kZWZpbmVkLFxuXG4gIC8qKlxuICAgKiBTdGFydCBhbmltYXRpb24gc2VxdWVuY2Ugd2l0aCBwYXNzZWQgYW5pbWF0aW9ucy5cbiAgICpcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHBsYXk6IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgaWYgKHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdGhpcy50cmFuc2l0aW9uUXVldWUucHVzaChmdW5jdGlvbihkb25lKSB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIGRvbmUoKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMuc3RhcnRBbmltYXRpb24oKTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuXG4gIC8qKlxuICAgKiBNb3N0IG9mIHRoZSBhbmltYXRpb25zIGZvbGxvdyB0aGlzIGRlZmF1bHQgcHJvY2Vzcy5cbiAgICpcbiAgICogQHBhcmFtIHtmcm9tfSBjc3Mgb3Igb3B0aW9ucyBvYmplY3QgY29udGFpbmluZyBjc3NcbiAgICogQHBhcmFtIHt0b30gY3NzIG9yIG9wdGlvbnMgb2JqZWN0IGNvbnRhaW5pbmcgY3NzXG4gICAqIEBwYXJhbSB7ZGVsYXl9IGRlbGF5IHRvIHdhaXRcbiAgICovXG4gIGRlZmF1bHQ6IGZ1bmN0aW9uKGZyb20sIHRvLCBkZWxheSkge1xuICAgIGZ1bmN0aW9uIHN0ZXAocGFyYW1zLCBkdXJhdGlvbiwgdGltaW5nKSB7XG4gICAgICBpZiAocGFyYW1zLmR1cmF0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZHVyYXRpb24gPSBwYXJhbXMuZHVyYXRpb247XG4gICAgICB9XG4gICAgICBpZiAocGFyYW1zLnRpbWluZyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRpbWluZyA9IHBhcmFtcy50aW1pbmc7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNzczogcGFyYW1zLmNzcyB8fCBwYXJhbXMsXG4gICAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcbiAgICAgICAgdGltaW5nOiB0aW1pbmdcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc2F2ZVN0eWxlKClcbiAgICAgIC5xdWV1ZShzdGVwKGZyb20sIDAsIHRoaXMuZGVmYXVsdHMudGltaW5nKSlcbiAgICAgIC53YWl0KGRlbGF5ID09PSB1bmRlZmluZWQgPyB0aGlzLmRlZmF1bHRzLmRlbGF5IDogZGVsYXkpXG4gICAgICAucXVldWUoc3RlcCh0bywgdGhpcy5kZWZhdWx0cy5kdXJhdGlvbiwgdGhpcy5kZWZhdWx0cy50aW1pbmcpKVxuICAgICAgLnJlc3RvcmVTdHlsZSgpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBRdWV1ZSB0cmFuc2l0aW9uIGFuaW1hdGlvbnMgb3Igb3RoZXIgZnVuY3Rpb24uXG4gICAqXG4gICAqIGUuZy4gYW5pbWl0KGVsdCkucXVldWUoe2NvbG9yOiAncmVkJ30pXG4gICAqIGUuZy4gYW5pbWl0KGVsdCkucXVldWUoe2NvbG9yOiAncmVkJ30sIHtkdXJhdGlvbjogMC40fSlcbiAgICogZS5nLiBhbmltaXQoZWx0KS5xdWV1ZSh7Y3NzOiB7Y29sb3I6ICdyZWQnfSwgZHVyYXRpb246IDAuMn0pXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fEFuaW1pdC5UcmFuc2l0aW9ufEZ1bmN0aW9ufSB0cmFuc2l0aW9uXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICovXG4gIHF1ZXVlOiBmdW5jdGlvbih0cmFuc2l0aW9uLCBvcHRpb25zKSB7XG4gICAgdmFyIHF1ZXVlID0gdGhpcy50cmFuc2l0aW9uUXVldWU7XG5cbiAgICBpZiAodHJhbnNpdGlvbiAmJiBvcHRpb25zKSB7XG4gICAgICBvcHRpb25zLmNzcyA9IHRyYW5zaXRpb247XG4gICAgICB0cmFuc2l0aW9uID0gbmV3IEFuaW1pdC5UcmFuc2l0aW9uKG9wdGlvbnMpO1xuICAgIH1cblxuICAgIGlmICghKHRyYW5zaXRpb24gaW5zdGFuY2VvZiBGdW5jdGlvbiB8fCB0cmFuc2l0aW9uIGluc3RhbmNlb2YgQW5pbWl0LlRyYW5zaXRpb24pKSB7XG4gICAgICBpZiAodHJhbnNpdGlvbi5jc3MpIHtcbiAgICAgICAgdHJhbnNpdGlvbiA9IG5ldyBBbmltaXQuVHJhbnNpdGlvbih0cmFuc2l0aW9uKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRyYW5zaXRpb24gPSBuZXcgQW5pbWl0LlRyYW5zaXRpb24oe1xuICAgICAgICAgIGNzczogdHJhbnNpdGlvblxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodHJhbnNpdGlvbiBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICBxdWV1ZS5wdXNoKHRyYW5zaXRpb24pO1xuICAgIH0gZWxzZSBpZiAodHJhbnNpdGlvbiBpbnN0YW5jZW9mIEFuaW1pdC5UcmFuc2l0aW9uKSB7XG4gICAgICBxdWV1ZS5wdXNoKHRyYW5zaXRpb24uYnVpbGQoKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBhcmd1bWVudHMnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcblxuICAvKipcbiAgICogUXVldWUgdHJhbnNpdGlvbiBhbmltYXRpb25zLlxuICAgKlxuICAgKiBAcGFyYW0ge0Zsb2F0fSBzZWNvbmRzXG4gICAqL1xuICB3YWl0OiBmdW5jdGlvbihzZWNvbmRzKSB7XG4gICAgaWYgKHNlY29uZHMgPiAwKSB7XG4gICAgICB0aGlzLnRyYW5zaXRpb25RdWV1ZS5wdXNoKGZ1bmN0aW9uKGRvbmUpIHtcbiAgICAgICAgc2V0VGltZW91dChkb25lLCAxMDAwICogc2Vjb25kcyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcblxuICBzYXZlU3R5bGU6IGZ1bmN0aW9uKCkge1xuXG4gICAgdGhpcy50cmFuc2l0aW9uUXVldWUucHVzaChmdW5jdGlvbihkb25lKSB7XG4gICAgICB0aGlzLmVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24oZWxlbWVudCwgaW5kZXgpIHtcbiAgICAgICAgdmFyIGNzcyA9IHRoaXMubGFzdFN0eWxlQXR0cmlidXRlRGljdFtpbmRleF0gPSB7fTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZW1lbnQuc3R5bGUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBjc3NbZWxlbWVudC5zdHlsZVtpXV0gPSBlbGVtZW50LnN0eWxlW2VsZW1lbnQuc3R5bGVbaV1dO1xuICAgICAgICB9XG4gICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgZG9uZSgpO1xuICAgIH0uYmluZCh0aGlzKSk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcblxuICAvKipcbiAgICogUmVzdG9yZSBlbGVtZW50J3Mgc3R5bGUuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogQHBhcmFtIHtGbG9hdH0gW29wdGlvbnMuZHVyYXRpb25dXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy50aW1pbmddXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy50cmFuc2l0aW9uXVxuICAgKi9cbiAgcmVzdG9yZVN0eWxlOiBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgaWYgKG9wdGlvbnMudHJhbnNpdGlvbiAmJiAhb3B0aW9ucy5kdXJhdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcIm9wdGlvbnMuZHVyYXRpb25cIiBpcyByZXF1aXJlZCB3aGVuIFwib3B0aW9ucy50cmFuc2l0aW9uXCIgaXMgZW5hYmxlZC4nKTtcbiAgICB9XG5cbiAgICB2YXIgdHJhbnNpdGlvbk5hbWUgPSB1dGlsLnRyYW5zaXRpb25Qcm9wZXJ0eU5hbWU7XG5cbiAgICBpZiAob3B0aW9ucy50cmFuc2l0aW9uIHx8IChvcHRpb25zLmR1cmF0aW9uICYmIG9wdGlvbnMuZHVyYXRpb24gPiAwKSkge1xuICAgICAgdmFyIHRyYW5zaXRpb25WYWx1ZSA9IG9wdGlvbnMudHJhbnNpdGlvbiB8fCAoJ2FsbCAnICsgb3B0aW9ucy5kdXJhdGlvbiArICdzICcgKyAob3B0aW9ucy50aW1pbmcgfHwgJ2xpbmVhcicpKTtcblxuICAgICAgdGhpcy50cmFuc2l0aW9uUXVldWUucHVzaChmdW5jdGlvbihkb25lKSB7XG4gICAgICAgIHZhciBlbGVtZW50cyA9IHRoaXMuZWxlbWVudHM7XG4gICAgICAgIHZhciB0aW1lb3V0SWQ7XG5cbiAgICAgICAgdmFyIGNsZWFyVHJhbnNpdGlvbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICAgICAgZWxlbWVudC5zdHlsZVt0cmFuc2l0aW9uTmFtZV0gPSAnJztcbiAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBhZGQgXCJ0cmFuc2l0aW9uZW5kXCIgZXZlbnQgaGFuZGxlclxuICAgICAgICB2YXIgcmVtb3ZlTGlzdGVuZXJzID0gdXRpbC5vbmNlT25UcmFuc2l0aW9uRW5kKGVsZW1lbnRzWzBdLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTtcbiAgICAgICAgICBjbGVhclRyYW5zaXRpb24oKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIGZvciBmYWlsIHNhZmUuXG4gICAgICAgIHRpbWVvdXRJZCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmVtb3ZlTGlzdGVuZXJzKCk7XG4gICAgICAgICAgY2xlYXJUcmFuc2l0aW9uKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9LCBvcHRpb25zLmR1cmF0aW9uICogMTAwMCAqIFRJTUVPVVRfUkFUSU8pO1xuXG4gICAgICAgIC8vIHRyYW5zaXRpb24gYW5kIHN0eWxlIHNldHRpbmdzXG4gICAgICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24oZWxlbWVudCwgaW5kZXgpIHtcblxuICAgICAgICAgIHZhciBjc3MgPSBzZWxmLmxhc3RTdHlsZUF0dHJpYnV0ZURpY3RbaW5kZXhdO1xuXG4gICAgICAgICAgaWYgKCFjc3MpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigncmVzdG9yZVN0eWxlKCk6IFRoZSBzdHlsZSBpcyBub3Qgc2F2ZWQuIEludm9rZSBzYXZlU3R5bGUoKSBiZWZvcmUuJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgc2VsZi5sYXN0U3R5bGVBdHRyaWJ1dGVEaWN0W2luZGV4XSA9IHVuZGVmaW5lZDtcblxuICAgICAgICAgIHZhciBuYW1lO1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBlbGVtZW50LnN0eWxlLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICBuYW1lID0gZWxlbWVudC5zdHlsZVtpXTtcbiAgICAgICAgICAgIGlmIChjc3NbbmFtZV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBjc3NbbmFtZV0gPSAnJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBlbGVtZW50LnN0eWxlW3RyYW5zaXRpb25OYW1lXSA9IHRyYW5zaXRpb25WYWx1ZTtcblxuICAgICAgICAgIE9iamVjdC5rZXlzKGNzcykuZm9yRWFjaChmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgICAgIGlmIChrZXkgIT09IHRyYW5zaXRpb25OYW1lKSB7XG4gICAgICAgICAgICAgIGVsZW1lbnQuc3R5bGVba2V5XSA9IGNzc1trZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgZWxlbWVudC5zdHlsZVt0cmFuc2l0aW9uTmFtZV0gPSB0cmFuc2l0aW9uVmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudHJhbnNpdGlvblF1ZXVlLnB1c2goZnVuY3Rpb24oZG9uZSkge1xuICAgICAgICByZXNldCgpO1xuICAgICAgICBkb25lKCk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcblxuICAgIGZ1bmN0aW9uIHJlc2V0KCkge1xuICAgICAgLy8gQ2xlYXIgdHJhbnNpdGlvbiBhbmltYXRpb24gc2V0dGluZ3MuXG4gICAgICBzZWxmLmVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24oZWxlbWVudCwgaW5kZXgpIHtcbiAgICAgICAgZWxlbWVudC5zdHlsZVt0cmFuc2l0aW9uTmFtZV0gPSAnbm9uZSc7XG5cbiAgICAgICAgdmFyIGNzcyA9IHNlbGYubGFzdFN0eWxlQXR0cmlidXRlRGljdFtpbmRleF07XG5cbiAgICAgICAgaWYgKCFjc3MpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Jlc3RvcmVTdHlsZSgpOiBUaGUgc3R5bGUgaXMgbm90IHNhdmVkLiBJbnZva2Ugc2F2ZVN0eWxlKCkgYmVmb3JlLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgc2VsZi5sYXN0U3R5bGVBdHRyaWJ1dGVEaWN0W2luZGV4XSA9IHVuZGVmaW5lZDtcblxuICAgICAgICBmb3IgKHZhciBpID0gMCwgbmFtZSA9ICcnOyBpIDwgZWxlbWVudC5zdHlsZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIG5hbWUgPSBlbGVtZW50LnN0eWxlW2ldO1xuICAgICAgICAgIGlmICh0eXBlb2YgY3NzW2VsZW1lbnQuc3R5bGVbaV1dID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgY3NzW2VsZW1lbnQuc3R5bGVbaV1dID0gJyc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgT2JqZWN0LmtleXMoY3NzKS5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICAgICAgICAgIGVsZW1lbnQuc3R5bGVba2V5XSA9IGNzc1trZXldO1xuICAgICAgICB9KTtcblxuICAgICAgfSk7XG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBTdGFydCBhbmltYXRpb24gc2VxdWVuY2UuXG4gICAqL1xuICBzdGFydEFuaW1hdGlvbjogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fZGVxdWV1ZVRyYW5zaXRpb24oKTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuXG4gIF9kZXF1ZXVlVHJhbnNpdGlvbjogZnVuY3Rpb24oKSB7XG4gICAgdmFyIHRyYW5zaXRpb24gPSB0aGlzLnRyYW5zaXRpb25RdWV1ZS5zaGlmdCgpO1xuICAgIGlmICh0aGlzLl9jdXJyZW50VHJhbnNpdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDdXJyZW50IHRyYW5zaXRpb24gZXhpc3RzLicpO1xuICAgIH1cbiAgICB0aGlzLl9jdXJyZW50VHJhbnNpdGlvbiA9IHRyYW5zaXRpb247XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHZhciBjYWxsZWQgPSBmYWxzZTtcblxuICAgIHZhciBkb25lID0gZnVuY3Rpb24oKSB7XG4gICAgICBpZiAoIWNhbGxlZCkge1xuICAgICAgICBjYWxsZWQgPSB0cnVlO1xuICAgICAgICBzZWxmLl9jdXJyZW50VHJhbnNpdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgc2VsZi5fZGVxdWV1ZVRyYW5zaXRpb24oKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBzdGF0ZTogVGhpcyBjYWxsYmFjayBpcyBjYWxsZWQgdHdpY2UuJyk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGlmICh0cmFuc2l0aW9uKSB7XG4gICAgICB0cmFuc2l0aW9uLmNhbGwodGhpcywgZG9uZSk7XG4gICAgfVxuICB9XG5cbn07XG5cbi8qKlxuICogQHBhcmFtIHtBbmltaXR9IGFyZ3VtZW50c1xuICovXG5BbmltaXQucnVuQWxsID0gZnVuY3Rpb24oLyogYXJndW1lbnRzLi4uICovKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgYXJndW1lbnRzW2ldLnBsYXkoKTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gKiBAcGFyYW0ge0Zsb2F0fSBbb3B0aW9ucy5kdXJhdGlvbl1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5wcm9wZXJ0eV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy50aW1pbmddXG4gKi9cbkFuaW1pdC5UcmFuc2l0aW9uID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICB0aGlzLm9wdGlvbnMuZHVyYXRpb24gPSB0aGlzLm9wdGlvbnMuZHVyYXRpb24gfHwgMDtcbiAgdGhpcy5vcHRpb25zLnRpbWluZyA9IHRoaXMub3B0aW9ucy50aW1pbmcgfHwgJ2xpbmVhcic7XG4gIHRoaXMub3B0aW9ucy5jc3MgPSB0aGlzLm9wdGlvbnMuY3NzIHx8IHt9O1xuICB0aGlzLm9wdGlvbnMucHJvcGVydHkgPSB0aGlzLm9wdGlvbnMucHJvcGVydHkgfHwgJ2FsbCc7XG59O1xuXG5BbmltaXQuVHJhbnNpdGlvbi5wcm90b3R5cGUgPSB7XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAgICogQHJldHVybiB7RnVuY3Rpb259XG4gICAqL1xuICBidWlsZDogZnVuY3Rpb24oKSB7XG5cbiAgICBpZiAoT2JqZWN0LmtleXModGhpcy5vcHRpb25zLmNzcykubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ29wdGlvbnMuY3NzIGlzIHJlcXVpcmVkLicpO1xuICAgIH1cblxuICAgIHZhciBjc3MgPSBjcmVhdGVBY3R1YWxDc3NQcm9wcyh0aGlzLm9wdGlvbnMuY3NzKTtcblxuICAgIGlmICh0aGlzLm9wdGlvbnMuZHVyYXRpb24gPiAwKSB7XG4gICAgICB2YXIgdHJhbnNpdGlvblZhbHVlID0gdXRpbC5idWlsZFRyYW5zaXRpb25WYWx1ZSh0aGlzLm9wdGlvbnMpO1xuICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGVsZW1lbnRzID0gdGhpcy5lbGVtZW50cztcbiAgICAgICAgdmFyIHRpbWVvdXQgPSBzZWxmLm9wdGlvbnMuZHVyYXRpb24gKiAxMDAwICogVElNRU9VVF9SQVRJTztcbiAgICAgICAgdmFyIHRpbWVvdXRJZDtcblxuICAgICAgICB2YXIgcmVtb3ZlTGlzdGVuZXJzID0gdXRpbC5vbmNlT25UcmFuc2l0aW9uRW5kKGVsZW1lbnRzWzBdLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aW1lb3V0SWQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHJlbW92ZUxpc3RlbmVycygpO1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH0sIHRpbWVvdXQpO1xuXG4gICAgICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICAgIGVsZW1lbnQuc3R5bGVbdXRpbC50cmFuc2l0aW9uUHJvcGVydHlOYW1lXSA9IHRyYW5zaXRpb25WYWx1ZTtcblxuICAgICAgICAgIE9iamVjdC5rZXlzKGNzcykuZm9yRWFjaChmdW5jdGlvbihuYW1lKSB7XG4gICAgICAgICAgICBlbGVtZW50LnN0eWxlW25hbWVdID0gY3NzW25hbWVdO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLmR1cmF0aW9uIDw9IDApIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihjYWxsYmFjaykge1xuICAgICAgICB2YXIgZWxlbWVudHMgPSB0aGlzLmVsZW1lbnRzO1xuXG4gICAgICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICAgIGVsZW1lbnQuc3R5bGVbdXRpbC50cmFuc2l0aW9uUHJvcGVydHlOYW1lXSA9ICcnO1xuXG4gICAgICAgICAgT2JqZWN0LmtleXMoY3NzKS5mb3JFYWNoKGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuc3R5bGVbbmFtZV0gPSBjc3NbbmFtZV07XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChlbGVtZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdXRpbC5mb3JjZUxheW91dEF0T25jZShlbGVtZW50cywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB1dGlsLmJhdGNoQW5pbWF0aW9uRnJhbWUoY2FsbGJhY2spO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHV0aWwuYmF0Y2hBbmltYXRpb25GcmFtZShjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlQWN0dWFsQ3NzUHJvcHMoY3NzKSB7XG4gICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgIE9iamVjdC5rZXlzKGNzcykuZm9yRWFjaChmdW5jdGlvbihuYW1lKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGNzc1tuYW1lXTtcblxuICAgICAgICBpZiAodXRpbC5oYXNDc3NQcm9wZXJ0eShuYW1lKSkge1xuICAgICAgICAgIHJlc3VsdFtuYW1lXSA9IHZhbHVlO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBwcmVmaXhlZCA9IHV0aWwudmVuZG9yUHJlZml4ICsgdXRpbC5jYXBpdGFsaXplKG5hbWUpO1xuICAgICAgICBpZiAodXRpbC5oYXNDc3NQcm9wZXJ0eShwcmVmaXhlZCkpIHtcbiAgICAgICAgICByZXN1bHRbcHJlZml4ZWRdID0gdmFsdWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzdWx0W3ByZWZpeGVkXSA9IHZhbHVlO1xuICAgICAgICAgIHJlc3VsdFtuYW1lXSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgfVxufTtcblxuZXhwb3J0IGRlZmF1bHQgQW5pbWl0O1xuXG4iLCIvKlxuICogR2VzdHVyZSBkZXRlY3RvciBsaWJyYXJ5IHRoYXQgZm9ya2VkIGZyb20gZ2l0aHViLmNvbS9FaWdodE1lZGlhL2hhbW1lci5qcy5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbmltcG9ydCB1dGlsIGZyb20gJy4vdXRpbCc7XG5cbnZhciBFdmVudCwgVXRpbHMsIERldGVjdGlvbiwgUG9pbnRlckV2ZW50O1xuXG4vKipcbiAqIEBvYmplY3Qgb25zLkdlc3R1cmVEZXRlY3RvclxuICogQGNhdGVnb3J5IGdlc3R1cmVcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dVXRpbGl0eSBjbGFzcyBmb3IgZ2VzdHVyZSBkZXRlY3Rpb24uWy9lbl1cbiAqICAgW2phXeOCuOOCp+OCueODgeODo+OCkuaknOefpeOBmeOCi+OBn+OCgeOBruODpuODvOODhuOCo+ODquODhuOCo+OCr+ODqeOCueOBp+OBmeOAglsvamFdXG4gKi9cblxuLyoqXG4gKiBAbWV0aG9kIGNvbnN0cnVjdG9yXG4gKiBAc2lnbmF0dXJlIGNvbnN0cnVjdG9yKGVsZW1lbnRbLCBvcHRpb25zXSlcbiAqIEBkZXNjcmlwdGlvblxuICogIFtlbl1DcmVhdGUgYSBuZXcgR2VzdHVyZURldGVjdG9yIGluc3RhbmNlLlsvZW5dXG4gKiAgW2phXUdlc3R1cmVEZXRlY3RvcuOBruOCpOODs+OCueOCv+ODs+OCueOCkueUn+aIkOOBl+OBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqICAgW2VuXU5hbWUgb2YgdGhlIGV2ZW50LlsvZW5dXG4gKiAgIFtqYV3jgrjjgqfjgrnjg4Hjg6PjgpLmpJznn6XjgZnjgotET03opoHntKDjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICogICBbZW5dT3B0aW9ucyBvYmplY3QuWy9lbl1cbiAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAcmV0dXJuIHtvbnMuR2VzdHVyZURldGVjdG9yLkluc3RhbmNlfVxuICovXG52YXIgR2VzdHVyZURldGVjdG9yID0gZnVuY3Rpb24gR2VzdHVyZURldGVjdG9yKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIG5ldyBHZXN0dXJlRGV0ZWN0b3IuSW5zdGFuY2UoZWxlbWVudCwgb3B0aW9ucyB8fCB7fSk7XG59O1xuXG5cbi8qKlxuICogZGVmYXVsdCBzZXR0aW5ncy5cbiAqIG1vcmUgc2V0dGluZ3MgYXJlIGRlZmluZWQgcGVyIGdlc3R1cmUgYXQgYC9nZXN0dXJlc2AuIEVhY2ggZ2VzdHVyZSBjYW4gYmUgZGlzYWJsZWQvZW5hYmxlZFxuICogYnkgc2V0dGluZyBpdCdzIG5hbWUgKGxpa2UgYHN3aXBlYCkgdG8gZmFsc2UuXG4gKiBZb3UgY2FuIHNldCB0aGUgZGVmYXVsdHMgZm9yIGFsbCBpbnN0YW5jZXMgYnkgY2hhbmdpbmcgdGhpcyBvYmplY3QgYmVmb3JlIGNyZWF0aW5nIGFuIGluc3RhbmNlLlxuICogQGV4YW1wbGVcbiAqIGBgYGBcbiAqICBHZXN0dXJlRGV0ZWN0b3IuZGVmYXVsdHMuZHJhZyA9IGZhbHNlO1xuICogIEdlc3R1cmVEZXRlY3Rvci5kZWZhdWx0cy5iZWhhdmlvci50b3VjaEFjdGlvbiA9ICdwYW4teSc7XG4gKiAgZGVsZXRlIEdlc3R1cmVEZXRlY3Rvci5kZWZhdWx0cy5iZWhhdmlvci51c2VyU2VsZWN0O1xuICogYGBgYFxuICogQHByb3BlcnR5IGRlZmF1bHRzXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5HZXN0dXJlRGV0ZWN0b3IuZGVmYXVsdHMgPSB7XG4gIGJlaGF2aW9yOiB7XG4gICAgLy8gdXNlclNlbGVjdDogJ25vbmUnLCAvLyBBbHNvIGRpc2FibGVzIHNlbGVjdGlvbiBpbiBgaW5wdXRgIGNoaWxkcmVuXG4gICAgdG91Y2hBY3Rpb246ICdwYW4teScsXG4gICAgdG91Y2hDYWxsb3V0OiAnbm9uZScsXG4gICAgY29udGVudFpvb21pbmc6ICdub25lJyxcbiAgICB1c2VyRHJhZzogJ25vbmUnLFxuICAgIHRhcEhpZ2hsaWdodENvbG9yOiAncmdiYSgwLDAsMCwwKSdcbiAgfVxufTtcblxuLyoqXG4gKiBHZXN0dXJlRGV0ZWN0b3IgZG9jdW1lbnQgd2hlcmUgdGhlIGJhc2UgZXZlbnRzIGFyZSBhZGRlZCBhdFxuICogQHByb3BlcnR5IERPQ1VNRU5UXG4gKiBAdHlwZSB7SFRNTEVsZW1lbnR9XG4gKiBAZGVmYXVsdCB3aW5kb3cuZG9jdW1lbnRcbiAqL1xuR2VzdHVyZURldGVjdG9yLkRPQ1VNRU5UID0gZG9jdW1lbnQ7XG5cbi8qKlxuICogZGV0ZWN0IHN1cHBvcnQgZm9yIHBvaW50ZXIgZXZlbnRzXG4gKiBAcHJvcGVydHkgSEFTX1BPSU5URVJFVkVOVFNcbiAqIEB0eXBlIHtCb29sZWFufVxuICovXG5HZXN0dXJlRGV0ZWN0b3IuSEFTX1BPSU5URVJFVkVOVFMgPSBuYXZpZ2F0b3IucG9pbnRlckVuYWJsZWQgfHwgbmF2aWdhdG9yLm1zUG9pbnRlckVuYWJsZWQ7XG5cbi8qKlxuICogZGV0ZWN0IHN1cHBvcnQgZm9yIHRvdWNoIGV2ZW50c1xuICogQHByb3BlcnR5IEhBU19UT1VDSEVWRU5UU1xuICogQHR5cGUge0Jvb2xlYW59XG4gKi9cbkdlc3R1cmVEZXRlY3Rvci5IQVNfVE9VQ0hFVkVOVFMgPSAoJ29udG91Y2hzdGFydCcgaW4gd2luZG93KTtcblxuLyoqXG4gKiBkZXRlY3QgbW9iaWxlIGJyb3dzZXJzXG4gKiBAcHJvcGVydHkgSVNfTU9CSUxFXG4gKiBAdHlwZSB7Qm9vbGVhbn1cbiAqL1xuR2VzdHVyZURldGVjdG9yLklTX01PQklMRSA9IC9tb2JpbGV8dGFibGV0fGlwKGFkfGhvbmV8b2QpfGFuZHJvaWR8c2lsay9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG5cbi8qKlxuICogZGV0ZWN0IGlmIHdlIHdhbnQgdG8gc3VwcG9ydCBtb3VzZWV2ZW50cyBhdCBhbGxcbiAqIEBwcm9wZXJ0eSBOT19NT1VTRUVWRU5UU1xuICogQHR5cGUge0Jvb2xlYW59XG4gKi9cbkdlc3R1cmVEZXRlY3Rvci5OT19NT1VTRUVWRU5UUyA9IChHZXN0dXJlRGV0ZWN0b3IuSEFTX1RPVUNIRVZFTlRTICYmIEdlc3R1cmVEZXRlY3Rvci5JU19NT0JJTEUpIHx8IEdlc3R1cmVEZXRlY3Rvci5IQVNfUE9JTlRFUkVWRU5UUztcblxuLyoqXG4gKiBpbnRlcnZhbCBpbiB3aGljaCBHZXN0dXJlRGV0ZWN0b3IgcmVjYWxjdWxhdGVzIGN1cnJlbnQgdmVsb2NpdHkvZGlyZWN0aW9uL2FuZ2xlIGluIG1zXG4gKiBAcHJvcGVydHkgQ0FMQ1VMQVRFX0lOVEVSVkFMXG4gKiBAdHlwZSB7TnVtYmVyfVxuICogQGRlZmF1bHQgMjVcbiAqL1xuR2VzdHVyZURldGVjdG9yLkNBTENVTEFURV9JTlRFUlZBTCA9IDI1O1xuXG4vKipcbiAqIGV2ZW50dHlwZXMgcGVyIHRvdWNoZXZlbnQgKHN0YXJ0LCBtb3ZlLCBlbmQpIGFyZSBmaWxsZWQgYnkgYEV2ZW50LmRldGVybWluZUV2ZW50VHlwZXNgIG9uIGBzZXR1cGBcbiAqIHRoZSBvYmplY3QgY29udGFpbnMgdGhlIERPTSBldmVudCBuYW1lcyBwZXIgdHlwZSAoYEVWRU5UX1NUQVJUYCwgYEVWRU5UX01PVkVgLCBgRVZFTlRfRU5EYClcbiAqIEBwcm9wZXJ0eSBFVkVOVF9UWVBFU1xuICogQHByaXZhdGVcbiAqIEB3cml0ZU9uY2VcbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cbnZhciBFVkVOVF9UWVBFUyA9IHt9O1xuXG4vKipcbiAqIGRpcmVjdGlvbiBzdHJpbmdzLCBmb3Igc2FmZSBjb21wYXJpc29uc1xuICogQHByb3BlcnR5IERJUkVDVElPTl9ET1dOfExFRlR8VVB8UklHSFRcbiAqIEBmaW5hbFxuICogQHR5cGUge1N0cmluZ31cbiAqIEBkZWZhdWx0ICdkb3duJyAnbGVmdCcgJ3VwJyAncmlnaHQnXG4gKi9cbnZhciBESVJFQ1RJT05fRE9XTiA9IEdlc3R1cmVEZXRlY3Rvci5ESVJFQ1RJT05fRE9XTiA9ICdkb3duJztcbnZhciBESVJFQ1RJT05fTEVGVCA9IEdlc3R1cmVEZXRlY3Rvci5ESVJFQ1RJT05fTEVGVCA9ICdsZWZ0JztcbnZhciBESVJFQ1RJT05fVVAgPSBHZXN0dXJlRGV0ZWN0b3IuRElSRUNUSU9OX1VQID0gJ3VwJztcbnZhciBESVJFQ1RJT05fUklHSFQgPSBHZXN0dXJlRGV0ZWN0b3IuRElSRUNUSU9OX1JJR0hUID0gJ3JpZ2h0JztcblxuLyoqXG4gKiBwb2ludGVydHlwZSBzdHJpbmdzLCBmb3Igc2FmZSBjb21wYXJpc29uc1xuICogQHByb3BlcnR5IFBPSU5URVJfTU9VU0V8VE9VQ0h8UEVOXG4gKiBAZmluYWxcbiAqIEB0eXBlIHtTdHJpbmd9XG4gKiBAZGVmYXVsdCAnbW91c2UnICd0b3VjaCcgJ3BlbidcbiAqL1xudmFyIFBPSU5URVJfTU9VU0UgPSBHZXN0dXJlRGV0ZWN0b3IuUE9JTlRFUl9NT1VTRSA9ICdtb3VzZSc7XG52YXIgUE9JTlRFUl9UT1VDSCA9IEdlc3R1cmVEZXRlY3Rvci5QT0lOVEVSX1RPVUNIID0gJ3RvdWNoJztcbnZhciBQT0lOVEVSX1BFTiA9IEdlc3R1cmVEZXRlY3Rvci5QT0lOVEVSX1BFTiA9ICdwZW4nO1xuXG4vKipcbiAqIGV2ZW50dHlwZXNcbiAqIEBwcm9wZXJ0eSBFVkVOVF9TVEFSVHxNT1ZFfEVORHxSRUxFQVNFfFRPVUNIXG4gKiBAZmluYWxcbiAqIEB0eXBlIHtTdHJpbmd9XG4gKiBAZGVmYXVsdCAnc3RhcnQnICdjaGFuZ2UnICdtb3ZlJyAnZW5kJyAncmVsZWFzZScgJ3RvdWNoJ1xuICovXG52YXIgRVZFTlRfU1RBUlQgPSBHZXN0dXJlRGV0ZWN0b3IuRVZFTlRfU1RBUlQgPSAnc3RhcnQnO1xudmFyIEVWRU5UX01PVkUgPSBHZXN0dXJlRGV0ZWN0b3IuRVZFTlRfTU9WRSA9ICdtb3ZlJztcbnZhciBFVkVOVF9FTkQgPSBHZXN0dXJlRGV0ZWN0b3IuRVZFTlRfRU5EID0gJ2VuZCc7XG52YXIgRVZFTlRfUkVMRUFTRSA9IEdlc3R1cmVEZXRlY3Rvci5FVkVOVF9SRUxFQVNFID0gJ3JlbGVhc2UnO1xudmFyIEVWRU5UX1RPVUNIID0gR2VzdHVyZURldGVjdG9yLkVWRU5UX1RPVUNIID0gJ3RvdWNoJztcblxuLyoqXG4gKiBpZiB0aGUgd2luZG93IGV2ZW50cyBhcmUgc2V0Li4uXG4gKiBAcHJvcGVydHkgUkVBRFlcbiAqIEB3cml0ZU9uY2VcbiAqIEB0eXBlIHtCb29sZWFufVxuICogQGRlZmF1bHQgZmFsc2VcbiAqL1xuR2VzdHVyZURldGVjdG9yLlJFQURZID0gZmFsc2U7XG5cbi8qKlxuICogcGx1Z2lucyBuYW1lc3BhY2VcbiAqIEBwcm9wZXJ0eSBwbHVnaW5zXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5HZXN0dXJlRGV0ZWN0b3IucGx1Z2lucyA9IEdlc3R1cmVEZXRlY3Rvci5wbHVnaW5zIHx8IHt9O1xuXG4vKipcbiAqIGdlc3R1cmVzIG5hbWVzcGFjZVxuICogc2VlIGAvZ2VzdHVyZXNgIGZvciB0aGUgZGVmaW5pdGlvbnNcbiAqIEBwcm9wZXJ0eSBnZXN0dXJlc1xuICogQHR5cGUge09iamVjdH1cbiAqL1xuR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzID0gR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzIHx8IHt9O1xuXG4vKipcbiAqIHNldHVwIGV2ZW50cyB0byBkZXRlY3QgZ2VzdHVyZXMgb24gdGhlIGRvY3VtZW50XG4gKiB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aGVuIGNyZWF0aW5nIGFuIG5ldyBpbnN0YW5jZVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gc2V0dXAob3B0cykge1xuICBpZiAoR2VzdHVyZURldGVjdG9yLlJFQURZKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gZmluZCB3aGF0IGV2ZW50dHlwZXMgd2UgYWRkIGxpc3RlbmVycyB0b1xuICBFdmVudC5kZXRlcm1pbmVFdmVudFR5cGVzKCk7XG5cbiAgLy8gUmVnaXN0ZXIgYWxsIGdlc3R1cmVzIGluc2lkZSBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZXNcbiAgVXRpbHMuZWFjaChHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZXMsIGZ1bmN0aW9uKGdlc3R1cmUpIHtcbiAgICBEZXRlY3Rpb24ucmVnaXN0ZXIoZ2VzdHVyZSk7XG4gIH0pO1xuXG4gIC8vIEFkZCB0b3VjaCBldmVudHMgb24gdGhlIGRvY3VtZW50XG4gIEV2ZW50Lm9uVG91Y2goR2VzdHVyZURldGVjdG9yLkRPQ1VNRU5ULCBFVkVOVF9NT1ZFLCBEZXRlY3Rpb24uZGV0ZWN0LCBvcHRzKTtcbiAgRXZlbnQub25Ub3VjaChHZXN0dXJlRGV0ZWN0b3IuRE9DVU1FTlQsIEVWRU5UX0VORCwgRGV0ZWN0aW9uLmRldGVjdCwgb3B0cyk7XG5cbiAgLy8gR2VzdHVyZURldGVjdG9yIGlzIHJlYWR5Li4uIVxuICBHZXN0dXJlRGV0ZWN0b3IuUkVBRFkgPSB0cnVlO1xufVxuXG4vKipcbiAqIEBtb2R1bGUgR2VzdHVyZURldGVjdG9yXG4gKlxuICogQGNsYXNzIFV0aWxzXG4gKiBAc3RhdGljXG4gKi9cblV0aWxzID0gR2VzdHVyZURldGVjdG9yLnV0aWxzID0ge1xuICAvKipcbiAgICogZXh0ZW5kIG1ldGhvZCwgY291bGQgYWxzbyBiZSB1c2VkIGZvciBjbG9uaW5nIHdoZW4gYGRlc3RgIGlzIGFuIGVtcHR5IG9iamVjdC5cbiAgICogY2hhbmdlcyB0aGUgZGVzdCBvYmplY3RcbiAgICogQHBhcmFtIHtPYmplY3R9IGRlc3RcbiAgICogQHBhcmFtIHtPYmplY3R9IHNyY1xuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFttZXJnZT1mYWxzZV0gIGRvIGEgbWVyZ2VcbiAgICogQHJldHVybiB7T2JqZWN0fSBkZXN0XG4gICAqL1xuICBleHRlbmQ6IGZ1bmN0aW9uIGV4dGVuZChkZXN0LCBzcmMsIG1lcmdlKSB7XG4gICAgZm9yICh2YXIga2V5IGluIHNyYykge1xuICAgICAgaWYgKHNyYy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIChkZXN0W2tleV0gPT09IHVuZGVmaW5lZCB8fCAhbWVyZ2UpKSB7XG4gICAgICAgIGRlc3Rba2V5XSA9IHNyY1trZXldO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGVzdDtcbiAgfSxcblxuICAvKipcbiAgICogc2ltcGxlIGFkZEV2ZW50TGlzdGVuZXIgd3JhcHBlclxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGhhbmRsZXJcbiAgICovXG4gIG9uOiBmdW5jdGlvbiBvbihlbGVtZW50LCB0eXBlLCBoYW5kbGVyLCBvcHQpIHtcbiAgICB1dGlsLmFkZEV2ZW50TGlzdGVuZXIoZWxlbWVudCwgdHlwZSwgaGFuZGxlciwgb3B0LCB0cnVlKTtcbiAgfSxcblxuICAvKipcbiAgICogc2ltcGxlIHJlbW92ZUV2ZW50TGlzdGVuZXIgd3JhcHBlclxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGhhbmRsZXJcbiAgICovXG4gIG9mZjogZnVuY3Rpb24gb2ZmKGVsZW1lbnQsIHR5cGUsIGhhbmRsZXIsIG9wdCkge1xuICAgIHV0aWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihlbGVtZW50LCB0eXBlLCBoYW5kbGVyLCBvcHQsIHRydWUpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBmb3JFYWNoIG92ZXIgYXJyYXlzIGFuZCBvYmplY3RzXG4gICAqIEBwYXJhbSB7T2JqZWN0fEFycmF5fSBvYmpcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0b3JcbiAgICogQHBhcmFtIHthbnl9IGl0ZXJhdG9yLml0ZW1cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGl0ZXJhdG9yLmluZGV4XG4gICAqIEBwYXJhbSB7T2JqZWN0fEFycmF5fSBpdGVyYXRvci5vYmogdGhlIHNvdXJjZSBvYmplY3RcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbnRleHQgdmFsdWUgdG8gdXNlIGFzIGB0aGlzYCBpbiB0aGUgaXRlcmF0b3JcbiAgICovXG4gIGVhY2g6IGZ1bmN0aW9uIGVhY2gob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIHZhciBpLCBsZW47XG5cbiAgICAvLyBuYXRpdmUgZm9yRWFjaCBvbiBhcnJheXNcbiAgICBpZiAoJ2ZvckVhY2gnIGluIG9iaikge1xuICAgICAgb2JqLmZvckVhY2goaXRlcmF0b3IsIGNvbnRleHQpO1xuICAgICAgLy8gYXJyYXlzXG4gICAgfSBlbHNlIGlmIChvYmoubGVuZ3RoICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGZvciAoaSA9IDAsIGxlbiA9IG9iai5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBpZiAoaXRlcmF0b3IuY2FsbChjb250ZXh0LCBvYmpbaV0sIGksIG9iaikgPT09IGZhbHNlKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBvYmplY3RzXG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAoaSBpbiBvYmopIHtcbiAgICAgICAgaWYgKG9iai5oYXNPd25Qcm9wZXJ0eShpKSAmJlxuICAgICAgICAgIGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgb2JqW2ldLCBpLCBvYmopID09PSBmYWxzZSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogZmluZCBpZiBhIHN0cmluZyBjb250YWlucyB0aGUgc3RyaW5nIHVzaW5nIGluZGV4T2ZcbiAgICogQHBhcmFtIHtTdHJpbmd9IHNyY1xuICAgKiBAcGFyYW0ge1N0cmluZ30gZmluZFxuICAgKiBAcmV0dXJuIHtCb29sZWFufSBmb3VuZFxuICAgKi9cbiAgaW5TdHI6IGZ1bmN0aW9uIGluU3RyKHNyYywgZmluZCkge1xuICAgIHJldHVybiBzcmMuaW5kZXhPZihmaW5kKSA+IC0xO1xuICB9LFxuXG4gIC8qKlxuICAgKiBmaW5kIGlmIGEgYXJyYXkgY29udGFpbnMgdGhlIG9iamVjdCB1c2luZyBpbmRleE9mIG9yIGEgc2ltcGxlIHBvbHlmaWxsXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzcmNcbiAgICogQHBhcmFtIHtTdHJpbmd9IGZpbmRcbiAgICogQHJldHVybiB7Qm9vbGVhbnxOdW1iZXJ9IGZhbHNlIHdoZW4gbm90IGZvdW5kLCBvciB0aGUgaW5kZXhcbiAgICovXG4gIGluQXJyYXk6IGZ1bmN0aW9uIGluQXJyYXkoc3JjLCBmaW5kLCBkZWVwKSB7XG4gICAgaWYgKGRlZXApIHtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBzcmMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHsgLy8gQXJyYXkuZmluZEluZGV4XG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhmaW5kKS5ldmVyeShmdW5jdGlvbihrZXkpIHsgcmV0dXJuIHNyY1tpXVtrZXldID09PSBmaW5kW2tleV07IH0pKSB7XG4gICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiAtMTtcbiAgICB9XG5cbiAgICBpZiAoc3JjLmluZGV4T2YpIHtcbiAgICAgIHJldHVybiBzcmMuaW5kZXhPZihmaW5kKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IHNyYy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBpZiAoc3JjW2ldID09PSBmaW5kKSB7XG4gICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiAtMTtcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIGNvbnZlcnQgYW4gYXJyYXktbGlrZSBvYmplY3QgKGBhcmd1bWVudHNgLCBgdG91Y2hsaXN0YCkgdG8gYW4gYXJyYXlcbiAgICogQHBhcmFtIHtPYmplY3R9IG9ialxuICAgKiBAcmV0dXJuIHtBcnJheX1cbiAgICovXG4gIHRvQXJyYXk6IGZ1bmN0aW9uIHRvQXJyYXkob2JqKSB7XG4gICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKG9iaiwgMCk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIGZpbmQgaWYgYSBub2RlIGlzIGluIHRoZSBnaXZlbiBwYXJlbnRcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gbm9kZVxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBwYXJlbnRcbiAgICogQHJldHVybiB7Qm9vbGVhbn0gZm91bmRcbiAgICovXG4gIGhhc1BhcmVudDogZnVuY3Rpb24gaGFzUGFyZW50KG5vZGUsIHBhcmVudCkge1xuICAgIHdoaWxlIChub2RlKSB7XG4gICAgICBpZiAobm9kZSA9PSBwYXJlbnQpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICBub2RlID0gbm9kZS5wYXJlbnROb2RlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgLyoqXG4gICAqIGdldCB0aGUgY2VudGVyIG9mIGFsbCB0aGUgdG91Y2hlc1xuICAgKiBAcGFyYW0ge0FycmF5fSB0b3VjaGVzXG4gICAqIEByZXR1cm4ge09iamVjdH0gY2VudGVyIGNvbnRhaW5zIGBwYWdlWGAsIGBwYWdlWWAsIGBjbGllbnRYYCBhbmQgYGNsaWVudFlgIHByb3BlcnRpZXNcbiAgICovXG4gIGdldENlbnRlcjogZnVuY3Rpb24gZ2V0Q2VudGVyKHRvdWNoZXMpIHtcbiAgICB2YXIgcGFnZVggPSBbXSxcbiAgICAgICAgcGFnZVkgPSBbXSxcbiAgICAgICAgY2xpZW50WCA9IFtdLFxuICAgICAgICBjbGllbnRZID0gW10sXG4gICAgICAgIG1pbiA9IE1hdGgubWluLFxuICAgICAgICBtYXggPSBNYXRoLm1heDtcblxuICAgIC8vIG5vIG5lZWQgdG8gbG9vcCB3aGVuIG9ubHkgb25lIHRvdWNoXG4gICAgaWYgKHRvdWNoZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBwYWdlWDogdG91Y2hlc1swXS5wYWdlWCxcbiAgICAgICAgcGFnZVk6IHRvdWNoZXNbMF0ucGFnZVksXG4gICAgICAgIGNsaWVudFg6IHRvdWNoZXNbMF0uY2xpZW50WCxcbiAgICAgICAgY2xpZW50WTogdG91Y2hlc1swXS5jbGllbnRZXG4gICAgICB9O1xuICAgIH1cblxuICAgIFV0aWxzLmVhY2godG91Y2hlcywgZnVuY3Rpb24odG91Y2gpIHtcbiAgICAgIHBhZ2VYLnB1c2godG91Y2gucGFnZVgpO1xuICAgICAgcGFnZVkucHVzaCh0b3VjaC5wYWdlWSk7XG4gICAgICBjbGllbnRYLnB1c2godG91Y2guY2xpZW50WCk7XG4gICAgICBjbGllbnRZLnB1c2godG91Y2guY2xpZW50WSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgcGFnZVg6IChtaW4uYXBwbHkoTWF0aCwgcGFnZVgpICsgbWF4LmFwcGx5KE1hdGgsIHBhZ2VYKSkgLyAyLFxuICAgICAgcGFnZVk6IChtaW4uYXBwbHkoTWF0aCwgcGFnZVkpICsgbWF4LmFwcGx5KE1hdGgsIHBhZ2VZKSkgLyAyLFxuICAgICAgY2xpZW50WDogKG1pbi5hcHBseShNYXRoLCBjbGllbnRYKSArIG1heC5hcHBseShNYXRoLCBjbGllbnRYKSkgLyAyLFxuICAgICAgY2xpZW50WTogKG1pbi5hcHBseShNYXRoLCBjbGllbnRZKSArIG1heC5hcHBseShNYXRoLCBjbGllbnRZKSkgLyAyXG4gICAgfTtcbiAgfSxcblxuICAvKipcbiAgICogY2FsY3VsYXRlIHRoZSB2ZWxvY2l0eSBiZXR3ZWVuIHR3byBwb2ludHMuIHVuaXQgaXMgaW4gcHggcGVyIG1zLlxuICAgKiBAcGFyYW0ge051bWJlcn0gZGVsdGFUaW1lXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBkZWx0YVhcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGRlbHRhWVxuICAgKiBAcmV0dXJuIHtPYmplY3R9IHZlbG9jaXR5IGB4YCBhbmQgYHlgXG4gICAqL1xuICBnZXRWZWxvY2l0eTogZnVuY3Rpb24gZ2V0VmVsb2NpdHkoZGVsdGFUaW1lLCBkZWx0YVgsIGRlbHRhWSkge1xuICAgIHJldHVybiB7XG4gICAgICB4OiBNYXRoLmFicyhkZWx0YVggLyBkZWx0YVRpbWUpIHx8IDAsXG4gICAgICB5OiBNYXRoLmFicyhkZWx0YVkgLyBkZWx0YVRpbWUpIHx8IDBcbiAgICB9O1xuICB9LFxuXG4gIC8qKlxuICAgKiBjYWxjdWxhdGUgdGhlIGFuZ2xlIGJldHdlZW4gdHdvIGNvb3JkaW5hdGVzXG4gICAqIEBwYXJhbSB7VG91Y2h9IHRvdWNoMVxuICAgKiBAcGFyYW0ge1RvdWNofSB0b3VjaDJcbiAgICogQHJldHVybiB7TnVtYmVyfSBhbmdsZVxuICAgKi9cbiAgZ2V0QW5nbGU6IGZ1bmN0aW9uIGdldEFuZ2xlKHRvdWNoMSwgdG91Y2gyKSB7XG4gICAgdmFyIHggPSB0b3VjaDIuY2xpZW50WCAtIHRvdWNoMS5jbGllbnRYLFxuICAgICAgICB5ID0gdG91Y2gyLmNsaWVudFkgLSB0b3VjaDEuY2xpZW50WTtcblxuICAgIHJldHVybiBNYXRoLmF0YW4yKHksIHgpICogMTgwIC8gTWF0aC5QSTtcbiAgfSxcblxuICAvKipcbiAgICogZG8gYSBzbWFsbCBjb21wYXJpc29uIHRvIGdldCB0aGUgZGlyZWN0aW9uIGJldHdlZW4gdHdvIHRvdWNoZXMuXG4gICAqIEBwYXJhbSB7VG91Y2h9IHRvdWNoMVxuICAgKiBAcGFyYW0ge1RvdWNofSB0b3VjaDJcbiAgICogQHJldHVybiB7U3RyaW5nfSBkaXJlY3Rpb24gbWF0Y2hlcyBgRElSRUNUSU9OX0xFRlR8UklHSFR8VVB8RE9XTmBcbiAgICovXG4gIGdldERpcmVjdGlvbjogZnVuY3Rpb24gZ2V0RGlyZWN0aW9uKHRvdWNoMSwgdG91Y2gyKSB7XG4gICAgdmFyIHggPSBNYXRoLmFicyh0b3VjaDEuY2xpZW50WCAtIHRvdWNoMi5jbGllbnRYKSxcbiAgICAgICAgeSA9IE1hdGguYWJzKHRvdWNoMS5jbGllbnRZIC0gdG91Y2gyLmNsaWVudFkpO1xuXG4gICAgaWYgKHggPj0geSkge1xuICAgICAgcmV0dXJuIHRvdWNoMS5jbGllbnRYIC0gdG91Y2gyLmNsaWVudFggPiAwID8gRElSRUNUSU9OX0xFRlQgOiBESVJFQ1RJT05fUklHSFQ7XG4gICAgfVxuICAgIHJldHVybiB0b3VjaDEuY2xpZW50WSAtIHRvdWNoMi5jbGllbnRZID4gMCA/IERJUkVDVElPTl9VUCA6IERJUkVDVElPTl9ET1dOO1xuICB9LFxuXG4gIC8qKlxuICAgKiBjYWxjdWxhdGUgdGhlIGRpc3RhbmNlIGJldHdlZW4gdHdvIHRvdWNoZXNcbiAgICogQHBhcmFtIHtUb3VjaH10b3VjaDFcbiAgICogQHBhcmFtIHtUb3VjaH0gdG91Y2gyXG4gICAqIEByZXR1cm4ge051bWJlcn0gZGlzdGFuY2VcbiAgICovXG4gIGdldERpc3RhbmNlOiBmdW5jdGlvbiBnZXREaXN0YW5jZSh0b3VjaDEsIHRvdWNoMikge1xuICAgIHZhciB4ID0gdG91Y2gyLmNsaWVudFggLSB0b3VjaDEuY2xpZW50WCxcbiAgICAgICAgeSA9IHRvdWNoMi5jbGllbnRZIC0gdG91Y2gxLmNsaWVudFk7XG5cbiAgICByZXR1cm4gTWF0aC5zcXJ0KCh4ICogeCkgKyAoeSAqIHkpKTtcbiAgfSxcblxuICAvKipcbiAgICogY2FsY3VsYXRlIHRoZSBzY2FsZSBmYWN0b3IgYmV0d2VlbiB0d28gdG91Y2hMaXN0c1xuICAgKiBubyBzY2FsZSBpcyAxLCBhbmQgZ29lcyBkb3duIHRvIDAgd2hlbiBwaW5jaGVkIHRvZ2V0aGVyLCBhbmQgYmlnZ2VyIHdoZW4gcGluY2hlZCBvdXRcbiAgICogQHBhcmFtIHtBcnJheX0gc3RhcnQgYXJyYXkgb2YgdG91Y2hlc1xuICAgKiBAcGFyYW0ge0FycmF5fSBlbmQgYXJyYXkgb2YgdG91Y2hlc1xuICAgKiBAcmV0dXJuIHtOdW1iZXJ9IHNjYWxlXG4gICAqL1xuICBnZXRTY2FsZTogZnVuY3Rpb24gZ2V0U2NhbGUoc3RhcnQsIGVuZCkge1xuICAgIC8vIG5lZWQgdHdvIGZpbmdlcnMuLi5cbiAgICBpZiAoc3RhcnQubGVuZ3RoID49IDIgJiYgZW5kLmxlbmd0aCA+PSAyKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXREaXN0YW5jZShlbmRbMF0sIGVuZFsxXSkgLyB0aGlzLmdldERpc3RhbmNlKHN0YXJ0WzBdLCBzdGFydFsxXSk7XG4gICAgfVxuICAgIHJldHVybiAxO1xuICB9LFxuXG4gIC8qKlxuICAgKiBjYWxjdWxhdGUgdGhlIHJvdGF0aW9uIGRlZ3JlZXMgYmV0d2VlbiB0d28gdG91Y2hMaXN0c1xuICAgKiBAcGFyYW0ge0FycmF5fSBzdGFydCBhcnJheSBvZiB0b3VjaGVzXG4gICAqIEBwYXJhbSB7QXJyYXl9IGVuZCBhcnJheSBvZiB0b3VjaGVzXG4gICAqIEByZXR1cm4ge051bWJlcn0gcm90YXRpb25cbiAgICovXG4gIGdldFJvdGF0aW9uOiBmdW5jdGlvbiBnZXRSb3RhdGlvbihzdGFydCwgZW5kKSB7XG4gICAgLy8gbmVlZCB0d28gZmluZ2Vyc1xuICAgIGlmIChzdGFydC5sZW5ndGggPj0gMiAmJiBlbmQubGVuZ3RoID49IDIpIHtcbiAgICAgIHJldHVybiB0aGlzLmdldEFuZ2xlKGVuZFsxXSwgZW5kWzBdKSAtIHRoaXMuZ2V0QW5nbGUoc3RhcnRbMV0sIHN0YXJ0WzBdKTtcbiAgICB9XG4gICAgcmV0dXJuIDA7XG4gIH0sXG5cbiAgLyoqXG4gICAqIGZpbmQgb3V0IGlmIHRoZSBkaXJlY3Rpb24gaXMgdmVydGljYWwgICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBkaXJlY3Rpb24gbWF0Y2hlcyBgRElSRUNUSU9OX1VQfERPV05gXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59IGlzX3ZlcnRpY2FsXG4gICAqL1xuICBpc1ZlcnRpY2FsOiBmdW5jdGlvbiBpc1ZlcnRpY2FsKGRpcmVjdGlvbikge1xuICAgIHJldHVybiBkaXJlY3Rpb24gPT0gRElSRUNUSU9OX1VQIHx8IGRpcmVjdGlvbiA9PSBESVJFQ1RJT05fRE9XTjtcbiAgfSxcblxuICAvKipcbiAgICogc2V0IGNzcyBwcm9wZXJ0aWVzIHdpdGggdGhlaXIgcHJlZml4ZXNcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcFxuICAgKiBAcGFyYW0ge1N0cmluZ30gdmFsdWVcbiAgICogQHBhcmFtIHtCb29sZWFufSBbdG9nZ2xlPXRydWVdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBzZXRQcmVmaXhlZENzczogZnVuY3Rpb24gc2V0UHJlZml4ZWRDc3MoZWxlbWVudCwgcHJvcCwgdmFsdWUsIHRvZ2dsZSkge1xuICAgIHZhciBwcmVmaXhlcyA9IFsnJywgJ1dlYmtpdCcsICdNb3onLCAnTycsICdtcyddO1xuICAgIHByb3AgPSBVdGlscy50b0NhbWVsQ2FzZShwcm9wKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJlZml4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBwID0gcHJvcDtcbiAgICAgIC8vIHByZWZpeGVzXG4gICAgICBpZiAocHJlZml4ZXNbaV0pIHtcbiAgICAgICAgcCA9IHByZWZpeGVzW2ldICsgcC5zbGljZSgwLCAxKS50b1VwcGVyQ2FzZSgpICsgcC5zbGljZSgxKTtcbiAgICAgIH1cblxuICAgICAgLy8gdGVzdCB0aGUgc3R5bGVcbiAgICAgIGlmIChwIGluIGVsZW1lbnQuc3R5bGUpIHtcbiAgICAgICAgZWxlbWVudC5zdHlsZVtwXSA9ICh0b2dnbGUgPT09IG51bGwgfHwgdG9nZ2xlKSAmJiB2YWx1ZSB8fCAnJztcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiB0b2dnbGUgYnJvd3NlciBkZWZhdWx0IGJlaGF2aW9yIGJ5IHNldHRpbmcgY3NzIHByb3BlcnRpZXMuXG4gICAqIGB1c2VyU2VsZWN0PSdub25lJ2AgYWxzbyBzZXRzIGBlbGVtZW50Lm9uc2VsZWN0c3RhcnRgIHRvIGZhbHNlXG4gICAqIGB1c2VyRHJhZz0nbm9uZSdgIGFsc28gc2V0cyBgZWxlbWVudC5vbmRyYWdzdGFydGAgdG8gZmFsc2VcbiAgICpcbiAgICogQHBhcmFtIHtIdG1sRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge09iamVjdH0gcHJvcHNcbiAgICogQHBhcmFtIHtCb29sZWFufSBbdG9nZ2xlPXRydWVdXG4gICAqL1xuICB0b2dnbGVCZWhhdmlvcjogZnVuY3Rpb24gdG9nZ2xlQmVoYXZpb3IoZWxlbWVudCwgcHJvcHMsIHRvZ2dsZSkge1xuICAgIGlmICghcHJvcHMgfHwgIWVsZW1lbnQgfHwgIWVsZW1lbnQuc3R5bGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBzZXQgdGhlIGNzcyBwcm9wZXJ0aWVzXG4gICAgVXRpbHMuZWFjaChwcm9wcywgZnVuY3Rpb24odmFsdWUsIHByb3ApIHtcbiAgICAgIFV0aWxzLnNldFByZWZpeGVkQ3NzKGVsZW1lbnQsIHByb3AsIHZhbHVlLCB0b2dnbGUpO1xuICAgIH0pO1xuXG4gICAgdmFyIGZhbHNlRm4gPSB0b2dnbGUgJiYgZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcblxuICAgIC8vIGFsc28gdGhlIGRpc2FibGUgb25zZWxlY3RzdGFydFxuICAgIGlmIChwcm9wcy51c2VyU2VsZWN0ID09ICdub25lJykge1xuICAgICAgZWxlbWVudC5vbnNlbGVjdHN0YXJ0ID0gZmFsc2VGbjtcbiAgICB9XG4gICAgLy8gYW5kIGRpc2FibGUgb25kcmFnc3RhcnRcbiAgICBpZiAocHJvcHMudXNlckRyYWcgPT0gJ25vbmUnKSB7XG4gICAgICBlbGVtZW50Lm9uZHJhZ3N0YXJ0ID0gZmFsc2VGbjtcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIGNvbnZlcnQgYSBzdHJpbmcgd2l0aCB1bmRlcnNjb3JlcyB0byBjYW1lbENhc2VcbiAgICogc28gcHJldmVudF9kZWZhdWx0IGJlY29tZXMgcHJldmVudERlZmF1bHRcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN0clxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IGNhbWVsQ2FzZVN0clxuICAgKi9cbiAgdG9DYW1lbENhc2U6IGZ1bmN0aW9uIHRvQ2FtZWxDYXNlKHN0cikge1xuICAgIHJldHVybiBzdHIucmVwbGFjZSgvW18tXShbYS16XSkvZywgZnVuY3Rpb24ocykge1xuICAgICAgcmV0dXJuIHNbMV0udG9VcHBlckNhc2UoKTtcbiAgICB9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBtb2R1bGUgR2VzdHVyZURldGVjdG9yXG4gKi9cbi8qKlxuICogQGNsYXNzIEV2ZW50XG4gKiBAc3RhdGljXG4gKi9cbkV2ZW50ID0gR2VzdHVyZURldGVjdG9yLmV2ZW50ID0ge1xuICAvKipcbiAgICogd2hlbiB0b3VjaCBldmVudHMgaGF2ZSBiZWVuIGZpcmVkLCB0aGlzIGlzIHRydWVcbiAgICogdGhpcyBpcyB1c2VkIHRvIHN0b3AgbW91c2UgZXZlbnRzXG4gICAqIEBwcm9wZXJ0eSBwcmV2ZW50X21vdXNlZXZlbnRzXG4gICAqIEBwcml2YXRlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKi9cbiAgcHJldmVudE1vdXNlRXZlbnRzOiBmYWxzZSxcblxuICAvKipcbiAgICogaWYgRVZFTlRfU1RBUlQgaGFzIGJlZW4gZmlyZWRcbiAgICogQHByb3BlcnR5IHN0YXJ0ZWRcbiAgICogQHByaXZhdGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqL1xuICBzdGFydGVkOiBmYWxzZSxcblxuICAvKipcbiAgICogd2hlbiB0aGUgbW91c2UgaXMgaG9sZCBkb3duLCB0aGlzIGlzIHRydWVcbiAgICogQHByb3BlcnR5IHNob3VsZF9kZXRlY3RcbiAgICogQHByaXZhdGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqL1xuICBzaG91bGREZXRlY3Q6IGZhbHNlLFxuXG4gIC8qKlxuICAgKiBzaW1wbGUgZXZlbnQgYmluZGVyIHdpdGggYSBob29rIGFuZCBzdXBwb3J0IGZvciBtdWx0aXBsZSB0eXBlc1xuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGhhbmRsZXJcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtob29rXVxuICAgKiBAcGFyYW0ge09iamVjdH0gaG9vay50eXBlXG4gICAqL1xuICBvbjogZnVuY3Rpb24gb24oZWxlbWVudCwgdHlwZSwgaGFuZGxlciwgb3B0LCBob29rKSB7XG4gICAgdmFyIHR5cGVzID0gdHlwZS5zcGxpdCgnICcpO1xuICAgIFV0aWxzLmVhY2godHlwZXMsIGZ1bmN0aW9uKHR5cGUpIHtcbiAgICAgIFV0aWxzLm9uKGVsZW1lbnQsIHR5cGUsIGhhbmRsZXIsIG9wdCk7XG4gICAgICBob29rICYmIGhvb2sodHlwZSk7XG4gICAgfSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIHNpbXBsZSBldmVudCB1bmJpbmRlciB3aXRoIGEgaG9vayBhbmQgc3VwcG9ydCBmb3IgbXVsdGlwbGUgdHlwZXNcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge1N0cmluZ30gdHlwZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBoYW5kbGVyXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0XVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaG9va11cbiAgICogQHBhcmFtIHtPYmplY3R9IGhvb2sudHlwZVxuICAgKi9cbiAgb2ZmOiBmdW5jdGlvbiBvZmYoZWxlbWVudCwgdHlwZSwgaGFuZGxlciwgb3B0LCBob29rKSB7XG4gICAgdmFyIHR5cGVzID0gdHlwZS5zcGxpdCgnICcpO1xuICAgIFV0aWxzLmVhY2godHlwZXMsIGZ1bmN0aW9uKHR5cGUpIHtcbiAgICAgIFV0aWxzLm9mZihlbGVtZW50LCB0eXBlLCBoYW5kbGVyLCBvcHQpO1xuICAgICAgaG9vayAmJiBob29rKHR5cGUpO1xuICAgIH0pO1xuICB9LFxuXG4gIC8qKlxuICAgKiB0aGUgY29yZSB0b3VjaCBldmVudCBoYW5kbGVyLlxuICAgKiB0aGlzIGZpbmRzIG91dCBpZiB3ZSBzaG91bGQgdG8gZGV0ZWN0IGdlc3R1cmVzXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAgICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50VHlwZSBtYXRjaGVzIGBFVkVOVF9TVEFSVHxNT1ZFfEVORGBcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaGFuZGxlclxuICAgKiBAcmV0dXJuIG9uVG91Y2hIYW5kbGVyIHtGdW5jdGlvbn0gdGhlIGNvcmUgZXZlbnQgaGFuZGxlclxuICAgKi9cbiAgb25Ub3VjaDogZnVuY3Rpb24gb25Ub3VjaChlbGVtZW50LCBldmVudFR5cGUsIGhhbmRsZXIsIG9wdCkge1xuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIHZhciBvblRvdWNoSGFuZGxlciA9IGZ1bmN0aW9uIG9uVG91Y2hIYW5kbGVyKGV2KSB7XG4gICAgICB2YXIgc3JjVHlwZSA9IGV2LnR5cGUudG9Mb3dlckNhc2UoKSxcbiAgICAgICAgICBpc1BvaW50ZXIgPSBHZXN0dXJlRGV0ZWN0b3IuSEFTX1BPSU5URVJFVkVOVFMsXG4gICAgICAgICAgaXNNb3VzZSA9IFV0aWxzLmluU3RyKHNyY1R5cGUsICdtb3VzZScpLFxuICAgICAgICAgIHRyaWdnZXJUeXBlO1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgaW4gYSBtb3VzZWV2ZW50LCBidXQgdGhlcmUgaGFzIGJlZW4gYSB0b3VjaGV2ZW50IHRyaWdnZXJlZCBpbiB0aGlzIHNlc3Npb25cbiAgICAgIC8vIHdlIHdhbnQgdG8gZG8gbm90aGluZy4gc2ltcGx5IGJyZWFrIG91dCBvZiB0aGUgZXZlbnQuXG4gICAgICBpZiAoaXNNb3VzZSAmJiBzZWxmLnByZXZlbnRNb3VzZUV2ZW50cykge1xuICAgICAgICByZXR1cm47XG5cbiAgICAgICAgLy8gbW91c2VidXR0b24gbXVzdCBiZSBkb3duXG4gICAgICB9IGVsc2UgaWYgKGlzTW91c2UgJiYgZXZlbnRUeXBlID09IEVWRU5UX1NUQVJUICYmIGV2LmJ1dHRvbiA9PT0gMCkge1xuICAgICAgICBzZWxmLnByZXZlbnRNb3VzZUV2ZW50cyA9IGZhbHNlO1xuICAgICAgICBzZWxmLnNob3VsZERldGVjdCA9IHRydWU7XG4gICAgICB9IGVsc2UgaWYgKGlzUG9pbnRlciAmJiBldmVudFR5cGUgPT0gRVZFTlRfU1RBUlQpIHtcbiAgICAgICAgc2VsZi5zaG91bGREZXRlY3QgPSAoZXYuYnV0dG9ucyA9PT0gMSB8fCBQb2ludGVyRXZlbnQubWF0Y2hUeXBlKFBPSU5URVJfVE9VQ0gsIGV2KSk7XG4gICAgICAgIC8vIGp1c3QgYSB2YWxpZCBzdGFydCBldmVudCwgYnV0IG5vIG1vdXNlXG4gICAgICB9IGVsc2UgaWYgKCFpc01vdXNlICYmIGV2ZW50VHlwZSA9PSBFVkVOVF9TVEFSVCkge1xuICAgICAgICBzZWxmLnByZXZlbnRNb3VzZUV2ZW50cyA9IHRydWU7XG4gICAgICAgIHNlbGYuc2hvdWxkRGV0ZWN0ID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgLy8gdXBkYXRlIHRoZSBwb2ludGVyIGV2ZW50IGJlZm9yZSBlbnRlcmluZyB0aGUgZGV0ZWN0aW9uXG4gICAgICBpZiAoaXNQb2ludGVyICYmIGV2ZW50VHlwZSAhPSBFVkVOVF9FTkQpIHtcbiAgICAgICAgUG9pbnRlckV2ZW50LnVwZGF0ZVBvaW50ZXIoZXZlbnRUeXBlLCBldik7XG4gICAgICB9XG5cbiAgICAgIC8vIHdlIGFyZSBpbiBhIHRvdWNoL2Rvd24gc3RhdGUsIHNvIGFsbG93ZWQgZGV0ZWN0aW9uIG9mIGdlc3R1cmVzXG4gICAgICBpZiAoc2VsZi5zaG91bGREZXRlY3QpIHtcbiAgICAgICAgdHJpZ2dlclR5cGUgPSBzZWxmLmRvRGV0ZWN0LmNhbGwoc2VsZiwgZXYsIGV2ZW50VHlwZSwgZWxlbWVudCwgaGFuZGxlcik7XG4gICAgICB9XG5cbiAgICAgIC8vIC4uLmFuZCB3ZSBhcmUgZG9uZSB3aXRoIHRoZSBkZXRlY3Rpb25cbiAgICAgIC8vIHNvIHJlc2V0IGV2ZXJ5dGhpbmcgdG8gc3RhcnQgZWFjaCBkZXRlY3Rpb24gdG90YWxseSBmcmVzaFxuICAgICAgaWYgKHRyaWdnZXJUeXBlID09IEVWRU5UX0VORCkge1xuICAgICAgICBzZWxmLnByZXZlbnRNb3VzZUV2ZW50cyA9IGZhbHNlO1xuICAgICAgICBzZWxmLnNob3VsZERldGVjdCA9IGZhbHNlO1xuICAgICAgICBQb2ludGVyRXZlbnQucmVzZXQoKTtcbiAgICAgICAgLy8gdXBkYXRlIHRoZSBwb2ludGVyZXZlbnQgb2JqZWN0IGFmdGVyIHRoZSBkZXRlY3Rpb25cbiAgICAgIH1cblxuICAgICAgaWYgKGlzUG9pbnRlciAmJiBldmVudFR5cGUgPT0gRVZFTlRfRU5EKSB7XG4gICAgICAgIFBvaW50ZXJFdmVudC51cGRhdGVQb2ludGVyKGV2ZW50VHlwZSwgZXYpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLm9uKGVsZW1lbnQsIEVWRU5UX1RZUEVTW2V2ZW50VHlwZV0sIG9uVG91Y2hIYW5kbGVyLCBvcHQpO1xuICAgIHJldHVybiBvblRvdWNoSGFuZGxlcjtcbiAgfSxcblxuICAvKipcbiAgICogdGhlIGNvcmUgZGV0ZWN0aW9uIG1ldGhvZFxuICAgKiB0aGlzIGZpbmRzIG91dCB3aGF0IEdlc3R1cmVEZXRlY3Rvci10b3VjaC1ldmVudHMgdG8gdHJpZ2dlclxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50VHlwZSBtYXRjaGVzIGBFVkVOVF9TVEFSVHxNT1ZFfEVORGBcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBoYW5kbGVyXG4gICAqIEByZXR1cm4ge1N0cmluZ30gdHJpZ2dlclR5cGUgbWF0Y2hlcyBgRVZFTlRfU1RBUlR8TU9WRXxFTkRgXG4gICAqL1xuICBkb0RldGVjdDogZnVuY3Rpb24gZG9EZXRlY3QoZXYsIGV2ZW50VHlwZSwgZWxlbWVudCwgaGFuZGxlcikge1xuICAgIHZhciB0b3VjaExpc3QgPSB0aGlzLmdldFRvdWNoTGlzdChldiwgZXZlbnRUeXBlKTtcbiAgICB2YXIgdG91Y2hMaXN0TGVuZ3RoID0gdG91Y2hMaXN0Lmxlbmd0aDtcbiAgICB2YXIgdHJpZ2dlclR5cGUgPSBldmVudFR5cGU7XG4gICAgdmFyIHRyaWdnZXJDaGFuZ2UgPSB0b3VjaExpc3QudHJpZ2dlcjsgLy8gdXNlZCBieSBmYWtlTXVsdGl0b3VjaCBwbHVnaW5cbiAgICB2YXIgY2hhbmdlZExlbmd0aCA9IHRvdWNoTGlzdExlbmd0aDtcblxuICAgIC8vIGF0IGVhY2ggdG91Y2hzdGFydC1saWtlIGV2ZW50IHdlIHdhbnQgYWxzbyB3YW50IHRvIHRyaWdnZXIgYSBUT1VDSCBldmVudC4uLlxuICAgIGlmIChldmVudFR5cGUgPT0gRVZFTlRfU1RBUlQpIHtcbiAgICAgIHRyaWdnZXJDaGFuZ2UgPSBFVkVOVF9UT1VDSDtcbiAgICAgIC8vIC4uLnRoZSBzYW1lIGZvciBhIHRvdWNoZW5kLWxpa2UgZXZlbnRcbiAgICB9IGVsc2UgaWYgKGV2ZW50VHlwZSA9PSBFVkVOVF9FTkQpIHtcbiAgICAgIHRyaWdnZXJDaGFuZ2UgPSBFVkVOVF9SRUxFQVNFO1xuXG4gICAgICAvLyBrZWVwIHRyYWNrIG9mIGhvdyBtYW55IHRvdWNoZXMgaGF2ZSBiZWVuIHJlbW92ZWRcbiAgICAgIGNoYW5nZWRMZW5ndGggPSB0b3VjaExpc3QubGVuZ3RoIC0gKChldi5jaGFuZ2VkVG91Y2hlcykgPyBldi5jaGFuZ2VkVG91Y2hlcy5sZW5ndGggOiAxKTtcbiAgICB9XG5cbiAgICAvLyBhZnRlciB0aGVyZSBhcmUgc3RpbGwgdG91Y2hlcyBvbiB0aGUgc2NyZWVuLFxuICAgIC8vIHdlIGp1c3Qgd2FudCB0byB0cmlnZ2VyIGEgTU9WRSBldmVudC4gc28gY2hhbmdlIHRoZSBTVEFSVCBvciBFTkQgdG8gYSBNT1ZFXG4gICAgLy8gYnV0IG9ubHkgYWZ0ZXIgZGV0ZWN0aW9uIGhhcyBiZWVuIHN0YXJ0ZWQsIHRoZSBmaXJzdCB0aW1lIHdlIGFjdHVhbGx5IHdhbnQgYSBTVEFSVFxuICAgIGlmIChjaGFuZ2VkTGVuZ3RoID4gMCAmJiB0aGlzLnN0YXJ0ZWQpIHtcbiAgICAgIHRyaWdnZXJUeXBlID0gRVZFTlRfTU9WRTtcbiAgICB9XG5cbiAgICAvLyBkZXRlY3Rpb24gaGFzIGJlZW4gc3RhcnRlZCwgd2Uga2VlcCB0cmFjayBvZiB0aGlzLCBzZWUgYWJvdmVcbiAgICB0aGlzLnN0YXJ0ZWQgPSB0cnVlO1xuXG4gICAgLy8gZ2VuZXJhdGUgc29tZSBldmVudCBkYXRhLCBzb21lIGJhc2ljIGluZm9ybWF0aW9uXG4gICAgdmFyIGV2RGF0YSA9IHRoaXMuY29sbGVjdEV2ZW50RGF0YShlbGVtZW50LCB0cmlnZ2VyVHlwZSwgdG91Y2hMaXN0LCBldik7XG5cbiAgICAvLyB0cmlnZ2VyIHRoZSB0cmlnZ2VyVHlwZSBldmVudCBiZWZvcmUgdGhlIGNoYW5nZSAoVE9VQ0gsIFJFTEVBU0UpIGV2ZW50c1xuICAgIC8vIGJ1dCB0aGUgRU5EIGV2ZW50IHNob3VsZCBiZSBhdCBsYXN0XG4gICAgaWYgKGV2ZW50VHlwZSAhPSBFVkVOVF9FTkQpIHtcbiAgICAgIGhhbmRsZXIuY2FsbChEZXRlY3Rpb24sIGV2RGF0YSk7XG4gICAgfVxuXG4gICAgLy8gdHJpZ2dlciBhIGNoYW5nZSAoVE9VQ0gsIFJFTEVBU0UpIGV2ZW50LCB0aGlzIG1lYW5zIHRoZSBsZW5ndGggb2YgdGhlIHRvdWNoZXMgY2hhbmdlZFxuICAgIGlmICh0cmlnZ2VyQ2hhbmdlKSB7XG4gICAgICBldkRhdGEuY2hhbmdlZExlbmd0aCA9IGNoYW5nZWRMZW5ndGg7XG4gICAgICBldkRhdGEuZXZlbnRUeXBlID0gdHJpZ2dlckNoYW5nZTtcblxuICAgICAgaGFuZGxlci5jYWxsKERldGVjdGlvbiwgZXZEYXRhKTtcblxuICAgICAgZXZEYXRhLmV2ZW50VHlwZSA9IHRyaWdnZXJUeXBlO1xuICAgICAgZGVsZXRlIGV2RGF0YS5jaGFuZ2VkTGVuZ3RoO1xuICAgIH1cblxuICAgIC8vIHRyaWdnZXIgdGhlIEVORCBldmVudFxuICAgIGlmICh0cmlnZ2VyVHlwZSA9PSBFVkVOVF9FTkQpIHtcbiAgICAgIGhhbmRsZXIuY2FsbChEZXRlY3Rpb24sIGV2RGF0YSk7XG5cbiAgICAgIC8vIC4uLmFuZCB3ZSBhcmUgZG9uZSB3aXRoIHRoZSBkZXRlY3Rpb25cbiAgICAgIC8vIHNvIHJlc2V0IGV2ZXJ5dGhpbmcgdG8gc3RhcnQgZWFjaCBkZXRlY3Rpb24gdG90YWxseSBmcmVzaFxuICAgICAgdGhpcy5zdGFydGVkID0gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRyaWdnZXJUeXBlO1xuICB9LFxuXG4gIC8qKlxuICAgKiB3ZSBoYXZlIGRpZmZlcmVudCBldmVudHMgZm9yIGVhY2ggZGV2aWNlL2Jyb3dzZXJcbiAgICogZGV0ZXJtaW5lIHdoYXQgd2UgbmVlZCBhbmQgc2V0IHRoZW0gaW4gdGhlIEVWRU5UX1RZUEVTIGNvbnN0YW50XG4gICAqIHRoZSBgb25Ub3VjaGAgbWV0aG9kIGlzIGJpbmQgdG8gdGhlc2UgcHJvcGVydGllcy5cbiAgICogQHJldHVybiB7T2JqZWN0fSBldmVudHNcbiAgICovXG4gIGRldGVybWluZUV2ZW50VHlwZXM6IGZ1bmN0aW9uIGRldGVybWluZUV2ZW50VHlwZXMoKSB7XG4gICAgdmFyIHR5cGVzO1xuICAgIGlmIChHZXN0dXJlRGV0ZWN0b3IuSEFTX1BPSU5URVJFVkVOVFMpIHtcbiAgICAgIGlmICh3aW5kb3cuUG9pbnRlckV2ZW50KSB7XG4gICAgICAgIHR5cGVzID0gW1xuICAgICAgICAgICdwb2ludGVyZG93bicsXG4gICAgICAgICAgJ3BvaW50ZXJtb3ZlJyxcbiAgICAgICAgICAncG9pbnRlcnVwIHBvaW50ZXJjYW5jZWwgbG9zdHBvaW50ZXJjYXB0dXJlJ1xuICAgICAgICBdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHlwZXMgPSBbXG4gICAgICAgICAgJ01TUG9pbnRlckRvd24nLFxuICAgICAgICAgICdNU1BvaW50ZXJNb3ZlJyxcbiAgICAgICAgICAnTVNQb2ludGVyVXAgTVNQb2ludGVyQ2FuY2VsIE1TTG9zdFBvaW50ZXJDYXB0dXJlJ1xuICAgICAgICBdO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoR2VzdHVyZURldGVjdG9yLk5PX01PVVNFRVZFTlRTKSB7XG4gICAgICB0eXBlcyA9IFtcbiAgICAgICAgJ3RvdWNoc3RhcnQnLFxuICAgICAgICAndG91Y2htb3ZlJyxcbiAgICAgICAgJ3RvdWNoZW5kIHRvdWNoY2FuY2VsJ1xuICAgICAgXTtcbiAgICB9IGVsc2Uge1xuICAgICAgdHlwZXMgPSBbXG4gICAgICAgICd0b3VjaHN0YXJ0IG1vdXNlZG93bicsXG4gICAgICAgICd0b3VjaG1vdmUgbW91c2Vtb3ZlJyxcbiAgICAgICAgJ3RvdWNoZW5kIHRvdWNoY2FuY2VsIG1vdXNldXAnXG4gICAgICBdO1xuICAgIH1cblxuICAgIEVWRU5UX1RZUEVTW0VWRU5UX1NUQVJUXSA9IHR5cGVzWzBdO1xuICAgIEVWRU5UX1RZUEVTW0VWRU5UX01PVkVdID0gdHlwZXNbMV07XG4gICAgRVZFTlRfVFlQRVNbRVZFTlRfRU5EXSA9IHR5cGVzWzJdO1xuICAgIHJldHVybiBFVkVOVF9UWVBFUztcbiAgfSxcblxuICAvKipcbiAgICogY3JlYXRlIHRvdWNoTGlzdCBkZXBlbmRpbmcgb24gdGhlIGV2ZW50XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKiBAcGFyYW0ge1N0cmluZ30gZXZlbnRUeXBlXG4gICAqIEByZXR1cm4ge0FycmF5fSB0b3VjaGVzXG4gICAqL1xuICBnZXRUb3VjaExpc3Q6IGZ1bmN0aW9uIGdldFRvdWNoTGlzdChldiwgZXZlbnRUeXBlKSB7XG4gICAgLy8gZ2V0IHRoZSBmYWtlIHBvaW50ZXJFdmVudCB0b3VjaGxpc3RcbiAgICBpZiAoR2VzdHVyZURldGVjdG9yLkhBU19QT0lOVEVSRVZFTlRTKSB7XG4gICAgICByZXR1cm4gUG9pbnRlckV2ZW50LmdldFRvdWNoTGlzdCgpO1xuICAgIH1cblxuICAgIC8vIGdldCB0aGUgdG91Y2hsaXN0XG4gICAgaWYgKGV2LnRvdWNoZXMpIHtcbiAgICAgIGlmIChldmVudFR5cGUgPT0gRVZFTlRfTU9WRSkge1xuICAgICAgICByZXR1cm4gZXYudG91Y2hlcztcbiAgICAgIH1cblxuICAgICAgdmFyIGlkZW50aWZpZXJzID0gW107XG4gICAgICB2YXIgY29uY2F0ID0gW10uY29uY2F0KFV0aWxzLnRvQXJyYXkoZXYudG91Y2hlcyksIFV0aWxzLnRvQXJyYXkoZXYuY2hhbmdlZFRvdWNoZXMpKTtcbiAgICAgIHZhciB0b3VjaExpc3QgPSBbXTtcblxuICAgICAgVXRpbHMuZWFjaChjb25jYXQsIGZ1bmN0aW9uKHRvdWNoKSB7XG4gICAgICAgIGlmIChVdGlscy5pbkFycmF5KGlkZW50aWZpZXJzLCB0b3VjaC5pZGVudGlmaWVyKSA9PT0gLTEpIHtcbiAgICAgICAgICB0b3VjaExpc3QucHVzaCh0b3VjaCk7XG4gICAgICAgIH1cbiAgICAgICAgaWRlbnRpZmllcnMucHVzaCh0b3VjaC5pZGVudGlmaWVyKTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gdG91Y2hMaXN0O1xuICAgIH1cblxuICAgIC8vIG1ha2UgZmFrZSB0b3VjaExpc3QgZnJvbSBtb3VzZSBwb3NpdGlvblxuICAgIGV2LmlkZW50aWZpZXIgPSAxO1xuICAgIHJldHVybiBbZXZdO1xuICB9LFxuXG4gIC8qKlxuICAgKiBjb2xsZWN0IGJhc2ljIGV2ZW50IGRhdGFcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge1N0cmluZ30gZXZlbnRUeXBlIG1hdGNoZXMgYEVWRU5UX1NUQVJUfE1PVkV8RU5EYFxuICAgKiBAcGFyYW0ge0FycmF5fSB0b3VjaGVzXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKiBAcmV0dXJuIHtPYmplY3R9IGV2XG4gICAqL1xuICBjb2xsZWN0RXZlbnREYXRhOiBmdW5jdGlvbiBjb2xsZWN0RXZlbnREYXRhKGVsZW1lbnQsIGV2ZW50VHlwZSwgdG91Y2hlcywgZXYpIHtcbiAgICAvLyBmaW5kIG91dCBwb2ludGVyVHlwZVxuICAgIHZhciBwb2ludGVyVHlwZSA9IFBPSU5URVJfVE9VQ0g7XG4gICAgaWYgKFV0aWxzLmluU3RyKGV2LnR5cGUsICdtb3VzZScpIHx8IFBvaW50ZXJFdmVudC5tYXRjaFR5cGUoUE9JTlRFUl9NT1VTRSwgZXYpKSB7XG4gICAgICBwb2ludGVyVHlwZSA9IFBPSU5URVJfTU9VU0U7XG4gICAgfSBlbHNlIGlmIChQb2ludGVyRXZlbnQubWF0Y2hUeXBlKFBPSU5URVJfUEVOLCBldikpIHtcbiAgICAgIHBvaW50ZXJUeXBlID0gUE9JTlRFUl9QRU47XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNlbnRlcjogVXRpbHMuZ2V0Q2VudGVyKHRvdWNoZXMpLFxuICAgICAgdGltZVN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgdGFyZ2V0OiBldi50YXJnZXQsXG4gICAgICB0b3VjaGVzOiB0b3VjaGVzLFxuICAgICAgZXZlbnRUeXBlOiBldmVudFR5cGUsXG4gICAgICBwb2ludGVyVHlwZTogcG9pbnRlclR5cGUsXG4gICAgICBzcmNFdmVudDogZXYsXG5cbiAgICAgIC8qKlxuICAgICAgICogcHJldmVudCB0aGUgYnJvd3NlciBkZWZhdWx0IGFjdGlvbnNcbiAgICAgICAqIG1vc3RseSB1c2VkIHRvIGRpc2FibGUgc2Nyb2xsaW5nIG9mIHRoZSBicm93c2VyXG4gICAgICAgKi9cbiAgICAgIHByZXZlbnREZWZhdWx0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHNyY0V2ZW50ID0gdGhpcy5zcmNFdmVudDtcbiAgICAgICAgc3JjRXZlbnQucHJldmVudE1hbmlwdWxhdGlvbiAmJiBzcmNFdmVudC5wcmV2ZW50TWFuaXB1bGF0aW9uKCk7XG4gICAgICAgIHNyY0V2ZW50LnByZXZlbnREZWZhdWx0ICYmIHNyY0V2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9LFxuXG4gICAgICAvKipcbiAgICAgICAqIHN0b3AgYnViYmxpbmcgdGhlIGV2ZW50IHVwIHRvIGl0cyBwYXJlbnRzXG4gICAgICAgKi9cbiAgICAgIHN0b3BQcm9wYWdhdGlvbjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuc3JjRXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICB9LFxuXG4gICAgICAvKipcbiAgICAgICAqIGltbWVkaWF0ZWx5IHN0b3AgZ2VzdHVyZSBkZXRlY3Rpb25cbiAgICAgICAqIG1pZ2h0IGJlIHVzZWZ1bCBhZnRlciBhIHN3aXBlIHdhcyBkZXRlY3RlZFxuICAgICAgICogQHJldHVybiB7Kn1cbiAgICAgICAqL1xuICAgICAgc3RvcERldGVjdDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBEZXRlY3Rpb24uc3RvcERldGVjdCgpO1xuICAgICAgfVxuICAgIH07XG4gIH1cbn07XG5cblxuLyoqXG4gKiBAbW9kdWxlIEdlc3R1cmVEZXRlY3RvclxuICpcbiAqIEBjbGFzcyBQb2ludGVyRXZlbnRcbiAqIEBzdGF0aWNcbiAqL1xuUG9pbnRlckV2ZW50ID0gR2VzdHVyZURldGVjdG9yLlBvaW50ZXJFdmVudCA9IHtcbiAgLyoqXG4gICAqIGhvbGRzIGFsbCBwb2ludGVycywgYnkgYGlkZW50aWZpZXJgXG4gICAqIEBwcm9wZXJ0eSBwb2ludGVyc1xuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgcG9pbnRlcnM6IHt9LFxuXG4gIC8qKlxuICAgKiBnZXQgdGhlIHBvaW50ZXJzIGFzIGFuIGFycmF5XG4gICAqIEByZXR1cm4ge0FycmF5fSB0b3VjaGxpc3RcbiAgICovXG4gIGdldFRvdWNoTGlzdDogZnVuY3Rpb24gZ2V0VG91Y2hMaXN0KCkge1xuICAgIHZhciB0b3VjaGxpc3QgPSBbXTtcbiAgICAvLyB3ZSBjYW4gdXNlIGZvckVhY2ggc2luY2UgcG9pbnRlckV2ZW50cyBvbmx5IGlzIGluIElFMTBcbiAgICBVdGlscy5lYWNoKHRoaXMucG9pbnRlcnMsIGZ1bmN0aW9uKHBvaW50ZXIpIHtcbiAgICAgIHRvdWNobGlzdC5wdXNoKHBvaW50ZXIpO1xuICAgIH0pO1xuICAgIHJldHVybiB0b3VjaGxpc3Q7XG4gIH0sXG5cbiAgLyoqXG4gICAqIHVwZGF0ZSB0aGUgcG9zaXRpb24gb2YgYSBwb2ludGVyXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBldmVudFR5cGUgbWF0Y2hlcyBgRVZFTlRfU1RBUlR8TU9WRXxFTkRgXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwb2ludGVyRXZlbnRcbiAgICovXG4gIHVwZGF0ZVBvaW50ZXI6IGZ1bmN0aW9uIHVwZGF0ZVBvaW50ZXIoZXZlbnRUeXBlLCBwb2ludGVyRXZlbnQpIHtcbiAgICBpZiAoZXZlbnRUeXBlID09IEVWRU5UX0VORCB8fCAoZXZlbnRUeXBlICE9IEVWRU5UX0VORCAmJiBwb2ludGVyRXZlbnQuYnV0dG9ucyAhPT0gMSkpIHtcbiAgICAgIGRlbGV0ZSB0aGlzLnBvaW50ZXJzW3BvaW50ZXJFdmVudC5wb2ludGVySWRdO1xuICAgIH0gZWxzZSB7XG4gICAgICBwb2ludGVyRXZlbnQuaWRlbnRpZmllciA9IHBvaW50ZXJFdmVudC5wb2ludGVySWQ7XG4gICAgICB0aGlzLnBvaW50ZXJzW3BvaW50ZXJFdmVudC5wb2ludGVySWRdID0gcG9pbnRlckV2ZW50O1xuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogY2hlY2sgaWYgZXYgbWF0Y2hlcyBwb2ludGVydHlwZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gcG9pbnRlclR5cGUgbWF0Y2hlcyBgUE9JTlRFUl9NT1VTRXxUT1VDSHxQRU5gXG4gICAqIEBwYXJhbSB7UG9pbnRlckV2ZW50fSBldlxuICAgKi9cbiAgbWF0Y2hUeXBlOiBmdW5jdGlvbiBtYXRjaFR5cGUocG9pbnRlclR5cGUsIGV2KSB7XG4gICAgaWYgKCFldi5wb2ludGVyVHlwZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHZhciBwdCA9IGV2LnBvaW50ZXJUeXBlLFxuICAgICAgICB0eXBlcyA9IHt9O1xuXG4gICAgdHlwZXNbUE9JTlRFUl9NT1VTRV0gPSAocHQgPT09IChldi5NU1BPSU5URVJfVFlQRV9NT1VTRSB8fCBQT0lOVEVSX01PVVNFKSk7XG4gICAgdHlwZXNbUE9JTlRFUl9UT1VDSF0gPSAocHQgPT09IChldi5NU1BPSU5URVJfVFlQRV9UT1VDSCB8fCBQT0lOVEVSX1RPVUNIKSk7XG4gICAgdHlwZXNbUE9JTlRFUl9QRU5dID0gKHB0ID09PSAoZXYuTVNQT0lOVEVSX1RZUEVfUEVOIHx8IFBPSU5URVJfUEVOKSk7XG4gICAgcmV0dXJuIHR5cGVzW3BvaW50ZXJUeXBlXTtcbiAgfSxcblxuICAvKipcbiAgICogcmVzZXQgdGhlIHN0b3JlZCBwb2ludGVyc1xuICAgKi9cbiAgcmVzZXQ6IGZ1bmN0aW9uIHJlc2V0TGlzdCgpIHtcbiAgICB0aGlzLnBvaW50ZXJzID0ge307XG4gIH1cbn07XG5cblxuLyoqXG4gKiBAbW9kdWxlIEdlc3R1cmVEZXRlY3RvclxuICpcbiAqIEBjbGFzcyBEZXRlY3Rpb25cbiAqIEBzdGF0aWNcbiAqL1xuRGV0ZWN0aW9uID0gR2VzdHVyZURldGVjdG9yLmRldGVjdGlvbiA9IHtcbiAgLy8gY29udGFpbnMgYWxsIHJlZ2lzdGVyZWQgR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzIGluIHRoZSBjb3JyZWN0IG9yZGVyXG4gIGdlc3R1cmVzOiBbXSxcblxuICAvLyBkYXRhIG9mIHRoZSBjdXJyZW50IEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlIGRldGVjdGlvbiBzZXNzaW9uXG4gIGN1cnJlbnQ6IG51bGwsXG5cbiAgLy8gdGhlIHByZXZpb3VzIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlIHNlc3Npb24gZGF0YVxuICAvLyBpcyBhIGZ1bGwgY2xvbmUgb2YgdGhlIHByZXZpb3VzIGdlc3R1cmUuY3VycmVudCBvYmplY3RcbiAgcHJldmlvdXM6IG51bGwsXG5cbiAgLy8gd2hlbiB0aGlzIGJlY29tZXMgdHJ1ZSwgbm8gZ2VzdHVyZXMgYXJlIGZpcmVkXG4gIHN0b3BwZWQ6IGZhbHNlLFxuXG4gIC8qKlxuICAgKiBzdGFydCBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZSBkZXRlY3Rpb25cbiAgICogQHBhcmFtIHtHZXN0dXJlRGV0ZWN0b3IuSW5zdGFuY2V9IGluc3RcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50RGF0YVxuICAgKi9cbiAgc3RhcnREZXRlY3Q6IGZ1bmN0aW9uIHN0YXJ0RGV0ZWN0KGluc3QsIGV2ZW50RGF0YSkge1xuICAgIC8vIGFscmVhZHkgYnVzeSB3aXRoIGEgR2VzdHVyZURldGVjdG9yLmdlc3R1cmUgZGV0ZWN0aW9uIG9uIGFuIGVsZW1lbnRcbiAgICBpZiAodGhpcy5jdXJyZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zdG9wcGVkID0gZmFsc2U7XG5cbiAgICAvLyBob2xkcyBjdXJyZW50IHNlc3Npb25cbiAgICB0aGlzLmN1cnJlbnQgPSB7XG4gICAgICBpbnN0OiBpbnN0LCAvLyByZWZlcmVuY2UgdG8gR2VzdHVyZURldGVjdG9ySW5zdGFuY2Ugd2UncmUgd29ya2luZyBmb3JcbiAgICAgIHN0YXJ0RXZlbnQ6IFV0aWxzLmV4dGVuZCh7fSwgZXZlbnREYXRhKSwgLy8gc3RhcnQgZXZlbnREYXRhIGZvciBkaXN0YW5jZXMsIHRpbWluZyBldGNcbiAgICAgIGxhc3RFdmVudDogZmFsc2UsIC8vIGxhc3QgZXZlbnREYXRhXG4gICAgICBsYXN0Q2FsY0V2ZW50OiBmYWxzZSwgLy8gbGFzdCBldmVudERhdGEgZm9yIGNhbGN1bGF0aW9ucy5cbiAgICAgIGZ1dHVyZUNhbGNFdmVudDogZmFsc2UsIC8vIGxhc3QgZXZlbnREYXRhIGZvciBjYWxjdWxhdGlvbnMuXG4gICAgICBsYXN0Q2FsY0RhdGE6IHt9LCAvLyBsYXN0IGxhc3RDYWxjRGF0YVxuICAgICAgbmFtZTogJycgLy8gY3VycmVudCBnZXN0dXJlIHdlJ3JlIGluL2RldGVjdGVkLCBjYW4gYmUgJ3RhcCcsICdob2xkJyBldGNcbiAgICB9O1xuXG4gICAgdGhpcy5kZXRlY3QoZXZlbnREYXRhKTtcbiAgfSxcblxuICAvKipcbiAgICogR2VzdHVyZURldGVjdG9yLmdlc3R1cmUgZGV0ZWN0aW9uXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudERhdGFcbiAgICogQHJldHVybiB7YW55fVxuICAgKi9cbiAgZGV0ZWN0OiBmdW5jdGlvbiBkZXRlY3QoZXZlbnREYXRhKSB7XG4gICAgaWYgKCF0aGlzLmN1cnJlbnQgfHwgdGhpcy5zdG9wcGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZXh0ZW5kIGV2ZW50IGRhdGEgd2l0aCBjYWxjdWxhdGlvbnMgYWJvdXQgc2NhbGUsIGRpc3RhbmNlIGV0Y1xuICAgIGV2ZW50RGF0YSA9IHRoaXMuZXh0ZW5kRXZlbnREYXRhKGV2ZW50RGF0YSk7XG5cbiAgICAvLyBHZXN0dXJlRGV0ZWN0b3IgaW5zdGFuY2UgYW5kIGluc3RhbmNlIG9wdGlvbnNcbiAgICB2YXIgaW5zdCA9IHRoaXMuY3VycmVudC5pbnN0LFxuICAgICAgICBpbnN0T3B0aW9ucyA9IGluc3Qub3B0aW9ucztcblxuICAgIC8vIGNhbGwgR2VzdHVyZURldGVjdG9yLmdlc3R1cmUgaGFuZGxlcnNcbiAgICBVdGlscy5lYWNoKHRoaXMuZ2VzdHVyZXMsIGZ1bmN0aW9uIHRyaWdnZXJHZXN0dXJlKGdlc3R1cmUpIHtcbiAgICAgIC8vIG9ubHkgd2hlbiB0aGUgaW5zdGFuY2Ugb3B0aW9ucyBoYXZlIGVuYWJsZWQgdGhpcyBnZXN0dXJlXG4gICAgICBpZiAoIXRoaXMuc3RvcHBlZCAmJiBpbnN0LmVuYWJsZWQgJiYgaW5zdE9wdGlvbnNbZ2VzdHVyZS5uYW1lXSkge1xuICAgICAgICBnZXN0dXJlLmhhbmRsZXIuY2FsbChnZXN0dXJlLCBldmVudERhdGEsIGluc3QpO1xuICAgICAgfVxuICAgIH0sIHRoaXMpO1xuXG4gICAgLy8gc3RvcmUgYXMgcHJldmlvdXMgZXZlbnQgZXZlbnRcbiAgICBpZiAodGhpcy5jdXJyZW50KSB7XG4gICAgICB0aGlzLmN1cnJlbnQubGFzdEV2ZW50ID0gZXZlbnREYXRhO1xuICAgIH1cblxuICAgIGlmIChldmVudERhdGEuZXZlbnRUeXBlID09IEVWRU5UX0VORCkge1xuICAgICAgdGhpcy5zdG9wRGV0ZWN0KCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGV2ZW50RGF0YTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBjb25zaXN0ZW50LXJldHVyblxuICB9LFxuXG4gIC8qKlxuICAgKiBjbGVhciB0aGUgR2VzdHVyZURldGVjdG9yLmdlc3R1cmUgdmFyc1xuICAgKiB0aGlzIGlzIGNhbGxlZCBvbiBlbmREZXRlY3QsIGJ1dCBjYW4gYWxzbyBiZSB1c2VkIHdoZW4gYSBmaW5hbCBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZSBoYXMgYmVlbiBkZXRlY3RlZFxuICAgKiB0byBzdG9wIG90aGVyIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlcyBmcm9tIGJlaW5nIGZpcmVkXG4gICAqL1xuICBzdG9wRGV0ZWN0OiBmdW5jdGlvbiBzdG9wRGV0ZWN0KCkge1xuICAgIC8vIGNsb25lIGN1cnJlbnQgZGF0YSB0byB0aGUgc3RvcmUgYXMgdGhlIHByZXZpb3VzIGdlc3R1cmVcbiAgICAvLyB1c2VkIGZvciB0aGUgZG91YmxlIHRhcCBnZXN0dXJlLCBzaW5jZSB0aGlzIGlzIGFuIG90aGVyIGdlc3R1cmUgZGV0ZWN0IHNlc3Npb25cbiAgICB0aGlzLnByZXZpb3VzID0gVXRpbHMuZXh0ZW5kKHt9LCB0aGlzLmN1cnJlbnQpO1xuXG4gICAgLy8gcmVzZXQgdGhlIGN1cnJlbnRcbiAgICB0aGlzLmN1cnJlbnQgPSBudWxsO1xuICAgIHRoaXMuc3RvcHBlZCA9IHRydWU7XG4gIH0sXG5cbiAgLyoqXG4gICAqIGNhbGN1bGF0ZSB2ZWxvY2l0eSwgYW5nbGUgYW5kIGRpcmVjdGlvblxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICogQHBhcmFtIHtPYmplY3R9IGNlbnRlclxuICAgKiBAcGFyYW0ge051bWJlcn0gZGVsdGFUaW1lXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBkZWx0YVhcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGRlbHRhWVxuICAgKi9cbiAgZ2V0Q2FsY3VsYXRlZERhdGE6IGZ1bmN0aW9uIGdldENhbGN1bGF0ZWREYXRhKGV2LCBjZW50ZXIsIGRlbHRhVGltZSwgZGVsdGFYLCBkZWx0YVkpIHtcbiAgICB2YXIgY3VyID0gdGhpcy5jdXJyZW50LFxuICAgICAgICByZWNhbGMgPSBmYWxzZSxcbiAgICAgICAgY2FsY0V2ID0gY3VyLmxhc3RDYWxjRXZlbnQsXG4gICAgICAgIGNhbGNEYXRhID0gY3VyLmxhc3RDYWxjRGF0YTtcblxuICAgIGlmIChjYWxjRXYgJiYgZXYudGltZVN0YW1wIC0gY2FsY0V2LnRpbWVTdGFtcCA+IEdlc3R1cmVEZXRlY3Rvci5DQUxDVUxBVEVfSU5URVJWQUwpIHtcbiAgICAgIGNlbnRlciA9IGNhbGNFdi5jZW50ZXI7XG4gICAgICBkZWx0YVRpbWUgPSBldi50aW1lU3RhbXAgLSBjYWxjRXYudGltZVN0YW1wO1xuICAgICAgZGVsdGFYID0gZXYuY2VudGVyLmNsaWVudFggLSBjYWxjRXYuY2VudGVyLmNsaWVudFg7XG4gICAgICBkZWx0YVkgPSBldi5jZW50ZXIuY2xpZW50WSAtIGNhbGNFdi5jZW50ZXIuY2xpZW50WTtcbiAgICAgIHJlY2FsYyA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKGV2LmV2ZW50VHlwZSA9PSBFVkVOVF9UT1VDSCB8fCBldi5ldmVudFR5cGUgPT0gRVZFTlRfUkVMRUFTRSkge1xuICAgICAgY3VyLmZ1dHVyZUNhbGNFdmVudCA9IGV2O1xuICAgIH1cblxuICAgIGlmICghY3VyLmxhc3RDYWxjRXZlbnQgfHwgcmVjYWxjKSB7XG4gICAgICBjYWxjRGF0YS52ZWxvY2l0eSA9IFV0aWxzLmdldFZlbG9jaXR5KGRlbHRhVGltZSwgZGVsdGFYLCBkZWx0YVkpO1xuICAgICAgY2FsY0RhdGEuYW5nbGUgPSBVdGlscy5nZXRBbmdsZShjZW50ZXIsIGV2LmNlbnRlcik7XG4gICAgICBjYWxjRGF0YS5kaXJlY3Rpb24gPSBVdGlscy5nZXREaXJlY3Rpb24oY2VudGVyLCBldi5jZW50ZXIpO1xuXG4gICAgICBjdXIubGFzdENhbGNFdmVudCA9IGN1ci5mdXR1cmVDYWxjRXZlbnQgfHwgZXY7XG4gICAgICBjdXIuZnV0dXJlQ2FsY0V2ZW50ID0gZXY7XG4gICAgfVxuXG4gICAgZXYudmVsb2NpdHlYID0gY2FsY0RhdGEudmVsb2NpdHkueDtcbiAgICBldi52ZWxvY2l0eVkgPSBjYWxjRGF0YS52ZWxvY2l0eS55O1xuICAgIGV2LmludGVyaW1BbmdsZSA9IGNhbGNEYXRhLmFuZ2xlO1xuICAgIGV2LmludGVyaW1EaXJlY3Rpb24gPSBjYWxjRGF0YS5kaXJlY3Rpb247XG4gIH0sXG5cbiAgLyoqXG4gICAqIGV4dGVuZCBldmVudERhdGEgZm9yIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlc1xuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICogQHJldHVybiB7T2JqZWN0fSBldlxuICAgKi9cbiAgZXh0ZW5kRXZlbnREYXRhOiBmdW5jdGlvbiBleHRlbmRFdmVudERhdGEoZXYpIHtcbiAgICB2YXIgY3VyID0gdGhpcy5jdXJyZW50LFxuICAgICAgICBzdGFydEV2ID0gY3VyLnN0YXJ0RXZlbnQsXG4gICAgICAgIGxhc3RFdiA9IGN1ci5sYXN0RXZlbnQgfHwgc3RhcnRFdjtcblxuICAgIC8vIHVwZGF0ZSB0aGUgc3RhcnQgdG91Y2hsaXN0IHRvIGNhbGN1bGF0ZSB0aGUgc2NhbGUvcm90YXRpb25cbiAgICBpZiAoZXYuZXZlbnRUeXBlID09IEVWRU5UX1RPVUNIIHx8IGV2LmV2ZW50VHlwZSA9PSBFVkVOVF9SRUxFQVNFKSB7XG4gICAgICBzdGFydEV2LnRvdWNoZXMgPSBbXTtcbiAgICAgIFV0aWxzLmVhY2goZXYudG91Y2hlcywgZnVuY3Rpb24odG91Y2gpIHtcbiAgICAgICAgc3RhcnRFdi50b3VjaGVzLnB1c2goe1xuICAgICAgICAgIGNsaWVudFg6IHRvdWNoLmNsaWVudFgsXG4gICAgICAgICAgY2xpZW50WTogdG91Y2guY2xpZW50WVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHZhciBkZWx0YVRpbWUgPSBldi50aW1lU3RhbXAgLSBzdGFydEV2LnRpbWVTdGFtcCxcbiAgICAgICAgZGVsdGFYID0gZXYuY2VudGVyLmNsaWVudFggLSBzdGFydEV2LmNlbnRlci5jbGllbnRYLFxuICAgICAgICBkZWx0YVkgPSBldi5jZW50ZXIuY2xpZW50WSAtIHN0YXJ0RXYuY2VudGVyLmNsaWVudFk7XG5cbiAgICB0aGlzLmdldENhbGN1bGF0ZWREYXRhKGV2LCBsYXN0RXYuY2VudGVyLCBkZWx0YVRpbWUsIGRlbHRhWCwgZGVsdGFZKTtcblxuICAgIFV0aWxzLmV4dGVuZChldiwge1xuICAgICAgc3RhcnRFdmVudDogc3RhcnRFdixcblxuICAgICAgZGVsdGFUaW1lOiBkZWx0YVRpbWUsXG4gICAgICBkZWx0YVg6IGRlbHRhWCxcbiAgICAgIGRlbHRhWTogZGVsdGFZLFxuXG4gICAgICBkaXN0YW5jZTogVXRpbHMuZ2V0RGlzdGFuY2Uoc3RhcnRFdi5jZW50ZXIsIGV2LmNlbnRlciksXG4gICAgICBhbmdsZTogVXRpbHMuZ2V0QW5nbGUoc3RhcnRFdi5jZW50ZXIsIGV2LmNlbnRlciksXG4gICAgICBkaXJlY3Rpb246IFV0aWxzLmdldERpcmVjdGlvbihzdGFydEV2LmNlbnRlciwgZXYuY2VudGVyKSxcbiAgICAgIHNjYWxlOiBVdGlscy5nZXRTY2FsZShzdGFydEV2LnRvdWNoZXMsIGV2LnRvdWNoZXMpLFxuICAgICAgcm90YXRpb246IFV0aWxzLmdldFJvdGF0aW9uKHN0YXJ0RXYudG91Y2hlcywgZXYudG91Y2hlcylcbiAgICB9KTtcblxuICAgIHJldHVybiBldjtcbiAgfSxcblxuICAvKipcbiAgICogcmVnaXN0ZXIgbmV3IGdlc3R1cmVcbiAgICogQHBhcmFtIHtPYmplY3R9IGdlc3R1cmUgb2JqZWN0LCBzZWUgYGdlc3R1cmVzL2AgZm9yIGRvY3VtZW50YXRpb25cbiAgICogQHJldHVybiB7QXJyYXl9IGdlc3R1cmVzXG4gICAqL1xuICByZWdpc3RlcjogZnVuY3Rpb24gcmVnaXN0ZXIoZ2VzdHVyZSkge1xuICAgIC8vIGFkZCBhbiBlbmFibGUgZ2VzdHVyZSBvcHRpb25zIGlmIHRoZXJlIGlzIG5vIGdpdmVuXG4gICAgdmFyIG9wdGlvbnMgPSBnZXN0dXJlLmRlZmF1bHRzIHx8IHt9O1xuICAgIGlmIChvcHRpb25zW2dlc3R1cmUubmFtZV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgb3B0aW9uc1tnZXN0dXJlLm5hbWVdID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBleHRlbmQgR2VzdHVyZURldGVjdG9yIGRlZmF1bHQgb3B0aW9ucyB3aXRoIHRoZSBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZSBvcHRpb25zXG4gICAgVXRpbHMuZXh0ZW5kKEdlc3R1cmVEZXRlY3Rvci5kZWZhdWx0cywgb3B0aW9ucywgdHJ1ZSk7XG5cbiAgICAvLyBzZXQgaXRzIGluZGV4XG4gICAgZ2VzdHVyZS5pbmRleCA9IGdlc3R1cmUuaW5kZXggfHwgMTAwMDtcblxuICAgIC8vIGFkZCBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZSB0byB0aGUgbGlzdFxuICAgIHRoaXMuZ2VzdHVyZXMucHVzaChnZXN0dXJlKTtcblxuICAgIC8vIHNvcnQgdGhlIGxpc3QgYnkgaW5kZXhcbiAgICB0aGlzLmdlc3R1cmVzLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgaWYgKGEuaW5kZXggPCBiLmluZGV4KSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cbiAgICAgIGlmIChhLmluZGV4ID4gYi5pbmRleCkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cbiAgICAgIHJldHVybiAwO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuZ2VzdHVyZXM7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBAbW9kdWxlIEdlc3R1cmVEZXRlY3RvclxuICovXG5cbi8qKlxuICogY3JlYXRlIG5ldyBHZXN0dXJlRGV0ZWN0b3IgaW5zdGFuY2VcbiAqIGFsbCBtZXRob2RzIHNob3VsZCByZXR1cm4gdGhlIGluc3RhbmNlIGl0c2VsZiwgc28gaXQgaXMgY2hhaW5hYmxlLlxuICpcbiAqIEBjbGFzcyBJbnN0YW5jZVxuICogQGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIG9wdGlvbnMgYXJlIG1lcmdlZCB3aXRoIGBHZXN0dXJlRGV0ZWN0b3IuZGVmYXVsdHNgXG4gKiBAcmV0dXJuIHtHZXN0dXJlRGV0ZWN0b3IuSW5zdGFuY2V9XG4gKi9cbkdlc3R1cmVEZXRlY3Rvci5JbnN0YW5jZSA9IGZ1bmN0aW9uKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgbGlzdGVuZXJPcHRpb25zID0gKG9wdGlvbnMgJiYgb3B0aW9ucy5wYXNzaXZlKSA/IHsgcGFzc2l2ZTogdHJ1ZSB9IDogdW5kZWZpbmVkO1xuXG4gIC8vIHNldHVwIEdlc3R1cmVEZXRlY3RvckpTIHdpbmRvdyBldmVudHMgYW5kIHJlZ2lzdGVyIGFsbCBnZXN0dXJlc1xuICAvLyB0aGlzIGFsc28gc2V0cyB1cCB0aGUgZGVmYXVsdCBvcHRpb25zXG4gIHNldHVwKGxpc3RlbmVyT3B0aW9ucyk7XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBlbGVtZW50XG4gICAqIEB0eXBlIHtIVE1MRWxlbWVudH1cbiAgICovXG4gIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBlbmFibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuICB0aGlzLmVuYWJsZWQgPSB0cnVlO1xuXG4gIC8qKlxuICAgKiBvcHRpb25zLCBtZXJnZWQgd2l0aCB0aGUgZGVmYXVsdHNcbiAgICogb3B0aW9ucyB3aXRoIGFuIF8gYXJlIGNvbnZlcnRlZCB0byBjYW1lbENhc2VcbiAgICogQHByb3BlcnR5IG9wdGlvbnNcbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIFV0aWxzLmVhY2gob3B0aW9ucywgZnVuY3Rpb24odmFsdWUsIG5hbWUpIHtcbiAgICBkZWxldGUgb3B0aW9uc1tuYW1lXTtcbiAgICBvcHRpb25zW1V0aWxzLnRvQ2FtZWxDYXNlKG5hbWUpXSA9IHZhbHVlO1xuICB9KTtcblxuICB0aGlzLm9wdGlvbnMgPSBVdGlscy5leHRlbmQoVXRpbHMuZXh0ZW5kKHt9LCBHZXN0dXJlRGV0ZWN0b3IuZGVmYXVsdHMpLCBvcHRpb25zIHx8IHt9KTtcbiAgdGhpcy5vcHRpb25zLmxpc3RlbmVyT3B0aW9ucyA9IGxpc3RlbmVyT3B0aW9ucztcblxuICAvLyBhZGQgc29tZSBjc3MgdG8gdGhlIGVsZW1lbnQgdG8gcHJldmVudCB0aGUgYnJvd3NlciBmcm9tIGRvaW5nIGl0cyBuYXRpdmUgYmVoYXZpb3JcbiAgaWYgKHRoaXMub3B0aW9ucy5iZWhhdmlvcikge1xuICAgIFV0aWxzLnRvZ2dsZUJlaGF2aW9yKHRoaXMuZWxlbWVudCwgdGhpcy5vcHRpb25zLmJlaGF2aW9yLCB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBldmVudCBzdGFydCBoYW5kbGVyIG9uIHRoZSBlbGVtZW50IHRvIHN0YXJ0IHRoZSBkZXRlY3Rpb25cbiAgICogQHByb3BlcnR5IGV2ZW50U3RhcnRIYW5kbGVyXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICB0aGlzLmV2ZW50U3RhcnRIYW5kbGVyID0gRXZlbnQub25Ub3VjaChlbGVtZW50LCBFVkVOVF9TVEFSVCwgZnVuY3Rpb24oZXYpIHtcbiAgICBpZiAoc2VsZi5lbmFibGVkICYmIGV2LmV2ZW50VHlwZSA9PSBFVkVOVF9TVEFSVCkge1xuICAgICAgRGV0ZWN0aW9uLnN0YXJ0RGV0ZWN0KHNlbGYsIGV2KTtcbiAgICB9IGVsc2UgaWYgKGV2LmV2ZW50VHlwZSA9PSBFVkVOVF9UT1VDSCkge1xuICAgICAgRGV0ZWN0aW9uLmRldGVjdChldik7XG4gICAgfVxuICB9LCBsaXN0ZW5lck9wdGlvbnMpO1xuXG4gIC8qKlxuICAgKiBrZWVwIGEgbGlzdCBvZiB1c2VyIGV2ZW50IGhhbmRsZXJzIHdoaWNoIG5lZWRzIHRvIGJlIHJlbW92ZWQgd2hlbiBjYWxsaW5nICdkaXNwb3NlJ1xuICAgKiBAcHJvcGVydHkgZXZlbnRIYW5kbGVyc1xuICAgKiBAdHlwZSB7QXJyYXl9XG4gICAqL1xuICB0aGlzLmV2ZW50SGFuZGxlcnMgPSBbXTtcbn07XG5cbkdlc3R1cmVEZXRlY3Rvci5JbnN0YW5jZS5wcm90b3R5cGUgPSB7XG4gIC8qKlxuICAgKiBAbWV0aG9kIG9uXG4gICAqIEBzaWduYXR1cmUgb24oZ2VzdHVyZXMsIGhhbmRsZXIpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXUFkZHMgYW4gZXZlbnQgaGFuZGxlciBmb3IgYSBnZXN0dXJlLiBBdmFpbGFibGUgZ2VzdHVyZXMgYXJlOiBkcmFnLCBkcmFnbGVmdCwgZHJhZ3JpZ2h0LCBkcmFndXAsIGRyYWdkb3duLCBob2xkLCByZWxlYXNlLCBzd2lwZSwgc3dpcGVsZWZ0LCBzd2lwZXJpZ2h0LCBzd2lwZXVwLCBzd2lwZWRvd24sIHRhcCwgZG91YmxldGFwLCB0b3VjaCwgdHJhbnNmb3JtLCBwaW5jaCwgcGluY2hpbiwgcGluY2hvdXQgYW5kIHJvdGF0ZS4gWy9lbl1cbiAgICogIFtqYV3jgrjjgqfjgrnjg4Hjg6Pjgavlr77jgZnjgovjgqTjg5njg7Pjg4jjg4/jg7Pjg4njg6njgpLov73liqDjgZfjgb7jgZnjgILmjIflrprjgafjgY3jgovjgrjjgqfjgrnjg4Hjg6PlkI3jga/jgIFkcmFnIGRyYWdsZWZ0IGRyYWdyaWdodCBkcmFndXAgZHJhZ2Rvd24gaG9sZCByZWxlYXNlIHN3aXBlIHN3aXBlbGVmdCBzd2lwZXJpZ2h0IHN3aXBldXAgc3dpcGVkb3duIHRhcCBkb3VibGV0YXAgdG91Y2ggdHJhbnNmb3JtIHBpbmNoIHBpbmNoaW4gcGluY2hvdXQgcm90YXRlIOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBnZXN0dXJlc1xuICAgKiAgIFtlbl1BIHNwYWNlIHNlcGFyYXRlZCBsaXN0IG9mIGdlc3R1cmVzLlsvZW5dXG4gICAqICAgW2phXeaknOefpeOBmeOCi+OCuOOCp+OCueODgeODo+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAguOCueODmuODvOOCueOBp+ikh+aVsOaMh+WumuOBmeOCi+OBk+OBqOOBjOOBp+OBjeOBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGhhbmRsZXJcbiAgICogICBbZW5dQW4gZXZlbnQgaGFuZGxpbmcgZnVuY3Rpb24uWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44OP44Oz44OJ44Op44Go44Gq44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIG9uOiBmdW5jdGlvbiBvbkV2ZW50KGdlc3R1cmVzLCBoYW5kbGVyLCBvcHQpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICBFdmVudC5vbihzZWxmLmVsZW1lbnQsIGdlc3R1cmVzLCBoYW5kbGVyLCB1dGlsLmV4dGVuZCh7fSwgc2VsZi5vcHRpb25zLmxpc3RlbmVyT3B0aW9ucywgb3B0KSwgZnVuY3Rpb24odHlwZSkge1xuICAgICAgc2VsZi5ldmVudEhhbmRsZXJzLnB1c2goeyBnZXN0dXJlOiB0eXBlLCBoYW5kbGVyOiBoYW5kbGVyIH0pO1xuICAgIH0pO1xuICAgIHJldHVybiBzZWxmO1xuICB9LFxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIG9mZlxuICAgKiBAc2lnbmF0dXJlIG9mZihnZXN0dXJlcywgaGFuZGxlcilcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dUmVtb3ZlIGFuIGV2ZW50IGxpc3RlbmVyLlsvZW5dXG4gICAqICBbamFd44Kk44OZ44Oz44OI44Oq44K544OK44O844KS5YmK6Zmk44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IGdlc3R1cmVzXG4gICAqICAgW2VuXUEgc3BhY2Ugc2VwYXJhdGVkIGxpc3Qgb2YgZ2VzdHVyZXMuWy9lbl1cbiAgICogICBbamFd44K444Kn44K544OB44Oj5ZCN44KS5oyH5a6a44GX44G+44GZ44CC44K544Oa44O844K544Gn6KSH5pWw5oyH5a6a44GZ44KL44GT44Go44GM44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaGFuZGxlclxuICAgKiAgIFtlbl1BbiBldmVudCBoYW5kbGluZyBmdW5jdGlvbi5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjg4/jg7Pjg4njg6njgajjgarjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgb2ZmOiBmdW5jdGlvbiBvZmZFdmVudChnZXN0dXJlcywgaGFuZGxlciwgb3B0KSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgRXZlbnQub2ZmKHNlbGYuZWxlbWVudCwgZ2VzdHVyZXMsIGhhbmRsZXIsIHV0aWwuZXh0ZW5kKHt9LCBzZWxmLm9wdGlvbnMubGlzdGVuZXJPcHRpb25zLCBvcHQpLCBmdW5jdGlvbih0eXBlKSB7XG4gICAgICB2YXIgaW5kZXggPSBVdGlscy5pbkFycmF5KHNlbGYuZXZlbnRIYW5kbGVycywgeyBnZXN0dXJlOiB0eXBlLCBoYW5kbGVyOiBoYW5kbGVyIH0sIHRydWUpO1xuICAgICAgaWYgKGluZGV4ID49IDApIHtcbiAgICAgICAgc2VsZi5ldmVudEhhbmRsZXJzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHNlbGY7XG4gIH0sXG5cbiAgLyoqXG4gICAqIHRyaWdnZXIgZ2VzdHVyZSBldmVudFxuICAgKiBAbWV0aG9kIHRyaWdnZXJcbiAgICogQHNpZ25hdHVyZSB0cmlnZ2VyKGdlc3R1cmUsIGV2ZW50RGF0YSlcbiAgICogQHBhcmFtIHtTdHJpbmd9IGdlc3R1cmVcbiAgICogQHBhcmFtIHtPYmplY3R9IFtldmVudERhdGFdXG4gICAqL1xuICB0cmlnZ2VyOiBmdW5jdGlvbiB0cmlnZ2VyRXZlbnQoZ2VzdHVyZSwgZXZlbnREYXRhKSB7XG4gICAgLy8gb3B0aW9uYWxcbiAgICBpZiAoIWV2ZW50RGF0YSkge1xuICAgICAgZXZlbnREYXRhID0ge307XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIERPTSBldmVudFxuICAgIHZhciBldmVudCA9IEdlc3R1cmVEZXRlY3Rvci5ET0NVTUVOVC5jcmVhdGVFdmVudCgnRXZlbnQnKTtcbiAgICBldmVudC5pbml0RXZlbnQoZ2VzdHVyZSwgdHJ1ZSwgdHJ1ZSk7XG4gICAgZXZlbnQuZ2VzdHVyZSA9IGV2ZW50RGF0YTtcblxuICAgIC8vIHRyaWdnZXIgb24gdGhlIHRhcmdldCBpZiBpdCBpcyBpbiB0aGUgaW5zdGFuY2UgZWxlbWVudCxcbiAgICAvLyB0aGlzIGlzIGZvciBldmVudCBkZWxlZ2F0aW9uIHRyaWNrc1xuICAgIHZhciBlbGVtZW50ID0gdGhpcy5lbGVtZW50O1xuICAgIGlmIChVdGlscy5oYXNQYXJlbnQoZXZlbnREYXRhLnRhcmdldCwgZWxlbWVudCkpIHtcbiAgICAgIGVsZW1lbnQgPSBldmVudERhdGEudGFyZ2V0O1xuICAgIH1cblxuICAgIGVsZW1lbnQuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEBtZXRob2QgZW5hYmxlXG4gICAqIEBzaWduYXR1cmUgZW5hYmxlKHN0YXRlKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1FbmFibGUgb3IgZGlzYWJsZSBnZXN0dXJlIGRldGVjdGlvbi5bL2VuXVxuICAgKiAgW2phXeOCuOOCp+OCueODgeODo+aknOefpeOCkuacieWKueWMli/nhKHlirnljJbjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IHN0YXRlXG4gICAqICAgW2VuXVNwZWNpZnkgaWYgaXQgc2hvdWxkIGJlIGVuYWJsZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeacieWKueOBq+OBmeOCi+OBi+OBqeOBhuOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBlbmFibGU6IGZ1bmN0aW9uIGVuYWJsZShzdGF0ZSkge1xuICAgIHRoaXMuZW5hYmxlZCA9IHN0YXRlO1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGRpc3Bvc2VcbiAgICogQHNpZ25hdHVyZSBkaXNwb3NlKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dUmVtb3ZlIGFuZCBkZXN0cm95IGFsbCBldmVudCBoYW5kbGVycyBmb3IgdGhpcyBpbnN0YW5jZS5bL2VuXVxuICAgKiAgW2phXeOBk+OBruOCpOODs+OCueOCv+ODs+OCueOBp+OBruOCuOOCp+OCueODgeODo+OBruaknOefpeOChOOAgeOCpOODmeODs+ODiOODj+ODs+ODieODqeOCkuWFqOOBpuino+mZpOOBl+OBpuW7g+ajhOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBkaXNwb3NlOiBmdW5jdGlvbiBkaXNwb3NlKCkge1xuICAgIHZhciBpLCBlaDtcblxuICAgIC8vIHVuZG8gYWxsIGNoYW5nZXMgbWFkZSBieSBzdG9wX2Jyb3dzZXJfYmVoYXZpb3JcbiAgICBVdGlscy50b2dnbGVCZWhhdmlvcih0aGlzLmVsZW1lbnQsIHRoaXMub3B0aW9ucy5iZWhhdmlvciwgZmFsc2UpO1xuXG4gICAgLy8gdW5iaW5kIGFsbCBjdXN0b20gZXZlbnQgaGFuZGxlcnNcbiAgICBmb3IgKGkgPSAtMTsgKGVoID0gdGhpcy5ldmVudEhhbmRsZXJzWysraV0pOykgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbmQtYXNzaWduXG4gICAgICBVdGlscy5vZmYodGhpcy5lbGVtZW50LCBlaC5nZXN0dXJlLCBlaC5oYW5kbGVyKTtcbiAgICB9XG5cbiAgICB0aGlzLmV2ZW50SGFuZGxlcnMgPSBbXTtcblxuICAgIC8vIHVuYmluZCB0aGUgc3RhcnQgZXZlbnQgbGlzdGVuZXJcbiAgICBFdmVudC5vZmYodGhpcy5lbGVtZW50LCBFVkVOVF9UWVBFU1tFVkVOVF9TVEFSVF0sIHRoaXMuZXZlbnRTdGFydEhhbmRsZXIpO1xuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBAbW9kdWxlIGdlc3R1cmVzXG4gKi9cbi8qKlxuICogTW92ZSB3aXRoIHggZmluZ2VycyAoZGVmYXVsdCAxKSBhcm91bmQgb24gdGhlIHBhZ2UuXG4gKiBQcmV2ZW50aW5nIHRoZSBkZWZhdWx0IGJyb3dzZXIgYmVoYXZpb3IgaXMgYSBnb29kIHdheSB0byBpbXByb3ZlIGZlZWwgYW5kIHdvcmtpbmcuXG4gKiBgYGBgXG4gKiAgR2VzdHVyZURldGVjdG9ydGltZS5vbihcImRyYWdcIiwgZnVuY3Rpb24oZXYpIHtcbiAqICAgIGNvbnNvbGUubG9nKGV2KTtcbiAqICAgIGV2Lmdlc3R1cmUucHJldmVudERlZmF1bHQoKTtcbiAqICB9KTtcbiAqIGBgYGBcbiAqXG4gKiBAY2xhc3MgRHJhZ1xuICogQHN0YXRpY1xuICovXG4vKipcbiAqIEBldmVudCBkcmFnXG4gKiBAcGFyYW0ge09iamVjdH0gZXZcbiAqL1xuLyoqXG4gKiBAZXZlbnQgZHJhZ3N0YXJ0XG4gKiBAcGFyYW0ge09iamVjdH0gZXZcbiAqL1xuLyoqXG4gKiBAZXZlbnQgZHJhZ2VuZFxuICogQHBhcmFtIHtPYmplY3R9IGV2XG4gKi9cbi8qKlxuICogQGV2ZW50IGRyYXBsZWZ0XG4gKiBAcGFyYW0ge09iamVjdH0gZXZcbiAqL1xuLyoqXG4gKiBAZXZlbnQgZHJhZ3JpZ2h0XG4gKiBAcGFyYW0ge09iamVjdH0gZXZcbiAqL1xuLyoqXG4gKiBAZXZlbnQgZHJhZ3VwXG4gKiBAcGFyYW0ge09iamVjdH0gZXZcbiAqL1xuLyoqXG4gKiBAZXZlbnQgZHJhZ2Rvd25cbiAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICovXG5cbi8qKlxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAqL1xuKGZ1bmN0aW9uKG5hbWUpIHtcbiAgdmFyIHRyaWdnZXJlZCA9IGZhbHNlO1xuXG4gIGZ1bmN0aW9uIGRyYWdHZXN0dXJlKGV2LCBpbnN0KSB7XG4gICAgdmFyIGN1ciA9IERldGVjdGlvbi5jdXJyZW50O1xuXG4gICAgLy8gbWF4IHRvdWNoZXNcbiAgICBpZiAoaW5zdC5vcHRpb25zLmRyYWdNYXhUb3VjaGVzID4gMCAmJlxuICAgICAgZXYudG91Y2hlcy5sZW5ndGggPiBpbnN0Lm9wdGlvbnMuZHJhZ01heFRvdWNoZXMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKGV2LmV2ZW50VHlwZSkge1xuICAgIGNhc2UgRVZFTlRfU1RBUlQ6XG4gICAgICB0cmlnZ2VyZWQgPSBmYWxzZTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSBFVkVOVF9NT1ZFOlxuICAgICAgLy8gd2hlbiB0aGUgZGlzdGFuY2Ugd2UgbW92ZWQgaXMgdG9vIHNtYWxsIHdlIHNraXAgdGhpcyBnZXN0dXJlXG4gICAgICAvLyBvciB3ZSBjYW4gYmUgYWxyZWFkeSBpbiBkcmFnZ2luZ1xuICAgICAgaWYgKGV2LmRpc3RhbmNlIDwgaW5zdC5vcHRpb25zLmRyYWdNaW5EaXN0YW5jZSAmJlxuICAgICAgICBjdXIubmFtZSAhPSBuYW1lKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIHN0YXJ0Q2VudGVyID0gY3VyLnN0YXJ0RXZlbnQuY2VudGVyO1xuXG4gICAgICAvLyB3ZSBhcmUgZHJhZ2dpbmchXG4gICAgICBpZiAoY3VyLm5hbWUgIT0gbmFtZSkge1xuICAgICAgICBjdXIubmFtZSA9IG5hbWU7XG4gICAgICAgIGlmIChpbnN0Lm9wdGlvbnMuZHJhZ0Rpc3RhbmNlQ29ycmVjdGlvbiAmJiBldi5kaXN0YW5jZSA+IDApIHtcbiAgICAgICAgICAvLyBXaGVuIGEgZHJhZyBpcyB0cmlnZ2VyZWQsIHNldCB0aGUgZXZlbnQgY2VudGVyIHRvIGRyYWdNaW5EaXN0YW5jZSBwaXhlbHMgZnJvbSB0aGUgb3JpZ2luYWwgZXZlbnQgY2VudGVyLlxuICAgICAgICAgIC8vIFdpdGhvdXQgdGhpcyBjb3JyZWN0aW9uLCB0aGUgZHJhZ2dlZCBkaXN0YW5jZSB3b3VsZCBqdW1wc3RhcnQgYXQgZHJhZ01pbkRpc3RhbmNlIHBpeGVscyBpbnN0ZWFkIG9mIGF0IDAuXG4gICAgICAgICAgLy8gSXQgbWlnaHQgYmUgdXNlZnVsIHRvIHNhdmUgdGhlIG9yaWdpbmFsIHN0YXJ0IHBvaW50IHNvbWV3aGVyZVxuICAgICAgICAgIHZhciBmYWN0b3IgPSBNYXRoLmFicyhpbnN0Lm9wdGlvbnMuZHJhZ01pbkRpc3RhbmNlIC8gZXYuZGlzdGFuY2UpO1xuICAgICAgICAgIHN0YXJ0Q2VudGVyLnBhZ2VYICs9IGV2LmRlbHRhWCAqIGZhY3RvcjtcbiAgICAgICAgICBzdGFydENlbnRlci5wYWdlWSArPSBldi5kZWx0YVkgKiBmYWN0b3I7XG4gICAgICAgICAgc3RhcnRDZW50ZXIuY2xpZW50WCArPSBldi5kZWx0YVggKiBmYWN0b3I7XG4gICAgICAgICAgc3RhcnRDZW50ZXIuY2xpZW50WSArPSBldi5kZWx0YVkgKiBmYWN0b3I7XG5cbiAgICAgICAgICAvLyByZWNhbGN1bGF0ZSBldmVudCBkYXRhIHVzaW5nIG5ldyBzdGFydCBwb2ludFxuICAgICAgICAgIGV2ID0gRGV0ZWN0aW9uLmV4dGVuZEV2ZW50RGF0YShldik7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gbG9jayBkcmFnIHRvIGF4aXM/XG4gICAgICBpZiAoY3VyLmxhc3RFdmVudC5kcmFnTG9ja1RvQXhpcyB8fFxuICAgICAgICAoIGluc3Qub3B0aW9ucy5kcmFnTG9ja1RvQXhpcyAmJlxuICAgICAgICAgIGluc3Qub3B0aW9ucy5kcmFnTG9ja01pbkRpc3RhbmNlIDw9IGV2LmRpc3RhbmNlXG4gICAgICAgICkpIHtcbiAgICAgICAgICBldi5kcmFnTG9ja1RvQXhpcyA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBrZWVwIGRpcmVjdGlvbiBvbiB0aGUgYXhpcyB0aGF0IHRoZSBkcmFnIGdlc3R1cmUgc3RhcnRlZCBvblxuICAgICAgICB2YXIgbGFzdERpcmVjdGlvbiA9IGN1ci5sYXN0RXZlbnQuZGlyZWN0aW9uO1xuICAgICAgICBpZiAoZXYuZHJhZ0xvY2tUb0F4aXMgJiYgbGFzdERpcmVjdGlvbiAhPT0gZXYuZGlyZWN0aW9uKSB7XG4gICAgICAgICAgaWYgKFV0aWxzLmlzVmVydGljYWwobGFzdERpcmVjdGlvbikpIHtcbiAgICAgICAgICAgIGV2LmRpcmVjdGlvbiA9IChldi5kZWx0YVkgPCAwKSA/IERJUkVDVElPTl9VUCA6IERJUkVDVElPTl9ET1dOO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBldi5kaXJlY3Rpb24gPSAoZXYuZGVsdGFYIDwgMCkgPyBESVJFQ1RJT05fTEVGVCA6IERJUkVDVElPTl9SSUdIVDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBmaXJzdCB0aW1lLCB0cmlnZ2VyIGRyYWdzdGFydCBldmVudFxuICAgICAgICBpZiAoIXRyaWdnZXJlZCkge1xuICAgICAgICAgIGluc3QudHJpZ2dlcihuYW1lICsgJ3N0YXJ0JywgZXYpO1xuICAgICAgICAgIHRyaWdnZXJlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0cmlnZ2VyIGV2ZW50c1xuICAgICAgICBpbnN0LnRyaWdnZXIobmFtZSwgZXYpO1xuICAgICAgICBpbnN0LnRyaWdnZXIobmFtZSArIGV2LmRpcmVjdGlvbiwgZXYpO1xuXG4gICAgICAgIHZhciBpc1ZlcnRpY2FsID0gVXRpbHMuaXNWZXJ0aWNhbChldi5kaXJlY3Rpb24pO1xuXG4gICAgICAgIC8vIGJsb2NrIHRoZSBicm93c2VyIGV2ZW50c1xuICAgICAgICBpZiAoKGluc3Qub3B0aW9ucy5kcmFnQmxvY2tWZXJ0aWNhbCAmJiBpc1ZlcnRpY2FsKSB8fFxuICAgICAgICAgIChpbnN0Lm9wdGlvbnMuZHJhZ0Jsb2NrSG9yaXpvbnRhbCAmJiAhaXNWZXJ0aWNhbCkpIHtcbiAgICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIEVWRU5UX1JFTEVBU0U6XG4gICAgICAgIGlmICh0cmlnZ2VyZWQgJiYgZXYuY2hhbmdlZExlbmd0aCA8PSBpbnN0Lm9wdGlvbnMuZHJhZ01heFRvdWNoZXMpIHtcbiAgICAgICAgICBpbnN0LnRyaWdnZXIobmFtZSArICdlbmQnLCBldik7XG4gICAgICAgICAgdHJpZ2dlcmVkID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgRVZFTlRfRU5EOlxuICAgICAgICB0cmlnZ2VyZWQgPSBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzLkRyYWcgPSB7XG4gICAgICBuYW1lOiBuYW1lLFxuICAgICAgaW5kZXg6IDUwLFxuICAgICAgaGFuZGxlcjogZHJhZ0dlc3R1cmUsXG4gICAgICBkZWZhdWx0czoge1xuICAgICAgICAvKipcbiAgICAgICAgICogbWluaW1hbCBtb3ZlbWVudCB0aGF0IGhhdmUgdG8gYmUgbWFkZSBiZWZvcmUgdGhlIGRyYWcgZXZlbnQgZ2V0cyB0cmlnZ2VyZWRcbiAgICAgICAgICogQHByb3BlcnR5IGRyYWdNaW5EaXN0YW5jZVxuICAgICAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAgICAgKiBAZGVmYXVsdCAxMFxuICAgICAgICAgKi9cbiAgICAgICAgZHJhZ01pbkRpc3RhbmNlOiAxMCxcblxuICAgICAgICAvKipcbiAgICAgICAgICogU2V0IGRyYWdEaXN0YW5jZUNvcnJlY3Rpb24gdG8gdHJ1ZSB0byBtYWtlIHRoZSBzdGFydGluZyBwb2ludCBvZiB0aGUgZHJhZ1xuICAgICAgICAgKiBiZSBjYWxjdWxhdGVkIGZyb20gd2hlcmUgdGhlIGRyYWcgd2FzIHRyaWdnZXJlZCwgbm90IGZyb20gd2hlcmUgdGhlIHRvdWNoIHN0YXJ0ZWQuXG4gICAgICAgICAqIFVzZWZ1bCB0byBhdm9pZCBhIGplcmstc3RhcnRpbmcgZHJhZywgd2hpY2ggY2FuIG1ha2UgZmluZS1hZGp1c3RtZW50c1xuICAgICAgICAgKiB0aHJvdWdoIGRyYWdnaW5nIGRpZmZpY3VsdCwgYW5kIGJlIHZpc3VhbGx5IHVuYXBwZWFsaW5nLlxuICAgICAgICAgKiBAcHJvcGVydHkgZHJhZ0Rpc3RhbmNlQ29ycmVjdGlvblxuICAgICAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgICAgICogQGRlZmF1bHQgdHJ1ZVxuICAgICAgICAgKi9cbiAgICAgICAgZHJhZ0Rpc3RhbmNlQ29ycmVjdGlvbjogdHJ1ZSxcblxuICAgICAgICAvKipcbiAgICAgICAgICogc2V0IDAgZm9yIHVubGltaXRlZCwgYnV0IHRoaXMgY2FuIGNvbmZsaWN0IHdpdGggdHJhbnNmb3JtXG4gICAgICAgICAqIEBwcm9wZXJ0eSBkcmFnTWF4VG91Y2hlc1xuICAgICAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAgICAgKiBAZGVmYXVsdCAxXG4gICAgICAgICAqL1xuICAgICAgICBkcmFnTWF4VG91Y2hlczogMSxcblxuICAgICAgICAvKipcbiAgICAgICAgICogcHJldmVudCBkZWZhdWx0IGJyb3dzZXIgYmVoYXZpb3Igd2hlbiBkcmFnZ2luZyBvY2N1cnNcbiAgICAgICAgICogYmUgY2FyZWZ1bCB3aXRoIGl0LCBpdCBtYWtlcyB0aGUgZWxlbWVudCBhIGJsb2NraW5nIGVsZW1lbnRcbiAgICAgICAgICogd2hlbiB5b3UgYXJlIHVzaW5nIHRoZSBkcmFnIGdlc3R1cmUsIGl0IGlzIGEgZ29vZCBwcmFjdGljZSB0byBzZXQgdGhpcyB0cnVlXG4gICAgICAgICAqIEBwcm9wZXJ0eSBkcmFnQmxvY2tIb3Jpem9udGFsXG4gICAgICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAgICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgICAgICAgKi9cbiAgICAgICAgZHJhZ0Jsb2NrSG9yaXpvbnRhbDogZmFsc2UsXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIHNhbWUgYXMgYGRyYWdCbG9ja0hvcml6b250YWxgLCBidXQgZm9yIHZlcnRpY2FsIG1vdmVtZW50XG4gICAgICAgICAqIEBwcm9wZXJ0eSBkcmFnQmxvY2tWZXJ0aWNhbFxuICAgICAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgICAgICogQGRlZmF1bHQgZmFsc2VcbiAgICAgICAgICovXG4gICAgICAgIGRyYWdCbG9ja1ZlcnRpY2FsOiBmYWxzZSxcblxuICAgICAgICAvKipcbiAgICAgICAgICogZHJhZ0xvY2tUb0F4aXMga2VlcHMgdGhlIGRyYWcgZ2VzdHVyZSBvbiB0aGUgYXhpcyB0aGF0IGl0IHN0YXJ0ZWQgb24sXG4gICAgICAgICAqIEl0IGRpc2FsbG93cyB2ZXJ0aWNhbCBkaXJlY3Rpb25zIGlmIHRoZSBpbml0aWFsIGRpcmVjdGlvbiB3YXMgaG9yaXpvbnRhbCwgYW5kIHZpY2UgdmVyc2EuXG4gICAgICAgICAqIEBwcm9wZXJ0eSBkcmFnTG9ja1RvQXhpc1xuICAgICAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgICAgICogQGRlZmF1bHQgZmFsc2VcbiAgICAgICAgICovXG4gICAgICAgIGRyYWdMb2NrVG9BeGlzOiBmYWxzZSxcblxuICAgICAgICAvKipcbiAgICAgICAgICogZHJhZyBsb2NrIG9ubHkga2lja3MgaW4gd2hlbiBkaXN0YW5jZSA+IGRyYWdMb2NrTWluRGlzdGFuY2VcbiAgICAgICAgICogVGhpcyB3YXksIGxvY2tpbmcgb2NjdXJzIG9ubHkgd2hlbiB0aGUgZGlzdGFuY2UgaGFzIGJlY29tZSBsYXJnZSBlbm91Z2ggdG8gcmVsaWFibHkgZGV0ZXJtaW5lIHRoZSBkaXJlY3Rpb25cbiAgICAgICAgICogQHByb3BlcnR5IGRyYWdMb2NrTWluRGlzdGFuY2VcbiAgICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAgICogQGRlZmF1bHQgMjVcbiAgICAgICAgICovXG4gICAgICAgIGRyYWdMb2NrTWluRGlzdGFuY2U6IDI1XG4gICAgICB9XG4gICAgfTtcbiAgfSkoJ2RyYWcnKTtcblxuICAvKipcbiAgICogQG1vZHVsZSBnZXN0dXJlc1xuICAgKi9cbiAgLyoqXG4gICAqIHRyaWdnZXIgYSBzaW1wbGUgZ2VzdHVyZSBldmVudCwgc28geW91IGNhbiBkbyBhbnl0aGluZyBpbiB5b3VyIGhhbmRsZXIuXG4gICAqIG9ubHkgdXNhYmxlIGlmIHlvdSBrbm93IHdoYXQgeW91ciBkb2luZy4uLlxuICAgKlxuICAgKiBAY2xhc3MgR2VzdHVyZVxuICAgKiBAc3RhdGljXG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IGdlc3R1cmVcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZXMuR2VzdHVyZSA9IHtcbiAgICBuYW1lOiAnZ2VzdHVyZScsXG4gICAgaW5kZXg6IDEzMzcsXG4gICAgaGFuZGxlcjogZnVuY3Rpb24gcmVsZWFzZUdlc3R1cmUoZXYsIGluc3QpIHtcbiAgICAgIGluc3QudHJpZ2dlcih0aGlzLm5hbWUsIGV2KTtcbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEBtb2R1bGUgZ2VzdHVyZXNcbiAgICovXG4gIC8qKlxuICAgKiBUb3VjaCBzdGF5cyBhdCB0aGUgc2FtZSBwbGFjZSBmb3IgeCB0aW1lXG4gICAqXG4gICAqIEBjbGFzcyBIb2xkXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIC8qKlxuICAgKiBAZXZlbnQgaG9sZFxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqL1xuICAoZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciB0aW1lcjtcblxuICAgIGZ1bmN0aW9uIGhvbGRHZXN0dXJlKGV2LCBpbnN0KSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IGluc3Qub3B0aW9ucyxcbiAgICAgICAgICBjdXJyZW50ID0gRGV0ZWN0aW9uLmN1cnJlbnQ7XG5cbiAgICAgIHN3aXRjaCAoZXYuZXZlbnRUeXBlKSB7XG4gICAgICBjYXNlIEVWRU5UX1NUQVJUOlxuICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuXG4gICAgICAgIC8vIHNldCB0aGUgZ2VzdHVyZSBzbyB3ZSBjYW4gY2hlY2sgaW4gdGhlIHRpbWVvdXQgaWYgaXQgc3RpbGwgaXNcbiAgICAgICAgY3VycmVudC5uYW1lID0gbmFtZTtcblxuICAgICAgICAvLyBzZXQgdGltZXIgYW5kIGlmIGFmdGVyIHRoZSB0aW1lb3V0IGl0IHN0aWxsIGlzIGhvbGQsXG4gICAgICAgIC8vIHdlIHRyaWdnZXIgdGhlIGhvbGQgZXZlbnRcbiAgICAgICAgdGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGlmIChjdXJyZW50ICYmIGN1cnJlbnQubmFtZSA9PSBuYW1lKSB7XG4gICAgICAgICAgICBpbnN0LnRyaWdnZXIobmFtZSwgZXYpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwgb3B0aW9ucy5ob2xkVGltZW91dCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIEVWRU5UX01PVkU6XG4gICAgICAgIGlmIChldi5kaXN0YW5jZSA+IG9wdGlvbnMuaG9sZFRocmVzaG9sZCkge1xuICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgRVZFTlRfUkVMRUFTRTpcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzLkhvbGQgPSB7XG4gICAgICBuYW1lOiBuYW1lLFxuICAgICAgaW5kZXg6IDEwLFxuICAgICAgZGVmYXVsdHM6IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwcm9wZXJ0eSBob2xkVGltZW91dFxuICAgICAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAgICAgKiBAZGVmYXVsdCA1MDBcbiAgICAgICAgICovXG4gICAgICAgIGhvbGRUaW1lb3V0OiA1MDAsXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIG1vdmVtZW50IGFsbG93ZWQgd2hpbGUgaG9sZGluZ1xuICAgICAgICAgKiBAcHJvcGVydHkgaG9sZFRocmVzaG9sZFxuICAgICAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAgICAgKiBAZGVmYXVsdCAyXG4gICAgICAgICAqL1xuICAgICAgICBob2xkVGhyZXNob2xkOiAyXG4gICAgICB9LFxuICAgICAgaGFuZGxlcjogaG9sZEdlc3R1cmVcbiAgICB9O1xuICB9KSgnaG9sZCcpO1xuXG4gIC8qKlxuICAgKiBAbW9kdWxlIGdlc3R1cmVzXG4gICAqL1xuICAvKipcbiAgICogd2hlbiBhIHRvdWNoIGlzIGJlaW5nIHJlbGVhc2VkIGZyb20gdGhlIHBhZ2VcbiAgICpcbiAgICogQGNsYXNzIFJlbGVhc2VcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgLyoqXG4gICAqIEBldmVudCByZWxlYXNlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKi9cbiAgR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzLlJlbGVhc2UgPSB7XG4gICAgbmFtZTogJ3JlbGVhc2UnLFxuICAgIGluZGV4OiBJbmZpbml0eSxcbiAgICBoYW5kbGVyOiBmdW5jdGlvbiByZWxlYXNlR2VzdHVyZShldiwgaW5zdCkge1xuICAgICAgaWYgKGV2LmV2ZW50VHlwZSA9PSBFVkVOVF9SRUxFQVNFKSB7XG4gICAgICAgIGluc3QudHJpZ2dlcih0aGlzLm5hbWUsIGV2KTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEBtb2R1bGUgZ2VzdHVyZXNcbiAgICovXG4gIC8qKlxuICAgKiB0cmlnZ2VycyBzd2lwZSBldmVudHMgd2hlbiB0aGUgZW5kIHZlbG9jaXR5IGlzIGFib3ZlIHRoZSB0aHJlc2hvbGRcbiAgICogZm9yIGJlc3QgdXNhZ2UsIHNldCBgcHJldmVudERlZmF1bHRgIChvbiB0aGUgZHJhZyBnZXN0dXJlKSB0byBgdHJ1ZWBcbiAgICogYGBgYFxuICAgKiAgR2VzdHVyZURldGVjdG9ydGltZS5vbihcImRyYWdsZWZ0IHN3aXBlbGVmdFwiLCBmdW5jdGlvbihldikge1xuICAgKiAgICBjb25zb2xlLmxvZyhldik7XG4gICAqICAgIGV2Lmdlc3R1cmUucHJldmVudERlZmF1bHQoKTtcbiAgICogIH0pO1xuICAgKiBgYGBgXG4gICAqXG4gICAqIEBjbGFzcyBTd2lwZVxuICAgKiBAc3RhdGljXG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHN3aXBlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKi9cbiAgLyoqXG4gICAqIEBldmVudCBzd2lwZWxlZnRcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHN3aXBlcmlnaHRcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHN3aXBldXBcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHN3aXBlZG93blxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG4gIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlcy5Td2lwZSA9IHtcbiAgICBuYW1lOiAnc3dpcGUnLFxuICAgIGluZGV4OiA0MCxcbiAgICBkZWZhdWx0czoge1xuICAgICAgLyoqXG4gICAgICAgKiBAcHJvcGVydHkgc3dpcGVNaW5Ub3VjaGVzXG4gICAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAgICogQGRlZmF1bHQgMVxuICAgICAgICovXG4gICAgICBzd2lwZU1pblRvdWNoZXM6IDEsXG5cbiAgICAgIC8qKlxuICAgICAgICogQHByb3BlcnR5IHN3aXBlTWF4VG91Y2hlc1xuICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAqIEBkZWZhdWx0IDFcbiAgICAgICAqL1xuICAgICAgc3dpcGVNYXhUb3VjaGVzOiAxLFxuXG4gICAgICAvKipcbiAgICAgICAqIGhvcml6b250YWwgc3dpcGUgdmVsb2NpdHlcbiAgICAgICAqIEBwcm9wZXJ0eSBzd2lwZVZlbG9jaXR5WFxuICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAqIEBkZWZhdWx0IDAuNlxuICAgICAgICovXG4gICAgICBzd2lwZVZlbG9jaXR5WDogMC42LFxuXG4gICAgICAvKipcbiAgICAgICAqIHZlcnRpY2FsIHN3aXBlIHZlbG9jaXR5XG4gICAgICAgKiBAcHJvcGVydHkgc3dpcGVWZWxvY2l0eVlcbiAgICAgICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAgICAgKiBAZGVmYXVsdCAwLjZcbiAgICAgICAqL1xuICAgICAgc3dpcGVWZWxvY2l0eVk6IDAuNlxuICAgIH0sXG5cbiAgICBoYW5kbGVyOiBmdW5jdGlvbiBzd2lwZUdlc3R1cmUoZXYsIGluc3QpIHtcbiAgICAgIGlmIChldi5ldmVudFR5cGUgPT0gRVZFTlRfUkVMRUFTRSkge1xuICAgICAgICB2YXIgdG91Y2hlcyA9IGV2LnRvdWNoZXMubGVuZ3RoLFxuICAgICAgICAgICAgb3B0aW9ucyA9IGluc3Qub3B0aW9ucztcblxuICAgICAgICAvLyBtYXggdG91Y2hlc1xuICAgICAgICBpZiAodG91Y2hlcyA8IG9wdGlvbnMuc3dpcGVNaW5Ub3VjaGVzIHx8XG4gICAgICAgICAgdG91Y2hlcyA+IG9wdGlvbnMuc3dpcGVNYXhUb3VjaGVzKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gd2hlbiB0aGUgZGlzdGFuY2Ugd2UgbW92ZWQgaXMgdG9vIHNtYWxsIHdlIHNraXAgdGhpcyBnZXN0dXJlXG4gICAgICAgIC8vIG9yIHdlIGNhbiBiZSBhbHJlYWR5IGluIGRyYWdnaW5nXG4gICAgICAgIGlmIChldi52ZWxvY2l0eVggPiBvcHRpb25zLnN3aXBlVmVsb2NpdHlYIHx8XG4gICAgICAgICAgZXYudmVsb2NpdHlZID4gb3B0aW9ucy5zd2lwZVZlbG9jaXR5WSkge1xuICAgICAgICAgIC8vIHRyaWdnZXIgc3dpcGUgZXZlbnRzXG4gICAgICAgICAgaW5zdC50cmlnZ2VyKHRoaXMubmFtZSwgZXYpO1xuICAgICAgICAgIGluc3QudHJpZ2dlcih0aGlzLm5hbWUgKyBldi5kaXJlY3Rpb24sIGV2KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQG1vZHVsZSBnZXN0dXJlc1xuICAgKi9cbiAgLyoqXG4gICAqIFNpbmdsZSB0YXAgYW5kIGEgZG91YmxlIHRhcCBvbiBhIHBsYWNlXG4gICAqXG4gICAqIEBjbGFzcyBUYXBcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgLyoqXG4gICAqIEBldmVudCB0YXBcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IGRvdWJsZXRhcFxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqL1xuICAoZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciBoYXNNb3ZlZCA9IGZhbHNlO1xuXG4gICAgZnVuY3Rpb24gdGFwR2VzdHVyZShldiwgaW5zdCkge1xuICAgICAgdmFyIG9wdGlvbnMgPSBpbnN0Lm9wdGlvbnMsXG4gICAgICAgICAgY3VycmVudCA9IERldGVjdGlvbi5jdXJyZW50LFxuICAgICAgICAgIHByZXYgPSBEZXRlY3Rpb24ucHJldmlvdXMsXG4gICAgICAgICAgc2luY2VQcmV2LFxuICAgICAgICAgIGRpZERvdWJsZVRhcDtcblxuICAgICAgc3dpdGNoIChldi5ldmVudFR5cGUpIHtcbiAgICAgIGNhc2UgRVZFTlRfU1RBUlQ6XG4gICAgICAgIGhhc01vdmVkID0gZmFsc2U7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIEVWRU5UX01PVkU6XG4gICAgICAgIGhhc01vdmVkID0gaGFzTW92ZWQgfHwgKGV2LmRpc3RhbmNlID4gb3B0aW9ucy50YXBNYXhEaXN0YW5jZSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIEVWRU5UX0VORDpcbiAgICAgICAgaWYgKCFVdGlscy5pblN0cihldi5zcmNFdmVudC50eXBlLCAnY2FuY2VsJykgJiYgZXYuZGVsdGFUaW1lIDwgb3B0aW9ucy50YXBNYXhUaW1lICYmICFoYXNNb3ZlZCkge1xuICAgICAgICAgIC8vIHByZXZpb3VzIGdlc3R1cmUsIGZvciB0aGUgZG91YmxlIHRhcCBzaW5jZSB0aGVzZSBhcmUgdHdvIGRpZmZlcmVudCBnZXN0dXJlIGRldGVjdGlvbnNcbiAgICAgICAgICBzaW5jZVByZXYgPSBwcmV2ICYmIHByZXYubGFzdEV2ZW50ICYmIGV2LnRpbWVTdGFtcCAtIHByZXYubGFzdEV2ZW50LnRpbWVTdGFtcDtcbiAgICAgICAgICBkaWREb3VibGVUYXAgPSBmYWxzZTtcblxuICAgICAgICAgIC8vIGNoZWNrIGlmIGRvdWJsZSB0YXBcbiAgICAgICAgICBpZiAocHJldiAmJiBwcmV2Lm5hbWUgPT0gbmFtZSAmJlxuICAgICAgICAgICAgKHNpbmNlUHJldiAmJiBzaW5jZVByZXYgPCBvcHRpb25zLmRvdWJsZVRhcEludGVydmFsKSAmJlxuICAgICAgICAgICAgZXYuZGlzdGFuY2UgPCBvcHRpb25zLmRvdWJsZVRhcERpc3RhbmNlKSB7XG4gICAgICAgICAgICBpbnN0LnRyaWdnZXIoJ2RvdWJsZXRhcCcsIGV2KTtcbiAgICAgICAgICAgIGRpZERvdWJsZVRhcCA9IHRydWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gZG8gYSBzaW5nbGUgdGFwXG4gICAgICAgICAgaWYgKCFkaWREb3VibGVUYXAgfHwgb3B0aW9ucy50YXBBbHdheXMpIHtcbiAgICAgICAgICAgIGN1cnJlbnQubmFtZSA9IG5hbWU7XG4gICAgICAgICAgICBpbnN0LnRyaWdnZXIoY3VycmVudC5uYW1lLCBldik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlcy5UYXAgPSB7XG4gICAgICBuYW1lOiBuYW1lLFxuICAgICAgaW5kZXg6IDEwMCxcbiAgICAgIGhhbmRsZXI6IHRhcEdlc3R1cmUsXG4gICAgICBkZWZhdWx0czoge1xuICAgICAgICAvKipcbiAgICAgICAgICogbWF4IHRpbWUgb2YgYSB0YXAsIHRoaXMgaXMgZm9yIHRoZSBzbG93IHRhcHBlcnNcbiAgICAgICAgICogQHByb3BlcnR5IHRhcE1heFRpbWVcbiAgICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAgICogQGRlZmF1bHQgMjUwXG4gICAgICAgICAqL1xuICAgICAgICB0YXBNYXhUaW1lOiAyNTAsXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIG1heCBkaXN0YW5jZSBvZiBtb3ZlbWVudCBvZiBhIHRhcCwgdGhpcyBpcyBmb3IgdGhlIHNsb3cgdGFwcGVyc1xuICAgICAgICAgKiBAcHJvcGVydHkgdGFwTWF4RGlzdGFuY2VcbiAgICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAgICogQGRlZmF1bHQgMTBcbiAgICAgICAgICovXG4gICAgICAgIHRhcE1heERpc3RhbmNlOiAxMCxcblxuICAgICAgICAvKipcbiAgICAgICAgICogYWx3YXlzIHRyaWdnZXIgdGhlIGB0YXBgIGV2ZW50LCBldmVuIHdoaWxlIGRvdWJsZS10YXBwaW5nXG4gICAgICAgICAqIEBwcm9wZXJ0eSB0YXBBbHdheXNcbiAgICAgICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICAgICAqIEBkZWZhdWx0IHRydWVcbiAgICAgICAgICovXG4gICAgICAgIHRhcEFsd2F5czogdHJ1ZSxcblxuICAgICAgICAvKipcbiAgICAgICAgICogbWF4IGRpc3RhbmNlIGJldHdlZW4gdHdvIHRhcHNcbiAgICAgICAgICogQHByb3BlcnR5IGRvdWJsZVRhcERpc3RhbmNlXG4gICAgICAgICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAgICAgICAqIEBkZWZhdWx0IDIwXG4gICAgICAgICAqL1xuICAgICAgICBkb3VibGVUYXBEaXN0YW5jZTogMjAsXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIG1heCB0aW1lIGJldHdlZW4gdHdvIHRhcHNcbiAgICAgICAgICogQHByb3BlcnR5IGRvdWJsZVRhcEludGVydmFsXG4gICAgICAgICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAgICAgICAqIEBkZWZhdWx0IDMwMFxuICAgICAgICAgKi9cbiAgICAgICAgZG91YmxlVGFwSW50ZXJ2YWw6IDMwMFxuICAgICAgfVxuICAgIH07XG4gIH0pKCd0YXAnKTtcblxuICAvKipcbiAgICogQG1vZHVsZSBnZXN0dXJlc1xuICAgKi9cbiAgLyoqXG4gICAqIHdoZW4gYSB0b3VjaCBpcyBiZWluZyB0b3VjaGVkIGF0IHRoZSBwYWdlXG4gICAqXG4gICAqIEBjbGFzcyBUb3VjaFxuICAgKiBAc3RhdGljXG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHRvdWNoXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKi9cbiAgR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzLlRvdWNoID0ge1xuICAgIG5hbWU6ICd0b3VjaCcsXG4gICAgaW5kZXg6IC1JbmZpbml0eSxcbiAgICBkZWZhdWx0czoge1xuICAgICAgLyoqXG4gICAgICAgKiBjYWxsIHByZXZlbnREZWZhdWx0IGF0IHRvdWNoc3RhcnQsIGFuZCBtYWtlcyB0aGUgZWxlbWVudCBibG9ja2luZyBieSBkaXNhYmxpbmcgdGhlIHNjcm9sbGluZyBvZiB0aGUgcGFnZSxcbiAgICAgICAqIGJ1dCBpdCBpbXByb3ZlcyBnZXN0dXJlcyBsaWtlIHRyYW5zZm9ybWluZyBhbmQgZHJhZ2dpbmcuXG4gICAgICAgKiBiZSBjYXJlZnVsIHdpdGggdXNpbmcgdGhpcywgaXQgY2FuIGJlIHZlcnkgYW5ub3lpbmcgZm9yIHVzZXJzIHRvIGJlIHN0dWNrIG9uIHRoZSBwYWdlXG4gICAgICAgKiBAcHJvcGVydHkgcHJldmVudERlZmF1bHRcbiAgICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAgICogQGRlZmF1bHQgZmFsc2VcbiAgICAgICAqL1xuICAgICAgcHJldmVudERlZmF1bHQ6IGZhbHNlLFxuXG4gICAgICAvKipcbiAgICAgICAqIGRpc2FibGUgbW91c2UgZXZlbnRzLCBzbyBvbmx5IHRvdWNoIChvciBwZW4hKSBpbnB1dCB0cmlnZ2VycyBldmVudHNcbiAgICAgICAqIEBwcm9wZXJ0eSBwcmV2ZW50TW91c2VcbiAgICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAgICogQGRlZmF1bHQgZmFsc2VcbiAgICAgICAqL1xuICAgICAgcHJldmVudE1vdXNlOiBmYWxzZVxuICAgIH0sXG4gICAgaGFuZGxlcjogZnVuY3Rpb24gdG91Y2hHZXN0dXJlKGV2LCBpbnN0KSB7XG4gICAgICBpZiAoaW5zdC5vcHRpb25zLnByZXZlbnRNb3VzZSAmJiBldi5wb2ludGVyVHlwZSA9PSBQT0lOVEVSX01PVVNFKSB7XG4gICAgICAgIGV2LnN0b3BEZXRlY3QoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoaW5zdC5vcHRpb25zLnByZXZlbnREZWZhdWx0KSB7XG4gICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChldi5ldmVudFR5cGUgPT0gRVZFTlRfVE9VQ0gpIHtcbiAgICAgICAgaW5zdC50cmlnZ2VyKCd0b3VjaCcsIGV2KTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEBtb2R1bGUgZ2VzdHVyZXNcbiAgICovXG4gIC8qKlxuICAgKiBVc2VyIHdhbnQgdG8gc2NhbGUgb3Igcm90YXRlIHdpdGggMiBmaW5nZXJzXG4gICAqIFByZXZlbnRpbmcgdGhlIGRlZmF1bHQgYnJvd3NlciBiZWhhdmlvciBpcyBhIGdvb2Qgd2F5IHRvIGltcHJvdmUgZmVlbCBhbmQgd29ya2luZy4gVGhpcyBjYW4gYmUgZG9uZSB3aXRoIHRoZVxuICAgKiBgcHJldmVudERlZmF1bHRgIG9wdGlvbi5cbiAgICpcbiAgICogQGNsYXNzIFRyYW5zZm9ybVxuICAgKiBAc3RhdGljXG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHRyYW5zZm9ybVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG4gIC8qKlxuICAgKiBAZXZlbnQgdHJhbnNmb3Jtc3RhcnRcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHRyYW5zZm9ybWVuZFxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG4gIC8qKlxuICAgKiBAZXZlbnQgcGluY2hpblxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG4gIC8qKlxuICAgKiBAZXZlbnQgcGluY2hvdXRcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHJvdGF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqL1xuICAoZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciB0cmlnZ2VyZWQgPSBmYWxzZTtcblxuICAgIGZ1bmN0aW9uIHRyYW5zZm9ybUdlc3R1cmUoZXYsIGluc3QpIHtcbiAgICAgIHN3aXRjaCAoZXYuZXZlbnRUeXBlKSB7XG4gICAgICBjYXNlIEVWRU5UX1NUQVJUOlxuICAgICAgICB0cmlnZ2VyZWQgPSBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgRVZFTlRfTU9WRTpcbiAgICAgICAgLy8gYXQgbGVhc3QgbXVsdGl0b3VjaFxuICAgICAgICBpZiAoZXYudG91Y2hlcy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHNjYWxlVGhyZXNob2xkID0gTWF0aC5hYnMoMSAtIGV2LnNjYWxlKTtcbiAgICAgICAgdmFyIHJvdGF0aW9uVGhyZXNob2xkID0gTWF0aC5hYnMoZXYucm90YXRpb24pO1xuXG4gICAgICAgIC8vIHdoZW4gdGhlIGRpc3RhbmNlIHdlIG1vdmVkIGlzIHRvbyBzbWFsbCB3ZSBza2lwIHRoaXMgZ2VzdHVyZVxuICAgICAgICAvLyBvciB3ZSBjYW4gYmUgYWxyZWFkeSBpbiBkcmFnZ2luZ1xuICAgICAgICBpZiAoc2NhbGVUaHJlc2hvbGQgPCBpbnN0Lm9wdGlvbnMudHJhbnNmb3JtTWluU2NhbGUgJiZcbiAgICAgICAgICByb3RhdGlvblRocmVzaG9sZCA8IGluc3Qub3B0aW9ucy50cmFuc2Zvcm1NaW5Sb3RhdGlvbikge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHdlIGFyZSB0cmFuc2Zvcm1pbmchXG4gICAgICAgIERldGVjdGlvbi5jdXJyZW50Lm5hbWUgPSBuYW1lO1xuXG4gICAgICAgIC8vIGZpcnN0IHRpbWUsIHRyaWdnZXIgZHJhZ3N0YXJ0IGV2ZW50XG4gICAgICAgIGlmICghdHJpZ2dlcmVkKSB7XG4gICAgICAgICAgaW5zdC50cmlnZ2VyKG5hbWUgKyAnc3RhcnQnLCBldik7XG4gICAgICAgICAgdHJpZ2dlcmVkID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGluc3QudHJpZ2dlcihuYW1lLCBldik7IC8vIGJhc2ljIHRyYW5zZm9ybSBldmVudFxuXG4gICAgICAgIC8vIHRyaWdnZXIgcm90YXRlIGV2ZW50XG4gICAgICAgIGlmIChyb3RhdGlvblRocmVzaG9sZCA+IGluc3Qub3B0aW9ucy50cmFuc2Zvcm1NaW5Sb3RhdGlvbikge1xuICAgICAgICAgIGluc3QudHJpZ2dlcigncm90YXRlJywgZXYpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdHJpZ2dlciBwaW5jaCBldmVudFxuICAgICAgICBpZiAoc2NhbGVUaHJlc2hvbGQgPiBpbnN0Lm9wdGlvbnMudHJhbnNmb3JtTWluU2NhbGUpIHtcbiAgICAgICAgICBpbnN0LnRyaWdnZXIoJ3BpbmNoJywgZXYpO1xuICAgICAgICAgIGluc3QudHJpZ2dlcigncGluY2gnICsgKGV2LnNjYWxlIDwgMSA/ICdpbicgOiAnb3V0JyksIGV2KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBFVkVOVF9SRUxFQVNFOlxuICAgICAgICBpZiAodHJpZ2dlcmVkICYmIGV2LmNoYW5nZWRMZW5ndGggPCAyKSB7XG4gICAgICAgICAgaW5zdC50cmlnZ2VyKG5hbWUgKyAnZW5kJywgZXYpO1xuICAgICAgICAgIHRyaWdnZXJlZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlcy5UcmFuc2Zvcm0gPSB7XG4gICAgICBuYW1lOiBuYW1lLFxuICAgICAgaW5kZXg6IDQ1LFxuICAgICAgZGVmYXVsdHM6IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIG1pbmltYWwgc2NhbGUgZmFjdG9yLCBubyBzY2FsZSBpcyAxLCB6b29taW4gaXMgdG8gMCBhbmQgem9vbW91dCB1bnRpbCBoaWdoZXIgdGhlbiAxXG4gICAgICAgICAqIEBwcm9wZXJ0eSB0cmFuc2Zvcm1NaW5TY2FsZVxuICAgICAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAgICAgKiBAZGVmYXVsdCAwLjAxXG4gICAgICAgICAqL1xuICAgICAgICB0cmFuc2Zvcm1NaW5TY2FsZTogMC4wMSxcblxuICAgICAgICAvKipcbiAgICAgICAgICogcm90YXRpb24gaW4gZGVncmVlc1xuICAgICAgICAgKiBAcHJvcGVydHkgdHJhbnNmb3JtTWluUm90YXRpb25cbiAgICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAgICogQGRlZmF1bHQgMVxuICAgICAgICAgKi9cbiAgICAgICAgdHJhbnNmb3JtTWluUm90YXRpb246IDFcbiAgICAgIH0sXG5cbiAgICAgIGhhbmRsZXI6IHRyYW5zZm9ybUdlc3R1cmVcbiAgICB9O1xuICB9KSgndHJhbnNmb3JtJyk7XG5cbmV4cG9ydCBkZWZhdWx0IEdlc3R1cmVEZXRlY3RvcjtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmxldCByZWFkeU1hcCwgcXVldWVNYXA7XG5cbmZ1bmN0aW9uIGlzQ29udGVudFJlYWR5KGVsZW1lbnQpIHtcbiAgaWYgKGVsZW1lbnQuY2hpbGROb2Rlcy5sZW5ndGggPiAwKSB7XG4gICAgc2V0Q29udGVudFJlYWR5KGVsZW1lbnQpO1xuICB9XG4gIHJldHVybiByZWFkeU1hcC5oYXMoZWxlbWVudCk7XG59XG5cbmZ1bmN0aW9uIHNldENvbnRlbnRSZWFkeShlbGVtZW50KSB7XG4gIHJlYWR5TWFwLnNldChlbGVtZW50LCB0cnVlKTtcbn1cblxuZnVuY3Rpb24gYWRkQ2FsbGJhY2soZWxlbWVudCwgZm4pIHtcbiAgaWYgKCFxdWV1ZU1hcC5oYXMoZWxlbWVudCkpIHtcbiAgICBxdWV1ZU1hcC5zZXQoZWxlbWVudCwgW10pO1xuICB9XG4gIHF1ZXVlTWFwLmdldChlbGVtZW50KS5wdXNoKGZuKTtcbn1cblxuZnVuY3Rpb24gY29uc3VtZVF1ZXVlKGVsZW1lbnQpIHtcbiAgY29uc3QgY2FsbGJhY2tzID0gcXVldWVNYXAuZ2V0KGVsZW1lbnQsIFtdKSB8fCBbXTtcbiAgcXVldWVNYXAuZGVsZXRlKGVsZW1lbnQpO1xuICBjYWxsYmFja3MuZm9yRWFjaChjYWxsYmFjayA9PiBjYWxsYmFjaygpKTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gY29udGVudFJlYWR5KGVsZW1lbnQsIGZuID0gKCkgPT4ge30pIHtcbiAgaWYgKHJlYWR5TWFwID09PSB1bmRlZmluZWQpIHtcbiAgICByZWFkeU1hcCA9IG5ldyBXZWFrTWFwKCk7XG4gICAgcXVldWVNYXAgPSBuZXcgV2Vha01hcCgpO1xuICB9XG5cbiAgYWRkQ2FsbGJhY2soZWxlbWVudCwgZm4pO1xuXG4gIGlmIChpc0NvbnRlbnRSZWFkeShlbGVtZW50KSkge1xuICAgIGNvbnN1bWVRdWV1ZShlbGVtZW50KTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBvYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKGNoYW5nZXMgPT4ge1xuICAgIHNldENvbnRlbnRSZWFkeShlbGVtZW50KTtcbiAgICBjb25zdW1lUXVldWUoZWxlbWVudCk7XG4gIH0pO1xuICBvYnNlcnZlci5vYnNlcnZlKGVsZW1lbnQsIHtjaGlsZExpc3Q6IHRydWUsIGNoYXJhY3RlckRhdGE6IHRydWV9KTtcblxuICAvLyBmYWlsYmFjayBmb3IgZWxlbWVudHMgaGFzIGVtcHR5IGNvbnRlbnQuXG4gIHNldEltbWVkaWF0ZSgoKSA9PiB7XG4gICAgc2V0Q29udGVudFJlYWR5KGVsZW1lbnQpO1xuICAgIGNvbnN1bWVRdWV1ZShlbGVtZW50KTtcbiAgfSk7XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5jbGFzcyBUb2FzdFF1ZXVlIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5xdWV1ZSA9IFtdO1xuICB9XG5cbiAgYWRkKGZuLCBwcm9taXNlKSB7XG4gICAgdGhpcy5xdWV1ZS5wdXNoKGZuKTtcblxuICAgIGlmICh0aGlzLnF1ZXVlLmxlbmd0aCA9PT0gMSkge1xuICAgICAgc2V0SW1tZWRpYXRlKHRoaXMucXVldWVbMF0pO1xuICAgIH1cblxuICAgIHByb21pc2UudGhlbigoKSA9PiB7XG4gICAgICB0aGlzLnF1ZXVlLnNoaWZ0KCk7XG5cbiAgICAgIGlmICh0aGlzLnF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgc2V0VGltZW91dCh0aGlzLnF1ZXVlWzBdLCAxMDAwLzMwKTsgLy8gQXBwbHkgc29tZSB2aXN1YWwgZGVsYXlcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBuZXcgVG9hc3RRdWV1ZSgpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi91dGlsJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi9jb250ZW50LXJlYWR5JztcbmltcG9ydCBUb2FzdFF1ZXVlIGZyb20gJy4vaW50ZXJuYWwvdG9hc3QtcXVldWUnO1xuXG5jb25zdCBfc2V0QXR0cmlidXRlcyA9IChlbGVtZW50LCBvcHRpb25zKSA9PiB7XG4gIFsnaWQnLCAnY2xhc3MnLCAnYW5pbWF0aW9uJ11cbiAgICAuZm9yRWFjaChhID0+IG9wdGlvbnMuaGFzT3duUHJvcGVydHkoYSkgJiYgZWxlbWVudC5zZXRBdHRyaWJ1dGUoYSwgb3B0aW9uc1thXSkpO1xuXG4gIGlmIChvcHRpb25zLm1vZGlmaWVyKSB7XG4gICAgdXRpbC5hZGRNb2RpZmllcihlbGVtZW50LCBvcHRpb25zLm1vZGlmaWVyKTtcbiAgfVxufTtcblxuY29uc3QgX25vcm1hbGl6ZUFyZ3VtZW50cyA9IChtZXNzYWdlLCBvcHRpb25zID0ge30sIGRlZmF1bHRzID0ge30pID0+IHtcbiAgb3B0aW9ucyA9IHsgLi4ub3B0aW9ucyB9O1xuICB0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycgPyAob3B0aW9ucy5tZXNzYWdlID0gbWVzc2FnZSkgOiAob3B0aW9ucyA9IG1lc3NhZ2UpO1xuICBpZiAoIW9wdGlvbnMgfHwgIW9wdGlvbnMubWVzc2FnZSAmJiAhb3B0aW9ucy5tZXNzYWdlSFRNTCkge1xuICAgIHV0aWwudGhyb3coJ05vdGlmaWNhdGlvbnMgbXVzdCBjb250YWluIGEgbWVzc2FnZScpO1xuICB9XG5cbiAgaWYgKG9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ2J1dHRvbkxhYmVscycpIHx8IG9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ2J1dHRvbkxhYmVsJykpIHtcbiAgICBvcHRpb25zLmJ1dHRvbkxhYmVscyA9IG9wdGlvbnMuYnV0dG9uTGFiZWxzIHx8IG9wdGlvbnMuYnV0dG9uTGFiZWw7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KG9wdGlvbnMuYnV0dG9uTGFiZWxzKSkge1xuICAgICAgb3B0aW9ucy5idXR0b25MYWJlbHMgPSBbb3B0aW9ucy5idXR0b25MYWJlbHMgfHwgJyddXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHV0aWwuZXh0ZW5kKHtcbiAgICAgIGNvbXBpbGU6IHBhcmFtID0+IHBhcmFtLFxuICAgICAgY2FsbGJhY2s6IHBhcmFtID0+IHBhcmFtLFxuICAgICAgYW5pbWF0aW9uOiAnZGVmYXVsdCcsXG4gICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgIHByaW1hcnlCdXR0b25JbmRleDogKG9wdGlvbnMuYnV0dG9uTGFiZWxzIHx8IGRlZmF1bHRzLmJ1dHRvbkxhYmVscyB8fCBbXSkubGVuZ3RoIC0gMVxuICAgIH0sIGRlZmF1bHRzLCBvcHRpb25zKTtcbn07XG5cbi8qKlxuICogQG9iamVjdCBvbnMubm90aWZpY2F0aW9uXG4gKiBAY2F0ZWdvcnkgZGlhbG9nXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2Uvbm90aWZpY2F0aW9uXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIFV0aWxpdHkgbWV0aG9kcyB0byBjcmVhdGUgZGlmZmVyZW50IGtpbmRzIG9mIG5vdGlmaWNhdGlvbnMuIFRoZXJlIGFyZSB0aHJlZSBtZXRob2RzIGF2YWlsYWJsZTpcbiAqXG4gKiAgICAgKiBgb25zLm5vdGlmaWNhdGlvbi5hbGVydCgpYFxuICogICAgICogYG9ucy5ub3RpZmljYXRpb24uY29uZmlybSgpYFxuICogICAgICogYG9ucy5ub3RpZmljYXRpb24ucHJvbXB0KClgXG4gKiAgICAgKiBgb25zLm5vdGlmaWNhdGlvbi50b2FzdCgpYFxuICpcbiAqICAgICBJdCB3aWxsIGF1dG9tYXRpY2FsbHkgZGlzcGxheSBhIE1hdGVyaWFsIERlc2lnbiBkaWFsb2cgb24gQW5kcm9pZCBkZXZpY2VzLlxuICogICBbL2VuXVxuICogICBbamFd44GE44GP44Gk44GL44Gu56iu6aGe44Gu44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44KS5L2c5oiQ44GZ44KL44Gf44KB44Gu44Om44O844OG44Kj44Oq44OG44Kj44Oh44K944OD44OJ44KS5Y+O44KB44Gf44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAqIEBleGFtcGxlXG4gKiBvbnMubm90aWZpY2F0aW9uLmFsZXJ0KCdIZWxsbywgd29ybGQhJyk7XG4gKlxuICogb25zLm5vdGlmaWNhdGlvbi5jb25maXJtKCdBcmUgeW91IHJlYWR5PycpXG4gKiAgIC50aGVuKFxuICogICAgIGZ1bmN0aW9uKGFuc3dlcikge1xuICogICAgICAgaWYgKGFuc3dlciA9PT0gMSkge1xuICogICAgICAgICBvbnMubm90aWZpY2F0aW9uLmFsZXJ0KCdMZXRcXCdzIGdvIScpO1xuICogICAgICAgfVxuICogICAgIH1cbiAqICAgKTtcbiAqXG4gKiBvbnMubm90aWZpY2F0aW9uLnByb21wdCgnSG93IG9sZCBhcmUgPycpXG4gKiAgIC50aGVuKFxuICogICAgIGZ1bmN0aW9uKGFnZSkge1xuICogICAgICAgb25zLm5vdGlmaWNhdGlvbi5hbGVydCgnWW91IGFyZSAnICsgYWdlICsgJyB5ZWFycyBvbGQuJyk7XG4gKiAgICAgfVxuICogICApO1xuICovXG5jb25zdCBub3RpZmljYXRpb24gPSB7fTtcblxubm90aWZpY2F0aW9uLl9jcmVhdGVBbGVydERpYWxvZyA9ICguLi5wYXJhbXMpID0+IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICBjb25zdCBvcHRpb25zID0gX25vcm1hbGl6ZUFyZ3VtZW50cyguLi5wYXJhbXMpO1xuICB1dGlsLmNoZWNrTWlzc2luZ0ltcG9ydCgnQWxlcnREaWFsb2cnLCAnQWxlcnREaWFsb2dCdXR0b24nKTtcblxuICAvLyBQcm9tcHQgaW5wdXQgc3RyaW5nXG4gIGxldCBpbnB1dFN0cmluZyA9ICcnO1xuICBpZiAob3B0aW9ucy5pc1Byb21wdCkge1xuICAgIGlucHV0U3RyaW5nID0gYFxuICAgICAgPGlucHV0XG4gICAgICAgIGNsYXNzPVwidGV4dC1pbnB1dCB0ZXh0LWlucHV0LS11bmRlcmJhclwiXG4gICAgICAgIHR5cGU9XCIke29wdGlvbnMuaW5wdXRUeXBlIHx8ICd0ZXh0J31cIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIiR7b3B0aW9ucy5wbGFjZWhvbGRlciB8fCAnJ31cIlxuICAgICAgICB2YWx1ZT1cIiR7b3B0aW9ucy5kZWZhdWx0VmFsdWUgfHwgJyd9XCJcbiAgICAgICAgc3R5bGU9XCJ3aWR0aDogMTAwJTsgbWFyZ2luLXRvcDogMTBweDtcIlxuICAgICAgLz5cbiAgICBgO1xuICB9XG5cbiAgLy8gQnV0dG9ucyBzdHJpbmdcbiAgbGV0IGJ1dHRvbnMgPSAnJztcbiAgb3B0aW9ucy5idXR0b25MYWJlbHMuZm9yRWFjaCgobGFiZWwsIGluZGV4KSA9PiB7XG4gICAgYnV0dG9ucyArPSBgXG4gICAgICA8b25zLWFsZXJ0LWRpYWxvZy1idXR0b25cbiAgICAgICAgY2xhc3M9XCJcbiAgICAgICAgICAke2luZGV4ID09PSBvcHRpb25zLnByaW1hcnlCdXR0b25JbmRleCA/ICcgYWxlcnQtZGlhbG9nLWJ1dHRvbi0tcHJpbWFsJyA6ICcnfVxuICAgICAgICAgICR7b3B0aW9ucy5idXR0b25MYWJlbHMubGVuZ3RoIDw9IDIgPyAnIGFsZXJ0LWRpYWxvZy1idXR0b24tLXJvd2Zvb3RlcicgOiAnJ31cbiAgICAgICAgXCJcbiAgICAgICAgc3R5bGU9XCJwb3NpdGlvbjogcmVsYXRpdmU7XCI+XG4gICAgICAgICR7bGFiZWx9XG4gICAgICA8L29ucy1hbGVydC1kaWFsb2ctYnV0dG9uPlxuICAgIGA7XG4gIH0pO1xuXG4gIC8vIERpYWxvZyBFbGVtZW50XG4gIGxldCBlbCA9IHt9O1xuICBjb25zdCBfZGVzdHJveURpYWxvZyA9ICgpID0+IHtcbiAgICBpZiAoZWwuZGlhbG9nLm9uRGlhbG9nQ2FuY2VsKSB7XG4gICAgICBlbC5kaWFsb2cucmVtb3ZlRXZlbnRMaXN0ZW5lcignZGlhbG9nLWNhbmNlbCcsIGVsLmRpYWxvZy5vbkRpYWxvZ0NhbmNlbCk7XG4gICAgfVxuXG4gICAgT2JqZWN0LmtleXMoZWwpLmZvckVhY2goa2V5ID0+IGRlbGV0ZSBlbFtrZXldKTtcbiAgICBlbCA9IG51bGw7XG5cbiAgICBpZiAob3B0aW9ucy5kZXN0cm95IGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIG9wdGlvbnMuZGVzdHJveSgpO1xuICAgIH1cbiAgfTtcblxuICBlbC5kaWFsb2cgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdvbnMtYWxlcnQtZGlhbG9nJyk7XG4gIGVsLmRpYWxvZy5pbm5lckhUTUwgPSBgXG4gICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZy1tYXNrXCJcbiAgICAgIHN0eWxlPVwiXG4gICAgICAgICR7b3B0aW9ucy5tYXNrQ29sb3IgPyAnYmFja2dyb3VuZC1jb2xvcjogJyArIG9wdGlvbnMubWFza0NvbG9yIDogJyd9XG4gICAgICBcIj48L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiYWxlcnQtZGlhbG9nXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiYWxlcnQtZGlhbG9nLWNvbnRhaW5lclwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiYWxlcnQtZGlhbG9nLXRpdGxlXCI+XG4gICAgICAgICAgJHtvcHRpb25zLnRpdGxlIHx8ICcnfVxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZy1jb250ZW50XCI+XG4gICAgICAgICAgJHtvcHRpb25zLm1lc3NhZ2UgfHwgb3B0aW9ucy5tZXNzYWdlSFRNTH1cbiAgICAgICAgICAke2lucHV0U3RyaW5nfVxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cIlxuICAgICAgICAgIGFsZXJ0LWRpYWxvZy1mb290ZXJcbiAgICAgICAgICAke29wdGlvbnMuYnV0dG9uTGFiZWxzLmxlbmd0aCA8PSAyID8gJyBhbGVydC1kaWFsb2ctZm9vdGVyLS1yb3dmb290ZXInIDogJyd9XG4gICAgICAgIFwiPlxuICAgICAgICAgICR7YnV0dG9uc31cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYDtcbiAgY29udGVudFJlYWR5KGVsLmRpYWxvZyk7XG5cbiAgLy8gU2V0IGF0dHJpYnV0ZXNcbiAgX3NldEF0dHJpYnV0ZXMoZWwuZGlhbG9nLCBvcHRpb25zKTtcblxuICAvLyBQcm9tcHQgZXZlbnRzXG4gIGlmIChvcHRpb25zLmlzUHJvbXB0ICYmIG9wdGlvbnMuc3VibWl0T25FbnRlcikge1xuICAgIGVsLmlucHV0ID0gZWwuZGlhbG9nLnF1ZXJ5U2VsZWN0b3IoJy50ZXh0LWlucHV0Jyk7XG4gICAgZWwuaW5wdXQub25rZXlwcmVzcyA9IGV2ZW50ID0+IHtcbiAgICAgIGlmIChldmVudC5rZXlDb2RlID09PSAxMykge1xuICAgICAgICBlbC5kaWFsb2cuaGlkZSgpXG4gICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGVsKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHJlc29sdmVWYWx1ZSA9IGVsLmlucHV0LnZhbHVlO1xuICAgICAgICAgICAgICBfZGVzdHJveURpYWxvZygpO1xuICAgICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKHJlc29sdmVWYWx1ZSk7XG4gICAgICAgICAgICAgIHJlc29sdmUocmVzb2x2ZVZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLy8gQnV0dG9uIGV2ZW50c1xuICBlbC5mb290ZXIgPSBlbC5kaWFsb2cucXVlcnlTZWxlY3RvcignLmFsZXJ0LWRpYWxvZy1mb290ZXInKTtcbiAgdXRpbC5hcnJheUZyb20oZWwuZGlhbG9nLnF1ZXJ5U2VsZWN0b3JBbGwoJy5hbGVydC1kaWFsb2ctYnV0dG9uJykpLmZvckVhY2goKGJ1dHRvbkVsZW1lbnQsIGluZGV4KSA9PiB7XG4gICAgYnV0dG9uRWxlbWVudC5vbmNsaWNrID0gKCkgPT4ge1xuICAgICAgICBlbC5kaWFsb2cuaGlkZSgpXG4gICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGVsKSB7XG4gICAgICAgICAgICAgIGxldCByZXNvbHZlVmFsdWUgPSBpbmRleDtcbiAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuaXNQcm9tcHQpIHtcbiAgICAgICAgICAgICAgICByZXNvbHZlVmFsdWUgPSBpbmRleCA9PT0gb3B0aW9ucy5wcmltYXJ5QnV0dG9uSW5kZXggPyBlbC5pbnB1dC52YWx1ZSA6IG51bGw7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZWwuZGlhbG9nLnJlbW92ZSgpO1xuICAgICAgICAgICAgICBfZGVzdHJveURpYWxvZygpO1xuICAgICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKHJlc29sdmVWYWx1ZSk7XG4gICAgICAgICAgICAgIHJlc29sdmUocmVzb2x2ZVZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgZWwuZm9vdGVyLmFwcGVuZENoaWxkKGJ1dHRvbkVsZW1lbnQpO1xuICB9KTtcblxuICAvLyBDYW5jZWwgZXZlbnRzXG4gIGlmIChvcHRpb25zLmNhbmNlbGFibGUpIHtcbiAgICBlbC5kaWFsb2cuY2FuY2VsYWJsZSA9IHRydWU7XG4gICAgZWwuZGlhbG9nLm9uRGlhbG9nQ2FuY2VsID0gKCkgPT4ge1xuICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHtcbiAgICAgICAgZWwuZGlhbG9nLnJlbW92ZSgpO1xuICAgICAgICBfZGVzdHJveURpYWxvZygpO1xuICAgICAgfSk7XG4gICAgICBjb25zdCByZXNvbHZlVmFsdWUgPSBvcHRpb25zLmlzUHJvbXB0ID8gbnVsbCA6IC0xO1xuICAgICAgb3B0aW9ucy5jYWxsYmFjayhyZXNvbHZlVmFsdWUpO1xuICAgICAgcmVzb2x2ZShyZXNvbHZlVmFsdWUpO1xuICAgIH07XG4gICAgZWwuZGlhbG9nLmFkZEV2ZW50TGlzdGVuZXIoJ2RpYWxvZy1jYW5jZWwnLCBlbC5kaWFsb2cub25EaWFsb2dDYW5jZWwsIGZhbHNlKTtcbiAgfVxuXG4gIC8vIFNob3cgZGlhbG9nXG4gIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZWwuZGlhbG9nKTtcbiAgb3B0aW9ucy5jb21waWxlKGVsLmRpYWxvZyk7XG4gIHNldEltbWVkaWF0ZSgoKSA9PiB7XG4gICAgZWwuZGlhbG9nLnNob3coKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBpZiAoZWwuaW5wdXQgJiYgb3B0aW9ucy5pc1Byb21wdCAmJiBvcHRpb25zLmF1dG9mb2N1cykge1xuICAgICAgICAgIGNvbnN0IHN0ckxlbmd0aCA9IGVsLmlucHV0LnZhbHVlLmxlbmd0aDtcbiAgICAgICAgICBlbC5pbnB1dC5mb2N1cygpO1xuICAgICAgICAgIGVsLmlucHV0LnNldFNlbGVjdGlvblJhbmdlKHN0ckxlbmd0aCwgc3RyTGVuZ3RoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH0pO1xufSk7XG5cbi8qKlxuICogQG1ldGhvZCBhbGVydFxuICogQHNpZ25hdHVyZSBhbGVydChtZXNzYWdlIFssIG9wdGlvbnNdIHwgb3B0aW9ucylcbiAqIEByZXR1cm4ge1Byb21pc2V9XG4gKiAgIFtlbl1XaWxsIHJlc29sdmUgdG8gdGhlIGluZGV4IG9mIHRoZSBidXR0b24gdGhhdCB3YXMgcHJlc3NlZCBvciBgLTFgIHdoZW4gY2FuY2VsZWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICogICBbZW5dTm90aWZpY2F0aW9uIG1lc3NhZ2UuIFRoaXMgYXJndW1lbnQgaXMgb3B0aW9uYWwgYnV0IGlmIGl0J3Mgbm90IGRlZmluZWQgZWl0aGVyIGBvcHRpb25zLm1lc3NhZ2VgIG9yIGBvcHRpb25zLm1lc3NhZ2VIVE1MYCBtdXN0IGJlIGRlZmluZWQgaW5zdGVhZC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgafjgZnjgIJbL2phXVxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLm1lc3NhZ2VdXG4gKiAgIFtlbl1Ob3RpZmljYXRpb24gbWVzc2FnZS5bL2VuXVxuICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44Gr6KGo56S644GZ44KL5paH5a2X5YiX44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5tZXNzYWdlSFRNTF1cbiAqICAgW2VuXU5vdGlmaWNhdGlvbiBtZXNzYWdlIGluIEhUTUwuWy9lbl1cbiAqICAgW2phXeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBq+ihqOekuuOBmeOCi0hUTUzjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICogQHBhcmFtIHtTdHJpbmcgfCBBcnJheX0gW29wdGlvbnMuYnV0dG9uTGFiZWxzXVxuICogICBbZW5dTGFiZWxzIGZvciB0aGUgYnV0dG9ucy4gRGVmYXVsdCBpcyBgXCJPS1wiYC5bL2VuXVxuICogICBbamFd56K66KqN44Oc44K/44Oz44Gu44Op44OZ44Or44KS5oyH5a6a44GX44G+44GZ44CCXCJPS1wi44GM44OH44OV44Kp44Or44OI44Gn44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5wcmltYXJ5QnV0dG9uSW5kZXhdXG4gKiAgIFtlbl1JbmRleCBvZiBwcmltYXJ5IGJ1dHRvbi4gRGVmYXVsdCBpcyB0aGUgbGFzdCBvbmUuWy9lbl1cbiAqICAgW2phXeODl+ODqeOCpOODnuODquODnOOCv+ODs+OBruOCpOODs+ODh+ODg+OCr+OCueOCkuaMh+WumuOBl+OBvuOBmeOAguODh+ODleOCqeODq+ODiOOBryAwIOOBp+OBmeOAglsvamFdXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmNhbmNlbGFibGVdXG4gKiAgIFtlbl1XaGV0aGVyIHRoZSBkaWFsb2cgaXMgY2FuY2VsYWJsZSBvciBub3QuIERlZmF1bHQgaXMgYGZhbHNlYC4gSWYgdGhlIGRpYWxvZyBpcyBjYW5jZWxhYmxlIGl0IGNhbiBiZSBjbG9zZWQgYnkgY2xpY2tpbmcgdGhlIGJhY2tncm91bmQgb3IgcHJlc3NpbmcgdGhlIEFuZHJvaWQgYmFjayBidXR0b24uWy9lbl1cbiAqICAgW2phXeODgOOCpOOCouODreOCsOOBjOOCreODo+ODs+OCu+ODq+WPr+iDveOBi+OBqeOBhuOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgbm9uZWAgYW5kIGBmYWRlYC4gRGVmYXVsdCBpcyBgZmFkZWAuWy9lbl1cbiAqICAgW2phXeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOCkuihqOekuuOBmeOCi+mam+OBruOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAglwibm9uZVwiLCBcImZhZGVcIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBp+OBjeOBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuaWRdXG4gKiAgIFtlbl1UaGUgYDxvbnMtYWxlcnQtZGlhbG9nPmAgZWxlbWVudCdzIElELlsvZW5dXG4gKiAgIFtqYV1vbnMtYWxlcnQtZGlhbG9n6KaB57Sg44GuSUTjgIJbL2phXVxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmNsYXNzXVxuICogICBbZW5dVGhlIGA8b25zLWFsZXJ0LWRpYWxvZz5gIGVsZW1lbnQncyBjbGFzcy5bL2VuXVxuICogICBbamFdb25zLWFsZXJ0LWRpYWxvZ+imgee0oOOBrmNsYXNz44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy50aXRsZV1cbiAqICAgW2VuXURpYWxvZyB0aXRsZS4gRGVmYXVsdCBpcyBgXCJBbGVydFwiYC5bL2VuXVxuICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44Gu5LiK6YOo44Gr6KGo56S644GZ44KL44K/44Kk44OI44Or44KS5oyH5a6a44GX44G+44GZ44CCXCJBbGVydFwi44GM44OH44OV44Kp44Or44OI44Gn44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5tb2RpZmllcl1cbiAqICAgW2VuXU1vZGlmaWVyIGZvciB0aGUgZGlhbG9nLlsvZW5dXG4gKiAgIFtqYV3jgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjga5tb2RpZmllcuWxnuaAp+OBruWApOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMubWFza0NvbG9yXVxuICogICBbZW5dQ29sb3Igb2YgdGhlIGJhY2tncm91bmQgbWFzay4gRGVmYXVsdCBpcyBcInJnYmEoMCwgMCwgMCwgMC4yKVwiIChcInJnYmEoMCwgMCwgMCwgMC4zKVwiIGZvciBNYXRlcmlhbCkuWy9lbl1cbiAqICAgW2phXeiDjOaZr+OBruODnuOCueOCr+OBruiJsuOCkuaMh+WumuOBl+OBvuOBmeOAglwicmdiYSgwLCAwLCAwLCAwLjIpXCLjgYzjg4fjg5Xjgqnjg6vjg4jlgKTjgafjgZnjgIJbL2phXVxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gKiAgIFtlbl1GdW5jdGlvbiB0aGF0IGV4ZWN1dGVzIGFmdGVyIGRpYWxvZyBoYXMgYmVlbiBjbG9zZWQuWy9lbl1cbiAqICAgW2phXeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBjOmWieOBmOOCieOCjOOBn+aZguOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIERpc3BsYXkgYW4gYWxlcnQgZGlhbG9nIHRvIHNob3cgdGhlIHVzZXIgYSBtZXNzYWdlLlxuICpcbiAqICAgICBUaGUgY29udGVudCBvZiB0aGUgbWVzc2FnZSBjYW4gYmUgZWl0aGVyIHNpbXBsZSB0ZXh0IG9yIEhUTUwuXG4gKlxuICogICAgIEl0IGNhbiBiZSBjYWxsZWQgaW4gdGhlIGZvbGxvd2luZyB3YXlzOlxuICpcbiAqICAgICBgYGBcbiAqICAgICBvbnMubm90aWZpY2F0aW9uLmFsZXJ0KG1lc3NhZ2UsIG9wdGlvbnMpO1xuICogICAgIG9ucy5ub3RpZmljYXRpb24uYWxlcnQob3B0aW9ucyk7XG4gKiAgICAgYGBgXG4gKlxuICogICAgIE11c3Qgc3BlY2lmeSBlaXRoZXIgYG1lc3NhZ2VgIG9yIGBtZXNzYWdlSFRNTGAuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1cbiAqICAgICDjg6bjg7zjgrbjg7zjgbjjg6Hjg4Pjgrvjg7zjgrjjgpLopovjgZvjgovjgZ/jgoHjga7jgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjgpLooajnpLrjgZfjgb7jgZnjgIJcbiAqICAgICDooajnpLrjgZnjgovjg6Hjg4Pjgrvjg7zjgrjjga/jgIHjg4bjgq3jgrnjg4jjgYvjgoLjgZfjgY/jga9IVE1M44KS5oyH5a6a44Gn44GN44G+44GZ44CCXG4gKiAgICAg44GT44Gu44Oh44K944OD44OJ44Gu5byV5pWw44Gr44Gv44CBb3B0aW9ucy5tZXNzYWdl44KC44GX44GP44Gvb3B0aW9ucy5tZXNzYWdlSFRNTOOBruOBqeOBoeOCieOBi+OCkuW/heOBmuaMh+WumuOBmeOCi+W/heimgeOBjOOBguOCiuOBvuOBmeOAglxuICogICBbL2phXVxuICovXG5ub3RpZmljYXRpb24uYWxlcnQgPSAobWVzc2FnZSwgb3B0aW9ucykgPT5cbiAgbm90aWZpY2F0aW9uLl9jcmVhdGVBbGVydERpYWxvZyhtZXNzYWdlLCBvcHRpb25zLCB7XG4gICAgYnV0dG9uTGFiZWxzOiBbJ09LJ10sXG4gICAgdGl0bGU6ICdBbGVydCdcbiAgfSk7XG5cbi8qKlxuICogQG1ldGhvZCBjb25maXJtXG4gKiBAc2lnbmF0dXJlIGNvbmZpcm0obWVzc2FnZSBbLCBvcHRpb25zXSB8IG9wdGlvbnMpXG4gKiBAcmV0dXJuIHtQcm9taXNlfVxuICogICBbZW5dV2lsbCByZXNvbHZlIHRvIHRoZSBpbmRleCBvZiB0aGUgYnV0dG9uIHRoYXQgd2FzIHByZXNzZWQgb3IgYC0xYCB3aGVuIGNhbmNlbGVkLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAqICAgW2VuXU5vdGlmaWNhdGlvbiBtZXNzYWdlLiBUaGlzIGFyZ3VtZW50IGlzIG9wdGlvbmFsIGJ1dCBpZiBpdCdzIG5vdCBkZWZpbmVkIGVpdGhlciBgb3B0aW9ucy5tZXNzYWdlYCBvciBgb3B0aW9ucy5tZXNzYWdlSFRNTGAgbXVzdCBiZSBkZWZpbmVkIGluc3RlYWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICogQHBhcmFtIHtBcnJheX0gW29wdGlvbnMuYnV0dG9uTGFiZWxzXVxuICogICBbZW5dTGFiZWxzIGZvciB0aGUgYnV0dG9ucy4gRGVmYXVsdCBpcyBgW1wiQ2FuY2VsXCIsIFwiT0tcIl1gLlsvZW5dXG4gKiAgIFtqYV3jg5zjgr/jg7Pjga7jg6njg5njg6vjga7phY3liJfjgpLmjIflrprjgZfjgb7jgZnjgIJbXCJDYW5jZWxcIiwgXCJPS1wiXeOBjOODh+ODleOCqeODq+ODiOOBp+OBmeOAglsvamFdXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMucHJpbWFyeUJ1dHRvbkluZGV4XVxuICogICBbZW5dSW5kZXggb2YgcHJpbWFyeSBidXR0b24uIERlZmF1bHQgaXMgdGhlIGxhc3Qgb25lLlsvZW5dXG4gKiAgIFtqYV3jg5fjg6njgqTjg57jg6rjg5zjgr/jg7Pjga7jgqTjg7Pjg4fjg4Pjgq/jgrnjgpLmjIflrprjgZfjgb7jgZnjgILjg4fjg5Xjgqnjg6vjg4jjga8gMSDjgafjgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBEaXNwbGF5IGEgZGlhbG9nIHRvIGFzayB0aGUgdXNlciBmb3IgY29uZmlybWF0aW9uLiBFeHRlbmRzIGBhbGVydCgpYCBwYXJhbWV0ZXJzLlxuICogICAgIFRoZSBkZWZhdWx0IGJ1dHRvbiBsYWJlbHMgYXJlIGBcIkNhbmNlbFwiYCBhbmQgYFwiT0tcImAgYnV0IHRoZXkgY2FuIGJlIGN1c3RvbWl6ZWQuXG4gKlxuICogICAgIEl0IGNhbiBiZSBjYWxsZWQgaW4gdGhlIGZvbGxvd2luZyB3YXlzOlxuICpcbiAqICAgICBgYGBcbiAqICAgICBvbnMubm90aWZpY2F0aW9uLmNvbmZpcm0obWVzc2FnZSwgb3B0aW9ucyk7XG4gKiAgICAgb25zLm5vdGlmaWNhdGlvbi5jb25maXJtKG9wdGlvbnMpO1xuICogICAgIGBgYFxuICpcbiAqICAgICBNdXN0IHNwZWNpZnkgZWl0aGVyIGBtZXNzYWdlYCBvciBgbWVzc2FnZUhUTUxgLlxuICogICBbL2VuXVxuICogICBbamFdXG4gKiAgICAg44Om44O844K244Gr56K66KqN44KS5L+D44GZ44OA44Kk44Ki44Ot44Kw44KS6KGo56S644GX44G+44GZ44CCXG4gKiAgICAg44OH44Kq44Or44Go44Gu44Oc44K/44Oz44Op44OZ44Or44Gv44CBXCJDYW5jZWxcIuOBqFwiT0tcIuOBp+OBmeOBjOOAgeOBk+OCjOOBr+OBk+OBruODoeOCveODg+ODieOBruW8leaVsOOBp+OCq+OCueOCv+ODnuOCpOOCuuOBp+OBjeOBvuOBmeOAglxuICogICAgIOOBk+OBruODoeOCveODg+ODieOBruW8leaVsOOBq+OBr+OAgW9wdGlvbnMubWVzc2FnZeOCguOBl+OBj+OBr29wdGlvbnMubWVzc2FnZUhUTUzjga7jganjgaHjgonjgYvjgpLlv4XjgZrmjIflrprjgZnjgovlv4XopoHjgYzjgYLjgorjgb7jgZnjgIJcbiAqICAgWy9qYV1cbiAqL1xubm90aWZpY2F0aW9uLmNvbmZpcm0gPSAobWVzc2FnZSwgb3B0aW9ucykgPT5cbiAgbm90aWZpY2F0aW9uLl9jcmVhdGVBbGVydERpYWxvZyhtZXNzYWdlLCBvcHRpb25zLCB7XG4gICAgYnV0dG9uTGFiZWxzOiBbJ0NhbmNlbCcsICdPSyddLFxuICAgIHRpdGxlOiAnQ29uZmlybSdcbiAgfSk7XG5cbi8qKlxuICogQG1ldGhvZCBwcm9tcHRcbiAqIEBzaWduYXR1cmUgcHJvbXB0KG1lc3NhZ2UgWywgb3B0aW9uc10gfCBvcHRpb25zKVxuICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAqICAgW2VuXU5vdGlmaWNhdGlvbiBtZXNzYWdlLiBUaGlzIGFyZ3VtZW50IGlzIG9wdGlvbmFsIGJ1dCBpZiBpdCdzIG5vdCBkZWZpbmVkIGVpdGhlciBgb3B0aW9ucy5tZXNzYWdlYCBvciBgb3B0aW9ucy5tZXNzYWdlSFRNTGAgbXVzdCBiZSBkZWZpbmVkIGluc3RlYWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcmV0dXJuIHtQcm9taXNlfVxuICogICBbZW5dV2lsbCByZXNvbHZlIHRvIHRoZSBpbnB1dCB2YWx1ZSB3aGVuIHRoZSBkaWFsb2cgaXMgY2xvc2VkIG9yIGBudWxsYCB3aGVuIGNhbmNlbGVkLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gKiBAcGFyYW0ge1N0cmluZyB8IEFycmF5fSBbb3B0aW9ucy5idXR0b25MYWJlbHNdXG4gKiAgIFtlbl1MYWJlbHMgZm9yIHRoZSBidXR0b25zLiBEZWZhdWx0IGlzIGBcIk9LXCJgLlsvZW5dXG4gKiAgIFtqYV3norroqo3jg5zjgr/jg7Pjga7jg6njg5njg6vjgpLmjIflrprjgZfjgb7jgZnjgIJcIk9LXCLjgYzjg4fjg5Xjgqnjg6vjg4jjgafjgZnjgIJbL2phXVxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLnByaW1hcnlCdXR0b25JbmRleF1cbiAqICAgW2VuXUluZGV4IG9mIHByaW1hcnkgYnV0dG9uLiBEZWZhdWx0IGlzIHRoZSBsYXN0IG9uZS5bL2VuXVxuICogICBbamFd44OX44Op44Kk44Oe44Oq44Oc44K/44Oz44Gu44Kk44Oz44OH44OD44Kv44K544KS5oyH5a6a44GX44G+44GZ44CC44OH44OV44Kp44Or44OI44GvIDAg44Gn44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5wbGFjZWhvbGRlcl1cbiAqICAgW2VuXVBsYWNlaG9sZGVyIGZvciB0aGUgdGV4dCBpbnB1dC5bL2VuXVxuICogICBbamFd44OG44Kt44K544OI5qyE44Gu44OX44Os44O844K544Ob44Or44OA44Gr6KGo56S644GZ44KL44OG44Kt44K544OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5kZWZhdWx0VmFsdWVdXG4gKiAgIFtlbl1EZWZhdWx0IHZhbHVlIGZvciB0aGUgdGV4dCBpbnB1dC5bL2VuXVxuICogICBbamFd44OG44Kt44K544OI5qyE44Gu44OH44OV44Kp44Or44OI44Gu5YCk44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5pbnB1dFR5cGVdXG4gKiAgIFtlbl1UeXBlIG9mIHRoZSBpbnB1dCBlbGVtZW50IChgcGFzc3dvcmRgLCBgZGF0ZWAuLi4pLiBEZWZhdWx0IGlzIGB0ZXh0YC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMuYXV0b2ZvY3VzXVxuICogICBbZW5dQXV0b2ZvY3VzIHRoZSBpbnB1dCBlbGVtZW50LiBEZWZhdWx0IGlzIGB0cnVlYC4gSW4gQ29yZG92YSwgYEtleWJvYXJkRGlzcGxheVJlcXVpcmVzVXNlckFjdGlvbmAgaW4gYGNvbmZpZy54bWxgIG11c3QgYmUgYGZhbHNlYCB0byBhY3RpdmF0ZSB0aGlzIGZlYXR1cmUuWy9lbl1cbiAqICAgW2phXWlucHV06KaB57Sg44Gr6Ieq5YuV55qE44Gr44OV44Kp44O844Kr44K544GZ44KL44GL44Gp44GG44GL44KS5oyH5a6a44GX44G+44GZ44CC44OH44OV44Kp44Or44OI44GvdHJ1ZeOBp+OBmeOAgkNvcmRvdmHnkrDlooPjgafjga/jgIHjgZPjga7mqZ/og73jgpLmnInlirnjgavjgZnjgovjgZ/jgoHjgavjga8gYGNvbmZpZy54bWxgIOOBpyBgS2V5Ym9hcmREaXNwbGF5UmVxdWlyZXNVc2VyQWN0aW9uYCDjgpIgYGZhbHNlYCDjgavoqK3lrprjgZnjgovlv4XopoHjgYzjgYLjgorjgb7jgZnjgIJbL2phXVxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5zdWJtaXRPbkVudGVyXVxuICogICBbZW5dU3VibWl0IGF1dG9tYXRpY2FsbHkgd2hlbiBlbnRlciBpcyBwcmVzc2VkLiBEZWZhdWx0IGlzIGB0cnVlYC5bL2VuXVxuICogICBbamFdRW50ZXLjgYzmirzjgZXjgozjgZ/pmpvjgavjgZ3jga5mb3Jt44KSc3VibWl044GZ44KL44GL44Gp44GG44GL44KS5oyH5a6a44GX44G+44GZ44CC44OH44OV44Kp44Or44OI44GvdHJ1ZeOBp+OBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIERpc3BsYXkgYSBkaWFsb2cgd2l0aCBhIHByb21wdCB0byBhc2sgdGhlIHVzZXIgYSBxdWVzdGlvbi4gRXh0ZW5kcyBgYWxlcnQoKWAgcGFyYW1ldGVycy5cbiAqXG4gKiAgICAgSXQgY2FuIGJlIGNhbGxlZCBpbiB0aGUgZm9sbG93aW5nIHdheXM6XG4gKlxuICogICAgIGBgYFxuICogICAgIG9ucy5ub3RpZmljYXRpb24ucHJvbXB0KG1lc3NhZ2UsIG9wdGlvbnMpO1xuICogICAgIG9ucy5ub3RpZmljYXRpb24ucHJvbXB0KG9wdGlvbnMpO1xuICogICAgIGBgYFxuICpcbiAqICAgICBNdXN0IHNwZWNpZnkgZWl0aGVyIGBtZXNzYWdlYCBvciBgbWVzc2FnZUhUTUxgLlxuICogICBbL2VuXVxuICogICBbamFdXG4gKiAgICAg44Om44O844K244O844Gr5YWl5Yqb44KS5L+D44GZ44OA44Kk44Ki44Ot44Kw44KS6KGo56S644GX44G+44GZ44CCXG4gKiAgICAg44GT44Gu44Oh44K944OD44OJ44Gu5byV5pWw44Gr44Gv44CBb3B0aW9ucy5tZXNzYWdl44KC44GX44GP44Gvb3B0aW9ucy5tZXNzYWdlSFRNTOOBruOBqeOBoeOCieOBi+OCkuW/heOBmuaMh+WumuOBmeOCi+W/heimgeOBjOOBguOCiuOBvuOBmeOAglxuICogICBbL2phXVxuICovXG5ub3RpZmljYXRpb24ucHJvbXB0ID0gKG1lc3NhZ2UsIG9wdGlvbnMpID0+XG4gIG5vdGlmaWNhdGlvbi5fY3JlYXRlQWxlcnREaWFsb2cobWVzc2FnZSwgb3B0aW9ucywge1xuICAgIGJ1dHRvbkxhYmVsczogWydPSyddLFxuICAgIHRpdGxlOiAnQWxlcnQnLFxuICAgIGlzUHJvbXB0OiB0cnVlLFxuICAgIGF1dG9mb2N1czogdHJ1ZSxcbiAgICBzdWJtaXRPbkVudGVyOiB0cnVlXG4gIH0pO1xuXG4vKipcbiAqIEBtZXRob2QgdG9hc3RcbiAqIEBzaWduYXR1cmUgdG9hc3QobWVzc2FnZSBbLCBvcHRpb25zXSB8IG9wdGlvbnMpXG4gKiBAcmV0dXJuIHtQcm9taXNlfVxuICogICBbZW5dV2lsbCByZXNvbHZlIHdoZW4gdGhlIHRvYXN0IGlzIGhpZGRlbi5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gKiAgIFtlbl1Ub2FzdCBtZXNzYWdlLiBUaGlzIGFyZ3VtZW50IGlzIG9wdGlvbmFsIGJ1dCBpZiBpdCdzIG5vdCBkZWZpbmVkIHRoZW4gYG9wdGlvbnMubWVzc2FnZWAgbXVzdCBiZSBkZWZpbmVkIGluc3RlYWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5tZXNzYWdlXVxuICogICBbZW5dTm90aWZpY2F0aW9uIG1lc3NhZ2UuWy9lbl1cbiAqICAgW2phXeODiOODvOOCueODiOOBq+ihqOekuuOBmeOCi+aWh+Wtl+WIl+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYnV0dG9uTGFiZWxdXG4gKiAgIFtlbl1MYWJlbCBmb3IgdGhlIGJ1dHRvbi5bL2VuXVxuICogICBbamFd56K66KqN44Oc44K/44Oz44Gu44Op44OZ44Or44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBub25lYCwgYGZhZGVgLCBgYXNjZW5kYCwgYGxpZnRgIGFuZCBgZmFsbGAuIERlZmF1bHQgaXMgYGFzY2VuZGAgZm9yIEFuZHJvaWQgYW5kIGBsaWZ0YCBmb3IgaU9TLlsvZW5dXG4gKiAgIFtqYV3jg4jjg7zjgrnjg4jjgpLooajnpLrjgZnjgovpmpvjga7jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcIm5vbmVcIiwgXCJmYWRlXCIsIFwiYXNjZW5kXCIsIFwibGlmdFwiLCBcImZhbGxcIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBp+OBjeOBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMudGltZW91dF1cbiAqICAgW2VuXU51bWJlciBvZiBtaWxpc2Vjb25kcyB3aGVyZSB0aGUgdG9hc3QgaXMgdmlzaWJsZSBiZWZvcmUgaGlkaW5nIGF1dG9tYXRpY2FsbHkuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmZvcmNlXVxuICogICBbZW5dSWYgYHRydWVgLCB0aGUgdG9hc3Qgc2tpcHMgdGhlIG5vdGlmaWNhdGlvbiBxdWV1ZSBhbmQgaXMgc2hvd24gaW1tZWRpYXRlbHkuIERlZmF1bHRzIHRvIGBmYWxzZWAuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuaWRdXG4gKiAgIFtlbl1UaGUgYDxvbnMtdG9hc3Q+YCBlbGVtZW50J3MgSUQuWy9lbl1cbiAqICAgW2phXW9ucy10b2FzdOimgee0oOOBrklE44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5jbGFzc11cbiAqICAgW2VuXVRoZSBgPG9ucy10b2FzdD5gIGVsZW1lbnQncyBjbGFzcy5bL2VuXVxuICogICBbamFdb25zLXRvYXN06KaB57Sg44GuY2xhc3PjgIJbL2phXVxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLm1vZGlmaWVyXVxuICogICBbZW5dTW9kaWZpZXIgZm9yIHRoZSBlbGVtZW50LlsvZW5dXG4gKiAgIFtqYV3jg4jjg7zjgrnjg4jjga5tb2RpZmllcuWxnuaAp+OBruWApOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAqICAgW2VuXUZ1bmN0aW9uIHRoYXQgZXhlY3V0ZXMgYWZ0ZXIgdG9hc3QgaGFzIGJlZW4gaGlkZGVuLlsvZW5dXG4gKiAgIFtqYV3jg4jjg7zjgrnjg4jjgYzplonjgZjjgonjgozjgZ/mmYLjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBEaXNwbGF5IGEgc2ltcGxlIG5vdGlmaWNhdGlvbiB0b2FzdCB3aXRoIGFuIG9wdGlvbmFsIGJ1dHRvbiB0aGF0IGNhbiBiZSB1c2VkIGZvciBzaW1wbGUgYWN0aW9ucy5cbiAqXG4gKiAgICAgSXQgY2FuIGJlIGNhbGxlZCBpbiB0aGUgZm9sbG93aW5nIHdheXM6XG4gKlxuICogICAgIGBgYFxuICogICAgIG9ucy5ub3RpZmljYXRpb24udG9hc3QobWVzc2FnZSwgb3B0aW9ucyk7XG4gKiAgICAgb25zLm5vdGlmaWNhdGlvbi50b2FzdChvcHRpb25zKTtcbiAqICAgICBgYGBcbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKi9cbm5vdGlmaWNhdGlvbi50b2FzdCA9IChtZXNzYWdlLCBvcHRpb25zKSA9PiB7XG4gIGNvbnN0IHByb21pc2UgPSBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICB1dGlsLmNoZWNrTWlzc2luZ0ltcG9ydCgnVG9hc3QnKTsgLy8gVGhyb3dzIGVycm9yLCBtdXN0IGJlIGluc2lkZSBwcm9taXNlXG5cbiAgICBvcHRpb25zID0gX25vcm1hbGl6ZUFyZ3VtZW50cyhtZXNzYWdlLCBvcHRpb25zLCB7XG4gICAgICB0aW1lb3V0OiAwLFxuICAgICAgZm9yY2U6IGZhbHNlXG4gICAgfSk7XG5cbiAgICBsZXQgdG9hc3QgPSB1dGlsLmNyZWF0ZUVsZW1lbnQoYFxuICAgICAgPG9ucy10b2FzdD5cbiAgICAgICAgJHtvcHRpb25zLm1lc3NhZ2V9XG4gICAgICAgICR7b3B0aW9ucy5idXR0b25MYWJlbHMgPyBgPGJ1dHRvbj4ke29wdGlvbnMuYnV0dG9uTGFiZWxzWzBdfTwvYnV0dG9uPmAgOiAnJ31cbiAgICAgIDwvb25zLXRvYXN0PlxuICAgIGApO1xuXG4gICAgX3NldEF0dHJpYnV0ZXModG9hc3QsIG9wdGlvbnMpO1xuXG4gICAgY29uc3QgZmluaXNoID0gdmFsdWUgPT4ge1xuICAgICAgaWYgKHRvYXN0KSB7XG4gICAgICAgIHRvYXN0XG4gICAgICAgIC5oaWRlKClcbiAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIGlmICh0b2FzdCkge1xuICAgICAgICAgICAgdG9hc3QucmVtb3ZlKCk7XG4gICAgICAgICAgICB0b2FzdCA9IG51bGw7XG4gICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKHZhbHVlKTtcbiAgICAgICAgICAgIHJlc29sdmUodmFsdWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGlmIChvcHRpb25zLmJ1dHRvbkxhYmVscykge1xuICAgICAgdXRpbC5maW5kQ2hpbGQodG9hc3QuX3RvYXN0LCAnYnV0dG9uJykub25jbGljayA9ICgpID0+IGZpbmlzaCgwKTtcbiAgICB9XG5cbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRvYXN0KTtcbiAgICBvcHRpb25zLmNvbXBpbGUodG9hc3QpO1xuXG4gICAgY29uc3Qgc2hvdyA9ICgpID0+IHtcbiAgICAgIHRvYXN0LnBhcmVudEVsZW1lbnQgJiYgdG9hc3Quc2hvdyhvcHRpb25zKS50aGVuKCgpID0+IHtcbiAgICAgICAgaWYgKG9wdGlvbnMudGltZW91dCkge1xuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gZmluaXNoKC0xKSwgb3B0aW9ucy50aW1lb3V0KVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgc2V0SW1tZWRpYXRlKCgpID0+IG9wdGlvbnMuZm9yY2UgPyBzaG93KCkgOiBUb2FzdFF1ZXVlLmFkZChzaG93LCBwcm9taXNlKSlcbiAgfSk7XG5cbiAgcmV0dXJuIHByb21pc2U7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBub3RpZmljYXRpb247XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuL3V0aWwnO1xuXG4vLyBWYWxpZGF0ZSBwYXJhbWV0ZXJzXG5jb25zdCBjaGVja09wdGlvbnMgPSBvcHRpb25zID0+IHtcbiAgY29uc3QgZXJyID0gKHByb3AsIHR5cGUgPSAnRnVuY3Rpb24nKSA9PiB1dGlsLnRocm93KGBcIm9wdGlvbnMuJHtwcm9wfVwiIG11c3QgYmUgYW4gaW5zdGFuY2Ugb2YgJHt0eXBlfWApO1xuICBjb25zdCBoYXNPd25Qcm9wZXJ0eSA9IHByb3AgPT4gT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwob3B0aW9ucywgcHJvcCk7XG4gIGNvbnN0IGluc3RhbmNlT2YgPSAocHJvcCwgdHlwZSA9IEZ1bmN0aW9uKSA9PiBvcHRpb25zW3Byb3BdIGluc3RhbmNlb2YgdHlwZTtcblxuICBjb25zdCBiID0gJ2J1dHRvbnMnLCBjYiA9ICdjYWxsYmFjaycsIGMgPSAnY29tcGlsZScsIGQgPSAnZGVzdHJveSc7XG4gICghaGFzT3duUHJvcGVydHkoYikgfHwgIWluc3RhbmNlT2YoYiwgQXJyYXkpKSAmJiBlcnIoYiwgJ0FycmF5Jyk7XG4gIChoYXNPd25Qcm9wZXJ0eShjYikgJiYgIWluc3RhbmNlT2YoY2IpKSAmJiBlcnIoY2IpO1xuICAoaGFzT3duUHJvcGVydHkoYykgJiYgIWluc3RhbmNlT2YoYykpICYmIGVycihjKTtcbiAgKGhhc093blByb3BlcnR5KGQpICYmICFpbnN0YW5jZU9mKGQpKSAmJiBlcnIoZCk7XG59O1xuXG4vLyBBY3Rpb24gU2hlZXRcbmV4cG9ydCBkZWZhdWx0IChvcHRpb25zID0ge30pID0+IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICB1dGlsLmNoZWNrTWlzc2luZ0ltcG9ydCgnQWN0aW9uU2hlZXQnKTtcbiAgY2hlY2tPcHRpb25zKG9wdGlvbnMpO1xuXG4gIC8vIE1haW4gY29tcG9uZW50XG4gIGxldCBhY3Rpb25TaGVldCA9IHV0aWwuY3JlYXRlRWxlbWVudChgXG4gICAgPG9ucy1hY3Rpb24tc2hlZXRcbiAgICAgICR7b3B0aW9ucy50aXRsZSA/IGB0aXRsZT1cIiR7b3B0aW9ucy50aXRsZX1cImAgOiAnJ31cbiAgICAgICR7b3B0aW9ucy5jYW5jZWxhYmxlID8gJ2NhbmNlbGFibGUnIDogJyd9XG4gICAgICAke29wdGlvbnMubW9kaWZpZXIgPyBgbW9kaWZpZXI9XCIke29wdGlvbnMubW9kaWZpZXJ9XCJgIDogJyd9XG4gICAgICAke29wdGlvbnMubWFza0NvbG9yID8gYG1hc2stY29sb3I9XCIke29wdGlvbnMubWFza0NvbG9yfVwiYCA6ICcnfVxuICAgICAgJHtvcHRpb25zLmlkID8gYGlkPVwiJHtvcHRpb25zLmlkfVwiYCA6ICcnfVxuICAgICAgJHtvcHRpb25zLmNsYXNzID8gYGNsYXNzPVwiJHtvcHRpb25zLmNsYXNzfVwiYCA6ICcnfVxuICAgID5cbiAgICAgIDxkaXYgY2xhc3M9XCJhY3Rpb24tc2hlZXRcIj48L2Rpdj5cbiAgICA8L29ucy1hY3Rpb24tc2hlZXQ+XG4gIGApO1xuXG4gIC8vIFJlc29sdmUgYWN0aW9uIGFuZCBjbGVhbiB1cFxuICBjb25zdCBmaW5pc2ggPSAoZXZlbnQsIGluZGV4ID0gLTEpID0+IHtcbiAgICBpZiAoYWN0aW9uU2hlZXQpIHtcbiAgICAgIG9wdGlvbnMuZGVzdHJveSAmJiBvcHRpb25zLmRlc3Ryb3koYWN0aW9uU2hlZXQpO1xuXG4gICAgICBhY3Rpb25TaGVldC5yZW1vdmVFdmVudExpc3RlbmVyKCdkaWFsb2ctY2FuY2VsJywgZmluaXNoLCBmYWxzZSk7XG4gICAgICBhY3Rpb25TaGVldC5yZW1vdmUoKTtcbiAgICAgIGFjdGlvblNoZWV0ID0gbnVsbDtcblxuICAgICAgb3B0aW9ucy5jYWxsYmFjayAmJiBvcHRpb25zLmNhbGxiYWNrKGluZGV4KTtcbiAgICAgIHJlc29sdmUoaW5kZXgpO1xuICAgIH1cbiAgfTtcblxuICAvLyBMaW5rIGNhbmNlbCBoYW5kbGVyXG4gIGFjdGlvblNoZWV0LmFkZEV2ZW50TGlzdGVuZXIoJ2RpYWxvZy1jYW5jZWwnLCBmaW5pc2gsIGZhbHNlKTtcblxuICAvLyBDcmVhdGUgYnV0dG9ucyBhbmQgbGluayBhY3Rpb24gaGFuZGxlclxuICBjb25zdCBidXR0b25zID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO1xuICBvcHRpb25zLmJ1dHRvbnMuZm9yRWFjaCgoaXRlbSwgaW5kZXgpID0+IHtcbiAgICBjb25zdCBidXR0b25PcHRpb25zID0gKHR5cGVvZiBpdGVtID09PSAnc3RyaW5nJykgPyB7IGxhYmVsOiBpdGVtIH0gOiB7IC4uLml0ZW0gfTtcbiAgICBpZiAob3B0aW9ucy5kZXN0cnVjdGl2ZSA9PT0gaW5kZXgpIHtcbiAgICAgIGJ1dHRvbk9wdGlvbnMubW9kaWZpZXIgPSAoYnV0dG9uT3B0aW9ucy5tb2RpZmllciB8fCAnJykgKyAnIGRlc3RydWN0aXZlJztcbiAgICB9XG5cbiAgICBjb25zdCBidXR0b24gPSB1dGlsLmNyZWF0ZUVsZW1lbnQoYFxuICAgICAgPG9ucy1hY3Rpb24tc2hlZXQtYnV0dG9uXG4gICAgICAgICR7YnV0dG9uT3B0aW9ucy5pY29uID8gYGljb249XCIke2J1dHRvbk9wdGlvbnMuaWNvbn1cImAgOiAnJ31cbiAgICAgICAgJHtidXR0b25PcHRpb25zLm1vZGlmaWVyID8gYG1vZGlmaWVyPVwiJHtidXR0b25PcHRpb25zLm1vZGlmaWVyfVwiYCA6ICcnfVxuICAgICAgPlxuICAgICAgICAke2J1dHRvbk9wdGlvbnMubGFiZWx9XG4gICAgICA8L29ucy1hY3Rpb24tc2hlZXQtYnV0dG9uPlxuICAgIGApO1xuXG4gICAgYnV0dG9uLm9uY2xpY2sgPSBldmVudCA9PiBhY3Rpb25TaGVldC5oaWRlKCkudGhlbigoKSA9PiBmaW5pc2goZXZlbnQsIGluZGV4KSk7XG4gICAgYnV0dG9ucy5hcHBlbmRDaGlsZChidXR0b24pO1xuICB9KTtcblxuICAvLyBGaW5pc2ggY29tcG9uZW50IGFuZCBhdHRhY2hcbiAgdXRpbC5maW5kQ2hpbGQoYWN0aW9uU2hlZXQsICcuYWN0aW9uLXNoZWV0JykuYXBwZW5kQ2hpbGQoYnV0dG9ucyk7XG4gIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYWN0aW9uU2hlZXQpO1xuICBvcHRpb25zLmNvbXBpbGUgJiYgb3B0aW9ucy5jb21waWxlKGVsLmRpYWxvZyk7XG5cbiAgLy8gU2hvd1xuICBzZXRJbW1lZGlhdGUoKCkgPT4gYWN0aW9uU2hlZXQuc2hvdyh7XG4gICAgYW5pbWF0aW9uOiBvcHRpb25zLmFuaW1hdGlvbixcbiAgICBhbmltYXRpb25PcHRpb25zOiBvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNcbiAgfSkpO1xufSk7XG4iLCIvKipcbiAqIE1pY3JvRXZlbnQgLSB0byBtYWtlIGFueSBqcyBvYmplY3QgYW4gZXZlbnQgZW1pdHRlciAoc2VydmVyIG9yIGJyb3dzZXIpXG4gKlxuICogLSBwdXJlIGphdmFzY3JpcHQgLSBzZXJ2ZXIgY29tcGF0aWJsZSwgYnJvd3NlciBjb21wYXRpYmxlXG4gKiAtIGRvbnQgcmVseSBvbiB0aGUgYnJvd3NlciBkb21zXG4gKiAtIHN1cGVyIHNpbXBsZSAtIHlvdSBnZXQgaXQgaW1tZWRpYXRlbHksIG5vIG15c3RlcnksIG5vIG1hZ2ljIGludm9sdmVkXG4gKlxuICogLSBjcmVhdGUgYSBNaWNyb0V2ZW50RGVidWcgd2l0aCBnb29kaWVzIHRvIGRlYnVnXG4gKiAgIC0gbWFrZSBpdCBzYWZlciB0byB1c2VcbiovXG5cbi8qKiBOT1RFOiBUaGlzIGxpYnJhcnkgaXMgY3VzdG9taXplZCBmb3IgT25zZW4gVUkuICovXG5cbmNvbnN0IE1pY3JvRXZlbnQgID0gZnVuY3Rpb24oKXt9O1xuTWljcm9FdmVudC5wcm90b3R5cGUgID0ge1xuICBvbjogZnVuY3Rpb24oZXZlbnQsIGZjdCl7XG4gICAgdGhpcy5fZXZlbnRzID0gdGhpcy5fZXZlbnRzIHx8IHt9O1xuICAgIHRoaXMuX2V2ZW50c1tldmVudF0gPSB0aGlzLl9ldmVudHNbZXZlbnRdIHx8IFtdO1xuICAgIHRoaXMuX2V2ZW50c1tldmVudF0ucHVzaChmY3QpO1xuICB9LFxuICBvbmNlOiBmdW5jdGlvbihldmVudCwgZmN0KXtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIHdyYXBwZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgIHNlbGYub2ZmKGV2ZW50LCB3cmFwcGVyKTtcbiAgICAgIHJldHVybiBmY3QuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICB9O1xuICAgIHRoaXMub24oZXZlbnQsIHdyYXBwZXIpO1xuICB9LFxuICBvZmY6IGZ1bmN0aW9uKGV2ZW50LCBmY3Qpe1xuICAgIHRoaXMuX2V2ZW50cyA9IHRoaXMuX2V2ZW50cyB8fCB7fTtcbiAgICBpZiAoZXZlbnQgaW4gdGhpcy5fZXZlbnRzID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX2V2ZW50c1tldmVudF0gPSB0aGlzLl9ldmVudHNbZXZlbnRdXG4gICAgICAuZmlsdGVyKGZ1bmN0aW9uKF9mY3QpIHtcbiAgICAgICAgaWYgKGZjdCkge1xuICAgICAgICAgICByZXR1cm4gZmN0ICE9PSBfZmN0O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH0sXG4gIGVtaXQ6IGZ1bmN0aW9uKGV2ZW50IC8qICwgYXJncy4uLiAqLyl7XG4gICAgdGhpcy5fZXZlbnRzID0gdGhpcy5fZXZlbnRzIHx8IHt9O1xuICAgIGlmIChldmVudCBpbiB0aGlzLl9ldmVudHMgPT09IGZhbHNlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZXZlbnRzW2V2ZW50XS5sZW5ndGg7IGkrKyl7XG4gICAgICB0aGlzLl9ldmVudHNbZXZlbnRdW2ldLmFwcGx5KHRoaXMsIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBtaXhpbiB3aWxsIGRlbGVnYXRlIGFsbCBNaWNyb0V2ZW50LmpzIGZ1bmN0aW9uIGluIHRoZSBkZXN0aW5hdGlvbiBvYmplY3RcbiAqXG4gKiAtIHJlcXVpcmUoJ01pY3JvRXZlbnQnKS5taXhpbihGb29iYXIpIHdpbGwgbWFrZSBGb29iYXIgYWJsZSB0byB1c2UgTWljcm9FdmVudFxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSB0aGUgb2JqZWN0IHdoaWNoIHdpbGwgc3VwcG9ydCBNaWNyb0V2ZW50XG4qL1xuTWljcm9FdmVudC5taXhpbiAgPSBmdW5jdGlvbihkZXN0T2JqZWN0KXtcbiAgdmFyIHByb3BzID0gWydvbicsICdvbmNlJywgJ29mZicsICdlbWl0J107XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpICsrKXtcbiAgICBpZiAodHlwZW9mIGRlc3RPYmplY3QgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGRlc3RPYmplY3QucHJvdG90eXBlW3Byb3BzW2ldXSAgPSBNaWNyb0V2ZW50LnByb3RvdHlwZVtwcm9wc1tpXV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlc3RPYmplY3RbcHJvcHNbaV1dID0gTWljcm9FdmVudC5wcm90b3R5cGVbcHJvcHNbaV1dO1xuICAgIH1cbiAgfVxufVxuXG53aW5kb3cuTWljcm9FdmVudCA9IE1pY3JvRXZlbnQ7XG5leHBvcnQgZGVmYXVsdCBNaWNyb0V2ZW50O1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IE1pY3JvRXZlbnQgZnJvbSAnLi9taWNyb2V2ZW50JztcblxuY29uc3QgY3JlYXRlID0gKCkgPT4ge1xuXG4gIC8qKlxuICAgKiBAb2JqZWN0IG9ucy5vcmllbnRhdGlvblxuICAgKiBAY2F0ZWdvcnkgdXRpbFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVXRpbGl0eSBtZXRob2RzIGZvciBvcmllbnRhdGlvbiBkZXRlY3Rpb24uWy9lbl1cbiAgICogICBbamFd55S76Z2i44Gu44Kq44Oq44Ko44Oz44OG44O844K344On44Oz5qSc55+l44Gu44Gf44KB44Gu44Om44O844OG44Kj44Oq44OG44Kj44Oh44K944OD44OJ44KS5Y+O44KB44Gm44GE44KL44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAgICovXG4gIGNvbnN0IG9iaiA9IHtcbiAgICAvKipcbiAgICAgKiBAZXZlbnQgY2hhbmdlXG4gICAgICogQGRlc2NyaXB0aW9uXG4gICAgICogICBbZW5dRmlyZWQgd2hlbiB0aGUgZGV2aWNlIG9yaWVudGF0aW9uIGNoYW5nZXMuWy9lbl1cbiAgICAgKiAgIFtqYV3jg4fjg5DjgqTjgrnjga7jgqrjg6rjgqjjg7Pjg4bjg7zjgrfjg6fjg7PjgYzlpInljJbjgZfjgZ/pmpvjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgICAqICAgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgICAqICAgW2phXeOCpOODmeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAgICogQHBhcmFtIHtCb29sZWFufSBldmVudC5pc1BvcnRyYWl0XG4gICAgICogICBbZW5dV2lsbCBiZSB0cnVlIGlmIHRoZSBjdXJyZW50IG9yaWVudGF0aW9uIGlzIHBvcnRyYWl0IG1vZGUuWy9lbl1cbiAgICAgKiAgIFtqYV3nj77lnKjjga7jgqrjg6rjgqjjg7Pjg4bjg7zjgrfjg6fjg7PjgYxwb3J0cmFpdOOBruWgtOWQiOOBq3RydWXjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqL1xuXG4gICAgLyoqXG4gICAgICogQG1ldGhvZCBvblxuICAgICAqIEBzaWduYXR1cmUgb24oZXZlbnROYW1lLCBsaXN0ZW5lcilcbiAgICAgKiBAZGVzY3JpcHRpb25cbiAgICAgKiAgIFtlbl1BZGQgYW4gZXZlbnQgbGlzdGVuZXIuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjg6rjgrnjg4rjg7zjgpLov73liqDjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBldmVudE5hbWVcbiAgICAgKiAgIFtlbl1OYW1lIG9mIHRoZSBldmVudC5bL2VuXVxuICAgICAqICAgW2phXeOCpOODmeODs+ODiOWQjeOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXJcbiAgICAgKiAgIFtlbl1GdW5jdGlvbiB0byBleGVjdXRlIHdoZW4gdGhlIGV2ZW50IGlzIHRyaWdnZXJlZC5bL2VuXVxuICAgICAqICAgW2phXeOBk+OBruOCpOODmeODs+ODiOOBjOeZuueBq+OBleOCjOOBn+mam+OBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAgICovXG5cbiAgICAvKipcbiAgICAgKiBAbWV0aG9kIG9uY2VcbiAgICAgKiBAc2lnbmF0dXJlIG9uY2UoZXZlbnROYW1lLCBsaXN0ZW5lcilcbiAgICAgKiBAZGVzY3JpcHRpb25cbiAgICAgKiAgW2VuXUFkZCBhbiBldmVudCBsaXN0ZW5lciB0aGF0J3Mgb25seSB0cmlnZ2VyZWQgb25jZS5bL2VuXVxuICAgICAqICBbamFd5LiA5bqm44Gg44GR5ZG844Gz5Ye644GV44KM44KL44Kk44OZ44Oz44OI44Oq44K544OK44O844KS6L+95Yqg44GX44G+44GZ44CCWy9qYV1cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZlbnROYW1lXG4gICAgICogICBbZW5dTmFtZSBvZiB0aGUgZXZlbnQuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyXG4gICAgICogICBbZW5dRnVuY3Rpb24gdG8gZXhlY3V0ZSB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgYznmbrngavjgZfjgZ/pmpvjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqL1xuXG4gICAgLyoqXG4gICAgICogQG1ldGhvZCBvZmZcbiAgICAgKiBAc2lnbmF0dXJlIG9mZihldmVudE5hbWUsIFtsaXN0ZW5lcl0pXG4gICAgICogQGRlc2NyaXB0aW9uXG4gICAgICogIFtlbl1SZW1vdmUgYW4gZXZlbnQgbGlzdGVuZXIuIElmIHRoZSBsaXN0ZW5lciBpcyBub3Qgc3BlY2lmaWVkIGFsbCBsaXN0ZW5lcnMgZm9yIHRoZSBldmVudCB0eXBlIHdpbGwgYmUgcmVtb3ZlZC5bL2VuXVxuICAgICAqICBbamFd44Kk44OZ44Oz44OI44Oq44K544OK44O844KS5YmK6Zmk44GX44G+44GZ44CC44KC44GX44Kk44OZ44Oz44OI44Oq44K544OK44O844KS5oyH5a6a44GX44Gq44GL44Gj44Gf5aC05ZCI44Gr44Gv44CB44Gd44Gu44Kk44OZ44Oz44OI44Gr57SQ44Gl44GP5YWo44Gm44Gu44Kk44OZ44Oz44OI44Oq44K544OK44O844GM5YmK6Zmk44GV44KM44G+44GZ44CCWy9qYV1cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZlbnROYW1lXG4gICAgICogICBbZW5dTmFtZSBvZiB0aGUgZXZlbnQuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyXG4gICAgICogICBbZW5dRnVuY3Rpb24gdG8gZXhlY3V0ZSB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuWy9lbl1cbiAgICAgKiAgIFtqYV3liYrpmaTjgZnjgovjgqTjg5njg7Pjg4jjg6rjgrnjg4rjg7zjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqL1xuXG4gICAgLy8gYWN0dWFsIGltcGxlbWVudGF0aW9uIHRvIGRldGVjdCBpZiB3aGV0aGVyIGN1cnJlbnQgc2NyZWVuIGlzIHBvcnRyYWl0IG9yIG5vdFxuICAgIF9pc1BvcnRyYWl0OiBmYWxzZSxcblxuICAgIC8qKlxuICAgICAqIEBtZXRob2QgaXNQb3J0cmFpdFxuICAgICAqIEBzaWduYXR1cmUgaXNQb3J0cmFpdCgpXG4gICAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICAgKiAgIFtlbl1XaWxsIGJlIHRydWUgaWYgdGhlIGN1cnJlbnQgb3JpZW50YXRpb24gaXMgcG9ydHJhaXQgbW9kZS5bL2VuXVxuICAgICAqICAgW2phXeOCquODquOCqOODs+ODhuODvOOCt+ODp+ODs+OBjHBvcnRyYWl044Oi44O844OJ44Gu5aC05ZCI44GrdHJ1ZeOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAgICogQGRlc2NyaXB0aW9uXG4gICAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBjdXJyZW50IHNjcmVlbiBvcmllbnRhdGlvbiBpcyBwb3J0cmFpdCBvciBub3QuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqrjg6rjgqjjg7Pjg4bjg7zjgrfjg6fjg7PjgYxwb3J0cmFpdOODouODvOODieOBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAgICovXG4gICAgaXNQb3J0cmFpdDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5faXNQb3J0cmFpdCgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBAbWV0aG9kIGlzTGFuZHNjYXBlXG4gICAgICogQHNpZ25hdHVyZSBpc0xhbmRzY2FwZSgpXG4gICAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICAgKiAgIFtlbl1XaWxsIGJlIHRydWUgaWYgdGhlIGN1cnJlbnQgb3JpZW50YXRpb24gaXMgbGFuZHNjYXBlIG1vZGUuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqrjg6rjgqjjg7Pjg4bjg7zjgrfjg6fjg7PjgYxsYW5kc2NhcGXjg6Ljg7zjg4njga7loLTlkIjjgat0cnVl44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAgICAgKiBAZGVzY3JpcHRpb25cbiAgICAgKiAgIFtlbl1SZXR1cm5zIHdoZXRoZXIgdGhlIGN1cnJlbnQgc2NyZWVuIG9yaWVudGF0aW9uIGlzIGxhbmRzY2FwZSBvciBub3QuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqrjg6rjgqjjg7Pjg4bjg7zjgrfjg6fjg7PjgYxsYW5kc2NhcGXjg6Ljg7zjg4njgYvjganjgYbjgYvjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqL1xuICAgIGlzTGFuZHNjYXBlOiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiAhdGhpcy5pc1BvcnRyYWl0KCk7XG4gICAgfSxcblxuICAgIF9pbml0OiBmdW5jdGlvbigpIHtcbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCB0aGlzLl9vbkRPTUNvbnRlbnRMb2FkZWQuYmluZCh0aGlzKSwgZmFsc2UpO1xuXG4gICAgICBpZiAoJ29yaWVudGF0aW9uJyBpbiB3aW5kb3cpIHtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ29yaWVudGF0aW9uY2hhbmdlJywgdGhpcy5fb25PcmllbnRhdGlvbkNoYW5nZS5iaW5kKHRoaXMpLCBmYWxzZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fb25SZXNpemUuYmluZCh0aGlzKSwgZmFsc2UpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9pc1BvcnRyYWl0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuaW5uZXJIZWlnaHQgPiB3aW5kb3cuaW5uZXJXaWR0aDtcbiAgICAgIH07XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfb25ET01Db250ZW50TG9hZGVkOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuX2luc3RhbGxJc1BvcnRyYWl0SW1wbGVtZW50YXRpb24oKTtcbiAgICAgIHRoaXMuZW1pdCgnY2hhbmdlJywge2lzUG9ydHJhaXQ6IHRoaXMuaXNQb3J0cmFpdCgpfSk7XG4gICAgfSxcblxuICAgIF9pbnN0YWxsSXNQb3J0cmFpdEltcGxlbWVudGF0aW9uOiBmdW5jdGlvbigpIHtcbiAgICAgIGNvbnN0IGlzUG9ydHJhaXQgPSB3aW5kb3cuaW5uZXJXaWR0aCA8IHdpbmRvdy5pbm5lckhlaWdodDtcblxuICAgICAgaWYgKCEoJ29yaWVudGF0aW9uJyBpbiB3aW5kb3cpKSB7XG4gICAgICAgIHRoaXMuX2lzUG9ydHJhaXQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gd2luZG93LmlubmVySGVpZ2h0ID4gd2luZG93LmlubmVyV2lkdGg7XG4gICAgICAgIH07XG4gICAgICB9IGVsc2UgaWYgKHdpbmRvdy5vcmllbnRhdGlvbiAlIDE4MCA9PT0gMCkge1xuICAgICAgICB0aGlzLl9pc1BvcnRyYWl0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIE1hdGguYWJzKHdpbmRvdy5vcmllbnRhdGlvbiAlIDE4MCkgPT09IDAgPyBpc1BvcnRyYWl0IDogIWlzUG9ydHJhaXQ7XG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9pc1BvcnRyYWl0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIE1hdGguYWJzKHdpbmRvdy5vcmllbnRhdGlvbiAlIDE4MCkgPT09IDkwID8gaXNQb3J0cmFpdCA6ICFpc1BvcnRyYWl0O1xuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0sXG5cbiAgICBfb25PcmllbnRhdGlvbkNoYW5nZTogZnVuY3Rpb24oKSB7XG4gICAgICBjb25zdCBpc1BvcnRyYWl0ID0gdGhpcy5faXNQb3J0cmFpdCgpO1xuXG4gICAgICAvLyBXYWl0IGZvciB0aGUgZGltZW5zaW9ucyB0byBjaGFuZ2UgYmVjYXVzZVxuICAgICAgLy8gb2YgQW5kcm9pZCBpbmNvbnNpc3RlbmN5LlxuICAgICAgbGV0IG5JdGVyID0gMDtcbiAgICAgIGNvbnN0IGludGVydmFsID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICBuSXRlcisrO1xuXG4gICAgICAgIGNvbnN0IHcgPSB3aW5kb3cuaW5uZXJXaWR0aDtcbiAgICAgICAgY29uc3QgaCA9IHdpbmRvdy5pbm5lckhlaWdodDtcblxuICAgICAgICBpZiAoKGlzUG9ydHJhaXQgJiYgdyA8PSBoKSB8fFxuICAgICAgICAgICAoIWlzUG9ydHJhaXQgJiYgdyA+PSBoKSkge1xuICAgICAgICAgIHRoaXMuZW1pdCgnY2hhbmdlJywge2lzUG9ydHJhaXQ6IGlzUG9ydHJhaXR9KTtcbiAgICAgICAgICBjbGVhckludGVydmFsKGludGVydmFsKTtcbiAgICAgICAgfSBlbHNlIGlmIChuSXRlciA9PT0gNTApIHtcbiAgICAgICAgICB0aGlzLmVtaXQoJ2NoYW5nZScsIHtpc1BvcnRyYWl0OiBpc1BvcnRyYWl0fSk7XG4gICAgICAgICAgY2xlYXJJbnRlcnZhbChpbnRlcnZhbCk7XG4gICAgICAgIH1cbiAgICAgIH0sIDIwKTtcbiAgICB9LFxuXG4gICAgLy8gUnVuIG9uIG5vdCBtb2JpbGUgYnJvd3Nlci5cbiAgICBfb25SZXNpemU6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5lbWl0KCdjaGFuZ2UnLCB7aXNQb3J0cmFpdDogdGhpcy5pc1BvcnRyYWl0KCl9KTtcbiAgICB9XG4gIH07XG5cbiAgTWljcm9FdmVudC5taXhpbihvYmopO1xuXG4gIHJldHVybiBvYmo7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBjcmVhdGUoKS5faW5pdCgpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi91dGlsJztcblxuLyoqXG4gKiBAb2JqZWN0IG9ucy5tb2RpZmllclxuICogQGNhdGVnb3J5IHZpc3VhbFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBVdGlsaXR5IG1ldGhvZHMgdG8gY2hhbmdlIG1vZGlmaWVyIGF0dHJpYnV0ZXMgb2YgT25zZW4gVUkgZWxlbWVudHMuLlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBleGFtcGxlXG4gKiBvbnMubW9kaWZpZXIuYWRkKG15T25zSW5wdXRFbGVtZW50LCAndW5kZXJiYXInKTtcbiAqIG9ucy5tb2RpZmllci50b2dnbGUobXlPbnNUb2FzdEVsZW1lbnQsICdjdXN0b20tbW9kaWZpZXInKTtcbiAqXG4gKi9cbmV4cG9ydCBkZWZhdWx0IHtcbiAgLyoqXG4gICAqIEBtZXRob2QgYWRkXG4gICAqIEBzaWduYXR1cmUgYWRkKGVsZW1lbnQsIG1vZGlmaWVyIFssIG1vZGlmaWVyXSlcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUFkZCB0aGUgc3BlY2lmaWVkIG1vZGlmaWVycyB0byB0aGUgZWxlbWVudCBpZiB0aGV5IGFyZSBub3QgYWxyZWFkeSBpbmNsdWRlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gICAqICAgW2VuXVRhcmdldCBlbGVtZW50LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtb2RpZmllclxuICAgKiAgIFtlbl1OYW1lIG9mIHRoZSBtb2RpZmllci5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgYWRkOiAoZWxlbWVudCwgLi4ubW9kaWZpZXJzKSA9PiBtb2RpZmllcnMuZm9yRWFjaChtb2RpZmllciA9PiB1dGlsLmFkZE1vZGlmaWVyKGVsZW1lbnQsIG1vZGlmaWVyKSksXG4gIC8qKlxuICAgKiBAbWV0aG9kIHJlbW92ZVxuICAgKiBAc2lnbmF0dXJlIHJlbW92ZShlbGVtZW50LCBtb2RpZmllciBbLCBtb2RpZmllcl0pXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZW1vdmUgdGhlIHNwZWNpZmllZCBtb2RpZmllcnMgZnJvbSB0aGUgZWxlbWVudCBpZiB0aGV5IGFyZSBpbmNsdWRlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gICAqICAgW2VuXVRhcmdldCBlbGVtZW50LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtb2RpZmllclxuICAgKiAgIFtlbl1OYW1lIG9mIHRoZSBtb2RpZmllci5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgcmVtb3ZlOiAoZWxlbWVudCwgLi4ubW9kaWZpZXJzKSA9PiBtb2RpZmllcnMuZm9yRWFjaChtb2RpZmllciA9PiB1dGlsLnJlbW92ZU1vZGlmaWVyKGVsZW1lbnQsIG1vZGlmaWVyKSksXG4gIC8qKlxuICAgKiBAbWV0aG9kIGNvbnRhaW5zXG4gICAqIEBzaWduYXR1cmUgY29udGFpbnMoZWxlbWVudCwgbW9kaWZpZXIpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DaGVjayB3aGV0aGVyIHRoZSBzcGVjaWZpZWQgbW9kaWZpZXIgaXMgaW5jbHVkZWQgaW4gdGhlIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiAgIFtlbl1UYXJnZXQgZWxlbWVudC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbW9kaWZpZXJcbiAgICogICBbZW5dTmFtZSBvZiB0aGUgbW9kaWZpZXIuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICogICBbZW5dYHRydWVgIHdoZW4gdGhlIHNwZWNpZmllZCBtb2RpZmllciBpcyBmb3VuZCBpbiB0aGUgZWxlbWVudCdzIGBtb2RpZmllcmAgYXR0cmlidXRlLiBgZmFsc2VgIG90aGVyd2lzZS5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgY29udGFpbnM6IHV0aWwuaGFzTW9kaWZpZXIsXG4gIC8qKlxuICAgKiBAbWV0aG9kIHRvZ2dsZVxuICAgKiBAc2lnbmF0dXJlIHRvZ2dsZShlbGVtZW50LCBtb2RpZmllciBbLCBmb3JjZV0pXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Ub2dnbGUgdGhlIHNwZWNpZmllZCBtb2RpZmllci5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gICAqICAgW2VuXVRhcmdldCBlbGVtZW50LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtb2RpZmllclxuICAgKiAgIFtlbl1OYW1lIG9mIHRoZSBtb2RpZmllci5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gZm9yY2VcbiAgICogICBbZW5dSWYgaXQgZXZhbHVhdGVzIHRvIHRydWUsIGFkZCBzcGVjaWZpZWQgbW9kaWZpZXIgdmFsdWUsIGFuZCBpZiBpdCBldmFsdWF0ZXMgdG8gZmFsc2UsIHJlbW92ZSBpdC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgdG9nZ2xlOiB1dGlsLnRvZ2dsZU1vZGlmaWVyXG59O1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi91dGlsJztcbmltcG9ydCBNaWNyb0V2ZW50IGZyb20gJy4vbWljcm9ldmVudCc7XG5cbmNvbnN0IHNvZnR3YXJlS2V5Ym9hcmQgPSBuZXcgTWljcm9FdmVudCgpO1xuc29mdHdhcmVLZXlib2FyZC5fdmlzaWJsZSA9IGZhbHNlO1xuXG5jb25zdCBvblNob3cgPSAoKSA9PiB7XG4gIHNvZnR3YXJlS2V5Ym9hcmQuX3Zpc2libGUgPSB0cnVlO1xuICBzb2Z0d2FyZUtleWJvYXJkLmVtaXQoJ3Nob3cnKTtcbn07XG5cbmNvbnN0IG9uSGlkZSA9ICgpID0+IHtcbiAgc29mdHdhcmVLZXlib2FyZC5fdmlzaWJsZSA9IGZhbHNlO1xuICBzb2Z0d2FyZUtleWJvYXJkLmVtaXQoJ2hpZGUnKTtcbn07XG5cbmNvbnN0IGJpbmRFdmVudHMgPSAoKSA9PiB7XG4gIGlmICh0eXBlb2YgS2V5Ym9hcmQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL21hcnRpbm1vc2UvY29yZG92YS1rZXlib2FyZC9ibG9iLzk1ZjNkYTNhMzhkOGY4ZTFmYTQxZmJmNDAxNDUzNTJjMTM1MzVhMDAvUkVBRE1FLm1kXG4gICAgS2V5Ym9hcmQub25zaG93ID0gb25TaG93O1xuICAgIEtleWJvYXJkLm9uaGlkZSA9IG9uSGlkZTtcbiAgICBzb2Z0d2FyZUtleWJvYXJkLmVtaXQoJ2luaXQnLCB7dmlzaWJsZTogS2V5Ym9hcmQuaXNWaXNpYmxlfSk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgY29yZG92YS5wbHVnaW5zICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgY29yZG92YS5wbHVnaW5zLktleWJvYXJkICE9PSAndW5kZWZpbmVkJykge1xuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9kcmlmdHljby9pb25pYy1wbHVnaW5zLWtleWJvYXJkL2Jsb2IvY2EyN2VjZi9SRUFETUUubWRcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbmF0aXZlLmtleWJvYXJkc2hvdycsIG9uU2hvdyk7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ25hdGl2ZS5rZXlib2FyZGhpZGUnLCBvbkhpZGUpO1xuICAgIHNvZnR3YXJlS2V5Ym9hcmQuZW1pdCgnaW5pdCcsIHt2aXNpYmxlOiBjb3Jkb3ZhLnBsdWdpbnMuS2V5Ym9hcmQuaXNWaXNpYmxlfSk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbmNvbnN0IG5vUGx1Z2luRXJyb3IgPSAoKSA9PiB7XG4gIHV0aWwud2Fybignb25zLWtleWJvYXJkOiBDb3Jkb3ZhIEtleWJvYXJkIHBsdWdpbiBpcyBub3QgcHJlc2VudC4nKTtcbn07XG5cbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RldmljZXJlYWR5JywgKCkgPT4ge1xuICBpZiAoIWJpbmRFdmVudHMoKSkge1xuICAgIGlmIChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdbb25zLWtleWJvYXJkLWFjdGl2ZV0nKSB8fFxuICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvcignW29ucy1rZXlib2FyZC1pbmFjdGl2ZV0nKSkge1xuICAgICAgbm9QbHVnaW5FcnJvcigpO1xuICAgIH1cblxuICAgIHNvZnR3YXJlS2V5Ym9hcmQub24gPSBub1BsdWdpbkVycm9yO1xuICB9XG59KTtcblxuZXhwb3J0IGRlZmF1bHQgc29mdHdhcmVLZXlib2FyZDtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmNvbnN0IGdlbmVyYXRlSWQgPSAoZnVuY3Rpb24oKSB7XG4gIGxldCBpID0gMDtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBpKys7XG4gIH07XG59KSgpO1xuXG4vKipcbiAqIERvb3IgbG9ja2luZyBzeXN0ZW0uXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMubG9nXVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBEb29yTG9jayB7XG5cbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5fbG9ja0xpc3QgPSBbXTtcbiAgICB0aGlzLl93YWl0TGlzdCA9IFtdO1xuICAgIHRoaXMuX2xvZyA9IG9wdGlvbnMubG9nIHx8IGZ1bmN0aW9uKCkge307XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXIgYSBsb2NrLlxuICAgKlxuICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gQ2FsbGJhY2sgZm9yIHVubG9ja2luZy5cbiAgICovXG4gIGxvY2soKSB7XG4gICAgY29uc3QgdW5sb2NrID0gKCkgPT4ge1xuICAgICAgdGhpcy5fdW5sb2NrKHVubG9jayk7XG4gICAgfTtcbiAgICB1bmxvY2suaWQgPSBnZW5lcmF0ZUlkKCk7XG4gICAgdGhpcy5fbG9ja0xpc3QucHVzaCh1bmxvY2spO1xuICAgIHRoaXMuX2xvZygnbG9jazogJyArICh1bmxvY2suaWQpKTtcblxuICAgIHJldHVybiB1bmxvY2s7XG4gIH1cblxuICBfdW5sb2NrKGZuKSB7XG4gICAgY29uc3QgaW5kZXggPSB0aGlzLl9sb2NrTGlzdC5pbmRleE9mKGZuKTtcbiAgICBpZiAoaW5kZXggPT09IC0xKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoaXMgZnVuY3Rpb24gaXMgbm90IHJlZ2lzdGVyZWQgaW4gdGhlIGxvY2sgbGlzdC4nKTtcbiAgICB9XG5cbiAgICB0aGlzLl9sb2NrTGlzdC5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIHRoaXMuX2xvZygndW5sb2NrOiAnICsgZm4uaWQpO1xuXG4gICAgdGhpcy5fdHJ5VG9GcmVlV2FpdExpc3QoKTtcbiAgfVxuXG4gIF90cnlUb0ZyZWVXYWl0TGlzdCgpIHtcbiAgICB3aGlsZSAoIXRoaXMuaXNMb2NrZWQoKSAmJiB0aGlzLl93YWl0TGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLl93YWl0TGlzdC5zaGlmdCgpKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVyIGEgY2FsbGJhY2sgZm9yIHdhaXRpbmcgdW5sb2NrZWQgZG9vci5cbiAgICpcbiAgICogQHBhcmFtcyB7RnVuY3Rpb259IGNhbGxiYWNrIENhbGxiYWNrIG9uIHVubG9ja2luZyB0aGUgZG9vciBjb21wbGV0ZWx5LlxuICAgKi9cbiAgd2FpdFVubG9jayhjYWxsYmFjaykge1xuICAgIGlmICghKGNhbGxiYWNrIGluc3RhbmNlb2YgRnVuY3Rpb24pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBjYWxsYmFjayBwYXJhbSBtdXN0IGJlIGEgZnVuY3Rpb24uJyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaXNMb2NrZWQoKSkge1xuICAgICAgdGhpcy5fd2FpdExpc3QucHVzaChjYWxsYmFjayk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNhbGxiYWNrKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0xvY2tlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5fbG9ja0xpc3QubGVuZ3RoID4gMDtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cbmltcG9ydCB1dGlsIGZyb20gJy4vdXRpbCc7XG5pbXBvcnQgaW50ZXJuYWwgZnJvbSAnLi9pbnRlcm5hbCc7XG5cbi8vIERlZmF1bHQgaW1wbGVtZW50YXRpb24gZm9yIGdsb2JhbCBQYWdlTG9hZGVyLlxuZnVuY3Rpb24gbG9hZFBhZ2Uoe3BhZ2UsIHBhcmVudCwgcGFyYW1zID0ge319LCBkb25lKSB7XG4gIGludGVybmFsLmdldFBhZ2VIVE1MQXN5bmMocGFnZSkudGhlbihodG1sID0+IHtcbiAgICBjb25zdCBwYWdlRWxlbWVudCA9IHV0aWwuY3JlYXRlRWxlbWVudChodG1sKTtcbiAgICBwYXJlbnQuYXBwZW5kQ2hpbGQocGFnZUVsZW1lbnQpO1xuXG4gICAgZG9uZShwYWdlRWxlbWVudCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiB1bmxvYWRQYWdlKGVsZW1lbnQpIHtcbiAgaWYgKGVsZW1lbnQuX2Rlc3Ryb3kgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIGVsZW1lbnQuX2Rlc3Ryb3koKTtcbiAgfSBlbHNlIHtcbiAgICBlbGVtZW50LnJlbW92ZSgpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBQYWdlTG9hZGVyIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtmbl0gUmV0dXJucyBhbiBvYmplY3QgdGhhdCBoYXMgXCJlbGVtZW50XCIgcHJvcGVydHkgYW5kIFwidW5sb2FkXCIgZnVuY3Rpb24uXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihsb2FkZXIsIHVubG9hZGVyKSB7XG4gICAgdGhpcy5fbG9hZGVyID0gbG9hZGVyIGluc3RhbmNlb2YgRnVuY3Rpb24gPyBsb2FkZXIgOiBsb2FkUGFnZTtcbiAgICB0aGlzLl91bmxvYWRlciA9IHVubG9hZGVyIGluc3RhbmNlb2YgRnVuY3Rpb24gPyB1bmxvYWRlciA6IHVubG9hZFBhZ2U7XG4gIH1cblxuICAvKipcbiAgICogU2V0IGludGVybmFsIGxvYWRlciBpbXBsZW1lbnRhdGlvbi5cbiAgICovXG4gIHNldCBpbnRlcm5hbExvYWRlcihmbikge1xuICAgIGlmICghKGZuIGluc3RhbmNlb2YgRnVuY3Rpb24pKSB7XG4gICAgICB0aHJvdyBFcnJvcignRmlyc3QgcGFyYW1ldGVyIG11c3QgYmUgYW4gaW5zdGFuY2Ugb2YgRnVuY3Rpb24nKTtcbiAgICB9XG4gICAgdGhpcy5fbG9hZGVyID0gZm47XG4gIH1cblxuICBnZXQgaW50ZXJuYWxMb2FkZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2xvYWRlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge2FueX0gb3B0aW9ucy5wYWdlXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gb3B0aW9ucy5wYXJlbnQgQSBsb2NhdGlvbiB0byBsb2FkIHBhZ2UuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucy5wYXJhbXNdIEV4dHJhIHBhcmFtZXRlcnMgZm9yIG9ucy1wYWdlLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lIFRha2UgYW4gb2JqZWN0IHRoYXQgaGFzIFwiZWxlbWVudFwiIHByb3BlcnR5IGFuZCBcInVubG9hZFwiIGZ1bmN0aW9uLlxuICAgKi9cbiAgbG9hZCh7cGFnZSwgcGFyZW50LCBwYXJhbXMgPSB7fX0sIGRvbmUpIHtcbiAgICB0aGlzLl9sb2FkZXIoe3BhZ2UsIHBhcmVudCwgcGFyYW1zfSwgcGFnZUVsZW1lbnQgPT4ge1xuICAgICAgaWYgKCEocGFnZUVsZW1lbnQgaW5zdGFuY2VvZiBFbGVtZW50KSkge1xuICAgICAgICB0aHJvdyBFcnJvcigncGFnZUVsZW1lbnQgbXVzdCBiZSBhbiBpbnN0YW5jZSBvZiBFbGVtZW50LicpO1xuICAgICAgfVxuXG4gICAgICBkb25lKHBhZ2VFbGVtZW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIHVubG9hZChwYWdlRWxlbWVudCkge1xuICAgIGlmICghKHBhZ2VFbGVtZW50IGluc3RhbmNlb2YgRWxlbWVudCkpIHtcbiAgICAgIHRocm93IEVycm9yKCdwYWdlRWxlbWVudCBtdXN0IGJlIGFuIGluc3RhbmNlIG9mIEVsZW1lbnQuJyk7XG4gICAgfVxuXG4gICAgdGhpcy5fdW5sb2FkZXIocGFnZUVsZW1lbnQpO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBkZWZhdWx0UGFnZUxvYWRlciA9IG5ldyBQYWdlTG9hZGVyKCk7XG5cbmV4cG9ydCBjb25zdCBpbnN0YW50UGFnZUxvYWRlciA9IG5ldyBQYWdlTG9hZGVyKFxuICBmdW5jdGlvbih7cGFnZSwgcGFyZW50LCBwYXJhbXMgPSB7fX0sIGRvbmUpIHtcbiAgICBjb25zdCBlbGVtZW50ID0gdXRpbC5jcmVhdGVFbGVtZW50KHBhZ2UudHJpbSgpKTtcbiAgICBwYXJlbnQuYXBwZW5kQ2hpbGQoZWxlbWVudCk7XG5cbiAgICBkb25lKGVsZW1lbnQpO1xuICB9LFxuICB1bmxvYWRQYWdlXG4pO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi91dGlsJztcbmltcG9ydCBlbGVtZW50cyBmcm9tICcuL2VsZW1lbnRzJ1xuaW1wb3J0IGFuaW1pdCBmcm9tICcuL2FuaW1pdCdcbmltcG9ydCBHZXN0dXJlRGV0ZWN0b3IgZnJvbSAnLi9nZXN0dXJlLWRldGVjdG9yJztcbmltcG9ydCBwbGF0Zm9ybSBmcm9tICcuL3BsYXRmb3JtJztcbmltcG9ydCBub3RpZmljYXRpb24gZnJvbSAnLi9ub3RpZmljYXRpb24nO1xuaW1wb3J0IGFjdGlvblNoZWV0IGZyb20gJy4vYWN0aW9uLXNoZWV0JztcbmltcG9ydCBpbnRlcm5hbCBmcm9tICcuL2ludGVybmFsJztcbmltcG9ydCBvcmllbnRhdGlvbiBmcm9tICcuL29yaWVudGF0aW9uJztcbmltcG9ydCBtb2RpZmllciBmcm9tICcuL21vZGlmaWVyJztcbmltcG9ydCBzb2Z0d2FyZUtleWJvYXJkIGZyb20gJy4vc29mdHdhcmUta2V5Ym9hcmQnO1xuaW1wb3J0IHBhZ2VBdHRyaWJ1dGVFeHByZXNzaW9uIGZyb20gJy4vcGFnZS1hdHRyaWJ1dGUtZXhwcmVzc2lvbic7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4vYXV0b3N0eWxlJztcbmltcG9ydCBEb29yTG9jayBmcm9tICcuL2Rvb3Jsb2NrJztcbmltcG9ydCB7IGRlZmF1bHRQYWdlTG9hZGVyLCBQYWdlTG9hZGVyIH0gZnJvbSAnLi9wYWdlLWxvYWRlcic7XG5cbi8qKlxuICogQG9iamVjdCBvbnNcbiAqIEBjYXRlZ29yeSB1dGlsXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2phXU9uc2VuIFVJ44Gn5Yip55So44Gn44GN44KL44Kw44Ot44O844OQ44Or44Gq44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAqICAgW2VuXUEgZ2xvYmFsIG9iamVjdCB0aGF0J3MgdXNlZCBpbiBPbnNlbiBVSS4gWy9lbl1cbiAqL1xuY29uc3Qgb25zID0ge1xuICBhbmltaXQsXG4gIGRlZmF1bHRQYWdlTG9hZGVyLFxuICBlbGVtZW50cyxcbiAgR2VzdHVyZURldGVjdG9yLFxuICBtb2RpZmllcixcbiAgbm90aWZpY2F0aW9uLFxuICBvcmllbnRhdGlvbixcbiAgcGFnZUF0dHJpYnV0ZUV4cHJlc3Npb24sXG4gIFBhZ2VMb2FkZXIsXG4gIHBsYXRmb3JtLFxuICBzb2Z0d2FyZUtleWJvYXJkLFxuICBfYXV0b1N0eWxlOiBhdXRvU3R5bGUsXG4gIF9pbnRlcm5hbDogaW50ZXJuYWwsXG4gIF9yZWFkeUxvY2s6IG5ldyBEb29yTG9jaygpLFxuICBfdXRpbDogdXRpbCxcbn07XG5cbm9ucy5wbGF0Zm9ybS5zZWxlY3QoKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gubWF0Y2goL3BsYXRmb3JtPShbXFx3LV0rKS8pIHx8IFtdKVsxXSk7XG5cbndhaXREZXZpY2VSZWFkeSgpO1xuXG5jb25zdCByZWFkeUVycm9yID0gYWZ0ZXIgPT4gdXRpbC50aHJvdyhgVGhpcyBtZXRob2QgbXVzdCBiZSBjYWxsZWQgJHthZnRlciA/ICdhZnRlcicgOiAnYmVmb3JlJ30gb25zLmlzUmVhZHkoKSBpcyB0cnVlYCk7XG5cbi8qKlxuICogQG1ldGhvZCBpc1JlYWR5XG4gKiBAc2lnbmF0dXJlIGlzUmVhZHkoKVxuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqICAgW2VuXVdpbGwgYmUgdHJ1ZSBpZiBPbnNlbiBVSSBpcyBpbml0aWFsaXplZC5bL2VuXVxuICogICBbamFd5Yid5pyf5YyW44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dUmV0dXJucyB0cnVlIGlmIE9uc2VuIFVJIGlzIGluaXRpYWxpemVkLlsvZW5dXG4gKiAgIFtqYV1PbnNlbiBVSeOBjOOBmeOBp+OBq+WIneacn+WMluOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBmeODoeOCveODg+ODieOBp+OBmeOAglsvamFdXG4gKi9cbm9ucy5pc1JlYWR5ID0gKCkgPT4ge1xuICByZXR1cm4gIW9ucy5fcmVhZHlMb2NrLmlzTG9ja2VkKCk7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgaXNXZWJWaWV3XG4gKiBAc2lnbmF0dXJlIGlzV2ViVmlldygpXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICogICBbZW5dV2lsbCBiZSB0cnVlIGlmIHRoZSBhcHAgaXMgcnVubmluZyBpbiBDb3Jkb3ZhLlsvZW5dXG4gKiAgIFtqYV1Db3Jkb3Zh44Gn5a6f6KGM44GV44KM44Gm44GE44KL5aC05ZCI44GrdHJ1ZeOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVJldHVybnMgdHJ1ZSBpZiBydW5uaW5nIGluc2lkZSBDb3Jkb3ZhLlsvZW5dXG4gKiAgIFtqYV1Db3Jkb3Zh44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GZ44Oh44K944OD44OJ44Gn44GZ44CCWy9qYV1cbiAqL1xub25zLmlzV2ViVmlldyA9IG9ucy5wbGF0Zm9ybS5pc1dlYlZpZXc7XG5cbi8qKlxuICogQG1ldGhvZCByZWFkeVxuICogQHNpZ25hdHVyZSByZWFkeShjYWxsYmFjaylcbiAqIEBkZXNjcmlwdGlvblxuICogICBbamFd44Ki44OX44Oq44Gu5Yid5pyf5YyW44Gr5Yip55So44GZ44KL44Oh44K944OD44OJ44Gn44GZ44CC5rih44GV44KM44Gf6Zai5pWw44Gv44CBT25zZW4gVUnjga7liJ3mnJ/ljJbjgYzntYLkuobjgZfjgabjgYTjgovmmYLngrnjgaflv4XjgZrlkbzjgbDjgozjgb7jgZnjgIJbL2phXVxuICogICBbZW5dTWV0aG9kIHVzZWQgdG8gd2FpdCBmb3IgYXBwIGluaXRpYWxpemF0aW9uLiBXYWl0cyBmb3IgYERPTUNvbnRlbnRMb2FkZWRgIGFuZCBgZGV2aWNlcmVhZHlgLCB3aGVuIG5lY2Vzc2FyeSwgYmVmb3JlIGV4ZWN1dGluZyB0aGUgY2FsbGJhY2suWy9lbl1cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gKiAgIFtlbl1GdW5jdGlvbiB0aGF0IGV4ZWN1dGVzIGFmdGVyIE9uc2VuIFVJIGhhcyBiZWVuIGluaXRpYWxpemVkLlsvZW5dXG4gKiAgIFtqYV1PbnNlbiBVSeOBjOWIneacn+WMluOBjOWujOS6huOBl+OBn+W+jOOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKi9cbm9ucy5yZWFkeSA9IGNhbGxiYWNrID0+IHtcbiAgaWYgKG9ucy5pc1JlYWR5KCkpIHtcbiAgICBjYWxsYmFjaygpO1xuICB9IGVsc2Uge1xuICAgIG9ucy5fcmVhZHlMb2NrLndhaXRVbmxvY2soY2FsbGJhY2spO1xuICB9XG59O1xuXG4vKipcbiAqIEBtZXRob2Qgc2V0RGVmYXVsdERldmljZUJhY2tCdXR0b25MaXN0ZW5lclxuICogQHNpZ25hdHVyZSBzZXREZWZhdWx0RGV2aWNlQmFja0J1dHRvbkxpc3RlbmVyKGxpc3RlbmVyKVxuICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXJcbiAqICAgW2VuXUZ1bmN0aW9uIHRoYXQgZXhlY3V0ZXMgd2hlbiBkZXZpY2UgYmFjayBidXR0b24gaXMgcHJlc3NlZC4gTXVzdCBiZSBjYWxsZWQgb24gYG9ucy5yZWFkeWAuWy9lbl1cbiAqICAgW2phXeODh+ODkOOCpOOCueOBruODkOODg+OCr+ODnOOCv+ODs+OBjOaKvOOBleOCjOOBn+aZguOBq+Wun+ihjOOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVNldCBkZWZhdWx0IGhhbmRsZXIgZm9yIGRldmljZSBiYWNrIGJ1dHRvbi5bL2VuXVxuICogICBbamFd44OH44OQ44Kk44K544Gu44OQ44OD44Kv44Oc44K/44Oz44Gu44Gf44KB44Gu44OH44OV44Kp44Or44OI44Gu44OP44Oz44OJ44Op44KS6Kit5a6a44GX44G+44GZ44CCWy9qYV1cbiAqL1xub25zLnNldERlZmF1bHREZXZpY2VCYWNrQnV0dG9uTGlzdGVuZXIgPSBmdW5jdGlvbihsaXN0ZW5lcikge1xuICBpZiAoIW9ucy5pc1JlYWR5KCkpIHtcbiAgICByZWFkeUVycm9yKHRydWUpO1xuICB9XG4gIG9ucy5fZGVmYXVsdERldmljZUJhY2tCdXR0b25IYW5kbGVyLnNldExpc3RlbmVyKGxpc3RlbmVyKTtcbn07XG5cbi8qKlxuICogQG1ldGhvZCBkaXNhYmxlRGV2aWNlQmFja0J1dHRvbkhhbmRsZXJcbiAqIEBzaWduYXR1cmUgZGlzYWJsZURldmljZUJhY2tCdXR0b25IYW5kbGVyKClcbiAqIEBkZXNjcmlwdGlvblxuICogW2VuXURpc2FibGUgZGV2aWNlIGJhY2sgYnV0dG9uIGV2ZW50IGhhbmRsZXIuIE11c3QgYmUgY2FsbGVkIG9uIGBvbnMucmVhZHlgLlsvZW5dXG4gKiBbamFd44OH44OQ44Kk44K544Gu44OQ44OD44Kv44Oc44K/44Oz44Gu44Kk44OZ44Oz44OI44KS5Y+X44GR5LuY44GR44Gq44GE44KI44GG44Gr44GX44G+44GZ44CCWy9qYV1cbiAqL1xub25zLmRpc2FibGVEZXZpY2VCYWNrQnV0dG9uSGFuZGxlciA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIW9ucy5pc1JlYWR5KCkpIHtcbiAgICByZWFkeUVycm9yKHRydWUpO1xuICB9XG4gIGludGVybmFsLmRiYkRpc3BhdGNoZXIuZGlzYWJsZSgpO1xufTtcblxuLyoqXG4gKiBAbWV0aG9kIGVuYWJsZURldmljZUJhY2tCdXR0b25IYW5kbGVyXG4gKiBAc2lnbmF0dXJlIGVuYWJsZURldmljZUJhY2tCdXR0b25IYW5kbGVyKClcbiAqIEBkZXNjcmlwdGlvblxuICogW2VuXUVuYWJsZSBkZXZpY2UgYmFjayBidXR0b24gZXZlbnQgaGFuZGxlci4gTXVzdCBiZSBjYWxsZWQgb24gYG9ucy5yZWFkeWAuWy9lbl1cbiAqIFtqYV3jg4fjg5DjgqTjgrnjga7jg5Djg4Pjgq/jg5zjgr/jg7Pjga7jgqTjg5njg7Pjg4jjgpLlj5fjgZHku5jjgZHjgovjgojjgYbjgavjgZfjgb7jgZnjgIJbL2phXVxuICovXG5vbnMuZW5hYmxlRGV2aWNlQmFja0J1dHRvbkhhbmRsZXIgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCFvbnMuaXNSZWFkeSgpKSB7XG4gICAgcmVhZHlFcnJvcih0cnVlKTtcbiAgfVxuICBpbnRlcm5hbC5kYmJEaXNwYXRjaGVyLmVuYWJsZSgpO1xufTtcblxub25zLmZpcmVEZXZpY2VCYWNrQnV0dG9uRXZlbnQgPSBmdW5jdGlvbigpIHtcbiAgaW50ZXJuYWwuZGJiRGlzcGF0Y2hlci5maXJlRGV2aWNlQmFja0J1dHRvbkV2ZW50KCk7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgZW5hYmxlQXV0b1N0YXR1c0JhckZpbGxcbiAqIEBzaWduYXR1cmUgZW5hYmxlQXV0b1N0YXR1c0JhckZpbGwoKVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1FbmFibGUgc3RhdHVzIGJhciBmaWxsIGZlYXR1cmUgb24gaU9TNyBhbmQgYWJvdmUgKGV4Y2VwdCBmb3IgaVBob25lIFgpLiBNdXN0IGJlIGNhbGxlZCBiZWZvcmUgYG9ucy5yZWFkeWAuWy9lbl1cbiAqICAgW2phXWlPUzfku6XkuIrvvIhpUGhvbmUgWOOBr+mZpOOBj++8ieOBp+OAgeOCueODhuODvOOCv+OCueODkOODvOmDqOWIhuOBrumrmOOBleOCkuiHquWLleeahOOBq+Wfi+OCgeOCi+WHpueQhuOCkuacieWKueOBq+OBl+OBvuOBmeOAglsvamFdXG4gKi9cbm9ucy5lbmFibGVBdXRvU3RhdHVzQmFyRmlsbCA9ICgpID0+IHtcbiAgaWYgKG9ucy5pc1JlYWR5KCkpIHtcbiAgICByZWFkeUVycm9yKGZhbHNlKTtcbiAgfVxuICBpbnRlcm5hbC5jb25maWcuYXV0b1N0YXR1c0JhckZpbGwgPSB0cnVlO1xufTtcblxuLyoqXG4gKiBAbWV0aG9kIGRpc2FibGVBdXRvU3RhdHVzQmFyRmlsbFxuICogQHNpZ25hdHVyZSBkaXNhYmxlQXV0b1N0YXR1c0JhckZpbGwoKVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1EaXNhYmxlIHN0YXR1cyBiYXIgZmlsbCBmZWF0dXJlIG9uIGlPUzcgYW5kIGFib3ZlIChleGNlcHQgZm9yIGlQaG9uZSBYKS4gTXVzdCBiZSBjYWxsZWQgYmVmb3JlIGBvbnMucmVhZHlgLlsvZW5dXG4gKiAgIFtqYV1pT1M35Lul5LiK77yIaVBob25lIFjjga/pmaTjgY/vvInjgafjgIHjgrnjg4bjg7zjgr/jgrnjg5Djg7zpg6jliIbjga7pq5jjgZXjgpLoh6rli5XnmoTjgavln4vjgoHjgovlh6bnkIbjgpLnhKHlirnjgavjgZfjgb7jgZnjgIJbL2phXVxuICovXG5vbnMuZGlzYWJsZUF1dG9TdGF0dXNCYXJGaWxsID0gKCkgPT4ge1xuICBpZiAob25zLmlzUmVhZHkoKSkge1xuICAgIHJlYWR5RXJyb3IoZmFsc2UpO1xuICB9XG4gIGludGVybmFsLmNvbmZpZy5hdXRvU3RhdHVzQmFyRmlsbCA9IGZhbHNlO1xufTtcblxuLyoqXG4gKiBAbWV0aG9kIG1vY2tTdGF0dXNCYXJcbiAqIEBzaWduYXR1cmUgbW9ja1N0YXR1c0JhcigpXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXUNyZWF0ZXMgYSBzdGF0aWMgZWxlbWVudCBzaW1pbGFyIHRvIGlPUyBzdGF0dXMgYmFyLiBPbmx5IHVzZWZ1bCBmb3IgYnJvd3NlciB0ZXN0aW5nLiBNdXN0IGJlIGNhbGxlZCBiZWZvcmUgYG9ucy5yZWFkeWAuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKi9cbm9ucy5tb2NrU3RhdHVzQmFyID0gKCkgPT4ge1xuICBpZiAob25zLmlzUmVhZHkoKSkge1xuICAgIHJlYWR5RXJyb3IoZmFsc2UpO1xuICB9XG5cbiAgY29uc3QgbW9jayA9ICgpID0+IHtcbiAgICBpZiAoIWRvY3VtZW50LmJvZHkuY2hpbGRyZW5bMF0gfHwgIWRvY3VtZW50LmJvZHkuY2hpbGRyZW5bMF0uY2xhc3NMaXN0LmNvbnRhaW5zKCdvbnMtc3RhdHVzLWJhci1tb2NrJykpIHtcbiAgICAgIGNvbnN0IGFuZHJvaWQgPSBwbGF0Zm9ybS5pc0FuZHJvaWQoKSwgaSA9IGkgPT4gYDxpIGNsYXNzPVwiJHtpLnNwbGl0KCctJylbMF19ICR7aX1cIj48L2k+YDtcbiAgICAgIGNvbnN0IGxlZnQgPSBhbmRyb2lkID8gYCR7aSgnem1kaS10d2l0dGVyJyl9ICR7aSgnem1kaS1nb29nbGUtcGxheScpfWAgOiBgTm8gU0lNICR7aSgnZmEtd2lmaScpfWAsXG4gICAgICAgIGNlbnRlciA9IGFuZHJvaWQgPyAnJyA6ICcxMjoyOCBQTScsXG4gICAgICAgIHJpZ2h0ID0gYW5kcm9pZCA/IGAke2koJ3ptZGktbmV0d29yaycpfSAke2koJ3ptZGktd2lmaScpfSAke2koJ3ptZGktYmF0dGVyeScpfSAxMjoyOCBQTWAgOiBgODAlICR7aSgnZmEtYmF0dGVyeS10aHJlZS1xdWFydGVycycpfWA7XG5cbiAgICAgIGRvY3VtZW50LmJvZHkuaW5zZXJ0QmVmb3JlKHV0aWwuY3JlYXRlRWxlbWVudChcbiAgICAgICAgYDxkaXYgY2xhc3M9XCJvbnMtc3RhdHVzLWJhci1tb2NrICR7YW5kcm9pZCA/ICdhbmRyb2lkJyA6ICdpb3MnfVwiPmAgK1xuICAgICAgICAgIGA8ZGl2PiR7bGVmdH08L2Rpdj48ZGl2PiR7Y2VudGVyfTwvZGl2PjxkaXY+JHtyaWdodH08L2Rpdj5gICtcbiAgICAgICAgYDwvZGl2PmBcbiAgICAgICksIGRvY3VtZW50LmJvZHkuZmlyc3RDaGlsZCk7XG4gICAgfVxuICB9O1xuXG4gIGRvY3VtZW50LmJvZHlcbiAgICA/IG1vY2soKVxuICAgIDogaW50ZXJuYWwud2FpdERPTUNvbnRlbnRMb2FkZWQobW9jayk7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgZGlzYWJsZUFuaW1hdGlvbnNcbiAqIEBzaWduYXR1cmUgZGlzYWJsZUFuaW1hdGlvbnMoKVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1EaXNhYmxlIGFsbCBhbmltYXRpb25zLiBDb3VsZCBiZSBoYW5keSBmb3IgdGVzdGluZyBhbmQgb2xkZXIgZGV2aWNlcy5bL2VuXVxuICogICBbamFd44Ki44OL44Oh44O844K344On44Oz44KS5YWo44Gm54Sh5Yq544Gr44GX44G+44GZ44CC44OG44K544OI44Gu6Zqb44Gr5L6/5Yip44Gn44GZ44CCWy9qYV1cbiAqL1xub25zLmRpc2FibGVBbmltYXRpb25zID0gKCkgPT4ge1xuICBpbnRlcm5hbC5jb25maWcuYW5pbWF0aW9uc0Rpc2FibGVkID0gdHJ1ZTtcbn07XG5cbi8qKlxuICogQG1ldGhvZCBlbmFibGVBbmltYXRpb25zXG4gKiBAc2lnbmF0dXJlIGVuYWJsZUFuaW1hdGlvbnMoKVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1FbmFibGUgYW5pbWF0aW9ucyAoZGVmYXVsdCkuWy9lbl1cbiAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+OCkuacieWKueOBq+OBl+OBvuOBmeOAglsvamFdXG4gKi9cbm9ucy5lbmFibGVBbmltYXRpb25zID0gKCkgPT4ge1xuICBpbnRlcm5hbC5jb25maWcuYW5pbWF0aW9uc0Rpc2FibGVkID0gZmFsc2U7XG59O1xuXG5vbnMuX2Rpc2FibGVXYXJuaW5ncyA9ICgpID0+IHtcbiAgaW50ZXJuYWwuY29uZmlnLndhcm5pbmdzRGlzYWJsZWQgPSB0cnVlO1xufTtcblxub25zLl9lbmFibGVXYXJuaW5ncyA9ICgpID0+IHtcbiAgaW50ZXJuYWwuY29uZmlnLndhcm5pbmdzRGlzYWJsZWQgPSBmYWxzZTtcbn07XG5cbi8qKlxuICogQG1ldGhvZCBkaXNhYmxlQXV0b1N0eWxpbmdcbiAqIEBzaWduYXR1cmUgZGlzYWJsZUF1dG9TdHlsaW5nKClcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dRGlzYWJsZSBhdXRvbWF0aWMgc3R5bGluZy5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqL1xub25zLmRpc2FibGVBdXRvU3R5bGluZyA9IGF1dG9TdHlsZS5kaXNhYmxlO1xuXG4vKipcbiAqIEBtZXRob2QgZW5hYmxlQXV0b1N0eWxpbmdcbiAqIEBzaWduYXR1cmUgZW5hYmxlQXV0b1N0eWxpbmcoKVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1FbmFibGUgYXV0b21hdGljIHN0eWxpbmcgYmFzZWQgb24gT1MgKGRlZmF1bHQpLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICovXG5vbnMuZW5hYmxlQXV0b1N0eWxpbmcgPSBhdXRvU3R5bGUuZW5hYmxlO1xuXG4vKipcbiAqIEBtZXRob2QgZGlzYWJsZUljb25BdXRvUHJlZml4XG4gKiBAc2lnbmF0dXJlIGRpc2FibGVJY29uQXV0b1ByZWZpeCgpXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXURpc2FibGUgYWRkaW5nIGBmYS1gIHByZWZpeCBhdXRvbWF0aWNhbGx5IHRvIGBvbnMtaWNvbmAgY2xhc3Nlcy4gVXNlZnVsIHdoZW4gaW5jbHVkaW5nIGN1c3RvbSBpY29uIHBhY2tzLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICovXG5vbnMuZGlzYWJsZUljb25BdXRvUHJlZml4ID0gKCkgPT4ge1xuICB1dGlsLmNoZWNrTWlzc2luZ0ltcG9ydCgnSWNvbicpO1xuICBlbGVtZW50cy5JY29uLnNldEF1dG9QcmVmaXgoZmFsc2UpO1xufTtcblxuLyoqXG4gKiBAbWV0aG9kIGZvcmNlVUlXZWJWaWV3U2Nyb2xsRml4XG4gKiBAc2lnbmF0dXJlIGZvcmNlVUlXZWJWaWV3U2Nyb2xsRml4KClcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gZm9yY2UgRW5hYmxlIG9yIGRpc2FibGUgdGhlIGZpeC5cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dQXBwbGllcyBhIGZpeCBmb3IgaU9TIFVJV2ViVmlldyB3aGljaCBwcmV2ZW50cyBzY3JvbGwgZXZlbnRzIGp1bXBpbmcgdG8gcGFnZXMgdW5kZXIgdGhlIHRvcCBsYXllci4gVGhpcyBtYXkgdmlzdWFsbHkgYWZmZWN0IG5vcm1hbCBzY3JvbGxpbmcgb2YgVUlXZWJWaWV3IGlmIHlvdSBvcGVuIGEgZGlhbG9nL21lbnUgYmVmb3JlIHRoZSBzY3JvbGwgbW9tZW50dW0gZmluaXNoZWQuIERpc2FibGVkIGJ5IGRlZmF1bHQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKi9cbm9ucy5mb3JjZVVJV2ViVmlld1Njcm9sbEZpeCA9IChmb3JjZSA9IHRydWUpID0+IHtcbiAgaW50ZXJuYWwuY29uZmlnLmZvcmNlVUlXZWJWaWV3U2Nyb2xsRml4ID0gZm9yY2U7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgZm9yY2VQbGF0Zm9ybVN0eWxpbmdcbiAqIEBzaWduYXR1cmUgZm9yY2VQbGF0Zm9ybVN0eWxpbmcocGxhdGZvcm0pXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVJlZnJlc2ggc3R5bGluZyBmb3IgdGhlIGdpdmVuIHBsYXRmb3JtLiBPbmx5IHVzZWZ1bCBmb3IgZGVtb3MuIFVzZSBgb25zLnBsYXRmb3JtLnNlbGVjdCguLi4pYCBpbnN0ZWFkIGZvciBkZXZlbG9wbWVudCBhbmQgcHJvZHVjdGlvbi5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7c3RyaW5nfSBwbGF0Zm9ybSBOZXcgcGxhdGZvcm0gdG8gc3R5bGUgdGhlIGVsZW1lbnRzLlxuICovXG5vbnMuZm9yY2VQbGF0Zm9ybVN0eWxpbmcgPSBuZXdQbGF0Zm9ybSA9PiB7XG4gIG9ucy5lbmFibGVBdXRvU3R5bGluZygpO1xuICBvbnMucGxhdGZvcm0uc2VsZWN0KG5ld1BsYXRmb3JtIHx8ICdpb3MnKTtcblxuICBvbnMuX3V0aWwuYXJyYXlGcm9tKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJyonKSlcbiAgICAuZm9yRWFjaChmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgICBpZiAoZWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdvbnMtaWYnKSB7XG4gICAgICAgIGVsZW1lbnQuX3BsYXRmb3JtVXBkYXRlKCk7XG4gICAgICB9IGVsc2UgaWYgKGVsZW1lbnQudGFnTmFtZS5tYXRjaCgvXm9ucy0vaSkpIHtcbiAgICAgICAgYXV0b1N0eWxlLnByZXBhcmUoZWxlbWVudCwgdHJ1ZSk7XG4gICAgICAgIGlmIChlbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ29ucy10YWJiYXInKSB7XG4gICAgICAgICAgZWxlbWVudC5fdXBkYXRlUG9zaXRpb24oKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xufTtcblxuLyoqXG4gKiBAbWV0aG9kIHByZWxvYWRcbiAqIEBzaWduYXR1cmUgcHJlbG9hZCh0ZW1wbGF0ZVBhdGhzKVxuICogQHBhcmFtIHtTdHJpbmd8QXJyYXl9IHRlbXBsYXRlUGF0aHNcbiAqICAgW2VuXVNldCBvZiBIVE1MIGZpbGUgcGF0aHMgY29udGFpbmluZyAnb25zLXBhZ2UnIGVsZW1lbnRzLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHJldHVybiB7UHJvbWlzZX1cbiAqICAgW2VuXVByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGFsbCB0aGUgdGVtcGxhdGVzIGFyZSBjYWNoZWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVNlcGFyYXRlZCBmaWxlcyBuZWVkIHRvIGJlIHJlcXVlc3RlZCBvbiBkZW1hbmQgYW5kIHRoaXMgY2FuIHNsaWdodGx5IGRlbGF5IHB1c2hpbmcgbmV3IHBhZ2VzLiBUaGlzIG1ldGhvZCByZXF1ZXN0cyBhbmQgY2FjaGVzIHRlbXBsYXRlcyBmb3IgbGF0ZXIgdXNlLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICovXG5vbnMucHJlbG9hZCA9IGZ1bmN0aW9uKHRlbXBsYXRlcyA9IFtdKSB7XG4gIHJldHVybiBQcm9taXNlLmFsbCgodGVtcGxhdGVzIGluc3RhbmNlb2YgQXJyYXkgPyB0ZW1wbGF0ZXMgOiBbdGVtcGxhdGVzXSkubWFwKHRlbXBsYXRlID0+IHtcbiAgICBpZiAodHlwZW9mIHRlbXBsYXRlICE9PSAnc3RyaW5nJykge1xuICAgICAgdXRpbC50aHJvdygnRXhwZWN0ZWQgc3RyaW5nIGFyZ3VtZW50cyBidXQgZ290ICcgKyB0eXBlb2YgdGVtcGxhdGUpO1xuICAgIH1cbiAgICByZXR1cm4gaW50ZXJuYWwuZ2V0VGVtcGxhdGVIVE1MQXN5bmModGVtcGxhdGUpO1xuICB9KSk7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgY3JlYXRlRWxlbWVudFxuICogQHNpZ25hdHVyZSBjcmVhdGVFbGVtZW50KHRlbXBsYXRlLCBvcHRpb25zKVxuICogQHBhcmFtIHtTdHJpbmd9IHRlbXBsYXRlXG4gKiAgIFtlbl1FaXRoZXIgYW4gSFRNTCBmaWxlIHBhdGgsIGEgYDx0ZW1wbGF0ZT5gIGlkIG9yIGFuIEhUTUwgc3RyaW5nIHN1Y2ggYXMgYCc8ZGl2IGlkPVwiZm9vXCI+aG9nZTwvZGl2PidgLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAqIEBwYXJhbSB7Qm9vbGVhbnxIVE1MRWxlbWVudH0gW29wdGlvbnMuYXBwZW5kXVxuICogICBbZW5dV2hldGhlciBvciBub3QgdGhlIGVsZW1lbnQgc2hvdWxkIGJlIGF1dG9tYXRpY2FsbHkgYXBwZW5kZWQgdG8gdGhlIERPTS4gIERlZmF1bHRzIHRvIGBmYWxzZWAuIElmIGB0cnVlYCB2YWx1ZSBpcyBnaXZlbiwgYGRvY3VtZW50LmJvZHlgIHdpbGwgYmUgdXNlZCBhcyB0aGUgdGFyZ2V0LlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gW29wdGlvbnMuaW5zZXJ0QmVmb3JlXVxuICogICBbZW5dUmVmZXJlbmNlIG5vZGUgdGhhdCBiZWNvbWVzIHRoZSBuZXh0IHNpYmxpbmcgb2YgdGhlIG5ldyBub2RlIChgb3B0aW9ucy5hcHBlbmRgIGVsZW1lbnQpLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHJldHVybiB7SFRNTEVsZW1lbnR8UHJvbWlzZX1cbiAqICAgW2VuXUlmIHRoZSBwcm92aWRlZCB0ZW1wbGF0ZSB3YXMgYW4gaW5saW5lIEhUTUwgc3RyaW5nLCBpdCByZXR1cm5zIHRoZSBuZXcgZWxlbWVudC4gT3RoZXJ3aXNlLCBpdCByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBuZXcgZWxlbWVudC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dQ3JlYXRlIGEgbmV3IGVsZW1lbnQgZnJvbSBhIHRlbXBsYXRlLiBCb3RoIGlubGluZSBIVE1MIGFuZCBleHRlcm5hbCBmaWxlcyBhcmUgc3VwcG9ydGVkIGFsdGhvdWdoIHRoZSByZXR1cm4gdmFsdWUgZGlmZmVycy5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqL1xub25zLmNyZWF0ZUVsZW1lbnQgPSAodGVtcGxhdGUsIG9wdGlvbnMgPSB7fSkgPT4ge1xuICB0ZW1wbGF0ZSA9IHRlbXBsYXRlLnRyaW0oKTtcblxuICBjb25zdCBjcmVhdGUgPSBodG1sID0+IHtcbiAgICBjb25zdCBlbGVtZW50ID0gb25zLl91dGlsLmNyZWF0ZUVsZW1lbnQoaHRtbCk7XG4gICAgZWxlbWVudC5yZW1vdmUoKTtcblxuICAgIGlmIChvcHRpb25zLmFwcGVuZCkge1xuICAgICAgY29uc3QgdGFyZ2V0ID0gb3B0aW9ucy5hcHBlbmQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCA/IG9wdGlvbnMuYXBwZW5kIDogZG9jdW1lbnQuYm9keTtcbiAgICAgIHRhcmdldC5pbnNlcnRCZWZvcmUoZWxlbWVudCwgb3B0aW9ucy5pbnNlcnRCZWZvcmUgfHwgbnVsbCk7XG4gICAgICBvcHRpb25zLmxpbmsgaW5zdGFuY2VvZiBGdW5jdGlvbiAmJiBvcHRpb25zLmxpbmsoZWxlbWVudCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH07XG5cbiAgcmV0dXJuIHRlbXBsYXRlLmNoYXJBdCgwKSA9PT0gJzwnID8gY3JlYXRlKHRlbXBsYXRlKSA6IGludGVybmFsLmdldFBhZ2VIVE1MQXN5bmModGVtcGxhdGUpLnRoZW4oY3JlYXRlKTtcbn07XG5cbi8qKlxuICogQG1ldGhvZCBjcmVhdGVQb3BvdmVyXG4gKiBAc2lnbmF0dXJlIGNyZWF0ZVBvcG92ZXIocGFnZSwgW29wdGlvbnNdKVxuICogQHBhcmFtIHtTdHJpbmd9IHBhZ2VcbiAqICAgW2VuXVBhZ2UgbmFtZS4gQ2FuIGJlIGVpdGhlciBhbiBIVE1MIGZpbGUgb3IgYSA8dGVtcGxhdGU+IGNvbnRhaW5pbmcgYSA8b25zLWRpYWxvZz4gY29tcG9uZW50LlsvZW5dXG4gKiAgIFtqYV1wYWdl44GuVVJM44GL44CB44KC44GX44GP44GvYDx0ZW1wbGF0ZT5g44Gn5a6j6KiA44GX44Gf44OG44Oz44OX44Os44O844OI44GuaWTlsZ7mgKfjga7lgKTjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucy5wYXJlbnRTY29wZV1cbiAqICAgW2VuXVBhcmVudCBzY29wZSBvZiB0aGUgZGlhbG9nLiBVc2VkIHRvIGJpbmQgbW9kZWxzIGFuZCBhY2Nlc3Mgc2NvcGUgbWV0aG9kcyBmcm9tIHRoZSBkaWFsb2cuWy9lbl1cbiAqICAgW2phXeODgOOCpOOCouODreOCsOWGheOBp+WIqeeUqOOBmeOCi+imquOCueOCs+ODvOODl+OCkuaMh+WumuOBl+OBvuOBmeOAguODgOOCpOOCouODreOCsOOBi+OCieODouODh+ODq+OChOOCueOCs+ODvOODl+OBruODoeOCveODg+ODieOBq+OCouOCr+OCu+OCueOBmeOCi+OBruOBq+S9v+OBhOOBvuOBmeOAguOBk+OBruODkeODqeODoeODvOOCv+OBr0FuZ3VsYXJKU+ODkOOCpOODs+ODh+OCo+ODs+OCsOOBp+OBruOBv+WIqeeUqOOBp+OBjeOBvuOBmeOAglsvamFdXG4gKiBAcmV0dXJuIHtQcm9taXNlfVxuICogICBbZW5dUHJvbWlzZSBvYmplY3QgdGhhdCByZXNvbHZlcyB0byB0aGUgcG9wb3ZlciBjb21wb25lbnQgb2JqZWN0LlsvZW5dXG4gKiAgIFtqYV3jg53jg4Pjg5fjgqrjg7zjg5Djg7zjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjgqrjg5bjgrjjgqfjgq/jg4jjgpLop6PmsbrjgZnjgotQcm9taXNl44Kq44OW44K444Kn44Kv44OI44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dQ3JlYXRlIGEgcG9wb3ZlciBpbnN0YW5jZSBmcm9tIGEgdGVtcGxhdGUuWy9lbl1cbiAqICAgW2phXeODhuODs+ODl+ODrOODvOODiOOBi+OCieODneODg+ODl+OCquODvOODkOODvOOBruOCpOODs+OCueOCv+ODs+OCueOCkueUn+aIkOOBl+OBvuOBmeOAglsvamFdXG4gKi9cbi8qKlxuICogQG1ldGhvZCBjcmVhdGVEaWFsb2dcbiAqIEBzaWduYXR1cmUgY3JlYXRlRGlhbG9nKHBhZ2UsIFtvcHRpb25zXSlcbiAqIEBwYXJhbSB7U3RyaW5nfSBwYWdlXG4gKiAgIFtlbl1QYWdlIG5hbWUuIENhbiBiZSBlaXRoZXIgYW4gSFRNTCBmaWxlIG9yIGFuIGA8dGVtcGxhdGU+YCBjb250YWluaW5nIGEgPG9ucy1kaWFsb2c+IGNvbXBvbmVudC5bL2VuXVxuICogICBbamFdcGFnZeOBrlVSTOOBi+OAgeOCguOBl+OBj+OBr2A8dGVtcGxhdGU+YOOBp+Wuo+iogOOBl+OBn+ODhuODs+ODl+ODrOODvOODiOOBrmlk5bGe5oCn44Gu5YCk44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gKiBAcmV0dXJuIHtQcm9taXNlfVxuICogICBbZW5dUHJvbWlzZSBvYmplY3QgdGhhdCByZXNvbHZlcyB0byB0aGUgZGlhbG9nIGNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAqICAgW2phXeODgOOCpOOCouODreOCsOOBruOCs+ODs+ODneODvOODjeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOCkuino+axuuOBmeOCi1Byb21pc2Xjgqrjg5bjgrjjgqfjgq/jg4jjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1DcmVhdGUgYSBkaWFsb2cgaW5zdGFuY2UgZnJvbSBhIHRlbXBsYXRlLlsvZW5dXG4gKiAgIFtqYV3jg4bjg7Pjg5fjg6zjg7zjg4jjgYvjgonjg4DjgqTjgqLjg63jgrDjga7jgqTjg7Pjgrnjgr/jg7PjgrnjgpLnlJ/miJDjgZfjgb7jgZnjgIJbL2phXVxuICovXG4vKipcbiAqIEBtZXRob2QgY3JlYXRlQWxlcnREaWFsb2dcbiAqIEBzaWduYXR1cmUgY3JlYXRlQWxlcnREaWFsb2cocGFnZSwgW29wdGlvbnNdKVxuICogQHBhcmFtIHtTdHJpbmd9IHBhZ2VcbiAqICAgW2VuXVBhZ2UgbmFtZS4gQ2FuIGJlIGVpdGhlciBhbiBIVE1MIGZpbGUgb3IgYW4gYDx0ZW1wbGF0ZT5gIGNvbnRhaW5pbmcgYSA8b25zLWFsZXJ0LWRpYWxvZz4gY29tcG9uZW50LlsvZW5dXG4gKiAgIFtqYV1wYWdl44GuVVJM44GL44CB44KC44GX44GP44GvYDx0ZW1wbGF0ZT5g44Gn5a6j6KiA44GX44Gf44OG44Oz44OX44Os44O844OI44GuaWTlsZ7mgKfjga7lgKTjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAqIEByZXR1cm4ge1Byb21pc2V9XG4gKiAgIFtlbl1Qcm9taXNlIG9iamVjdCB0aGF0IHJlc29sdmVzIHRvIHRoZSBhbGVydCBkaWFsb2cgY29tcG9uZW50IG9iamVjdC5bL2VuXVxuICogICBbamFd44OA44Kk44Ki44Ot44Kw44Gu44Kz44Oz44Od44O844ON44Oz44OI44Kq44OW44K444Kn44Kv44OI44KS6Kej5rG644GZ44KLUHJvbWlzZeOCquODluOCuOOCp+OCr+ODiOOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXUNyZWF0ZSBhIGFsZXJ0IGRpYWxvZyBpbnN0YW5jZSBmcm9tIGEgdGVtcGxhdGUuWy9lbl1cbiAqICAgW2phXeODhuODs+ODl+ODrOODvOODiOOBi+OCieOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBruOCpOODs+OCueOCv+ODs+OCueOCkueUn+aIkOOBl+OBvuOBmeOAglsvamFdXG4gKi9cbm9ucy5jcmVhdGVQb3BvdmVyID0gb25zLmNyZWF0ZURpYWxvZyA9IG9ucy5jcmVhdGVBbGVydERpYWxvZyA9ICh0ZW1wbGF0ZSwgb3B0aW9ucyA9IHt9KSA9PiBvbnMuY3JlYXRlRWxlbWVudCh0ZW1wbGF0ZSwgeyBhcHBlbmQ6IHRydWUsIC4uLm9wdGlvbnMgfSk7XG5cbi8qKlxuICogQG1ldGhvZCBvcGVuQWN0aW9uU2hlZXRcbiAqIEBzaWduYXR1cmUgb3BlbkFjdGlvblNoZWV0KG9wdGlvbnMpXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVNob3dzIGFuIGluc3RhbnQgQWN0aW9uIFNoZWV0IGFuZCBsZXRzIHRoZSB1c2VyIGNob29zZSBhbiBhY3Rpb24uWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICogQHBhcmFtIHtBcnJheX0gW29wdGlvbnMuYnV0dG9uc11cbiAqICAgW2VuXVJlcHJlc2VudCBlYWNoIGJ1dHRvbiBvZiB0aGUgYWN0aW9uIHNoZWV0IGZvbGxvd2luZyB0aGUgc3BlY2lmaWVkIG9yZGVyLiBFdmVyeSBpdGVtIGNhbiBiZSBlaXRoZXIgYSBzdHJpbmcgbGFiZWwgb3IgYW4gb2JqZWN0IGNvbnRhaW5pbmcgYGxhYmVsYCwgYGljb25gIGFuZCBgbW9kaWZpZXJgIHByb3BlcnRpZXMuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMudGl0bGVdXG4gKiAgIFtlbl1PcHRpb25hbCB0aXRsZSBmb3IgdGhlIGFjdGlvbiBzaGVldC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5kZXN0cnVjdGl2ZV1cbiAqICAgW2VuXU9wdGlvbmFsIGluZGV4IG9mIHRoZSBcImRlc3RydWN0aXZlXCIgYnV0dG9uIChvbmx5IGZvciBpT1MpLiBJdCBjYW4gYmUgc3BlY2lmaWVkIGluIHRoZSBidXR0b24gYXJyYXkgYXMgd2VsbC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMuY2FuY2VsYWJsZV1cbiAqICAgW2VuXVdoZXRoZXIgdGhlIGFjdGlvbiBzaGVldCBjYW4gYmUgY2FuY2VsZWQgYnkgdGFwcGluZyBvbiB0aGUgYmFja2dyb3VuZCBtYXNrIG9yIG5vdC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5tb2RpZmllcl1cbiAqICAgW2VuXU1vZGlmaWVyIGF0dHJpYnV0ZSBvZiB0aGUgYWN0aW9uIHNoZWV0LiBFLmcuIGAnZGVzdHJ1Y3RpdmUnYC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5tYXNrQ29sb3JdXG4gKiAgIFtlbl1PcHRpb25hbGx5IGNoYW5nZSB0aGUgYmFja2dyb3VuZCBtYXNrIGNvbG9yLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmlkXVxuICogICBbZW5dVGhlIGVsZW1lbnQncyBpZCBhdHRyaWJ1dGUuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuY2xhc3NdXG4gKiAgIFtlbl1UaGUgZWxlbWVudCdzIGNsYXNzIGF0dHJpYnV0ZS5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEByZXR1cm4ge1Byb21pc2V9XG4gKiAgIFtlbl1XaWxsIHJlc29sdmUgd2hlbiB0aGUgYWN0aW9uIHNoZWV0IGlzIGNsb3NlZC4gVGhlIHJlc29sdmUgdmFsdWUgaXMgZWl0aGVyIHRoZSBpbmRleCBvZiB0aGUgdGFwcGVkIGJ1dHRvbiBvciAtMSB3aGVuIGNhbmNlbGVkLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICovXG5vbnMub3BlbkFjdGlvblNoZWV0ID0gYWN0aW9uU2hlZXQ7XG5cbi8qKlxuICogQG1ldGhvZCByZXNvbHZlTG9hZGluZ1BsYWNlaG9sZGVyXG4gKiBAc2lnbmF0dXJlIHJlc29sdmVMb2FkaW5nUGxhY2Vob2xkZXIocGFnZSlcbiAqIEBwYXJhbSB7U3RyaW5nfSBwYWdlXG4gKiAgIFtlbl1QYWdlIG5hbWUuIENhbiBiZSBlaXRoZXIgYW4gSFRNTCBmaWxlIG9yIGEgYDx0ZW1wbGF0ZT5gIGlkLlsvZW5dXG4gKiAgIFtqYV1wYWdl44GuVVJM44GL44CB44KC44GX44GP44GvYDx0ZW1wbGF0ZT5g44Gn5a6j6KiA44GX44Gf44OG44Oz44OX44Os44O844OI44GuaWTlsZ7mgKfjga7lgKTjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1JZiBubyBwYWdlIGlzIGRlZmluZWQgZm9yIHRoZSBgb25zLWxvYWRpbmctcGxhY2Vob2xkZXJgIGF0dHJpYnV0ZSBpdCB3aWxsIHdhaXQgZm9yIHRoaXMgbWV0aG9kIGJlaW5nIGNhbGxlZCBiZWZvcmUgbG9hZGluZyB0aGUgcGFnZS5bL2VuXVxuICogICBbamFdb25zLWxvYWRpbmctcGxhY2Vob2xkZXLjga7lsZ7mgKflgKTjgajjgZfjgabjg5rjg7zjgrjjgYzmjIflrprjgZXjgozjgabjgYTjgarjgYTloLTlkIjjga/jgIHjg5rjg7zjgrjjg63jg7zjg4nliY3jgavlkbzjgbDjgozjgotvbnMucmVzb2x2ZUxvYWRpbmdQbGFjZWhvbGRlcuWHpueQhuOBjOihjOOCj+OCjOOCi+OBvuOBp+ihqOekuuOBleOCjOOBvuOBm+OCk+OAglsvamFdXG4gKi9cbm9ucy5yZXNvbHZlTG9hZGluZ1BsYWNlaG9sZGVyID0gKHBhZ2UsIGxpbmspID0+IHtcbiAgY29uc3QgZWxlbWVudHMgPSBvbnMuX3V0aWwuYXJyYXlGcm9tKHdpbmRvdy5kb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbb25zLWxvYWRpbmctcGxhY2Vob2xkZXJdJykpO1xuICBpZiAoZWxlbWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgdXRpbC50aHJvdygnTm8gb25zLWxvYWRpbmctcGxhY2Vob2xkZXIgZXhpc3RzJyk7XG4gIH1cblxuICBlbGVtZW50c1xuICAgIC5maWx0ZXIoZWxlbWVudCA9PiAhZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3BhZ2UnKSlcbiAgICAuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCdvbnMtbG9hZGluZy1wbGFjZWhvbGRlcicsIHBhZ2UpO1xuICAgICAgb25zLl9yZXNvbHZlTG9hZGluZ1BsYWNlaG9sZGVyKGVsZW1lbnQsIHBhZ2UsIGxpbmspO1xuICAgIH0pO1xufTtcblxuXG5vbnMuX3NldHVwTG9hZGluZ1BsYWNlSG9sZGVycyA9IGZ1bmN0aW9uKCkge1xuICBvbnMucmVhZHkoKCkgPT4ge1xuICAgIGNvbnN0IGVsZW1lbnRzID0gb25zLl91dGlsLmFycmF5RnJvbSh3aW5kb3cuZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnW29ucy1sb2FkaW5nLXBsYWNlaG9sZGVyXScpKTtcblxuICAgIGVsZW1lbnRzLmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICBjb25zdCBwYWdlID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ29ucy1sb2FkaW5nLXBsYWNlaG9sZGVyJyk7XG4gICAgICBpZiAodHlwZW9mIHBhZ2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG9ucy5fcmVzb2x2ZUxvYWRpbmdQbGFjZWhvbGRlcihlbGVtZW50LCBwYWdlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG59O1xuXG5vbnMuX3Jlc29sdmVMb2FkaW5nUGxhY2Vob2xkZXIgPSBmdW5jdGlvbihwYXJlbnQsIHBhZ2UsIGxpbmsgPSAoKGVsLCBkb25lKSA9PiBkb25lKCkpKSB7XG4gIHBhZ2UgJiYgb25zLmNyZWF0ZUVsZW1lbnQocGFnZSlcbiAgICAudGhlbihlbGVtZW50ID0+IHtcbiAgICAgIGVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgIHBhcmVudC5hcHBlbmRDaGlsZChlbGVtZW50KTtcbiAgICAgIGxpbmsoZWxlbWVudCwgKCkgPT4ge1xuICAgICAgICB3aGlsZSAocGFyZW50LmZpcnN0Q2hpbGQgJiYgcGFyZW50LmZpcnN0Q2hpbGQgIT09IGVsZW1lbnQpIHtcbiAgICAgICAgICBwYXJlbnQucmVtb3ZlQ2hpbGQocGFyZW50LmZpcnN0Q2hpbGQpO1xuICAgICAgICB9XG4gICAgICAgIGVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICcnO1xuICAgICAgfSk7XG4gICAgfSlcbiAgICAuY2F0Y2goZXJyb3IgPT4gUHJvbWlzZS5yZWplY3QoJ1VuYWJsZWQgdG8gcmVzb2x2ZSBwbGFjZWhvbGRlcjogJyArIGVycm9yKSk7XG59O1xuXG5mdW5jdGlvbiB3YWl0RGV2aWNlUmVhZHkoKSB7XG4gIGNvbnN0IHVubG9ja0RldmljZVJlYWR5ID0gb25zLl9yZWFkeUxvY2subG9jaygpO1xuICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsICgpID0+IHtcbiAgICBpZiAob25zLmlzV2ViVmlldygpKSB7XG4gICAgICB3aW5kb3cuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZGV2aWNlcmVhZHknLCB1bmxvY2tEZXZpY2VSZWFkeSwgZmFsc2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICB1bmxvY2tEZXZpY2VSZWFkeSgpO1xuICAgIH1cbiAgfSwgZmFsc2UpO1xufVxuXG4vKipcbiAqIEBtZXRob2QgZ2V0U2NyaXB0UGFnZVxuICogQHNpZ25hdHVyZSBnZXRTY3JpcHRQYWdlKClcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dQWNjZXNzIHRoZSBsYXN0IGNyZWF0ZWQgcGFnZSBmcm9tIHRoZSBjdXJyZW50IGBzY3JpcHRgIHNjb3BlLiBPbmx5IHdvcmtzIGluc2lkZSBgPHNjcmlwdD48L3NjcmlwdD5gIHRhZ3MgdGhhdCBhcmUgZGlyZWN0IGNoaWxkcmVuIG9mIGBvbnMtcGFnZWAgZWxlbWVudC4gVXNlIHRoaXMgdG8gYWRkIGxpZmVjeWNsZSBob29rcyB0byBhIHBhZ2UuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcmV0dXJuIHtIVE1MRWxlbWVudH1cbiAqICAgW2VuXVJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcgcGFnZSBlbGVtZW50LlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICovXG5jb25zdCBnZXRDUyA9ICdjdXJyZW50U2NyaXB0JyBpbiBkb2N1bWVudCA/ICgpID0+IGRvY3VtZW50LmN1cnJlbnRTY3JpcHQgOiAoKSA9PiBkb2N1bWVudC5zY3JpcHRzW2RvY3VtZW50LnNjcmlwdHMubGVuZ3RoIC0gMV07XG5vbnMuZ2V0U2NyaXB0UGFnZSA9ICgpID0+IGdldENTKCkgJiYgL29ucy1wYWdlL2kudGVzdChnZXRDUygpLnBhcmVudEVsZW1lbnQudGFnTmFtZSkgJiYgZ2V0Q1MoKS5wYXJlbnRFbGVtZW50IHx8IG51bGw7XG5cbmV4cG9ydCBkZWZhdWx0IG9ucztcbiIsIjsoZnVuY3Rpb24gKCkge1xuXHQndXNlIHN0cmljdCc7XG5cblx0LyoqXG5cdCAqIEBwcmVzZXJ2ZSBGYXN0Q2xpY2s6IHBvbHlmaWxsIHRvIHJlbW92ZSBjbGljayBkZWxheXMgb24gYnJvd3NlcnMgd2l0aCB0b3VjaCBVSXMuXG5cdCAqXG5cdCAqIEBjb2RpbmdzdGFuZGFyZCBmdGxhYnMtanN2MlxuXHQgKiBAY29weXJpZ2h0IFRoZSBGaW5hbmNpYWwgVGltZXMgTGltaXRlZCBbQWxsIFJpZ2h0cyBSZXNlcnZlZF1cblx0ICogQGxpY2Vuc2UgTUlUIExpY2Vuc2UgKHNlZSBMSUNFTlNFLnR4dClcblx0ICovXG5cblx0Lypqc2xpbnQgYnJvd3Nlcjp0cnVlLCBub2RlOnRydWUqL1xuXHQvKmdsb2JhbCBkZWZpbmUsIEV2ZW50LCBOb2RlKi9cblxuXG5cdC8qKlxuXHQgKiBJbnN0YW50aWF0ZSBmYXN0LWNsaWNraW5nIGxpc3RlbmVycyBvbiB0aGUgc3BlY2lmaWVkIGxheWVyLlxuXHQgKlxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICogQHBhcmFtIHtFbGVtZW50fSBsYXllciBUaGUgbGF5ZXIgdG8gbGlzdGVuIG9uXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gVGhlIG9wdGlvbnMgdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHRzXG5cdCAqL1xuXHRmdW5jdGlvbiBGYXN0Q2xpY2sobGF5ZXIsIG9wdGlvbnMpIHtcblx0XHR2YXIgb2xkT25DbGljaztcblxuXHRcdG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciBhIGNsaWNrIGlzIGN1cnJlbnRseSBiZWluZyB0cmFja2VkLlxuXHRcdCAqXG5cdFx0ICogQHR5cGUgYm9vbGVhblxuXHRcdCAqL1xuXHRcdHRoaXMudHJhY2tpbmdDbGljayA9IGZhbHNlO1xuXG5cblx0XHQvKipcblx0XHQgKiBUaW1lc3RhbXAgZm9yIHdoZW4gY2xpY2sgdHJhY2tpbmcgc3RhcnRlZC5cblx0XHQgKlxuXHRcdCAqIEB0eXBlIG51bWJlclxuXHRcdCAqL1xuXHRcdHRoaXMudHJhY2tpbmdDbGlja1N0YXJ0ID0gMDtcblxuXG5cdFx0LyoqXG5cdFx0ICogVGhlIGVsZW1lbnQgYmVpbmcgdHJhY2tlZCBmb3IgYSBjbGljay5cblx0XHQgKlxuXHRcdCAqIEB0eXBlIEV2ZW50VGFyZ2V0XG5cdFx0ICovXG5cdFx0dGhpcy50YXJnZXRFbGVtZW50ID0gbnVsbDtcblxuXG5cdFx0LyoqXG5cdFx0ICogWC1jb29yZGluYXRlIG9mIHRvdWNoIHN0YXJ0IGV2ZW50LlxuXHRcdCAqXG5cdFx0ICogQHR5cGUgbnVtYmVyXG5cdFx0ICovXG5cdFx0dGhpcy50b3VjaFN0YXJ0WCA9IDA7XG5cblxuXHRcdC8qKlxuXHRcdCAqIFktY29vcmRpbmF0ZSBvZiB0b3VjaCBzdGFydCBldmVudC5cblx0XHQgKlxuXHRcdCAqIEB0eXBlIG51bWJlclxuXHRcdCAqL1xuXHRcdHRoaXMudG91Y2hTdGFydFkgPSAwO1xuXG5cblx0XHQvKipcblx0XHQgKiBJRCBvZiB0aGUgbGFzdCB0b3VjaCwgcmV0cmlldmVkIGZyb20gVG91Y2guaWRlbnRpZmllci5cblx0XHQgKlxuXHRcdCAqIEB0eXBlIG51bWJlclxuXHRcdCAqL1xuXHRcdHRoaXMubGFzdFRvdWNoSWRlbnRpZmllciA9IDA7XG5cblxuXHRcdC8qKlxuXHRcdCAqIFRvdWNobW92ZSBib3VuZGFyeSwgYmV5b25kIHdoaWNoIGEgY2xpY2sgd2lsbCBiZSBjYW5jZWxsZWQuXG5cdFx0ICpcblx0XHQgKiBAdHlwZSBudW1iZXJcblx0XHQgKi9cblx0XHR0aGlzLnRvdWNoQm91bmRhcnkgPSBvcHRpb25zLnRvdWNoQm91bmRhcnkgfHwgMTA7XG5cblxuXHRcdC8qKlxuXHRcdCAqIFRoZSBGYXN0Q2xpY2sgbGF5ZXIuXG5cdFx0ICpcblx0XHQgKiBAdHlwZSBFbGVtZW50XG5cdFx0ICovXG5cdFx0dGhpcy5sYXllciA9IGxheWVyO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIG1pbmltdW0gdGltZSBiZXR3ZWVuIHRhcCh0b3VjaHN0YXJ0IGFuZCB0b3VjaGVuZCkgZXZlbnRzXG5cdFx0ICpcblx0XHQgKiBAdHlwZSBudW1iZXJcblx0XHQgKi9cblx0XHR0aGlzLnRhcERlbGF5ID0gb3B0aW9ucy50YXBEZWxheSB8fCAyMDA7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgbWF4aW11bSB0aW1lIGZvciBhIHRhcFxuXHRcdCAqXG5cdFx0ICogQHR5cGUgbnVtYmVyXG5cdFx0ICovXG5cdFx0dGhpcy50YXBUaW1lb3V0ID0gb3B0aW9ucy50YXBUaW1lb3V0IHx8IDcwMDtcblxuXHRcdGlmIChGYXN0Q2xpY2subm90TmVlZGVkKGxheWVyKSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIFNvbWUgb2xkIHZlcnNpb25zIG9mIEFuZHJvaWQgZG9uJ3QgaGF2ZSBGdW5jdGlvbi5wcm90b3R5cGUuYmluZFxuXHRcdGZ1bmN0aW9uIGJpbmQobWV0aG9kLCBjb250ZXh0KSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oKSB7IHJldHVybiBtZXRob2QuYXBwbHkoY29udGV4dCwgYXJndW1lbnRzKTsgfTtcblx0XHR9XG5cblxuXHRcdHZhciBtZXRob2RzID0gWydvbk1vdXNlJywgJ29uQ2xpY2snLCAnb25Ub3VjaFN0YXJ0JywgJ29uVG91Y2hNb3ZlJywgJ29uVG91Y2hFbmQnLCAnb25Ub3VjaENhbmNlbCddO1xuXHRcdHZhciBjb250ZXh0ID0gdGhpcztcblx0XHRmb3IgKHZhciBpID0gMCwgbCA9IG1ldGhvZHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG5cdFx0XHRjb250ZXh0W21ldGhvZHNbaV1dID0gYmluZChjb250ZXh0W21ldGhvZHNbaV1dLCBjb250ZXh0KTtcblx0XHR9XG5cblx0XHQvLyBTZXQgdXAgZXZlbnQgaGFuZGxlcnMgYXMgcmVxdWlyZWRcblx0XHRpZiAoZGV2aWNlSXNBbmRyb2lkKSB7XG5cdFx0XHRsYXllci5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW92ZXInLCB0aGlzLm9uTW91c2UsIHRydWUpO1xuXHRcdFx0bGF5ZXIuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5vbk1vdXNlLCB0cnVlKTtcblx0XHRcdGxheWVyLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLm9uTW91c2UsIHRydWUpO1xuXHRcdH1cblxuXHRcdGxheWVyLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5vbkNsaWNrLCB0cnVlKTtcblx0XHRsYXllci5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdGhpcy5vblRvdWNoU3RhcnQsIGZhbHNlKTtcblx0XHRsYXllci5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLm9uVG91Y2hNb3ZlLCBmYWxzZSk7XG5cdFx0bGF5ZXIuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLm9uVG91Y2hFbmQsIGZhbHNlKTtcblx0XHRsYXllci5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGNhbmNlbCcsIHRoaXMub25Ub3VjaENhbmNlbCwgZmFsc2UpO1xuXG5cdFx0Ly8gSGFjayBpcyByZXF1aXJlZCBmb3IgYnJvd3NlcnMgdGhhdCBkb24ndCBzdXBwb3J0IEV2ZW50I3N0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbiAoZS5nLiBBbmRyb2lkIDIpXG5cdFx0Ly8gd2hpY2ggaXMgaG93IEZhc3RDbGljayBub3JtYWxseSBzdG9wcyBjbGljayBldmVudHMgYnViYmxpbmcgdG8gY2FsbGJhY2tzIHJlZ2lzdGVyZWQgb24gdGhlIEZhc3RDbGlja1xuXHRcdC8vIGxheWVyIHdoZW4gdGhleSBhcmUgY2FuY2VsbGVkLlxuXHRcdGlmICghRXZlbnQucHJvdG90eXBlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbikge1xuXHRcdFx0bGF5ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uKHR5cGUsIGNhbGxiYWNrLCBjYXB0dXJlKSB7XG5cdFx0XHRcdHZhciBybXYgPSBOb2RlLnByb3RvdHlwZS5yZW1vdmVFdmVudExpc3RlbmVyO1xuXHRcdFx0XHRpZiAodHlwZSA9PT0gJ2NsaWNrJykge1xuXHRcdFx0XHRcdHJtdi5jYWxsKGxheWVyLCB0eXBlLCBjYWxsYmFjay5oaWphY2tlZCB8fCBjYWxsYmFjaywgY2FwdHVyZSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cm12LmNhbGwobGF5ZXIsIHR5cGUsIGNhbGxiYWNrLCBjYXB0dXJlKTtcblx0XHRcdFx0fVxuXHRcdFx0fTtcblxuXHRcdFx0bGF5ZXIuYWRkRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uKHR5cGUsIGNhbGxiYWNrLCBjYXB0dXJlKSB7XG5cdFx0XHRcdHZhciBhZHYgPSBOb2RlLnByb3RvdHlwZS5hZGRFdmVudExpc3RlbmVyO1xuXHRcdFx0XHRpZiAodHlwZSA9PT0gJ2NsaWNrJykge1xuXHRcdFx0XHRcdGFkdi5jYWxsKGxheWVyLCB0eXBlLCBjYWxsYmFjay5oaWphY2tlZCB8fCAoY2FsbGJhY2suaGlqYWNrZWQgPSBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0XHRcdFx0aWYgKCFldmVudC5wcm9wYWdhdGlvblN0b3BwZWQpIHtcblx0XHRcdFx0XHRcdFx0Y2FsbGJhY2soZXZlbnQpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0pLCBjYXB0dXJlKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRhZHYuY2FsbChsYXllciwgdHlwZSwgY2FsbGJhY2ssIGNhcHR1cmUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdH1cblxuXHRcdC8vIElmIGEgaGFuZGxlciBpcyBhbHJlYWR5IGRlY2xhcmVkIGluIHRoZSBlbGVtZW50J3Mgb25jbGljayBhdHRyaWJ1dGUsIGl0IHdpbGwgYmUgZmlyZWQgYmVmb3JlXG5cdFx0Ly8gRmFzdENsaWNrJ3Mgb25DbGljayBoYW5kbGVyLiBGaXggdGhpcyBieSBwdWxsaW5nIG91dCB0aGUgdXNlci1kZWZpbmVkIGhhbmRsZXIgZnVuY3Rpb24gYW5kXG5cdFx0Ly8gYWRkaW5nIGl0IGFzIGxpc3RlbmVyLlxuXHRcdGlmICh0eXBlb2YgbGF5ZXIub25jbGljayA9PT0gJ2Z1bmN0aW9uJykge1xuXG5cdFx0XHQvLyBBbmRyb2lkIGJyb3dzZXIgb24gYXQgbGVhc3QgMy4yIHJlcXVpcmVzIGEgbmV3IHJlZmVyZW5jZSB0byB0aGUgZnVuY3Rpb24gaW4gbGF5ZXIub25jbGlja1xuXHRcdFx0Ly8gLSB0aGUgb2xkIG9uZSB3b24ndCB3b3JrIGlmIHBhc3NlZCB0byBhZGRFdmVudExpc3RlbmVyIGRpcmVjdGx5LlxuXHRcdFx0b2xkT25DbGljayA9IGxheWVyLm9uY2xpY2s7XG5cdFx0XHRsYXllci5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRcdG9sZE9uQ2xpY2soZXZlbnQpO1xuXHRcdFx0fSwgZmFsc2UpO1xuXHRcdFx0bGF5ZXIub25jbGljayA9IG51bGw7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCogV2luZG93cyBQaG9uZSA4LjEgZmFrZXMgdXNlciBhZ2VudCBzdHJpbmcgdG8gbG9vayBsaWtlIEFuZHJvaWQgYW5kIGlQaG9uZS5cblx0KlxuXHQqIEB0eXBlIGJvb2xlYW5cblx0Ki9cblx0dmFyIGRldmljZUlzV2luZG93c1Bob25lID0gbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKFwiV2luZG93cyBQaG9uZVwiKSA+PSAwO1xuXG5cdC8qKlxuXHQgKiBBbmRyb2lkIHJlcXVpcmVzIGV4Y2VwdGlvbnMuXG5cdCAqXG5cdCAqIEB0eXBlIGJvb2xlYW5cblx0ICovXG5cdHZhciBkZXZpY2VJc0FuZHJvaWQgPSBuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJ0FuZHJvaWQnKSA+IDAgJiYgIWRldmljZUlzV2luZG93c1Bob25lO1xuXG5cblx0LyoqXG5cdCAqIGlPUyByZXF1aXJlcyBleGNlcHRpb25zLlxuXHQgKlxuXHQgKiBAdHlwZSBib29sZWFuXG5cdCAqL1xuXHR2YXIgZGV2aWNlSXNJT1MgPSAvaVAoYWR8aG9uZXxvZCkvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkgJiYgIWRldmljZUlzV2luZG93c1Bob25lO1xuXG5cblx0LyoqXG5cdCAqIGlPUyA0IHJlcXVpcmVzIGFuIGV4Y2VwdGlvbiBmb3Igc2VsZWN0IGVsZW1lbnRzLlxuXHQgKlxuXHQgKiBAdHlwZSBib29sZWFuXG5cdCAqL1xuXHR2YXIgZGV2aWNlSXNJT1M0ID0gZGV2aWNlSXNJT1MgJiYgKC9PUyA0X1xcZChfXFxkKT8vKS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuXG5cblx0LyoqXG5cdCAqIGlPUyA2LjAtNy4qIHJlcXVpcmVzIHRoZSB0YXJnZXQgZWxlbWVudCB0byBiZSBtYW51YWxseSBkZXJpdmVkXG5cdCAqXG5cdCAqIEB0eXBlIGJvb2xlYW5cblx0ICovXG5cdHZhciBkZXZpY2VJc0lPU1dpdGhCYWRUYXJnZXQgPSBkZXZpY2VJc0lPUyAmJiAoL09TIFs2LTddX1xcZC8pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG5cblx0LyoqXG5cdCAqIEJsYWNrQmVycnkgcmVxdWlyZXMgZXhjZXB0aW9ucy5cblx0ICpcblx0ICogQHR5cGUgYm9vbGVhblxuXHQgKi9cblx0dmFyIGRldmljZUlzQmxhY2tCZXJyeTEwID0gbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCdCQjEwJykgPiAwO1xuXG5cdC8qKlxuXHQgKiBWYWxpZCB0eXBlcyBmb3IgdGV4dCBpbnB1dHNcblx0ICpcblx0ICogQHR5cGUgYXJyYXlcblx0ICovXG5cdHZhciB0ZXh0RmllbGRzID0gWydlbWFpbCcsICdudW1iZXInLCAncGFzc3dvcmQnLCAnc2VhcmNoJywgJ3RlbCcsICd0ZXh0JywgJ3VybCddO1xuXG5cdC8qKlxuXHQgKiBEZXRlcm1pbmUgd2hldGhlciBhIGdpdmVuIGVsZW1lbnQgcmVxdWlyZXMgYSBuYXRpdmUgY2xpY2suXG5cdCAqXG5cdCAqIEBwYXJhbSB7RXZlbnRUYXJnZXR8RWxlbWVudH0gdGFyZ2V0IFRhcmdldCBET00gZWxlbWVudFxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIHRoZSBlbGVtZW50IG5lZWRzIGEgbmF0aXZlIGNsaWNrXG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm5lZWRzQ2xpY2sgPSBmdW5jdGlvbih0YXJnZXQpIHtcblx0XHRzd2l0Y2ggKHRhcmdldC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSB7XG5cblx0XHQvLyBEb24ndCBzZW5kIGEgc3ludGhldGljIGNsaWNrIHRvIGRpc2FibGVkIGlucHV0cyAoaXNzdWUgIzYyKVxuXHRcdGNhc2UgJ2J1dHRvbic6XG5cdFx0Y2FzZSAnc2VsZWN0Jzpcblx0XHRjYXNlICd0ZXh0YXJlYSc6XG5cdFx0XHRpZiAodGFyZ2V0LmRpc2FibGVkKSB7XG5cdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRicmVhaztcblx0XHRjYXNlICdpbnB1dCc6XG5cblx0XHRcdC8vIEZpbGUgaW5wdXRzIG5lZWQgcmVhbCBjbGlja3Mgb24gaU9TIDYgZHVlIHRvIGEgYnJvd3NlciBidWcgKGlzc3VlICM2OClcblx0XHRcdGlmICgoZGV2aWNlSXNJT1MgJiYgdGFyZ2V0LnR5cGUgPT09ICdmaWxlJykgfHwgdGFyZ2V0LmRpc2FibGVkKSB7XG5cdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRicmVhaztcblx0XHRjYXNlICdsYWJlbCc6XG5cdFx0Y2FzZSAnaWZyYW1lJzogLy8gaU9TOCBob21lc2NyZWVuIGFwcHMgY2FuIHByZXZlbnQgZXZlbnRzIGJ1YmJsaW5nIGludG8gZnJhbWVzXG5cdFx0Y2FzZSAndmlkZW8nOlxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuICgvXFxibmVlZHNjbGlja1xcYi8pLnRlc3QodGFyZ2V0LmNsYXNzTmFtZSk7XG5cdH07XG5cblxuXHQvKipcblx0ICogRGV0ZXJtaW5lIHdoZXRoZXIgYSBnaXZlbiBlbGVtZW50IHJlcXVpcmVzIGEgY2FsbCB0byBmb2N1cyB0byBzaW11bGF0ZSBjbGljayBpbnRvIGVsZW1lbnQuXG5cdCAqXG5cdCAqIEBwYXJhbSB7RXZlbnRUYXJnZXR8RWxlbWVudH0gdGFyZ2V0IFRhcmdldCBET00gZWxlbWVudFxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIHRoZSBlbGVtZW50IHJlcXVpcmVzIGEgY2FsbCB0byBmb2N1cyB0byBzaW11bGF0ZSBuYXRpdmUgY2xpY2suXG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm5lZWRzRm9jdXMgPSBmdW5jdGlvbih0YXJnZXQpIHtcblx0XHRzd2l0Y2ggKHRhcmdldC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSB7XG5cdFx0Y2FzZSAndGV4dGFyZWEnOlxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0Y2FzZSAnc2VsZWN0Jzpcblx0XHRcdHJldHVybiAhZGV2aWNlSXNBbmRyb2lkO1xuXHRcdGNhc2UgJ2lucHV0Jzpcblx0XHRcdHN3aXRjaCAodGFyZ2V0LnR5cGUpIHtcblx0XHRcdGNhc2UgJ2J1dHRvbic6XG5cdFx0XHRjYXNlICdjaGVja2JveCc6XG5cdFx0XHRjYXNlICdmaWxlJzpcblx0XHRcdGNhc2UgJ2ltYWdlJzpcblx0XHRcdGNhc2UgJ3JhZGlvJzpcblx0XHRcdGNhc2UgJ3N1Ym1pdCc6XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gTm8gcG9pbnQgaW4gYXR0ZW1wdGluZyB0byBmb2N1cyBkaXNhYmxlZCBpbnB1dHNcblx0XHRcdHJldHVybiAhdGFyZ2V0LmRpc2FibGVkICYmICF0YXJnZXQucmVhZE9ubHk7XG5cdFx0ZGVmYXVsdDpcblx0XHRcdHJldHVybiAoL1xcYm5lZWRzZm9jdXNcXGIvKS50ZXN0KHRhcmdldC5jbGFzc05hbWUpO1xuXHRcdH1cblx0fTtcblxuXG5cdC8qKlxuXHQgKiBTZW5kIGEgY2xpY2sgZXZlbnQgdG8gdGhlIHNwZWNpZmllZCBlbGVtZW50LlxuXHQgKlxuXHQgKiBAcGFyYW0ge0V2ZW50VGFyZ2V0fEVsZW1lbnR9IHRhcmdldEVsZW1lbnRcblx0ICogQHBhcmFtIHtFdmVudH0gZXZlbnRcblx0ICovXG5cdEZhc3RDbGljay5wcm90b3R5cGUuc2VuZENsaWNrID0gZnVuY3Rpb24odGFyZ2V0RWxlbWVudCwgZXZlbnQpIHtcblx0XHR2YXIgY2xpY2tFdmVudCwgdG91Y2g7XG5cblx0XHQvLyBPbiBzb21lIEFuZHJvaWQgZGV2aWNlcyBhY3RpdmVFbGVtZW50IG5lZWRzIHRvIGJlIGJsdXJyZWQgb3RoZXJ3aXNlIHRoZSBzeW50aGV0aWMgY2xpY2sgd2lsbCBoYXZlIG5vIGVmZmVjdCAoIzI0KVxuXHRcdGlmIChkb2N1bWVudC5hY3RpdmVFbGVtZW50ICYmIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgIT09IHRhcmdldEVsZW1lbnQpIHtcblx0XHRcdGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQuYmx1cigpO1xuXHRcdH1cblxuXHRcdHRvdWNoID0gZXZlbnQuY2hhbmdlZFRvdWNoZXNbMF07XG5cblx0XHQvLyBTeW50aGVzaXNlIGEgY2xpY2sgZXZlbnQsIHdpdGggYW4gZXh0cmEgYXR0cmlidXRlIHNvIGl0IGNhbiBiZSB0cmFja2VkXG5cdFx0Y2xpY2tFdmVudCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdNb3VzZUV2ZW50cycpO1xuXHRcdGNsaWNrRXZlbnQuaW5pdE1vdXNlRXZlbnQodGhpcy5kZXRlcm1pbmVFdmVudFR5cGUodGFyZ2V0RWxlbWVudCksIHRydWUsIHRydWUsIHdpbmRvdywgMSwgdG91Y2guc2NyZWVuWCwgdG91Y2guc2NyZWVuWSwgdG91Y2guY2xpZW50WCwgdG91Y2guY2xpZW50WSwgZmFsc2UsIGZhbHNlLCBmYWxzZSwgZmFsc2UsIDAsIG51bGwpO1xuXHRcdGNsaWNrRXZlbnQuZm9yd2FyZGVkVG91Y2hFdmVudCA9IHRydWU7XG5cdFx0dGFyZ2V0RWxlbWVudC5kaXNwYXRjaEV2ZW50KGNsaWNrRXZlbnQpO1xuXHR9O1xuXG5cdEZhc3RDbGljay5wcm90b3R5cGUuZGV0ZXJtaW5lRXZlbnRUeXBlID0gZnVuY3Rpb24odGFyZ2V0RWxlbWVudCkge1xuXG5cdFx0Ly9Jc3N1ZSAjMTU5OiBBbmRyb2lkIENocm9tZSBTZWxlY3QgQm94IGRvZXMgbm90IG9wZW4gd2l0aCBhIHN5bnRoZXRpYyBjbGljayBldmVudFxuXHRcdGlmIChkZXZpY2VJc0FuZHJvaWQgJiYgdGFyZ2V0RWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdzZWxlY3QnKSB7XG5cdFx0XHRyZXR1cm4gJ21vdXNlZG93bic7XG5cdFx0fVxuXG5cdFx0cmV0dXJuICdjbGljayc7XG5cdH07XG5cblxuXHQvKipcblx0ICogQHBhcmFtIHtFdmVudFRhcmdldHxFbGVtZW50fSB0YXJnZXRFbGVtZW50XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLmZvY3VzID0gZnVuY3Rpb24odGFyZ2V0RWxlbWVudCkge1xuXHRcdHZhciBsZW5ndGg7XG5cblx0XHQvLyBJc3N1ZSAjMTYwOiBvbiBpT1MgNywgc29tZSBpbnB1dCBlbGVtZW50cyAoZS5nLiBkYXRlIGRhdGV0aW1lIG1vbnRoKSB0aHJvdyBhIHZhZ3VlIFR5cGVFcnJvciBvbiBzZXRTZWxlY3Rpb25SYW5nZS4gVGhlc2UgZWxlbWVudHMgZG9uJ3QgaGF2ZSBhbiBpbnRlZ2VyIHZhbHVlIGZvciB0aGUgc2VsZWN0aW9uU3RhcnQgYW5kIHNlbGVjdGlvbkVuZCBwcm9wZXJ0aWVzLCBidXQgdW5mb3J0dW5hdGVseSB0aGF0IGNhbid0IGJlIHVzZWQgZm9yIGRldGVjdGlvbiBiZWNhdXNlIGFjY2Vzc2luZyB0aGUgcHJvcGVydGllcyBhbHNvIHRocm93cyBhIFR5cGVFcnJvci4gSnVzdCBjaGVjayB0aGUgdHlwZSBpbnN0ZWFkLiBGaWxlZCBhcyBBcHBsZSBidWcgIzE1MTIyNzI0LlxuXHRcdGlmIChkZXZpY2VJc0lPUyAmJiB0YXJnZXRFbGVtZW50LnNldFNlbGVjdGlvblJhbmdlICYmIHRhcmdldEVsZW1lbnQudHlwZS5pbmRleE9mKCdkYXRlJykgIT09IDAgJiYgdGFyZ2V0RWxlbWVudC50eXBlICE9PSAndGltZScgJiYgdGFyZ2V0RWxlbWVudC50eXBlICE9PSAnbW9udGgnICYmIHRhcmdldEVsZW1lbnQudHlwZSAhPT0gJ2VtYWlsJyAmJiB0YXJnZXRFbGVtZW50LnR5cGUgIT09ICdudW1iZXInKSB7XG5cdFx0XHRsZW5ndGggPSB0YXJnZXRFbGVtZW50LnZhbHVlLmxlbmd0aDtcblx0XHRcdHRhcmdldEVsZW1lbnQuc2V0U2VsZWN0aW9uUmFuZ2UobGVuZ3RoLCBsZW5ndGgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0YXJnZXRFbGVtZW50LmZvY3VzKCk7XG5cdFx0fVxuXHR9O1xuXG5cblx0LyoqXG5cdCAqIENoZWNrIHdoZXRoZXIgdGhlIGdpdmVuIHRhcmdldCBlbGVtZW50IGlzIGEgY2hpbGQgb2YgYSBzY3JvbGxhYmxlIGxheWVyIGFuZCBpZiBzbywgc2V0IGEgZmxhZyBvbiBpdC5cblx0ICpcblx0ICogQHBhcmFtIHtFdmVudFRhcmdldHxFbGVtZW50fSB0YXJnZXRFbGVtZW50XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLnVwZGF0ZVNjcm9sbFBhcmVudCA9IGZ1bmN0aW9uKHRhcmdldEVsZW1lbnQpIHtcblx0XHR2YXIgc2Nyb2xsUGFyZW50LCBwYXJlbnRFbGVtZW50O1xuXG5cdFx0c2Nyb2xsUGFyZW50ID0gdGFyZ2V0RWxlbWVudC5mYXN0Q2xpY2tTY3JvbGxQYXJlbnQ7XG5cblx0XHQvLyBBdHRlbXB0IHRvIGRpc2NvdmVyIHdoZXRoZXIgdGhlIHRhcmdldCBlbGVtZW50IGlzIGNvbnRhaW5lZCB3aXRoaW4gYSBzY3JvbGxhYmxlIGxheWVyLiBSZS1jaGVjayBpZiB0aGVcblx0XHQvLyB0YXJnZXQgZWxlbWVudCB3YXMgbW92ZWQgdG8gYW5vdGhlciBwYXJlbnQuXG5cdFx0aWYgKCFzY3JvbGxQYXJlbnQgfHwgIXNjcm9sbFBhcmVudC5jb250YWlucyh0YXJnZXRFbGVtZW50KSkge1xuXHRcdFx0cGFyZW50RWxlbWVudCA9IHRhcmdldEVsZW1lbnQ7XG5cdFx0XHRkbyB7XG5cdFx0XHRcdGlmIChwYXJlbnRFbGVtZW50LnNjcm9sbEhlaWdodCA+IHBhcmVudEVsZW1lbnQub2Zmc2V0SGVpZ2h0KSB7XG5cdFx0XHRcdFx0c2Nyb2xsUGFyZW50ID0gcGFyZW50RWxlbWVudDtcblx0XHRcdFx0XHR0YXJnZXRFbGVtZW50LmZhc3RDbGlja1Njcm9sbFBhcmVudCA9IHBhcmVudEVsZW1lbnQ7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRwYXJlbnRFbGVtZW50ID0gcGFyZW50RWxlbWVudC5wYXJlbnRFbGVtZW50O1xuXHRcdFx0fSB3aGlsZSAocGFyZW50RWxlbWVudCk7XG5cdFx0fVxuXG5cdFx0Ly8gQWx3YXlzIHVwZGF0ZSB0aGUgc2Nyb2xsIHRvcCB0cmFja2VyIGlmIHBvc3NpYmxlLlxuXHRcdGlmIChzY3JvbGxQYXJlbnQpIHtcblx0XHRcdHNjcm9sbFBhcmVudC5mYXN0Q2xpY2tMYXN0U2Nyb2xsVG9wID0gc2Nyb2xsUGFyZW50LnNjcm9sbFRvcDtcblx0XHR9XG5cdH07XG5cblxuXHQvKipcblx0ICogQHBhcmFtIHtFdmVudFRhcmdldH0gdGFyZ2V0RWxlbWVudFxuXHQgKiBAcmV0dXJucyB7RWxlbWVudHxFdmVudFRhcmdldH1cblx0ICovXG5cdEZhc3RDbGljay5wcm90b3R5cGUuZ2V0VGFyZ2V0RWxlbWVudEZyb21FdmVudFRhcmdldCA9IGZ1bmN0aW9uKGV2ZW50VGFyZ2V0KSB7XG5cblx0XHQvLyBPbiBzb21lIG9sZGVyIGJyb3dzZXJzIChub3RhYmx5IFNhZmFyaSBvbiBpT1MgNC4xIC0gc2VlIGlzc3VlICM1NikgdGhlIGV2ZW50IHRhcmdldCBtYXkgYmUgYSB0ZXh0IG5vZGUuXG5cdFx0aWYgKGV2ZW50VGFyZ2V0Lm5vZGVUeXBlID09PSBOb2RlLlRFWFRfTk9ERSkge1xuXHRcdFx0cmV0dXJuIGV2ZW50VGFyZ2V0LnBhcmVudE5vZGU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGV2ZW50VGFyZ2V0O1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIEBwYXJhbSB7RXZlbnRUYXJnZXR9IHRhcmdldEVsZW1lbnRcblx0ICogQHJldHVybnMge2Jvb2xlYW59XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLmlzVGV4dEZpZWxkID0gZnVuY3Rpb24odGFyZ2V0RWxlbWVudCkge1xuXHRcdHJldHVybiAoXG5cdFx0XHR0YXJnZXRFbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ3RleHRhcmVhJ1xuXHRcdFx0fHwgdGV4dEZpZWxkcy5pbmRleE9mKHRhcmdldEVsZW1lbnQudHlwZSkgIT09IC0xXG5cdFx0KTtcblx0fTtcblxuXHQvKipcblx0ICogT24gdG91Y2ggc3RhcnQsIHJlY29yZCB0aGUgcG9zaXRpb24gYW5kIHNjcm9sbCBvZmZzZXQuXG5cdCAqXG5cdCAqIEBwYXJhbSB7RXZlbnR9IGV2ZW50XG5cdCAqIEByZXR1cm5zIHtib29sZWFufVxuXHQgKi9cblx0RmFzdENsaWNrLnByb3RvdHlwZS5vblRvdWNoU3RhcnQgPSBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciB0YXJnZXRFbGVtZW50LCB0b3VjaCwgc2VsZWN0aW9uO1xuXG5cdFx0Ly8gSWdub3JlIG11bHRpcGxlIHRvdWNoZXMsIG90aGVyd2lzZSBwaW5jaC10by16b29tIGlzIHByZXZlbnRlZCBpZiBib3RoIGZpbmdlcnMgYXJlIG9uIHRoZSBGYXN0Q2xpY2sgZWxlbWVudCAoaXNzdWUgIzExMSkuXG5cdFx0aWYgKGV2ZW50LnRhcmdldFRvdWNoZXMubGVuZ3RoID4gMSkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0dGFyZ2V0RWxlbWVudCA9IHRoaXMuZ2V0VGFyZ2V0RWxlbWVudEZyb21FdmVudFRhcmdldChldmVudC50YXJnZXQpO1xuXHRcdHRvdWNoID0gZXZlbnQudGFyZ2V0VG91Y2hlc1swXTtcblxuXHRcdC8vIElnbm9yZSB0b3VjaGVzIG9uIGNvbnRlbnRlZGl0YWJsZSBlbGVtZW50cyB0byBwcmV2ZW50IGNvbmZsaWN0IHdpdGggdGV4dCBzZWxlY3Rpb24uXG5cdFx0Ly8gKEZvciBkZXRhaWxzOiBodHRwczovL2dpdGh1Yi5jb20vZnRsYWJzL2Zhc3RjbGljay9wdWxsLzIxMSApXG5cdFx0aWYgKHRhcmdldEVsZW1lbnQuaXNDb250ZW50RWRpdGFibGUpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdGlmIChkZXZpY2VJc0lPUykge1xuXHRcdFx0Ly8gSWdub3JlIHRvdWNoc3RhcnQgaW4gZm9jdXNlZCB0ZXh0IGZpZWxkXG5cdFx0XHQvLyBBbGxvd3Mgbm9ybWFsIHRleHQgc2VsZWN0aW9uIGFuZCBjb21tYW5kcyAoc2VsZWN0L3Bhc3RlL2N1dCkgd2hlbiBhIGZpZWxkIGhhcyBmb2N1cywgd2hpbGUgc3RpbGwgYWxsb3dpbmcgZmFzdCB0YXAtdG8tZm9jdXMuXG5cdFx0XHQvLyBXaXRob3V0IHRoaXMgZml4LCB1c2VyIG5lZWRzIHRvIHRhcC1hbmQtaG9sZCBhIHRleHQgZmllbGQgZm9yIGNvbnRleHQgbWVudSwgYW5kIGRvdWJsZS10YXAgdG8gc2VsZWN0IHRleHQgZG9lc24ndCB3b3JrIGF0IGFsbC5cblx0XHRcdGlmICh0YXJnZXRFbGVtZW50ID09PSBkb2N1bWVudC5hY3RpdmVFbGVtZW50ICYmIHRoaXMuaXNUZXh0RmllbGQodGFyZ2V0RWxlbWVudCkpIHtcblx0XHRcdCAgcmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cblx0XHRcdGlmICghZGV2aWNlSXNJT1M0KSB7XG5cblx0XHRcdFx0Ly8gV2VpcmQgdGhpbmdzIGhhcHBlbiBvbiBpT1Mgd2hlbiBhbiBhbGVydCBvciBjb25maXJtIGRpYWxvZyBpcyBvcGVuZWQgZnJvbSBhIGNsaWNrIGV2ZW50IGNhbGxiYWNrIChpc3N1ZSAjMjMpOlxuXHRcdFx0XHQvLyB3aGVuIHRoZSB1c2VyIG5leHQgdGFwcyBhbnl3aGVyZSBlbHNlIG9uIHRoZSBwYWdlLCBuZXcgdG91Y2hzdGFydCBhbmQgdG91Y2hlbmQgZXZlbnRzIGFyZSBkaXNwYXRjaGVkXG5cdFx0XHRcdC8vIHdpdGggdGhlIHNhbWUgaWRlbnRpZmllciBhcyB0aGUgdG91Y2ggZXZlbnQgdGhhdCBwcmV2aW91c2x5IHRyaWdnZXJlZCB0aGUgY2xpY2sgdGhhdCB0cmlnZ2VyZWQgdGhlIGFsZXJ0LlxuXHRcdFx0XHQvLyBTYWRseSwgdGhlcmUgaXMgYW4gaXNzdWUgb24gaU9TIDQgdGhhdCBjYXVzZXMgc29tZSBub3JtYWwgdG91Y2ggZXZlbnRzIHRvIGhhdmUgdGhlIHNhbWUgaWRlbnRpZmllciBhcyBhblxuXHRcdFx0XHQvLyBpbW1lZGlhdGVseSBwcmVjZWVkaW5nIHRvdWNoIGV2ZW50IChpc3N1ZSAjNTIpLCBzbyB0aGlzIGZpeCBpcyB1bmF2YWlsYWJsZSBvbiB0aGF0IHBsYXRmb3JtLlxuXHRcdFx0XHQvLyBJc3N1ZSAxMjA6IHRvdWNoLmlkZW50aWZpZXIgaXMgMCB3aGVuIENocm9tZSBkZXYgdG9vbHMgJ0VtdWxhdGUgdG91Y2ggZXZlbnRzJyBpcyBzZXQgd2l0aCBhbiBpT1MgZGV2aWNlIFVBIHN0cmluZyxcblx0XHRcdFx0Ly8gd2hpY2ggY2F1c2VzIGFsbCB0b3VjaCBldmVudHMgdG8gYmUgaWdub3JlZC4gQXMgdGhpcyBibG9jayBvbmx5IGFwcGxpZXMgdG8gaU9TLCBhbmQgaU9TIGlkZW50aWZpZXJzIGFyZSBhbHdheXMgbG9uZyxcblx0XHRcdFx0Ly8gcmFuZG9tIGludGVnZXJzLCBpdCdzIHNhZmUgdG8gdG8gY29udGludWUgaWYgdGhlIGlkZW50aWZpZXIgaXMgMCBoZXJlLlxuXHRcdFx0XHRpZiAodG91Y2guaWRlbnRpZmllciAmJiB0b3VjaC5pZGVudGlmaWVyID09PSB0aGlzLmxhc3RUb3VjaElkZW50aWZpZXIpIHtcblx0XHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMubGFzdFRvdWNoSWRlbnRpZmllciA9IHRvdWNoLmlkZW50aWZpZXI7XG5cblx0XHRcdFx0Ly8gSWYgdGhlIHRhcmdldCBlbGVtZW50IGlzIGEgY2hpbGQgb2YgYSBzY3JvbGxhYmxlIGxheWVyICh1c2luZyAtd2Via2l0LW92ZXJmbG93LXNjcm9sbGluZzogdG91Y2gpIGFuZDpcblx0XHRcdFx0Ly8gMSkgdGhlIHVzZXIgZG9lcyBhIGZsaW5nIHNjcm9sbCBvbiB0aGUgc2Nyb2xsYWJsZSBsYXllclxuXHRcdFx0XHQvLyAyKSB0aGUgdXNlciBzdG9wcyB0aGUgZmxpbmcgc2Nyb2xsIHdpdGggYW5vdGhlciB0YXBcblx0XHRcdFx0Ly8gdGhlbiB0aGUgZXZlbnQudGFyZ2V0IG9mIHRoZSBsYXN0ICd0b3VjaGVuZCcgZXZlbnQgd2lsbCBiZSB0aGUgZWxlbWVudCB0aGF0IHdhcyB1bmRlciB0aGUgdXNlcidzIGZpbmdlclxuXHRcdFx0XHQvLyB3aGVuIHRoZSBmbGluZyBzY3JvbGwgd2FzIHN0YXJ0ZWQsIGNhdXNpbmcgRmFzdENsaWNrIHRvIHNlbmQgYSBjbGljayBldmVudCB0byB0aGF0IGxheWVyIC0gdW5sZXNzIGEgY2hlY2tcblx0XHRcdFx0Ly8gaXMgbWFkZSB0byBlbnN1cmUgdGhhdCBhIHBhcmVudCBsYXllciB3YXMgbm90IHNjcm9sbGVkIGJlZm9yZSBzZW5kaW5nIGEgc3ludGhldGljIGNsaWNrIChpc3N1ZSAjNDIpLlxuXHRcdFx0XHR0aGlzLnVwZGF0ZVNjcm9sbFBhcmVudCh0YXJnZXRFbGVtZW50KTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aGlzLnRyYWNraW5nQ2xpY2sgPSB0cnVlO1xuXHRcdHRoaXMudHJhY2tpbmdDbGlja1N0YXJ0ID0gZXZlbnQudGltZVN0YW1wO1xuXHRcdHRoaXMudGFyZ2V0RWxlbWVudCA9IHRhcmdldEVsZW1lbnQ7XG5cblx0XHR0aGlzLnRvdWNoU3RhcnRYID0gdG91Y2gucGFnZVg7XG5cdFx0dGhpcy50b3VjaFN0YXJ0WSA9IHRvdWNoLnBhZ2VZO1xuXG5cdFx0Ly8gUHJldmVudCBwaGFudG9tIGNsaWNrcyBvbiBmYXN0IGRvdWJsZS10YXAgKGlzc3VlICMzNilcblx0XHRpZiAoKGV2ZW50LnRpbWVTdGFtcCAtIHRoaXMubGFzdENsaWNrVGltZSkgPCB0aGlzLnRhcERlbGF5ICYmIChldmVudC50aW1lU3RhbXAgLSB0aGlzLmxhc3RDbGlja1RpbWUpID4gLTEpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRydWU7XG5cdH07XG5cblxuXHQvKipcblx0ICogQmFzZWQgb24gYSB0b3VjaG1vdmUgZXZlbnQgb2JqZWN0LCBjaGVjayB3aGV0aGVyIHRoZSB0b3VjaCBoYXMgbW92ZWQgcGFzdCBhIGJvdW5kYXJ5IHNpbmNlIGl0IHN0YXJ0ZWQuXG5cdCAqXG5cdCAqIEBwYXJhbSB7RXZlbnR9IGV2ZW50XG5cdCAqIEByZXR1cm5zIHtib29sZWFufVxuXHQgKi9cblx0RmFzdENsaWNrLnByb3RvdHlwZS50b3VjaEhhc01vdmVkID0gZnVuY3Rpb24oZXZlbnQpIHtcblx0XHR2YXIgdG91Y2ggPSBldmVudC5jaGFuZ2VkVG91Y2hlc1swXSwgYm91bmRhcnkgPSB0aGlzLnRvdWNoQm91bmRhcnk7XG5cblx0XHRpZiAoTWF0aC5hYnModG91Y2gucGFnZVggLSB0aGlzLnRvdWNoU3RhcnRYKSA+IGJvdW5kYXJ5IHx8IE1hdGguYWJzKHRvdWNoLnBhZ2VZIC0gdGhpcy50b3VjaFN0YXJ0WSkgPiBib3VuZGFyeSkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIFVwZGF0ZSB0aGUgbGFzdCBwb3NpdGlvbi5cblx0ICpcblx0ICogQHBhcmFtIHtFdmVudH0gZXZlbnRcblx0ICogQHJldHVybnMge2Jvb2xlYW59XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm9uVG91Y2hNb3ZlID0gZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoIXRoaXMudHJhY2tpbmdDbGljaykge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0Ly8gSWYgdGhlIHRvdWNoIGhhcyBtb3ZlZCwgY2FuY2VsIHRoZSBjbGljayB0cmFja2luZ1xuXHRcdGlmICh0aGlzLnRhcmdldEVsZW1lbnQgIT09IHRoaXMuZ2V0VGFyZ2V0RWxlbWVudEZyb21FdmVudFRhcmdldChldmVudC50YXJnZXQpIHx8IHRoaXMudG91Y2hIYXNNb3ZlZChldmVudCkpIHtcblx0XHRcdHRoaXMudHJhY2tpbmdDbGljayA9IGZhbHNlO1xuXHRcdFx0dGhpcy50YXJnZXRFbGVtZW50ID0gbnVsbDtcblx0XHR9XG5cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fTtcblxuXG5cdC8qKlxuXHQgKiBBdHRlbXB0IHRvIGZpbmQgdGhlIGxhYmVsbGVkIGNvbnRyb2wgZm9yIHRoZSBnaXZlbiBsYWJlbCBlbGVtZW50LlxuXHQgKlxuXHQgKiBAcGFyYW0ge0V2ZW50VGFyZ2V0fEhUTUxMYWJlbEVsZW1lbnR9IGxhYmVsRWxlbWVudFxuXHQgKiBAcmV0dXJucyB7RWxlbWVudHxudWxsfVxuXHQgKi9cblx0RmFzdENsaWNrLnByb3RvdHlwZS5maW5kQ29udHJvbCA9IGZ1bmN0aW9uKGxhYmVsRWxlbWVudCkge1xuXG5cdFx0Ly8gRmFzdCBwYXRoIGZvciBuZXdlciBicm93c2VycyBzdXBwb3J0aW5nIHRoZSBIVE1MNSBjb250cm9sIGF0dHJpYnV0ZVxuXHRcdGlmIChsYWJlbEVsZW1lbnQuY29udHJvbCAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRyZXR1cm4gbGFiZWxFbGVtZW50LmNvbnRyb2w7XG5cdFx0fVxuXG5cdFx0Ly8gQWxsIGJyb3dzZXJzIHVuZGVyIHRlc3QgdGhhdCBzdXBwb3J0IHRvdWNoIGV2ZW50cyBhbHNvIHN1cHBvcnQgdGhlIEhUTUw1IGh0bWxGb3IgYXR0cmlidXRlXG5cdFx0aWYgKGxhYmVsRWxlbWVudC5odG1sRm9yKSB7XG5cdFx0XHRyZXR1cm4gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQobGFiZWxFbGVtZW50Lmh0bWxGb3IpO1xuXHRcdH1cblxuXHRcdC8vIElmIG5vIGZvciBhdHRyaWJ1dGUgZXhpc3RzLCBhdHRlbXB0IHRvIHJldHJpZXZlIHRoZSBmaXJzdCBsYWJlbGxhYmxlIGRlc2NlbmRhbnQgZWxlbWVudFxuXHRcdC8vIHRoZSBsaXN0IG9mIHdoaWNoIGlzIGRlZmluZWQgaGVyZTogaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDUvZm9ybXMuaHRtbCNjYXRlZ29yeS1sYWJlbFxuXHRcdHJldHVybiBsYWJlbEVsZW1lbnQucXVlcnlTZWxlY3RvcignYnV0dG9uLCBpbnB1dDpub3QoW3R5cGU9aGlkZGVuXSksIGtleWdlbiwgbWV0ZXIsIG91dHB1dCwgcHJvZ3Jlc3MsIHNlbGVjdCwgdGV4dGFyZWEnKTtcblx0fTtcblxuXG5cdC8qKlxuXHQgKiBPbiB0b3VjaCBlbmQsIGRldGVybWluZSB3aGV0aGVyIHRvIHNlbmQgYSBjbGljayBldmVudCBhdCBvbmNlLlxuXHQgKlxuXHQgKiBAcGFyYW0ge0V2ZW50fSBldmVudFxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn1cblx0ICovXG5cdEZhc3RDbGljay5wcm90b3R5cGUub25Ub3VjaEVuZCA9IGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0dmFyIGZvckVsZW1lbnQsIHRyYWNraW5nQ2xpY2tTdGFydCwgdGFyZ2V0VGFnTmFtZSwgc2Nyb2xsUGFyZW50LCB0b3VjaCwgdGFyZ2V0RWxlbWVudCA9IHRoaXMudGFyZ2V0RWxlbWVudDtcblxuXHRcdGlmICghdGhpcy50cmFja2luZ0NsaWNrKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHQvLyBQcmV2ZW50IHBoYW50b20gY2xpY2tzIG9uIGZhc3QgZG91YmxlLXRhcCAoaXNzdWUgIzM2KVxuXHRcdGlmICgoZXZlbnQudGltZVN0YW1wIC0gdGhpcy5sYXN0Q2xpY2tUaW1lKSA8IHRoaXMudGFwRGVsYXkgJiYgKGV2ZW50LnRpbWVTdGFtcCAtIHRoaXMubGFzdENsaWNrVGltZSkgPiAtMSkge1xuXHRcdFx0dGhpcy5jYW5jZWxOZXh0Q2xpY2sgPSB0cnVlO1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKChldmVudC50aW1lU3RhbXAgLSB0aGlzLnRyYWNraW5nQ2xpY2tTdGFydCkgPiB0aGlzLnRhcFRpbWVvdXQpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdC8vIFJlc2V0IHRvIHByZXZlbnQgd3JvbmcgY2xpY2sgY2FuY2VsIG9uIGlucHV0IChpc3N1ZSAjMTU2KS5cblx0XHR0aGlzLmNhbmNlbE5leHRDbGljayA9IGZhbHNlO1xuXG5cdFx0dGhpcy5sYXN0Q2xpY2tUaW1lID0gZXZlbnQudGltZVN0YW1wO1xuXG5cdFx0dHJhY2tpbmdDbGlja1N0YXJ0ID0gdGhpcy50cmFja2luZ0NsaWNrU3RhcnQ7XG5cdFx0dGhpcy50cmFja2luZ0NsaWNrID0gZmFsc2U7XG5cdFx0dGhpcy50cmFja2luZ0NsaWNrU3RhcnQgPSAwO1xuXG5cdFx0Ly8gT24gc29tZSBpT1MgZGV2aWNlcywgdGhlIHRhcmdldEVsZW1lbnQgc3VwcGxpZWQgd2l0aCB0aGUgZXZlbnQgaXMgaW52YWxpZCBpZiB0aGUgbGF5ZXJcblx0XHQvLyBpcyBwZXJmb3JtaW5nIGEgdHJhbnNpdGlvbiBvciBzY3JvbGwsIGFuZCBoYXMgdG8gYmUgcmUtZGV0ZWN0ZWQgbWFudWFsbHkuIE5vdGUgdGhhdFxuXHRcdC8vIGZvciB0aGlzIHRvIGZ1bmN0aW9uIGNvcnJlY3RseSwgaXQgbXVzdCBiZSBjYWxsZWQgKmFmdGVyKiB0aGUgZXZlbnQgdGFyZ2V0IGlzIGNoZWNrZWQhXG5cdFx0Ly8gU2VlIGlzc3VlICM1NzsgYWxzbyBmaWxlZCBhcyByZGFyOi8vMTMwNDg1ODkgLlxuXHRcdGlmIChkZXZpY2VJc0lPU1dpdGhCYWRUYXJnZXQpIHtcblx0XHRcdHRvdWNoID0gZXZlbnQuY2hhbmdlZFRvdWNoZXNbMF07XG5cblx0XHRcdC8vIEluIGNlcnRhaW4gY2FzZXMgYXJndW1lbnRzIG9mIGVsZW1lbnRGcm9tUG9pbnQgY2FuIGJlIG5lZ2F0aXZlLCBzbyBwcmV2ZW50IHNldHRpbmcgdGFyZ2V0RWxlbWVudCB0byBudWxsXG5cdFx0XHR0YXJnZXRFbGVtZW50ID0gZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludCh0b3VjaC5wYWdlWCAtIHdpbmRvdy5wYWdlWE9mZnNldCwgdG91Y2gucGFnZVkgLSB3aW5kb3cucGFnZVlPZmZzZXQpIHx8IHRhcmdldEVsZW1lbnQ7XG5cdFx0XHR0YXJnZXRFbGVtZW50LmZhc3RDbGlja1Njcm9sbFBhcmVudCA9IHRoaXMudGFyZ2V0RWxlbWVudC5mYXN0Q2xpY2tTY3JvbGxQYXJlbnQ7XG5cdFx0fVxuXG5cdFx0dGFyZ2V0VGFnTmFtZSA9IHRhcmdldEVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdGlmICh0YXJnZXRUYWdOYW1lID09PSAnbGFiZWwnKSB7XG5cdFx0XHRmb3JFbGVtZW50ID0gdGhpcy5maW5kQ29udHJvbCh0YXJnZXRFbGVtZW50KTtcblx0XHRcdGlmIChmb3JFbGVtZW50KSB7XG5cdFx0XHRcdHRoaXMuZm9jdXModGFyZ2V0RWxlbWVudCk7XG5cdFx0XHRcdGlmIChkZXZpY2VJc0FuZHJvaWQpIHtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0YXJnZXRFbGVtZW50ID0gZm9yRWxlbWVudDtcblx0XHRcdH1cblx0XHR9IGVsc2UgaWYgKHRoaXMubmVlZHNGb2N1cyh0YXJnZXRFbGVtZW50KSkge1xuXG5cdFx0XHQvLyBDYXNlIDE6IElmIHRoZSB0b3VjaCBzdGFydGVkIGEgd2hpbGUgYWdvIChiZXN0IGd1ZXNzIGlzIDEwMG1zIGJhc2VkIG9uIHRlc3RzIGZvciBpc3N1ZSAjMzYpIHRoZW4gZm9jdXMgd2lsbCBiZSB0cmlnZ2VyZWQgYW55d2F5LiBSZXR1cm4gZWFybHkgYW5kIHVuc2V0IHRoZSB0YXJnZXQgZWxlbWVudCByZWZlcmVuY2Ugc28gdGhhdCB0aGUgc3Vic2VxdWVudCBjbGljayB3aWxsIGJlIGFsbG93ZWQgdGhyb3VnaC5cblx0XHRcdC8vIENhc2UgMjogV2l0aG91dCB0aGlzIGV4Y2VwdGlvbiBmb3IgaW5wdXQgZWxlbWVudHMgdGFwcGVkIHdoZW4gdGhlIGRvY3VtZW50IGlzIGNvbnRhaW5lZCBpbiBhbiBpZnJhbWUsIHRoZW4gYW55IGlucHV0dGVkIHRleHQgd29uJ3QgYmUgdmlzaWJsZSBldmVuIHRob3VnaCB0aGUgdmFsdWUgYXR0cmlidXRlIGlzIHVwZGF0ZWQgYXMgdGhlIHVzZXIgdHlwZXMgKGlzc3VlICMzNykuXG5cdFx0XHRpZiAoKGV2ZW50LnRpbWVTdGFtcCAtIHRyYWNraW5nQ2xpY2tTdGFydCkgPiAxMDAgfHwgKGRldmljZUlzSU9TICYmIHdpbmRvdy50b3AgIT09IHdpbmRvdyAmJiB0YXJnZXRUYWdOYW1lID09PSAnaW5wdXQnKSkge1xuXHRcdFx0XHR0aGlzLnRhcmdldEVsZW1lbnQgPSBudWxsO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuZm9jdXModGFyZ2V0RWxlbWVudCk7XG5cdFx0XHR0aGlzLnNlbmRDbGljayh0YXJnZXRFbGVtZW50LCBldmVudCk7XG5cblx0XHRcdC8vIFNlbGVjdCBlbGVtZW50cyBuZWVkIHRoZSBldmVudCB0byBnbyB0aHJvdWdoIG9uIGlPUyA0LCBvdGhlcndpc2UgdGhlIHNlbGVjdG9yIG1lbnUgd29uJ3Qgb3Blbi5cblx0XHRcdC8vIEFsc28gdGhpcyBicmVha3Mgb3BlbmluZyBzZWxlY3RzIHdoZW4gVm9pY2VPdmVyIGlzIGFjdGl2ZSBvbiBpT1M2LCBpT1M3IChhbmQgcG9zc2libHkgb3RoZXJzKVxuXHRcdFx0aWYgKCFkZXZpY2VJc0lPUzQgfHwgdGFyZ2V0VGFnTmFtZSAhPT0gJ3NlbGVjdCcpIHtcblx0XHRcdFx0dGhpcy50YXJnZXRFbGVtZW50ID0gbnVsbDtcblx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdGlmIChkZXZpY2VJc0lPUyAmJiAhZGV2aWNlSXNJT1M0KSB7XG5cblx0XHRcdC8vIERvbid0IHNlbmQgYSBzeW50aGV0aWMgY2xpY2sgZXZlbnQgaWYgdGhlIHRhcmdldCBlbGVtZW50IGlzIGNvbnRhaW5lZCB3aXRoaW4gYSBwYXJlbnQgbGF5ZXIgdGhhdCB3YXMgc2Nyb2xsZWRcblx0XHRcdC8vIGFuZCB0aGlzIHRhcCBpcyBiZWluZyB1c2VkIHRvIHN0b3AgdGhlIHNjcm9sbGluZyAodXN1YWxseSBpbml0aWF0ZWQgYnkgYSBmbGluZyAtIGlzc3VlICM0MikuXG5cdFx0XHRzY3JvbGxQYXJlbnQgPSB0YXJnZXRFbGVtZW50LmZhc3RDbGlja1Njcm9sbFBhcmVudDtcblx0XHRcdGlmIChzY3JvbGxQYXJlbnQgJiYgc2Nyb2xsUGFyZW50LmZhc3RDbGlja0xhc3RTY3JvbGxUb3AgIT09IHNjcm9sbFBhcmVudC5zY3JvbGxUb3ApIHtcblx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gUHJldmVudCB0aGUgYWN0dWFsIGNsaWNrIGZyb20gZ29pbmcgdGhvdWdoIC0gdW5sZXNzIHRoZSB0YXJnZXQgbm9kZSBpcyBtYXJrZWQgYXMgcmVxdWlyaW5nXG5cdFx0Ly8gcmVhbCBjbGlja3Mgb3IgaWYgaXQgaXMgaW4gdGhlIHdoaXRlbGlzdCBpbiB3aGljaCBjYXNlIG9ubHkgbm9uLXByb2dyYW1tYXRpYyBjbGlja3MgYXJlIHBlcm1pdHRlZC5cblx0XHRpZiAoIXRoaXMubmVlZHNDbGljayh0YXJnZXRFbGVtZW50KSkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdHRoaXMuc2VuZENsaWNrKHRhcmdldEVsZW1lbnQsIGV2ZW50KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH07XG5cblxuXHQvKipcblx0ICogT24gdG91Y2ggY2FuY2VsLCBzdG9wIHRyYWNraW5nIHRoZSBjbGljay5cblx0ICpcblx0ICogQHJldHVybnMge3ZvaWR9XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm9uVG91Y2hDYW5jZWwgPSBmdW5jdGlvbigpIHtcblx0XHR0aGlzLnRyYWNraW5nQ2xpY2sgPSBmYWxzZTtcblx0XHR0aGlzLnRhcmdldEVsZW1lbnQgPSBudWxsO1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIERldGVybWluZSBtb3VzZSBldmVudHMgd2hpY2ggc2hvdWxkIGJlIHBlcm1pdHRlZC5cblx0ICpcblx0ICogQHBhcmFtIHtFdmVudH0gZXZlbnRcblx0ICogQHJldHVybnMge2Jvb2xlYW59XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm9uTW91c2UgPSBmdW5jdGlvbihldmVudCkge1xuXG5cdFx0Ly8gSWYgYSB0YXJnZXQgZWxlbWVudCB3YXMgbmV2ZXIgc2V0IChiZWNhdXNlIGEgdG91Y2ggZXZlbnQgd2FzIG5ldmVyIGZpcmVkKSBhbGxvdyB0aGUgZXZlbnRcblx0XHRpZiAoIXRoaXMudGFyZ2V0RWxlbWVudCkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKGV2ZW50LmZvcndhcmRlZFRvdWNoRXZlbnQpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdC8vIFByb2dyYW1tYXRpY2FsbHkgZ2VuZXJhdGVkIGV2ZW50cyB0YXJnZXRpbmcgYSBzcGVjaWZpYyBlbGVtZW50IHNob3VsZCBiZSBwZXJtaXR0ZWRcblx0XHRpZiAoIWV2ZW50LmNhbmNlbGFibGUpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdC8vIERlcml2ZSBhbmQgY2hlY2sgdGhlIHRhcmdldCBlbGVtZW50IHRvIHNlZSB3aGV0aGVyIHRoZSBtb3VzZSBldmVudCBuZWVkcyB0byBiZSBwZXJtaXR0ZWQ7XG5cdFx0Ly8gdW5sZXNzIGV4cGxpY2l0bHkgZW5hYmxlZCwgcHJldmVudCBub24tdG91Y2ggY2xpY2sgZXZlbnRzIGZyb20gdHJpZ2dlcmluZyBhY3Rpb25zLFxuXHRcdC8vIHRvIHByZXZlbnQgZ2hvc3QvZG91YmxlY2xpY2tzLlxuXHRcdGlmICghdGhpcy5uZWVkc0NsaWNrKHRoaXMudGFyZ2V0RWxlbWVudCkgfHwgdGhpcy5jYW5jZWxOZXh0Q2xpY2spIHtcblxuXHRcdFx0Ly8gUHJldmVudCBhbnkgdXNlci1hZGRlZCBsaXN0ZW5lcnMgZGVjbGFyZWQgb24gRmFzdENsaWNrIGVsZW1lbnQgZnJvbSBiZWluZyBmaXJlZC5cblx0XHRcdGlmIChldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24pIHtcblx0XHRcdFx0ZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdC8vIFBhcnQgb2YgdGhlIGhhY2sgZm9yIGJyb3dzZXJzIHRoYXQgZG9uJ3Qgc3VwcG9ydCBFdmVudCNzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24gKGUuZy4gQW5kcm9pZCAyKVxuXHRcdFx0XHRldmVudC5wcm9wYWdhdGlvblN0b3BwZWQgPSB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDYW5jZWwgdGhlIGV2ZW50XG5cdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHQvLyBJZiB0aGUgbW91c2UgZXZlbnQgaXMgcGVybWl0dGVkLCByZXR1cm4gdHJ1ZSBmb3IgdGhlIGFjdGlvbiB0byBnbyB0aHJvdWdoLlxuXHRcdHJldHVybiB0cnVlO1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIE9uIGFjdHVhbCBjbGlja3MsIGRldGVybWluZSB3aGV0aGVyIHRoaXMgaXMgYSB0b3VjaC1nZW5lcmF0ZWQgY2xpY2ssIGEgY2xpY2sgYWN0aW9uIG9jY3VycmluZ1xuXHQgKiBuYXR1cmFsbHkgYWZ0ZXIgYSBkZWxheSBhZnRlciBhIHRvdWNoICh3aGljaCBuZWVkcyB0byBiZSBjYW5jZWxsZWQgdG8gYXZvaWQgZHVwbGljYXRpb24pLCBvclxuXHQgKiBhbiBhY3R1YWwgY2xpY2sgd2hpY2ggc2hvdWxkIGJlIHBlcm1pdHRlZC5cblx0ICpcblx0ICogQHBhcmFtIHtFdmVudH0gZXZlbnRcblx0ICogQHJldHVybnMge2Jvb2xlYW59XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm9uQ2xpY2sgPSBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciBwZXJtaXR0ZWQ7XG5cblx0XHQvLyBJdCdzIHBvc3NpYmxlIGZvciBhbm90aGVyIEZhc3RDbGljay1saWtlIGxpYnJhcnkgZGVsaXZlcmVkIHdpdGggdGhpcmQtcGFydHkgY29kZSB0byBmaXJlIGEgY2xpY2sgZXZlbnQgYmVmb3JlIEZhc3RDbGljayBkb2VzIChpc3N1ZSAjNDQpLiBJbiB0aGF0IGNhc2UsIHNldCB0aGUgY2xpY2stdHJhY2tpbmcgZmxhZyBiYWNrIHRvIGZhbHNlIGFuZCByZXR1cm4gZWFybHkuIFRoaXMgd2lsbCBjYXVzZSBvblRvdWNoRW5kIHRvIHJldHVybiBlYXJseS5cblx0XHRpZiAodGhpcy50cmFja2luZ0NsaWNrKSB7XG5cdFx0XHR0aGlzLnRhcmdldEVsZW1lbnQgPSBudWxsO1xuXHRcdFx0dGhpcy50cmFja2luZ0NsaWNrID0gZmFsc2U7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHQvLyBWZXJ5IG9kZCBiZWhhdmlvdXIgb24gaU9TIChpc3N1ZSAjMTgpOiBpZiBhIHN1Ym1pdCBlbGVtZW50IGlzIHByZXNlbnQgaW5zaWRlIGEgZm9ybSBhbmQgdGhlIHVzZXIgaGl0cyBlbnRlciBpbiB0aGUgaU9TIHNpbXVsYXRvciBvciBjbGlja3MgdGhlIEdvIGJ1dHRvbiBvbiB0aGUgcG9wLXVwIE9TIGtleWJvYXJkIHRoZSBhIGtpbmQgb2YgJ2Zha2UnIGNsaWNrIGV2ZW50IHdpbGwgYmUgdHJpZ2dlcmVkIHdpdGggdGhlIHN1Ym1pdC10eXBlIGlucHV0IGVsZW1lbnQgYXMgdGhlIHRhcmdldC5cblx0XHRpZiAoZXZlbnQudGFyZ2V0LnR5cGUgPT09ICdzdWJtaXQnICYmIGV2ZW50LmRldGFpbCA9PT0gMCkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cGVybWl0dGVkID0gdGhpcy5vbk1vdXNlKGV2ZW50KTtcblxuXHRcdC8vIE9ubHkgdW5zZXQgdGFyZ2V0RWxlbWVudCBpZiB0aGUgY2xpY2sgaXMgbm90IHBlcm1pdHRlZC4gVGhpcyB3aWxsIGVuc3VyZSB0aGF0IHRoZSBjaGVjayBmb3IgIXRhcmdldEVsZW1lbnQgaW4gb25Nb3VzZSBmYWlscyBhbmQgdGhlIGJyb3dzZXIncyBjbGljayBkb2Vzbid0IGdvIHRocm91Z2guXG5cdFx0aWYgKCFwZXJtaXR0ZWQpIHtcblx0XHRcdHRoaXMudGFyZ2V0RWxlbWVudCA9IG51bGw7XG5cdFx0fVxuXG5cdFx0Ly8gSWYgY2xpY2tzIGFyZSBwZXJtaXR0ZWQsIHJldHVybiB0cnVlIGZvciB0aGUgYWN0aW9uIHRvIGdvIHRocm91Z2guXG5cdFx0cmV0dXJuIHBlcm1pdHRlZDtcblx0fTtcblxuXG5cdC8qKlxuXHQgKiBSZW1vdmUgYWxsIEZhc3RDbGljaydzIGV2ZW50IGxpc3RlbmVycy5cblx0ICpcblx0ICogQHJldHVybnMge3ZvaWR9XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbigpIHtcblx0XHR2YXIgbGF5ZXIgPSB0aGlzLmxheWVyO1xuXG5cdFx0aWYgKGRldmljZUlzQW5kcm9pZCkge1xuXHRcdFx0bGF5ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2VvdmVyJywgdGhpcy5vbk1vdXNlLCB0cnVlKTtcblx0XHRcdGxheWVyLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMub25Nb3VzZSwgdHJ1ZSk7XG5cdFx0XHRsYXllci5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5vbk1vdXNlLCB0cnVlKTtcblx0XHR9XG5cblx0XHRsYXllci5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMub25DbGljaywgdHJ1ZSk7XG5cdFx0bGF5ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMub25Ub3VjaFN0YXJ0LCBmYWxzZSk7XG5cdFx0bGF5ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5vblRvdWNoTW92ZSwgZmFsc2UpO1xuXHRcdGxheWVyLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdGhpcy5vblRvdWNoRW5kLCBmYWxzZSk7XG5cdFx0bGF5ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hjYW5jZWwnLCB0aGlzLm9uVG91Y2hDYW5jZWwsIGZhbHNlKTtcblx0fTtcblxuXG5cdC8qKlxuXHQgKiBDaGVjayB3aGV0aGVyIEZhc3RDbGljayBpcyBuZWVkZWQuXG5cdCAqXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gbGF5ZXIgVGhlIGxheWVyIHRvIGxpc3RlbiBvblxuXHQgKi9cblx0RmFzdENsaWNrLm5vdE5lZWRlZCA9IGZ1bmN0aW9uKGxheWVyKSB7XG5cdFx0dmFyIG1ldGFWaWV3cG9ydDtcblx0XHR2YXIgY2hyb21lVmVyc2lvbjtcblx0XHR2YXIgYmxhY2tiZXJyeVZlcnNpb247XG5cdFx0dmFyIGZpcmVmb3hWZXJzaW9uO1xuXG5cdFx0Ly8gRGV2aWNlcyB0aGF0IGRvbid0IHN1cHBvcnQgdG91Y2ggZG9uJ3QgbmVlZCBGYXN0Q2xpY2tcblx0XHRpZiAodHlwZW9mIHdpbmRvdy5vbnRvdWNoc3RhcnQgPT09ICd1bmRlZmluZWQnKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHQvLyBDaHJvbWUgdmVyc2lvbiAtIHplcm8gZm9yIG90aGVyIGJyb3dzZXJzXG5cdFx0Y2hyb21lVmVyc2lvbiA9ICsoL0Nocm9tZVxcLyhbMC05XSspLy5leGVjKG5hdmlnYXRvci51c2VyQWdlbnQpIHx8IFssMF0pWzFdO1xuXG5cdFx0aWYgKGNocm9tZVZlcnNpb24pIHtcblxuXHRcdFx0aWYgKGRldmljZUlzQW5kcm9pZCkge1xuXHRcdFx0XHRtZXRhVmlld3BvcnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdtZXRhW25hbWU9dmlld3BvcnRdJyk7XG5cblx0XHRcdFx0aWYgKG1ldGFWaWV3cG9ydCkge1xuXHRcdFx0XHRcdC8vIENocm9tZSBvbiBBbmRyb2lkIHdpdGggdXNlci1zY2FsYWJsZT1cIm5vXCIgZG9lc24ndCBuZWVkIEZhc3RDbGljayAoaXNzdWUgIzg5KVxuXHRcdFx0XHRcdGlmIChtZXRhVmlld3BvcnQuY29udGVudC5pbmRleE9mKCd1c2VyLXNjYWxhYmxlPW5vJykgIT09IC0xKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0Ly8gQ2hyb21lIDMyIGFuZCBhYm92ZSB3aXRoIHdpZHRoPWRldmljZS13aWR0aCBvciBsZXNzIGRvbid0IG5lZWQgRmFzdENsaWNrXG5cdFx0XHRcdFx0aWYgKGNocm9tZVZlcnNpb24gPiAzMSAmJiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsV2lkdGggPD0gd2luZG93Lm91dGVyV2lkdGgpIHtcblx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHQvLyBDaHJvbWUgZGVza3RvcCBkb2Vzbid0IG5lZWQgRmFzdENsaWNrIChpc3N1ZSAjMTUpXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoZGV2aWNlSXNCbGFja0JlcnJ5MTApIHtcblx0XHRcdGJsYWNrYmVycnlWZXJzaW9uID0gbmF2aWdhdG9yLnVzZXJBZ2VudC5tYXRjaCgvVmVyc2lvblxcLyhbMC05XSopXFwuKFswLTldKikvKTtcblxuXHRcdFx0Ly8gQmxhY2tCZXJyeSAxMC4zKyBkb2VzIG5vdCByZXF1aXJlIEZhc3RjbGljayBsaWJyYXJ5LlxuXHRcdFx0Ly8gaHR0cHM6Ly9naXRodWIuY29tL2Z0bGFicy9mYXN0Y2xpY2svaXNzdWVzLzI1MVxuXHRcdFx0aWYgKGJsYWNrYmVycnlWZXJzaW9uWzFdID49IDEwICYmIGJsYWNrYmVycnlWZXJzaW9uWzJdID49IDMpIHtcblx0XHRcdFx0bWV0YVZpZXdwb3J0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignbWV0YVtuYW1lPXZpZXdwb3J0XScpO1xuXG5cdFx0XHRcdGlmIChtZXRhVmlld3BvcnQpIHtcblx0XHRcdFx0XHQvLyB1c2VyLXNjYWxhYmxlPW5vIGVsaW1pbmF0ZXMgY2xpY2sgZGVsYXkuXG5cdFx0XHRcdFx0aWYgKG1ldGFWaWV3cG9ydC5jb250ZW50LmluZGV4T2YoJ3VzZXItc2NhbGFibGU9bm8nKSAhPT0gLTEpIHtcblx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHQvLyB3aWR0aD1kZXZpY2Utd2lkdGggKG9yIGxlc3MgdGhhbiBkZXZpY2Utd2lkdGgpIGVsaW1pbmF0ZXMgY2xpY2sgZGVsYXkuXG5cdFx0XHRcdFx0aWYgKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxXaWR0aCA8PSB3aW5kb3cub3V0ZXJXaWR0aCkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gSUUxMCB3aXRoIC1tcy10b3VjaC1hY3Rpb246IG5vbmUgb3IgbWFuaXB1bGF0aW9uLCB3aGljaCBkaXNhYmxlcyBkb3VibGUtdGFwLXRvLXpvb20gKGlzc3VlICM5Nylcblx0XHRpZiAobGF5ZXIuc3R5bGUubXNUb3VjaEFjdGlvbiA9PT0gJ25vbmUnIHx8IGxheWVyLnN0eWxlLnRvdWNoQWN0aW9uID09PSAnbWFuaXB1bGF0aW9uJykge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0Ly8gRmlyZWZveCB2ZXJzaW9uIC0gemVybyBmb3Igb3RoZXIgYnJvd3NlcnNcblx0XHRmaXJlZm94VmVyc2lvbiA9ICsoL0ZpcmVmb3hcXC8oWzAtOV0rKS8uZXhlYyhuYXZpZ2F0b3IudXNlckFnZW50KSB8fCBbLDBdKVsxXTtcblxuXHRcdGlmIChmaXJlZm94VmVyc2lvbiA+PSAyNykge1xuXHRcdFx0Ly8gRmlyZWZveCAyNysgZG9lcyBub3QgaGF2ZSB0YXAgZGVsYXkgaWYgdGhlIGNvbnRlbnQgaXMgbm90IHpvb21hYmxlIC0gaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9OTIyODk2XG5cblx0XHRcdG1ldGFWaWV3cG9ydCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ21ldGFbbmFtZT12aWV3cG9ydF0nKTtcblx0XHRcdGlmIChtZXRhVmlld3BvcnQgJiYgKG1ldGFWaWV3cG9ydC5jb250ZW50LmluZGV4T2YoJ3VzZXItc2NhbGFibGU9bm8nKSAhPT0gLTEgfHwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFdpZHRoIDw9IHdpbmRvdy5vdXRlcldpZHRoKSkge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBJRTExOiBwcmVmaXhlZCAtbXMtdG91Y2gtYWN0aW9uIGlzIG5vIGxvbmdlciBzdXBwb3J0ZWQgYW5kIGl0J3MgcmVjb21lbmRlZCB0byB1c2Ugbm9uLXByZWZpeGVkIHZlcnNpb25cblx0XHQvLyBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvd2luZG93cy9hcHBzL0hoNzY3MzEzLmFzcHhcblx0XHRpZiAobGF5ZXIuc3R5bGUudG91Y2hBY3Rpb24gPT09ICdub25lJyB8fCBsYXllci5zdHlsZS50b3VjaEFjdGlvbiA9PT0gJ21hbmlwdWxhdGlvbicpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdHJldHVybiBmYWxzZTtcblx0fTtcblxuXG5cdC8qKlxuXHQgKiBGYWN0b3J5IG1ldGhvZCBmb3IgY3JlYXRpbmcgYSBGYXN0Q2xpY2sgb2JqZWN0XG5cdCAqXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gbGF5ZXIgVGhlIGxheWVyIHRvIGxpc3RlbiBvblxuXHQgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIFRoZSBvcHRpb25zIHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0c1xuXHQgKi9cblx0RmFzdENsaWNrLmF0dGFjaCA9IGZ1bmN0aW9uKGxheWVyLCBvcHRpb25zKSB7XG5cdFx0cmV0dXJuIG5ldyBGYXN0Q2xpY2sobGF5ZXIsIG9wdGlvbnMpO1xuXHR9O1xuXG5cblx0aWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09ICdvYmplY3QnICYmIGRlZmluZS5hbWQpIHtcblxuXHRcdC8vIEFNRC4gUmVnaXN0ZXIgYXMgYW4gYW5vbnltb3VzIG1vZHVsZS5cblx0XHRkZWZpbmUoZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gRmFzdENsaWNrO1xuXHRcdH0pO1xuXHR9IGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnICYmIG1vZHVsZS5leHBvcnRzKSB7XG5cdFx0bW9kdWxlLmV4cG9ydHMgPSBGYXN0Q2xpY2suYXR0YWNoO1xuXHRcdG1vZHVsZS5leHBvcnRzLkZhc3RDbGljayA9IEZhc3RDbGljaztcblx0fSBlbHNlIHtcblx0XHR3aW5kb3cuRmFzdENsaWNrID0gRmFzdENsaWNrO1xuXHR9XG59KCkpO1xuIiwiLy8gRm9yIEBvbnNlbnVpL2N1c3RvbS1lbGVtZW50c1xuaWYgKHdpbmRvdy5jdXN0b21FbGVtZW50cykgeyAvLyBldmVuIGlmIG5hdGl2ZSBDRTEgaW1wbCBleGlzdHMsIHVzZSBwb2x5ZmlsbFxuICAgIHdpbmRvdy5jdXN0b21FbGVtZW50cy5mb3JjZVBvbHlmaWxsID0gdHJ1ZTtcbn1cbiIsIi8vIGh0dHBzOi8vZ2l0aHViLmNvbS96bG9pcm9jay9jb3JlLWpzL2lzc3Vlcy84NiNpc3N1ZWNvbW1lbnQtMTE1NzU5MDI4XG52YXIgZ2xvYmFsID0gbW9kdWxlLmV4cG9ydHMgPSB0eXBlb2Ygd2luZG93ICE9ICd1bmRlZmluZWQnICYmIHdpbmRvdy5NYXRoID09IE1hdGhcbiAgPyB3aW5kb3cgOiB0eXBlb2Ygc2VsZiAhPSAndW5kZWZpbmVkJyAmJiBzZWxmLk1hdGggPT0gTWF0aCA/IHNlbGZcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLW5ldy1mdW5jXG4gIDogRnVuY3Rpb24oJ3JldHVybiB0aGlzJykoKTtcbmlmICh0eXBlb2YgX19nID09ICdudW1iZXInKSBfX2cgPSBnbG9iYWw7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcbiIsInZhciBjb3JlID0gbW9kdWxlLmV4cG9ydHMgPSB7IHZlcnNpb246ICcyLjUuMScgfTtcbmlmICh0eXBlb2YgX19lID09ICdudW1iZXInKSBfX2UgPSBjb3JlOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gdHlwZW9mIGl0ID09PSAnb2JqZWN0JyA/IGl0ICE9PSBudWxsIDogdHlwZW9mIGl0ID09PSAnZnVuY3Rpb24nO1xufTtcbiIsInZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgaWYgKCFpc09iamVjdChpdCkpIHRocm93IFR5cGVFcnJvcihpdCArICcgaXMgbm90IGFuIG9iamVjdCEnKTtcbiAgcmV0dXJuIGl0O1xufTtcbiIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGV4ZWMpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gISFleGVjKCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxufTtcbiIsIi8vIFRoYW5rJ3MgSUU4IGZvciBoaXMgZnVubnkgZGVmaW5lUHJvcGVydHlcbm1vZHVsZS5leHBvcnRzID0gIXJlcXVpcmUoJy4vX2ZhaWxzJykoZnVuY3Rpb24gKCkge1xuICByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCAnYScsIHsgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiA3OyB9IH0pLmEgIT0gNztcbn0pO1xuIiwidmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0Jyk7XG52YXIgZG9jdW1lbnQgPSByZXF1aXJlKCcuL19nbG9iYWwnKS5kb2N1bWVudDtcbi8vIHR5cGVvZiBkb2N1bWVudC5jcmVhdGVFbGVtZW50IGlzICdvYmplY3QnIGluIG9sZCBJRVxudmFyIGlzID0gaXNPYmplY3QoZG9jdW1lbnQpICYmIGlzT2JqZWN0KGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIGlzID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChpdCkgOiB7fTtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9ICFyZXF1aXJlKCcuL19kZXNjcmlwdG9ycycpICYmICFyZXF1aXJlKCcuL19mYWlscycpKGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShyZXF1aXJlKCcuL19kb20tY3JlYXRlJykoJ2RpdicpLCAnYScsIHsgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiA3OyB9IH0pLmEgIT0gNztcbn0pO1xuIiwiLy8gNy4xLjEgVG9QcmltaXRpdmUoaW5wdXQgWywgUHJlZmVycmVkVHlwZV0pXG52YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuL19pcy1vYmplY3QnKTtcbi8vIGluc3RlYWQgb2YgdGhlIEVTNiBzcGVjIHZlcnNpb24sIHdlIGRpZG4ndCBpbXBsZW1lbnQgQEB0b1ByaW1pdGl2ZSBjYXNlXG4vLyBhbmQgdGhlIHNlY29uZCBhcmd1bWVudCAtIGZsYWcgLSBwcmVmZXJyZWQgdHlwZSBpcyBhIHN0cmluZ1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQsIFMpIHtcbiAgaWYgKCFpc09iamVjdChpdCkpIHJldHVybiBpdDtcbiAgdmFyIGZuLCB2YWw7XG4gIGlmIChTICYmIHR5cGVvZiAoZm4gPSBpdC50b1N0cmluZykgPT0gJ2Z1bmN0aW9uJyAmJiAhaXNPYmplY3QodmFsID0gZm4uY2FsbChpdCkpKSByZXR1cm4gdmFsO1xuICBpZiAodHlwZW9mIChmbiA9IGl0LnZhbHVlT2YpID09ICdmdW5jdGlvbicgJiYgIWlzT2JqZWN0KHZhbCA9IGZuLmNhbGwoaXQpKSkgcmV0dXJuIHZhbDtcbiAgaWYgKCFTICYmIHR5cGVvZiAoZm4gPSBpdC50b1N0cmluZykgPT0gJ2Z1bmN0aW9uJyAmJiAhaXNPYmplY3QodmFsID0gZm4uY2FsbChpdCkpKSByZXR1cm4gdmFsO1xuICB0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBjb252ZXJ0IG9iamVjdCB0byBwcmltaXRpdmUgdmFsdWVcIik7XG59O1xuIiwidmFyIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0Jyk7XG52YXIgSUU4X0RPTV9ERUZJTkUgPSByZXF1aXJlKCcuL19pZTgtZG9tLWRlZmluZScpO1xudmFyIHRvUHJpbWl0aXZlID0gcmVxdWlyZSgnLi9fdG8tcHJpbWl0aXZlJyk7XG52YXIgZFAgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7XG5cbmV4cG9ydHMuZiA9IHJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJykgPyBPYmplY3QuZGVmaW5lUHJvcGVydHkgOiBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0eShPLCBQLCBBdHRyaWJ1dGVzKSB7XG4gIGFuT2JqZWN0KE8pO1xuICBQID0gdG9QcmltaXRpdmUoUCwgdHJ1ZSk7XG4gIGFuT2JqZWN0KEF0dHJpYnV0ZXMpO1xuICBpZiAoSUU4X0RPTV9ERUZJTkUpIHRyeSB7XG4gICAgcmV0dXJuIGRQKE8sIFAsIEF0dHJpYnV0ZXMpO1xuICB9IGNhdGNoIChlKSB7IC8qIGVtcHR5ICovIH1cbiAgaWYgKCdnZXQnIGluIEF0dHJpYnV0ZXMgfHwgJ3NldCcgaW4gQXR0cmlidXRlcykgdGhyb3cgVHlwZUVycm9yKCdBY2Nlc3NvcnMgbm90IHN1cHBvcnRlZCEnKTtcbiAgaWYgKCd2YWx1ZScgaW4gQXR0cmlidXRlcykgT1tQXSA9IEF0dHJpYnV0ZXMudmFsdWU7XG4gIHJldHVybiBPO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGJpdG1hcCwgdmFsdWUpIHtcbiAgcmV0dXJuIHtcbiAgICBlbnVtZXJhYmxlOiAhKGJpdG1hcCAmIDEpLFxuICAgIGNvbmZpZ3VyYWJsZTogIShiaXRtYXAgJiAyKSxcbiAgICB3cml0YWJsZTogIShiaXRtYXAgJiA0KSxcbiAgICB2YWx1ZTogdmFsdWVcbiAgfTtcbn07XG4iLCJ2YXIgZFAgPSByZXF1aXJlKCcuL19vYmplY3QtZHAnKTtcbnZhciBjcmVhdGVEZXNjID0gcmVxdWlyZSgnLi9fcHJvcGVydHktZGVzYycpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL19kZXNjcmlwdG9ycycpID8gZnVuY3Rpb24gKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICByZXR1cm4gZFAuZihvYmplY3QsIGtleSwgY3JlYXRlRGVzYygxLCB2YWx1ZSkpO1xufSA6IGZ1bmN0aW9uIChvYmplY3QsIGtleSwgdmFsdWUpIHtcbiAgb2JqZWN0W2tleV0gPSB2YWx1ZTtcbiAgcmV0dXJuIG9iamVjdDtcbn07XG4iLCJ2YXIgaGFzT3duUHJvcGVydHkgPSB7fS5oYXNPd25Qcm9wZXJ0eTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0LCBrZXkpIHtcbiAgcmV0dXJuIGhhc093blByb3BlcnR5LmNhbGwoaXQsIGtleSk7XG59O1xuIiwidmFyIGlkID0gMDtcbnZhciBweCA9IE1hdGgucmFuZG9tKCk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgcmV0dXJuICdTeW1ib2woJy5jb25jYXQoa2V5ID09PSB1bmRlZmluZWQgPyAnJyA6IGtleSwgJylfJywgKCsraWQgKyBweCkudG9TdHJpbmcoMzYpKTtcbn07XG4iLCJ2YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi9fZ2xvYmFsJyk7XG52YXIgaGlkZSA9IHJlcXVpcmUoJy4vX2hpZGUnKTtcbnZhciBoYXMgPSByZXF1aXJlKCcuL19oYXMnKTtcbnZhciBTUkMgPSByZXF1aXJlKCcuL191aWQnKSgnc3JjJyk7XG52YXIgVE9fU1RSSU5HID0gJ3RvU3RyaW5nJztcbnZhciAkdG9TdHJpbmcgPSBGdW5jdGlvbltUT19TVFJJTkddO1xudmFyIFRQTCA9ICgnJyArICR0b1N0cmluZykuc3BsaXQoVE9fU1RSSU5HKTtcblxucmVxdWlyZSgnLi9fY29yZScpLmluc3BlY3RTb3VyY2UgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuICR0b1N0cmluZy5jYWxsKGl0KTtcbn07XG5cbihtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChPLCBrZXksIHZhbCwgc2FmZSkge1xuICB2YXIgaXNGdW5jdGlvbiA9IHR5cGVvZiB2YWwgPT0gJ2Z1bmN0aW9uJztcbiAgaWYgKGlzRnVuY3Rpb24pIGhhcyh2YWwsICduYW1lJykgfHwgaGlkZSh2YWwsICduYW1lJywga2V5KTtcbiAgaWYgKE9ba2V5XSA9PT0gdmFsKSByZXR1cm47XG4gIGlmIChpc0Z1bmN0aW9uKSBoYXModmFsLCBTUkMpIHx8IGhpZGUodmFsLCBTUkMsIE9ba2V5XSA/ICcnICsgT1trZXldIDogVFBMLmpvaW4oU3RyaW5nKGtleSkpKTtcbiAgaWYgKE8gPT09IGdsb2JhbCkge1xuICAgIE9ba2V5XSA9IHZhbDtcbiAgfSBlbHNlIGlmICghc2FmZSkge1xuICAgIGRlbGV0ZSBPW2tleV07XG4gICAgaGlkZShPLCBrZXksIHZhbCk7XG4gIH0gZWxzZSBpZiAoT1trZXldKSB7XG4gICAgT1trZXldID0gdmFsO1xuICB9IGVsc2Uge1xuICAgIGhpZGUoTywga2V5LCB2YWwpO1xuICB9XG4vLyBhZGQgZmFrZSBGdW5jdGlvbiN0b1N0cmluZyBmb3IgY29ycmVjdCB3b3JrIHdyYXBwZWQgbWV0aG9kcyAvIGNvbnN0cnVjdG9ycyB3aXRoIG1ldGhvZHMgbGlrZSBMb0Rhc2ggaXNOYXRpdmVcbn0pKEZ1bmN0aW9uLnByb3RvdHlwZSwgVE9fU1RSSU5HLCBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgcmV0dXJuIHR5cGVvZiB0aGlzID09ICdmdW5jdGlvbicgJiYgdGhpc1tTUkNdIHx8ICR0b1N0cmluZy5jYWxsKHRoaXMpO1xufSk7XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICBpZiAodHlwZW9mIGl0ICE9ICdmdW5jdGlvbicpIHRocm93IFR5cGVFcnJvcihpdCArICcgaXMgbm90IGEgZnVuY3Rpb24hJyk7XG4gIHJldHVybiBpdDtcbn07XG4iLCIvLyBvcHRpb25hbCAvIHNpbXBsZSBjb250ZXh0IGJpbmRpbmdcbnZhciBhRnVuY3Rpb24gPSByZXF1aXJlKCcuL19hLWZ1bmN0aW9uJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChmbiwgdGhhdCwgbGVuZ3RoKSB7XG4gIGFGdW5jdGlvbihmbik7XG4gIGlmICh0aGF0ID09PSB1bmRlZmluZWQpIHJldHVybiBmbjtcbiAgc3dpdGNoIChsZW5ndGgpIHtcbiAgICBjYXNlIDE6IHJldHVybiBmdW5jdGlvbiAoYSkge1xuICAgICAgcmV0dXJuIGZuLmNhbGwodGhhdCwgYSk7XG4gICAgfTtcbiAgICBjYXNlIDI6IHJldHVybiBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgcmV0dXJuIGZuLmNhbGwodGhhdCwgYSwgYik7XG4gICAgfTtcbiAgICBjYXNlIDM6IHJldHVybiBmdW5jdGlvbiAoYSwgYiwgYykge1xuICAgICAgcmV0dXJuIGZuLmNhbGwodGhhdCwgYSwgYiwgYyk7XG4gICAgfTtcbiAgfVxuICByZXR1cm4gZnVuY3Rpb24gKC8qIC4uLmFyZ3MgKi8pIHtcbiAgICByZXR1cm4gZm4uYXBwbHkodGhhdCwgYXJndW1lbnRzKTtcbiAgfTtcbn07XG4iLCJ2YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi9fZ2xvYmFsJyk7XG52YXIgY29yZSA9IHJlcXVpcmUoJy4vX2NvcmUnKTtcbnZhciBoaWRlID0gcmVxdWlyZSgnLi9faGlkZScpO1xudmFyIHJlZGVmaW5lID0gcmVxdWlyZSgnLi9fcmVkZWZpbmUnKTtcbnZhciBjdHggPSByZXF1aXJlKCcuL19jdHgnKTtcbnZhciBQUk9UT1RZUEUgPSAncHJvdG90eXBlJztcblxudmFyICRleHBvcnQgPSBmdW5jdGlvbiAodHlwZSwgbmFtZSwgc291cmNlKSB7XG4gIHZhciBJU19GT1JDRUQgPSB0eXBlICYgJGV4cG9ydC5GO1xuICB2YXIgSVNfR0xPQkFMID0gdHlwZSAmICRleHBvcnQuRztcbiAgdmFyIElTX1NUQVRJQyA9IHR5cGUgJiAkZXhwb3J0LlM7XG4gIHZhciBJU19QUk9UTyA9IHR5cGUgJiAkZXhwb3J0LlA7XG4gIHZhciBJU19CSU5EID0gdHlwZSAmICRleHBvcnQuQjtcbiAgdmFyIHRhcmdldCA9IElTX0dMT0JBTCA/IGdsb2JhbCA6IElTX1NUQVRJQyA/IGdsb2JhbFtuYW1lXSB8fCAoZ2xvYmFsW25hbWVdID0ge30pIDogKGdsb2JhbFtuYW1lXSB8fCB7fSlbUFJPVE9UWVBFXTtcbiAgdmFyIGV4cG9ydHMgPSBJU19HTE9CQUwgPyBjb3JlIDogY29yZVtuYW1lXSB8fCAoY29yZVtuYW1lXSA9IHt9KTtcbiAgdmFyIGV4cFByb3RvID0gZXhwb3J0c1tQUk9UT1RZUEVdIHx8IChleHBvcnRzW1BST1RPVFlQRV0gPSB7fSk7XG4gIHZhciBrZXksIG93biwgb3V0LCBleHA7XG4gIGlmIChJU19HTE9CQUwpIHNvdXJjZSA9IG5hbWU7XG4gIGZvciAoa2V5IGluIHNvdXJjZSkge1xuICAgIC8vIGNvbnRhaW5zIGluIG5hdGl2ZVxuICAgIG93biA9ICFJU19GT1JDRUQgJiYgdGFyZ2V0ICYmIHRhcmdldFtrZXldICE9PSB1bmRlZmluZWQ7XG4gICAgLy8gZXhwb3J0IG5hdGl2ZSBvciBwYXNzZWRcbiAgICBvdXQgPSAob3duID8gdGFyZ2V0IDogc291cmNlKVtrZXldO1xuICAgIC8vIGJpbmQgdGltZXJzIHRvIGdsb2JhbCBmb3IgY2FsbCBmcm9tIGV4cG9ydCBjb250ZXh0XG4gICAgZXhwID0gSVNfQklORCAmJiBvd24gPyBjdHgob3V0LCBnbG9iYWwpIDogSVNfUFJPVE8gJiYgdHlwZW9mIG91dCA9PSAnZnVuY3Rpb24nID8gY3R4KEZ1bmN0aW9uLmNhbGwsIG91dCkgOiBvdXQ7XG4gICAgLy8gZXh0ZW5kIGdsb2JhbFxuICAgIGlmICh0YXJnZXQpIHJlZGVmaW5lKHRhcmdldCwga2V5LCBvdXQsIHR5cGUgJiAkZXhwb3J0LlUpO1xuICAgIC8vIGV4cG9ydFxuICAgIGlmIChleHBvcnRzW2tleV0gIT0gb3V0KSBoaWRlKGV4cG9ydHMsIGtleSwgZXhwKTtcbiAgICBpZiAoSVNfUFJPVE8gJiYgZXhwUHJvdG9ba2V5XSAhPSBvdXQpIGV4cFByb3RvW2tleV0gPSBvdXQ7XG4gIH1cbn07XG5nbG9iYWwuY29yZSA9IGNvcmU7XG4vLyB0eXBlIGJpdG1hcFxuJGV4cG9ydC5GID0gMTsgICAvLyBmb3JjZWRcbiRleHBvcnQuRyA9IDI7ICAgLy8gZ2xvYmFsXG4kZXhwb3J0LlMgPSA0OyAgIC8vIHN0YXRpY1xuJGV4cG9ydC5QID0gODsgICAvLyBwcm90b1xuJGV4cG9ydC5CID0gMTY7ICAvLyBiaW5kXG4kZXhwb3J0LlcgPSAzMjsgIC8vIHdyYXBcbiRleHBvcnQuVSA9IDY0OyAgLy8gc2FmZVxuJGV4cG9ydC5SID0gMTI4OyAvLyByZWFsIHByb3RvIG1ldGhvZCBmb3IgYGxpYnJhcnlgXG5tb2R1bGUuZXhwb3J0cyA9ICRleHBvcnQ7XG4iLCJleHBvcnRzLmYgPSB7fS5wcm9wZXJ0eUlzRW51bWVyYWJsZTtcbiIsInZhciB0b1N0cmluZyA9IHt9LnRvU3RyaW5nO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gdG9TdHJpbmcuY2FsbChpdCkuc2xpY2UoOCwgLTEpO1xufTtcbiIsIi8vIGZhbGxiYWNrIGZvciBub24tYXJyYXktbGlrZSBFUzMgYW5kIG5vbi1lbnVtZXJhYmxlIG9sZCBWOCBzdHJpbmdzXG52YXIgY29mID0gcmVxdWlyZSgnLi9fY29mJyk7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcHJvdG90eXBlLWJ1aWx0aW5zXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdCgneicpLnByb3BlcnR5SXNFbnVtZXJhYmxlKDApID8gT2JqZWN0IDogZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiBjb2YoaXQpID09ICdTdHJpbmcnID8gaXQuc3BsaXQoJycpIDogT2JqZWN0KGl0KTtcbn07XG4iLCIvLyA3LjIuMSBSZXF1aXJlT2JqZWN0Q29lcmNpYmxlKGFyZ3VtZW50KVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgaWYgKGl0ID09IHVuZGVmaW5lZCkgdGhyb3cgVHlwZUVycm9yKFwiQ2FuJ3QgY2FsbCBtZXRob2Qgb24gIFwiICsgaXQpO1xuICByZXR1cm4gaXQ7XG59O1xuIiwiLy8gdG8gaW5kZXhlZCBvYmplY3QsIHRvT2JqZWN0IHdpdGggZmFsbGJhY2sgZm9yIG5vbi1hcnJheS1saWtlIEVTMyBzdHJpbmdzXG52YXIgSU9iamVjdCA9IHJlcXVpcmUoJy4vX2lvYmplY3QnKTtcbnZhciBkZWZpbmVkID0gcmVxdWlyZSgnLi9fZGVmaW5lZCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIElPYmplY3QoZGVmaW5lZChpdCkpO1xufTtcbiIsInZhciBwSUUgPSByZXF1aXJlKCcuL19vYmplY3QtcGllJyk7XG52YXIgY3JlYXRlRGVzYyA9IHJlcXVpcmUoJy4vX3Byb3BlcnR5LWRlc2MnKTtcbnZhciB0b0lPYmplY3QgPSByZXF1aXJlKCcuL190by1pb2JqZWN0Jyk7XG52YXIgdG9QcmltaXRpdmUgPSByZXF1aXJlKCcuL190by1wcmltaXRpdmUnKTtcbnZhciBoYXMgPSByZXF1aXJlKCcuL19oYXMnKTtcbnZhciBJRThfRE9NX0RFRklORSA9IHJlcXVpcmUoJy4vX2llOC1kb20tZGVmaW5lJyk7XG52YXIgZ09QRCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7XG5cbmV4cG9ydHMuZiA9IHJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJykgPyBnT1BEIDogZnVuY3Rpb24gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKE8sIFApIHtcbiAgTyA9IHRvSU9iamVjdChPKTtcbiAgUCA9IHRvUHJpbWl0aXZlKFAsIHRydWUpO1xuICBpZiAoSUU4X0RPTV9ERUZJTkUpIHRyeSB7XG4gICAgcmV0dXJuIGdPUEQoTywgUCk7XG4gIH0gY2F0Y2ggKGUpIHsgLyogZW1wdHkgKi8gfVxuICBpZiAoaGFzKE8sIFApKSByZXR1cm4gY3JlYXRlRGVzYyghcElFLmYuY2FsbChPLCBQKSwgT1tQXSk7XG59O1xuIiwiLy8gV29ya3Mgd2l0aCBfX3Byb3RvX18gb25seS4gT2xkIHY4IGNhbid0IHdvcmsgd2l0aCBudWxsIHByb3RvIG9iamVjdHMuXG4vKiBlc2xpbnQtZGlzYWJsZSBuby1wcm90byAqL1xudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0Jyk7XG52YXIgYW5PYmplY3QgPSByZXF1aXJlKCcuL19hbi1vYmplY3QnKTtcbnZhciBjaGVjayA9IGZ1bmN0aW9uIChPLCBwcm90bykge1xuICBhbk9iamVjdChPKTtcbiAgaWYgKCFpc09iamVjdChwcm90bykgJiYgcHJvdG8gIT09IG51bGwpIHRocm93IFR5cGVFcnJvcihwcm90byArIFwiOiBjYW4ndCBzZXQgYXMgcHJvdG90eXBlIVwiKTtcbn07XG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgc2V0OiBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwgKCdfX3Byb3RvX18nIGluIHt9ID8gLy8gZXNsaW50LWRpc2FibGUtbGluZVxuICAgIGZ1bmN0aW9uICh0ZXN0LCBidWdneSwgc2V0KSB7XG4gICAgICB0cnkge1xuICAgICAgICBzZXQgPSByZXF1aXJlKCcuL19jdHgnKShGdW5jdGlvbi5jYWxsLCByZXF1aXJlKCcuL19vYmplY3QtZ29wZCcpLmYoT2JqZWN0LnByb3RvdHlwZSwgJ19fcHJvdG9fXycpLnNldCwgMik7XG4gICAgICAgIHNldCh0ZXN0LCBbXSk7XG4gICAgICAgIGJ1Z2d5ID0gISh0ZXN0IGluc3RhbmNlb2YgQXJyYXkpO1xuICAgICAgfSBjYXRjaCAoZSkgeyBidWdneSA9IHRydWU7IH1cbiAgICAgIHJldHVybiBmdW5jdGlvbiBzZXRQcm90b3R5cGVPZihPLCBwcm90bykge1xuICAgICAgICBjaGVjayhPLCBwcm90byk7XG4gICAgICAgIGlmIChidWdneSkgTy5fX3Byb3RvX18gPSBwcm90bztcbiAgICAgICAgZWxzZSBzZXQoTywgcHJvdG8pO1xuICAgICAgICByZXR1cm4gTztcbiAgICAgIH07XG4gICAgfSh7fSwgZmFsc2UpIDogdW5kZWZpbmVkKSxcbiAgY2hlY2s6IGNoZWNrXG59O1xuIiwiLy8gMTkuMS4zLjE5IE9iamVjdC5zZXRQcm90b3R5cGVPZihPLCBwcm90bylcbnZhciAkZXhwb3J0ID0gcmVxdWlyZSgnLi9fZXhwb3J0Jyk7XG4kZXhwb3J0KCRleHBvcnQuUywgJ09iamVjdCcsIHsgc2V0UHJvdG90eXBlT2Y6IHJlcXVpcmUoJy4vX3NldC1wcm90bycpLnNldCB9KTtcbiIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5zZXQtcHJvdG90eXBlLW9mJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKS5PYmplY3Quc2V0UHJvdG90eXBlT2Y7XG4iLCJ2YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi9fZ2xvYmFsJyk7XG52YXIgU0hBUkVEID0gJ19fY29yZS1qc19zaGFyZWRfXyc7XG52YXIgc3RvcmUgPSBnbG9iYWxbU0hBUkVEXSB8fCAoZ2xvYmFsW1NIQVJFRF0gPSB7fSk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgcmV0dXJuIHN0b3JlW2tleV0gfHwgKHN0b3JlW2tleV0gPSB7fSk7XG59O1xuIiwidmFyIHN0b3JlID0gcmVxdWlyZSgnLi9fc2hhcmVkJykoJ3drcycpO1xudmFyIHVpZCA9IHJlcXVpcmUoJy4vX3VpZCcpO1xudmFyIFN5bWJvbCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpLlN5bWJvbDtcbnZhciBVU0VfU1lNQk9MID0gdHlwZW9mIFN5bWJvbCA9PSAnZnVuY3Rpb24nO1xuXG52YXIgJGV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gIHJldHVybiBzdG9yZVtuYW1lXSB8fCAoc3RvcmVbbmFtZV0gPVxuICAgIFVTRV9TWU1CT0wgJiYgU3ltYm9sW25hbWVdIHx8IChVU0VfU1lNQk9MID8gU3ltYm9sIDogdWlkKSgnU3ltYm9sLicgKyBuYW1lKSk7XG59O1xuXG4kZXhwb3J0cy5zdG9yZSA9IHN0b3JlO1xuIiwiLy8gZ2V0dGluZyB0YWcgZnJvbSAxOS4xLjMuNiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nKClcbnZhciBjb2YgPSByZXF1aXJlKCcuL19jb2YnKTtcbnZhciBUQUcgPSByZXF1aXJlKCcuL193a3MnKSgndG9TdHJpbmdUYWcnKTtcbi8vIEVTMyB3cm9uZyBoZXJlXG52YXIgQVJHID0gY29mKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGFyZ3VtZW50czsgfSgpKSA9PSAnQXJndW1lbnRzJztcblxuLy8gZmFsbGJhY2sgZm9yIElFMTEgU2NyaXB0IEFjY2VzcyBEZW5pZWQgZXJyb3JcbnZhciB0cnlHZXQgPSBmdW5jdGlvbiAoaXQsIGtleSkge1xuICB0cnkge1xuICAgIHJldHVybiBpdFtrZXldO1xuICB9IGNhdGNoIChlKSB7IC8qIGVtcHR5ICovIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIHZhciBPLCBULCBCO1xuICByZXR1cm4gaXQgPT09IHVuZGVmaW5lZCA/ICdVbmRlZmluZWQnIDogaXQgPT09IG51bGwgPyAnTnVsbCdcbiAgICAvLyBAQHRvU3RyaW5nVGFnIGNhc2VcbiAgICA6IHR5cGVvZiAoVCA9IHRyeUdldChPID0gT2JqZWN0KGl0KSwgVEFHKSkgPT0gJ3N0cmluZycgPyBUXG4gICAgLy8gYnVpbHRpblRhZyBjYXNlXG4gICAgOiBBUkcgPyBjb2YoTylcbiAgICAvLyBFUzMgYXJndW1lbnRzIGZhbGxiYWNrXG4gICAgOiAoQiA9IGNvZihPKSkgPT0gJ09iamVjdCcgJiYgdHlwZW9mIE8uY2FsbGVlID09ICdmdW5jdGlvbicgPyAnQXJndW1lbnRzJyA6IEI7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuLy8gMTkuMS4zLjYgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZygpXG52YXIgY2xhc3NvZiA9IHJlcXVpcmUoJy4vX2NsYXNzb2YnKTtcbnZhciB0ZXN0ID0ge307XG50ZXN0W3JlcXVpcmUoJy4vX3drcycpKCd0b1N0cmluZ1RhZycpXSA9ICd6JztcbmlmICh0ZXN0ICsgJycgIT0gJ1tvYmplY3Qgel0nKSB7XG4gIHJlcXVpcmUoJy4vX3JlZGVmaW5lJykoT2JqZWN0LnByb3RvdHlwZSwgJ3RvU3RyaW5nJywgZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuICdbb2JqZWN0ICcgKyBjbGFzc29mKHRoaXMpICsgJ10nO1xuICB9LCB0cnVlKTtcbn1cbiIsIi8vIDcuMS40IFRvSW50ZWdlclxudmFyIGNlaWwgPSBNYXRoLmNlaWw7XG52YXIgZmxvb3IgPSBNYXRoLmZsb29yO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIGlzTmFOKGl0ID0gK2l0KSA/IDAgOiAoaXQgPiAwID8gZmxvb3IgOiBjZWlsKShpdCk7XG59O1xuIiwidmFyIHRvSW50ZWdlciA9IHJlcXVpcmUoJy4vX3RvLWludGVnZXInKTtcbnZhciBkZWZpbmVkID0gcmVxdWlyZSgnLi9fZGVmaW5lZCcpO1xuLy8gdHJ1ZSAgLT4gU3RyaW5nI2F0XG4vLyBmYWxzZSAtPiBTdHJpbmcjY29kZVBvaW50QXRcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKFRPX1NUUklORykge1xuICByZXR1cm4gZnVuY3Rpb24gKHRoYXQsIHBvcykge1xuICAgIHZhciBzID0gU3RyaW5nKGRlZmluZWQodGhhdCkpO1xuICAgIHZhciBpID0gdG9JbnRlZ2VyKHBvcyk7XG4gICAgdmFyIGwgPSBzLmxlbmd0aDtcbiAgICB2YXIgYSwgYjtcbiAgICBpZiAoaSA8IDAgfHwgaSA+PSBsKSByZXR1cm4gVE9fU1RSSU5HID8gJycgOiB1bmRlZmluZWQ7XG4gICAgYSA9IHMuY2hhckNvZGVBdChpKTtcbiAgICByZXR1cm4gYSA8IDB4ZDgwMCB8fCBhID4gMHhkYmZmIHx8IGkgKyAxID09PSBsIHx8IChiID0gcy5jaGFyQ29kZUF0KGkgKyAxKSkgPCAweGRjMDAgfHwgYiA+IDB4ZGZmZlxuICAgICAgPyBUT19TVFJJTkcgPyBzLmNoYXJBdChpKSA6IGFcbiAgICAgIDogVE9fU1RSSU5HID8gcy5zbGljZShpLCBpICsgMikgOiAoYSAtIDB4ZDgwMCA8PCAxMCkgKyAoYiAtIDB4ZGMwMCkgKyAweDEwMDAwO1xuICB9O1xufTtcbiIsIm1vZHVsZS5leHBvcnRzID0gZmFsc2U7XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHt9O1xuIiwiLy8gNy4xLjE1IFRvTGVuZ3RoXG52YXIgdG9JbnRlZ2VyID0gcmVxdWlyZSgnLi9fdG8taW50ZWdlcicpO1xudmFyIG1pbiA9IE1hdGgubWluO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIGl0ID4gMCA/IG1pbih0b0ludGVnZXIoaXQpLCAweDFmZmZmZmZmZmZmZmZmKSA6IDA7IC8vIHBvdygyLCA1MykgLSAxID09IDkwMDcxOTkyNTQ3NDA5OTFcbn07XG4iLCJ2YXIgdG9JbnRlZ2VyID0gcmVxdWlyZSgnLi9fdG8taW50ZWdlcicpO1xudmFyIG1heCA9IE1hdGgubWF4O1xudmFyIG1pbiA9IE1hdGgubWluO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaW5kZXgsIGxlbmd0aCkge1xuICBpbmRleCA9IHRvSW50ZWdlcihpbmRleCk7XG4gIHJldHVybiBpbmRleCA8IDAgPyBtYXgoaW5kZXggKyBsZW5ndGgsIDApIDogbWluKGluZGV4LCBsZW5ndGgpO1xufTtcbiIsIi8vIGZhbHNlIC0+IEFycmF5I2luZGV4T2Zcbi8vIHRydWUgIC0+IEFycmF5I2luY2x1ZGVzXG52YXIgdG9JT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8taW9iamVjdCcpO1xudmFyIHRvTGVuZ3RoID0gcmVxdWlyZSgnLi9fdG8tbGVuZ3RoJyk7XG52YXIgdG9BYnNvbHV0ZUluZGV4ID0gcmVxdWlyZSgnLi9fdG8tYWJzb2x1dGUtaW5kZXgnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKElTX0lOQ0xVREVTKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoJHRoaXMsIGVsLCBmcm9tSW5kZXgpIHtcbiAgICB2YXIgTyA9IHRvSU9iamVjdCgkdGhpcyk7XG4gICAgdmFyIGxlbmd0aCA9IHRvTGVuZ3RoKE8ubGVuZ3RoKTtcbiAgICB2YXIgaW5kZXggPSB0b0Fic29sdXRlSW5kZXgoZnJvbUluZGV4LCBsZW5ndGgpO1xuICAgIHZhciB2YWx1ZTtcbiAgICAvLyBBcnJheSNpbmNsdWRlcyB1c2VzIFNhbWVWYWx1ZVplcm8gZXF1YWxpdHkgYWxnb3JpdGhtXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXNlbGYtY29tcGFyZVxuICAgIGlmIChJU19JTkNMVURFUyAmJiBlbCAhPSBlbCkgd2hpbGUgKGxlbmd0aCA+IGluZGV4KSB7XG4gICAgICB2YWx1ZSA9IE9baW5kZXgrK107XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2VsZi1jb21wYXJlXG4gICAgICBpZiAodmFsdWUgIT0gdmFsdWUpIHJldHVybiB0cnVlO1xuICAgIC8vIEFycmF5I2luZGV4T2YgaWdub3JlcyBob2xlcywgQXJyYXkjaW5jbHVkZXMgLSBub3RcbiAgICB9IGVsc2UgZm9yICg7bGVuZ3RoID4gaW5kZXg7IGluZGV4KyspIGlmIChJU19JTkNMVURFUyB8fCBpbmRleCBpbiBPKSB7XG4gICAgICBpZiAoT1tpbmRleF0gPT09IGVsKSByZXR1cm4gSVNfSU5DTFVERVMgfHwgaW5kZXggfHwgMDtcbiAgICB9IHJldHVybiAhSVNfSU5DTFVERVMgJiYgLTE7XG4gIH07XG59O1xuIiwidmFyIHNoYXJlZCA9IHJlcXVpcmUoJy4vX3NoYXJlZCcpKCdrZXlzJyk7XG52YXIgdWlkID0gcmVxdWlyZSgnLi9fdWlkJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgcmV0dXJuIHNoYXJlZFtrZXldIHx8IChzaGFyZWRba2V5XSA9IHVpZChrZXkpKTtcbn07XG4iLCJ2YXIgaGFzID0gcmVxdWlyZSgnLi9faGFzJyk7XG52YXIgdG9JT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8taW9iamVjdCcpO1xudmFyIGFycmF5SW5kZXhPZiA9IHJlcXVpcmUoJy4vX2FycmF5LWluY2x1ZGVzJykoZmFsc2UpO1xudmFyIElFX1BST1RPID0gcmVxdWlyZSgnLi9fc2hhcmVkLWtleScpKCdJRV9QUk9UTycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmplY3QsIG5hbWVzKSB7XG4gIHZhciBPID0gdG9JT2JqZWN0KG9iamVjdCk7XG4gIHZhciBpID0gMDtcbiAgdmFyIHJlc3VsdCA9IFtdO1xuICB2YXIga2V5O1xuICBmb3IgKGtleSBpbiBPKSBpZiAoa2V5ICE9IElFX1BST1RPKSBoYXMoTywga2V5KSAmJiByZXN1bHQucHVzaChrZXkpO1xuICAvLyBEb24ndCBlbnVtIGJ1ZyAmIGhpZGRlbiBrZXlzXG4gIHdoaWxlIChuYW1lcy5sZW5ndGggPiBpKSBpZiAoaGFzKE8sIGtleSA9IG5hbWVzW2krK10pKSB7XG4gICAgfmFycmF5SW5kZXhPZihyZXN1bHQsIGtleSkgfHwgcmVzdWx0LnB1c2goa2V5KTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufTtcbiIsIi8vIElFIDgtIGRvbid0IGVudW0gYnVnIGtleXNcbm1vZHVsZS5leHBvcnRzID0gKFxuICAnY29uc3RydWN0b3IsaGFzT3duUHJvcGVydHksaXNQcm90b3R5cGVPZixwcm9wZXJ0eUlzRW51bWVyYWJsZSx0b0xvY2FsZVN0cmluZyx0b1N0cmluZyx2YWx1ZU9mJ1xuKS5zcGxpdCgnLCcpO1xuIiwiLy8gMTkuMS4yLjE0IC8gMTUuMi4zLjE0IE9iamVjdC5rZXlzKE8pXG52YXIgJGtleXMgPSByZXF1aXJlKCcuL19vYmplY3Qta2V5cy1pbnRlcm5hbCcpO1xudmFyIGVudW1CdWdLZXlzID0gcmVxdWlyZSgnLi9fZW51bS1idWcta2V5cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5rZXlzIHx8IGZ1bmN0aW9uIGtleXMoTykge1xuICByZXR1cm4gJGtleXMoTywgZW51bUJ1Z0tleXMpO1xufTtcbiIsInZhciBkUCA9IHJlcXVpcmUoJy4vX29iamVjdC1kcCcpO1xudmFyIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0Jyk7XG52YXIgZ2V0S2V5cyA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKSA/IE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzIDogZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyhPLCBQcm9wZXJ0aWVzKSB7XG4gIGFuT2JqZWN0KE8pO1xuICB2YXIga2V5cyA9IGdldEtleXMoUHJvcGVydGllcyk7XG4gIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDtcbiAgdmFyIGkgPSAwO1xuICB2YXIgUDtcbiAgd2hpbGUgKGxlbmd0aCA+IGkpIGRQLmYoTywgUCA9IGtleXNbaSsrXSwgUHJvcGVydGllc1tQXSk7XG4gIHJldHVybiBPO1xufTtcbiIsInZhciBkb2N1bWVudCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpLmRvY3VtZW50O1xubW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudCAmJiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4iLCIvLyAxOS4xLjIuMiAvIDE1LjIuMy41IE9iamVjdC5jcmVhdGUoTyBbLCBQcm9wZXJ0aWVzXSlcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4vX2FuLW9iamVjdCcpO1xudmFyIGRQcyA9IHJlcXVpcmUoJy4vX29iamVjdC1kcHMnKTtcbnZhciBlbnVtQnVnS2V5cyA9IHJlcXVpcmUoJy4vX2VudW0tYnVnLWtleXMnKTtcbnZhciBJRV9QUk9UTyA9IHJlcXVpcmUoJy4vX3NoYXJlZC1rZXknKSgnSUVfUFJPVE8nKTtcbnZhciBFbXB0eSA9IGZ1bmN0aW9uICgpIHsgLyogZW1wdHkgKi8gfTtcbnZhciBQUk9UT1RZUEUgPSAncHJvdG90eXBlJztcblxuLy8gQ3JlYXRlIG9iamVjdCB3aXRoIGZha2UgYG51bGxgIHByb3RvdHlwZTogdXNlIGlmcmFtZSBPYmplY3Qgd2l0aCBjbGVhcmVkIHByb3RvdHlwZVxudmFyIGNyZWF0ZURpY3QgPSBmdW5jdGlvbiAoKSB7XG4gIC8vIFRocmFzaCwgd2FzdGUgYW5kIHNvZG9teTogSUUgR0MgYnVnXG4gIHZhciBpZnJhbWUgPSByZXF1aXJlKCcuL19kb20tY3JlYXRlJykoJ2lmcmFtZScpO1xuICB2YXIgaSA9IGVudW1CdWdLZXlzLmxlbmd0aDtcbiAgdmFyIGx0ID0gJzwnO1xuICB2YXIgZ3QgPSAnPic7XG4gIHZhciBpZnJhbWVEb2N1bWVudDtcbiAgaWZyYW1lLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gIHJlcXVpcmUoJy4vX2h0bWwnKS5hcHBlbmRDaGlsZChpZnJhbWUpO1xuICBpZnJhbWUuc3JjID0gJ2phdmFzY3JpcHQ6JzsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1zY3JpcHQtdXJsXG4gIC8vIGNyZWF0ZURpY3QgPSBpZnJhbWUuY29udGVudFdpbmRvdy5PYmplY3Q7XG4gIC8vIGh0bWwucmVtb3ZlQ2hpbGQoaWZyYW1lKTtcbiAgaWZyYW1lRG9jdW1lbnQgPSBpZnJhbWUuY29udGVudFdpbmRvdy5kb2N1bWVudDtcbiAgaWZyYW1lRG9jdW1lbnQub3BlbigpO1xuICBpZnJhbWVEb2N1bWVudC53cml0ZShsdCArICdzY3JpcHQnICsgZ3QgKyAnZG9jdW1lbnQuRj1PYmplY3QnICsgbHQgKyAnL3NjcmlwdCcgKyBndCk7XG4gIGlmcmFtZURvY3VtZW50LmNsb3NlKCk7XG4gIGNyZWF0ZURpY3QgPSBpZnJhbWVEb2N1bWVudC5GO1xuICB3aGlsZSAoaS0tKSBkZWxldGUgY3JlYXRlRGljdFtQUk9UT1RZUEVdW2VudW1CdWdLZXlzW2ldXTtcbiAgcmV0dXJuIGNyZWF0ZURpY3QoKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gT2JqZWN0LmNyZWF0ZSB8fCBmdW5jdGlvbiBjcmVhdGUoTywgUHJvcGVydGllcykge1xuICB2YXIgcmVzdWx0O1xuICBpZiAoTyAhPT0gbnVsbCkge1xuICAgIEVtcHR5W1BST1RPVFlQRV0gPSBhbk9iamVjdChPKTtcbiAgICByZXN1bHQgPSBuZXcgRW1wdHkoKTtcbiAgICBFbXB0eVtQUk9UT1RZUEVdID0gbnVsbDtcbiAgICAvLyBhZGQgXCJfX3Byb3RvX19cIiBmb3IgT2JqZWN0LmdldFByb3RvdHlwZU9mIHBvbHlmaWxsXG4gICAgcmVzdWx0W0lFX1BST1RPXSA9IE87XG4gIH0gZWxzZSByZXN1bHQgPSBjcmVhdGVEaWN0KCk7XG4gIHJldHVybiBQcm9wZXJ0aWVzID09PSB1bmRlZmluZWQgPyByZXN1bHQgOiBkUHMocmVzdWx0LCBQcm9wZXJ0aWVzKTtcbn07XG4iLCJ2YXIgZGVmID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJykuZjtcbnZhciBoYXMgPSByZXF1aXJlKCcuL19oYXMnKTtcbnZhciBUQUcgPSByZXF1aXJlKCcuL193a3MnKSgndG9TdHJpbmdUYWcnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQsIHRhZywgc3RhdCkge1xuICBpZiAoaXQgJiYgIWhhcyhpdCA9IHN0YXQgPyBpdCA6IGl0LnByb3RvdHlwZSwgVEFHKSkgZGVmKGl0LCBUQUcsIHsgY29uZmlndXJhYmxlOiB0cnVlLCB2YWx1ZTogdGFnIH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBjcmVhdGUgPSByZXF1aXJlKCcuL19vYmplY3QtY3JlYXRlJyk7XG52YXIgZGVzY3JpcHRvciA9IHJlcXVpcmUoJy4vX3Byb3BlcnR5LWRlc2MnKTtcbnZhciBzZXRUb1N0cmluZ1RhZyA9IHJlcXVpcmUoJy4vX3NldC10by1zdHJpbmctdGFnJyk7XG52YXIgSXRlcmF0b3JQcm90b3R5cGUgPSB7fTtcblxuLy8gMjUuMS4yLjEuMSAlSXRlcmF0b3JQcm90b3R5cGUlW0BAaXRlcmF0b3JdKClcbnJlcXVpcmUoJy4vX2hpZGUnKShJdGVyYXRvclByb3RvdHlwZSwgcmVxdWlyZSgnLi9fd2tzJykoJ2l0ZXJhdG9yJyksIGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgTkFNRSwgbmV4dCkge1xuICBDb25zdHJ1Y3Rvci5wcm90b3R5cGUgPSBjcmVhdGUoSXRlcmF0b3JQcm90b3R5cGUsIHsgbmV4dDogZGVzY3JpcHRvcigxLCBuZXh0KSB9KTtcbiAgc2V0VG9TdHJpbmdUYWcoQ29uc3RydWN0b3IsIE5BTUUgKyAnIEl0ZXJhdG9yJyk7XG59O1xuIiwiLy8gNy4xLjEzIFRvT2JqZWN0KGFyZ3VtZW50KVxudmFyIGRlZmluZWQgPSByZXF1aXJlKCcuL19kZWZpbmVkJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gT2JqZWN0KGRlZmluZWQoaXQpKTtcbn07XG4iLCIvLyAxOS4xLjIuOSAvIDE1LjIuMy4yIE9iamVjdC5nZXRQcm90b3R5cGVPZihPKVxudmFyIGhhcyA9IHJlcXVpcmUoJy4vX2hhcycpO1xudmFyIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8tb2JqZWN0Jyk7XG52YXIgSUVfUFJPVE8gPSByZXF1aXJlKCcuL19zaGFyZWQta2V5JykoJ0lFX1BST1RPJyk7XG52YXIgT2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5nZXRQcm90b3R5cGVPZiB8fCBmdW5jdGlvbiAoTykge1xuICBPID0gdG9PYmplY3QoTyk7XG4gIGlmIChoYXMoTywgSUVfUFJPVE8pKSByZXR1cm4gT1tJRV9QUk9UT107XG4gIGlmICh0eXBlb2YgTy5jb25zdHJ1Y3RvciA9PSAnZnVuY3Rpb24nICYmIE8gaW5zdGFuY2VvZiBPLmNvbnN0cnVjdG9yKSB7XG4gICAgcmV0dXJuIE8uY29uc3RydWN0b3IucHJvdG90eXBlO1xuICB9IHJldHVybiBPIGluc3RhbmNlb2YgT2JqZWN0ID8gT2JqZWN0UHJvdG8gOiBudWxsO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBMSUJSQVJZID0gcmVxdWlyZSgnLi9fbGlicmFyeScpO1xudmFyICRleHBvcnQgPSByZXF1aXJlKCcuL19leHBvcnQnKTtcbnZhciByZWRlZmluZSA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lJyk7XG52YXIgaGlkZSA9IHJlcXVpcmUoJy4vX2hpZGUnKTtcbnZhciBoYXMgPSByZXF1aXJlKCcuL19oYXMnKTtcbnZhciBJdGVyYXRvcnMgPSByZXF1aXJlKCcuL19pdGVyYXRvcnMnKTtcbnZhciAkaXRlckNyZWF0ZSA9IHJlcXVpcmUoJy4vX2l0ZXItY3JlYXRlJyk7XG52YXIgc2V0VG9TdHJpbmdUYWcgPSByZXF1aXJlKCcuL19zZXQtdG8tc3RyaW5nLXRhZycpO1xudmFyIGdldFByb3RvdHlwZU9mID0gcmVxdWlyZSgnLi9fb2JqZWN0LWdwbycpO1xudmFyIElURVJBVE9SID0gcmVxdWlyZSgnLi9fd2tzJykoJ2l0ZXJhdG9yJyk7XG52YXIgQlVHR1kgPSAhKFtdLmtleXMgJiYgJ25leHQnIGluIFtdLmtleXMoKSk7IC8vIFNhZmFyaSBoYXMgYnVnZ3kgaXRlcmF0b3JzIHcvbyBgbmV4dGBcbnZhciBGRl9JVEVSQVRPUiA9ICdAQGl0ZXJhdG9yJztcbnZhciBLRVlTID0gJ2tleXMnO1xudmFyIFZBTFVFUyA9ICd2YWx1ZXMnO1xuXG52YXIgcmV0dXJuVGhpcyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKEJhc2UsIE5BTUUsIENvbnN0cnVjdG9yLCBuZXh0LCBERUZBVUxULCBJU19TRVQsIEZPUkNFRCkge1xuICAkaXRlckNyZWF0ZShDb25zdHJ1Y3RvciwgTkFNRSwgbmV4dCk7XG4gIHZhciBnZXRNZXRob2QgPSBmdW5jdGlvbiAoa2luZCkge1xuICAgIGlmICghQlVHR1kgJiYga2luZCBpbiBwcm90bykgcmV0dXJuIHByb3RvW2tpbmRdO1xuICAgIHN3aXRjaCAoa2luZCkge1xuICAgICAgY2FzZSBLRVlTOiByZXR1cm4gZnVuY3Rpb24ga2V5cygpIHsgcmV0dXJuIG5ldyBDb25zdHJ1Y3Rvcih0aGlzLCBraW5kKTsgfTtcbiAgICAgIGNhc2UgVkFMVUVTOiByZXR1cm4gZnVuY3Rpb24gdmFsdWVzKCkgeyByZXR1cm4gbmV3IENvbnN0cnVjdG9yKHRoaXMsIGtpbmQpOyB9O1xuICAgIH0gcmV0dXJuIGZ1bmN0aW9uIGVudHJpZXMoKSB7IHJldHVybiBuZXcgQ29uc3RydWN0b3IodGhpcywga2luZCk7IH07XG4gIH07XG4gIHZhciBUQUcgPSBOQU1FICsgJyBJdGVyYXRvcic7XG4gIHZhciBERUZfVkFMVUVTID0gREVGQVVMVCA9PSBWQUxVRVM7XG4gIHZhciBWQUxVRVNfQlVHID0gZmFsc2U7XG4gIHZhciBwcm90byA9IEJhc2UucHJvdG90eXBlO1xuICB2YXIgJG5hdGl2ZSA9IHByb3RvW0lURVJBVE9SXSB8fCBwcm90b1tGRl9JVEVSQVRPUl0gfHwgREVGQVVMVCAmJiBwcm90b1tERUZBVUxUXTtcbiAgdmFyICRkZWZhdWx0ID0gJG5hdGl2ZSB8fCBnZXRNZXRob2QoREVGQVVMVCk7XG4gIHZhciAkZW50cmllcyA9IERFRkFVTFQgPyAhREVGX1ZBTFVFUyA/ICRkZWZhdWx0IDogZ2V0TWV0aG9kKCdlbnRyaWVzJykgOiB1bmRlZmluZWQ7XG4gIHZhciAkYW55TmF0aXZlID0gTkFNRSA9PSAnQXJyYXknID8gcHJvdG8uZW50cmllcyB8fCAkbmF0aXZlIDogJG5hdGl2ZTtcbiAgdmFyIG1ldGhvZHMsIGtleSwgSXRlcmF0b3JQcm90b3R5cGU7XG4gIC8vIEZpeCBuYXRpdmVcbiAgaWYgKCRhbnlOYXRpdmUpIHtcbiAgICBJdGVyYXRvclByb3RvdHlwZSA9IGdldFByb3RvdHlwZU9mKCRhbnlOYXRpdmUuY2FsbChuZXcgQmFzZSgpKSk7XG4gICAgaWYgKEl0ZXJhdG9yUHJvdG90eXBlICE9PSBPYmplY3QucHJvdG90eXBlICYmIEl0ZXJhdG9yUHJvdG90eXBlLm5leHQpIHtcbiAgICAgIC8vIFNldCBAQHRvU3RyaW5nVGFnIHRvIG5hdGl2ZSBpdGVyYXRvcnNcbiAgICAgIHNldFRvU3RyaW5nVGFnKEl0ZXJhdG9yUHJvdG90eXBlLCBUQUcsIHRydWUpO1xuICAgICAgLy8gZml4IGZvciBzb21lIG9sZCBlbmdpbmVzXG4gICAgICBpZiAoIUxJQlJBUlkgJiYgIWhhcyhJdGVyYXRvclByb3RvdHlwZSwgSVRFUkFUT1IpKSBoaWRlKEl0ZXJhdG9yUHJvdG90eXBlLCBJVEVSQVRPUiwgcmV0dXJuVGhpcyk7XG4gICAgfVxuICB9XG4gIC8vIGZpeCBBcnJheSN7dmFsdWVzLCBAQGl0ZXJhdG9yfS5uYW1lIGluIFY4IC8gRkZcbiAgaWYgKERFRl9WQUxVRVMgJiYgJG5hdGl2ZSAmJiAkbmF0aXZlLm5hbWUgIT09IFZBTFVFUykge1xuICAgIFZBTFVFU19CVUcgPSB0cnVlO1xuICAgICRkZWZhdWx0ID0gZnVuY3Rpb24gdmFsdWVzKCkgeyByZXR1cm4gJG5hdGl2ZS5jYWxsKHRoaXMpOyB9O1xuICB9XG4gIC8vIERlZmluZSBpdGVyYXRvclxuICBpZiAoKCFMSUJSQVJZIHx8IEZPUkNFRCkgJiYgKEJVR0dZIHx8IFZBTFVFU19CVUcgfHwgIXByb3RvW0lURVJBVE9SXSkpIHtcbiAgICBoaWRlKHByb3RvLCBJVEVSQVRPUiwgJGRlZmF1bHQpO1xuICB9XG4gIC8vIFBsdWcgZm9yIGxpYnJhcnlcbiAgSXRlcmF0b3JzW05BTUVdID0gJGRlZmF1bHQ7XG4gIEl0ZXJhdG9yc1tUQUddID0gcmV0dXJuVGhpcztcbiAgaWYgKERFRkFVTFQpIHtcbiAgICBtZXRob2RzID0ge1xuICAgICAgdmFsdWVzOiBERUZfVkFMVUVTID8gJGRlZmF1bHQgOiBnZXRNZXRob2QoVkFMVUVTKSxcbiAgICAgIGtleXM6IElTX1NFVCA/ICRkZWZhdWx0IDogZ2V0TWV0aG9kKEtFWVMpLFxuICAgICAgZW50cmllczogJGVudHJpZXNcbiAgICB9O1xuICAgIGlmIChGT1JDRUQpIGZvciAoa2V5IGluIG1ldGhvZHMpIHtcbiAgICAgIGlmICghKGtleSBpbiBwcm90bykpIHJlZGVmaW5lKHByb3RvLCBrZXksIG1ldGhvZHNba2V5XSk7XG4gICAgfSBlbHNlICRleHBvcnQoJGV4cG9ydC5QICsgJGV4cG9ydC5GICogKEJVR0dZIHx8IFZBTFVFU19CVUcpLCBOQU1FLCBtZXRob2RzKTtcbiAgfVxuICByZXR1cm4gbWV0aG9kcztcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgJGF0ID0gcmVxdWlyZSgnLi9fc3RyaW5nLWF0JykodHJ1ZSk7XG5cbi8vIDIxLjEuMy4yNyBTdHJpbmcucHJvdG90eXBlW0BAaXRlcmF0b3JdKClcbnJlcXVpcmUoJy4vX2l0ZXItZGVmaW5lJykoU3RyaW5nLCAnU3RyaW5nJywgZnVuY3Rpb24gKGl0ZXJhdGVkKSB7XG4gIHRoaXMuX3QgPSBTdHJpbmcoaXRlcmF0ZWQpOyAvLyB0YXJnZXRcbiAgdGhpcy5faSA9IDA7ICAgICAgICAgICAgICAgIC8vIG5leHQgaW5kZXhcbi8vIDIxLjEuNS4yLjEgJVN0cmluZ0l0ZXJhdG9yUHJvdG90eXBlJS5uZXh0KClcbn0sIGZ1bmN0aW9uICgpIHtcbiAgdmFyIE8gPSB0aGlzLl90O1xuICB2YXIgaW5kZXggPSB0aGlzLl9pO1xuICB2YXIgcG9pbnQ7XG4gIGlmIChpbmRleCA+PSBPLmxlbmd0aCkgcmV0dXJuIHsgdmFsdWU6IHVuZGVmaW5lZCwgZG9uZTogdHJ1ZSB9O1xuICBwb2ludCA9ICRhdChPLCBpbmRleCk7XG4gIHRoaXMuX2kgKz0gcG9pbnQubGVuZ3RoO1xuICByZXR1cm4geyB2YWx1ZTogcG9pbnQsIGRvbmU6IGZhbHNlIH07XG59KTtcbiIsIi8vIDIyLjEuMy4zMSBBcnJheS5wcm90b3R5cGVbQEB1bnNjb3BhYmxlc11cbnZhciBVTlNDT1BBQkxFUyA9IHJlcXVpcmUoJy4vX3drcycpKCd1bnNjb3BhYmxlcycpO1xudmFyIEFycmF5UHJvdG8gPSBBcnJheS5wcm90b3R5cGU7XG5pZiAoQXJyYXlQcm90b1tVTlNDT1BBQkxFU10gPT0gdW5kZWZpbmVkKSByZXF1aXJlKCcuL19oaWRlJykoQXJyYXlQcm90bywgVU5TQ09QQUJMRVMsIHt9KTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGtleSkge1xuICBBcnJheVByb3RvW1VOU0NPUEFCTEVTXVtrZXldID0gdHJ1ZTtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChkb25lLCB2YWx1ZSkge1xuICByZXR1cm4geyB2YWx1ZTogdmFsdWUsIGRvbmU6ICEhZG9uZSB9O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBhZGRUb1Vuc2NvcGFibGVzID0gcmVxdWlyZSgnLi9fYWRkLXRvLXVuc2NvcGFibGVzJyk7XG52YXIgc3RlcCA9IHJlcXVpcmUoJy4vX2l0ZXItc3RlcCcpO1xudmFyIEl0ZXJhdG9ycyA9IHJlcXVpcmUoJy4vX2l0ZXJhdG9ycycpO1xudmFyIHRvSU9iamVjdCA9IHJlcXVpcmUoJy4vX3RvLWlvYmplY3QnKTtcblxuLy8gMjIuMS4zLjQgQXJyYXkucHJvdG90eXBlLmVudHJpZXMoKVxuLy8gMjIuMS4zLjEzIEFycmF5LnByb3RvdHlwZS5rZXlzKClcbi8vIDIyLjEuMy4yOSBBcnJheS5wcm90b3R5cGUudmFsdWVzKClcbi8vIDIyLjEuMy4zMCBBcnJheS5wcm90b3R5cGVbQEBpdGVyYXRvcl0oKVxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL19pdGVyLWRlZmluZScpKEFycmF5LCAnQXJyYXknLCBmdW5jdGlvbiAoaXRlcmF0ZWQsIGtpbmQpIHtcbiAgdGhpcy5fdCA9IHRvSU9iamVjdChpdGVyYXRlZCk7IC8vIHRhcmdldFxuICB0aGlzLl9pID0gMDsgICAgICAgICAgICAgICAgICAgLy8gbmV4dCBpbmRleFxuICB0aGlzLl9rID0ga2luZDsgICAgICAgICAgICAgICAgLy8ga2luZFxuLy8gMjIuMS41LjIuMSAlQXJyYXlJdGVyYXRvclByb3RvdHlwZSUubmV4dCgpXG59LCBmdW5jdGlvbiAoKSB7XG4gIHZhciBPID0gdGhpcy5fdDtcbiAgdmFyIGtpbmQgPSB0aGlzLl9rO1xuICB2YXIgaW5kZXggPSB0aGlzLl9pKys7XG4gIGlmICghTyB8fCBpbmRleCA+PSBPLmxlbmd0aCkge1xuICAgIHRoaXMuX3QgPSB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIHN0ZXAoMSk7XG4gIH1cbiAgaWYgKGtpbmQgPT0gJ2tleXMnKSByZXR1cm4gc3RlcCgwLCBpbmRleCk7XG4gIGlmIChraW5kID09ICd2YWx1ZXMnKSByZXR1cm4gc3RlcCgwLCBPW2luZGV4XSk7XG4gIHJldHVybiBzdGVwKDAsIFtpbmRleCwgT1tpbmRleF1dKTtcbn0sICd2YWx1ZXMnKTtcblxuLy8gYXJndW1lbnRzTGlzdFtAQGl0ZXJhdG9yXSBpcyAlQXJyYXlQcm90b192YWx1ZXMlICg5LjQuNC42LCA5LjQuNC43KVxuSXRlcmF0b3JzLkFyZ3VtZW50cyA9IEl0ZXJhdG9ycy5BcnJheTtcblxuYWRkVG9VbnNjb3BhYmxlcygna2V5cycpO1xuYWRkVG9VbnNjb3BhYmxlcygndmFsdWVzJyk7XG5hZGRUb1Vuc2NvcGFibGVzKCdlbnRyaWVzJyk7XG4iLCJ2YXIgJGl0ZXJhdG9ycyA9IHJlcXVpcmUoJy4vZXM2LmFycmF5Lml0ZXJhdG9yJyk7XG52YXIgZ2V0S2V5cyA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzJyk7XG52YXIgcmVkZWZpbmUgPSByZXF1aXJlKCcuL19yZWRlZmluZScpO1xudmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpO1xudmFyIGhpZGUgPSByZXF1aXJlKCcuL19oaWRlJyk7XG52YXIgSXRlcmF0b3JzID0gcmVxdWlyZSgnLi9faXRlcmF0b3JzJyk7XG52YXIgd2tzID0gcmVxdWlyZSgnLi9fd2tzJyk7XG52YXIgSVRFUkFUT1IgPSB3a3MoJ2l0ZXJhdG9yJyk7XG52YXIgVE9fU1RSSU5HX1RBRyA9IHdrcygndG9TdHJpbmdUYWcnKTtcbnZhciBBcnJheVZhbHVlcyA9IEl0ZXJhdG9ycy5BcnJheTtcblxudmFyIERPTUl0ZXJhYmxlcyA9IHtcbiAgQ1NTUnVsZUxpc3Q6IHRydWUsIC8vIFRPRE86IE5vdCBzcGVjIGNvbXBsaWFudCwgc2hvdWxkIGJlIGZhbHNlLlxuICBDU1NTdHlsZURlY2xhcmF0aW9uOiBmYWxzZSxcbiAgQ1NTVmFsdWVMaXN0OiBmYWxzZSxcbiAgQ2xpZW50UmVjdExpc3Q6IGZhbHNlLFxuICBET01SZWN0TGlzdDogZmFsc2UsXG4gIERPTVN0cmluZ0xpc3Q6IGZhbHNlLFxuICBET01Ub2tlbkxpc3Q6IHRydWUsXG4gIERhdGFUcmFuc2Zlckl0ZW1MaXN0OiBmYWxzZSxcbiAgRmlsZUxpc3Q6IGZhbHNlLFxuICBIVE1MQWxsQ29sbGVjdGlvbjogZmFsc2UsXG4gIEhUTUxDb2xsZWN0aW9uOiBmYWxzZSxcbiAgSFRNTEZvcm1FbGVtZW50OiBmYWxzZSxcbiAgSFRNTFNlbGVjdEVsZW1lbnQ6IGZhbHNlLFxuICBNZWRpYUxpc3Q6IHRydWUsIC8vIFRPRE86IE5vdCBzcGVjIGNvbXBsaWFudCwgc2hvdWxkIGJlIGZhbHNlLlxuICBNaW1lVHlwZUFycmF5OiBmYWxzZSxcbiAgTmFtZWROb2RlTWFwOiBmYWxzZSxcbiAgTm9kZUxpc3Q6IHRydWUsXG4gIFBhaW50UmVxdWVzdExpc3Q6IGZhbHNlLFxuICBQbHVnaW46IGZhbHNlLFxuICBQbHVnaW5BcnJheTogZmFsc2UsXG4gIFNWR0xlbmd0aExpc3Q6IGZhbHNlLFxuICBTVkdOdW1iZXJMaXN0OiBmYWxzZSxcbiAgU1ZHUGF0aFNlZ0xpc3Q6IGZhbHNlLFxuICBTVkdQb2ludExpc3Q6IGZhbHNlLFxuICBTVkdTdHJpbmdMaXN0OiBmYWxzZSxcbiAgU1ZHVHJhbnNmb3JtTGlzdDogZmFsc2UsXG4gIFNvdXJjZUJ1ZmZlckxpc3Q6IGZhbHNlLFxuICBTdHlsZVNoZWV0TGlzdDogdHJ1ZSwgLy8gVE9ETzogTm90IHNwZWMgY29tcGxpYW50LCBzaG91bGQgYmUgZmFsc2UuXG4gIFRleHRUcmFja0N1ZUxpc3Q6IGZhbHNlLFxuICBUZXh0VHJhY2tMaXN0OiBmYWxzZSxcbiAgVG91Y2hMaXN0OiBmYWxzZVxufTtcblxuZm9yICh2YXIgY29sbGVjdGlvbnMgPSBnZXRLZXlzKERPTUl0ZXJhYmxlcyksIGkgPSAwOyBpIDwgY29sbGVjdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgdmFyIE5BTUUgPSBjb2xsZWN0aW9uc1tpXTtcbiAgdmFyIGV4cGxpY2l0ID0gRE9NSXRlcmFibGVzW05BTUVdO1xuICB2YXIgQ29sbGVjdGlvbiA9IGdsb2JhbFtOQU1FXTtcbiAgdmFyIHByb3RvID0gQ29sbGVjdGlvbiAmJiBDb2xsZWN0aW9uLnByb3RvdHlwZTtcbiAgdmFyIGtleTtcbiAgaWYgKHByb3RvKSB7XG4gICAgaWYgKCFwcm90b1tJVEVSQVRPUl0pIGhpZGUocHJvdG8sIElURVJBVE9SLCBBcnJheVZhbHVlcyk7XG4gICAgaWYgKCFwcm90b1tUT19TVFJJTkdfVEFHXSkgaGlkZShwcm90bywgVE9fU1RSSU5HX1RBRywgTkFNRSk7XG4gICAgSXRlcmF0b3JzW05BTUVdID0gQXJyYXlWYWx1ZXM7XG4gICAgaWYgKGV4cGxpY2l0KSBmb3IgKGtleSBpbiAkaXRlcmF0b3JzKSBpZiAoIXByb3RvW2tleV0pIHJlZGVmaW5lKHByb3RvLCBrZXksICRpdGVyYXRvcnNba2V5XSwgdHJ1ZSk7XG4gIH1cbn1cbiIsInZhciByZWRlZmluZSA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh0YXJnZXQsIHNyYywgc2FmZSkge1xuICBmb3IgKHZhciBrZXkgaW4gc3JjKSByZWRlZmluZSh0YXJnZXQsIGtleSwgc3JjW2tleV0sIHNhZmUpO1xuICByZXR1cm4gdGFyZ2V0O1xufTtcbiIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0LCBDb25zdHJ1Y3RvciwgbmFtZSwgZm9yYmlkZGVuRmllbGQpIHtcbiAgaWYgKCEoaXQgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikgfHwgKGZvcmJpZGRlbkZpZWxkICE9PSB1bmRlZmluZWQgJiYgZm9yYmlkZGVuRmllbGQgaW4gaXQpKSB7XG4gICAgdGhyb3cgVHlwZUVycm9yKG5hbWUgKyAnOiBpbmNvcnJlY3QgaW52b2NhdGlvbiEnKTtcbiAgfSByZXR1cm4gaXQ7XG59O1xuIiwiLy8gY2FsbCBzb21ldGhpbmcgb24gaXRlcmF0b3Igc3RlcCB3aXRoIHNhZmUgY2xvc2luZyBvbiBlcnJvclxudmFyIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0Jyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdGVyYXRvciwgZm4sIHZhbHVlLCBlbnRyaWVzKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGVudHJpZXMgPyBmbihhbk9iamVjdCh2YWx1ZSlbMF0sIHZhbHVlWzFdKSA6IGZuKHZhbHVlKTtcbiAgLy8gNy40LjYgSXRlcmF0b3JDbG9zZShpdGVyYXRvciwgY29tcGxldGlvbilcbiAgfSBjYXRjaCAoZSkge1xuICAgIHZhciByZXQgPSBpdGVyYXRvclsncmV0dXJuJ107XG4gICAgaWYgKHJldCAhPT0gdW5kZWZpbmVkKSBhbk9iamVjdChyZXQuY2FsbChpdGVyYXRvcikpO1xuICAgIHRocm93IGU7XG4gIH1cbn07XG4iLCIvLyBjaGVjayBvbiBkZWZhdWx0IEFycmF5IGl0ZXJhdG9yXG52YXIgSXRlcmF0b3JzID0gcmVxdWlyZSgnLi9faXRlcmF0b3JzJyk7XG52YXIgSVRFUkFUT1IgPSByZXF1aXJlKCcuL193a3MnKSgnaXRlcmF0b3InKTtcbnZhciBBcnJheVByb3RvID0gQXJyYXkucHJvdG90eXBlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gaXQgIT09IHVuZGVmaW5lZCAmJiAoSXRlcmF0b3JzLkFycmF5ID09PSBpdCB8fCBBcnJheVByb3RvW0lURVJBVE9SXSA9PT0gaXQpO1xufTtcbiIsInZhciBjbGFzc29mID0gcmVxdWlyZSgnLi9fY2xhc3NvZicpO1xudmFyIElURVJBVE9SID0gcmVxdWlyZSgnLi9fd2tzJykoJ2l0ZXJhdG9yJyk7XG52YXIgSXRlcmF0b3JzID0gcmVxdWlyZSgnLi9faXRlcmF0b3JzJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vX2NvcmUnKS5nZXRJdGVyYXRvck1ldGhvZCA9IGZ1bmN0aW9uIChpdCkge1xuICBpZiAoaXQgIT0gdW5kZWZpbmVkKSByZXR1cm4gaXRbSVRFUkFUT1JdXG4gICAgfHwgaXRbJ0BAaXRlcmF0b3InXVxuICAgIHx8IEl0ZXJhdG9yc1tjbGFzc29mKGl0KV07XG59O1xuIiwidmFyIGN0eCA9IHJlcXVpcmUoJy4vX2N0eCcpO1xudmFyIGNhbGwgPSByZXF1aXJlKCcuL19pdGVyLWNhbGwnKTtcbnZhciBpc0FycmF5SXRlciA9IHJlcXVpcmUoJy4vX2lzLWFycmF5LWl0ZXInKTtcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4vX2FuLW9iamVjdCcpO1xudmFyIHRvTGVuZ3RoID0gcmVxdWlyZSgnLi9fdG8tbGVuZ3RoJyk7XG52YXIgZ2V0SXRlckZuID0gcmVxdWlyZSgnLi9jb3JlLmdldC1pdGVyYXRvci1tZXRob2QnKTtcbnZhciBCUkVBSyA9IHt9O1xudmFyIFJFVFVSTiA9IHt9O1xudmFyIGV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdGVyYWJsZSwgZW50cmllcywgZm4sIHRoYXQsIElURVJBVE9SKSB7XG4gIHZhciBpdGVyRm4gPSBJVEVSQVRPUiA/IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGl0ZXJhYmxlOyB9IDogZ2V0SXRlckZuKGl0ZXJhYmxlKTtcbiAgdmFyIGYgPSBjdHgoZm4sIHRoYXQsIGVudHJpZXMgPyAyIDogMSk7XG4gIHZhciBpbmRleCA9IDA7XG4gIHZhciBsZW5ndGgsIHN0ZXAsIGl0ZXJhdG9yLCByZXN1bHQ7XG4gIGlmICh0eXBlb2YgaXRlckZuICE9ICdmdW5jdGlvbicpIHRocm93IFR5cGVFcnJvcihpdGVyYWJsZSArICcgaXMgbm90IGl0ZXJhYmxlIScpO1xuICAvLyBmYXN0IGNhc2UgZm9yIGFycmF5cyB3aXRoIGRlZmF1bHQgaXRlcmF0b3JcbiAgaWYgKGlzQXJyYXlJdGVyKGl0ZXJGbikpIGZvciAobGVuZ3RoID0gdG9MZW5ndGgoaXRlcmFibGUubGVuZ3RoKTsgbGVuZ3RoID4gaW5kZXg7IGluZGV4KyspIHtcbiAgICByZXN1bHQgPSBlbnRyaWVzID8gZihhbk9iamVjdChzdGVwID0gaXRlcmFibGVbaW5kZXhdKVswXSwgc3RlcFsxXSkgOiBmKGl0ZXJhYmxlW2luZGV4XSk7XG4gICAgaWYgKHJlc3VsdCA9PT0gQlJFQUsgfHwgcmVzdWx0ID09PSBSRVRVUk4pIHJldHVybiByZXN1bHQ7XG4gIH0gZWxzZSBmb3IgKGl0ZXJhdG9yID0gaXRlckZuLmNhbGwoaXRlcmFibGUpOyAhKHN0ZXAgPSBpdGVyYXRvci5uZXh0KCkpLmRvbmU7KSB7XG4gICAgcmVzdWx0ID0gY2FsbChpdGVyYXRvciwgZiwgc3RlcC52YWx1ZSwgZW50cmllcyk7XG4gICAgaWYgKHJlc3VsdCA9PT0gQlJFQUsgfHwgcmVzdWx0ID09PSBSRVRVUk4pIHJldHVybiByZXN1bHQ7XG4gIH1cbn07XG5leHBvcnRzLkJSRUFLID0gQlJFQUs7XG5leHBvcnRzLlJFVFVSTiA9IFJFVFVSTjtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBnbG9iYWwgPSByZXF1aXJlKCcuL19nbG9iYWwnKTtcbnZhciBkUCA9IHJlcXVpcmUoJy4vX29iamVjdC1kcCcpO1xudmFyIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKTtcbnZhciBTUEVDSUVTID0gcmVxdWlyZSgnLi9fd2tzJykoJ3NwZWNpZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoS0VZKSB7XG4gIHZhciBDID0gZ2xvYmFsW0tFWV07XG4gIGlmIChERVNDUklQVE9SUyAmJiBDICYmICFDW1NQRUNJRVNdKSBkUC5mKEMsIFNQRUNJRVMsIHtcbiAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9XG4gIH0pO1xufTtcbiIsInZhciBNRVRBID0gcmVxdWlyZSgnLi9fdWlkJykoJ21ldGEnKTtcbnZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpO1xudmFyIGhhcyA9IHJlcXVpcmUoJy4vX2hhcycpO1xudmFyIHNldERlc2MgPSByZXF1aXJlKCcuL19vYmplY3QtZHAnKS5mO1xudmFyIGlkID0gMDtcbnZhciBpc0V4dGVuc2libGUgPSBPYmplY3QuaXNFeHRlbnNpYmxlIHx8IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRydWU7XG59O1xudmFyIEZSRUVaRSA9ICFyZXF1aXJlKCcuL19mYWlscycpKGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIGlzRXh0ZW5zaWJsZShPYmplY3QucHJldmVudEV4dGVuc2lvbnMoe30pKTtcbn0pO1xudmFyIHNldE1ldGEgPSBmdW5jdGlvbiAoaXQpIHtcbiAgc2V0RGVzYyhpdCwgTUVUQSwgeyB2YWx1ZToge1xuICAgIGk6ICdPJyArICsraWQsIC8vIG9iamVjdCBJRFxuICAgIHc6IHt9ICAgICAgICAgIC8vIHdlYWsgY29sbGVjdGlvbnMgSURzXG4gIH0gfSk7XG59O1xudmFyIGZhc3RLZXkgPSBmdW5jdGlvbiAoaXQsIGNyZWF0ZSkge1xuICAvLyByZXR1cm4gcHJpbWl0aXZlIHdpdGggcHJlZml4XG4gIGlmICghaXNPYmplY3QoaXQpKSByZXR1cm4gdHlwZW9mIGl0ID09ICdzeW1ib2wnID8gaXQgOiAodHlwZW9mIGl0ID09ICdzdHJpbmcnID8gJ1MnIDogJ1AnKSArIGl0O1xuICBpZiAoIWhhcyhpdCwgTUVUQSkpIHtcbiAgICAvLyBjYW4ndCBzZXQgbWV0YWRhdGEgdG8gdW5jYXVnaHQgZnJvemVuIG9iamVjdFxuICAgIGlmICghaXNFeHRlbnNpYmxlKGl0KSkgcmV0dXJuICdGJztcbiAgICAvLyBub3QgbmVjZXNzYXJ5IHRvIGFkZCBtZXRhZGF0YVxuICAgIGlmICghY3JlYXRlKSByZXR1cm4gJ0UnO1xuICAgIC8vIGFkZCBtaXNzaW5nIG1ldGFkYXRhXG4gICAgc2V0TWV0YShpdCk7XG4gIC8vIHJldHVybiBvYmplY3QgSURcbiAgfSByZXR1cm4gaXRbTUVUQV0uaTtcbn07XG52YXIgZ2V0V2VhayA9IGZ1bmN0aW9uIChpdCwgY3JlYXRlKSB7XG4gIGlmICghaGFzKGl0LCBNRVRBKSkge1xuICAgIC8vIGNhbid0IHNldCBtZXRhZGF0YSB0byB1bmNhdWdodCBmcm96ZW4gb2JqZWN0XG4gICAgaWYgKCFpc0V4dGVuc2libGUoaXQpKSByZXR1cm4gdHJ1ZTtcbiAgICAvLyBub3QgbmVjZXNzYXJ5IHRvIGFkZCBtZXRhZGF0YVxuICAgIGlmICghY3JlYXRlKSByZXR1cm4gZmFsc2U7XG4gICAgLy8gYWRkIG1pc3NpbmcgbWV0YWRhdGFcbiAgICBzZXRNZXRhKGl0KTtcbiAgLy8gcmV0dXJuIGhhc2ggd2VhayBjb2xsZWN0aW9ucyBJRHNcbiAgfSByZXR1cm4gaXRbTUVUQV0udztcbn07XG4vLyBhZGQgbWV0YWRhdGEgb24gZnJlZXplLWZhbWlseSBtZXRob2RzIGNhbGxpbmdcbnZhciBvbkZyZWV6ZSA9IGZ1bmN0aW9uIChpdCkge1xuICBpZiAoRlJFRVpFICYmIG1ldGEuTkVFRCAmJiBpc0V4dGVuc2libGUoaXQpICYmICFoYXMoaXQsIE1FVEEpKSBzZXRNZXRhKGl0KTtcbiAgcmV0dXJuIGl0O1xufTtcbnZhciBtZXRhID0gbW9kdWxlLmV4cG9ydHMgPSB7XG4gIEtFWTogTUVUQSxcbiAgTkVFRDogZmFsc2UsXG4gIGZhc3RLZXk6IGZhc3RLZXksXG4gIGdldFdlYWs6IGdldFdlYWssXG4gIG9uRnJlZXplOiBvbkZyZWV6ZVxufTtcbiIsInZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQsIFRZUEUpIHtcbiAgaWYgKCFpc09iamVjdChpdCkgfHwgaXQuX3QgIT09IFRZUEUpIHRocm93IFR5cGVFcnJvcignSW5jb21wYXRpYmxlIHJlY2VpdmVyLCAnICsgVFlQRSArICcgcmVxdWlyZWQhJyk7XG4gIHJldHVybiBpdDtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZFAgPSByZXF1aXJlKCcuL19vYmplY3QtZHAnKS5mO1xudmFyIGNyZWF0ZSA9IHJlcXVpcmUoJy4vX29iamVjdC1jcmVhdGUnKTtcbnZhciByZWRlZmluZUFsbCA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lLWFsbCcpO1xudmFyIGN0eCA9IHJlcXVpcmUoJy4vX2N0eCcpO1xudmFyIGFuSW5zdGFuY2UgPSByZXF1aXJlKCcuL19hbi1pbnN0YW5jZScpO1xudmFyIGZvck9mID0gcmVxdWlyZSgnLi9fZm9yLW9mJyk7XG52YXIgJGl0ZXJEZWZpbmUgPSByZXF1aXJlKCcuL19pdGVyLWRlZmluZScpO1xudmFyIHN0ZXAgPSByZXF1aXJlKCcuL19pdGVyLXN0ZXAnKTtcbnZhciBzZXRTcGVjaWVzID0gcmVxdWlyZSgnLi9fc2V0LXNwZWNpZXMnKTtcbnZhciBERVNDUklQVE9SUyA9IHJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJyk7XG52YXIgZmFzdEtleSA9IHJlcXVpcmUoJy4vX21ldGEnKS5mYXN0S2V5O1xudmFyIHZhbGlkYXRlID0gcmVxdWlyZSgnLi9fdmFsaWRhdGUtY29sbGVjdGlvbicpO1xudmFyIFNJWkUgPSBERVNDUklQVE9SUyA/ICdfcycgOiAnc2l6ZSc7XG5cbnZhciBnZXRFbnRyeSA9IGZ1bmN0aW9uICh0aGF0LCBrZXkpIHtcbiAgLy8gZmFzdCBjYXNlXG4gIHZhciBpbmRleCA9IGZhc3RLZXkoa2V5KTtcbiAgdmFyIGVudHJ5O1xuICBpZiAoaW5kZXggIT09ICdGJykgcmV0dXJuIHRoYXQuX2lbaW5kZXhdO1xuICAvLyBmcm96ZW4gb2JqZWN0IGNhc2VcbiAgZm9yIChlbnRyeSA9IHRoYXQuX2Y7IGVudHJ5OyBlbnRyeSA9IGVudHJ5Lm4pIHtcbiAgICBpZiAoZW50cnkuayA9PSBrZXkpIHJldHVybiBlbnRyeTtcbiAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGdldENvbnN0cnVjdG9yOiBmdW5jdGlvbiAod3JhcHBlciwgTkFNRSwgSVNfTUFQLCBBRERFUikge1xuICAgIHZhciBDID0gd3JhcHBlcihmdW5jdGlvbiAodGhhdCwgaXRlcmFibGUpIHtcbiAgICAgIGFuSW5zdGFuY2UodGhhdCwgQywgTkFNRSwgJ19pJyk7XG4gICAgICB0aGF0Ll90ID0gTkFNRTsgICAgICAgICAvLyBjb2xsZWN0aW9uIHR5cGVcbiAgICAgIHRoYXQuX2kgPSBjcmVhdGUobnVsbCk7IC8vIGluZGV4XG4gICAgICB0aGF0Ll9mID0gdW5kZWZpbmVkOyAgICAvLyBmaXJzdCBlbnRyeVxuICAgICAgdGhhdC5fbCA9IHVuZGVmaW5lZDsgICAgLy8gbGFzdCBlbnRyeVxuICAgICAgdGhhdFtTSVpFXSA9IDA7ICAgICAgICAgLy8gc2l6ZVxuICAgICAgaWYgKGl0ZXJhYmxlICE9IHVuZGVmaW5lZCkgZm9yT2YoaXRlcmFibGUsIElTX01BUCwgdGhhdFtBRERFUl0sIHRoYXQpO1xuICAgIH0pO1xuICAgIHJlZGVmaW5lQWxsKEMucHJvdG90eXBlLCB7XG4gICAgICAvLyAyMy4xLjMuMSBNYXAucHJvdG90eXBlLmNsZWFyKClcbiAgICAgIC8vIDIzLjIuMy4yIFNldC5wcm90b3R5cGUuY2xlYXIoKVxuICAgICAgY2xlYXI6IGZ1bmN0aW9uIGNsZWFyKCkge1xuICAgICAgICBmb3IgKHZhciB0aGF0ID0gdmFsaWRhdGUodGhpcywgTkFNRSksIGRhdGEgPSB0aGF0Ll9pLCBlbnRyeSA9IHRoYXQuX2Y7IGVudHJ5OyBlbnRyeSA9IGVudHJ5Lm4pIHtcbiAgICAgICAgICBlbnRyeS5yID0gdHJ1ZTtcbiAgICAgICAgICBpZiAoZW50cnkucCkgZW50cnkucCA9IGVudHJ5LnAubiA9IHVuZGVmaW5lZDtcbiAgICAgICAgICBkZWxldGUgZGF0YVtlbnRyeS5pXTtcbiAgICAgICAgfVxuICAgICAgICB0aGF0Ll9mID0gdGhhdC5fbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhhdFtTSVpFXSA9IDA7XG4gICAgICB9LFxuICAgICAgLy8gMjMuMS4zLjMgTWFwLnByb3RvdHlwZS5kZWxldGUoa2V5KVxuICAgICAgLy8gMjMuMi4zLjQgU2V0LnByb3RvdHlwZS5kZWxldGUodmFsdWUpXG4gICAgICAnZGVsZXRlJzogZnVuY3Rpb24gKGtleSkge1xuICAgICAgICB2YXIgdGhhdCA9IHZhbGlkYXRlKHRoaXMsIE5BTUUpO1xuICAgICAgICB2YXIgZW50cnkgPSBnZXRFbnRyeSh0aGF0LCBrZXkpO1xuICAgICAgICBpZiAoZW50cnkpIHtcbiAgICAgICAgICB2YXIgbmV4dCA9IGVudHJ5Lm47XG4gICAgICAgICAgdmFyIHByZXYgPSBlbnRyeS5wO1xuICAgICAgICAgIGRlbGV0ZSB0aGF0Ll9pW2VudHJ5LmldO1xuICAgICAgICAgIGVudHJ5LnIgPSB0cnVlO1xuICAgICAgICAgIGlmIChwcmV2KSBwcmV2Lm4gPSBuZXh0O1xuICAgICAgICAgIGlmIChuZXh0KSBuZXh0LnAgPSBwcmV2O1xuICAgICAgICAgIGlmICh0aGF0Ll9mID09IGVudHJ5KSB0aGF0Ll9mID0gbmV4dDtcbiAgICAgICAgICBpZiAodGhhdC5fbCA9PSBlbnRyeSkgdGhhdC5fbCA9IHByZXY7XG4gICAgICAgICAgdGhhdFtTSVpFXS0tO1xuICAgICAgICB9IHJldHVybiAhIWVudHJ5O1xuICAgICAgfSxcbiAgICAgIC8vIDIzLjIuMy42IFNldC5wcm90b3R5cGUuZm9yRWFjaChjYWxsYmFja2ZuLCB0aGlzQXJnID0gdW5kZWZpbmVkKVxuICAgICAgLy8gMjMuMS4zLjUgTWFwLnByb3RvdHlwZS5mb3JFYWNoKGNhbGxiYWNrZm4sIHRoaXNBcmcgPSB1bmRlZmluZWQpXG4gICAgICBmb3JFYWNoOiBmdW5jdGlvbiBmb3JFYWNoKGNhbGxiYWNrZm4gLyogLCB0aGF0ID0gdW5kZWZpbmVkICovKSB7XG4gICAgICAgIHZhbGlkYXRlKHRoaXMsIE5BTUUpO1xuICAgICAgICB2YXIgZiA9IGN0eChjYWxsYmFja2ZuLCBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCwgMyk7XG4gICAgICAgIHZhciBlbnRyeTtcbiAgICAgICAgd2hpbGUgKGVudHJ5ID0gZW50cnkgPyBlbnRyeS5uIDogdGhpcy5fZikge1xuICAgICAgICAgIGYoZW50cnkudiwgZW50cnkuaywgdGhpcyk7XG4gICAgICAgICAgLy8gcmV2ZXJ0IHRvIHRoZSBsYXN0IGV4aXN0aW5nIGVudHJ5XG4gICAgICAgICAgd2hpbGUgKGVudHJ5ICYmIGVudHJ5LnIpIGVudHJ5ID0gZW50cnkucDtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIC8vIDIzLjEuMy43IE1hcC5wcm90b3R5cGUuaGFzKGtleSlcbiAgICAgIC8vIDIzLjIuMy43IFNldC5wcm90b3R5cGUuaGFzKHZhbHVlKVxuICAgICAgaGFzOiBmdW5jdGlvbiBoYXMoa2V5KSB7XG4gICAgICAgIHJldHVybiAhIWdldEVudHJ5KHZhbGlkYXRlKHRoaXMsIE5BTUUpLCBrZXkpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmIChERVNDUklQVE9SUykgZFAoQy5wcm90b3R5cGUsICdzaXplJywge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB2YWxpZGF0ZSh0aGlzLCBOQU1FKVtTSVpFXTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gQztcbiAgfSxcbiAgZGVmOiBmdW5jdGlvbiAodGhhdCwga2V5LCB2YWx1ZSkge1xuICAgIHZhciBlbnRyeSA9IGdldEVudHJ5KHRoYXQsIGtleSk7XG4gICAgdmFyIHByZXYsIGluZGV4O1xuICAgIC8vIGNoYW5nZSBleGlzdGluZyBlbnRyeVxuICAgIGlmIChlbnRyeSkge1xuICAgICAgZW50cnkudiA9IHZhbHVlO1xuICAgIC8vIGNyZWF0ZSBuZXcgZW50cnlcbiAgICB9IGVsc2Uge1xuICAgICAgdGhhdC5fbCA9IGVudHJ5ID0ge1xuICAgICAgICBpOiBpbmRleCA9IGZhc3RLZXkoa2V5LCB0cnVlKSwgLy8gPC0gaW5kZXhcbiAgICAgICAgazoga2V5LCAgICAgICAgICAgICAgICAgICAgICAgIC8vIDwtIGtleVxuICAgICAgICB2OiB2YWx1ZSwgICAgICAgICAgICAgICAgICAgICAgLy8gPC0gdmFsdWVcbiAgICAgICAgcDogcHJldiA9IHRoYXQuX2wsICAgICAgICAgICAgIC8vIDwtIHByZXZpb3VzIGVudHJ5XG4gICAgICAgIG46IHVuZGVmaW5lZCwgICAgICAgICAgICAgICAgICAvLyA8LSBuZXh0IGVudHJ5XG4gICAgICAgIHI6IGZhbHNlICAgICAgICAgICAgICAgICAgICAgICAvLyA8LSByZW1vdmVkXG4gICAgICB9O1xuICAgICAgaWYgKCF0aGF0Ll9mKSB0aGF0Ll9mID0gZW50cnk7XG4gICAgICBpZiAocHJldikgcHJldi5uID0gZW50cnk7XG4gICAgICB0aGF0W1NJWkVdKys7XG4gICAgICAvLyBhZGQgdG8gaW5kZXhcbiAgICAgIGlmIChpbmRleCAhPT0gJ0YnKSB0aGF0Ll9pW2luZGV4XSA9IGVudHJ5O1xuICAgIH0gcmV0dXJuIHRoYXQ7XG4gIH0sXG4gIGdldEVudHJ5OiBnZXRFbnRyeSxcbiAgc2V0U3Ryb25nOiBmdW5jdGlvbiAoQywgTkFNRSwgSVNfTUFQKSB7XG4gICAgLy8gYWRkIC5rZXlzLCAudmFsdWVzLCAuZW50cmllcywgW0BAaXRlcmF0b3JdXG4gICAgLy8gMjMuMS4zLjQsIDIzLjEuMy44LCAyMy4xLjMuMTEsIDIzLjEuMy4xMiwgMjMuMi4zLjUsIDIzLjIuMy44LCAyMy4yLjMuMTAsIDIzLjIuMy4xMVxuICAgICRpdGVyRGVmaW5lKEMsIE5BTUUsIGZ1bmN0aW9uIChpdGVyYXRlZCwga2luZCkge1xuICAgICAgdGhpcy5fdCA9IHZhbGlkYXRlKGl0ZXJhdGVkLCBOQU1FKTsgLy8gdGFyZ2V0XG4gICAgICB0aGlzLl9rID0ga2luZDsgICAgICAgICAgICAgICAgICAgICAvLyBraW5kXG4gICAgICB0aGlzLl9sID0gdW5kZWZpbmVkOyAgICAgICAgICAgICAgICAvLyBwcmV2aW91c1xuICAgIH0sIGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciB0aGF0ID0gdGhpcztcbiAgICAgIHZhciBraW5kID0gdGhhdC5faztcbiAgICAgIHZhciBlbnRyeSA9IHRoYXQuX2w7XG4gICAgICAvLyByZXZlcnQgdG8gdGhlIGxhc3QgZXhpc3RpbmcgZW50cnlcbiAgICAgIHdoaWxlIChlbnRyeSAmJiBlbnRyeS5yKSBlbnRyeSA9IGVudHJ5LnA7XG4gICAgICAvLyBnZXQgbmV4dCBlbnRyeVxuICAgICAgaWYgKCF0aGF0Ll90IHx8ICEodGhhdC5fbCA9IGVudHJ5ID0gZW50cnkgPyBlbnRyeS5uIDogdGhhdC5fdC5fZikpIHtcbiAgICAgICAgLy8gb3IgZmluaXNoIHRoZSBpdGVyYXRpb25cbiAgICAgICAgdGhhdC5fdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIHN0ZXAoMSk7XG4gICAgICB9XG4gICAgICAvLyByZXR1cm4gc3RlcCBieSBraW5kXG4gICAgICBpZiAoa2luZCA9PSAna2V5cycpIHJldHVybiBzdGVwKDAsIGVudHJ5LmspO1xuICAgICAgaWYgKGtpbmQgPT0gJ3ZhbHVlcycpIHJldHVybiBzdGVwKDAsIGVudHJ5LnYpO1xuICAgICAgcmV0dXJuIHN0ZXAoMCwgW2VudHJ5LmssIGVudHJ5LnZdKTtcbiAgICB9LCBJU19NQVAgPyAnZW50cmllcycgOiAndmFsdWVzJywgIUlTX01BUCwgdHJ1ZSk7XG5cbiAgICAvLyBhZGQgW0BAc3BlY2llc10sIDIzLjEuMi4yLCAyMy4yLjIuMlxuICAgIHNldFNwZWNpZXMoTkFNRSk7XG4gIH1cbn07XG4iLCJ2YXIgSVRFUkFUT1IgPSByZXF1aXJlKCcuL193a3MnKSgnaXRlcmF0b3InKTtcbnZhciBTQUZFX0NMT1NJTkcgPSBmYWxzZTtcblxudHJ5IHtcbiAgdmFyIHJpdGVyID0gWzddW0lURVJBVE9SXSgpO1xuICByaXRlclsncmV0dXJuJ10gPSBmdW5jdGlvbiAoKSB7IFNBRkVfQ0xPU0lORyA9IHRydWU7IH07XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby10aHJvdy1saXRlcmFsXG4gIEFycmF5LmZyb20ocml0ZXIsIGZ1bmN0aW9uICgpIHsgdGhyb3cgMjsgfSk7XG59IGNhdGNoIChlKSB7IC8qIGVtcHR5ICovIH1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZXhlYywgc2tpcENsb3NpbmcpIHtcbiAgaWYgKCFza2lwQ2xvc2luZyAmJiAhU0FGRV9DTE9TSU5HKSByZXR1cm4gZmFsc2U7XG4gIHZhciBzYWZlID0gZmFsc2U7XG4gIHRyeSB7XG4gICAgdmFyIGFyciA9IFs3XTtcbiAgICB2YXIgaXRlciA9IGFycltJVEVSQVRPUl0oKTtcbiAgICBpdGVyLm5leHQgPSBmdW5jdGlvbiAoKSB7IHJldHVybiB7IGRvbmU6IHNhZmUgPSB0cnVlIH07IH07XG4gICAgYXJyW0lURVJBVE9SXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGl0ZXI7IH07XG4gICAgZXhlYyhhcnIpO1xuICB9IGNhdGNoIChlKSB7IC8qIGVtcHR5ICovIH1cbiAgcmV0dXJuIHNhZmU7XG59O1xuIiwidmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0Jyk7XG52YXIgc2V0UHJvdG90eXBlT2YgPSByZXF1aXJlKCcuL19zZXQtcHJvdG8nKS5zZXQ7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh0aGF0LCB0YXJnZXQsIEMpIHtcbiAgdmFyIFMgPSB0YXJnZXQuY29uc3RydWN0b3I7XG4gIHZhciBQO1xuICBpZiAoUyAhPT0gQyAmJiB0eXBlb2YgUyA9PSAnZnVuY3Rpb24nICYmIChQID0gUy5wcm90b3R5cGUpICE9PSBDLnByb3RvdHlwZSAmJiBpc09iamVjdChQKSAmJiBzZXRQcm90b3R5cGVPZikge1xuICAgIHNldFByb3RvdHlwZU9mKHRoYXQsIFApO1xuICB9IHJldHVybiB0aGF0O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBnbG9iYWwgPSByZXF1aXJlKCcuL19nbG9iYWwnKTtcbnZhciAkZXhwb3J0ID0gcmVxdWlyZSgnLi9fZXhwb3J0Jyk7XG52YXIgcmVkZWZpbmUgPSByZXF1aXJlKCcuL19yZWRlZmluZScpO1xudmFyIHJlZGVmaW5lQWxsID0gcmVxdWlyZSgnLi9fcmVkZWZpbmUtYWxsJyk7XG52YXIgbWV0YSA9IHJlcXVpcmUoJy4vX21ldGEnKTtcbnZhciBmb3JPZiA9IHJlcXVpcmUoJy4vX2Zvci1vZicpO1xudmFyIGFuSW5zdGFuY2UgPSByZXF1aXJlKCcuL19hbi1pbnN0YW5jZScpO1xudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0Jyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuL19mYWlscycpO1xudmFyICRpdGVyRGV0ZWN0ID0gcmVxdWlyZSgnLi9faXRlci1kZXRlY3QnKTtcbnZhciBzZXRUb1N0cmluZ1RhZyA9IHJlcXVpcmUoJy4vX3NldC10by1zdHJpbmctdGFnJyk7XG52YXIgaW5oZXJpdElmUmVxdWlyZWQgPSByZXF1aXJlKCcuL19pbmhlcml0LWlmLXJlcXVpcmVkJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKE5BTUUsIHdyYXBwZXIsIG1ldGhvZHMsIGNvbW1vbiwgSVNfTUFQLCBJU19XRUFLKSB7XG4gIHZhciBCYXNlID0gZ2xvYmFsW05BTUVdO1xuICB2YXIgQyA9IEJhc2U7XG4gIHZhciBBRERFUiA9IElTX01BUCA/ICdzZXQnIDogJ2FkZCc7XG4gIHZhciBwcm90byA9IEMgJiYgQy5wcm90b3R5cGU7XG4gIHZhciBPID0ge307XG4gIHZhciBmaXhNZXRob2QgPSBmdW5jdGlvbiAoS0VZKSB7XG4gICAgdmFyIGZuID0gcHJvdG9bS0VZXTtcbiAgICByZWRlZmluZShwcm90bywgS0VZLFxuICAgICAgS0VZID09ICdkZWxldGUnID8gZnVuY3Rpb24gKGEpIHtcbiAgICAgICAgcmV0dXJuIElTX1dFQUsgJiYgIWlzT2JqZWN0KGEpID8gZmFsc2UgOiBmbi5jYWxsKHRoaXMsIGEgPT09IDAgPyAwIDogYSk7XG4gICAgICB9IDogS0VZID09ICdoYXMnID8gZnVuY3Rpb24gaGFzKGEpIHtcbiAgICAgICAgcmV0dXJuIElTX1dFQUsgJiYgIWlzT2JqZWN0KGEpID8gZmFsc2UgOiBmbi5jYWxsKHRoaXMsIGEgPT09IDAgPyAwIDogYSk7XG4gICAgICB9IDogS0VZID09ICdnZXQnID8gZnVuY3Rpb24gZ2V0KGEpIHtcbiAgICAgICAgcmV0dXJuIElTX1dFQUsgJiYgIWlzT2JqZWN0KGEpID8gdW5kZWZpbmVkIDogZm4uY2FsbCh0aGlzLCBhID09PSAwID8gMCA6IGEpO1xuICAgICAgfSA6IEtFWSA9PSAnYWRkJyA/IGZ1bmN0aW9uIGFkZChhKSB7IGZuLmNhbGwodGhpcywgYSA9PT0gMCA/IDAgOiBhKTsgcmV0dXJuIHRoaXM7IH1cbiAgICAgICAgOiBmdW5jdGlvbiBzZXQoYSwgYikgeyBmbi5jYWxsKHRoaXMsIGEgPT09IDAgPyAwIDogYSwgYik7IHJldHVybiB0aGlzOyB9XG4gICAgKTtcbiAgfTtcbiAgaWYgKHR5cGVvZiBDICE9ICdmdW5jdGlvbicgfHwgIShJU19XRUFLIHx8IHByb3RvLmZvckVhY2ggJiYgIWZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgICBuZXcgQygpLmVudHJpZXMoKS5uZXh0KCk7XG4gIH0pKSkge1xuICAgIC8vIGNyZWF0ZSBjb2xsZWN0aW9uIGNvbnN0cnVjdG9yXG4gICAgQyA9IGNvbW1vbi5nZXRDb25zdHJ1Y3Rvcih3cmFwcGVyLCBOQU1FLCBJU19NQVAsIEFEREVSKTtcbiAgICByZWRlZmluZUFsbChDLnByb3RvdHlwZSwgbWV0aG9kcyk7XG4gICAgbWV0YS5ORUVEID0gdHJ1ZTtcbiAgfSBlbHNlIHtcbiAgICB2YXIgaW5zdGFuY2UgPSBuZXcgQygpO1xuICAgIC8vIGVhcmx5IGltcGxlbWVudGF0aW9ucyBub3Qgc3VwcG9ydHMgY2hhaW5pbmdcbiAgICB2YXIgSEFTTlRfQ0hBSU5JTkcgPSBpbnN0YW5jZVtBRERFUl0oSVNfV0VBSyA/IHt9IDogLTAsIDEpICE9IGluc3RhbmNlO1xuICAgIC8vIFY4IH4gIENocm9taXVtIDQwLSB3ZWFrLWNvbGxlY3Rpb25zIHRocm93cyBvbiBwcmltaXRpdmVzLCBidXQgc2hvdWxkIHJldHVybiBmYWxzZVxuICAgIHZhciBUSFJPV1NfT05fUFJJTUlUSVZFUyA9IGZhaWxzKGZ1bmN0aW9uICgpIHsgaW5zdGFuY2UuaGFzKDEpOyB9KTtcbiAgICAvLyBtb3N0IGVhcmx5IGltcGxlbWVudGF0aW9ucyBkb2Vzbid0IHN1cHBvcnRzIGl0ZXJhYmxlcywgbW9zdCBtb2Rlcm4gLSBub3QgY2xvc2UgaXQgY29ycmVjdGx5XG4gICAgdmFyIEFDQ0VQVF9JVEVSQUJMRVMgPSAkaXRlckRldGVjdChmdW5jdGlvbiAoaXRlcikgeyBuZXcgQyhpdGVyKTsgfSk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tbmV3XG4gICAgLy8gZm9yIGVhcmx5IGltcGxlbWVudGF0aW9ucyAtMCBhbmQgKzAgbm90IHRoZSBzYW1lXG4gICAgdmFyIEJVR0dZX1pFUk8gPSAhSVNfV0VBSyAmJiBmYWlscyhmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBWOCB+IENocm9taXVtIDQyLSBmYWlscyBvbmx5IHdpdGggNSsgZWxlbWVudHNcbiAgICAgIHZhciAkaW5zdGFuY2UgPSBuZXcgQygpO1xuICAgICAgdmFyIGluZGV4ID0gNTtcbiAgICAgIHdoaWxlIChpbmRleC0tKSAkaW5zdGFuY2VbQURERVJdKGluZGV4LCBpbmRleCk7XG4gICAgICByZXR1cm4gISRpbnN0YW5jZS5oYXMoLTApO1xuICAgIH0pO1xuICAgIGlmICghQUNDRVBUX0lURVJBQkxFUykge1xuICAgICAgQyA9IHdyYXBwZXIoZnVuY3Rpb24gKHRhcmdldCwgaXRlcmFibGUpIHtcbiAgICAgICAgYW5JbnN0YW5jZSh0YXJnZXQsIEMsIE5BTUUpO1xuICAgICAgICB2YXIgdGhhdCA9IGluaGVyaXRJZlJlcXVpcmVkKG5ldyBCYXNlKCksIHRhcmdldCwgQyk7XG4gICAgICAgIGlmIChpdGVyYWJsZSAhPSB1bmRlZmluZWQpIGZvck9mKGl0ZXJhYmxlLCBJU19NQVAsIHRoYXRbQURERVJdLCB0aGF0KTtcbiAgICAgICAgcmV0dXJuIHRoYXQ7XG4gICAgICB9KTtcbiAgICAgIEMucHJvdG90eXBlID0gcHJvdG87XG4gICAgICBwcm90by5jb25zdHJ1Y3RvciA9IEM7XG4gICAgfVxuICAgIGlmIChUSFJPV1NfT05fUFJJTUlUSVZFUyB8fCBCVUdHWV9aRVJPKSB7XG4gICAgICBmaXhNZXRob2QoJ2RlbGV0ZScpO1xuICAgICAgZml4TWV0aG9kKCdoYXMnKTtcbiAgICAgIElTX01BUCAmJiBmaXhNZXRob2QoJ2dldCcpO1xuICAgIH1cbiAgICBpZiAoQlVHR1lfWkVSTyB8fCBIQVNOVF9DSEFJTklORykgZml4TWV0aG9kKEFEREVSKTtcbiAgICAvLyB3ZWFrIGNvbGxlY3Rpb25zIHNob3VsZCBub3QgY29udGFpbnMgLmNsZWFyIG1ldGhvZFxuICAgIGlmIChJU19XRUFLICYmIHByb3RvLmNsZWFyKSBkZWxldGUgcHJvdG8uY2xlYXI7XG4gIH1cblxuICBzZXRUb1N0cmluZ1RhZyhDLCBOQU1FKTtcblxuICBPW05BTUVdID0gQztcbiAgJGV4cG9ydCgkZXhwb3J0LkcgKyAkZXhwb3J0LlcgKyAkZXhwb3J0LkYgKiAoQyAhPSBCYXNlKSwgTyk7XG5cbiAgaWYgKCFJU19XRUFLKSBjb21tb24uc2V0U3Ryb25nKEMsIE5BTUUsIElTX01BUCk7XG5cbiAgcmV0dXJuIEM7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIHN0cm9uZyA9IHJlcXVpcmUoJy4vX2NvbGxlY3Rpb24tc3Ryb25nJyk7XG52YXIgdmFsaWRhdGUgPSByZXF1aXJlKCcuL192YWxpZGF0ZS1jb2xsZWN0aW9uJyk7XG52YXIgU0VUID0gJ1NldCc7XG5cbi8vIDIzLjIgU2V0IE9iamVjdHNcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fY29sbGVjdGlvbicpKFNFVCwgZnVuY3Rpb24gKGdldCkge1xuICByZXR1cm4gZnVuY3Rpb24gU2V0KCkgeyByZXR1cm4gZ2V0KHRoaXMsIGFyZ3VtZW50cy5sZW5ndGggPiAwID8gYXJndW1lbnRzWzBdIDogdW5kZWZpbmVkKTsgfTtcbn0sIHtcbiAgLy8gMjMuMi4zLjEgU2V0LnByb3RvdHlwZS5hZGQodmFsdWUpXG4gIGFkZDogZnVuY3Rpb24gYWRkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHN0cm9uZy5kZWYodmFsaWRhdGUodGhpcywgU0VUKSwgdmFsdWUgPSB2YWx1ZSA9PT0gMCA/IDAgOiB2YWx1ZSwgdmFsdWUpO1xuICB9XG59LCBzdHJvbmcpO1xuIiwidmFyIGZvck9mID0gcmVxdWlyZSgnLi9fZm9yLW9mJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0ZXIsIElURVJBVE9SKSB7XG4gIHZhciByZXN1bHQgPSBbXTtcbiAgZm9yT2YoaXRlciwgZmFsc2UsIHJlc3VsdC5wdXNoLCByZXN1bHQsIElURVJBVE9SKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn07XG4iLCIvLyBodHRwczovL2dpdGh1Yi5jb20vRGF2aWRCcnVhbnQvTWFwLVNldC5wcm90b3R5cGUudG9KU09OXG52YXIgY2xhc3NvZiA9IHJlcXVpcmUoJy4vX2NsYXNzb2YnKTtcbnZhciBmcm9tID0gcmVxdWlyZSgnLi9fYXJyYXktZnJvbS1pdGVyYWJsZScpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoTkFNRSkge1xuICByZXR1cm4gZnVuY3Rpb24gdG9KU09OKCkge1xuICAgIGlmIChjbGFzc29mKHRoaXMpICE9IE5BTUUpIHRocm93IFR5cGVFcnJvcihOQU1FICsgXCIjdG9KU09OIGlzbid0IGdlbmVyaWNcIik7XG4gICAgcmV0dXJuIGZyb20odGhpcyk7XG4gIH07XG59O1xuIiwiLy8gaHR0cHM6Ly9naXRodWIuY29tL0RhdmlkQnJ1YW50L01hcC1TZXQucHJvdG90eXBlLnRvSlNPTlxudmFyICRleHBvcnQgPSByZXF1aXJlKCcuL19leHBvcnQnKTtcblxuJGV4cG9ydCgkZXhwb3J0LlAgKyAkZXhwb3J0LlIsICdTZXQnLCB7IHRvSlNPTjogcmVxdWlyZSgnLi9fY29sbGVjdGlvbi10by1qc29uJykoJ1NldCcpIH0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuLy8gaHR0cHM6Ly90YzM5LmdpdGh1Yi5pby9wcm9wb3NhbC1zZXRtYXAtb2Zmcm9tL1xudmFyICRleHBvcnQgPSByZXF1aXJlKCcuL19leHBvcnQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoQ09MTEVDVElPTikge1xuICAkZXhwb3J0KCRleHBvcnQuUywgQ09MTEVDVElPTiwgeyBvZjogZnVuY3Rpb24gb2YoKSB7XG4gICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgdmFyIEEgPSBBcnJheShsZW5ndGgpO1xuICAgIHdoaWxlIChsZW5ndGgtLSkgQVtsZW5ndGhdID0gYXJndW1lbnRzW2xlbmd0aF07XG4gICAgcmV0dXJuIG5ldyB0aGlzKEEpO1xuICB9IH0pO1xufTtcbiIsIi8vIGh0dHBzOi8vdGMzOS5naXRodWIuaW8vcHJvcG9zYWwtc2V0bWFwLW9mZnJvbS8jc2VjLXNldC5vZlxucmVxdWlyZSgnLi9fc2V0LWNvbGxlY3Rpb24tb2YnKSgnU2V0Jyk7XG4iLCIndXNlIHN0cmljdCc7XG4vLyBodHRwczovL3RjMzkuZ2l0aHViLmlvL3Byb3Bvc2FsLXNldG1hcC1vZmZyb20vXG52YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xudmFyIGFGdW5jdGlvbiA9IHJlcXVpcmUoJy4vX2EtZnVuY3Rpb24nKTtcbnZhciBjdHggPSByZXF1aXJlKCcuL19jdHgnKTtcbnZhciBmb3JPZiA9IHJlcXVpcmUoJy4vX2Zvci1vZicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChDT0xMRUNUSU9OKSB7XG4gICRleHBvcnQoJGV4cG9ydC5TLCBDT0xMRUNUSU9OLCB7IGZyb206IGZ1bmN0aW9uIGZyb20oc291cmNlIC8qICwgbWFwRm4sIHRoaXNBcmcgKi8pIHtcbiAgICB2YXIgbWFwRm4gPSBhcmd1bWVudHNbMV07XG4gICAgdmFyIG1hcHBpbmcsIEEsIG4sIGNiO1xuICAgIGFGdW5jdGlvbih0aGlzKTtcbiAgICBtYXBwaW5nID0gbWFwRm4gIT09IHVuZGVmaW5lZDtcbiAgICBpZiAobWFwcGluZykgYUZ1bmN0aW9uKG1hcEZuKTtcbiAgICBpZiAoc291cmNlID09IHVuZGVmaW5lZCkgcmV0dXJuIG5ldyB0aGlzKCk7XG4gICAgQSA9IFtdO1xuICAgIGlmIChtYXBwaW5nKSB7XG4gICAgICBuID0gMDtcbiAgICAgIGNiID0gY3R4KG1hcEZuLCBhcmd1bWVudHNbMl0sIDIpO1xuICAgICAgZm9yT2Yoc291cmNlLCBmYWxzZSwgZnVuY3Rpb24gKG5leHRJdGVtKSB7XG4gICAgICAgIEEucHVzaChjYihuZXh0SXRlbSwgbisrKSk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yT2Yoc291cmNlLCBmYWxzZSwgQS5wdXNoLCBBKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyB0aGlzKEEpO1xuICB9IH0pO1xufTtcbiIsIi8vIGh0dHBzOi8vdGMzOS5naXRodWIuaW8vcHJvcG9zYWwtc2V0bWFwLW9mZnJvbS8jc2VjLXNldC5mcm9tXG5yZXF1aXJlKCcuL19zZXQtY29sbGVjdGlvbi1mcm9tJykoJ1NldCcpO1xuIiwicmVxdWlyZSgnLi4vbW9kdWxlcy9lczYub2JqZWN0LnRvLXN0cmluZycpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczYuc3RyaW5nLml0ZXJhdG9yJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUnKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvZXM2LnNldCcpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczcuc2V0LnRvLWpzb24nKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvZXM3LnNldC5vZicpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczcuc2V0LmZyb20nKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vbW9kdWxlcy9fY29yZScpLlNldDtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBzdHJvbmcgPSByZXF1aXJlKCcuL19jb2xsZWN0aW9uLXN0cm9uZycpO1xudmFyIHZhbGlkYXRlID0gcmVxdWlyZSgnLi9fdmFsaWRhdGUtY29sbGVjdGlvbicpO1xudmFyIE1BUCA9ICdNYXAnO1xuXG4vLyAyMy4xIE1hcCBPYmplY3RzXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vX2NvbGxlY3Rpb24nKShNQVAsIGZ1bmN0aW9uIChnZXQpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIE1hcCgpIHsgcmV0dXJuIGdldCh0aGlzLCBhcmd1bWVudHMubGVuZ3RoID4gMCA/IGFyZ3VtZW50c1swXSA6IHVuZGVmaW5lZCk7IH07XG59LCB7XG4gIC8vIDIzLjEuMy42IE1hcC5wcm90b3R5cGUuZ2V0KGtleSlcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoa2V5KSB7XG4gICAgdmFyIGVudHJ5ID0gc3Ryb25nLmdldEVudHJ5KHZhbGlkYXRlKHRoaXMsIE1BUCksIGtleSk7XG4gICAgcmV0dXJuIGVudHJ5ICYmIGVudHJ5LnY7XG4gIH0sXG4gIC8vIDIzLjEuMy45IE1hcC5wcm90b3R5cGUuc2V0KGtleSwgdmFsdWUpXG4gIHNldDogZnVuY3Rpb24gc2V0KGtleSwgdmFsdWUpIHtcbiAgICByZXR1cm4gc3Ryb25nLmRlZih2YWxpZGF0ZSh0aGlzLCBNQVApLCBrZXkgPT09IDAgPyAwIDoga2V5LCB2YWx1ZSk7XG4gIH1cbn0sIHN0cm9uZywgdHJ1ZSk7XG4iLCIvLyBodHRwczovL2dpdGh1Yi5jb20vRGF2aWRCcnVhbnQvTWFwLVNldC5wcm90b3R5cGUudG9KU09OXG52YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xuXG4kZXhwb3J0KCRleHBvcnQuUCArICRleHBvcnQuUiwgJ01hcCcsIHsgdG9KU09OOiByZXF1aXJlKCcuL19jb2xsZWN0aW9uLXRvLWpzb24nKSgnTWFwJykgfSk7XG4iLCIvLyBodHRwczovL3RjMzkuZ2l0aHViLmlvL3Byb3Bvc2FsLXNldG1hcC1vZmZyb20vI3NlYy1tYXAub2ZcbnJlcXVpcmUoJy4vX3NldC1jb2xsZWN0aW9uLW9mJykoJ01hcCcpO1xuIiwiLy8gaHR0cHM6Ly90YzM5LmdpdGh1Yi5pby9wcm9wb3NhbC1zZXRtYXAtb2Zmcm9tLyNzZWMtbWFwLmZyb21cbnJlcXVpcmUoJy4vX3NldC1jb2xsZWN0aW9uLWZyb20nKSgnTWFwJyk7XG4iLCJyZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi5vYmplY3QudG8tc3RyaW5nJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi5zdHJpbmcuaXRlcmF0b3InKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvd2ViLmRvbS5pdGVyYWJsZScpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczYubWFwJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNy5tYXAudG8tanNvbicpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczcubWFwLm9mJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNy5tYXAuZnJvbScpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9tb2R1bGVzL19jb3JlJykuTWFwO1xuIiwiLy8gNy4yLjIgSXNBcnJheShhcmd1bWVudClcbnZhciBjb2YgPSByZXF1aXJlKCcuL19jb2YnKTtcbm1vZHVsZS5leHBvcnRzID0gQXJyYXkuaXNBcnJheSB8fCBmdW5jdGlvbiBpc0FycmF5KGFyZykge1xuICByZXR1cm4gY29mKGFyZykgPT0gJ0FycmF5Jztcbn07XG4iLCJ2YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuL19pcy1vYmplY3QnKTtcbnZhciBpc0FycmF5ID0gcmVxdWlyZSgnLi9faXMtYXJyYXknKTtcbnZhciBTUEVDSUVTID0gcmVxdWlyZSgnLi9fd2tzJykoJ3NwZWNpZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob3JpZ2luYWwpIHtcbiAgdmFyIEM7XG4gIGlmIChpc0FycmF5KG9yaWdpbmFsKSkge1xuICAgIEMgPSBvcmlnaW5hbC5jb25zdHJ1Y3RvcjtcbiAgICAvLyBjcm9zcy1yZWFsbSBmYWxsYmFja1xuICAgIGlmICh0eXBlb2YgQyA9PSAnZnVuY3Rpb24nICYmIChDID09PSBBcnJheSB8fCBpc0FycmF5KEMucHJvdG90eXBlKSkpIEMgPSB1bmRlZmluZWQ7XG4gICAgaWYgKGlzT2JqZWN0KEMpKSB7XG4gICAgICBDID0gQ1tTUEVDSUVTXTtcbiAgICAgIGlmIChDID09PSBudWxsKSBDID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfSByZXR1cm4gQyA9PT0gdW5kZWZpbmVkID8gQXJyYXkgOiBDO1xufTtcbiIsIi8vIDkuNC4yLjMgQXJyYXlTcGVjaWVzQ3JlYXRlKG9yaWdpbmFsQXJyYXksIGxlbmd0aClcbnZhciBzcGVjaWVzQ29uc3RydWN0b3IgPSByZXF1aXJlKCcuL19hcnJheS1zcGVjaWVzLWNvbnN0cnVjdG9yJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9yaWdpbmFsLCBsZW5ndGgpIHtcbiAgcmV0dXJuIG5ldyAoc3BlY2llc0NvbnN0cnVjdG9yKG9yaWdpbmFsKSkobGVuZ3RoKTtcbn07XG4iLCIvLyAwIC0+IEFycmF5I2ZvckVhY2hcbi8vIDEgLT4gQXJyYXkjbWFwXG4vLyAyIC0+IEFycmF5I2ZpbHRlclxuLy8gMyAtPiBBcnJheSNzb21lXG4vLyA0IC0+IEFycmF5I2V2ZXJ5XG4vLyA1IC0+IEFycmF5I2ZpbmRcbi8vIDYgLT4gQXJyYXkjZmluZEluZGV4XG52YXIgY3R4ID0gcmVxdWlyZSgnLi9fY3R4Jyk7XG52YXIgSU9iamVjdCA9IHJlcXVpcmUoJy4vX2lvYmplY3QnKTtcbnZhciB0b09iamVjdCA9IHJlcXVpcmUoJy4vX3RvLW9iamVjdCcpO1xudmFyIHRvTGVuZ3RoID0gcmVxdWlyZSgnLi9fdG8tbGVuZ3RoJyk7XG52YXIgYXNjID0gcmVxdWlyZSgnLi9fYXJyYXktc3BlY2llcy1jcmVhdGUnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKFRZUEUsICRjcmVhdGUpIHtcbiAgdmFyIElTX01BUCA9IFRZUEUgPT0gMTtcbiAgdmFyIElTX0ZJTFRFUiA9IFRZUEUgPT0gMjtcbiAgdmFyIElTX1NPTUUgPSBUWVBFID09IDM7XG4gIHZhciBJU19FVkVSWSA9IFRZUEUgPT0gNDtcbiAgdmFyIElTX0ZJTkRfSU5ERVggPSBUWVBFID09IDY7XG4gIHZhciBOT19IT0xFUyA9IFRZUEUgPT0gNSB8fCBJU19GSU5EX0lOREVYO1xuICB2YXIgY3JlYXRlID0gJGNyZWF0ZSB8fCBhc2M7XG4gIHJldHVybiBmdW5jdGlvbiAoJHRoaXMsIGNhbGxiYWNrZm4sIHRoYXQpIHtcbiAgICB2YXIgTyA9IHRvT2JqZWN0KCR0aGlzKTtcbiAgICB2YXIgc2VsZiA9IElPYmplY3QoTyk7XG4gICAgdmFyIGYgPSBjdHgoY2FsbGJhY2tmbiwgdGhhdCwgMyk7XG4gICAgdmFyIGxlbmd0aCA9IHRvTGVuZ3RoKHNlbGYubGVuZ3RoKTtcbiAgICB2YXIgaW5kZXggPSAwO1xuICAgIHZhciByZXN1bHQgPSBJU19NQVAgPyBjcmVhdGUoJHRoaXMsIGxlbmd0aCkgOiBJU19GSUxURVIgPyBjcmVhdGUoJHRoaXMsIDApIDogdW5kZWZpbmVkO1xuICAgIHZhciB2YWwsIHJlcztcbiAgICBmb3IgKDtsZW5ndGggPiBpbmRleDsgaW5kZXgrKykgaWYgKE5PX0hPTEVTIHx8IGluZGV4IGluIHNlbGYpIHtcbiAgICAgIHZhbCA9IHNlbGZbaW5kZXhdO1xuICAgICAgcmVzID0gZih2YWwsIGluZGV4LCBPKTtcbiAgICAgIGlmIChUWVBFKSB7XG4gICAgICAgIGlmIChJU19NQVApIHJlc3VsdFtpbmRleF0gPSByZXM7ICAgLy8gbWFwXG4gICAgICAgIGVsc2UgaWYgKHJlcykgc3dpdGNoIChUWVBFKSB7XG4gICAgICAgICAgY2FzZSAzOiByZXR1cm4gdHJ1ZTsgICAgICAgICAgICAgLy8gc29tZVxuICAgICAgICAgIGNhc2UgNTogcmV0dXJuIHZhbDsgICAgICAgICAgICAgIC8vIGZpbmRcbiAgICAgICAgICBjYXNlIDY6IHJldHVybiBpbmRleDsgICAgICAgICAgICAvLyBmaW5kSW5kZXhcbiAgICAgICAgICBjYXNlIDI6IHJlc3VsdC5wdXNoKHZhbCk7ICAgICAgICAvLyBmaWx0ZXJcbiAgICAgICAgfSBlbHNlIGlmIChJU19FVkVSWSkgcmV0dXJuIGZhbHNlOyAvLyBldmVyeVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gSVNfRklORF9JTkRFWCA/IC0xIDogSVNfU09NRSB8fCBJU19FVkVSWSA/IElTX0VWRVJZIDogcmVzdWx0O1xuICB9O1xufTtcbiIsImV4cG9ydHMuZiA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHM7XG4iLCIndXNlIHN0cmljdCc7XG4vLyAxOS4xLjIuMSBPYmplY3QuYXNzaWduKHRhcmdldCwgc291cmNlLCAuLi4pXG52YXIgZ2V0S2V5cyA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzJyk7XG52YXIgZ09QUyA9IHJlcXVpcmUoJy4vX29iamVjdC1nb3BzJyk7XG52YXIgcElFID0gcmVxdWlyZSgnLi9fb2JqZWN0LXBpZScpO1xudmFyIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8tb2JqZWN0Jyk7XG52YXIgSU9iamVjdCA9IHJlcXVpcmUoJy4vX2lvYmplY3QnKTtcbnZhciAkYXNzaWduID0gT2JqZWN0LmFzc2lnbjtcblxuLy8gc2hvdWxkIHdvcmsgd2l0aCBzeW1ib2xzIGFuZCBzaG91bGQgaGF2ZSBkZXRlcm1pbmlzdGljIHByb3BlcnR5IG9yZGVyIChWOCBidWcpXG5tb2R1bGUuZXhwb3J0cyA9ICEkYXNzaWduIHx8IHJlcXVpcmUoJy4vX2ZhaWxzJykoZnVuY3Rpb24gKCkge1xuICB2YXIgQSA9IHt9O1xuICB2YXIgQiA9IHt9O1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW5kZWZcbiAgdmFyIFMgPSBTeW1ib2woKTtcbiAgdmFyIEsgPSAnYWJjZGVmZ2hpamtsbW5vcHFyc3QnO1xuICBBW1NdID0gNztcbiAgSy5zcGxpdCgnJykuZm9yRWFjaChmdW5jdGlvbiAoaykgeyBCW2tdID0gazsgfSk7XG4gIHJldHVybiAkYXNzaWduKHt9LCBBKVtTXSAhPSA3IHx8IE9iamVjdC5rZXlzKCRhc3NpZ24oe30sIEIpKS5qb2luKCcnKSAhPSBLO1xufSkgPyBmdW5jdGlvbiBhc3NpZ24odGFyZ2V0LCBzb3VyY2UpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICB2YXIgVCA9IHRvT2JqZWN0KHRhcmdldCk7XG4gIHZhciBhTGVuID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgdmFyIGluZGV4ID0gMTtcbiAgdmFyIGdldFN5bWJvbHMgPSBnT1BTLmY7XG4gIHZhciBpc0VudW0gPSBwSUUuZjtcbiAgd2hpbGUgKGFMZW4gPiBpbmRleCkge1xuICAgIHZhciBTID0gSU9iamVjdChhcmd1bWVudHNbaW5kZXgrK10pO1xuICAgIHZhciBrZXlzID0gZ2V0U3ltYm9scyA/IGdldEtleXMoUykuY29uY2F0KGdldFN5bWJvbHMoUykpIDogZ2V0S2V5cyhTKTtcbiAgICB2YXIgbGVuZ3RoID0ga2V5cy5sZW5ndGg7XG4gICAgdmFyIGogPSAwO1xuICAgIHZhciBrZXk7XG4gICAgd2hpbGUgKGxlbmd0aCA+IGopIGlmIChpc0VudW0uY2FsbChTLCBrZXkgPSBrZXlzW2orK10pKSBUW2tleV0gPSBTW2tleV07XG4gIH0gcmV0dXJuIFQ7XG59IDogJGFzc2lnbjtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciByZWRlZmluZUFsbCA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lLWFsbCcpO1xudmFyIGdldFdlYWsgPSByZXF1aXJlKCcuL19tZXRhJykuZ2V0V2VhaztcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4vX2FuLW9iamVjdCcpO1xudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0Jyk7XG52YXIgYW5JbnN0YW5jZSA9IHJlcXVpcmUoJy4vX2FuLWluc3RhbmNlJyk7XG52YXIgZm9yT2YgPSByZXF1aXJlKCcuL19mb3Itb2YnKTtcbnZhciBjcmVhdGVBcnJheU1ldGhvZCA9IHJlcXVpcmUoJy4vX2FycmF5LW1ldGhvZHMnKTtcbnZhciAkaGFzID0gcmVxdWlyZSgnLi9faGFzJyk7XG52YXIgdmFsaWRhdGUgPSByZXF1aXJlKCcuL192YWxpZGF0ZS1jb2xsZWN0aW9uJyk7XG52YXIgYXJyYXlGaW5kID0gY3JlYXRlQXJyYXlNZXRob2QoNSk7XG52YXIgYXJyYXlGaW5kSW5kZXggPSBjcmVhdGVBcnJheU1ldGhvZCg2KTtcbnZhciBpZCA9IDA7XG5cbi8vIGZhbGxiYWNrIGZvciB1bmNhdWdodCBmcm96ZW4ga2V5c1xudmFyIHVuY2F1Z2h0RnJvemVuU3RvcmUgPSBmdW5jdGlvbiAodGhhdCkge1xuICByZXR1cm4gdGhhdC5fbCB8fCAodGhhdC5fbCA9IG5ldyBVbmNhdWdodEZyb3plblN0b3JlKCkpO1xufTtcbnZhciBVbmNhdWdodEZyb3plblN0b3JlID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLmEgPSBbXTtcbn07XG52YXIgZmluZFVuY2F1Z2h0RnJvemVuID0gZnVuY3Rpb24gKHN0b3JlLCBrZXkpIHtcbiAgcmV0dXJuIGFycmF5RmluZChzdG9yZS5hLCBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gaXRbMF0gPT09IGtleTtcbiAgfSk7XG59O1xuVW5jYXVnaHRGcm96ZW5TdG9yZS5wcm90b3R5cGUgPSB7XG4gIGdldDogZnVuY3Rpb24gKGtleSkge1xuICAgIHZhciBlbnRyeSA9IGZpbmRVbmNhdWdodEZyb3plbih0aGlzLCBrZXkpO1xuICAgIGlmIChlbnRyeSkgcmV0dXJuIGVudHJ5WzFdO1xuICB9LFxuICBoYXM6IGZ1bmN0aW9uIChrZXkpIHtcbiAgICByZXR1cm4gISFmaW5kVW5jYXVnaHRGcm96ZW4odGhpcywga2V5KTtcbiAgfSxcbiAgc2V0OiBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgIHZhciBlbnRyeSA9IGZpbmRVbmNhdWdodEZyb3plbih0aGlzLCBrZXkpO1xuICAgIGlmIChlbnRyeSkgZW50cnlbMV0gPSB2YWx1ZTtcbiAgICBlbHNlIHRoaXMuYS5wdXNoKFtrZXksIHZhbHVlXSk7XG4gIH0sXG4gICdkZWxldGUnOiBmdW5jdGlvbiAoa2V5KSB7XG4gICAgdmFyIGluZGV4ID0gYXJyYXlGaW5kSW5kZXgodGhpcy5hLCBmdW5jdGlvbiAoaXQpIHtcbiAgICAgIHJldHVybiBpdFswXSA9PT0ga2V5O1xuICAgIH0pO1xuICAgIGlmICh+aW5kZXgpIHRoaXMuYS5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIHJldHVybiAhIX5pbmRleDtcbiAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGdldENvbnN0cnVjdG9yOiBmdW5jdGlvbiAod3JhcHBlciwgTkFNRSwgSVNfTUFQLCBBRERFUikge1xuICAgIHZhciBDID0gd3JhcHBlcihmdW5jdGlvbiAodGhhdCwgaXRlcmFibGUpIHtcbiAgICAgIGFuSW5zdGFuY2UodGhhdCwgQywgTkFNRSwgJ19pJyk7XG4gICAgICB0aGF0Ll90ID0gTkFNRTsgICAgICAvLyBjb2xsZWN0aW9uIHR5cGVcbiAgICAgIHRoYXQuX2kgPSBpZCsrOyAgICAgIC8vIGNvbGxlY3Rpb24gaWRcbiAgICAgIHRoYXQuX2wgPSB1bmRlZmluZWQ7IC8vIGxlYWsgc3RvcmUgZm9yIHVuY2F1Z2h0IGZyb3plbiBvYmplY3RzXG4gICAgICBpZiAoaXRlcmFibGUgIT0gdW5kZWZpbmVkKSBmb3JPZihpdGVyYWJsZSwgSVNfTUFQLCB0aGF0W0FEREVSXSwgdGhhdCk7XG4gICAgfSk7XG4gICAgcmVkZWZpbmVBbGwoQy5wcm90b3R5cGUsIHtcbiAgICAgIC8vIDIzLjMuMy4yIFdlYWtNYXAucHJvdG90eXBlLmRlbGV0ZShrZXkpXG4gICAgICAvLyAyMy40LjMuMyBXZWFrU2V0LnByb3RvdHlwZS5kZWxldGUodmFsdWUpXG4gICAgICAnZGVsZXRlJzogZnVuY3Rpb24gKGtleSkge1xuICAgICAgICBpZiAoIWlzT2JqZWN0KGtleSkpIHJldHVybiBmYWxzZTtcbiAgICAgICAgdmFyIGRhdGEgPSBnZXRXZWFrKGtleSk7XG4gICAgICAgIGlmIChkYXRhID09PSB0cnVlKSByZXR1cm4gdW5jYXVnaHRGcm96ZW5TdG9yZSh2YWxpZGF0ZSh0aGlzLCBOQU1FKSlbJ2RlbGV0ZSddKGtleSk7XG4gICAgICAgIHJldHVybiBkYXRhICYmICRoYXMoZGF0YSwgdGhpcy5faSkgJiYgZGVsZXRlIGRhdGFbdGhpcy5faV07XG4gICAgICB9LFxuICAgICAgLy8gMjMuMy4zLjQgV2Vha01hcC5wcm90b3R5cGUuaGFzKGtleSlcbiAgICAgIC8vIDIzLjQuMy40IFdlYWtTZXQucHJvdG90eXBlLmhhcyh2YWx1ZSlcbiAgICAgIGhhczogZnVuY3Rpb24gaGFzKGtleSkge1xuICAgICAgICBpZiAoIWlzT2JqZWN0KGtleSkpIHJldHVybiBmYWxzZTtcbiAgICAgICAgdmFyIGRhdGEgPSBnZXRXZWFrKGtleSk7XG4gICAgICAgIGlmIChkYXRhID09PSB0cnVlKSByZXR1cm4gdW5jYXVnaHRGcm96ZW5TdG9yZSh2YWxpZGF0ZSh0aGlzLCBOQU1FKSkuaGFzKGtleSk7XG4gICAgICAgIHJldHVybiBkYXRhICYmICRoYXMoZGF0YSwgdGhpcy5faSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIEM7XG4gIH0sXG4gIGRlZjogZnVuY3Rpb24gKHRoYXQsIGtleSwgdmFsdWUpIHtcbiAgICB2YXIgZGF0YSA9IGdldFdlYWsoYW5PYmplY3Qoa2V5KSwgdHJ1ZSk7XG4gICAgaWYgKGRhdGEgPT09IHRydWUpIHVuY2F1Z2h0RnJvemVuU3RvcmUodGhhdCkuc2V0KGtleSwgdmFsdWUpO1xuICAgIGVsc2UgZGF0YVt0aGF0Ll9pXSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGF0O1xuICB9LFxuICB1ZnN0b3JlOiB1bmNhdWdodEZyb3plblN0b3JlXG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGVhY2ggPSByZXF1aXJlKCcuL19hcnJheS1tZXRob2RzJykoMCk7XG52YXIgcmVkZWZpbmUgPSByZXF1aXJlKCcuL19yZWRlZmluZScpO1xudmFyIG1ldGEgPSByZXF1aXJlKCcuL19tZXRhJyk7XG52YXIgYXNzaWduID0gcmVxdWlyZSgnLi9fb2JqZWN0LWFzc2lnbicpO1xudmFyIHdlYWsgPSByZXF1aXJlKCcuL19jb2xsZWN0aW9uLXdlYWsnKTtcbnZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpO1xudmFyIGZhaWxzID0gcmVxdWlyZSgnLi9fZmFpbHMnKTtcbnZhciB2YWxpZGF0ZSA9IHJlcXVpcmUoJy4vX3ZhbGlkYXRlLWNvbGxlY3Rpb24nKTtcbnZhciBXRUFLX01BUCA9ICdXZWFrTWFwJztcbnZhciBnZXRXZWFrID0gbWV0YS5nZXRXZWFrO1xudmFyIGlzRXh0ZW5zaWJsZSA9IE9iamVjdC5pc0V4dGVuc2libGU7XG52YXIgdW5jYXVnaHRGcm96ZW5TdG9yZSA9IHdlYWsudWZzdG9yZTtcbnZhciB0bXAgPSB7fTtcbnZhciBJbnRlcm5hbE1hcDtcblxudmFyIHdyYXBwZXIgPSBmdW5jdGlvbiAoZ2V0KSB7XG4gIHJldHVybiBmdW5jdGlvbiBXZWFrTWFwKCkge1xuICAgIHJldHVybiBnZXQodGhpcywgYXJndW1lbnRzLmxlbmd0aCA+IDAgPyBhcmd1bWVudHNbMF0gOiB1bmRlZmluZWQpO1xuICB9O1xufTtcblxudmFyIG1ldGhvZHMgPSB7XG4gIC8vIDIzLjMuMy4zIFdlYWtNYXAucHJvdG90eXBlLmdldChrZXkpXG4gIGdldDogZnVuY3Rpb24gZ2V0KGtleSkge1xuICAgIGlmIChpc09iamVjdChrZXkpKSB7XG4gICAgICB2YXIgZGF0YSA9IGdldFdlYWsoa2V5KTtcbiAgICAgIGlmIChkYXRhID09PSB0cnVlKSByZXR1cm4gdW5jYXVnaHRGcm96ZW5TdG9yZSh2YWxpZGF0ZSh0aGlzLCBXRUFLX01BUCkpLmdldChrZXkpO1xuICAgICAgcmV0dXJuIGRhdGEgPyBkYXRhW3RoaXMuX2ldIDogdW5kZWZpbmVkO1xuICAgIH1cbiAgfSxcbiAgLy8gMjMuMy4zLjUgV2Vha01hcC5wcm90b3R5cGUuc2V0KGtleSwgdmFsdWUpXG4gIHNldDogZnVuY3Rpb24gc2V0KGtleSwgdmFsdWUpIHtcbiAgICByZXR1cm4gd2Vhay5kZWYodmFsaWRhdGUodGhpcywgV0VBS19NQVApLCBrZXksIHZhbHVlKTtcbiAgfVxufTtcblxuLy8gMjMuMyBXZWFrTWFwIE9iamVjdHNcbnZhciAkV2Vha01hcCA9IG1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fY29sbGVjdGlvbicpKFdFQUtfTUFQLCB3cmFwcGVyLCBtZXRob2RzLCB3ZWFrLCB0cnVlLCB0cnVlKTtcblxuLy8gSUUxMSBXZWFrTWFwIGZyb3plbiBrZXlzIGZpeFxuaWYgKGZhaWxzKGZ1bmN0aW9uICgpIHsgcmV0dXJuIG5ldyAkV2Vha01hcCgpLnNldCgoT2JqZWN0LmZyZWV6ZSB8fCBPYmplY3QpKHRtcCksIDcpLmdldCh0bXApICE9IDc7IH0pKSB7XG4gIEludGVybmFsTWFwID0gd2Vhay5nZXRDb25zdHJ1Y3Rvcih3cmFwcGVyLCBXRUFLX01BUCk7XG4gIGFzc2lnbihJbnRlcm5hbE1hcC5wcm90b3R5cGUsIG1ldGhvZHMpO1xuICBtZXRhLk5FRUQgPSB0cnVlO1xuICBlYWNoKFsnZGVsZXRlJywgJ2hhcycsICdnZXQnLCAnc2V0J10sIGZ1bmN0aW9uIChrZXkpIHtcbiAgICB2YXIgcHJvdG8gPSAkV2Vha01hcC5wcm90b3R5cGU7XG4gICAgdmFyIG1ldGhvZCA9IHByb3RvW2tleV07XG4gICAgcmVkZWZpbmUocHJvdG8sIGtleSwgZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgIC8vIHN0b3JlIGZyb3plbiBvYmplY3RzIG9uIGludGVybmFsIHdlYWttYXAgc2hpbVxuICAgICAgaWYgKGlzT2JqZWN0KGEpICYmICFpc0V4dGVuc2libGUoYSkpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9mKSB0aGlzLl9mID0gbmV3IEludGVybmFsTWFwKCk7XG4gICAgICAgIHZhciByZXN1bHQgPSB0aGlzLl9mW2tleV0oYSwgYik7XG4gICAgICAgIHJldHVybiBrZXkgPT0gJ3NldCcgPyB0aGlzIDogcmVzdWx0O1xuICAgICAgLy8gc3RvcmUgYWxsIHRoZSByZXN0IG9uIG5hdGl2ZSB3ZWFrbWFwXG4gICAgICB9IHJldHVybiBtZXRob2QuY2FsbCh0aGlzLCBhLCBiKTtcbiAgICB9KTtcbiAgfSk7XG59XG4iLCIvLyBodHRwczovL3RjMzkuZ2l0aHViLmlvL3Byb3Bvc2FsLXNldG1hcC1vZmZyb20vI3NlYy13ZWFrbWFwLm9mXG5yZXF1aXJlKCcuL19zZXQtY29sbGVjdGlvbi1vZicpKCdXZWFrTWFwJyk7XG4iLCIvLyBodHRwczovL3RjMzkuZ2l0aHViLmlvL3Byb3Bvc2FsLXNldG1hcC1vZmZyb20vI3NlYy13ZWFrbWFwLmZyb21cbnJlcXVpcmUoJy4vX3NldC1jb2xsZWN0aW9uLWZyb20nKSgnV2Vha01hcCcpO1xuIiwicmVxdWlyZSgnLi4vbW9kdWxlcy9lczYub2JqZWN0LnRvLXN0cmluZycpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy93ZWIuZG9tLml0ZXJhYmxlJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi53ZWFrLW1hcCcpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczcud2Vhay1tYXAub2YnKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvZXM3LndlYWstbWFwLmZyb20nKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vbW9kdWxlcy9fY29yZScpLldlYWtNYXA7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgJGRlZmluZVByb3BlcnR5ID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJyk7XG52YXIgY3JlYXRlRGVzYyA9IHJlcXVpcmUoJy4vX3Byb3BlcnR5LWRlc2MnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqZWN0LCBpbmRleCwgdmFsdWUpIHtcbiAgaWYgKGluZGV4IGluIG9iamVjdCkgJGRlZmluZVByb3BlcnR5LmYob2JqZWN0LCBpbmRleCwgY3JlYXRlRGVzYygwLCB2YWx1ZSkpO1xuICBlbHNlIG9iamVjdFtpbmRleF0gPSB2YWx1ZTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgY3R4ID0gcmVxdWlyZSgnLi9fY3R4Jyk7XG52YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xudmFyIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8tb2JqZWN0Jyk7XG52YXIgY2FsbCA9IHJlcXVpcmUoJy4vX2l0ZXItY2FsbCcpO1xudmFyIGlzQXJyYXlJdGVyID0gcmVxdWlyZSgnLi9faXMtYXJyYXktaXRlcicpO1xudmFyIHRvTGVuZ3RoID0gcmVxdWlyZSgnLi9fdG8tbGVuZ3RoJyk7XG52YXIgY3JlYXRlUHJvcGVydHkgPSByZXF1aXJlKCcuL19jcmVhdGUtcHJvcGVydHknKTtcbnZhciBnZXRJdGVyRm4gPSByZXF1aXJlKCcuL2NvcmUuZ2V0LWl0ZXJhdG9yLW1ldGhvZCcpO1xuXG4kZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiAqICFyZXF1aXJlKCcuL19pdGVyLWRldGVjdCcpKGZ1bmN0aW9uIChpdGVyKSB7IEFycmF5LmZyb20oaXRlcik7IH0pLCAnQXJyYXknLCB7XG4gIC8vIDIyLjEuMi4xIEFycmF5LmZyb20oYXJyYXlMaWtlLCBtYXBmbiA9IHVuZGVmaW5lZCwgdGhpc0FyZyA9IHVuZGVmaW5lZClcbiAgZnJvbTogZnVuY3Rpb24gZnJvbShhcnJheUxpa2UgLyogLCBtYXBmbiA9IHVuZGVmaW5lZCwgdGhpc0FyZyA9IHVuZGVmaW5lZCAqLykge1xuICAgIHZhciBPID0gdG9PYmplY3QoYXJyYXlMaWtlKTtcbiAgICB2YXIgQyA9IHR5cGVvZiB0aGlzID09ICdmdW5jdGlvbicgPyB0aGlzIDogQXJyYXk7XG4gICAgdmFyIGFMZW4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgIHZhciBtYXBmbiA9IGFMZW4gPiAxID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkO1xuICAgIHZhciBtYXBwaW5nID0gbWFwZm4gIT09IHVuZGVmaW5lZDtcbiAgICB2YXIgaW5kZXggPSAwO1xuICAgIHZhciBpdGVyRm4gPSBnZXRJdGVyRm4oTyk7XG4gICAgdmFyIGxlbmd0aCwgcmVzdWx0LCBzdGVwLCBpdGVyYXRvcjtcbiAgICBpZiAobWFwcGluZykgbWFwZm4gPSBjdHgobWFwZm4sIGFMZW4gPiAyID8gYXJndW1lbnRzWzJdIDogdW5kZWZpbmVkLCAyKTtcbiAgICAvLyBpZiBvYmplY3QgaXNuJ3QgaXRlcmFibGUgb3IgaXQncyBhcnJheSB3aXRoIGRlZmF1bHQgaXRlcmF0b3IgLSB1c2Ugc2ltcGxlIGNhc2VcbiAgICBpZiAoaXRlckZuICE9IHVuZGVmaW5lZCAmJiAhKEMgPT0gQXJyYXkgJiYgaXNBcnJheUl0ZXIoaXRlckZuKSkpIHtcbiAgICAgIGZvciAoaXRlcmF0b3IgPSBpdGVyRm4uY2FsbChPKSwgcmVzdWx0ID0gbmV3IEMoKTsgIShzdGVwID0gaXRlcmF0b3IubmV4dCgpKS5kb25lOyBpbmRleCsrKSB7XG4gICAgICAgIGNyZWF0ZVByb3BlcnR5KHJlc3VsdCwgaW5kZXgsIG1hcHBpbmcgPyBjYWxsKGl0ZXJhdG9yLCBtYXBmbiwgW3N0ZXAudmFsdWUsIGluZGV4XSwgdHJ1ZSkgOiBzdGVwLnZhbHVlKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbGVuZ3RoID0gdG9MZW5ndGgoTy5sZW5ndGgpO1xuICAgICAgZm9yIChyZXN1bHQgPSBuZXcgQyhsZW5ndGgpOyBsZW5ndGggPiBpbmRleDsgaW5kZXgrKykge1xuICAgICAgICBjcmVhdGVQcm9wZXJ0eShyZXN1bHQsIGluZGV4LCBtYXBwaW5nID8gbWFwZm4oT1tpbmRleF0sIGluZGV4KSA6IE9baW5kZXhdKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmVzdWx0Lmxlbmd0aCA9IGluZGV4O1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn0pO1xuIiwicmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczYuc3RyaW5nLml0ZXJhdG9yJyk7XG5yZXF1aXJlKCcuLi8uLi9tb2R1bGVzL2VzNi5hcnJheS5mcm9tJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKS5BcnJheS5mcm9tO1xuIiwiY29uc3QgcmVzZXJ2ZWRUYWdMaXN0ID0gbmV3IFNldChbXG4gICdhbm5vdGF0aW9uLXhtbCcsXG4gICdjb2xvci1wcm9maWxlJyxcbiAgJ2ZvbnQtZmFjZScsXG4gICdmb250LWZhY2Utc3JjJyxcbiAgJ2ZvbnQtZmFjZS11cmknLFxuICAnZm9udC1mYWNlLWZvcm1hdCcsXG4gICdmb250LWZhY2UtbmFtZScsXG4gICdtaXNzaW5nLWdseXBoJyxcbl0pO1xuXG4vKipcbiAqIEBwYXJhbSB7c3RyaW5nfSBsb2NhbE5hbWVcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZEN1c3RvbUVsZW1lbnROYW1lKGxvY2FsTmFtZSkge1xuICBjb25zdCByZXNlcnZlZCA9IHJlc2VydmVkVGFnTGlzdC5oYXMobG9jYWxOYW1lKTtcbiAgY29uc3QgdmFsaWRGb3JtID0gL15bYS16XVsuMC05X2Etel0qLVtcXC0uMC05X2Etel0qJC8udGVzdChsb2NhbE5hbWUpO1xuICByZXR1cm4gIXJlc2VydmVkICYmIHZhbGlkRm9ybTtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHshTm9kZX0gbm9kZVxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQ29ubmVjdGVkKG5vZGUpIHtcbiAgLy8gVXNlIGBOb2RlI2lzQ29ubmVjdGVkYCwgaWYgZGVmaW5lZC5cbiAgY29uc3QgbmF0aXZlVmFsdWUgPSBub2RlLmlzQ29ubmVjdGVkO1xuICBpZiAobmF0aXZlVmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBuYXRpdmVWYWx1ZTtcbiAgfVxuXG4gIC8qKiBAdHlwZSB7P05vZGV8dW5kZWZpbmVkfSAqL1xuICBsZXQgY3VycmVudCA9IG5vZGU7XG4gIHdoaWxlIChjdXJyZW50ICYmICEoY3VycmVudC5fX0NFX2lzSW1wb3J0RG9jdW1lbnQgfHwgY3VycmVudCBpbnN0YW5jZW9mIERvY3VtZW50KSkge1xuICAgIGN1cnJlbnQgPSBjdXJyZW50LnBhcmVudE5vZGUgfHwgKHdpbmRvdy5TaGFkb3dSb290ICYmIGN1cnJlbnQgaW5zdGFuY2VvZiBTaGFkb3dSb290ID8gY3VycmVudC5ob3N0IDogdW5kZWZpbmVkKTtcbiAgfVxuICByZXR1cm4gISEoY3VycmVudCAmJiAoY3VycmVudC5fX0NFX2lzSW1wb3J0RG9jdW1lbnQgfHwgY3VycmVudCBpbnN0YW5jZW9mIERvY3VtZW50KSk7XG59XG5cbi8qKlxuICogQHBhcmFtIHshTm9kZX0gcm9vdFxuICogQHBhcmFtIHshTm9kZX0gc3RhcnRcbiAqIEByZXR1cm4gez9Ob2RlfVxuICovXG5mdW5jdGlvbiBuZXh0U2libGluZ09yQW5jZXN0b3JTaWJsaW5nKHJvb3QsIHN0YXJ0KSB7XG4gIGxldCBub2RlID0gc3RhcnQ7XG4gIHdoaWxlIChub2RlICYmIG5vZGUgIT09IHJvb3QgJiYgIW5vZGUubmV4dFNpYmxpbmcpIHtcbiAgICBub2RlID0gbm9kZS5wYXJlbnROb2RlO1xuICB9XG4gIHJldHVybiAoIW5vZGUgfHwgbm9kZSA9PT0gcm9vdCkgPyBudWxsIDogbm9kZS5uZXh0U2libGluZztcbn1cblxuLyoqXG4gKiBAcGFyYW0geyFOb2RlfSByb290XG4gKiBAcGFyYW0geyFOb2RlfSBzdGFydFxuICogQHJldHVybiB7P05vZGV9XG4gKi9cbmZ1bmN0aW9uIG5leHROb2RlKHJvb3QsIHN0YXJ0KSB7XG4gIHJldHVybiBzdGFydC5maXJzdENoaWxkID8gc3RhcnQuZmlyc3RDaGlsZCA6IG5leHRTaWJsaW5nT3JBbmNlc3RvclNpYmxpbmcocm9vdCwgc3RhcnQpO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7IU5vZGV9IHJvb3RcbiAqIEBwYXJhbSB7IWZ1bmN0aW9uKCFFbGVtZW50KX0gY2FsbGJhY2tcbiAqIEBwYXJhbSB7IVNldDxOb2RlPj19IHZpc2l0ZWRJbXBvcnRzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3YWxrRGVlcERlc2NlbmRhbnRFbGVtZW50cyhyb290LCBjYWxsYmFjaywgdmlzaXRlZEltcG9ydHMgPSBuZXcgU2V0KCkpIHtcbiAgbGV0IG5vZGUgPSByb290O1xuICB3aGlsZSAobm9kZSkge1xuICAgIGlmIChub2RlLm5vZGVUeXBlID09PSBOb2RlLkVMRU1FTlRfTk9ERSkge1xuICAgICAgY29uc3QgZWxlbWVudCA9IC8qKiBAdHlwZSB7IUVsZW1lbnR9ICovKG5vZGUpO1xuXG4gICAgICBjYWxsYmFjayhlbGVtZW50KTtcblxuICAgICAgY29uc3QgbG9jYWxOYW1lID0gZWxlbWVudC5sb2NhbE5hbWU7XG4gICAgICBpZiAobG9jYWxOYW1lID09PSAnbGluaycgJiYgZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3JlbCcpID09PSAnaW1wb3J0Jykge1xuICAgICAgICAvLyBJZiB0aGlzIGltcG9ydCAocG9seWZpbGxlZCBvciBub3QpIGhhcyBpdCdzIHJvb3Qgbm9kZSBhdmFpbGFibGUsXG4gICAgICAgIC8vIHdhbGsgaXQuXG4gICAgICAgIGNvbnN0IGltcG9ydE5vZGUgPSAvKiogQHR5cGUgeyFOb2RlfSAqLyAoZWxlbWVudC5pbXBvcnQpO1xuICAgICAgICBpZiAoaW1wb3J0Tm9kZSBpbnN0YW5jZW9mIE5vZGUgJiYgIXZpc2l0ZWRJbXBvcnRzLmhhcyhpbXBvcnROb2RlKSkge1xuICAgICAgICAgIC8vIFByZXZlbnQgbXVsdGlwbGUgd2Fsa3Mgb2YgdGhlIHNhbWUgaW1wb3J0IHJvb3QuXG4gICAgICAgICAgdmlzaXRlZEltcG9ydHMuYWRkKGltcG9ydE5vZGUpO1xuXG4gICAgICAgICAgZm9yIChsZXQgY2hpbGQgPSBpbXBvcnROb2RlLmZpcnN0Q2hpbGQ7IGNoaWxkOyBjaGlsZCA9IGNoaWxkLm5leHRTaWJsaW5nKSB7XG4gICAgICAgICAgICB3YWxrRGVlcERlc2NlbmRhbnRFbGVtZW50cyhjaGlsZCwgY2FsbGJhY2ssIHZpc2l0ZWRJbXBvcnRzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZ25vcmUgZGVzY2VuZGFudHMgb2YgaW1wb3J0IGxpbmtzIHRvIHByZXZlbnQgYXR0ZW1wdGluZyB0byB3YWxrIHRoZVxuICAgICAgICAvLyBlbGVtZW50cyBjcmVhdGVkIGJ5IHRoZSBIVE1MIEltcG9ydHMgcG9seWZpbGwgdGhhdCB3ZSBqdXN0IHdhbGtlZFxuICAgICAgICAvLyBhYm92ZS5cbiAgICAgICAgbm9kZSA9IG5leHRTaWJsaW5nT3JBbmNlc3RvclNpYmxpbmcocm9vdCwgZWxlbWVudCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfSBlbHNlIGlmIChsb2NhbE5hbWUgPT09ICd0ZW1wbGF0ZScpIHtcbiAgICAgICAgLy8gSWdub3JlIGRlc2NlbmRhbnRzIG9mIHRlbXBsYXRlcy4gVGhlcmUgc2hvdWxkbid0IGJlIGFueSBkZXNjZW5kYW50c1xuICAgICAgICAvLyBiZWNhdXNlIHRoZXkgd2lsbCBiZSBtb3ZlZCBpbnRvIGAuY29udGVudGAgZHVyaW5nIGNvbnN0cnVjdGlvbiBpblxuICAgICAgICAvLyBicm93c2VycyB0aGF0IHN1cHBvcnQgdGVtcGxhdGUgYnV0LCBpbiBjYXNlIHRoZXkgZXhpc3QgYW5kIGFyZSBzdGlsbFxuICAgICAgICAvLyB3YWl0aW5nIHRvIGJlIG1vdmVkIGJ5IGEgcG9seWZpbGwsIHRoZXkgd2lsbCBiZSBpZ25vcmVkLlxuICAgICAgICBub2RlID0gbmV4dFNpYmxpbmdPckFuY2VzdG9yU2libGluZyhyb290LCBlbGVtZW50KTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIFdhbGsgc2hhZG93IHJvb3RzLlxuICAgICAgY29uc3Qgc2hhZG93Um9vdCA9IGVsZW1lbnQuX19DRV9zaGFkb3dSb290O1xuICAgICAgaWYgKHNoYWRvd1Jvb3QpIHtcbiAgICAgICAgZm9yIChsZXQgY2hpbGQgPSBzaGFkb3dSb290LmZpcnN0Q2hpbGQ7IGNoaWxkOyBjaGlsZCA9IGNoaWxkLm5leHRTaWJsaW5nKSB7XG4gICAgICAgICAgd2Fsa0RlZXBEZXNjZW5kYW50RWxlbWVudHMoY2hpbGQsIGNhbGxiYWNrLCB2aXNpdGVkSW1wb3J0cyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBub2RlID0gbmV4dE5vZGUocm9vdCwgbm9kZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBVc2VkIHRvIHN1cHByZXNzIENsb3N1cmUncyBcIk1vZGlmeWluZyB0aGUgcHJvdG90eXBlIGlzIG9ubHkgYWxsb3dlZCBpZiB0aGVcbiAqIGNvbnN0cnVjdG9yIGlzIGluIHRoZSBzYW1lIHNjb3BlXCIgd2FybmluZyB3aXRob3V0IHVzaW5nXG4gKiBgQHN1cHByZXNzIHtuZXdDaGVja1R5cGVzLCBkdXBsaWNhdGV9YCBiZWNhdXNlIGBuZXdDaGVja1R5cGVzYCBpcyB0b28gYnJvYWQuXG4gKlxuICogQHBhcmFtIHshT2JqZWN0fSBkZXN0aW5hdGlvblxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7Kn0gdmFsdWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldFByb3BlcnR5VW5jaGVja2VkKGRlc3RpbmF0aW9uLCBuYW1lLCB2YWx1ZSkge1xuICBkZXN0aW5hdGlvbltuYW1lXSA9IHZhbHVlO1xufVxuIiwiLyoqXG4gKiBAZW51bSB7bnVtYmVyfVxuICovXG5jb25zdCBDdXN0b21FbGVtZW50U3RhdGUgPSB7XG4gIGN1c3RvbTogMSxcbiAgZmFpbGVkOiAyLFxufTtcblxuZXhwb3J0IGRlZmF1bHQgQ3VzdG9tRWxlbWVudFN0YXRlO1xuIiwiaW1wb3J0ICogYXMgVXRpbGl0aWVzIGZyb20gJy4vVXRpbGl0aWVzLmpzJztcbmltcG9ydCBDRVN0YXRlIGZyb20gJy4vQ3VzdG9tRWxlbWVudFN0YXRlLmpzJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ3VzdG9tRWxlbWVudEludGVybmFscyB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIC8qKiBAdHlwZSB7IU1hcDxzdHJpbmcsICFDdXN0b21FbGVtZW50RGVmaW5pdGlvbj59ICovXG4gICAgdGhpcy5fbG9jYWxOYW1lVG9EZWZpbml0aW9uID0gbmV3IE1hcCgpO1xuXG4gICAgLyoqIEB0eXBlIHshTWFwPCFGdW5jdGlvbiwgIUN1c3RvbUVsZW1lbnREZWZpbml0aW9uPn0gKi9cbiAgICB0aGlzLl9jb25zdHJ1Y3RvclRvRGVmaW5pdGlvbiA9IG5ldyBNYXAoKTtcblxuICAgIC8qKiBAdHlwZSB7IUFycmF5PCFmdW5jdGlvbighTm9kZSk+fSAqL1xuICAgIHRoaXMuX3BhdGNoZXMgPSBbXTtcblxuICAgIC8qKiBAdHlwZSB7Ym9vbGVhbn0gKi9cbiAgICB0aGlzLl9oYXNQYXRjaGVzID0gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IGxvY2FsTmFtZVxuICAgKiBAcGFyYW0geyFDdXN0b21FbGVtZW50RGVmaW5pdGlvbn0gZGVmaW5pdGlvblxuICAgKi9cbiAgc2V0RGVmaW5pdGlvbihsb2NhbE5hbWUsIGRlZmluaXRpb24pIHtcbiAgICB0aGlzLl9sb2NhbE5hbWVUb0RlZmluaXRpb24uc2V0KGxvY2FsTmFtZSwgZGVmaW5pdGlvbik7XG4gICAgdGhpcy5fY29uc3RydWN0b3JUb0RlZmluaXRpb24uc2V0KGRlZmluaXRpb24uY29uc3RydWN0b3IsIGRlZmluaXRpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBsb2NhbE5hbWVcbiAgICogQHJldHVybiB7IUN1c3RvbUVsZW1lbnREZWZpbml0aW9ufHVuZGVmaW5lZH1cbiAgICovXG4gIGxvY2FsTmFtZVRvRGVmaW5pdGlvbihsb2NhbE5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5fbG9jYWxOYW1lVG9EZWZpbml0aW9uLmdldChsb2NhbE5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBjb25zdHJ1Y3RvclxuICAgKiBAcmV0dXJuIHshQ3VzdG9tRWxlbWVudERlZmluaXRpb258dW5kZWZpbmVkfVxuICAgKi9cbiAgY29uc3RydWN0b3JUb0RlZmluaXRpb24oY29uc3RydWN0b3IpIHtcbiAgICByZXR1cm4gdGhpcy5fY29uc3RydWN0b3JUb0RlZmluaXRpb24uZ2V0KGNvbnN0cnVjdG9yKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0geyFmdW5jdGlvbighTm9kZSl9IGxpc3RlbmVyXG4gICAqL1xuICBhZGRQYXRjaChsaXN0ZW5lcikge1xuICAgIHRoaXMuX2hhc1BhdGNoZXMgPSB0cnVlO1xuICAgIHRoaXMuX3BhdGNoZXMucHVzaChsaXN0ZW5lcik7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHshTm9kZX0gbm9kZVxuICAgKi9cbiAgcGF0Y2hUcmVlKG5vZGUpIHtcbiAgICBpZiAoIXRoaXMuX2hhc1BhdGNoZXMpIHJldHVybjtcblxuICAgIFV0aWxpdGllcy53YWxrRGVlcERlc2NlbmRhbnRFbGVtZW50cyhub2RlLCBlbGVtZW50ID0+IHRoaXMucGF0Y2goZWxlbWVudCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IU5vZGV9IG5vZGVcbiAgICovXG4gIHBhdGNoKG5vZGUpIHtcbiAgICBpZiAoIXRoaXMuX2hhc1BhdGNoZXMpIHJldHVybjtcblxuICAgIGlmIChub2RlLl9fQ0VfcGF0Y2hlZCkgcmV0dXJuO1xuICAgIG5vZGUuX19DRV9wYXRjaGVkID0gdHJ1ZTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5fcGF0Y2hlcy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5fcGF0Y2hlc1tpXShub2RlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHshTm9kZX0gcm9vdFxuICAgKi9cbiAgY29ubmVjdFRyZWUocm9vdCkge1xuICAgIGNvbnN0IGVsZW1lbnRzID0gW107XG5cbiAgICBVdGlsaXRpZXMud2Fsa0RlZXBEZXNjZW5kYW50RWxlbWVudHMocm9vdCwgZWxlbWVudCA9PiBlbGVtZW50cy5wdXNoKGVsZW1lbnQpKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZWxlbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSBlbGVtZW50c1tpXTtcbiAgICAgIGlmIChlbGVtZW50Ll9fQ0Vfc3RhdGUgPT09IENFU3RhdGUuY3VzdG9tKSB7XG4gICAgICAgIGlmIChVdGlsaXRpZXMuaXNDb25uZWN0ZWQoZWxlbWVudCkpIHtcbiAgICAgICAgICB0aGlzLmNvbm5lY3RlZENhbGxiYWNrKGVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnVwZ3JhZGVFbGVtZW50KGVsZW1lbnQpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0geyFOb2RlfSByb290XG4gICAqL1xuICBkaXNjb25uZWN0VHJlZShyb290KSB7XG4gICAgY29uc3QgZWxlbWVudHMgPSBbXTtcblxuICAgIFV0aWxpdGllcy53YWxrRGVlcERlc2NlbmRhbnRFbGVtZW50cyhyb290LCBlbGVtZW50ID0+IGVsZW1lbnRzLnB1c2goZWxlbWVudCkpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBlbGVtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgZWxlbWVudCA9IGVsZW1lbnRzW2ldO1xuICAgICAgaWYgKGVsZW1lbnQuX19DRV9zdGF0ZSA9PT0gQ0VTdGF0ZS5jdXN0b20pIHtcbiAgICAgICAgdGhpcy5kaXNjb25uZWN0ZWRDYWxsYmFjayhlbGVtZW50KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVXBncmFkZXMgYWxsIHVuY3VzdG9taXplZCBjdXN0b20gZWxlbWVudHMgYXQgYW5kIGJlbG93IGEgcm9vdCBub2RlIGZvclxuICAgKiB3aGljaCB0aGVyZSBpcyBhIGRlZmluaXRpb24uIFdoZW4gY3VzdG9tIGVsZW1lbnQgcmVhY3Rpb24gY2FsbGJhY2tzIGFyZVxuICAgKiBhc3N1bWVkIHRvIGJlIGNhbGxlZCBzeW5jaHJvbm91c2x5ICh3aGljaCwgYnkgdGhlIGN1cnJlbnQgRE9NIC8gSFRNTCBzcGVjXG4gICAqIGRlZmluaXRpb25zLCB0aGV5IGFyZSAqbm90KiksIGNhbGxiYWNrcyBmb3IgYm90aCBlbGVtZW50cyBjdXN0b21pemVkXG4gICAqIHN5bmNocm9ub3VzbHkgYnkgdGhlIHBhcnNlciBhbmQgZWxlbWVudHMgYmVpbmcgdXBncmFkZWQgb2NjdXIgaW4gdGhlIHNhbWVcbiAgICogcmVsYXRpdmUgb3JkZXIuXG4gICAqXG4gICAqIE5PVEU6IFRoaXMgZnVuY3Rpb24sIHdoZW4gdXNlZCB0byBzaW11bGF0ZSB0aGUgY29uc3RydWN0aW9uIG9mIGEgdHJlZSB0aGF0XG4gICAqIGlzIGFscmVhZHkgY3JlYXRlZCBidXQgbm90IGN1c3RvbWl6ZWQgKGkuZS4gYnkgdGhlIHBhcnNlciksIGRvZXMgKm5vdCpcbiAgICogcHJldmVudCB0aGUgZWxlbWVudCBmcm9tIHJlYWRpbmcgdGhlICdmaW5hbCcgKHRydWUpIHN0YXRlIG9mIHRoZSB0cmVlLiBGb3JcbiAgICogZXhhbXBsZSwgdGhlIGVsZW1lbnQsIGR1cmluZyB0cnVseSBzeW5jaHJvbm91cyBwYXJzaW5nIC8gY29uc3RydWN0aW9uIHdvdWxkXG4gICAqIHNlZSB0aGF0IGl0IGNvbnRhaW5zIG5vIGNoaWxkcmVuIGFzIHRoZXkgaGF2ZSBub3QgeWV0IGJlZW4gaW5zZXJ0ZWQuXG4gICAqIEhvd2V2ZXIsIHRoaXMgZnVuY3Rpb24gZG9lcyBub3QgbW9kaWZ5IHRoZSB0cmVlLCB0aGUgZWxlbWVudCB3aWxsXG4gICAqIChpbmNvcnJlY3RseSkgaGF2ZSBjaGlsZHJlbi4gQWRkaXRpb25hbGx5LCBzZWxmLW1vZGlmaWNhdGlvbiByZXN0cmljdGlvbnNcbiAgICogZm9yIGN1c3RvbSBlbGVtZW50IGNvbnN0cnVjdG9ycyBpbXBvc2VkIGJ5IHRoZSBET00gc3BlYyBhcmUgKm5vdCogZW5mb3JjZWQuXG4gICAqXG4gICAqXG4gICAqIFRoZSBmb2xsb3dpbmcgbmVzdGVkIGxpc3Qgc2hvd3MgdGhlIHN0ZXBzIGV4dGVuZGluZyBkb3duIGZyb20gdGhlIEhUTUxcbiAgICogc3BlYydzIHBhcnNpbmcgc2VjdGlvbiB0aGF0IGNhdXNlIGVsZW1lbnRzIHRvIGJlIHN5bmNocm9ub3VzbHkgY3JlYXRlZCBhbmRcbiAgICogdXBncmFkZWQ6XG4gICAqXG4gICAqIFRoZSBcImluIGJvZHlcIiBpbnNlcnRpb24gbW9kZTpcbiAgICogaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2Uvc3ludGF4Lmh0bWwjcGFyc2luZy1tYWluLWluYm9keVxuICAgKiAtIFN3aXRjaCBvbiB0b2tlbjpcbiAgICogICAuLiBvdGhlciBjYXNlcyAuLlxuICAgKiAgIC0+IEFueSBvdGhlciBzdGFydCB0YWdcbiAgICogICAgICAtIFtJbnNlcnQgYW4gSFRNTCBlbGVtZW50XShiZWxvdykgZm9yIHRoZSB0b2tlbi5cbiAgICpcbiAgICogSW5zZXJ0IGFuIEhUTUwgZWxlbWVudDpcbiAgICogaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2Uvc3ludGF4Lmh0bWwjaW5zZXJ0LWFuLWh0bWwtZWxlbWVudFxuICAgKiAtIEluc2VydCBhIGZvcmVpZ24gZWxlbWVudCBmb3IgdGhlIHRva2VuIGluIHRoZSBIVE1MIG5hbWVzcGFjZTpcbiAgICogICBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9zeW50YXguaHRtbCNpbnNlcnQtYS1mb3JlaWduLWVsZW1lbnRcbiAgICogICAtIENyZWF0ZSBhbiBlbGVtZW50IGZvciBhIHRva2VuOlxuICAgKiAgICAgaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2Uvc3ludGF4Lmh0bWwjY3JlYXRlLWFuLWVsZW1lbnQtZm9yLXRoZS10b2tlblxuICAgKiAgICAgLSBXaWxsIGV4ZWN1dGUgc2NyaXB0IGZsYWcgaXMgdHJ1ZT9cbiAgICogICAgICAgLSAoRWxlbWVudCBxdWV1ZSBwdXNoZWQgdG8gdGhlIGN1c3RvbSBlbGVtZW50IHJlYWN0aW9ucyBzdGFjay4pXG4gICAqICAgICAtIENyZWF0ZSBhbiBlbGVtZW50OlxuICAgKiAgICAgICBodHRwczovL2RvbS5zcGVjLndoYXR3Zy5vcmcvI2NvbmNlcHQtY3JlYXRlLWVsZW1lbnRcbiAgICogICAgICAgLSBTeW5jIENFIGZsYWcgaXMgdHJ1ZT9cbiAgICogICAgICAgICAtIENvbnN0cnVjdG9yIGNhbGxlZC5cbiAgICogICAgICAgICAtIFNlbGYtbW9kaWZpY2F0aW9uIHJlc3RyaWN0aW9ucyBlbmZvcmNlZC5cbiAgICogICAgICAgLSBTeW5jIENFIGZsYWcgaXMgZmFsc2U/XG4gICAqICAgICAgICAgLSAoVXBncmFkZSByZWFjdGlvbiBlbnF1ZXVlZC4pXG4gICAqICAgICAtIEF0dHJpYnV0ZXMgYXBwZW5kZWQgdG8gZWxlbWVudC5cbiAgICogICAgICAgKGBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2tgIHJlYWN0aW9ucyBlbnF1ZXVlZC4pXG4gICAqICAgICAtIFdpbGwgZXhlY3V0ZSBzY3JpcHQgZmxhZyBpcyB0cnVlP1xuICAgKiAgICAgICAtIChFbGVtZW50IHF1ZXVlIHBvcHBlZCBmcm9tIHRoZSBjdXN0b20gZWxlbWVudCByZWFjdGlvbnMgc3RhY2suXG4gICAqICAgICAgICAgUmVhY3Rpb25zIGluIHRoZSBwb3BwZWQgc3RhY2sgYXJlIGludm9rZWQuKVxuICAgKiAgIC0gKEVsZW1lbnQgcXVldWUgcHVzaGVkIHRvIHRoZSBjdXN0b20gZWxlbWVudCByZWFjdGlvbnMgc3RhY2suKVxuICAgKiAgIC0gSW5zZXJ0IHRoZSBlbGVtZW50OlxuICAgKiAgICAgaHR0cHM6Ly9kb20uc3BlYy53aGF0d2cub3JnLyNjb25jZXB0LW5vZGUtaW5zZXJ0XG4gICAqICAgICAtIFNoYWRvdy1pbmNsdWRpbmcgZGVzY2VuZGFudHMgYXJlIGNvbm5lY3RlZC4gRHVyaW5nIHBhcnNpbmdcbiAgICogICAgICAgY29uc3RydWN0aW9uLCB0aGVyZSBhcmUgbm8gc2hhZG93LSpleGNsdWRpbmcqIGRlc2NlbmRhbnRzLlxuICAgKiAgICAgICBIb3dldmVyLCB0aGUgY29uc3RydWN0b3IgbWF5IGhhdmUgdmFsaWRseSBhdHRhY2hlZCBhIHNoYWRvd1xuICAgKiAgICAgICB0cmVlIHRvIGl0c2VsZiBhbmQgYWRkZWQgZGVzY2VuZGFudHMgdG8gdGhhdCBzaGFkb3cgdHJlZS5cbiAgICogICAgICAgKGBjb25uZWN0ZWRDYWxsYmFja2AgcmVhY3Rpb25zIGVucXVldWVkLilcbiAgICogICAtIChFbGVtZW50IHF1ZXVlIHBvcHBlZCBmcm9tIHRoZSBjdXN0b20gZWxlbWVudCByZWFjdGlvbnMgc3RhY2suXG4gICAqICAgICBSZWFjdGlvbnMgaW4gdGhlIHBvcHBlZCBzdGFjayBhcmUgaW52b2tlZC4pXG4gICAqXG4gICAqIEBwYXJhbSB7IU5vZGV9IHJvb3RcbiAgICogQHBhcmFtIHshU2V0PE5vZGU+PX0gdmlzaXRlZEltcG9ydHNcbiAgICovXG4gIHBhdGNoQW5kVXBncmFkZVRyZWUocm9vdCwgdmlzaXRlZEltcG9ydHMgPSBuZXcgU2V0KCkpIHtcbiAgICBjb25zdCBlbGVtZW50cyA9IFtdO1xuXG4gICAgY29uc3QgZ2F0aGVyRWxlbWVudHMgPSBlbGVtZW50ID0+IHtcbiAgICAgIGlmIChlbGVtZW50LmxvY2FsTmFtZSA9PT0gJ2xpbmsnICYmIGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdyZWwnKSA9PT0gJ2ltcG9ydCcpIHtcbiAgICAgICAgLy8gVGhlIEhUTUwgSW1wb3J0cyBwb2x5ZmlsbCBzZXRzIGEgZGVzY2VuZGFudCBlbGVtZW50IG9mIHRoZSBsaW5rIHRvXG4gICAgICAgIC8vIHRoZSBgaW1wb3J0YCBwcm9wZXJ0eSwgc3BlY2lmaWNhbGx5IHRoaXMgaXMgKm5vdCogYSBEb2N1bWVudC5cbiAgICAgICAgY29uc3QgaW1wb3J0Tm9kZSA9IC8qKiBAdHlwZSB7P05vZGV9ICovIChlbGVtZW50LmltcG9ydCk7XG5cbiAgICAgICAgaWYgKGltcG9ydE5vZGUgaW5zdGFuY2VvZiBOb2RlICYmIGltcG9ydE5vZGUucmVhZHlTdGF0ZSA9PT0gJ2NvbXBsZXRlJykge1xuICAgICAgICAgIGltcG9ydE5vZGUuX19DRV9pc0ltcG9ydERvY3VtZW50ID0gdHJ1ZTtcblxuICAgICAgICAgIC8vIENvbm5lY3RlZCBsaW5rcyBhcmUgYXNzb2NpYXRlZCB3aXRoIHRoZSByZWdpc3RyeS5cbiAgICAgICAgICBpbXBvcnROb2RlLl9fQ0VfaGFzUmVnaXN0cnkgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIElmIHRoaXMgbGluaydzIGltcG9ydCByb290IGlzIG5vdCBhdmFpbGFibGUsIGl0cyBjb250ZW50cyBjYW4ndCBiZVxuICAgICAgICAgIC8vIHdhbGtlZC4gV2FpdCBmb3IgJ2xvYWQnIGFuZCB3YWxrIGl0IHdoZW4gaXQncyByZWFkeS5cbiAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBpbXBvcnROb2RlID0gLyoqIEB0eXBlIHshTm9kZX0gKi8gKGVsZW1lbnQuaW1wb3J0KTtcblxuICAgICAgICAgICAgaWYgKGltcG9ydE5vZGUuX19DRV9kb2N1bWVudExvYWRIYW5kbGVkKSByZXR1cm47XG4gICAgICAgICAgICBpbXBvcnROb2RlLl9fQ0VfZG9jdW1lbnRMb2FkSGFuZGxlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGltcG9ydE5vZGUuX19DRV9pc0ltcG9ydERvY3VtZW50ID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gQ29ubmVjdGVkIGxpbmtzIGFyZSBhc3NvY2lhdGVkIHdpdGggdGhlIHJlZ2lzdHJ5LlxuICAgICAgICAgICAgaW1wb3J0Tm9kZS5fX0NFX2hhc1JlZ2lzdHJ5ID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gQ2xvbmUgdGhlIGB2aXNpdGVkSW1wb3J0c2Agc2V0IHRoYXQgd2FzIHBvcHVsYXRlZCBzeW5jIGR1cmluZ1xuICAgICAgICAgICAgLy8gdGhlIGBwYXRjaEFuZFVwZ3JhZGVUcmVlYCBjYWxsIHRoYXQgY2F1c2VkIHRoaXMgJ2xvYWQnIGhhbmRsZXIgdG9cbiAgICAgICAgICAgIC8vIGJlIGFkZGVkLiBUaGVuLCByZW1vdmUgKnRoaXMqIGxpbmsncyBpbXBvcnQgbm9kZSBzbyB0aGF0IHdlIGNhblxuICAgICAgICAgICAgLy8gd2FsayB0aGF0IGltcG9ydCBhZ2FpbiwgZXZlbiBpZiBpdCB3YXMgcGFydGlhbGx5IHdhbGtlZCBsYXRlclxuICAgICAgICAgICAgLy8gZHVyaW5nIHRoZSBzYW1lIGBwYXRjaEFuZFVwZ3JhZGVUcmVlYCBjYWxsLlxuICAgICAgICAgICAgY29uc3QgY2xvbmVkVmlzaXRlZEltcG9ydHMgPSBuZXcgU2V0KHZpc2l0ZWRJbXBvcnRzKTtcbiAgICAgICAgICAgIHZpc2l0ZWRJbXBvcnRzLmRlbGV0ZShpbXBvcnROb2RlKTtcblxuICAgICAgICAgICAgdGhpcy5wYXRjaEFuZFVwZ3JhZGVUcmVlKGltcG9ydE5vZGUsIHZpc2l0ZWRJbXBvcnRzKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZWxlbWVudHMucHVzaChlbGVtZW50KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgLy8gYHdhbGtEZWVwRGVzY2VuZGFudEVsZW1lbnRzYCBwb3B1bGF0ZXMgKGFuZCBpbnRlcm5hbGx5IGNoZWNrcyBhZ2FpbnN0KVxuICAgIC8vIGB2aXNpdGVkSW1wb3J0c2Agd2hlbiB0cmF2ZXJzaW5nIGEgbG9hZGVkIGltcG9ydC5cbiAgICBVdGlsaXRpZXMud2Fsa0RlZXBEZXNjZW5kYW50RWxlbWVudHMocm9vdCwgZ2F0aGVyRWxlbWVudHMsIHZpc2l0ZWRJbXBvcnRzKTtcblxuICAgIGlmICh0aGlzLl9oYXNQYXRjaGVzKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMucGF0Y2goZWxlbWVudHNbaV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZWxlbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMudXBncmFkZUVsZW1lbnQoZWxlbWVudHNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gICAqL1xuICB1cGdyYWRlRWxlbWVudChlbGVtZW50KSB7XG4gICAgY29uc3QgY3VycmVudFN0YXRlID0gZWxlbWVudC5fX0NFX3N0YXRlO1xuICAgIGlmIChjdXJyZW50U3RhdGUgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuXG4gICAgY29uc3QgZGVmaW5pdGlvbiA9IHRoaXMubG9jYWxOYW1lVG9EZWZpbml0aW9uKGVsZW1lbnQubG9jYWxOYW1lKTtcbiAgICBpZiAoIWRlZmluaXRpb24pIHJldHVybjtcblxuICAgIGRlZmluaXRpb24uY29uc3RydWN0aW9uU3RhY2sucHVzaChlbGVtZW50KTtcblxuICAgIGNvbnN0IGNvbnN0cnVjdG9yID0gZGVmaW5pdGlvbi5jb25zdHJ1Y3RvcjtcbiAgICB0cnkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgbGV0IHJlc3VsdCA9IG5ldyAoY29uc3RydWN0b3IpKCk7XG4gICAgICAgIGlmIChyZXN1bHQgIT09IGVsZW1lbnQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBjdXN0b20gZWxlbWVudCBjb25zdHJ1Y3RvciBkaWQgbm90IHByb2R1Y2UgdGhlIGVsZW1lbnQgYmVpbmcgdXBncmFkZWQuJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGRlZmluaXRpb24uY29uc3RydWN0aW9uU3RhY2sucG9wKCk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZWxlbWVudC5fX0NFX3N0YXRlID0gQ0VTdGF0ZS5mYWlsZWQ7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIGVsZW1lbnQuX19DRV9zdGF0ZSA9IENFU3RhdGUuY3VzdG9tO1xuICAgIGVsZW1lbnQuX19DRV9kZWZpbml0aW9uID0gZGVmaW5pdGlvbjtcblxuICAgIGlmIChkZWZpbml0aW9uLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaykge1xuICAgICAgY29uc3Qgb2JzZXJ2ZWRBdHRyaWJ1dGVzID0gZGVmaW5pdGlvbi5vYnNlcnZlZEF0dHJpYnV0ZXM7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9ic2VydmVkQXR0cmlidXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBuYW1lID0gb2JzZXJ2ZWRBdHRyaWJ1dGVzW2ldO1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKG5hbWUpO1xuICAgICAgICBpZiAodmFsdWUgIT09IG51bGwpIHtcbiAgICAgICAgICB0aGlzLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhlbGVtZW50LCBuYW1lLCBudWxsLCB2YWx1ZSwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoVXRpbGl0aWVzLmlzQ29ubmVjdGVkKGVsZW1lbnQpKSB7XG4gICAgICB0aGlzLmNvbm5lY3RlZENhbGxiYWNrKGVsZW1lbnQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gICAqL1xuICBjb25uZWN0ZWRDYWxsYmFjayhlbGVtZW50KSB7XG4gICAgY29uc3QgZGVmaW5pdGlvbiA9IGVsZW1lbnQuX19DRV9kZWZpbml0aW9uO1xuICAgIGlmIChkZWZpbml0aW9uLmNvbm5lY3RlZENhbGxiYWNrKSB7XG4gICAgICBkZWZpbml0aW9uLmNvbm5lY3RlZENhbGxiYWNrLmNhbGwoZWxlbWVudCk7XG4gICAgfVxuXG4gICAgZWxlbWVudC5fX0NFX2lzQ29ubmVjdGVkQ2FsbGJhY2tDYWxsZWQgPSB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAgICovXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKGVsZW1lbnQpIHtcbiAgICBpZiAoIWVsZW1lbnQuX19DRV9pc0Nvbm5lY3RlZENhbGxiYWNrQ2FsbGVkKSB7XG4gICAgICB0aGlzLmNvbm5lY3RlZENhbGxiYWNrKGVsZW1lbnQpO1xuICAgIH1cblxuICAgIGNvbnN0IGRlZmluaXRpb24gPSBlbGVtZW50Ll9fQ0VfZGVmaW5pdGlvbjtcbiAgICBpZiAoZGVmaW5pdGlvbi5kaXNjb25uZWN0ZWRDYWxsYmFjaykge1xuICAgICAgZGVmaW5pdGlvbi5kaXNjb25uZWN0ZWRDYWxsYmFjay5jYWxsKGVsZW1lbnQpO1xuICAgIH1cblxuICAgIGVsZW1lbnQuX19DRV9pc0Nvbm5lY3RlZENhbGxiYWNrQ2FsbGVkID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHs/c3RyaW5nfSBvbGRWYWx1ZVxuICAgKiBAcGFyYW0gez9zdHJpbmd9IG5ld1ZhbHVlXG4gICAqIEBwYXJhbSB7P3N0cmluZ30gbmFtZXNwYWNlXG4gICAqL1xuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2soZWxlbWVudCwgbmFtZSwgb2xkVmFsdWUsIG5ld1ZhbHVlLCBuYW1lc3BhY2UpIHtcbiAgICBjb25zdCBkZWZpbml0aW9uID0gZWxlbWVudC5fX0NFX2RlZmluaXRpb247XG4gICAgaWYgKFxuICAgICAgZGVmaW5pdGlvbi5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sgJiZcbiAgICAgIGRlZmluaXRpb24ub2JzZXJ2ZWRBdHRyaWJ1dGVzLmluZGV4T2YobmFtZSkgPiAtMVxuICAgICkge1xuICAgICAgZGVmaW5pdGlvbi5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2suY2FsbChlbGVtZW50LCBuYW1lLCBvbGRWYWx1ZSwgbmV3VmFsdWUsIG5hbWVzcGFjZSk7XG4gICAgfVxuICB9XG59XG4iLCJpbXBvcnQgQ3VzdG9tRWxlbWVudEludGVybmFscyBmcm9tICcuL0N1c3RvbUVsZW1lbnRJbnRlcm5hbHMuanMnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBEb2N1bWVudENvbnN0cnVjdGlvbk9ic2VydmVyIHtcbiAgY29uc3RydWN0b3IoaW50ZXJuYWxzLCBkb2MpIHtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7IUN1c3RvbUVsZW1lbnRJbnRlcm5hbHN9XG4gICAgICovXG4gICAgdGhpcy5faW50ZXJuYWxzID0gaW50ZXJuYWxzO1xuXG4gICAgLyoqXG4gICAgICogQHR5cGUgeyFEb2N1bWVudH1cbiAgICAgKi9cbiAgICB0aGlzLl9kb2N1bWVudCA9IGRvYztcblxuICAgIC8qKlxuICAgICAqIEB0eXBlIHtNdXRhdGlvbk9ic2VydmVyfHVuZGVmaW5lZH1cbiAgICAgKi9cbiAgICB0aGlzLl9vYnNlcnZlciA9IHVuZGVmaW5lZDtcblxuXG4gICAgLy8gU2ltdWxhdGUgdHJlZSBjb25zdHJ1Y3Rpb24gZm9yIGFsbCBjdXJyZW50bHkgYWNjZXNzaWJsZSBub2RlcyBpbiB0aGVcbiAgICAvLyBkb2N1bWVudC5cbiAgICB0aGlzLl9pbnRlcm5hbHMucGF0Y2hBbmRVcGdyYWRlVHJlZSh0aGlzLl9kb2N1bWVudCk7XG5cbiAgICBpZiAodGhpcy5fZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ2xvYWRpbmcnKSB7XG4gICAgICB0aGlzLl9vYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKHRoaXMuX2hhbmRsZU11dGF0aW9ucy5iaW5kKHRoaXMpKTtcblxuICAgICAgLy8gTm9kZXMgY3JlYXRlZCBieSB0aGUgcGFyc2VyIGFyZSBnaXZlbiB0byB0aGUgb2JzZXJ2ZXIgKmJlZm9yZSogdGhlIG5leHRcbiAgICAgIC8vIHRhc2sgcnVucy4gSW5saW5lIHNjcmlwdHMgYXJlIHJ1biBpbiBhIG5ldyB0YXNrLiBUaGlzIG1lYW5zIHRoYXQgdGhlXG4gICAgICAvLyBvYnNlcnZlciB3aWxsIGJlIGFibGUgdG8gaGFuZGxlIHRoZSBuZXdseSBwYXJzZWQgbm9kZXMgYmVmb3JlIHRoZSBpbmxpbmVcbiAgICAgIC8vIHNjcmlwdCBpcyBydW4uXG4gICAgICB0aGlzLl9vYnNlcnZlci5vYnNlcnZlKHRoaXMuX2RvY3VtZW50LCB7XG4gICAgICAgIGNoaWxkTGlzdDogdHJ1ZSxcbiAgICAgICAgc3VidHJlZTogdHJ1ZSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGRpc2Nvbm5lY3QoKSB7XG4gICAgaWYgKHRoaXMuX29ic2VydmVyKSB7XG4gICAgICB0aGlzLl9vYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IUFycmF5PCFNdXRhdGlvblJlY29yZD59IG11dGF0aW9uc1xuICAgKi9cbiAgX2hhbmRsZU11dGF0aW9ucyhtdXRhdGlvbnMpIHtcbiAgICAvLyBPbmNlIHRoZSBkb2N1bWVudCdzIGByZWFkeVN0YXRlYCBpcyAnaW50ZXJhY3RpdmUnIG9yICdjb21wbGV0ZScsIGFsbCBuZXdcbiAgICAvLyBub2RlcyBjcmVhdGVkIHdpdGhpbiB0aGF0IGRvY3VtZW50IHdpbGwgYmUgdGhlIHJlc3VsdCBvZiBzY3JpcHQgYW5kXG4gICAgLy8gc2hvdWxkIGJlIGhhbmRsZWQgYnkgcGF0Y2hpbmcuXG4gICAgY29uc3QgcmVhZHlTdGF0ZSA9IHRoaXMuX2RvY3VtZW50LnJlYWR5U3RhdGU7XG4gICAgaWYgKHJlYWR5U3RhdGUgPT09ICdpbnRlcmFjdGl2ZScgfHwgcmVhZHlTdGF0ZSA9PT0gJ2NvbXBsZXRlJykge1xuICAgICAgdGhpcy5kaXNjb25uZWN0KCk7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtdXRhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGFkZGVkTm9kZXMgPSBtdXRhdGlvbnNbaV0uYWRkZWROb2RlcztcbiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgYWRkZWROb2Rlcy5sZW5ndGg7IGorKykge1xuICAgICAgICBjb25zdCBub2RlID0gYWRkZWROb2Rlc1tqXTtcbiAgICAgICAgdGhpcy5faW50ZXJuYWxzLnBhdGNoQW5kVXBncmFkZVRyZWUobm9kZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iLCIvKipcbiAqIEB0ZW1wbGF0ZSBUXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIERlZmVycmVkIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7VHx1bmRlZmluZWR9XG4gICAgICovXG4gICAgdGhpcy5fdmFsdWUgPSB1bmRlZmluZWQ7XG5cbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtGdW5jdGlvbnx1bmRlZmluZWR9XG4gICAgICovXG4gICAgdGhpcy5fcmVzb2x2ZSA9IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyFQcm9taXNlPFQ+fVxuICAgICAqL1xuICAgIHRoaXMuX3Byb21pc2UgPSBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIHRoaXMuX3Jlc29sdmUgPSByZXNvbHZlO1xuXG4gICAgICBpZiAodGhpcy5fdmFsdWUpIHtcbiAgICAgICAgcmVzb2x2ZSh0aGlzLl92YWx1ZSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtUfSB2YWx1ZVxuICAgKi9cbiAgcmVzb2x2ZSh2YWx1ZSkge1xuICAgIGlmICh0aGlzLl92YWx1ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBbHJlYWR5IHJlc29sdmVkLicpO1xuICAgIH1cblxuICAgIHRoaXMuX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAodGhpcy5fcmVzb2x2ZSkge1xuICAgICAgdGhpcy5fcmVzb2x2ZSh2YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4geyFQcm9taXNlPFQ+fVxuICAgKi9cbiAgdG9Qcm9taXNlKCkge1xuICAgIHJldHVybiB0aGlzLl9wcm9taXNlO1xuICB9XG59XG4iLCJpbXBvcnQgQ3VzdG9tRWxlbWVudEludGVybmFscyBmcm9tICcuL0N1c3RvbUVsZW1lbnRJbnRlcm5hbHMuanMnO1xuaW1wb3J0IERvY3VtZW50Q29uc3RydWN0aW9uT2JzZXJ2ZXIgZnJvbSAnLi9Eb2N1bWVudENvbnN0cnVjdGlvbk9ic2VydmVyLmpzJztcbmltcG9ydCBEZWZlcnJlZCBmcm9tICcuL0RlZmVycmVkLmpzJztcbmltcG9ydCAqIGFzIFV0aWxpdGllcyBmcm9tICcuL1V0aWxpdGllcy5qcyc7XG5cbi8qKlxuICogQHVucmVzdHJpY3RlZFxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDdXN0b21FbGVtZW50UmVnaXN0cnkge1xuXG4gIC8qKlxuICAgKiBAcGFyYW0geyFDdXN0b21FbGVtZW50SW50ZXJuYWxzfSBpbnRlcm5hbHNcbiAgICovXG4gIGNvbnN0cnVjdG9yKGludGVybmFscykge1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgdGhpcy5fZWxlbWVudERlZmluaXRpb25Jc1J1bm5pbmcgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyFDdXN0b21FbGVtZW50SW50ZXJuYWxzfVxuICAgICAqL1xuICAgIHRoaXMuX2ludGVybmFscyA9IGludGVybmFscztcblxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyFNYXA8c3RyaW5nLCAhRGVmZXJyZWQ8dW5kZWZpbmVkPj59XG4gICAgICovXG4gICAgdGhpcy5fd2hlbkRlZmluZWREZWZlcnJlZCA9IG5ldyBNYXAoKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBkZWZhdWx0IGZsdXNoIGNhbGxiYWNrIHRyaWdnZXJzIHRoZSBkb2N1bWVudCB3YWxrIHN5bmNocm9ub3VzbHkuXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7IUZ1bmN0aW9ufVxuICAgICAqL1xuICAgIHRoaXMuX2ZsdXNoQ2FsbGJhY2sgPSBmbiA9PiBmbigpO1xuXG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICB0aGlzLl9mbHVzaFBlbmRpbmcgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyFBcnJheTxzdHJpbmc+fVxuICAgICAqL1xuICAgIHRoaXMuX3VuZmx1c2hlZExvY2FsTmFtZXMgPSBbXTtcblxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyFEb2N1bWVudENvbnN0cnVjdGlvbk9ic2VydmVyfVxuICAgICAqL1xuICAgIHRoaXMuX2RvY3VtZW50Q29uc3RydWN0aW9uT2JzZXJ2ZXIgPSBuZXcgRG9jdW1lbnRDb25zdHJ1Y3Rpb25PYnNlcnZlcihpbnRlcm5hbHMsIGRvY3VtZW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbG9jYWxOYW1lXG4gICAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBjb25zdHJ1Y3RvclxuICAgKi9cbiAgZGVmaW5lKGxvY2FsTmFtZSwgY29uc3RydWN0b3IpIHtcbiAgICBpZiAoIShjb25zdHJ1Y3RvciBpbnN0YW5jZW9mIEZ1bmN0aW9uKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQ3VzdG9tIGVsZW1lbnQgY29uc3RydWN0b3JzIG11c3QgYmUgZnVuY3Rpb25zLicpO1xuICAgIH1cblxuICAgIGlmICghVXRpbGl0aWVzLmlzVmFsaWRDdXN0b21FbGVtZW50TmFtZShsb2NhbE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoYFRoZSBlbGVtZW50IG5hbWUgJyR7bG9jYWxOYW1lfScgaXMgbm90IHZhbGlkLmApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9pbnRlcm5hbHMubG9jYWxOYW1lVG9EZWZpbml0aW9uKGxvY2FsTmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQSBjdXN0b20gZWxlbWVudCB3aXRoIG5hbWUgJyR7bG9jYWxOYW1lfScgaGFzIGFscmVhZHkgYmVlbiBkZWZpbmVkLmApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9lbGVtZW50RGVmaW5pdGlvbklzUnVubmluZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBIGN1c3RvbSBlbGVtZW50IGlzIGFscmVhZHkgYmVpbmcgZGVmaW5lZC4nKTtcbiAgICB9XG4gICAgdGhpcy5fZWxlbWVudERlZmluaXRpb25Jc1J1bm5pbmcgPSB0cnVlO1xuXG4gICAgbGV0IGNvbm5lY3RlZENhbGxiYWNrO1xuICAgIGxldCBkaXNjb25uZWN0ZWRDYWxsYmFjaztcbiAgICBsZXQgYWRvcHRlZENhbGxiYWNrO1xuICAgIGxldCBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2s7XG4gICAgbGV0IG9ic2VydmVkQXR0cmlidXRlcztcbiAgICB0cnkge1xuICAgICAgLyoqIEB0eXBlIHshT2JqZWN0fSAqL1xuICAgICAgY29uc3QgcHJvdG90eXBlID0gY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgaWYgKCEocHJvdG90eXBlIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgY3VzdG9tIGVsZW1lbnQgY29uc3RydWN0b3JcXCdzIHByb3RvdHlwZSBpcyBub3QgYW4gb2JqZWN0LicpO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBnZXRDYWxsYmFjayhuYW1lKSB7XG4gICAgICAgIGNvbnN0IGNhbGxiYWNrVmFsdWUgPSBwcm90b3R5cGVbbmFtZV07XG4gICAgICAgIGlmIChjYWxsYmFja1ZhbHVlICE9PSB1bmRlZmluZWQgJiYgIShjYWxsYmFja1ZhbHVlIGluc3RhbmNlb2YgRnVuY3Rpb24pKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgJyR7bmFtZX0nIGNhbGxiYWNrIG11c3QgYmUgYSBmdW5jdGlvbi5gKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY2FsbGJhY2tWYWx1ZTtcbiAgICAgIH1cblxuICAgICAgY29ubmVjdGVkQ2FsbGJhY2sgPSBnZXRDYWxsYmFjaygnY29ubmVjdGVkQ2FsbGJhY2snKTtcbiAgICAgIGRpc2Nvbm5lY3RlZENhbGxiYWNrID0gZ2V0Q2FsbGJhY2soJ2Rpc2Nvbm5lY3RlZENhbGxiYWNrJyk7XG4gICAgICBhZG9wdGVkQ2FsbGJhY2sgPSBnZXRDYWxsYmFjaygnYWRvcHRlZENhbGxiYWNrJyk7XG4gICAgICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sgPSBnZXRDYWxsYmFjaygnYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrJyk7XG4gICAgICBvYnNlcnZlZEF0dHJpYnV0ZXMgPSBjb25zdHJ1Y3Rvclsnb2JzZXJ2ZWRBdHRyaWJ1dGVzJ10gfHwgW107XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLl9lbGVtZW50RGVmaW5pdGlvbklzUnVubmluZyA9IGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGRlZmluaXRpb24gPSB7XG4gICAgICBsb2NhbE5hbWUsXG4gICAgICBjb25zdHJ1Y3RvcixcbiAgICAgIGNvbm5lY3RlZENhbGxiYWNrLFxuICAgICAgZGlzY29ubmVjdGVkQ2FsbGJhY2ssXG4gICAgICBhZG9wdGVkQ2FsbGJhY2ssXG4gICAgICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2ssXG4gICAgICBvYnNlcnZlZEF0dHJpYnV0ZXMsXG4gICAgICBjb25zdHJ1Y3Rpb25TdGFjazogW10sXG4gICAgfTtcblxuICAgIHRoaXMuX2ludGVybmFscy5zZXREZWZpbml0aW9uKGxvY2FsTmFtZSwgZGVmaW5pdGlvbik7XG5cbiAgICB0aGlzLl91bmZsdXNoZWRMb2NhbE5hbWVzLnB1c2gobG9jYWxOYW1lKTtcblxuICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgY2FsbGVkIHRoZSBmbHVzaCBjYWxsYmFjayBhbmQgaXQgaGFzbid0IGNhbGxlZCBiYWNrIHlldCxcbiAgICAvLyBkb24ndCBjYWxsIGl0IGFnYWluLlxuICAgIGlmICghdGhpcy5fZmx1c2hQZW5kaW5nKSB7XG4gICAgICB0aGlzLl9mbHVzaFBlbmRpbmcgPSB0cnVlO1xuICAgICAgdGhpcy5fZmx1c2hDYWxsYmFjaygoKSA9PiB0aGlzLl9mbHVzaCgpKTtcbiAgICB9XG4gIH1cblxuICBfZmx1c2goKSB7XG4gICAgLy8gSWYgbm8gbmV3IGRlZmluaXRpb25zIHdlcmUgZGVmaW5lZCwgZG9uJ3QgYXR0ZW1wdCB0byBmbHVzaC4gVGhpcyBjb3VsZFxuICAgIC8vIGhhcHBlbiBpZiBhIGZsdXNoIGNhbGxiYWNrIGtlZXBzIHRoZSBmdW5jdGlvbiBpdCBpcyBnaXZlbiBhbmQgY2FsbHMgaXRcbiAgICAvLyBtdWx0aXBsZSB0aW1lcy5cbiAgICBpZiAodGhpcy5fZmx1c2hQZW5kaW5nID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgdGhpcy5fZmx1c2hQZW5kaW5nID0gZmFsc2U7XG4gICAgdGhpcy5faW50ZXJuYWxzLnBhdGNoQW5kVXBncmFkZVRyZWUoZG9jdW1lbnQpO1xuXG4gICAgd2hpbGUgKHRoaXMuX3VuZmx1c2hlZExvY2FsTmFtZXMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgbG9jYWxOYW1lID0gdGhpcy5fdW5mbHVzaGVkTG9jYWxOYW1lcy5zaGlmdCgpO1xuICAgICAgY29uc3QgZGVmZXJyZWQgPSB0aGlzLl93aGVuRGVmaW5lZERlZmVycmVkLmdldChsb2NhbE5hbWUpO1xuICAgICAgaWYgKGRlZmVycmVkKSB7XG4gICAgICAgIGRlZmVycmVkLnJlc29sdmUodW5kZWZpbmVkKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IGxvY2FsTmFtZVxuICAgKiBAcmV0dXJuIHtGdW5jdGlvbnx1bmRlZmluZWR9XG4gICAqL1xuICBnZXQobG9jYWxOYW1lKSB7XG4gICAgY29uc3QgZGVmaW5pdGlvbiA9IHRoaXMuX2ludGVybmFscy5sb2NhbE5hbWVUb0RlZmluaXRpb24obG9jYWxOYW1lKTtcbiAgICBpZiAoZGVmaW5pdGlvbikge1xuICAgICAgcmV0dXJuIGRlZmluaXRpb24uY29uc3RydWN0b3I7XG4gICAgfVxuXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbG9jYWxOYW1lXG4gICAqIEByZXR1cm4geyFQcm9taXNlPHVuZGVmaW5lZD59XG4gICAqL1xuICB3aGVuRGVmaW5lZChsb2NhbE5hbWUpIHtcbiAgICBpZiAoIVV0aWxpdGllcy5pc1ZhbGlkQ3VzdG9tRWxlbWVudE5hbWUobG9jYWxOYW1lKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBTeW50YXhFcnJvcihgJyR7bG9jYWxOYW1lfScgaXMgbm90IGEgdmFsaWQgY3VzdG9tIGVsZW1lbnQgbmFtZS5gKSk7XG4gICAgfVxuXG4gICAgY29uc3QgcHJpb3IgPSB0aGlzLl93aGVuRGVmaW5lZERlZmVycmVkLmdldChsb2NhbE5hbWUpO1xuICAgIGlmIChwcmlvcikge1xuICAgICAgcmV0dXJuIHByaW9yLnRvUHJvbWlzZSgpO1xuICAgIH1cblxuICAgIGNvbnN0IGRlZmVycmVkID0gbmV3IERlZmVycmVkKCk7XG4gICAgdGhpcy5fd2hlbkRlZmluZWREZWZlcnJlZC5zZXQobG9jYWxOYW1lLCBkZWZlcnJlZCk7XG5cbiAgICBjb25zdCBkZWZpbml0aW9uID0gdGhpcy5faW50ZXJuYWxzLmxvY2FsTmFtZVRvRGVmaW5pdGlvbihsb2NhbE5hbWUpO1xuICAgIC8vIFJlc29sdmUgaW1tZWRpYXRlbHkgb25seSBpZiB0aGUgZ2l2ZW4gbG9jYWwgbmFtZSBoYXMgYSBkZWZpbml0aW9uICphbmQqXG4gICAgLy8gdGhlIGZ1bGwgZG9jdW1lbnQgd2FsayB0byB1cGdyYWRlIGVsZW1lbnRzIHdpdGggdGhhdCBsb2NhbCBuYW1lIGhhc1xuICAgIC8vIGFscmVhZHkgaGFwcGVuZWQuXG4gICAgaWYgKGRlZmluaXRpb24gJiYgdGhpcy5fdW5mbHVzaGVkTG9jYWxOYW1lcy5pbmRleE9mKGxvY2FsTmFtZSkgPT09IC0xKSB7XG4gICAgICBkZWZlcnJlZC5yZXNvbHZlKHVuZGVmaW5lZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlZmVycmVkLnRvUHJvbWlzZSgpO1xuICB9XG5cbiAgcG9seWZpbGxXcmFwRmx1c2hDYWxsYmFjayhvdXRlcikge1xuICAgIHRoaXMuX2RvY3VtZW50Q29uc3RydWN0aW9uT2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuICAgIGNvbnN0IGlubmVyID0gdGhpcy5fZmx1c2hDYWxsYmFjaztcbiAgICB0aGlzLl9mbHVzaENhbGxiYWNrID0gZmx1c2ggPT4gb3V0ZXIoKCkgPT4gaW5uZXIoZmx1c2gpKTtcbiAgfVxufVxuXG4vLyBDbG9zdXJlIGNvbXBpbGVyIGV4cG9ydHMuXG53aW5kb3dbJ0N1c3RvbUVsZW1lbnRSZWdpc3RyeSddID0gQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5O1xuQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5LnByb3RvdHlwZVsnZGVmaW5lJ10gPSBDdXN0b21FbGVtZW50UmVnaXN0cnkucHJvdG90eXBlLmRlZmluZTtcbkN1c3RvbUVsZW1lbnRSZWdpc3RyeS5wcm90b3R5cGVbJ2dldCddID0gQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5LnByb3RvdHlwZS5nZXQ7XG5DdXN0b21FbGVtZW50UmVnaXN0cnkucHJvdG90eXBlWyd3aGVuRGVmaW5lZCddID0gQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5LnByb3RvdHlwZS53aGVuRGVmaW5lZDtcbkN1c3RvbUVsZW1lbnRSZWdpc3RyeS5wcm90b3R5cGVbJ3BvbHlmaWxsV3JhcEZsdXNoQ2FsbGJhY2snXSA9IEN1c3RvbUVsZW1lbnRSZWdpc3RyeS5wcm90b3R5cGUucG9seWZpbGxXcmFwRmx1c2hDYWxsYmFjaztcbiIsImV4cG9ydCBkZWZhdWx0IHtcbiAgRG9jdW1lbnRfY3JlYXRlRWxlbWVudDogd2luZG93LkRvY3VtZW50LnByb3RvdHlwZS5jcmVhdGVFbGVtZW50LFxuICBEb2N1bWVudF9jcmVhdGVFbGVtZW50TlM6IHdpbmRvdy5Eb2N1bWVudC5wcm90b3R5cGUuY3JlYXRlRWxlbWVudE5TLFxuICBEb2N1bWVudF9pbXBvcnROb2RlOiB3aW5kb3cuRG9jdW1lbnQucHJvdG90eXBlLmltcG9ydE5vZGUsXG4gIERvY3VtZW50X3ByZXBlbmQ6IHdpbmRvdy5Eb2N1bWVudC5wcm90b3R5cGVbJ3ByZXBlbmQnXSxcbiAgRG9jdW1lbnRfYXBwZW5kOiB3aW5kb3cuRG9jdW1lbnQucHJvdG90eXBlWydhcHBlbmQnXSxcbiAgTm9kZV9jbG9uZU5vZGU6IHdpbmRvdy5Ob2RlLnByb3RvdHlwZS5jbG9uZU5vZGUsXG4gIE5vZGVfYXBwZW5kQ2hpbGQ6IHdpbmRvdy5Ob2RlLnByb3RvdHlwZS5hcHBlbmRDaGlsZCxcbiAgTm9kZV9pbnNlcnRCZWZvcmU6IHdpbmRvdy5Ob2RlLnByb3RvdHlwZS5pbnNlcnRCZWZvcmUsXG4gIE5vZGVfcmVtb3ZlQ2hpbGQ6IHdpbmRvdy5Ob2RlLnByb3RvdHlwZS5yZW1vdmVDaGlsZCxcbiAgTm9kZV9yZXBsYWNlQ2hpbGQ6IHdpbmRvdy5Ob2RlLnByb3RvdHlwZS5yZXBsYWNlQ2hpbGQsXG4gIE5vZGVfdGV4dENvbnRlbnQ6IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iod2luZG93Lk5vZGUucHJvdG90eXBlLCAndGV4dENvbnRlbnQnKSxcbiAgRWxlbWVudF9hdHRhY2hTaGFkb3c6IHdpbmRvdy5FbGVtZW50LnByb3RvdHlwZVsnYXR0YWNoU2hhZG93J10sXG4gIEVsZW1lbnRfaW5uZXJIVE1MOiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHdpbmRvdy5FbGVtZW50LnByb3RvdHlwZSwgJ2lubmVySFRNTCcpLFxuICBFbGVtZW50X2dldEF0dHJpYnV0ZTogd2luZG93LkVsZW1lbnQucHJvdG90eXBlLmdldEF0dHJpYnV0ZSxcbiAgRWxlbWVudF9zZXRBdHRyaWJ1dGU6IHdpbmRvdy5FbGVtZW50LnByb3RvdHlwZS5zZXRBdHRyaWJ1dGUsXG4gIEVsZW1lbnRfcmVtb3ZlQXR0cmlidXRlOiB3aW5kb3cuRWxlbWVudC5wcm90b3R5cGUucmVtb3ZlQXR0cmlidXRlLFxuICBFbGVtZW50X2dldEF0dHJpYnV0ZU5TOiB3aW5kb3cuRWxlbWVudC5wcm90b3R5cGUuZ2V0QXR0cmlidXRlTlMsXG4gIEVsZW1lbnRfc2V0QXR0cmlidXRlTlM6IHdpbmRvdy5FbGVtZW50LnByb3RvdHlwZS5zZXRBdHRyaWJ1dGVOUyxcbiAgRWxlbWVudF9yZW1vdmVBdHRyaWJ1dGVOUzogd2luZG93LkVsZW1lbnQucHJvdG90eXBlLnJlbW92ZUF0dHJpYnV0ZU5TLFxuICBFbGVtZW50X2luc2VydEFkamFjZW50RWxlbWVudDogd2luZG93LkVsZW1lbnQucHJvdG90eXBlWydpbnNlcnRBZGphY2VudEVsZW1lbnQnXSxcbiAgRWxlbWVudF9wcmVwZW5kOiB3aW5kb3cuRWxlbWVudC5wcm90b3R5cGVbJ3ByZXBlbmQnXSxcbiAgRWxlbWVudF9hcHBlbmQ6IHdpbmRvdy5FbGVtZW50LnByb3RvdHlwZVsnYXBwZW5kJ10sXG4gIEVsZW1lbnRfYmVmb3JlOiB3aW5kb3cuRWxlbWVudC5wcm90b3R5cGVbJ2JlZm9yZSddLFxuICBFbGVtZW50X2FmdGVyOiB3aW5kb3cuRWxlbWVudC5wcm90b3R5cGVbJ2FmdGVyJ10sXG4gIEVsZW1lbnRfcmVwbGFjZVdpdGg6IHdpbmRvdy5FbGVtZW50LnByb3RvdHlwZVsncmVwbGFjZVdpdGgnXSxcbiAgRWxlbWVudF9yZW1vdmU6IHdpbmRvdy5FbGVtZW50LnByb3RvdHlwZVsncmVtb3ZlJ10sXG4gIEhUTUxFbGVtZW50OiB3aW5kb3cuSFRNTEVsZW1lbnQsXG4gIEhUTUxFbGVtZW50X2lubmVySFRNTDogT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih3aW5kb3cuSFRNTEVsZW1lbnQucHJvdG90eXBlLCAnaW5uZXJIVE1MJyksXG4gIEhUTUxFbGVtZW50X2luc2VydEFkamFjZW50RWxlbWVudDogd2luZG93LkhUTUxFbGVtZW50LnByb3RvdHlwZVsnaW5zZXJ0QWRqYWNlbnRFbGVtZW50J10sXG59O1xuIiwiLyoqXG4gKiBUaGlzIGNsYXNzIGV4aXN0cyBvbmx5IHRvIHdvcmsgYXJvdW5kIENsb3N1cmUncyBsYWNrIG9mIGEgd2F5IHRvIGRlc2NyaWJlXG4gKiBzaW5nbGV0b25zLiBJdCByZXByZXNlbnRzIHRoZSAnYWxyZWFkeSBjb25zdHJ1Y3RlZCBtYXJrZXInIHVzZWQgaW4gY3VzdG9tXG4gKiBlbGVtZW50IGNvbnN0cnVjdGlvbiBzdGFja3MuXG4gKlxuICogaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy8jY29uY2VwdC1hbHJlYWR5LWNvbnN0cnVjdGVkLW1hcmtlclxuICovXG5jbGFzcyBBbHJlYWR5Q29uc3RydWN0ZWRNYXJrZXIge31cblxuZXhwb3J0IGRlZmF1bHQgbmV3IEFscmVhZHlDb25zdHJ1Y3RlZE1hcmtlcigpO1xuIiwiaW1wb3J0IE5hdGl2ZSBmcm9tICcuL05hdGl2ZS5qcyc7XG5pbXBvcnQgQ3VzdG9tRWxlbWVudEludGVybmFscyBmcm9tICcuLi9DdXN0b21FbGVtZW50SW50ZXJuYWxzLmpzJztcbmltcG9ydCBDRVN0YXRlIGZyb20gJy4uL0N1c3RvbUVsZW1lbnRTdGF0ZS5qcyc7XG5pbXBvcnQgQWxyZWFkeUNvbnN0cnVjdGVkTWFya2VyIGZyb20gJy4uL0FscmVhZHlDb25zdHJ1Y3RlZE1hcmtlci5qcyc7XG5cbi8qKlxuICogQHBhcmFtIHshQ3VzdG9tRWxlbWVudEludGVybmFsc30gaW50ZXJuYWxzXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKGludGVybmFscykge1xuICB3aW5kb3dbJ0hUTUxFbGVtZW50J10gPSAoZnVuY3Rpb24oKSB7XG4gICAgLyoqXG4gICAgICogQHR5cGUge2Z1bmN0aW9uKG5ldzogSFRNTEVsZW1lbnQpOiAhSFRNTEVsZW1lbnR9XG4gICAgICovXG4gICAgZnVuY3Rpb24gSFRNTEVsZW1lbnQoKSB7XG4gICAgICAvLyBUaGlzIHNob3VsZCByZWFsbHkgYmUgYG5ldy50YXJnZXRgIGJ1dCBgbmV3LnRhcmdldGAgY2FuJ3QgYmUgZW11bGF0ZWRcbiAgICAgIC8vIGluIEVTNS4gQXNzdW1pbmcgdGhlIHVzZXIga2VlcHMgdGhlIGRlZmF1bHQgdmFsdWUgb2YgdGhlIGNvbnN0cnVjdG9yJ3NcbiAgICAgIC8vIHByb3RvdHlwZSdzIGBjb25zdHJ1Y3RvcmAgcHJvcGVydHksIHRoaXMgaXMgZXF1aXZhbGVudC5cbiAgICAgIC8qKiBAdHlwZSB7IUZ1bmN0aW9ufSAqL1xuICAgICAgY29uc3QgY29uc3RydWN0b3IgPSB0aGlzLmNvbnN0cnVjdG9yO1xuXG4gICAgICBjb25zdCBkZWZpbml0aW9uID0gaW50ZXJuYWxzLmNvbnN0cnVjdG9yVG9EZWZpbml0aW9uKGNvbnN0cnVjdG9yKTtcbiAgICAgIGlmICghZGVmaW5pdGlvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBjdXN0b20gZWxlbWVudCBiZWluZyBjb25zdHJ1Y3RlZCB3YXMgbm90IHJlZ2lzdGVyZWQgd2l0aCBgY3VzdG9tRWxlbWVudHNgLicpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjb25zdHJ1Y3Rpb25TdGFjayA9IGRlZmluaXRpb24uY29uc3RydWN0aW9uU3RhY2s7XG5cbiAgICAgIGlmIChjb25zdHJ1Y3Rpb25TdGFjay5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc3QgZWxlbWVudCA9IE5hdGl2ZS5Eb2N1bWVudF9jcmVhdGVFbGVtZW50LmNhbGwoZG9jdW1lbnQsIGRlZmluaXRpb24ubG9jYWxOYW1lKTtcbiAgICAgICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKGVsZW1lbnQsIGNvbnN0cnVjdG9yLnByb3RvdHlwZSk7XG4gICAgICAgIGVsZW1lbnQuX19DRV9zdGF0ZSA9IENFU3RhdGUuY3VzdG9tO1xuICAgICAgICBlbGVtZW50Ll9fQ0VfZGVmaW5pdGlvbiA9IGRlZmluaXRpb247XG4gICAgICAgIGludGVybmFscy5wYXRjaChlbGVtZW50KTtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGxhc3RJbmRleCA9IGNvbnN0cnVjdGlvblN0YWNrLmxlbmd0aCAtIDE7XG4gICAgICBjb25zdCBlbGVtZW50ID0gY29uc3RydWN0aW9uU3RhY2tbbGFzdEluZGV4XTtcbiAgICAgIGlmIChlbGVtZW50ID09PSBBbHJlYWR5Q29uc3RydWN0ZWRNYXJrZXIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgSFRNTEVsZW1lbnQgY29uc3RydWN0b3Igd2FzIGVpdGhlciBjYWxsZWQgcmVlbnRyYW50bHkgZm9yIHRoaXMgY29uc3RydWN0b3Igb3IgY2FsbGVkIG11bHRpcGxlIHRpbWVzLicpO1xuICAgICAgfVxuICAgICAgY29uc3RydWN0aW9uU3RhY2tbbGFzdEluZGV4XSA9IEFscmVhZHlDb25zdHJ1Y3RlZE1hcmtlcjtcblxuICAgICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKGVsZW1lbnQsIGNvbnN0cnVjdG9yLnByb3RvdHlwZSk7XG4gICAgICBpbnRlcm5hbHMucGF0Y2goLyoqIEB0eXBlIHshSFRNTEVsZW1lbnR9ICovIChlbGVtZW50KSk7XG5cbiAgICAgIHJldHVybiBlbGVtZW50O1xuICAgIH1cblxuICAgIEhUTUxFbGVtZW50LnByb3RvdHlwZSA9IE5hdGl2ZS5IVE1MRWxlbWVudC5wcm90b3R5cGU7XG5cbiAgICByZXR1cm4gSFRNTEVsZW1lbnQ7XG4gIH0pKCk7XG59O1xuIiwiaW1wb3J0IEN1c3RvbUVsZW1lbnRJbnRlcm5hbHMgZnJvbSAnLi4vLi4vQ3VzdG9tRWxlbWVudEludGVybmFscy5qcyc7XG5pbXBvcnQgKiBhcyBVdGlsaXRpZXMgZnJvbSAnLi4vLi4vVXRpbGl0aWVzLmpzJztcblxuLyoqXG4gKiBAdHlwZWRlZiB7e1xuICogICBwcmVwZW5kOiAhZnVuY3Rpb24oLi4uKCFOb2RlfHN0cmluZykpLFxuICAqICBhcHBlbmQ6ICFmdW5jdGlvbiguLi4oIU5vZGV8c3RyaW5nKSksXG4gKiB9fVxuICovXG5sZXQgUGFyZW50Tm9kZU5hdGl2ZU1ldGhvZHM7XG5cbi8qKlxuICogQHBhcmFtIHshQ3VzdG9tRWxlbWVudEludGVybmFsc30gaW50ZXJuYWxzXG4gKiBAcGFyYW0geyFPYmplY3R9IGRlc3RpbmF0aW9uXG4gKiBAcGFyYW0geyFQYXJlbnROb2RlTmF0aXZlTWV0aG9kc30gYnVpbHRJblxuICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnRlcm5hbHMsIGRlc3RpbmF0aW9uLCBidWlsdEluKSB7XG4gIC8qKlxuICAgKiBAcGFyYW0gey4uLighTm9kZXxzdHJpbmcpfSBub2Rlc1xuICAgKi9cbiAgZGVzdGluYXRpb25bJ3ByZXBlbmQnXSA9IGZ1bmN0aW9uKC4uLm5vZGVzKSB7XG4gICAgLy8gVE9ETzogRml4IHRoaXMgZm9yIHdoZW4gb25lIG9mIGBub2Rlc2AgaXMgYSBEb2N1bWVudEZyYWdtZW50IVxuICAgIGNvbnN0IGNvbm5lY3RlZEJlZm9yZSA9IC8qKiBAdHlwZSB7IUFycmF5PCFOb2RlPn0gKi8gKG5vZGVzLmZpbHRlcihub2RlID0+IHtcbiAgICAgIC8vIERvY3VtZW50RnJhZ21lbnRzIGFyZSBub3QgY29ubmVjdGVkIGFuZCB3aWxsIG5vdCBiZSBhZGRlZCB0byB0aGUgbGlzdC5cbiAgICAgIHJldHVybiBub2RlIGluc3RhbmNlb2YgTm9kZSAmJiBVdGlsaXRpZXMuaXNDb25uZWN0ZWQobm9kZSk7XG4gICAgfSkpO1xuXG4gICAgYnVpbHRJbi5wcmVwZW5kLmFwcGx5KHRoaXMsIG5vZGVzKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29ubmVjdGVkQmVmb3JlLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpbnRlcm5hbHMuZGlzY29ubmVjdFRyZWUoY29ubmVjdGVkQmVmb3JlW2ldKTtcbiAgICB9XG5cbiAgICBpZiAoVXRpbGl0aWVzLmlzQ29ubmVjdGVkKHRoaXMpKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBFbGVtZW50KSB7XG4gICAgICAgICAgaW50ZXJuYWxzLmNvbm5lY3RUcmVlKG5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBAcGFyYW0gey4uLighTm9kZXxzdHJpbmcpfSBub2Rlc1xuICAgKi9cbiAgZGVzdGluYXRpb25bJ2FwcGVuZCddID0gZnVuY3Rpb24oLi4ubm9kZXMpIHtcbiAgICAvLyBUT0RPOiBGaXggdGhpcyBmb3Igd2hlbiBvbmUgb2YgYG5vZGVzYCBpcyBhIERvY3VtZW50RnJhZ21lbnQhXG4gICAgY29uc3QgY29ubmVjdGVkQmVmb3JlID0gLyoqIEB0eXBlIHshQXJyYXk8IU5vZGU+fSAqLyAobm9kZXMuZmlsdGVyKG5vZGUgPT4ge1xuICAgICAgLy8gRG9jdW1lbnRGcmFnbWVudHMgYXJlIG5vdCBjb25uZWN0ZWQgYW5kIHdpbGwgbm90IGJlIGFkZGVkIHRvIHRoZSBsaXN0LlxuICAgICAgcmV0dXJuIG5vZGUgaW5zdGFuY2VvZiBOb2RlICYmIFV0aWxpdGllcy5pc0Nvbm5lY3RlZChub2RlKTtcbiAgICB9KSk7XG5cbiAgICBidWlsdEluLmFwcGVuZC5hcHBseSh0aGlzLCBub2Rlcyk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvbm5lY3RlZEJlZm9yZS5sZW5ndGg7IGkrKykge1xuICAgICAgaW50ZXJuYWxzLmRpc2Nvbm5lY3RUcmVlKGNvbm5lY3RlZEJlZm9yZVtpXSk7XG4gICAgfVxuXG4gICAgaWYgKFV0aWxpdGllcy5pc0Nvbm5lY3RlZCh0aGlzKSkge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBub2RlID0gbm9kZXNbaV07XG4gICAgICAgIGlmIChub2RlIGluc3RhbmNlb2YgRWxlbWVudCkge1xuICAgICAgICAgIGludGVybmFscy5jb25uZWN0VHJlZShub2RlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcbn07XG4iLCJpbXBvcnQgTmF0aXZlIGZyb20gJy4vTmF0aXZlLmpzJztcbmltcG9ydCBDdXN0b21FbGVtZW50SW50ZXJuYWxzIGZyb20gJy4uL0N1c3RvbUVsZW1lbnRJbnRlcm5hbHMuanMnO1xuaW1wb3J0ICogYXMgVXRpbGl0aWVzIGZyb20gJy4uL1V0aWxpdGllcy5qcyc7XG5cbmltcG9ydCBQYXRjaFBhcmVudE5vZGUgZnJvbSAnLi9JbnRlcmZhY2UvUGFyZW50Tm9kZS5qcyc7XG5cbi8qKlxuICogQHBhcmFtIHshQ3VzdG9tRWxlbWVudEludGVybmFsc30gaW50ZXJuYWxzXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKGludGVybmFscykge1xuICBVdGlsaXRpZXMuc2V0UHJvcGVydHlVbmNoZWNrZWQoRG9jdW1lbnQucHJvdG90eXBlLCAnY3JlYXRlRWxlbWVudCcsXG4gICAgLyoqXG4gICAgICogQHRoaXMge0RvY3VtZW50fVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBsb2NhbE5hbWVcbiAgICAgKiBAcmV0dXJuIHshRWxlbWVudH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbihsb2NhbE5hbWUpIHtcbiAgICAgIC8vIE9ubHkgY3JlYXRlIGN1c3RvbSBlbGVtZW50cyBpZiB0aGlzIGRvY3VtZW50IGlzIGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVnaXN0cnkuXG4gICAgICBpZiAodGhpcy5fX0NFX2hhc1JlZ2lzdHJ5KSB7XG4gICAgICAgIGNvbnN0IGRlZmluaXRpb24gPSBpbnRlcm5hbHMubG9jYWxOYW1lVG9EZWZpbml0aW9uKGxvY2FsTmFtZSk7XG4gICAgICAgIGlmIChkZWZpbml0aW9uKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyAoZGVmaW5pdGlvbi5jb25zdHJ1Y3RvcikoKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCByZXN1bHQgPSAvKiogQHR5cGUgeyFFbGVtZW50fSAqL1xuICAgICAgICAoTmF0aXZlLkRvY3VtZW50X2NyZWF0ZUVsZW1lbnQuY2FsbCh0aGlzLCBsb2NhbE5hbWUpKTtcbiAgICAgIGludGVybmFscy5wYXRjaChyZXN1bHQpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcblxuICBVdGlsaXRpZXMuc2V0UHJvcGVydHlVbmNoZWNrZWQoRG9jdW1lbnQucHJvdG90eXBlLCAnaW1wb3J0Tm9kZScsXG4gICAgLyoqXG4gICAgICogQHRoaXMge0RvY3VtZW50fVxuICAgICAqIEBwYXJhbSB7IU5vZGV9IG5vZGVcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBkZWVwXG4gICAgICogQHJldHVybiB7IU5vZGV9XG4gICAgICovXG4gICAgZnVuY3Rpb24obm9kZSwgZGVlcCkge1xuICAgICAgY29uc3QgY2xvbmUgPSBOYXRpdmUuRG9jdW1lbnRfaW1wb3J0Tm9kZS5jYWxsKHRoaXMsIG5vZGUsIGRlZXApO1xuICAgICAgLy8gT25seSBjcmVhdGUgY3VzdG9tIGVsZW1lbnRzIGlmIHRoaXMgZG9jdW1lbnQgaXMgYXNzb2NpYXRlZCB3aXRoIHRoZSByZWdpc3RyeS5cbiAgICAgIGlmICghdGhpcy5fX0NFX2hhc1JlZ2lzdHJ5KSB7XG4gICAgICAgIGludGVybmFscy5wYXRjaFRyZWUoY2xvbmUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW50ZXJuYWxzLnBhdGNoQW5kVXBncmFkZVRyZWUoY2xvbmUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNsb25lO1xuICAgIH0pO1xuXG4gIGNvbnN0IE5TX0hUTUwgPSBcImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWxcIjtcblxuICBVdGlsaXRpZXMuc2V0UHJvcGVydHlVbmNoZWNrZWQoRG9jdW1lbnQucHJvdG90eXBlLCAnY3JlYXRlRWxlbWVudE5TJyxcbiAgICAvKipcbiAgICAgKiBAdGhpcyB7RG9jdW1lbnR9XG4gICAgICogQHBhcmFtIHs/c3RyaW5nfSBuYW1lc3BhY2VcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbG9jYWxOYW1lXG4gICAgICogQHJldHVybiB7IUVsZW1lbnR9XG4gICAgICovXG4gICAgZnVuY3Rpb24obmFtZXNwYWNlLCBsb2NhbE5hbWUpIHtcbiAgICAgIC8vIE9ubHkgY3JlYXRlIGN1c3RvbSBlbGVtZW50cyBpZiB0aGlzIGRvY3VtZW50IGlzIGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVnaXN0cnkuXG4gICAgICBpZiAodGhpcy5fX0NFX2hhc1JlZ2lzdHJ5ICYmIChuYW1lc3BhY2UgPT09IG51bGwgfHwgbmFtZXNwYWNlID09PSBOU19IVE1MKSkge1xuICAgICAgICBjb25zdCBkZWZpbml0aW9uID0gaW50ZXJuYWxzLmxvY2FsTmFtZVRvRGVmaW5pdGlvbihsb2NhbE5hbWUpO1xuICAgICAgICBpZiAoZGVmaW5pdGlvbikge1xuICAgICAgICAgIHJldHVybiBuZXcgKGRlZmluaXRpb24uY29uc3RydWN0b3IpKCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVzdWx0ID0gLyoqIEB0eXBlIHshRWxlbWVudH0gKi9cbiAgICAgICAgKE5hdGl2ZS5Eb2N1bWVudF9jcmVhdGVFbGVtZW50TlMuY2FsbCh0aGlzLCBuYW1lc3BhY2UsIGxvY2FsTmFtZSkpO1xuICAgICAgaW50ZXJuYWxzLnBhdGNoKHJlc3VsdCk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gIFBhdGNoUGFyZW50Tm9kZShpbnRlcm5hbHMsIERvY3VtZW50LnByb3RvdHlwZSwge1xuICAgIHByZXBlbmQ6IE5hdGl2ZS5Eb2N1bWVudF9wcmVwZW5kLFxuICAgIGFwcGVuZDogTmF0aXZlLkRvY3VtZW50X2FwcGVuZCxcbiAgfSk7XG59O1xuIiwiaW1wb3J0IE5hdGl2ZSBmcm9tICcuL05hdGl2ZS5qcyc7XG5pbXBvcnQgQ3VzdG9tRWxlbWVudEludGVybmFscyBmcm9tICcuLi9DdXN0b21FbGVtZW50SW50ZXJuYWxzLmpzJztcbmltcG9ydCAqIGFzIFV0aWxpdGllcyBmcm9tICcuLi9VdGlsaXRpZXMuanMnO1xuXG4vKipcbiAqIEBwYXJhbSB7IUN1c3RvbUVsZW1lbnRJbnRlcm5hbHN9IGludGVybmFsc1xuICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnRlcm5hbHMpIHtcbiAgLy8gYE5vZGUjbm9kZVZhbHVlYCBpcyBpbXBsZW1lbnRlZCBvbiBgQXR0cmAuXG4gIC8vIGBOb2RlI3RleHRDb250ZW50YCBpcyBpbXBsZW1lbnRlZCBvbiBgQXR0cmAsIGBFbGVtZW50YC5cblxuICBVdGlsaXRpZXMuc2V0UHJvcGVydHlVbmNoZWNrZWQoTm9kZS5wcm90b3R5cGUsICdpbnNlcnRCZWZvcmUnLFxuICAgIC8qKlxuICAgICAqIEB0aGlzIHtOb2RlfVxuICAgICAqIEBwYXJhbSB7IU5vZGV9IG5vZGVcbiAgICAgKiBAcGFyYW0gez9Ob2RlfSByZWZOb2RlXG4gICAgICogQHJldHVybiB7IU5vZGV9XG4gICAgICovXG4gICAgZnVuY3Rpb24obm9kZSwgcmVmTm9kZSkge1xuICAgICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBEb2N1bWVudEZyYWdtZW50KSB7XG4gICAgICAgIGNvbnN0IGluc2VydGVkTm9kZXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuYXBwbHkobm9kZS5jaGlsZE5vZGVzKTtcbiAgICAgICAgY29uc3QgbmF0aXZlUmVzdWx0ID0gTmF0aXZlLk5vZGVfaW5zZXJ0QmVmb3JlLmNhbGwodGhpcywgbm9kZSwgcmVmTm9kZSk7XG5cbiAgICAgICAgLy8gRG9jdW1lbnRGcmFnbWVudHMgY2FuJ3QgYmUgY29ubmVjdGVkLCBzbyBgZGlzY29ubmVjdFRyZWVgIHdpbGwgbmV2ZXJcbiAgICAgICAgLy8gbmVlZCB0byBiZSBjYWxsZWQgb24gYSBEb2N1bWVudEZyYWdtZW50J3MgY2hpbGRyZW4gYWZ0ZXIgaW5zZXJ0aW5nIGl0LlxuXG4gICAgICAgIGlmIChVdGlsaXRpZXMuaXNDb25uZWN0ZWQodGhpcykpIHtcbiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGluc2VydGVkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGludGVybmFscy5jb25uZWN0VHJlZShpbnNlcnRlZE5vZGVzW2ldKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbmF0aXZlUmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBub2RlV2FzQ29ubmVjdGVkID0gVXRpbGl0aWVzLmlzQ29ubmVjdGVkKG5vZGUpO1xuICAgICAgY29uc3QgbmF0aXZlUmVzdWx0ID0gTmF0aXZlLk5vZGVfaW5zZXJ0QmVmb3JlLmNhbGwodGhpcywgbm9kZSwgcmVmTm9kZSk7XG5cbiAgICAgIGlmIChub2RlV2FzQ29ubmVjdGVkKSB7XG4gICAgICAgIGludGVybmFscy5kaXNjb25uZWN0VHJlZShub2RlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKFV0aWxpdGllcy5pc0Nvbm5lY3RlZCh0aGlzKSkge1xuICAgICAgICBpbnRlcm5hbHMuY29ubmVjdFRyZWUobm9kZSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBuYXRpdmVSZXN1bHQ7XG4gICAgfSk7XG5cbiAgVXRpbGl0aWVzLnNldFByb3BlcnR5VW5jaGVja2VkKE5vZGUucHJvdG90eXBlLCAnYXBwZW5kQ2hpbGQnLFxuICAgIC8qKlxuICAgICAqIEB0aGlzIHtOb2RlfVxuICAgICAqIEBwYXJhbSB7IU5vZGV9IG5vZGVcbiAgICAgKiBAcmV0dXJuIHshTm9kZX1cbiAgICAgKi9cbiAgICBmdW5jdGlvbihub2RlKSB7XG4gICAgICBpZiAobm9kZSBpbnN0YW5jZW9mIERvY3VtZW50RnJhZ21lbnQpIHtcbiAgICAgICAgY29uc3QgaW5zZXJ0ZWROb2RlcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5hcHBseShub2RlLmNoaWxkTm9kZXMpO1xuICAgICAgICBjb25zdCBuYXRpdmVSZXN1bHQgPSBOYXRpdmUuTm9kZV9hcHBlbmRDaGlsZC5jYWxsKHRoaXMsIG5vZGUpO1xuXG4gICAgICAgIC8vIERvY3VtZW50RnJhZ21lbnRzIGNhbid0IGJlIGNvbm5lY3RlZCwgc28gYGRpc2Nvbm5lY3RUcmVlYCB3aWxsIG5ldmVyXG4gICAgICAgIC8vIG5lZWQgdG8gYmUgY2FsbGVkIG9uIGEgRG9jdW1lbnRGcmFnbWVudCdzIGNoaWxkcmVuIGFmdGVyIGluc2VydGluZyBpdC5cblxuICAgICAgICBpZiAoVXRpbGl0aWVzLmlzQ29ubmVjdGVkKHRoaXMpKSB7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnNlcnRlZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpbnRlcm5hbHMuY29ubmVjdFRyZWUoaW5zZXJ0ZWROb2Rlc1tpXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5hdGl2ZVJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgbm9kZVdhc0Nvbm5lY3RlZCA9IFV0aWxpdGllcy5pc0Nvbm5lY3RlZChub2RlKTtcbiAgICAgIGNvbnN0IG5hdGl2ZVJlc3VsdCA9IE5hdGl2ZS5Ob2RlX2FwcGVuZENoaWxkLmNhbGwodGhpcywgbm9kZSk7XG5cbiAgICAgIGlmIChub2RlV2FzQ29ubmVjdGVkKSB7XG4gICAgICAgIGludGVybmFscy5kaXNjb25uZWN0VHJlZShub2RlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKFV0aWxpdGllcy5pc0Nvbm5lY3RlZCh0aGlzKSkge1xuICAgICAgICBpbnRlcm5hbHMuY29ubmVjdFRyZWUobm9kZSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBuYXRpdmVSZXN1bHQ7XG4gICAgfSk7XG5cbiAgVXRpbGl0aWVzLnNldFByb3BlcnR5VW5jaGVja2VkKE5vZGUucHJvdG90eXBlLCAnY2xvbmVOb2RlJyxcbiAgICAvKipcbiAgICAgKiBAdGhpcyB7Tm9kZX1cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBkZWVwXG4gICAgICogQHJldHVybiB7IU5vZGV9XG4gICAgICovXG4gICAgZnVuY3Rpb24oZGVlcCkge1xuICAgICAgY29uc3QgY2xvbmUgPSBOYXRpdmUuTm9kZV9jbG9uZU5vZGUuY2FsbCh0aGlzLCBkZWVwKTtcbiAgICAgIC8vIE9ubHkgY3JlYXRlIGN1c3RvbSBlbGVtZW50cyBpZiB0aGlzIGVsZW1lbnQncyBvd25lciBkb2N1bWVudCBpc1xuICAgICAgLy8gYXNzb2NpYXRlZCB3aXRoIHRoZSByZWdpc3RyeS5cbiAgICAgIGlmICghdGhpcy5vd25lckRvY3VtZW50Ll9fQ0VfaGFzUmVnaXN0cnkpIHtcbiAgICAgICAgaW50ZXJuYWxzLnBhdGNoVHJlZShjbG9uZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbnRlcm5hbHMucGF0Y2hBbmRVcGdyYWRlVHJlZShjbG9uZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gY2xvbmU7XG4gICAgfSk7XG5cbiAgVXRpbGl0aWVzLnNldFByb3BlcnR5VW5jaGVja2VkKE5vZGUucHJvdG90eXBlLCAncmVtb3ZlQ2hpbGQnLFxuICAgIC8qKlxuICAgICAqIEB0aGlzIHtOb2RlfVxuICAgICAqIEBwYXJhbSB7IU5vZGV9IG5vZGVcbiAgICAgKiBAcmV0dXJuIHshTm9kZX1cbiAgICAgKi9cbiAgICBmdW5jdGlvbihub2RlKSB7XG4gICAgICBjb25zdCBub2RlV2FzQ29ubmVjdGVkID0gVXRpbGl0aWVzLmlzQ29ubmVjdGVkKG5vZGUpO1xuICAgICAgY29uc3QgbmF0aXZlUmVzdWx0ID0gTmF0aXZlLk5vZGVfcmVtb3ZlQ2hpbGQuY2FsbCh0aGlzLCBub2RlKTtcblxuICAgICAgaWYgKG5vZGVXYXNDb25uZWN0ZWQpIHtcbiAgICAgICAgaW50ZXJuYWxzLmRpc2Nvbm5lY3RUcmVlKG5vZGUpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gbmF0aXZlUmVzdWx0O1xuICAgIH0pO1xuXG4gIFV0aWxpdGllcy5zZXRQcm9wZXJ0eVVuY2hlY2tlZChOb2RlLnByb3RvdHlwZSwgJ3JlcGxhY2VDaGlsZCcsXG4gICAgLyoqXG4gICAgICogQHRoaXMge05vZGV9XG4gICAgICogQHBhcmFtIHshTm9kZX0gbm9kZVRvSW5zZXJ0XG4gICAgICogQHBhcmFtIHshTm9kZX0gbm9kZVRvUmVtb3ZlXG4gICAgICogQHJldHVybiB7IU5vZGV9XG4gICAgICovXG4gICAgZnVuY3Rpb24obm9kZVRvSW5zZXJ0LCBub2RlVG9SZW1vdmUpIHtcbiAgICAgIGlmIChub2RlVG9JbnNlcnQgaW5zdGFuY2VvZiBEb2N1bWVudEZyYWdtZW50KSB7XG4gICAgICAgIGNvbnN0IGluc2VydGVkTm9kZXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuYXBwbHkobm9kZVRvSW5zZXJ0LmNoaWxkTm9kZXMpO1xuICAgICAgICBjb25zdCBuYXRpdmVSZXN1bHQgPSBOYXRpdmUuTm9kZV9yZXBsYWNlQ2hpbGQuY2FsbCh0aGlzLCBub2RlVG9JbnNlcnQsIG5vZGVUb1JlbW92ZSk7XG5cbiAgICAgICAgLy8gRG9jdW1lbnRGcmFnbWVudHMgY2FuJ3QgYmUgY29ubmVjdGVkLCBzbyBgZGlzY29ubmVjdFRyZWVgIHdpbGwgbmV2ZXJcbiAgICAgICAgLy8gbmVlZCB0byBiZSBjYWxsZWQgb24gYSBEb2N1bWVudEZyYWdtZW50J3MgY2hpbGRyZW4gYWZ0ZXIgaW5zZXJ0aW5nIGl0LlxuXG4gICAgICAgIGlmIChVdGlsaXRpZXMuaXNDb25uZWN0ZWQodGhpcykpIHtcbiAgICAgICAgICBpbnRlcm5hbHMuZGlzY29ubmVjdFRyZWUobm9kZVRvUmVtb3ZlKTtcbiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGluc2VydGVkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGludGVybmFscy5jb25uZWN0VHJlZShpbnNlcnRlZE5vZGVzW2ldKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbmF0aXZlUmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBub2RlVG9JbnNlcnRXYXNDb25uZWN0ZWQgPSBVdGlsaXRpZXMuaXNDb25uZWN0ZWQobm9kZVRvSW5zZXJ0KTtcbiAgICAgIGNvbnN0IG5hdGl2ZVJlc3VsdCA9IE5hdGl2ZS5Ob2RlX3JlcGxhY2VDaGlsZC5jYWxsKHRoaXMsIG5vZGVUb0luc2VydCwgbm9kZVRvUmVtb3ZlKTtcbiAgICAgIGNvbnN0IHRoaXNJc0Nvbm5lY3RlZCA9IFV0aWxpdGllcy5pc0Nvbm5lY3RlZCh0aGlzKTtcblxuICAgICAgaWYgKHRoaXNJc0Nvbm5lY3RlZCkge1xuICAgICAgICBpbnRlcm5hbHMuZGlzY29ubmVjdFRyZWUobm9kZVRvUmVtb3ZlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG5vZGVUb0luc2VydFdhc0Nvbm5lY3RlZCkge1xuICAgICAgICBpbnRlcm5hbHMuZGlzY29ubmVjdFRyZWUobm9kZVRvSW5zZXJ0KTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXNJc0Nvbm5lY3RlZCkge1xuICAgICAgICBpbnRlcm5hbHMuY29ubmVjdFRyZWUobm9kZVRvSW5zZXJ0KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5hdGl2ZVJlc3VsdDtcbiAgICB9KTtcblxuXG4gIGZ1bmN0aW9uIHBhdGNoX3RleHRDb250ZW50KGRlc3RpbmF0aW9uLCBiYXNlRGVzY3JpcHRvcikge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShkZXN0aW5hdGlvbiwgJ3RleHRDb250ZW50Jywge1xuICAgICAgZW51bWVyYWJsZTogYmFzZURlc2NyaXB0b3IuZW51bWVyYWJsZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIGdldDogYmFzZURlc2NyaXB0b3IuZ2V0LFxuICAgICAgc2V0OiAvKiogQHRoaXMge05vZGV9ICovIGZ1bmN0aW9uKGFzc2lnbmVkVmFsdWUpIHtcbiAgICAgICAgLy8gSWYgdGhpcyBpcyBhIHRleHQgbm9kZSB0aGVuIHRoZXJlIGFyZSBubyBub2RlcyB0byBkaXNjb25uZWN0LlxuICAgICAgICBpZiAodGhpcy5ub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREUpIHtcbiAgICAgICAgICBiYXNlRGVzY3JpcHRvci5zZXQuY2FsbCh0aGlzLCBhc3NpZ25lZFZhbHVlKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmVtb3ZlZE5vZGVzID0gdW5kZWZpbmVkO1xuICAgICAgICAvLyBDaGVja2luZyBmb3IgYGZpcnN0Q2hpbGRgIGlzIGZhc3RlciB0aGFuIHJlYWRpbmcgYGNoaWxkTm9kZXMubGVuZ3RoYFxuICAgICAgICAvLyB0byBjb21wYXJlIHdpdGggMC5cbiAgICAgICAgaWYgKHRoaXMuZmlyc3RDaGlsZCkge1xuICAgICAgICAgIC8vIFVzaW5nIGBjaGlsZE5vZGVzYCBpcyBmYXN0ZXIgdGhhbiBgY2hpbGRyZW5gLCBldmVuIHRob3VnaCB3ZSBvbmx5XG4gICAgICAgICAgLy8gY2FyZSBhYm91dCBlbGVtZW50cy5cbiAgICAgICAgICBjb25zdCBjaGlsZE5vZGVzID0gdGhpcy5jaGlsZE5vZGVzO1xuICAgICAgICAgIGNvbnN0IGNoaWxkTm9kZXNMZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICBpZiAoY2hpbGROb2Rlc0xlbmd0aCA+IDAgJiYgVXRpbGl0aWVzLmlzQ29ubmVjdGVkKHRoaXMpKSB7XG4gICAgICAgICAgICAvLyBDb3B5aW5nIGFuIGFycmF5IGJ5IGl0ZXJhdGluZyBpcyBmYXN0ZXIgdGhhbiB1c2luZyBzbGljZS5cbiAgICAgICAgICAgIHJlbW92ZWROb2RlcyA9IG5ldyBBcnJheShjaGlsZE5vZGVzTGVuZ3RoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hpbGROb2Rlc0xlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgIHJlbW92ZWROb2Rlc1tpXSA9IGNoaWxkTm9kZXNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgYmFzZURlc2NyaXB0b3Iuc2V0LmNhbGwodGhpcywgYXNzaWduZWRWYWx1ZSk7XG5cbiAgICAgICAgaWYgKHJlbW92ZWROb2Rlcykge1xuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVtb3ZlZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpbnRlcm5hbHMuZGlzY29ubmVjdFRyZWUocmVtb3ZlZE5vZGVzW2ldKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBpZiAoTmF0aXZlLk5vZGVfdGV4dENvbnRlbnQgJiYgTmF0aXZlLk5vZGVfdGV4dENvbnRlbnQuZ2V0KSB7XG4gICAgcGF0Y2hfdGV4dENvbnRlbnQoTm9kZS5wcm90b3R5cGUsIE5hdGl2ZS5Ob2RlX3RleHRDb250ZW50KTtcbiAgfSBlbHNlIHtcbiAgICBpbnRlcm5hbHMuYWRkUGF0Y2goZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgcGF0Y2hfdGV4dENvbnRlbnQoZWxlbWVudCwge1xuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgIC8vIE5PVEU6IFRoaXMgaW1wbGVtZW50YXRpb24gb2YgdGhlIGB0ZXh0Q29udGVudGAgZ2V0dGVyIGFzc3VtZXMgdGhhdFxuICAgICAgICAvLyB0ZXh0IG5vZGVzJyBgdGV4dENvbnRlbnRgIGdldHRlciB3aWxsIG5vdCBiZSBwYXRjaGVkLlxuICAgICAgICBnZXQ6IC8qKiBAdGhpcyB7Tm9kZX0gKi8gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgLyoqIEB0eXBlIHshQXJyYXk8c3RyaW5nPn0gKi9cbiAgICAgICAgICBjb25zdCBwYXJ0cyA9IFtdO1xuXG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHBhcnRzLnB1c2godGhpcy5jaGlsZE5vZGVzW2ldLnRleHRDb250ZW50KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gcGFydHMuam9pbignJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHNldDogLyoqIEB0aGlzIHtOb2RlfSAqLyBmdW5jdGlvbihhc3NpZ25lZFZhbHVlKSB7XG4gICAgICAgICAgd2hpbGUgKHRoaXMuZmlyc3RDaGlsZCkge1xuICAgICAgICAgICAgTmF0aXZlLk5vZGVfcmVtb3ZlQ2hpbGQuY2FsbCh0aGlzLCB0aGlzLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBOYXRpdmUuTm9kZV9hcHBlbmRDaGlsZC5jYWxsKHRoaXMsIGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGFzc2lnbmVkVmFsdWUpKTtcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG59O1xuIiwiaW1wb3J0IEN1c3RvbUVsZW1lbnRJbnRlcm5hbHMgZnJvbSAnLi4vLi4vQ3VzdG9tRWxlbWVudEludGVybmFscy5qcyc7XG5pbXBvcnQgKiBhcyBVdGlsaXRpZXMgZnJvbSAnLi4vLi4vVXRpbGl0aWVzLmpzJztcblxuLyoqXG4gKiBAdHlwZWRlZiB7e1xuICogICBiZWZvcmU6ICFmdW5jdGlvbiguLi4oIU5vZGV8c3RyaW5nKSksXG4gKiAgIGFmdGVyOiAhZnVuY3Rpb24oLi4uKCFOb2RlfHN0cmluZykpLFxuICogICByZXBsYWNlV2l0aDogIWZ1bmN0aW9uKC4uLighTm9kZXxzdHJpbmcpKSxcbiAqICAgcmVtb3ZlOiAhZnVuY3Rpb24oKSxcbiAqIH19XG4gKi9cbmxldCBDaGlsZE5vZGVOYXRpdmVNZXRob2RzO1xuXG4vKipcbiAqIEBwYXJhbSB7IUN1c3RvbUVsZW1lbnRJbnRlcm5hbHN9IGludGVybmFsc1xuICogQHBhcmFtIHshT2JqZWN0fSBkZXN0aW5hdGlvblxuICogQHBhcmFtIHshQ2hpbGROb2RlTmF0aXZlTWV0aG9kc30gYnVpbHRJblxuICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnRlcm5hbHMsIGRlc3RpbmF0aW9uLCBidWlsdEluKSB7XG4gIC8qKlxuICAgKiBAcGFyYW0gey4uLighTm9kZXxzdHJpbmcpfSBub2Rlc1xuICAgKi9cbiAgZGVzdGluYXRpb25bJ2JlZm9yZSddID0gZnVuY3Rpb24oLi4ubm9kZXMpIHtcbiAgICAvLyBUT0RPOiBGaXggdGhpcyBmb3Igd2hlbiBvbmUgb2YgYG5vZGVzYCBpcyBhIERvY3VtZW50RnJhZ21lbnQhXG4gICAgY29uc3QgY29ubmVjdGVkQmVmb3JlID0gLyoqIEB0eXBlIHshQXJyYXk8IU5vZGU+fSAqLyAobm9kZXMuZmlsdGVyKG5vZGUgPT4ge1xuICAgICAgLy8gRG9jdW1lbnRGcmFnbWVudHMgYXJlIG5vdCBjb25uZWN0ZWQgYW5kIHdpbGwgbm90IGJlIGFkZGVkIHRvIHRoZSBsaXN0LlxuICAgICAgcmV0dXJuIG5vZGUgaW5zdGFuY2VvZiBOb2RlICYmIFV0aWxpdGllcy5pc0Nvbm5lY3RlZChub2RlKTtcbiAgICB9KSk7XG5cbiAgICBidWlsdEluLmJlZm9yZS5hcHBseSh0aGlzLCBub2Rlcyk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvbm5lY3RlZEJlZm9yZS5sZW5ndGg7IGkrKykge1xuICAgICAgaW50ZXJuYWxzLmRpc2Nvbm5lY3RUcmVlKGNvbm5lY3RlZEJlZm9yZVtpXSk7XG4gICAgfVxuXG4gICAgaWYgKFV0aWxpdGllcy5pc0Nvbm5lY3RlZCh0aGlzKSkge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBub2RlID0gbm9kZXNbaV07XG4gICAgICAgIGlmIChub2RlIGluc3RhbmNlb2YgRWxlbWVudCkge1xuICAgICAgICAgIGludGVybmFscy5jb25uZWN0VHJlZShub2RlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQHBhcmFtIHsuLi4oIU5vZGV8c3RyaW5nKX0gbm9kZXNcbiAgICovXG4gIGRlc3RpbmF0aW9uWydhZnRlciddID0gZnVuY3Rpb24oLi4ubm9kZXMpIHtcbiAgICAvLyBUT0RPOiBGaXggdGhpcyBmb3Igd2hlbiBvbmUgb2YgYG5vZGVzYCBpcyBhIERvY3VtZW50RnJhZ21lbnQhXG4gICAgY29uc3QgY29ubmVjdGVkQmVmb3JlID0gLyoqIEB0eXBlIHshQXJyYXk8IU5vZGU+fSAqLyAobm9kZXMuZmlsdGVyKG5vZGUgPT4ge1xuICAgICAgLy8gRG9jdW1lbnRGcmFnbWVudHMgYXJlIG5vdCBjb25uZWN0ZWQgYW5kIHdpbGwgbm90IGJlIGFkZGVkIHRvIHRoZSBsaXN0LlxuICAgICAgcmV0dXJuIG5vZGUgaW5zdGFuY2VvZiBOb2RlICYmIFV0aWxpdGllcy5pc0Nvbm5lY3RlZChub2RlKTtcbiAgICB9KSk7XG5cbiAgICBidWlsdEluLmFmdGVyLmFwcGx5KHRoaXMsIG5vZGVzKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29ubmVjdGVkQmVmb3JlLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpbnRlcm5hbHMuZGlzY29ubmVjdFRyZWUoY29ubmVjdGVkQmVmb3JlW2ldKTtcbiAgICB9XG5cbiAgICBpZiAoVXRpbGl0aWVzLmlzQ29ubmVjdGVkKHRoaXMpKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBFbGVtZW50KSB7XG4gICAgICAgICAgaW50ZXJuYWxzLmNvbm5lY3RUcmVlKG5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBAcGFyYW0gey4uLighTm9kZXxzdHJpbmcpfSBub2Rlc1xuICAgKi9cbiAgZGVzdGluYXRpb25bJ3JlcGxhY2VXaXRoJ10gPSBmdW5jdGlvbiguLi5ub2Rlcykge1xuICAgIC8vIFRPRE86IEZpeCB0aGlzIGZvciB3aGVuIG9uZSBvZiBgbm9kZXNgIGlzIGEgRG9jdW1lbnRGcmFnbWVudCFcbiAgICBjb25zdCBjb25uZWN0ZWRCZWZvcmUgPSAvKiogQHR5cGUgeyFBcnJheTwhTm9kZT59ICovIChub2Rlcy5maWx0ZXIobm9kZSA9PiB7XG4gICAgICAvLyBEb2N1bWVudEZyYWdtZW50cyBhcmUgbm90IGNvbm5lY3RlZCBhbmQgd2lsbCBub3QgYmUgYWRkZWQgdG8gdGhlIGxpc3QuXG4gICAgICByZXR1cm4gbm9kZSBpbnN0YW5jZW9mIE5vZGUgJiYgVXRpbGl0aWVzLmlzQ29ubmVjdGVkKG5vZGUpO1xuICAgIH0pKTtcblxuICAgIGNvbnN0IHdhc0Nvbm5lY3RlZCA9IFV0aWxpdGllcy5pc0Nvbm5lY3RlZCh0aGlzKTtcblxuICAgIGJ1aWx0SW4ucmVwbGFjZVdpdGguYXBwbHkodGhpcywgbm9kZXMpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb25uZWN0ZWRCZWZvcmUubGVuZ3RoOyBpKyspIHtcbiAgICAgIGludGVybmFscy5kaXNjb25uZWN0VHJlZShjb25uZWN0ZWRCZWZvcmVbaV0pO1xuICAgIH1cblxuICAgIGlmICh3YXNDb25uZWN0ZWQpIHtcbiAgICAgIGludGVybmFscy5kaXNjb25uZWN0VHJlZSh0aGlzKTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3Qgbm9kZSA9IG5vZGVzW2ldO1xuICAgICAgICBpZiAobm9kZSBpbnN0YW5jZW9mIEVsZW1lbnQpIHtcbiAgICAgICAgICBpbnRlcm5hbHMuY29ubmVjdFRyZWUobm9kZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgZGVzdGluYXRpb25bJ3JlbW92ZSddID0gZnVuY3Rpb24oKSB7XG4gICAgY29uc3Qgd2FzQ29ubmVjdGVkID0gVXRpbGl0aWVzLmlzQ29ubmVjdGVkKHRoaXMpO1xuXG4gICAgYnVpbHRJbi5yZW1vdmUuY2FsbCh0aGlzKTtcblxuICAgIGlmICh3YXNDb25uZWN0ZWQpIHtcbiAgICAgIGludGVybmFscy5kaXNjb25uZWN0VHJlZSh0aGlzKTtcbiAgICB9XG4gIH07XG59O1xuIiwiaW1wb3J0IE5hdGl2ZSBmcm9tICcuL05hdGl2ZS5qcyc7XG5pbXBvcnQgQ3VzdG9tRWxlbWVudEludGVybmFscyBmcm9tICcuLi9DdXN0b21FbGVtZW50SW50ZXJuYWxzLmpzJztcbmltcG9ydCBDRVN0YXRlIGZyb20gJy4uL0N1c3RvbUVsZW1lbnRTdGF0ZS5qcyc7XG5pbXBvcnQgKiBhcyBVdGlsaXRpZXMgZnJvbSAnLi4vVXRpbGl0aWVzLmpzJztcblxuaW1wb3J0IFBhdGNoUGFyZW50Tm9kZSBmcm9tICcuL0ludGVyZmFjZS9QYXJlbnROb2RlLmpzJztcbmltcG9ydCBQYXRjaENoaWxkTm9kZSBmcm9tICcuL0ludGVyZmFjZS9DaGlsZE5vZGUuanMnO1xuXG4vKipcbiAqIEBwYXJhbSB7IUN1c3RvbUVsZW1lbnRJbnRlcm5hbHN9IGludGVybmFsc1xuICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnRlcm5hbHMpIHtcbiAgaWYgKE5hdGl2ZS5FbGVtZW50X2F0dGFjaFNoYWRvdykge1xuICAgIFV0aWxpdGllcy5zZXRQcm9wZXJ0eVVuY2hlY2tlZChFbGVtZW50LnByb3RvdHlwZSwgJ2F0dGFjaFNoYWRvdycsXG4gICAgICAvKipcbiAgICAgICAqIEB0aGlzIHtFbGVtZW50fVxuICAgICAgICogQHBhcmFtIHshe21vZGU6IHN0cmluZ319IGluaXRcbiAgICAgICAqIEByZXR1cm4ge1NoYWRvd1Jvb3R9XG4gICAgICAgKi9cbiAgICAgIGZ1bmN0aW9uKGluaXQpIHtcbiAgICAgICAgY29uc3Qgc2hhZG93Um9vdCA9IE5hdGl2ZS5FbGVtZW50X2F0dGFjaFNoYWRvdy5jYWxsKHRoaXMsIGluaXQpO1xuICAgICAgICB0aGlzLl9fQ0Vfc2hhZG93Um9vdCA9IHNoYWRvd1Jvb3Q7XG4gICAgICAgIHJldHVybiBzaGFkb3dSb290O1xuICAgICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS53YXJuKCdDdXN0b20gRWxlbWVudHM6IGBFbGVtZW50I2F0dGFjaFNoYWRvd2Agd2FzIG5vdCBwYXRjaGVkLicpO1xuICB9XG5cblxuICBmdW5jdGlvbiBwYXRjaF9pbm5lckhUTUwoZGVzdGluYXRpb24sIGJhc2VEZXNjcmlwdG9yKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGRlc3RpbmF0aW9uLCAnaW5uZXJIVE1MJywge1xuICAgICAgZW51bWVyYWJsZTogYmFzZURlc2NyaXB0b3IuZW51bWVyYWJsZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIGdldDogYmFzZURlc2NyaXB0b3IuZ2V0LFxuICAgICAgc2V0OiAvKiogQHRoaXMge0VsZW1lbnR9ICovIGZ1bmN0aW9uKGh0bWxTdHJpbmcpIHtcbiAgICAgICAgY29uc3QgaXNDb25uZWN0ZWQgPSBVdGlsaXRpZXMuaXNDb25uZWN0ZWQodGhpcyk7XG5cbiAgICAgICAgLy8gTk9URTogSW4gSUUxMSwgd2hlbiB1c2luZyB0aGUgbmF0aXZlIGBpbm5lckhUTUxgIHNldHRlciwgYWxsIG5vZGVzXG4gICAgICAgIC8vIHRoYXQgd2VyZSBwcmV2aW91c2x5IGRlc2NlbmRhbnRzIG9mIHRoZSBjb250ZXh0IGVsZW1lbnQgaGF2ZSBhbGwgb2ZcbiAgICAgICAgLy8gdGhlaXIgY2hpbGRyZW4gcmVtb3ZlZCBhcyBwYXJ0IG9mIHRoZSBzZXQgLSB0aGUgZW50aXJlIHN1YnRyZWUgaXNcbiAgICAgICAgLy8gJ2Rpc2Fzc2VtYmxlZCcuIFRoaXMgd29yayBhcm91bmQgd2Fsa3MgdGhlIHN1YnRyZWUgKmJlZm9yZSogdXNpbmcgdGhlXG4gICAgICAgIC8vIG5hdGl2ZSBzZXR0ZXIuXG4gICAgICAgIC8qKiBAdHlwZSB7IUFycmF5PCFFbGVtZW50Pnx1bmRlZmluZWR9ICovXG4gICAgICAgIGxldCByZW1vdmVkRWxlbWVudHMgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChpc0Nvbm5lY3RlZCkge1xuICAgICAgICAgIHJlbW92ZWRFbGVtZW50cyA9IFtdO1xuICAgICAgICAgIFV0aWxpdGllcy53YWxrRGVlcERlc2NlbmRhbnRFbGVtZW50cyh0aGlzLCBlbGVtZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChlbGVtZW50ICE9PSB0aGlzKSB7XG4gICAgICAgICAgICAgIHJlbW92ZWRFbGVtZW50cy5wdXNoKGVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgYmFzZURlc2NyaXB0b3Iuc2V0LmNhbGwodGhpcywgaHRtbFN0cmluZyk7XG5cbiAgICAgICAgaWYgKHJlbW92ZWRFbGVtZW50cykge1xuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVtb3ZlZEVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBlbGVtZW50ID0gcmVtb3ZlZEVsZW1lbnRzW2ldO1xuICAgICAgICAgICAgaWYgKGVsZW1lbnQuX19DRV9zdGF0ZSA9PT0gQ0VTdGF0ZS5jdXN0b20pIHtcbiAgICAgICAgICAgICAgaW50ZXJuYWxzLmRpc2Nvbm5lY3RlZENhbGxiYWNrKGVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE9ubHkgY3JlYXRlIGN1c3RvbSBlbGVtZW50cyBpZiB0aGlzIGVsZW1lbnQncyBvd25lciBkb2N1bWVudCBpc1xuICAgICAgICAvLyBhc3NvY2lhdGVkIHdpdGggdGhlIHJlZ2lzdHJ5LlxuICAgICAgICBpZiAoIXRoaXMub3duZXJEb2N1bWVudC5fX0NFX2hhc1JlZ2lzdHJ5KSB7XG4gICAgICAgICAgaW50ZXJuYWxzLnBhdGNoVHJlZSh0aGlzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpbnRlcm5hbHMucGF0Y2hBbmRVcGdyYWRlVHJlZSh0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaHRtbFN0cmluZztcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBpZiAoTmF0aXZlLkVsZW1lbnRfaW5uZXJIVE1MICYmIE5hdGl2ZS5FbGVtZW50X2lubmVySFRNTC5nZXQpIHtcbiAgICBwYXRjaF9pbm5lckhUTUwoRWxlbWVudC5wcm90b3R5cGUsIE5hdGl2ZS5FbGVtZW50X2lubmVySFRNTCk7XG4gIH0gZWxzZSBpZiAoTmF0aXZlLkhUTUxFbGVtZW50X2lubmVySFRNTCAmJiBOYXRpdmUuSFRNTEVsZW1lbnRfaW5uZXJIVE1MLmdldCkge1xuICAgIHBhdGNoX2lubmVySFRNTChIVE1MRWxlbWVudC5wcm90b3R5cGUsIE5hdGl2ZS5IVE1MRWxlbWVudF9pbm5lckhUTUwpO1xuICB9IGVsc2Uge1xuXG4gICAgLyoqIEB0eXBlIHtIVE1MRGl2RWxlbWVudH0gKi9cbiAgICBjb25zdCByYXdEaXYgPSBOYXRpdmUuRG9jdW1lbnRfY3JlYXRlRWxlbWVudC5jYWxsKGRvY3VtZW50LCAnZGl2Jyk7XG5cbiAgICBpbnRlcm5hbHMuYWRkUGF0Y2goZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgcGF0Y2hfaW5uZXJIVE1MKGVsZW1lbnQsIHtcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICAvLyBJbXBsZW1lbnRzIGdldHRpbmcgYGlubmVySFRNTGAgYnkgcGVyZm9ybWluZyBhbiB1bnBhdGNoZWQgYGNsb25lTm9kZWBcbiAgICAgICAgLy8gb2YgdGhlIGVsZW1lbnQgYW5kIHJldHVybmluZyB0aGUgcmVzdWx0aW5nIGVsZW1lbnQncyBgaW5uZXJIVE1MYC5cbiAgICAgICAgLy8gVE9ETzogSXMgdGhpcyB0b28gZXhwZW5zaXZlP1xuICAgICAgICBnZXQ6IC8qKiBAdGhpcyB7RWxlbWVudH0gKi8gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIE5hdGl2ZS5Ob2RlX2Nsb25lTm9kZS5jYWxsKHRoaXMsIHRydWUpLmlubmVySFRNTDtcbiAgICAgICAgfSxcbiAgICAgICAgLy8gSW1wbGVtZW50cyBzZXR0aW5nIGBpbm5lckhUTUxgIGJ5IGNyZWF0aW5nIGFuIHVucGF0Y2hlZCBlbGVtZW50LFxuICAgICAgICAvLyBzZXR0aW5nIGBpbm5lckhUTUxgIG9mIHRoYXQgZWxlbWVudCBhbmQgcmVwbGFjaW5nIHRoZSB0YXJnZXRcbiAgICAgICAgLy8gZWxlbWVudCdzIGNoaWxkcmVuIHdpdGggdGhvc2Ugb2YgdGhlIHVucGF0Y2hlZCBlbGVtZW50LlxuICAgICAgICBzZXQ6IC8qKiBAdGhpcyB7RWxlbWVudH0gKi8gZnVuY3Rpb24oYXNzaWduZWRWYWx1ZSkge1xuICAgICAgICAgIC8vIE5PVEU6IHJlLXJvdXRlIHRvIGBjb250ZW50YCBmb3IgYHRlbXBsYXRlYCBlbGVtZW50cy5cbiAgICAgICAgICAvLyBXZSBuZWVkIHRvIGRvIHRoaXMgYmVjYXVzZSBgdGVtcGxhdGUuYXBwZW5kQ2hpbGRgIGRvZXMgbm90XG4gICAgICAgICAgLy8gcm91dGUgaW50byBgdGVtcGxhdGUuY29udGVudGAuXG4gICAgICAgICAgLyoqIEB0eXBlIHshTm9kZX0gKi9cbiAgICAgICAgICBjb25zdCBjb250ZW50ID0gdGhpcy5sb2NhbE5hbWUgPT09ICd0ZW1wbGF0ZScgPyAoLyoqIEB0eXBlIHshSFRNTFRlbXBsYXRlRWxlbWVudH0gKi8gKHRoaXMpKS5jb250ZW50IDogdGhpcztcbiAgICAgICAgICByYXdEaXYuaW5uZXJIVE1MID0gYXNzaWduZWRWYWx1ZTtcblxuICAgICAgICAgIHdoaWxlIChjb250ZW50LmNoaWxkTm9kZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgTmF0aXZlLk5vZGVfcmVtb3ZlQ2hpbGQuY2FsbChjb250ZW50LCBjb250ZW50LmNoaWxkTm9kZXNbMF0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICB3aGlsZSAocmF3RGl2LmNoaWxkTm9kZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgTmF0aXZlLk5vZGVfYXBwZW5kQ2hpbGQuY2FsbChjb250ZW50LCByYXdEaXYuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIFV0aWxpdGllcy5zZXRQcm9wZXJ0eVVuY2hlY2tlZChFbGVtZW50LnByb3RvdHlwZSwgJ3NldEF0dHJpYnV0ZScsXG4gICAgLyoqXG4gICAgICogQHRoaXMge0VsZW1lbnR9XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmV3VmFsdWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbihuYW1lLCBuZXdWYWx1ZSkge1xuICAgICAgLy8gRmFzdCBwYXRoIGZvciBub24tY3VzdG9tIGVsZW1lbnRzLlxuICAgICAgaWYgKHRoaXMuX19DRV9zdGF0ZSAhPT0gQ0VTdGF0ZS5jdXN0b20pIHtcbiAgICAgICAgcmV0dXJuIE5hdGl2ZS5FbGVtZW50X3NldEF0dHJpYnV0ZS5jYWxsKHRoaXMsIG5hbWUsIG5ld1ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb2xkVmFsdWUgPSBOYXRpdmUuRWxlbWVudF9nZXRBdHRyaWJ1dGUuY2FsbCh0aGlzLCBuYW1lKTtcbiAgICAgIE5hdGl2ZS5FbGVtZW50X3NldEF0dHJpYnV0ZS5jYWxsKHRoaXMsIG5hbWUsIG5ld1ZhbHVlKTtcbiAgICAgIG5ld1ZhbHVlID0gTmF0aXZlLkVsZW1lbnRfZ2V0QXR0cmlidXRlLmNhbGwodGhpcywgbmFtZSk7XG4gICAgICBpbnRlcm5hbHMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKHRoaXMsIG5hbWUsIG9sZFZhbHVlLCBuZXdWYWx1ZSwgbnVsbCk7XG4gICAgfSk7XG5cbiAgVXRpbGl0aWVzLnNldFByb3BlcnR5VW5jaGVja2VkKEVsZW1lbnQucHJvdG90eXBlLCAnc2V0QXR0cmlidXRlTlMnLFxuICAgIC8qKlxuICAgICAqIEB0aGlzIHtFbGVtZW50fVxuICAgICAqIEBwYXJhbSB7P3N0cmluZ30gbmFtZXNwYWNlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmV3VmFsdWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbihuYW1lc3BhY2UsIG5hbWUsIG5ld1ZhbHVlKSB7XG4gICAgICAvLyBGYXN0IHBhdGggZm9yIG5vbi1jdXN0b20gZWxlbWVudHMuXG4gICAgICBpZiAodGhpcy5fX0NFX3N0YXRlICE9PSBDRVN0YXRlLmN1c3RvbSkge1xuICAgICAgICByZXR1cm4gTmF0aXZlLkVsZW1lbnRfc2V0QXR0cmlidXRlTlMuY2FsbCh0aGlzLCBuYW1lc3BhY2UsIG5hbWUsIG5ld1ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb2xkVmFsdWUgPSBOYXRpdmUuRWxlbWVudF9nZXRBdHRyaWJ1dGVOUy5jYWxsKHRoaXMsIG5hbWVzcGFjZSwgbmFtZSk7XG4gICAgICBOYXRpdmUuRWxlbWVudF9zZXRBdHRyaWJ1dGVOUy5jYWxsKHRoaXMsIG5hbWVzcGFjZSwgbmFtZSwgbmV3VmFsdWUpO1xuICAgICAgbmV3VmFsdWUgPSBOYXRpdmUuRWxlbWVudF9nZXRBdHRyaWJ1dGVOUy5jYWxsKHRoaXMsIG5hbWVzcGFjZSwgbmFtZSk7XG4gICAgICBpbnRlcm5hbHMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKHRoaXMsIG5hbWUsIG9sZFZhbHVlLCBuZXdWYWx1ZSwgbmFtZXNwYWNlKTtcbiAgICB9KTtcblxuICBVdGlsaXRpZXMuc2V0UHJvcGVydHlVbmNoZWNrZWQoRWxlbWVudC5wcm90b3R5cGUsICdyZW1vdmVBdHRyaWJ1dGUnLFxuICAgIC8qKlxuICAgICAqIEB0aGlzIHtFbGVtZW50fVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAgICovXG4gICAgZnVuY3Rpb24obmFtZSkge1xuICAgICAgLy8gRmFzdCBwYXRoIGZvciBub24tY3VzdG9tIGVsZW1lbnRzLlxuICAgICAgaWYgKHRoaXMuX19DRV9zdGF0ZSAhPT0gQ0VTdGF0ZS5jdXN0b20pIHtcbiAgICAgICAgcmV0dXJuIE5hdGl2ZS5FbGVtZW50X3JlbW92ZUF0dHJpYnV0ZS5jYWxsKHRoaXMsIG5hbWUpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBvbGRWYWx1ZSA9IE5hdGl2ZS5FbGVtZW50X2dldEF0dHJpYnV0ZS5jYWxsKHRoaXMsIG5hbWUpO1xuICAgICAgTmF0aXZlLkVsZW1lbnRfcmVtb3ZlQXR0cmlidXRlLmNhbGwodGhpcywgbmFtZSk7XG4gICAgICBpZiAob2xkVmFsdWUgIT09IG51bGwpIHtcbiAgICAgICAgaW50ZXJuYWxzLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayh0aGlzLCBuYW1lLCBvbGRWYWx1ZSwgbnVsbCwgbnVsbCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgVXRpbGl0aWVzLnNldFByb3BlcnR5VW5jaGVja2VkKEVsZW1lbnQucHJvdG90eXBlLCAncmVtb3ZlQXR0cmlidXRlTlMnLFxuICAgIC8qKlxuICAgICAqIEB0aGlzIHtFbGVtZW50fVxuICAgICAqIEBwYXJhbSB7P3N0cmluZ30gbmFtZXNwYWNlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbihuYW1lc3BhY2UsIG5hbWUpIHtcbiAgICAgIC8vIEZhc3QgcGF0aCBmb3Igbm9uLWN1c3RvbSBlbGVtZW50cy5cbiAgICAgIGlmICh0aGlzLl9fQ0Vfc3RhdGUgIT09IENFU3RhdGUuY3VzdG9tKSB7XG4gICAgICAgIHJldHVybiBOYXRpdmUuRWxlbWVudF9yZW1vdmVBdHRyaWJ1dGVOUy5jYWxsKHRoaXMsIG5hbWVzcGFjZSwgbmFtZSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG9sZFZhbHVlID0gTmF0aXZlLkVsZW1lbnRfZ2V0QXR0cmlidXRlTlMuY2FsbCh0aGlzLCBuYW1lc3BhY2UsIG5hbWUpO1xuICAgICAgTmF0aXZlLkVsZW1lbnRfcmVtb3ZlQXR0cmlidXRlTlMuY2FsbCh0aGlzLCBuYW1lc3BhY2UsIG5hbWUpO1xuICAgICAgLy8gSW4gb2xkZXIgYnJvd3NlcnMsIGBFbGVtZW50I2dldEF0dHJpYnV0ZU5TYCBtYXkgcmV0dXJuIHRoZSBlbXB0eSBzdHJpbmdcbiAgICAgIC8vIGluc3RlYWQgb2YgbnVsbCBpZiB0aGUgYXR0cmlidXRlIGRvZXMgbm90IGV4aXN0LiBGb3IgZGV0YWlscywgc2VlO1xuICAgICAgLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0VsZW1lbnQvZ2V0QXR0cmlidXRlTlMjTm90ZXNcbiAgICAgIGNvbnN0IG5ld1ZhbHVlID0gTmF0aXZlLkVsZW1lbnRfZ2V0QXR0cmlidXRlTlMuY2FsbCh0aGlzLCBuYW1lc3BhY2UsIG5hbWUpO1xuICAgICAgaWYgKG9sZFZhbHVlICE9PSBuZXdWYWx1ZSkge1xuICAgICAgICBpbnRlcm5hbHMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKHRoaXMsIG5hbWUsIG9sZFZhbHVlLCBuZXdWYWx1ZSwgbmFtZXNwYWNlKTtcbiAgICAgIH1cbiAgICB9KTtcblxuXG4gIGZ1bmN0aW9uIHBhdGNoX2luc2VydEFkamFjZW50RWxlbWVudChkZXN0aW5hdGlvbiwgYmFzZU1ldGhvZCkge1xuICAgIFV0aWxpdGllcy5zZXRQcm9wZXJ0eVVuY2hlY2tlZChkZXN0aW5hdGlvbiwgJ2luc2VydEFkamFjZW50RWxlbWVudCcsXG4gICAgICAvKipcbiAgICAgICAqIEB0aGlzIHtFbGVtZW50fVxuICAgICAgICogQHBhcmFtIHtzdHJpbmd9IHdoZXJlXG4gICAgICAgKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gICAgICAgKiBAcmV0dXJuIHs/RWxlbWVudH1cbiAgICAgICAqL1xuICAgICAgZnVuY3Rpb24od2hlcmUsIGVsZW1lbnQpIHtcbiAgICAgICAgY29uc3Qgd2FzQ29ubmVjdGVkID0gVXRpbGl0aWVzLmlzQ29ubmVjdGVkKGVsZW1lbnQpO1xuICAgICAgICBjb25zdCBpbnNlcnRlZEVsZW1lbnQgPSAvKiogQHR5cGUgeyFFbGVtZW50fSAqL1xuICAgICAgICAgIChiYXNlTWV0aG9kLmNhbGwodGhpcywgd2hlcmUsIGVsZW1lbnQpKTtcblxuICAgICAgICBpZiAod2FzQ29ubmVjdGVkKSB7XG4gICAgICAgICAgaW50ZXJuYWxzLmRpc2Nvbm5lY3RUcmVlKGVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFV0aWxpdGllcy5pc0Nvbm5lY3RlZChpbnNlcnRlZEVsZW1lbnQpKSB7XG4gICAgICAgICAgaW50ZXJuYWxzLmNvbm5lY3RUcmVlKGVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpbnNlcnRlZEVsZW1lbnQ7XG4gICAgICB9KTtcbiAgfVxuXG4gIGlmIChOYXRpdmUuSFRNTEVsZW1lbnRfaW5zZXJ0QWRqYWNlbnRFbGVtZW50KSB7XG4gICAgcGF0Y2hfaW5zZXJ0QWRqYWNlbnRFbGVtZW50KEhUTUxFbGVtZW50LnByb3RvdHlwZSwgTmF0aXZlLkhUTUxFbGVtZW50X2luc2VydEFkamFjZW50RWxlbWVudCk7XG4gIH0gZWxzZSBpZiAoTmF0aXZlLkVsZW1lbnRfaW5zZXJ0QWRqYWNlbnRFbGVtZW50KSB7XG4gICAgcGF0Y2hfaW5zZXJ0QWRqYWNlbnRFbGVtZW50KEVsZW1lbnQucHJvdG90eXBlLCBOYXRpdmUuRWxlbWVudF9pbnNlcnRBZGphY2VudEVsZW1lbnQpO1xuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUud2FybignQ3VzdG9tIEVsZW1lbnRzOiBgRWxlbWVudCNpbnNlcnRBZGphY2VudEVsZW1lbnRgIHdhcyBub3QgcGF0Y2hlZC4nKTtcbiAgfVxuXG5cbiAgUGF0Y2hQYXJlbnROb2RlKGludGVybmFscywgRWxlbWVudC5wcm90b3R5cGUsIHtcbiAgICBwcmVwZW5kOiBOYXRpdmUuRWxlbWVudF9wcmVwZW5kLFxuICAgIGFwcGVuZDogTmF0aXZlLkVsZW1lbnRfYXBwZW5kLFxuICB9KTtcblxuICBQYXRjaENoaWxkTm9kZShpbnRlcm5hbHMsIEVsZW1lbnQucHJvdG90eXBlLCB7XG4gICAgYmVmb3JlOiBOYXRpdmUuRWxlbWVudF9iZWZvcmUsXG4gICAgYWZ0ZXI6IE5hdGl2ZS5FbGVtZW50X2FmdGVyLFxuICAgIHJlcGxhY2VXaXRoOiBOYXRpdmUuRWxlbWVudF9yZXBsYWNlV2l0aCxcbiAgICByZW1vdmU6IE5hdGl2ZS5FbGVtZW50X3JlbW92ZSxcbiAgfSk7XG59O1xuIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IChjKSAyMDE2IFRoZSBQb2x5bWVyIFByb2plY3QgQXV0aG9ycy4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqIFRoaXMgY29kZSBtYXkgb25seSBiZSB1c2VkIHVuZGVyIHRoZSBCU0Qgc3R5bGUgbGljZW5zZSBmb3VuZCBhdCBodHRwOi8vcG9seW1lci5naXRodWIuaW8vTElDRU5TRS50eHRcbiAqIFRoZSBjb21wbGV0ZSBzZXQgb2YgYXV0aG9ycyBtYXkgYmUgZm91bmQgYXQgaHR0cDovL3BvbHltZXIuZ2l0aHViLmlvL0FVVEhPUlMudHh0XG4gKiBUaGUgY29tcGxldGUgc2V0IG9mIGNvbnRyaWJ1dG9ycyBtYXkgYmUgZm91bmQgYXQgaHR0cDovL3BvbHltZXIuZ2l0aHViLmlvL0NPTlRSSUJVVE9SUy50eHRcbiAqIENvZGUgZGlzdHJpYnV0ZWQgYnkgR29vZ2xlIGFzIHBhcnQgb2YgdGhlIHBvbHltZXIgcHJvamVjdCBpcyBhbHNvXG4gKiBzdWJqZWN0IHRvIGFuIGFkZGl0aW9uYWwgSVAgcmlnaHRzIGdyYW50IGZvdW5kIGF0IGh0dHA6Ly9wb2x5bWVyLmdpdGh1Yi5pby9QQVRFTlRTLnR4dFxuICovXG5cbmltcG9ydCBDdXN0b21FbGVtZW50SW50ZXJuYWxzIGZyb20gJy4vQ3VzdG9tRWxlbWVudEludGVybmFscy5qcyc7XG5pbXBvcnQgQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5IGZyb20gJy4vQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5LmpzJztcblxuaW1wb3J0IFBhdGNoSFRNTEVsZW1lbnQgZnJvbSAnLi9QYXRjaC9IVE1MRWxlbWVudC5qcyc7XG5pbXBvcnQgUGF0Y2hEb2N1bWVudCBmcm9tICcuL1BhdGNoL0RvY3VtZW50LmpzJztcbmltcG9ydCBQYXRjaE5vZGUgZnJvbSAnLi9QYXRjaC9Ob2RlLmpzJztcbmltcG9ydCBQYXRjaEVsZW1lbnQgZnJvbSAnLi9QYXRjaC9FbGVtZW50LmpzJztcblxuY29uc3QgcHJpb3JDdXN0b21FbGVtZW50cyA9IHdpbmRvd1snY3VzdG9tRWxlbWVudHMnXTtcblxuaWYgKCFwcmlvckN1c3RvbUVsZW1lbnRzIHx8XG4gICAgIHByaW9yQ3VzdG9tRWxlbWVudHNbJ2ZvcmNlUG9seWZpbGwnXSB8fFxuICAgICAodHlwZW9mIHByaW9yQ3VzdG9tRWxlbWVudHNbJ2RlZmluZSddICE9ICdmdW5jdGlvbicpIHx8XG4gICAgICh0eXBlb2YgcHJpb3JDdXN0b21FbGVtZW50c1snZ2V0J10gIT0gJ2Z1bmN0aW9uJykpIHtcbiAgLyoqIEB0eXBlIHshQ3VzdG9tRWxlbWVudEludGVybmFsc30gKi9cbiAgY29uc3QgaW50ZXJuYWxzID0gbmV3IEN1c3RvbUVsZW1lbnRJbnRlcm5hbHMoKTtcblxuICBQYXRjaEhUTUxFbGVtZW50KGludGVybmFscyk7XG4gIFBhdGNoRG9jdW1lbnQoaW50ZXJuYWxzKTtcbiAgUGF0Y2hOb2RlKGludGVybmFscyk7XG4gIFBhdGNoRWxlbWVudChpbnRlcm5hbHMpO1xuXG4gIC8vIFRoZSBtYWluIGRvY3VtZW50IGlzIGFsd2F5cyBhc3NvY2lhdGVkIHdpdGggdGhlIHJlZ2lzdHJ5LlxuICBkb2N1bWVudC5fX0NFX2hhc1JlZ2lzdHJ5ID0gdHJ1ZTtcblxuICAvKiogQHR5cGUgeyFDdXN0b21FbGVtZW50UmVnaXN0cnl9ICovXG4gIGNvbnN0IGN1c3RvbUVsZW1lbnRzID0gbmV3IEN1c3RvbUVsZW1lbnRSZWdpc3RyeShpbnRlcm5hbHMpO1xuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3aW5kb3csICdjdXN0b21FbGVtZW50cycsIHtcbiAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICB2YWx1ZTogY3VzdG9tRWxlbWVudHMsXG4gIH0pO1xufVxuIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IChjKSAyMDE0IFRoZSBQb2x5bWVyIFByb2plY3QgQXV0aG9ycy4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqIFRoaXMgY29kZSBtYXkgb25seSBiZSB1c2VkIHVuZGVyIHRoZSBCU0Qgc3R5bGUgbGljZW5zZSBmb3VuZCBhdCBodHRwOi8vcG9seW1lci5naXRodWIuaW8vTElDRU5TRS50eHRcbiAqIFRoZSBjb21wbGV0ZSBzZXQgb2YgYXV0aG9ycyBtYXkgYmUgZm91bmQgYXQgaHR0cDovL3BvbHltZXIuZ2l0aHViLmlvL0FVVEhPUlMudHh0XG4gKiBUaGUgY29tcGxldGUgc2V0IG9mIGNvbnRyaWJ1dG9ycyBtYXkgYmUgZm91bmQgYXQgaHR0cDovL3BvbHltZXIuZ2l0aHViLmlvL0NPTlRSSUJVVE9SUy50eHRcbiAqIENvZGUgZGlzdHJpYnV0ZWQgYnkgR29vZ2xlIGFzIHBhcnQgb2YgdGhlIHBvbHltZXIgcHJvamVjdCBpcyBhbHNvXG4gKiBzdWJqZWN0IHRvIGFuIGFkZGl0aW9uYWwgSVAgcmlnaHRzIGdyYW50IGZvdW5kIGF0IGh0dHA6Ly9wb2x5bWVyLmdpdGh1Yi5pby9QQVRFTlRTLnR4dFxuICovXG4vLyBAdmVyc2lvbiAwLjcuMjJcblxuKGZ1bmN0aW9uKGdsb2JhbCkge1xuICBpZiAoZ2xvYmFsLkpzTXV0YXRpb25PYnNlcnZlcikge1xuICAgIHJldHVybjtcbiAgfVxuICB2YXIgcmVnaXN0cmF0aW9uc1RhYmxlID0gbmV3IFdlYWtNYXAoKTtcbiAgdmFyIHNldEltbWVkaWF0ZTtcbiAgaWYgKC9UcmlkZW50fEVkZ2UvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpIHtcbiAgICBzZXRJbW1lZGlhdGUgPSBzZXRUaW1lb3V0O1xuICB9IGVsc2UgaWYgKHdpbmRvdy5zZXRJbW1lZGlhdGUpIHtcbiAgICBzZXRJbW1lZGlhdGUgPSB3aW5kb3cuc2V0SW1tZWRpYXRlO1xuICB9IGVsc2Uge1xuICAgIHZhciBzZXRJbW1lZGlhdGVRdWV1ZSA9IFtdO1xuICAgIHZhciBzZW50aW5lbCA9IFN0cmluZyhNYXRoLnJhbmRvbSgpKTtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgZnVuY3Rpb24oZSkge1xuICAgICAgaWYgKGUuZGF0YSA9PT0gc2VudGluZWwpIHtcbiAgICAgICAgdmFyIHF1ZXVlID0gc2V0SW1tZWRpYXRlUXVldWU7XG4gICAgICAgIHNldEltbWVkaWF0ZVF1ZXVlID0gW107XG4gICAgICAgIHF1ZXVlLmZvckVhY2goZnVuY3Rpb24oZnVuYykge1xuICAgICAgICAgIGZ1bmMoKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgc2V0SW1tZWRpYXRlID0gZnVuY3Rpb24oZnVuYykge1xuICAgICAgc2V0SW1tZWRpYXRlUXVldWUucHVzaChmdW5jKTtcbiAgICAgIHdpbmRvdy5wb3N0TWVzc2FnZShzZW50aW5lbCwgXCIqXCIpO1xuICAgIH07XG4gIH1cbiAgdmFyIGlzU2NoZWR1bGVkID0gZmFsc2U7XG4gIHZhciBzY2hlZHVsZWRPYnNlcnZlcnMgPSBbXTtcbiAgZnVuY3Rpb24gc2NoZWR1bGVDYWxsYmFjayhvYnNlcnZlcikge1xuICAgIHNjaGVkdWxlZE9ic2VydmVycy5wdXNoKG9ic2VydmVyKTtcbiAgICBpZiAoIWlzU2NoZWR1bGVkKSB7XG4gICAgICBpc1NjaGVkdWxlZCA9IHRydWU7XG4gICAgICBzZXRJbW1lZGlhdGUoZGlzcGF0Y2hDYWxsYmFja3MpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiB3cmFwSWZOZWVkZWQobm9kZSkge1xuICAgIHJldHVybiB3aW5kb3cuU2hhZG93RE9NUG9seWZpbGwgJiYgd2luZG93LlNoYWRvd0RPTVBvbHlmaWxsLndyYXBJZk5lZWRlZChub2RlKSB8fCBub2RlO1xuICB9XG4gIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2tzKCkge1xuICAgIGlzU2NoZWR1bGVkID0gZmFsc2U7XG4gICAgdmFyIG9ic2VydmVycyA9IHNjaGVkdWxlZE9ic2VydmVycztcbiAgICBzY2hlZHVsZWRPYnNlcnZlcnMgPSBbXTtcbiAgICBvYnNlcnZlcnMuc29ydChmdW5jdGlvbihvMSwgbzIpIHtcbiAgICAgIHJldHVybiBvMS51aWRfIC0gbzIudWlkXztcbiAgICB9KTtcbiAgICB2YXIgYW55Tm9uRW1wdHkgPSBmYWxzZTtcbiAgICBvYnNlcnZlcnMuZm9yRWFjaChmdW5jdGlvbihvYnNlcnZlcikge1xuICAgICAgdmFyIHF1ZXVlID0gb2JzZXJ2ZXIudGFrZVJlY29yZHMoKTtcbiAgICAgIHJlbW92ZVRyYW5zaWVudE9ic2VydmVyc0ZvcihvYnNlcnZlcik7XG4gICAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIG9ic2VydmVyLmNhbGxiYWNrXyhxdWV1ZSwgb2JzZXJ2ZXIpO1xuICAgICAgICBhbnlOb25FbXB0eSA9IHRydWU7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKGFueU5vbkVtcHR5KSBkaXNwYXRjaENhbGxiYWNrcygpO1xuICB9XG4gIGZ1bmN0aW9uIHJlbW92ZVRyYW5zaWVudE9ic2VydmVyc0ZvcihvYnNlcnZlcikge1xuICAgIG9ic2VydmVyLm5vZGVzXy5mb3JFYWNoKGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgIHZhciByZWdpc3RyYXRpb25zID0gcmVnaXN0cmF0aW9uc1RhYmxlLmdldChub2RlKTtcbiAgICAgIGlmICghcmVnaXN0cmF0aW9ucykgcmV0dXJuO1xuICAgICAgcmVnaXN0cmF0aW9ucy5mb3JFYWNoKGZ1bmN0aW9uKHJlZ2lzdHJhdGlvbikge1xuICAgICAgICBpZiAocmVnaXN0cmF0aW9uLm9ic2VydmVyID09PSBvYnNlcnZlcikgcmVnaXN0cmF0aW9uLnJlbW92ZVRyYW5zaWVudE9ic2VydmVycygpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgZnVuY3Rpb24gZm9yRWFjaEFuY2VzdG9yQW5kT2JzZXJ2ZXJFbnF1ZXVlUmVjb3JkKHRhcmdldCwgY2FsbGJhY2spIHtcbiAgICBmb3IgKHZhciBub2RlID0gdGFyZ2V0OyBub2RlOyBub2RlID0gbm9kZS5wYXJlbnROb2RlKSB7XG4gICAgICB2YXIgcmVnaXN0cmF0aW9ucyA9IHJlZ2lzdHJhdGlvbnNUYWJsZS5nZXQobm9kZSk7XG4gICAgICBpZiAocmVnaXN0cmF0aW9ucykge1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJlZ2lzdHJhdGlvbnMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICB2YXIgcmVnaXN0cmF0aW9uID0gcmVnaXN0cmF0aW9uc1tqXTtcbiAgICAgICAgICB2YXIgb3B0aW9ucyA9IHJlZ2lzdHJhdGlvbi5vcHRpb25zO1xuICAgICAgICAgIGlmIChub2RlICE9PSB0YXJnZXQgJiYgIW9wdGlvbnMuc3VidHJlZSkgY29udGludWU7XG4gICAgICAgICAgdmFyIHJlY29yZCA9IGNhbGxiYWNrKG9wdGlvbnMpO1xuICAgICAgICAgIGlmIChyZWNvcmQpIHJlZ2lzdHJhdGlvbi5lbnF1ZXVlKHJlY29yZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgdmFyIHVpZENvdW50ZXIgPSAwO1xuICBmdW5jdGlvbiBKc011dGF0aW9uT2JzZXJ2ZXIoY2FsbGJhY2spIHtcbiAgICB0aGlzLmNhbGxiYWNrXyA9IGNhbGxiYWNrO1xuICAgIHRoaXMubm9kZXNfID0gW107XG4gICAgdGhpcy5yZWNvcmRzXyA9IFtdO1xuICAgIHRoaXMudWlkXyA9ICsrdWlkQ291bnRlcjtcbiAgfVxuICBKc011dGF0aW9uT2JzZXJ2ZXIucHJvdG90eXBlID0ge1xuICAgIG9ic2VydmU6IGZ1bmN0aW9uKHRhcmdldCwgb3B0aW9ucykge1xuICAgICAgdGFyZ2V0ID0gd3JhcElmTmVlZGVkKHRhcmdldCk7XG4gICAgICBpZiAoIW9wdGlvbnMuY2hpbGRMaXN0ICYmICFvcHRpb25zLmF0dHJpYnV0ZXMgJiYgIW9wdGlvbnMuY2hhcmFjdGVyRGF0YSB8fCBvcHRpb25zLmF0dHJpYnV0ZU9sZFZhbHVlICYmICFvcHRpb25zLmF0dHJpYnV0ZXMgfHwgb3B0aW9ucy5hdHRyaWJ1dGVGaWx0ZXIgJiYgb3B0aW9ucy5hdHRyaWJ1dGVGaWx0ZXIubGVuZ3RoICYmICFvcHRpb25zLmF0dHJpYnV0ZXMgfHwgb3B0aW9ucy5jaGFyYWN0ZXJEYXRhT2xkVmFsdWUgJiYgIW9wdGlvbnMuY2hhcmFjdGVyRGF0YSkge1xuICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoKTtcbiAgICAgIH1cbiAgICAgIHZhciByZWdpc3RyYXRpb25zID0gcmVnaXN0cmF0aW9uc1RhYmxlLmdldCh0YXJnZXQpO1xuICAgICAgaWYgKCFyZWdpc3RyYXRpb25zKSByZWdpc3RyYXRpb25zVGFibGUuc2V0KHRhcmdldCwgcmVnaXN0cmF0aW9ucyA9IFtdKTtcbiAgICAgIHZhciByZWdpc3RyYXRpb247XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlZ2lzdHJhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKHJlZ2lzdHJhdGlvbnNbaV0ub2JzZXJ2ZXIgPT09IHRoaXMpIHtcbiAgICAgICAgICByZWdpc3RyYXRpb24gPSByZWdpc3RyYXRpb25zW2ldO1xuICAgICAgICAgIHJlZ2lzdHJhdGlvbi5yZW1vdmVMaXN0ZW5lcnMoKTtcbiAgICAgICAgICByZWdpc3RyYXRpb24ub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICghcmVnaXN0cmF0aW9uKSB7XG4gICAgICAgIHJlZ2lzdHJhdGlvbiA9IG5ldyBSZWdpc3RyYXRpb24odGhpcywgdGFyZ2V0LCBvcHRpb25zKTtcbiAgICAgICAgcmVnaXN0cmF0aW9ucy5wdXNoKHJlZ2lzdHJhdGlvbik7XG4gICAgICAgIHRoaXMubm9kZXNfLnB1c2godGFyZ2V0KTtcbiAgICAgIH1cbiAgICAgIHJlZ2lzdHJhdGlvbi5hZGRMaXN0ZW5lcnMoKTtcbiAgICB9LFxuICAgIGRpc2Nvbm5lY3Q6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5ub2Rlc18uZm9yRWFjaChmdW5jdGlvbihub2RlKSB7XG4gICAgICAgIHZhciByZWdpc3RyYXRpb25zID0gcmVnaXN0cmF0aW9uc1RhYmxlLmdldChub2RlKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZWdpc3RyYXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIHJlZ2lzdHJhdGlvbiA9IHJlZ2lzdHJhdGlvbnNbaV07XG4gICAgICAgICAgaWYgKHJlZ2lzdHJhdGlvbi5vYnNlcnZlciA9PT0gdGhpcykge1xuICAgICAgICAgICAgcmVnaXN0cmF0aW9uLnJlbW92ZUxpc3RlbmVycygpO1xuICAgICAgICAgICAgcmVnaXN0cmF0aW9ucy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sIHRoaXMpO1xuICAgICAgdGhpcy5yZWNvcmRzXyA9IFtdO1xuICAgIH0sXG4gICAgdGFrZVJlY29yZHM6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGNvcHlPZlJlY29yZHMgPSB0aGlzLnJlY29yZHNfO1xuICAgICAgdGhpcy5yZWNvcmRzXyA9IFtdO1xuICAgICAgcmV0dXJuIGNvcHlPZlJlY29yZHM7XG4gICAgfVxuICB9O1xuICBmdW5jdGlvbiBNdXRhdGlvblJlY29yZCh0eXBlLCB0YXJnZXQpIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMudGFyZ2V0ID0gdGFyZ2V0O1xuICAgIHRoaXMuYWRkZWROb2RlcyA9IFtdO1xuICAgIHRoaXMucmVtb3ZlZE5vZGVzID0gW107XG4gICAgdGhpcy5wcmV2aW91c1NpYmxpbmcgPSBudWxsO1xuICAgIHRoaXMubmV4dFNpYmxpbmcgPSBudWxsO1xuICAgIHRoaXMuYXR0cmlidXRlTmFtZSA9IG51bGw7XG4gICAgdGhpcy5hdHRyaWJ1dGVOYW1lc3BhY2UgPSBudWxsO1xuICAgIHRoaXMub2xkVmFsdWUgPSBudWxsO1xuICB9XG4gIGZ1bmN0aW9uIGNvcHlNdXRhdGlvblJlY29yZChvcmlnaW5hbCkge1xuICAgIHZhciByZWNvcmQgPSBuZXcgTXV0YXRpb25SZWNvcmQob3JpZ2luYWwudHlwZSwgb3JpZ2luYWwudGFyZ2V0KTtcbiAgICByZWNvcmQuYWRkZWROb2RlcyA9IG9yaWdpbmFsLmFkZGVkTm9kZXMuc2xpY2UoKTtcbiAgICByZWNvcmQucmVtb3ZlZE5vZGVzID0gb3JpZ2luYWwucmVtb3ZlZE5vZGVzLnNsaWNlKCk7XG4gICAgcmVjb3JkLnByZXZpb3VzU2libGluZyA9IG9yaWdpbmFsLnByZXZpb3VzU2libGluZztcbiAgICByZWNvcmQubmV4dFNpYmxpbmcgPSBvcmlnaW5hbC5uZXh0U2libGluZztcbiAgICByZWNvcmQuYXR0cmlidXRlTmFtZSA9IG9yaWdpbmFsLmF0dHJpYnV0ZU5hbWU7XG4gICAgcmVjb3JkLmF0dHJpYnV0ZU5hbWVzcGFjZSA9IG9yaWdpbmFsLmF0dHJpYnV0ZU5hbWVzcGFjZTtcbiAgICByZWNvcmQub2xkVmFsdWUgPSBvcmlnaW5hbC5vbGRWYWx1ZTtcbiAgICByZXR1cm4gcmVjb3JkO1xuICB9XG4gIHZhciBjdXJyZW50UmVjb3JkLCByZWNvcmRXaXRoT2xkVmFsdWU7XG4gIGZ1bmN0aW9uIGdldFJlY29yZCh0eXBlLCB0YXJnZXQpIHtcbiAgICByZXR1cm4gY3VycmVudFJlY29yZCA9IG5ldyBNdXRhdGlvblJlY29yZCh0eXBlLCB0YXJnZXQpO1xuICB9XG4gIGZ1bmN0aW9uIGdldFJlY29yZFdpdGhPbGRWYWx1ZShvbGRWYWx1ZSkge1xuICAgIGlmIChyZWNvcmRXaXRoT2xkVmFsdWUpIHJldHVybiByZWNvcmRXaXRoT2xkVmFsdWU7XG4gICAgcmVjb3JkV2l0aE9sZFZhbHVlID0gY29weU11dGF0aW9uUmVjb3JkKGN1cnJlbnRSZWNvcmQpO1xuICAgIHJlY29yZFdpdGhPbGRWYWx1ZS5vbGRWYWx1ZSA9IG9sZFZhbHVlO1xuICAgIHJldHVybiByZWNvcmRXaXRoT2xkVmFsdWU7XG4gIH1cbiAgZnVuY3Rpb24gY2xlYXJSZWNvcmRzKCkge1xuICAgIGN1cnJlbnRSZWNvcmQgPSByZWNvcmRXaXRoT2xkVmFsdWUgPSB1bmRlZmluZWQ7XG4gIH1cbiAgZnVuY3Rpb24gcmVjb3JkUmVwcmVzZW50c0N1cnJlbnRNdXRhdGlvbihyZWNvcmQpIHtcbiAgICByZXR1cm4gcmVjb3JkID09PSByZWNvcmRXaXRoT2xkVmFsdWUgfHwgcmVjb3JkID09PSBjdXJyZW50UmVjb3JkO1xuICB9XG4gIGZ1bmN0aW9uIHNlbGVjdFJlY29yZChsYXN0UmVjb3JkLCBuZXdSZWNvcmQpIHtcbiAgICBpZiAobGFzdFJlY29yZCA9PT0gbmV3UmVjb3JkKSByZXR1cm4gbGFzdFJlY29yZDtcbiAgICBpZiAocmVjb3JkV2l0aE9sZFZhbHVlICYmIHJlY29yZFJlcHJlc2VudHNDdXJyZW50TXV0YXRpb24obGFzdFJlY29yZCkpIHJldHVybiByZWNvcmRXaXRoT2xkVmFsdWU7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgZnVuY3Rpb24gUmVnaXN0cmF0aW9uKG9ic2VydmVyLCB0YXJnZXQsIG9wdGlvbnMpIHtcbiAgICB0aGlzLm9ic2VydmVyID0gb2JzZXJ2ZXI7XG4gICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB0aGlzLnRyYW5zaWVudE9ic2VydmVkTm9kZXMgPSBbXTtcbiAgfVxuICBSZWdpc3RyYXRpb24ucHJvdG90eXBlID0ge1xuICAgIGVucXVldWU6IGZ1bmN0aW9uKHJlY29yZCkge1xuICAgICAgdmFyIHJlY29yZHMgPSB0aGlzLm9ic2VydmVyLnJlY29yZHNfO1xuICAgICAgdmFyIGxlbmd0aCA9IHJlY29yZHMubGVuZ3RoO1xuICAgICAgaWYgKHJlY29yZHMubGVuZ3RoID4gMCkge1xuICAgICAgICB2YXIgbGFzdFJlY29yZCA9IHJlY29yZHNbbGVuZ3RoIC0gMV07XG4gICAgICAgIHZhciByZWNvcmRUb1JlcGxhY2VMYXN0ID0gc2VsZWN0UmVjb3JkKGxhc3RSZWNvcmQsIHJlY29yZCk7XG4gICAgICAgIGlmIChyZWNvcmRUb1JlcGxhY2VMYXN0KSB7XG4gICAgICAgICAgcmVjb3Jkc1tsZW5ndGggLSAxXSA9IHJlY29yZFRvUmVwbGFjZUxhc3Q7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzY2hlZHVsZUNhbGxiYWNrKHRoaXMub2JzZXJ2ZXIpO1xuICAgICAgfVxuICAgICAgcmVjb3Jkc1tsZW5ndGhdID0gcmVjb3JkO1xuICAgIH0sXG4gICAgYWRkTGlzdGVuZXJzOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuYWRkTGlzdGVuZXJzXyh0aGlzLnRhcmdldCk7XG4gICAgfSxcbiAgICBhZGRMaXN0ZW5lcnNfOiBmdW5jdGlvbihub2RlKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgIGlmIChvcHRpb25zLmF0dHJpYnV0ZXMpIG5vZGUuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUF0dHJNb2RpZmllZFwiLCB0aGlzLCB0cnVlKTtcbiAgICAgIGlmIChvcHRpb25zLmNoYXJhY3RlckRhdGEpIG5vZGUuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNoYXJhY3RlckRhdGFNb2RpZmllZFwiLCB0aGlzLCB0cnVlKTtcbiAgICAgIGlmIChvcHRpb25zLmNoaWxkTGlzdCkgbm9kZS5hZGRFdmVudExpc3RlbmVyKFwiRE9NTm9kZUluc2VydGVkXCIsIHRoaXMsIHRydWUpO1xuICAgICAgaWYgKG9wdGlvbnMuY2hpbGRMaXN0IHx8IG9wdGlvbnMuc3VidHJlZSkgbm9kZS5hZGRFdmVudExpc3RlbmVyKFwiRE9NTm9kZVJlbW92ZWRcIiwgdGhpcywgdHJ1ZSk7XG4gICAgfSxcbiAgICByZW1vdmVMaXN0ZW5lcnM6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcnNfKHRoaXMudGFyZ2V0KTtcbiAgICB9LFxuICAgIHJlbW92ZUxpc3RlbmVyc186IGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgIHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgaWYgKG9wdGlvbnMuYXR0cmlidXRlcykgbm9kZS5yZW1vdmVFdmVudExpc3RlbmVyKFwiRE9NQXR0ck1vZGlmaWVkXCIsIHRoaXMsIHRydWUpO1xuICAgICAgaWYgKG9wdGlvbnMuY2hhcmFjdGVyRGF0YSkgbm9kZS5yZW1vdmVFdmVudExpc3RlbmVyKFwiRE9NQ2hhcmFjdGVyRGF0YU1vZGlmaWVkXCIsIHRoaXMsIHRydWUpO1xuICAgICAgaWYgKG9wdGlvbnMuY2hpbGRMaXN0KSBub2RlLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJET01Ob2RlSW5zZXJ0ZWRcIiwgdGhpcywgdHJ1ZSk7XG4gICAgICBpZiAob3B0aW9ucy5jaGlsZExpc3QgfHwgb3B0aW9ucy5zdWJ0cmVlKSBub2RlLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJET01Ob2RlUmVtb3ZlZFwiLCB0aGlzLCB0cnVlKTtcbiAgICB9LFxuICAgIGFkZFRyYW5zaWVudE9ic2VydmVyOiBmdW5jdGlvbihub2RlKSB7XG4gICAgICBpZiAobm9kZSA9PT0gdGhpcy50YXJnZXQpIHJldHVybjtcbiAgICAgIHRoaXMuYWRkTGlzdGVuZXJzXyhub2RlKTtcbiAgICAgIHRoaXMudHJhbnNpZW50T2JzZXJ2ZWROb2Rlcy5wdXNoKG5vZGUpO1xuICAgICAgdmFyIHJlZ2lzdHJhdGlvbnMgPSByZWdpc3RyYXRpb25zVGFibGUuZ2V0KG5vZGUpO1xuICAgICAgaWYgKCFyZWdpc3RyYXRpb25zKSByZWdpc3RyYXRpb25zVGFibGUuc2V0KG5vZGUsIHJlZ2lzdHJhdGlvbnMgPSBbXSk7XG4gICAgICByZWdpc3RyYXRpb25zLnB1c2godGhpcyk7XG4gICAgfSxcbiAgICByZW1vdmVUcmFuc2llbnRPYnNlcnZlcnM6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHRyYW5zaWVudE9ic2VydmVkTm9kZXMgPSB0aGlzLnRyYW5zaWVudE9ic2VydmVkTm9kZXM7XG4gICAgICB0aGlzLnRyYW5zaWVudE9ic2VydmVkTm9kZXMgPSBbXTtcbiAgICAgIHRyYW5zaWVudE9ic2VydmVkTm9kZXMuZm9yRWFjaChmdW5jdGlvbihub2RlKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXJzXyhub2RlKTtcbiAgICAgICAgdmFyIHJlZ2lzdHJhdGlvbnMgPSByZWdpc3RyYXRpb25zVGFibGUuZ2V0KG5vZGUpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlZ2lzdHJhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpZiAocmVnaXN0cmF0aW9uc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgcmVnaXN0cmF0aW9ucy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sIHRoaXMpO1xuICAgIH0sXG4gICAgaGFuZGxlRXZlbnQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICBzd2l0Y2ggKGUudHlwZSkge1xuICAgICAgIGNhc2UgXCJET01BdHRyTW9kaWZpZWRcIjpcbiAgICAgICAgdmFyIG5hbWUgPSBlLmF0dHJOYW1lO1xuICAgICAgICB2YXIgbmFtZXNwYWNlID0gZS5yZWxhdGVkTm9kZS5uYW1lc3BhY2VVUkk7XG4gICAgICAgIHZhciB0YXJnZXQgPSBlLnRhcmdldDtcbiAgICAgICAgdmFyIHJlY29yZCA9IG5ldyBnZXRSZWNvcmQoXCJhdHRyaWJ1dGVzXCIsIHRhcmdldCk7XG4gICAgICAgIHJlY29yZC5hdHRyaWJ1dGVOYW1lID0gbmFtZTtcbiAgICAgICAgcmVjb3JkLmF0dHJpYnV0ZU5hbWVzcGFjZSA9IG5hbWVzcGFjZTtcbiAgICAgICAgdmFyIG9sZFZhbHVlID0gZS5hdHRyQ2hhbmdlID09PSBNdXRhdGlvbkV2ZW50LkFERElUSU9OID8gbnVsbCA6IGUucHJldlZhbHVlO1xuICAgICAgICBmb3JFYWNoQW5jZXN0b3JBbmRPYnNlcnZlckVucXVldWVSZWNvcmQodGFyZ2V0LCBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICAgICAgaWYgKCFvcHRpb25zLmF0dHJpYnV0ZXMpIHJldHVybjtcbiAgICAgICAgICBpZiAob3B0aW9ucy5hdHRyaWJ1dGVGaWx0ZXIgJiYgb3B0aW9ucy5hdHRyaWJ1dGVGaWx0ZXIubGVuZ3RoICYmIG9wdGlvbnMuYXR0cmlidXRlRmlsdGVyLmluZGV4T2YobmFtZSkgPT09IC0xICYmIG9wdGlvbnMuYXR0cmlidXRlRmlsdGVyLmluZGV4T2YobmFtZXNwYWNlKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKG9wdGlvbnMuYXR0cmlidXRlT2xkVmFsdWUpIHJldHVybiBnZXRSZWNvcmRXaXRoT2xkVmFsdWUob2xkVmFsdWUpO1xuICAgICAgICAgIHJldHVybiByZWNvcmQ7XG4gICAgICAgIH0pO1xuICAgICAgICBicmVhaztcblxuICAgICAgIGNhc2UgXCJET01DaGFyYWN0ZXJEYXRhTW9kaWZpZWRcIjpcbiAgICAgICAgdmFyIHRhcmdldCA9IGUudGFyZ2V0O1xuICAgICAgICB2YXIgcmVjb3JkID0gZ2V0UmVjb3JkKFwiY2hhcmFjdGVyRGF0YVwiLCB0YXJnZXQpO1xuICAgICAgICB2YXIgb2xkVmFsdWUgPSBlLnByZXZWYWx1ZTtcbiAgICAgICAgZm9yRWFjaEFuY2VzdG9yQW5kT2JzZXJ2ZXJFbnF1ZXVlUmVjb3JkKHRhcmdldCwgZnVuY3Rpb24ob3B0aW9ucykge1xuICAgICAgICAgIGlmICghb3B0aW9ucy5jaGFyYWN0ZXJEYXRhKSByZXR1cm47XG4gICAgICAgICAgaWYgKG9wdGlvbnMuY2hhcmFjdGVyRGF0YU9sZFZhbHVlKSByZXR1cm4gZ2V0UmVjb3JkV2l0aE9sZFZhbHVlKG9sZFZhbHVlKTtcbiAgICAgICAgICByZXR1cm4gcmVjb3JkO1xuICAgICAgICB9KTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgICBjYXNlIFwiRE9NTm9kZVJlbW92ZWRcIjpcbiAgICAgICAgdGhpcy5hZGRUcmFuc2llbnRPYnNlcnZlcihlLnRhcmdldCk7XG5cbiAgICAgICBjYXNlIFwiRE9NTm9kZUluc2VydGVkXCI6XG4gICAgICAgIHZhciBjaGFuZ2VkTm9kZSA9IGUudGFyZ2V0O1xuICAgICAgICB2YXIgYWRkZWROb2RlcywgcmVtb3ZlZE5vZGVzO1xuICAgICAgICBpZiAoZS50eXBlID09PSBcIkRPTU5vZGVJbnNlcnRlZFwiKSB7XG4gICAgICAgICAgYWRkZWROb2RlcyA9IFsgY2hhbmdlZE5vZGUgXTtcbiAgICAgICAgICByZW1vdmVkTm9kZXMgPSBbXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhZGRlZE5vZGVzID0gW107XG4gICAgICAgICAgcmVtb3ZlZE5vZGVzID0gWyBjaGFuZ2VkTm9kZSBdO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwcmV2aW91c1NpYmxpbmcgPSBjaGFuZ2VkTm9kZS5wcmV2aW91c1NpYmxpbmc7XG4gICAgICAgIHZhciBuZXh0U2libGluZyA9IGNoYW5nZWROb2RlLm5leHRTaWJsaW5nO1xuICAgICAgICB2YXIgcmVjb3JkID0gZ2V0UmVjb3JkKFwiY2hpbGRMaXN0XCIsIGUudGFyZ2V0LnBhcmVudE5vZGUpO1xuICAgICAgICByZWNvcmQuYWRkZWROb2RlcyA9IGFkZGVkTm9kZXM7XG4gICAgICAgIHJlY29yZC5yZW1vdmVkTm9kZXMgPSByZW1vdmVkTm9kZXM7XG4gICAgICAgIHJlY29yZC5wcmV2aW91c1NpYmxpbmcgPSBwcmV2aW91c1NpYmxpbmc7XG4gICAgICAgIHJlY29yZC5uZXh0U2libGluZyA9IG5leHRTaWJsaW5nO1xuICAgICAgICBmb3JFYWNoQW5jZXN0b3JBbmRPYnNlcnZlckVucXVldWVSZWNvcmQoZS5yZWxhdGVkTm9kZSwgZnVuY3Rpb24ob3B0aW9ucykge1xuICAgICAgICAgIGlmICghb3B0aW9ucy5jaGlsZExpc3QpIHJldHVybjtcbiAgICAgICAgICByZXR1cm4gcmVjb3JkO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGNsZWFyUmVjb3JkcygpO1xuICAgIH1cbiAgfTtcbiAgZ2xvYmFsLkpzTXV0YXRpb25PYnNlcnZlciA9IEpzTXV0YXRpb25PYnNlcnZlcjtcbiAgaWYgKCFnbG9iYWwuTXV0YXRpb25PYnNlcnZlcikge1xuICAgIGdsb2JhbC5NdXRhdGlvbk9ic2VydmVyID0gSnNNdXRhdGlvbk9ic2VydmVyO1xuICAgIEpzTXV0YXRpb25PYnNlcnZlci5faXNQb2x5ZmlsbGVkID0gdHJ1ZTtcbiAgfVxufSkoc2VsZik7XG4iLCIvKlxuQ29weXJpZ2h0IChjKSAyMDEyIEJhcm5lc2FuZG5vYmxlLmNvbSwgbGxjLCBEb25hdm9uIFdlc3QsIGFuZCBEb21lbmljIERlbmljb2xhXG5cblBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZ1xuYSBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG5cIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbndpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbmRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0b1xucGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvXG50aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG5cblRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlXG5pbmNsdWRlZCBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cblxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCxcbkVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkRcbk5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkVcbkxJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT05cbk9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTlxuV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbiovXG4oZnVuY3Rpb24gKGdsb2JhbCwgdW5kZWZpbmVkKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICBpZiAoZ2xvYmFsLnNldEltbWVkaWF0ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIG5leHRIYW5kbGUgPSAxOyAvLyBTcGVjIHNheXMgZ3JlYXRlciB0aGFuIHplcm9cbiAgICB2YXIgdGFza3NCeUhhbmRsZSA9IHt9O1xuICAgIHZhciBjdXJyZW50bHlSdW5uaW5nQVRhc2sgPSBmYWxzZTtcbiAgICB2YXIgZG9jID0gZ2xvYmFsLmRvY3VtZW50O1xuICAgIHZhciBzZXRJbW1lZGlhdGU7XG5cbiAgICBmdW5jdGlvbiBhZGRGcm9tU2V0SW1tZWRpYXRlQXJndW1lbnRzKGFyZ3MpIHtcbiAgICAgICAgdGFza3NCeUhhbmRsZVtuZXh0SGFuZGxlXSA9IHBhcnRpYWxseUFwcGxpZWQuYXBwbHkodW5kZWZpbmVkLCBhcmdzKTtcbiAgICAgICAgcmV0dXJuIG5leHRIYW5kbGUrKztcbiAgICB9XG5cbiAgICAvLyBUaGlzIGZ1bmN0aW9uIGFjY2VwdHMgdGhlIHNhbWUgYXJndW1lbnRzIGFzIHNldEltbWVkaWF0ZSwgYnV0XG4gICAgLy8gcmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgcmVxdWlyZXMgbm8gYXJndW1lbnRzLlxuICAgIGZ1bmN0aW9uIHBhcnRpYWxseUFwcGxpZWQoaGFuZGxlcikge1xuICAgICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBoYW5kbGVyID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICBoYW5kbGVyLmFwcGx5KHVuZGVmaW5lZCwgYXJncyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIChuZXcgRnVuY3Rpb24oXCJcIiArIGhhbmRsZXIpKSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJ1bklmUHJlc2VudChoYW5kbGUpIHtcbiAgICAgICAgLy8gRnJvbSB0aGUgc3BlYzogXCJXYWl0IHVudGlsIGFueSBpbnZvY2F0aW9ucyBvZiB0aGlzIGFsZ29yaXRobSBzdGFydGVkIGJlZm9yZSB0aGlzIG9uZSBoYXZlIGNvbXBsZXRlZC5cIlxuICAgICAgICAvLyBTbyBpZiB3ZSdyZSBjdXJyZW50bHkgcnVubmluZyBhIHRhc2ssIHdlJ2xsIG5lZWQgdG8gZGVsYXkgdGhpcyBpbnZvY2F0aW9uLlxuICAgICAgICBpZiAoY3VycmVudGx5UnVubmluZ0FUYXNrKSB7XG4gICAgICAgICAgICAvLyBEZWxheSBieSBkb2luZyBhIHNldFRpbWVvdXQuIHNldEltbWVkaWF0ZSB3YXMgdHJpZWQgaW5zdGVhZCwgYnV0IGluIEZpcmVmb3ggNyBpdCBnZW5lcmF0ZWQgYVxuICAgICAgICAgICAgLy8gXCJ0b28gbXVjaCByZWN1cnNpb25cIiBlcnJvci5cbiAgICAgICAgICAgIHNldFRpbWVvdXQocGFydGlhbGx5QXBwbGllZChydW5JZlByZXNlbnQsIGhhbmRsZSksIDApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHRhc2sgPSB0YXNrc0J5SGFuZGxlW2hhbmRsZV07XG4gICAgICAgICAgICBpZiAodGFzaykge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRseVJ1bm5pbmdBVGFzayA9IHRydWU7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgdGFzaygpO1xuICAgICAgICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFySW1tZWRpYXRlKGhhbmRsZSk7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRseVJ1bm5pbmdBVGFzayA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNsZWFySW1tZWRpYXRlKGhhbmRsZSkge1xuICAgICAgICBkZWxldGUgdGFza3NCeUhhbmRsZVtoYW5kbGVdO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGluc3RhbGxOZXh0VGlja0ltcGxlbWVudGF0aW9uKCkge1xuICAgICAgICBzZXRJbW1lZGlhdGUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBoYW5kbGUgPSBhZGRGcm9tU2V0SW1tZWRpYXRlQXJndW1lbnRzKGFyZ3VtZW50cyk7XG4gICAgICAgICAgICBwcm9jZXNzLm5leHRUaWNrKHBhcnRpYWxseUFwcGxpZWQocnVuSWZQcmVzZW50LCBoYW5kbGUpKTtcbiAgICAgICAgICAgIHJldHVybiBoYW5kbGU7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2FuVXNlUG9zdE1lc3NhZ2UoKSB7XG4gICAgICAgIC8vIFRoZSB0ZXN0IGFnYWluc3QgYGltcG9ydFNjcmlwdHNgIHByZXZlbnRzIHRoaXMgaW1wbGVtZW50YXRpb24gZnJvbSBiZWluZyBpbnN0YWxsZWQgaW5zaWRlIGEgd2ViIHdvcmtlcixcbiAgICAgICAgLy8gd2hlcmUgYGdsb2JhbC5wb3N0TWVzc2FnZWAgbWVhbnMgc29tZXRoaW5nIGNvbXBsZXRlbHkgZGlmZmVyZW50IGFuZCBjYW4ndCBiZSB1c2VkIGZvciB0aGlzIHB1cnBvc2UuXG4gICAgICAgIGlmIChnbG9iYWwucG9zdE1lc3NhZ2UgJiYgIWdsb2JhbC5pbXBvcnRTY3JpcHRzKSB7XG4gICAgICAgICAgICB2YXIgcG9zdE1lc3NhZ2VJc0FzeW5jaHJvbm91cyA9IHRydWU7XG4gICAgICAgICAgICB2YXIgb2xkT25NZXNzYWdlID0gZ2xvYmFsLm9ubWVzc2FnZTtcbiAgICAgICAgICAgIGdsb2JhbC5vbm1lc3NhZ2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZUlzQXN5bmNocm9ub3VzID0gZmFsc2U7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZ2xvYmFsLnBvc3RNZXNzYWdlKFwiXCIsIFwiKlwiKTtcbiAgICAgICAgICAgIGdsb2JhbC5vbm1lc3NhZ2UgPSBvbGRPbk1lc3NhZ2U7XG4gICAgICAgICAgICByZXR1cm4gcG9zdE1lc3NhZ2VJc0FzeW5jaHJvbm91cztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGluc3RhbGxQb3N0TWVzc2FnZUltcGxlbWVudGF0aW9uKCkge1xuICAgICAgICAvLyBJbnN0YWxscyBhbiBldmVudCBoYW5kbGVyIG9uIGBnbG9iYWxgIGZvciB0aGUgYG1lc3NhZ2VgIGV2ZW50OiBzZWVcbiAgICAgICAgLy8gKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi9ET00vd2luZG93LnBvc3RNZXNzYWdlXG4gICAgICAgIC8vICogaHR0cDovL3d3dy53aGF0d2cub3JnL3NwZWNzL3dlYi1hcHBzL2N1cnJlbnQtd29yay9tdWx0aXBhZ2UvY29tbXMuaHRtbCNjcm9zc0RvY3VtZW50TWVzc2FnZXNcblxuICAgICAgICB2YXIgbWVzc2FnZVByZWZpeCA9IFwic2V0SW1tZWRpYXRlJFwiICsgTWF0aC5yYW5kb20oKSArIFwiJFwiO1xuICAgICAgICB2YXIgb25HbG9iYWxNZXNzYWdlID0gZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgICAgIGlmIChldmVudC5zb3VyY2UgPT09IGdsb2JhbCAmJlxuICAgICAgICAgICAgICAgIHR5cGVvZiBldmVudC5kYXRhID09PSBcInN0cmluZ1wiICYmXG4gICAgICAgICAgICAgICAgZXZlbnQuZGF0YS5pbmRleE9mKG1lc3NhZ2VQcmVmaXgpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcnVuSWZQcmVzZW50KCtldmVudC5kYXRhLnNsaWNlKG1lc3NhZ2VQcmVmaXgubGVuZ3RoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKGdsb2JhbC5hZGRFdmVudExpc3RlbmVyKSB7XG4gICAgICAgICAgICBnbG9iYWwuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgb25HbG9iYWxNZXNzYWdlLCBmYWxzZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnbG9iYWwuYXR0YWNoRXZlbnQoXCJvbm1lc3NhZ2VcIiwgb25HbG9iYWxNZXNzYWdlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNldEltbWVkaWF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGhhbmRsZSA9IGFkZEZyb21TZXRJbW1lZGlhdGVBcmd1bWVudHMoYXJndW1lbnRzKTtcbiAgICAgICAgICAgIGdsb2JhbC5wb3N0TWVzc2FnZShtZXNzYWdlUHJlZml4ICsgaGFuZGxlLCBcIipcIik7XG4gICAgICAgICAgICByZXR1cm4gaGFuZGxlO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGluc3RhbGxNZXNzYWdlQ2hhbm5lbEltcGxlbWVudGF0aW9uKCkge1xuICAgICAgICB2YXIgY2hhbm5lbCA9IG5ldyBNZXNzYWdlQ2hhbm5lbCgpO1xuICAgICAgICBjaGFubmVsLnBvcnQxLm9ubWVzc2FnZSA9IGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgICAgICB2YXIgaGFuZGxlID0gZXZlbnQuZGF0YTtcbiAgICAgICAgICAgIHJ1bklmUHJlc2VudChoYW5kbGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNldEltbWVkaWF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGhhbmRsZSA9IGFkZEZyb21TZXRJbW1lZGlhdGVBcmd1bWVudHMoYXJndW1lbnRzKTtcbiAgICAgICAgICAgIGNoYW5uZWwucG9ydDIucG9zdE1lc3NhZ2UoaGFuZGxlKTtcbiAgICAgICAgICAgIHJldHVybiBoYW5kbGU7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5zdGFsbFJlYWR5U3RhdGVDaGFuZ2VJbXBsZW1lbnRhdGlvbigpIHtcbiAgICAgICAgdmFyIGh0bWwgPSBkb2MuZG9jdW1lbnRFbGVtZW50O1xuICAgICAgICBzZXRJbW1lZGlhdGUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBoYW5kbGUgPSBhZGRGcm9tU2V0SW1tZWRpYXRlQXJndW1lbnRzKGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAvLyBDcmVhdGUgYSA8c2NyaXB0PiBlbGVtZW50OyBpdHMgcmVhZHlzdGF0ZWNoYW5nZSBldmVudCB3aWxsIGJlIGZpcmVkIGFzeW5jaHJvbm91c2x5IG9uY2UgaXQgaXMgaW5zZXJ0ZWRcbiAgICAgICAgICAgIC8vIGludG8gdGhlIGRvY3VtZW50LiBEbyBzbywgdGh1cyBxdWV1aW5nIHVwIHRoZSB0YXNrLiBSZW1lbWJlciB0byBjbGVhbiB1cCBvbmNlIGl0J3MgYmVlbiBjYWxsZWQuXG4gICAgICAgICAgICB2YXIgc2NyaXB0ID0gZG9jLmNyZWF0ZUVsZW1lbnQoXCJzY3JpcHRcIik7XG4gICAgICAgICAgICBzY3JpcHQub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJ1bklmUHJlc2VudChoYW5kbGUpO1xuICAgICAgICAgICAgICAgIHNjcmlwdC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBudWxsO1xuICAgICAgICAgICAgICAgIGh0bWwucmVtb3ZlQ2hpbGQoc2NyaXB0KTtcbiAgICAgICAgICAgICAgICBzY3JpcHQgPSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGh0bWwuYXBwZW5kQ2hpbGQoc2NyaXB0KTtcbiAgICAgICAgICAgIHJldHVybiBoYW5kbGU7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5zdGFsbFNldFRpbWVvdXRJbXBsZW1lbnRhdGlvbigpIHtcbiAgICAgICAgc2V0SW1tZWRpYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgaGFuZGxlID0gYWRkRnJvbVNldEltbWVkaWF0ZUFyZ3VtZW50cyhhcmd1bWVudHMpO1xuICAgICAgICAgICAgc2V0VGltZW91dChwYXJ0aWFsbHlBcHBsaWVkKHJ1bklmUHJlc2VudCwgaGFuZGxlKSwgMCk7XG4gICAgICAgICAgICByZXR1cm4gaGFuZGxlO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIElmIHN1cHBvcnRlZCwgd2Ugc2hvdWxkIGF0dGFjaCB0byB0aGUgcHJvdG90eXBlIG9mIGdsb2JhbCwgc2luY2UgdGhhdCBpcyB3aGVyZSBzZXRUaW1lb3V0IGV0IGFsLiBsaXZlLlxuICAgIHZhciBhdHRhY2hUbyA9IE9iamVjdC5nZXRQcm90b3R5cGVPZiAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YoZ2xvYmFsKTtcbiAgICBhdHRhY2hUbyA9IGF0dGFjaFRvICYmIGF0dGFjaFRvLnNldFRpbWVvdXQgPyBhdHRhY2hUbyA6IGdsb2JhbDtcblxuICAgIC8vIERvbid0IGdldCBmb29sZWQgYnkgZS5nLiBicm93c2VyaWZ5IGVudmlyb25tZW50cy5cbiAgICBpZiAoe30udG9TdHJpbmcuY2FsbChnbG9iYWwucHJvY2VzcykgPT09IFwiW29iamVjdCBwcm9jZXNzXVwiKSB7XG4gICAgICAgIC8vIEZvciBOb2RlLmpzIGJlZm9yZSAwLjlcbiAgICAgICAgaW5zdGFsbE5leHRUaWNrSW1wbGVtZW50YXRpb24oKTtcblxuICAgIH0gZWxzZSBpZiAoY2FuVXNlUG9zdE1lc3NhZ2UoKSkge1xuICAgICAgICAvLyBGb3Igbm9uLUlFMTAgbW9kZXJuIGJyb3dzZXJzXG4gICAgICAgIGluc3RhbGxQb3N0TWVzc2FnZUltcGxlbWVudGF0aW9uKCk7XG5cbiAgICB9IGVsc2UgaWYgKGdsb2JhbC5NZXNzYWdlQ2hhbm5lbCkge1xuICAgICAgICAvLyBGb3Igd2ViIHdvcmtlcnMsIHdoZXJlIHN1cHBvcnRlZFxuICAgICAgICBpbnN0YWxsTWVzc2FnZUNoYW5uZWxJbXBsZW1lbnRhdGlvbigpO1xuXG4gICAgfSBlbHNlIGlmIChkb2MgJiYgXCJvbnJlYWR5c3RhdGVjaGFuZ2VcIiBpbiBkb2MuY3JlYXRlRWxlbWVudChcInNjcmlwdFwiKSkge1xuICAgICAgICAvLyBGb3IgSUUgNuKAkzhcbiAgICAgICAgaW5zdGFsbFJlYWR5U3RhdGVDaGFuZ2VJbXBsZW1lbnRhdGlvbigpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gRm9yIG9sZGVyIGJyb3dzZXJzXG4gICAgICAgIGluc3RhbGxTZXRUaW1lb3V0SW1wbGVtZW50YXRpb24oKTtcbiAgICB9XG5cbiAgICBhdHRhY2hUby5zZXRJbW1lZGlhdGUgPSBzZXRJbW1lZGlhdGU7XG4gICAgYXR0YWNoVG8uY2xlYXJJbW1lZGlhdGUgPSBjbGVhckltbWVkaWF0ZTtcbn0oc2VsZikpO1xuIiwiLy8gQ2F1dGlvbjpcbi8vIERvIG5vdCByZXBsYWNlIHRoaXMgaW1wb3J0IHN0YXRlbWVudCB3aXRoIGNvZGVzLlxuLy9cbi8vIElmIHlvdSByZXBsYWNlIHRoaXMgaW1wb3J0IHN0YXRlbWVudCB3aXRoIGNvZGVzLFxuLy8gdGhlIGNvZGVzIHdpbGwgYmUgZXhlY3V0ZWQgYWZ0ZXIgdGhlIGZvbGxvd2luZyBwb2x5ZmlsbHMgYXJlIGltcG9ydGVkXG4vLyBiZWNhdXNlIGltcG9ydCBzdGF0ZW1lbnRzIGFyZSBob2lzdGVkIGR1cmluZyBjb21waWxhdGlvbi5cbmltcG9ydCAnLi9wb2x5ZmlsbC1zd2l0Y2hlcyc7XG5cbi8vIFBvbHlmaWxsIEVDTUFTY3JpcHQgc3RhbmRhcmQgZmVhdHVyZXMgd2l0aCBnbG9iYWwgbmFtZXNwYWNlIHBvbGx1dGlvblxuaW1wb3J0ICdjb3JlLWpzL2ZuL29iamVjdC9zZXQtcHJvdG90eXBlLW9mJztcbmltcG9ydCAnY29yZS1qcy9mbi9zZXQnO1xuaW1wb3J0ICdjb3JlLWpzL2ZuL21hcCc7XG5pbXBvcnQgJ2NvcmUtanMvZm4vd2Vhay1tYXAnO1xuaW1wb3J0ICdjb3JlLWpzL2ZuL2FycmF5L2Zyb20nO1xuXG4vLyBQb2x5ZmlsbCBDdXN0b20gRWxlbWVudHMgdjEgd2l0aCBnbG9iYWwgbmFtZXNwYWNlIHBvbGx1dGlvblxuaW1wb3J0ICdAb25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL2N1c3RvbS1lbGVtZW50cyc7XG5cbi8vIFBvbHlmaWxsIE11dGF0aW9uT2JzZXJ2ZXIgd2l0aCBnbG9iYWwgbmFtZXNwYWNlIHBvbGx1dGlvblxuaW1wb3J0ICcuL011dGF0aW9uT2JzZXJ2ZXJAMC43LjIyL011dGF0aW9uT2JzZXJ2ZXIuanMnO1xuXG4vLyBQb2x5ZmlsbCBzZXRJbW1lZGlhdGUgd2l0aCBnbG9iYWwgbmFtZXNwYWNlIHBvbGx1dGlvblxuaW1wb3J0ICcuL3NldEltbWVkaWF0ZUAxLjAuMittb2Qvc2V0SW1tZWRpYXRlLmpzJztcbiIsIihmdW5jdGlvbigpIHtcbiAgdmFyIERFRkFVTFRfVklFV1BPUlQgPSAnd2lkdGg9ZGV2aWNlLXdpZHRoLGluaXRpYWwtc2NhbGU9MSxtYXhpbXVtLXNjYWxlPTEsbWluaW11bS1zY2FsZT0xLHVzZXItc2NhbGFibGU9bm8nO1xuXG4gIHZhciBWaWV3cG9ydCA9IHsgXG4gICAgZW5zdXJlVmlld3BvcnRFbGVtZW50OiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciB2aWV3cG9ydEVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdtZXRhW25hbWU9dmlld3BvcnRdJyk7XG5cbiAgICAgIGlmICghdmlld3BvcnRFbGVtZW50KSB7XG4gICAgICAgIHZpZXdwb3J0RWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ21ldGEnKTtcbiAgICAgICAgdmlld3BvcnRFbGVtZW50Lm5hbWUgPSAndmlld3BvcnQnO1xuICAgICAgICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHZpZXdwb3J0RWxlbWVudCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB2aWV3cG9ydEVsZW1lbnQ7XG4gICAgfSxcblxuICAgIHNldHVwOiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciB2aWV3cG9ydEVsZW1lbnQgPSBWaWV3cG9ydC5lbnN1cmVWaWV3cG9ydEVsZW1lbnQoKTtcblxuICAgICAgaWYgKCF2aWV3cG9ydEVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXZpZXdwb3J0RWxlbWVudC5oYXNBdHRyaWJ1dGUoJ2NvbnRlbnQnKSkge1xuICAgICAgICB2aWV3cG9ydEVsZW1lbnQuc2V0QXR0cmlidXRlKCdjb250ZW50JywgREVGQVVMVF9WSUVXUE9SVCk7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIHdpbmRvdy5WaWV3cG9ydCA9IFZpZXdwb3J0O1xufSkoKTtcbiIsImltcG9ydCB7IEZhc3RDbGljayB9IGZyb20gJ0BvbnNlbnVpL2Zhc3RjbGljayc7XG5pbXBvcnQgJy4vb25zL3BsYXRmb3JtJzsgLy8gVGhpcyBmaWxlIG11c3QgYmUgbG9hZGVkIGJlZm9yZSBDdXN0b20gRWxlbWVudHMgcG9seWZpbGxzLlxuaW1wb3J0ICcuL3BvbHlmaWxscy9pbmRleC5qcyc7XG5pbXBvcnQgJy4vdmVuZG9yL2luZGV4LmpzJztcbmltcG9ydCAnLi9vbnMvbWljcm9ldmVudC5qcyc7XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIHNldHVwKG9ucykge1xuICBpZiAod2luZG93Ll9vbnNMb2FkZWQpIHtcbiAgICBvbnMuX3V0aWwud2FybignT25zZW4gVUkgaXMgbG9hZGVkIG1vcmUgdGhhbiBvbmNlLicpO1xuICB9XG4gIHdpbmRvdy5fb25zTG9hZGVkID0gdHJ1ZTtcblxuICAvLyBmYXN0Y2xpY2tcbiAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCAoKSA9PiB7XG4gICAgb25zLmZhc3RDbGljayA9IEZhc3RDbGljay5hdHRhY2goZG9jdW1lbnQuYm9keSk7XG5cbiAgICBjb25zdCBzdXBwb3J0VG91Y2hBY3Rpb24gPSAndG91Y2gtYWN0aW9uJyBpbiBkb2N1bWVudC5ib2R5LnN0eWxlO1xuXG4gICAgb25zLnBsYXRmb3JtLl9ydW5PbkFjdHVhbFBsYXRmb3JtKCgpID0+IHtcbiAgICAgIGlmIChvbnMucGxhdGZvcm0uaXNBbmRyb2lkKCkpIHtcbiAgICAgICAgLy8gSW4gQW5kcm9pZDQuNCssIGNvcnJlY3Qgdmlld3BvcnQgc2V0dGluZ3MgY2FuIHJlbW92ZSBjbGljayBkZWxheS5cbiAgICAgICAgLy8gU28gZGlzYWJsZSBGYXN0Q2xpY2sgb24gQW5kcm9pZC5cbiAgICAgICAgb25zLmZhc3RDbGljay5kZXN0cm95KCk7XG4gICAgICB9IGVsc2UgaWYgKG9ucy5wbGF0Zm9ybS5pc0lPUygpKSB7XG4gICAgICAgIGlmIChzdXBwb3J0VG91Y2hBY3Rpb24gJiYgKG9ucy5wbGF0Zm9ybS5pc0lPU1NhZmFyaSgpIHx8IG9ucy5wbGF0Zm9ybS5pc1dLV2ViVmlldygpKSkge1xuICAgICAgICAgIC8vIElmICd0b3VjaC1hY3Rpb24nIHN1cHBvcnRlZCBpbiBpT1MgU2FmYXJpIG9yIFdLV2ViVmlldywgZGlzYWJsZSBGYXN0Q2xpY2suXG4gICAgICAgICAgb25zLmZhc3RDbGljay5kZXN0cm95KCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gRG8gbm90aGluZy4gJ3RvdWNoLWFjdGlvbjogbWFuaXB1bGF0aW9uJyBoYXMgbm8gZWZmZWN0IG9uIFVJV2ViVmlldy5cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9LCBmYWxzZSk7XG5cbiAgb25zLnJlYWR5KGZ1bmN0aW9uKCkge1xuICAgIG9ucy5lbmFibGVEZXZpY2VCYWNrQnV0dG9uSGFuZGxlcigpO1xuICAgIG9ucy5fZGVmYXVsdERldmljZUJhY2tCdXR0b25IYW5kbGVyID0gb25zLl9pbnRlcm5hbC5kYmJEaXNwYXRjaGVyLmNyZWF0ZUhhbmRsZXIod2luZG93LmRvY3VtZW50LmJvZHksICgpID0+IHtcbiAgICAgIGlmIChPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChuYXZpZ2F0b3IsICdhcHAnKSkge1xuICAgICAgICBuYXZpZ2F0b3IuYXBwLmV4aXRBcHAoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQ291bGQgbm90IGNsb3NlIHRoZSBhcHAuIElzIFxcJ2NvcmRvdmEuanNcXCcgaW5jbHVkZWQ/XFxuRXJyb3I6IFxcJ3dpbmRvdy5uYXZpZ2F0b3IuYXBwXFwnIGlzIHVuZGVmaW5lZC4nKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBkb2N1bWVudC5ib2R5Ll9nZXN0dXJlRGV0ZWN0b3IgPSBuZXcgb25zLkdlc3R1cmVEZXRlY3Rvcihkb2N1bWVudC5ib2R5LCB7IHBhc3NpdmU6IHRydWUgfSk7XG5cbiAgICAvLyBTaW11bGF0ZSBEZXZpY2UgQmFjayBCdXR0b24gb24gRVNDIHByZXNzXG4gICAgaWYgKCFvbnMucGxhdGZvcm0uaXNXZWJWaWV3KCkpIHtcbiAgICAgIGRvY3VtZW50LmJvZHkuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgIGlmIChldmVudC5rZXlDb2RlID09PSAyNykge1xuICAgICAgICAgIG9ucy5maXJlRGV2aWNlQmFja0J1dHRvbkV2ZW50KCk7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgfVxuXG4gICAgLy8gc2V0dXAgbG9hZGluZyBwbGFjZWhvbGRlclxuICAgIG9ucy5fc2V0dXBMb2FkaW5nUGxhY2VIb2xkZXJzKCk7XG4gIH0pO1xuXG4gIC8vIHZpZXdwb3J0LmpzXG4gIFZpZXdwb3J0LnNldHVwKCk7XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5mdW5jdGlvbiBnZXRFbGVtZW50Q2xhc3MoKSB7XG4gIGlmICh0eXBlb2YgSFRNTEVsZW1lbnQgIT09ICdmdW5jdGlvbicpIHsgLy8gY2FzZSBvZiBTYWZhcmlcbiAgICBjb25zdCBCYXNlRWxlbWVudCA9ICgpID0+IHt9O1xuICAgIEJhc2VFbGVtZW50LnByb3RvdHlwZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIHJldHVybiBCYXNlRWxlbWVudDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gSFRNTEVsZW1lbnQ7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQmFzZUVsZW1lbnQgZXh0ZW5kcyBnZXRFbGVtZW50Q2xhc3MoKSB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy10ZW1wbGF0ZVxuICogQGNhdGVnb3J5IHV0aWxcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgRGVmaW5lIGEgc2VwYXJhdGUgSFRNTCBmcmFnbWVudCBhbmQgdXNlIGFzIGEgdGVtcGxhdGUuIFRoZXNlIHRlbXBsYXRlcyBjYW4gYmUgbG9hZGVkIGFzIHBhZ2VzIGluIGA8b25zLW5hdmlnYXRvcj5gLCBgPG9ucy10YWJiYXI+YCBhbmQgYDxvbnMtc3BsaXR0ZXI+YC4gVGhleSBjYW4gYWxzbyBiZSB1c2VkIHRvIGdlbmVyYXRlIGRpYWxvZ3MuIFNpbmNlIE9uc2VuIFVJIDIuNC4wLCB0aGUgbmF0aXZlIGA8dGVtcGxhdGU+YCBlbGVtZW50IGNhbiBiZSB1c2VkIGluc3RlYWQgb2YgYDxvbnMtdGVtcGxhdGU+YCBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlIGFuZCBmZWF0dXJlcy4gYDxvbnMtdGVtcGxhdGU+YCBpcyBzdGlsbCBzdXBwb3J0ZWQgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV3jg4bjg7Pjg5fjg6zjg7zjg4jjgajjgZfjgabkvb/nlKjjgZnjgovjgZ/jgoHjga5IVE1M44OV44Op44Kw44Oh44Oz44OI44KS5a6a576p44GX44G+44GZ44CC44GT44Gu6KaB57Sg44GnSFRNTOOCkuWuo+iogOOBmeOCi+OBqOOAgWlk5bGe5oCn44Gr5oyH5a6a44GX44Gf5ZCN5YmN44KScGFnZeOBrlVSTOOBqOOBl+OBpm9ucy1uYXZpZ2F0b3Ljgarjganjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjgYvjgonlj4LnhafjgafjgY3jgb7jgZnjgIJbL2phXVxuICogQHNlZWFsc28gb25zLW5hdmlnYXRvclxuICogICBbZW5dVGhlIGA8b25zLW5hdmlnYXRvcj5gIGNvbXBvbmVudCBlbmFibGVzIHN0YWNrIGJhc2VkIG5hdmlnYXRpb24uWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtdGFiYmFyXG4gKiAgIFtlbl1UaGUgYDxvbnMtdGFiYmFyPmAgY29tcG9uZW50IGlzIHVzZWQgdG8gYWRkIHRhYiBuYXZpZ2F0aW9uLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLXNwbGl0dGVyXG4gKiAgIFtlbl1UaGUgYDxvbnMtc3BsaXR0ZXI+YCBjb21wb25lbnQgY2FuIGJlIHVzZWQgdG8gY3JlYXRlIGEgZHJhZ2dhYmxlIG1lbnUgb3IgY29sdW1uIGJhc2VkIGxheW91dC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXRlbXBsYXRlIGlkPVwiZm9vYmFyLmh0bWxcIj5cbiAqICAgPG9ucy1wYWdlPlxuICogICAgIFBhZ2UgY29udGVudFxuICogICA8L29ucy1wYWdlPlxuICogPC9vbnMtdGVtcGxhdGU+XG4gKlxuICogPG9ucy1uYXZpZ2F0b3IgcGFnZT1cImZvb2Jhci5odG1sXCI+PC9vbnMtbmF2aWdhdG9yPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUZW1wbGF0ZUVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB0ZW1wbGF0ZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UZW1wbGF0ZSBjb250ZW50LiBUaGlzIHByb3BlcnR5IGNhbiBub3QgYmUgdXNlZCB3aXRoIEFuZ3VsYXJKUyBiaW5kaW5ncy5bL2VuXVxuICAgKiAgW2phXVsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLnRlbXBsYXRlID0gdGhpcy5pbm5lckhUTUw7XG5cbiAgICB3aGlsZSAodGhpcy5maXJzdENoaWxkKSB7XG4gICAgICB0aGlzLnJlbW92ZUNoaWxkKHRoaXMuZmlyc3RDaGlsZCk7XG4gICAgfVxuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgaWYgKHRoaXMucGFyZW50Tm9kZSkgeyAvLyBOb3RlOiB0aGlzLnBhcmVudE5vZGUgaXMgbm90IHNldCBpbiBzb21lIENFMC9DRTEgcG9seWZpbGxzLlxuICAgICAgLy8gU2hvdyB3YXJuaW5nIHdoZW4gdGhlIG9ucy10ZW1wbGF0ZSBpcyBub3QgbG9jYXRlZCBqdXN0IHVuZGVyIGRvY3VtZW50LmJvZHlcbiAgICAgIGlmICh0aGlzLnBhcmVudE5vZGUgIT09IGRvY3VtZW50LmJvZHkpIHsgLy8gaWYgdGhlIHBhcmVudCBpcyBub3QgZG9jdW1lbnQuYm9keVxuICAgICAgICB1dGlsLndhcm4oYG9ucy10ZW1wbGF0ZSAoaWQgPSAke3RoaXMuZ2V0QXR0cmlidXRlKCdpZCcpfSkgbXVzdCBiZSBsb2NhdGVkIGp1c3QgdW5kZXIgZG9jdW1lbnQuYm9keSR7IHRoaXMucGFyZW50Tm9kZS5vdXRlckhUTUwgPyBgOlxcblxcbiR7dGhpcy5wYXJlbnROb2RlLm91dGVySFRNTH1gIDogJy4nIH1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgZXZlbnQgPSBuZXcgQ3VzdG9tRXZlbnQoJ190ZW1wbGF0ZWxvYWRlZCcsIHtidWJibGVzOiB0cnVlLCBjYW5jZWxhYmxlOiB0cnVlfSk7XG4gICAgZXZlbnQudGVtcGxhdGUgPSB0aGlzLnRlbXBsYXRlO1xuICAgIGV2ZW50LnRlbXBsYXRlSWQgPSB0aGlzLmdldEF0dHJpYnV0ZSgnaWQnKTtcblxuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gIH1cbn1cblxub25zRWxlbWVudHMuVGVtcGxhdGUgPSBUZW1wbGF0ZUVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy10ZW1wbGF0ZScsIFRlbXBsYXRlRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCBvcmllbnRhdGlvbiBmcm9tICcuLi9vbnMvb3JpZW50YXRpb24nO1xuaW1wb3J0IHBsYXRmb3JtIGZyb20gJy4uL29ucy9wbGF0Zm9ybSc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtaWZcbiAqIEBjYXRlZ29yeSBjb25kaXRpb25hbFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2lmXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIENvbmRpdGlvbmFsbHkgZGlzcGxheSBjb250ZW50IGRlcGVuZGluZyBvbiB0aGUgcGxhdGZvcm0sIGRldmljZSBvcmllbnRhdGlvbiBvciBib3RoLlxuICpcbiAqICAgICBTb21ldGltZXMgaXQgaXMgdXNlZnVsIHRvIGNvbmRpdGlvbmFsbHkgaGlkZSBvciBzaG93IGNlcnRhaW4gY29tcG9uZW50cyBiYXNlZCBvbiBwbGF0Zm9ybS4gV2hlbiBydW5uaW5nIG9uIGlPUyB0aGUgYDxvbnMtaWY+YCBlbGVtZW50IGNhbiBiZSB1c2VkIHRvIGhpZGUgdGhlIGA8b25zLWZhYj5gIGVsZW1lbnQuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNjcm9zcy1wbGF0Zm9ybS1zdHlsaW5nLWF1dG9zdHlsaW5nIFtlbl1JbmZvcm1hdGlvbiBhYm91dCBjcm9zcyBwbGF0Zm9ybSBzdHlsaW5nWy9lbl1bamFdSW5mb3JtYXRpb24gYWJvdXQgY3Jvc3MgcGxhdGZvcm0gc3R5bGluZ1svamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1wYWdlPlxuICogICA8b25zLWlmIG9yaWVudGF0aW9uPVwibGFuZHNjYXBlXCI+XG4gKiAgICAgTGFuZHNjYXBlIHZpZXchXG4gKiAgIDwvb25zLWlmPlxuICogICA8b25zLWlmIHBsYXRmb3JtPVwiYW5kcm9pZFwiPlxuICogICAgIFRoaXMgaXMgQW5kcm9pZC5cbiAqICAgPC9vbnMtaWY+XG4gKiAgIDxvbnMtaWYgcGxhdGZvcm09XCJpb3Mgb3RoZXJcIj5cbiAqICAgICBUaGlzIGlzIG5vdCBBbmRyb2lkLlxuICogICA8L29ucy1pZj5cbiAqIDwvb25zLXBhZ2U+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIElmRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBwbGF0Zm9ybVxuICAgKiBAaW5pdG9ubHlcbiAgICogQHR5cGUge3N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU3BhY2Utc2VwYXJhdGVkIHBsYXRmb3JtIG5hbWVzLiBQb3NzaWJsZSB2YWx1ZXMgYXJlIGBcImlvc1wiYCwgYFwiYW5kcm9pZFwiYCwgYFwid2luZG93c1wiYCBhbmQgYFwib3RoZXJcImAuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBvcmllbnRhdGlvblxuICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1FaXRoZXIgYFwicG9ydHJhaXRcImAgb3IgYFwibGFuZHNjYXBlXCJgLlsvZW5dXG4gICAqICBbamFdcG9ydHJhaXTjgoLjgZfjgY/jga9sYW5kc2NhcGXjgpLmjIflrprjgZfjgb7jgZlbL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIGlmIChwbGF0Zm9ybS5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpICE9PSBudWxsKSB7XG4gICAgICAgIHRoaXMuX3BsYXRmb3JtVXBkYXRlKCk7XG4gICAgICB9IGVsc2UgaWYgKCF0aGlzLl9pc0FsbG93ZWRQbGF0Zm9ybSgpKSB7XG4gICAgICAgIHdoaWxlICh0aGlzLmNoaWxkTm9kZXNbMF0pIHtcbiAgICAgICAgICB0aGlzLmNoaWxkTm9kZXNbMF0ucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcGxhdGZvcm1VcGRhdGUoKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRoaXMuX29uT3JpZW50YXRpb25DaGFuZ2UoKTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIG9yaWVudGF0aW9uLm9uKCdjaGFuZ2UnLCB0aGlzLl9vbk9yaWVudGF0aW9uQ2hhbmdlLmJpbmQodGhpcykpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnb3JpZW50YXRpb24nXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lKSB7XG4gICAgaWYgKG5hbWUgPT09ICdvcmllbnRhdGlvbicpIHtcbiAgICAgIHRoaXMuX29uT3JpZW50YXRpb25DaGFuZ2UoKTtcbiAgICB9XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBvcmllbnRhdGlvbi5vZmYoJ2NoYW5nZScsIHRoaXMuX29uT3JpZW50YXRpb25DaGFuZ2UpO1xuICB9XG5cbiAgX3BsYXRmb3JtVXBkYXRlKCkge1xuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9IHRoaXMuX2lzQWxsb3dlZFBsYXRmb3JtKCkgPyAnJyA6ICdub25lJztcbiAgfVxuXG4gIF9pc0FsbG93ZWRQbGF0Zm9ybSgpIHtcbiAgICByZXR1cm4gIXRoaXMuZ2V0QXR0cmlidXRlKCdwbGF0Zm9ybScpIHx8IHRoaXMuZ2V0QXR0cmlidXRlKCdwbGF0Zm9ybScpLnNwbGl0KC9cXHMrLykuaW5kZXhPZihwbGF0Zm9ybS5nZXRNb2JpbGVPUygpKSA+PSAwO1xuICB9XG5cbiAgX29uT3JpZW50YXRpb25DaGFuZ2UoKSB7XG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdvcmllbnRhdGlvbicpICYmIHRoaXMuX2lzQWxsb3dlZFBsYXRmb3JtKCkpIHtcbiAgICAgIGNvbnN0IGNvbmRpdGlvbmFsT3JpZW50YXRpb24gPSB0aGlzLmdldEF0dHJpYnV0ZSgnb3JpZW50YXRpb24nKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgY29uc3QgY3VycmVudE9yaWVudGF0aW9uID0gb3JpZW50YXRpb24uaXNQb3J0cmFpdCgpID8gJ3BvcnRyYWl0JyA6ICdsYW5kc2NhcGUnO1xuXG4gICAgICB0aGlzLnN0eWxlLmRpc3BsYXkgPSAoY29uZGl0aW9uYWxPcmllbnRhdGlvbiA9PT0gY3VycmVudE9yaWVudGF0aW9uKSA/ICcnIDogJ25vbmUnO1xuICAgIH1cbiAgfVxufVxuXG5vbnNFbGVtZW50cy5JZiA9IElmRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWlmJywgSWZFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4vdXRpbCc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJhc2VBbmltYXRvciB7XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnRpbWluZ1xuICAgKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5kdXJhdGlvblxuICAgKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5kZWxheVxuICAgKi9cbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy50aW1pbmcgPSBvcHRpb25zLnRpbWluZyB8fCAnbGluZWFyJztcbiAgICB0aGlzLmR1cmF0aW9uID0gb3B0aW9ucy5kdXJhdGlvbiB8fCAwO1xuICAgIHRoaXMuZGVsYXkgPSBvcHRpb25zLmRlbGF5IHx8IDA7XG5cbiAgICB0aGlzLmRlZiA9IHtcbiAgICAgIHRpbWluZzogdGhpcy50aW1pbmcsXG4gICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgIGRlbGF5OiB0aGlzLmRlbGF5XG4gICAgfTtcbiAgfVxuXG4gIHN0YXRpYyBleHRlbmQocHJvcGVydGllcyA9IHt9KSB7XG4gICAgY29uc3QgZXh0ZW5kZWRBbmltYXRvciA9IHRoaXM7XG4gICAgY29uc3QgbmV3QW5pbWF0b3IgPSBmdW5jdGlvbigpIHtcbiAgICAgIGV4dGVuZGVkQW5pbWF0b3IuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIHV0aWwuZXh0ZW5kKHRoaXMsIHByb3BlcnRpZXMpO1xuICAgIH07XG5cbiAgICBuZXdBbmltYXRvci5wcm90b3R5cGUgPSB0aGlzLnByb3RvdHlwZTtcbiAgICByZXR1cm4gbmV3QW5pbWF0b3I7XG4gIH1cbn1cblxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuLy8gVGhpcyBvYmplY3Qgc2hvdWxkIG5vdCBiZSBleHBvc2VkIHRvIHVzZXJzLiBQbGVhc2Uga2VlcCB0aGlzIHByaXZhdGUuXG5jb25zdCBpUGhvbmVYUGF0Y2ggPSB7fTtcblxuaVBob25lWFBhdGNoLmlzSVBob25lWFBvcnRyYWl0UGF0Y2hBY3RpdmUgPSAoKSA9PiB7XG4gIHJldHVybiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuZ2V0QXR0cmlidXRlKCdvbnNmbGFnLWlwaG9uZXgtcG9ydHJhaXQnKSAhPSBudWxsICYmIHdpbmRvdy5pbm5lcldpZHRoIDwgd2luZG93LmlubmVySGVpZ2h0O1xufVxuXG5pUGhvbmVYUGF0Y2guaXNJUGhvbmVYTGFuZHNjYXBlUGF0Y2hBY3RpdmUgPSAoKSA9PiB7XG4gIC8vIElmIHdpZHRoID09PSBoZWlnaHQsIHRyZWF0IGl0IGFzIGxhbmRzY2FwZVxuICByZXR1cm4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmdldEF0dHJpYnV0ZSgnb25zZmxhZy1pcGhvbmV4LWxhbmRzY2FwZScpICE9IG51bGwgJiYgd2luZG93LmlubmVyV2lkdGggPj0gd2luZG93LmlubmVySGVpZ2h0O1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHNhZmUgYXJlYSBsZW5ndGhzIGJhc2VkIG9uIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBzYWZlIGFyZWFzLlxuICovXG5pUGhvbmVYUGF0Y2guZ2V0U2FmZUFyZWFMZW5ndGhzID0gKCkgPT4ge1xuICBsZXQgc2FmZUFyZWFMZW5ndGhzO1xuICBpZiAoaVBob25lWFBhdGNoLmlzSVBob25lWFBvcnRyYWl0UGF0Y2hBY3RpdmUoKSkge1xuICAgIHNhZmVBcmVhTGVuZ3RocyA9IHtcbiAgICAgIHRvcDogNDQsXG4gICAgICByaWdodDogMCxcbiAgICAgIGJvdHRvbTogMzQsXG4gICAgICBsZWZ0OiAwXG4gICAgfTtcbiAgfSBlbHNlIGlmIChpUGhvbmVYUGF0Y2guaXNJUGhvbmVYTGFuZHNjYXBlUGF0Y2hBY3RpdmUoKSkge1xuICAgIHNhZmVBcmVhTGVuZ3RocyA9IHtcbiAgICAgIHRvcDogMCxcbiAgICAgIHJpZ2h0OiA0NCxcbiAgICAgIGJvdHRvbTogMjEsXG4gICAgICBsZWZ0OiA0NFxuICAgIH07XG4gIH0gZWxzZSB7XG4gICAgc2FmZUFyZWFMZW5ndGhzID0ge1xuICAgICAgdG9wOiAwLFxuICAgICAgcmlnaHQ6IDAsXG4gICAgICBib3R0b206IDAsXG4gICAgICBsZWZ0OiAwXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBzYWZlQXJlYUxlbmd0aHM7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc2FmZSBhcmVhIHJlY3QgYmFzZWQgb24gdGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIHNhZmUgYXJlYXMuXG4gKi9cbmlQaG9uZVhQYXRjaC5nZXRTYWZlQXJlYURPTVJlY3QgPSAoKSA9PiB7XG4gIGxldCBzYWZlQXJlYVJlY3Q7XG4gIGlmIChpUGhvbmVYUGF0Y2guaXNJUGhvbmVYUG9ydHJhaXRQYXRjaEFjdGl2ZSgpKSB7XG4gICAgc2FmZUFyZWFSZWN0ID0ge1xuICAgICAgeDogMCxcbiAgICAgIHk6IDQ0LCAvKiAwICsgNDQgKHRvcCBzYWZlIGFyZWEpICovXG4gICAgICB3aWR0aDogd2luZG93LmlubmVyV2lkdGgsXG4gICAgICBoZWlnaHQ6IHdpbmRvdy5pbm5lckhlaWdodCAtIDc4IC8qIGhlaWdodCAtIDQ0ICh0b3Agc2FmZSBhcmVhKSAtIDM0IChib3R0b20gc2FmZSBhcmVhKSAqL1xuICAgIH07XG4gIH0gZWxzZSBpZiAoaVBob25lWFBhdGNoLmlzSVBob25lWExhbmRzY2FwZVBhdGNoQWN0aXZlKCkpIHtcbiAgICBzYWZlQXJlYVJlY3QgPSB7XG4gICAgICB4OiA0NCwgLyogMCArIDQ0IChsZWZ0IHNhZmUgYXJlYSkgKi9cbiAgICAgIHk6IDAsXG4gICAgICB3aWR0aDogd2luZG93LmlubmVyV2lkdGggLSA4OCwgLyogd2lkdGggLSA0NCAobGVmdCBzYWZlIGFyZWEpIC0gMzQgKHJpZ2h0IHNhZmUgYXJlYSkgKi9cbiAgICAgIGhlaWdodDogd2luZG93LmlubmVySGVpZ2h0IC0gMjEgLyogaGVpZ2h0IC0gMjEgKGJvdHRvbSBzYWZlIGFyZWEpICovXG4gICAgfTtcbiAgfSBlbHNlIHtcbiAgICBzYWZlQXJlYVJlY3QgPSB7XG4gICAgICB4OiAwLFxuICAgICAgeTogMCxcbiAgICAgIHdpZHRoOiB3aW5kb3cuaW5uZXJXaWR0aCxcbiAgICAgIGhlaWdodDogd2luZG93LmlubmVySGVpZ2h0XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgLi4uc2FmZUFyZWFSZWN0LFxuICAgIGxlZnQ6IHNhZmVBcmVhUmVjdC54LFxuICAgIHRvcDogc2FmZUFyZWFSZWN0LnksXG4gICAgcmlnaHQ6IHNhZmVBcmVhUmVjdC54ICsgc2FmZUFyZWFSZWN0LndpZHRoLFxuICAgIGJvdHRvbTogc2FmZUFyZWFSZWN0LnkgKyBzYWZlQXJlYVJlY3QuaGVpZ2h0XG4gIH07XG59XG5cbmV4cG9ydCBkZWZhdWx0IGlQaG9uZVhQYXRjaDtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBhbmltaXQgZnJvbSAnLi4vLi4vb25zL2FuaW1pdCc7XG5pbXBvcnQgQmFzZUFuaW1hdG9yIGZyb20gJy4uLy4uL29ucy9iYXNlLWFuaW1hdG9yJ1xuaW1wb3J0IGlQaG9uZVhQYXRjaCBmcm9tICcuLi8uLi9vbnMvaXBob25leC1wYXRjaCc7XG5cbmV4cG9ydCBjbGFzcyBBY3Rpb25TaGVldEFuaW1hdG9yIGV4dGVuZHMgQmFzZUFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7dGltaW5nID0gJ2xpbmVhcicsIGRlbGF5ID0gMCwgZHVyYXRpb24gPSAwLjJ9ID0ge30pIHtcbiAgICBzdXBlcih7IHRpbWluZywgZGVsYXksIGR1cmF0aW9uIH0pXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZGlhbG9nXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGRvbmVcbiAgICovXG4gIHNob3coZGlhbG9nLCBkb25lKSB7XG4gICAgZG9uZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBoaWRlKGRpYWxvZywgZG9uZSkge1xuICAgIGRvbmUoKTtcbiAgfVxufVxuXG4vKipcbiAqIEFuZHJvaWQgc3R5bGUgYW5pbWF0b3IgZm9yIEFjdGlvbiBTaGVldC5cbiAqL1xuZXhwb3J0IGNsYXNzIE1EQWN0aW9uU2hlZXRBbmltYXRvciBleHRlbmRzIEFjdGlvblNoZWV0QW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHsgdGltaW5nID0gJ2Vhc2UnLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC40IH0gPSB7fSkge1xuICAgIHN1cGVyKHt0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbn0pO1xuXG4gICAgdGhpcy5tYXNrVGltaW5nID0gJ2xpbmVhcic7XG4gICAgdGhpcy5tYXNrRHVyYXRpb24gPSAwLjI7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgc2hvdyhkaWFsb2csIGNhbGxiYWNrKSB7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuICAgICAgYW5pbWl0KGRpYWxvZy5fbWFzaylcbiAgICAgICAgLnF1ZXVlKHsgb3BhY2l0eTogMCB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoeyBvcGFjaXR5OiAxLjAgfSwge1xuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLm1hc2tEdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMubWFza1RpbWluZ1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fc2hlZXQsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDAsIDgwJSwgMClgLCBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKScsIG9wYWNpdHk6IDEgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICBjYWxsYmFjayAmJiBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUoZGlhbG9nLCBjYWxsYmFjaykge1xuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX21hc2spXG4gICAgICAgIC5xdWV1ZSh7IG9wYWNpdHk6IDEgfSlcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHsgb3BhY2l0eTogMCB9LCB7XG4gICAgICAgICAgZHVyYXRpb246IHRoaXMubWFza0R1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogdGhpcy5tYXNrVGltaW5nXG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9zaGVldCwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknLCBvcGFjaXR5OiAxIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCA4MCUsIDApYCwgb3BhY2l0eTogMCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBpT1Mgc3R5bGUgYW5pbWF0b3IgZm9yIGRpYWxvZy5cbiAqL1xuZXhwb3J0IGNsYXNzIElPU0FjdGlvblNoZWV0QW5pbWF0b3IgZXh0ZW5kcyBBY3Rpb25TaGVldEFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7IHRpbWluZyA9ICdlYXNlJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuMyB9ID0ge30pIHtcbiAgICBzdXBlcih7dGltaW5nLCBkZWxheSwgZHVyYXRpb259KTtcblxuICAgIHRoaXMubWFza1RpbWluZyA9ICdsaW5lYXInO1xuICAgIHRoaXMubWFza0R1cmF0aW9uID0gMC4yO1xuICAgIGlmIChpUGhvbmVYUGF0Y2guaXNJUGhvbmVYUG9ydHJhaXRQYXRjaEFjdGl2ZSgpKSB7XG4gICAgICB0aGlzLmxpZnRBbW91bnQgPSAnY2FsYygxMDAlICsgNDhweCknO1xuICAgIH0gZWxzZSBpZiAoaVBob25lWFBhdGNoLmlzSVBob25lWExhbmRzY2FwZVBhdGNoQWN0aXZlKCkpIHtcbiAgICAgIHRoaXMubGlmdEFtb3VudCA9ICdjYWxjKDEwMCUgKyAzM3B4KSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubGlmdEFtb3VudCA9IGRvY3VtZW50LmJvZHkuY2xpZW50SGVpZ2h0IC8gMi4wIC0gMSArICdweCc7IC8vIGF2b2lkIEZvcmNlZCBTeW5jaHJvbm91cyBMYXlvdXRcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgc2hvdyhkaWFsb2csIGNhbGxiYWNrKSB7XG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fbWFzaylcbiAgICAgIC5xdWV1ZSh7IG9wYWNpdHk6IDAgfSlcbiAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAucXVldWUoeyBvcGFjaXR5OiAxIH0sIHtcbiAgICAgICAgZHVyYXRpb246IHRoaXMubWFza0R1cmF0aW9uLFxuICAgICAgICB0aW1pbmc6IHRoaXMubWFza1RpbWluZ1xuICAgICAgfSksXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX3NoZWV0LCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCAke3RoaXMubGlmdEFtb3VudH0sIDApYCB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknIH1cbiAgICAgICAgKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZGlhbG9nXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBoaWRlKGRpYWxvZywgY2FsbGJhY2spIHtcbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9tYXNrKVxuICAgICAgLnF1ZXVlKHsgb3BhY2l0eTogMSB9KVxuICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgIC5xdWV1ZSh7IG9wYWNpdHk6IDAgfSwge1xuICAgICAgICBkdXJhdGlvbjogdGhpcy5tYXNrRHVyYXRpb24sXG4gICAgICAgIHRpbWluZzogdGhpcy5tYXNrVGltaW5nXG4gICAgICB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fc2hlZXQsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDAsIDApJyB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoMCwgJHt0aGlzLmxpZnRBbW91bnR9LCAwKWAgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICBjYWxsYmFjayAmJiBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQW5pbWF0b3JGYWN0b3J5IGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9hbmltYXRvci1mYWN0b3J5JztcbmltcG9ydCBEb29yTG9jayBmcm9tICcuLi8uLi9vbnMvZG9vcmxvY2snO1xuaW1wb3J0IGRldmljZUJhY2tCdXR0b25EaXNwYXRjaGVyIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9kZXZpY2UtYmFjay1idXR0b24tZGlzcGF0Y2hlcic7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQmFzZURpYWxvZ0VsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgdXRpbC50aHJvd01lbWJlcigpO1xuICB9XG5cbiAgX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSgpIHtcbiAgICB1dGlsLnRocm93TWVtYmVyKCk7XG4gIH1cblxuICBfdG9nZ2xlU3R5bGUoc2hvdWxkU2hvdykge1xuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9IHNob3VsZFNob3cgPyAnYmxvY2snIDogJ25vbmUnO1xuICB9XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yID09PSBCYXNlRGlhbG9nRWxlbWVudCkge1xuICAgICAgdXRpbC50aHJvd0Fic3RyYWN0KCk7XG4gICAgfVxuXG4gICAgdGhpcy5fdmlzaWJsZSA9IGZhbHNlO1xuICAgIHRoaXMuX2Rvb3JMb2NrID0gbmV3IERvb3JMb2NrKCk7XG4gICAgdGhpcy5fY2FuY2VsID0gdGhpcy5fY2FuY2VsLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fc2VsZkNhbWVsTmFtZSA9IHV0aWwuY2FtZWxpemUodGhpcy50YWdOYW1lLnNsaWNlKDQpKTtcbiAgICB0aGlzLl9kZWZhdWx0REJCID0gZSA9PiB0aGlzLmNhbmNlbGFibGUgPyB0aGlzLl9jYW5jZWwoKSA6IGUuY2FsbFBhcmVudEhhbmRsZXIoKTtcbiAgICB0aGlzLl9hbmltYXRvckZhY3RvcnkgPSB0aGlzLl91cGRhdGVBbmltYXRvckZhY3RvcnkoKTtcbiAgfVxuXG4gIGdldCBvbkRldmljZUJhY2tCdXR0b24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyO1xuICB9XG5cbiAgc2V0IG9uRGV2aWNlQmFja0J1dHRvbihjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLl9iYWNrQnV0dG9uSGFuZGxlcikge1xuICAgICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIuZGVzdHJveSgpO1xuICAgIH1cblxuICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyID0gZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIuY3JlYXRlSGFuZGxlcih0aGlzLCBjYWxsYmFjayk7XG4gIH1cblxuICBfY2FuY2VsKCkge1xuICAgIGlmICh0aGlzLmNhbmNlbGFibGUgJiYgIXRoaXMuX3J1bm5pbmcpIHtcbiAgICAgIHRoaXMuX3J1bm5pbmcgPSB0cnVlO1xuICAgICAgdGhpcy5oaWRlKClcbiAgICAgICAgLnRoZW4oXG4gICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fcnVubmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdkaWFsb2ctY2FuY2VsJyk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICAoKSA9PiB0aGlzLl9ydW5uaW5nID0gZmFsc2VcbiAgICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBzaG93KC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gdGhpcy5fc2V0VmlzaWJsZSh0cnVlLCAuLi5hcmdzKTtcbiAgfVxuXG4gIGhpZGUoLi4uYXJncykge1xuICAgIHJldHVybiB0aGlzLl9zZXRWaXNpYmxlKGZhbHNlLCAuLi5hcmdzKTtcbiAgfVxuXG4gIHRvZ2dsZSguLi5hcmdzKSB7XG4gICAgcmV0dXJuIHRoaXMuX3NldFZpc2libGUoIXRoaXMudmlzaWJsZSwgLi4uYXJncyk7XG4gIH1cblxuICBfc2V0VmlzaWJsZShzaG91bGRTaG93LCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBhY3Rpb24gPSBzaG91bGRTaG93ID8gJ3Nob3cnIDogJ2hpZGUnO1xuXG4gICAgb3B0aW9ucyA9IHsgLi4ub3B0aW9ucyB9O1xuICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyA9IHV0aWwuZXh0ZW5kKFxuICAgICAgb3B0aW9ucy5hbmltYXRpb25PcHRpb25zIHx8IHt9LFxuICAgICAgQW5pbWF0b3JGYWN0b3J5LnBhcnNlQW5pbWF0aW9uT3B0aW9uc1N0cmluZyh0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uLW9wdGlvbnMnKSlcbiAgICApO1xuXG4gICAgbGV0IGNhbmNlbGVkID0gZmFsc2U7XG4gICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsIGBwcmUke2FjdGlvbn1gLCB7IC8vIHByZXNob3cgcHJlaGlkZVxuICAgICAgW3RoaXMuX3NlbGZDYW1lbE5hbWVdOiB0aGlzLFxuICAgICAgY2FuY2VsOiAoKSA9PiBjYW5jZWxlZCA9IHRydWVcbiAgICB9KTtcblxuICAgIGlmIChjYW5jZWxlZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGBDYW5jZWxlZCBpbiBwcmUke2FjdGlvbn0gZXZlbnQuYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgdGhpcy5fZG9vckxvY2sud2FpdFVubG9jaygoKSA9PiB7XG4gICAgICAgIGNvbnN0IHVubG9jayA9IHRoaXMuX2Rvb3JMb2NrLmxvY2soKTtcbiAgICAgICAgY29uc3QgYW5pbWF0b3IgPSB0aGlzLl9hbmltYXRvckZhY3RvcnkubmV3QW5pbWF0b3Iob3B0aW9ucyk7XG5cbiAgICAgICAgc2hvdWxkU2hvdyAmJiB0aGlzLl90b2dnbGVTdHlsZSh0cnVlLCBvcHRpb25zKTtcbiAgICAgICAgdGhpcy5fdmlzaWJsZSA9IHNob3VsZFNob3c7XG4gICAgICAgIHV0aWwuaW9zUGFnZVNjcm9sbEZpeChzaG91bGRTaG93KTtcblxuICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICAgIGFuaW1hdG9yW2FjdGlvbl0odGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgIXNob3VsZFNob3cgJiYgdGhpcy5fdG9nZ2xlU3R5bGUoZmFsc2UsIG9wdGlvbnMpO1xuXG4gICAgICAgICAgICB1bmxvY2soKTtcblxuICAgICAgICAgICAgdXRpbC5wcm9wYWdhdGVBY3Rpb24odGhpcywgJ18nICsgYWN0aW9uKTtcbiAgICAgICAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAncG9zdCcgKyBhY3Rpb24sIHtbdGhpcy5fc2VsZkNhbWVsTmFtZV06IHRoaXN9KTsgLy8gcG9zdHNob3cgcG9zdGhpZGVcblxuICAgICAgICAgICAgaWYgKG9wdGlvbnMuY2FsbGJhY2sgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKHRoaXMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXNvbHZlKHRoaXMpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBnZXQgdmlzaWJsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fdmlzaWJsZTtcbiAgfVxuXG4gIHNldCBkaXNhYmxlZCh2YWx1ZSkge1xuICAgIHJldHVybiB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnZGlzYWJsZWQnLCB2YWx1ZSk7XG4gIH1cblxuICBnZXQgZGlzYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdkaXNhYmxlZCcpO1xuICB9XG5cbiAgc2V0IGNhbmNlbGFibGUodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2NhbmNlbGFibGUnLCB2YWx1ZSk7XG4gIH1cblxuICBnZXQgY2FuY2VsYWJsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2NhbmNlbGFibGUnKTtcbiAgfVxuXG4gIF91cGRhdGVNYXNrKCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICBpZiAodGhpcy5fbWFzayAmJiB0aGlzLmdldEF0dHJpYnV0ZSgnbWFzay1jb2xvcicpKSB7XG4gICAgICAgIHRoaXMuX21hc2suc3R5bGUuYmFja2dyb3VuZENvbG9yID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ21hc2stY29sb3InKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGlmICh0eXBlb2YgdGhpcy5fZGVmYXVsdERCQiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdGhpcy5vbkRldmljZUJhY2tCdXR0b24gPSB0aGlzLl9kZWZhdWx0REJCLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIGlmICh0aGlzLl9tYXNrKSB7XG4gICAgICAgIHRoaXMuX21hc2suYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9jYW5jZWwsIGZhbHNlKTtcbiAgICAgICAgdXRpbC5pb3NNYXNrU2Nyb2xsRml4KHRoaXMuX21hc2ssIHRydWUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgaWYgKHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyKSB7XG4gICAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlci5kZXN0cm95KCk7XG4gICAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlciA9IG51bGw7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX21hc2spIHtcbiAgICAgIHRoaXMuX21hc2sucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9jYW5jZWwsIGZhbHNlKTtcbiAgICAgIHV0aWwuaW9zTWFza1Njcm9sbEZpeCh0aGlzLl9tYXNrLCBmYWxzZSk7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnYW5pbWF0aW9uJywgJ21hc2stY29sb3InXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdtb2RpZmllcic6XG4gICAgICAgIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCB0aGlzLl9zY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2FuaW1hdGlvbic6XG4gICAgICAgIHRoaXMuX2FuaW1hdG9yRmFjdG9yeSA9IHRoaXMuX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ21hc2stY29sb3InOlxuICAgICAgICB0aGlzLl91cGRhdGVNYXNrKCk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBnZXQgZXZlbnRzKCkge1xuICAgIHJldHVybiBbJ3ByZXNob3cnLCAncG9zdHNob3cnLCAncHJlaGlkZScsICdwb3N0aGlkZScsICdkaWFsb2ctY2FuY2VsJ107XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi8uLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi8uLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEFuaW1hdG9yRmFjdG9yeSBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvYW5pbWF0b3ItZmFjdG9yeSc7XG5pbXBvcnQgeyBBY3Rpb25TaGVldEFuaW1hdG9yLCBJT1NBY3Rpb25TaGVldEFuaW1hdG9yLCBNREFjdGlvblNoZWV0QW5pbWF0b3IgfSBmcm9tICcuL2FuaW1hdG9yJztcbmltcG9ydCBwbGF0Zm9ybSBmcm9tICcuLi8uLi9vbnMvcGxhdGZvcm0nO1xuaW1wb3J0IEJhc2VEaWFsb2dFbGVtZW50IGZyb20gJy4uL2Jhc2UvYmFzZS1kaWFsb2cnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi8uLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy5hY3Rpb24tc2hlZXQnOiAnYWN0aW9uLXNoZWV0LS0qJyxcbiAgJy5hY3Rpb24tc2hlZXQtbWFzayc6ICdhY3Rpb24tc2hlZXQtbWFzay0tKicsXG4gICcuYWN0aW9uLXNoZWV0LXRpdGxlJzogJ2FjdGlvbi1zaGVldC10aXRsZS0tKidcbn07XG5cbmNvbnN0IF9hbmltYXRvckRpY3QgPSB7XG4gICdkZWZhdWx0JzogKCkgPT4gcGxhdGZvcm0uaXNBbmRyb2lkKCkgPyBNREFjdGlvblNoZWV0QW5pbWF0b3IgOiBJT1NBY3Rpb25TaGVldEFuaW1hdG9yLFxuICAnbm9uZSc6IEFjdGlvblNoZWV0QW5pbWF0b3Jcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWFjdGlvbi1zaGVldFxuICogQGNhdGVnb3J5IGRpYWxvZ1xuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBBY3Rpb24vYm90dG9tIHNoZWV0IHRoYXQgaXMgZGlzcGxheWVkIG9uIHRvcCBvZiBjdXJyZW50IHNjcmVlbi5cbiAqXG4gKiAgICAgVGhpcyBlbGVtZW50IGNhbiBlaXRoZXIgYmUgYXR0YWNoZWQgZGlyZWN0bHkgdG8gdGhlIGA8Ym9keT5gIG9yIGR5bmFtaWNhbGx5IGNyZWF0ZWQgZnJvbSBhIHRlbXBsYXRlIHVzaW5nIHRoZSBgb25zLmNyZWF0ZUVsZW1lbnQodGVtcGxhdGUsIHsgYXBwZW5kOiB0cnVlIH0pYCB1dGlsaXR5IGZ1bmN0aW9uIGFuZCB0aGUgYDx0ZW1wbGF0ZT5gIHRhZy5cbiAqXG4gKiAgICAgVGhlIGFjdGlvbiBzaGVldCBpcyB1c2VmdWwgZm9yIGRpc3BsYXlpbmcgYSBsaXN0IG9mIG9wdGlvbnMgYW5kIGFza2luZyB0aGUgdXNlciB0byBtYWtlIGEgZGVjaXNpb24uIEEgYG9ucy1hY3Rpb24tc2hlZXQtYnV0dG9uYCBpcyBwcm92aWRlZCBmb3IgdGhpcyBwdXJwb3NlLCBhbHRob3VnaCBpdCBjYW4gY29udGFpbiBhbnkgdHlwZSBvZiBjb250ZW50LlxuICpcbiAqICAgICBJdCB3aWxsIGF1dG9tYXRpY2FsbHkgYmUgZGlzcGxheWVkIGFzIE1hdGVyaWFsIERlc2lnbiAoYm90dG9tIHNoZWV0KSB3aGVuIHJ1bm5pbmcgb24gYW4gQW5kcm9pZCBkZXZpY2UuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1cbiAqICAgICDjgqLjgq/jgrfjg6fjg7Pjgrfjg7zjg4jjgIHjgoLjgZfjgY/jga/jg5zjg4jjg6Djgrfjg7zjg4jjgpLnj77lnKjjga7jgrnjgq/jg6rjg7zjg7PkuIrjgavooajnpLrjgZfjgb7jgZnjgIJcbiAqXG4gKiAgICAg44GT44Gu6KaB57Sg44Gv44CBYDxib2R5PmDopoHntKDjgavnm7TmjqXjgqLjgr/jg4Pjg4HjgZXjgozjgovjgYvjgIHjgoLjgZfjgY/jga9gb25zLmNyZWF0ZUVsZW1lbnQodGVtcGxhdGUsIHsgYXBwZW5kOiB0cnVlIH0pYOOBqGA8dGVtcGxhdGU+YOOCv+OCsOOCkuS9v+OBo+OBpuODhuODs+ODl+ODrOODvOODiOOBi+OCieWLleeahOOBq+eUn+aIkOOBleOCjOOBvuOBmeOAglxuICpcbiAqICAgICDjgqLjgq/jgrfjg6fjg7Pjgrfjg7zjg4jjga/jgIHpgbjmip7ogqLjga7jg6rjgrnjg4jjgpLooajnpLrjgZfjgabjg6bjg7zjgrbjg7zjgavlsIvjga3jgovjga7jgavkvr/liKnjgafjgZnjgIJgb25zLWFjdGlvbi1zaGVldC1idXR0b25g44Gv44CB44GT44Gu6KaB57Sg44Gu5Lit44Gr572u44GP44Gf44KB44Gr5o+Q5L6b44GV44KM44Gm44GE44G+44GZ44GM44CB44Gd44KM5Lul5aSW44Gr44KC5LuW44Gu44Gp44Gu44KI44GG44Gq6KaB57Sg44KS5ZCr44KA44GT44Go44GM44Gn44GN44G+44GZ44CCXG4gKlxuICogICAgIEFuZHJvaWTjg4fjg5DjgqTjgrnjgaflrp/ooYzjgZXjgozjgovjgajjgY3jgavjga/jgIHoh6rli5XnmoTjgavjg57jg4bjg6rjgqLjg6vjg4fjgrbjgqTjg7Mo44Oc44OI44Og44K344O844OIKeOBqOOBl+OBpuihqOekuuOBleOCjOOBvuOBmeOAglxuICogICBbL2phXVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1EaXNwbGF5IGEgTWF0ZXJpYWwgRGVzaWduIGJvdHRvbSBzaGVldC5bL2VuXVxuICogICBbamFd44Oe44OG44Oq44Ki44Or44OH44K244Kk44Oz44Gu44Oc44OI44Og44K344O844OI44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEB0dXRvcmlhbCB2YW5pbGxhL3JlZmVyZW5jZS9hY3Rpb24tc2hlZXRcbiAqIEBndWlkZSB0aGVtaW5nLmh0bWwjbW9kaWZpZXJzIFtlbl1Nb3JlIGRldGFpbHMgYWJvdXQgdGhlIGBtb2RpZmllcmAgYXR0cmlidXRlWy9lbl1bamFdbW9kaWZpZXLlsZ7mgKfjga7kvb/jgYTmlrlbL2phXVxuICogQHNlZWFsc28gb25zLXBvcG92ZXJcbiAqICAgW2VuXWA8b25zLXBvcG92ZXI+YCBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLXBvcG92ZXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLW1vZGFsXG4gKiAgIFtlbl1gPG9ucy1tb2RhbD5gIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtbW9kYWzjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtYWN0aW9uLXNoZWV0IGlkPVwic2hlZXRcIj5cbiAqICAgPG9ucy1hY3Rpb24tc2hlZXQtYnV0dG9uPkxhYmVsPC9vbnMtYWN0aW9uLXNoZWV0LWJ1dHRvbj5cbiAqICAgPG9ucy1hY3Rpb24tc2hlZXQtYnV0dG9uPkxhYmVsPC9vbnMtYWN0aW9uLXNoZWV0LWJ1dHRvbj5cbiAqIDwvb25zLWFjdGlvbi1zaGVldD5cbiAqXG4gKiA8c2NyaXB0PlxuICogICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc2hlZXQnKS5zaG93KCk7XG4gKiA8L3NjcmlwdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQWN0aW9uU2hlZXRFbGVtZW50IGV4dGVuZHMgQmFzZURpYWxvZ0VsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlc2hvd1xuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYmVmb3JlIHRoZSBhY3Rpb24gc2hlZXQgaXMgZGlzcGxheWVkLlsvZW5dXG4gICAqIFtqYV3jg4DjgqTjgqLjg63jgrDjgYzooajnpLrjgZXjgozjgovnm7TliY3jgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuYWN0aW9uU2hlZXRcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC5jYW5jZWxcbiAgICogICBbZW5dRXhlY3V0ZSB0aGlzIGZ1bmN0aW9uIHRvIHN0b3AgdGhlIGFjdGlvbiBzaGVldCBmcm9tIGJlaW5nIHNob3duLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWun+ihjOOBmeOCi+OBqOOAgeODgOOCpOOCouODreOCsOOBruihqOekuuOBjOOCreODo+ODs+OCu+ODq+OBleOCjOOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdHNob3dcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFtlbl1GaXJlZCBqdXN0IGFmdGVyIHRoZSBhY3Rpb24gc2hlZXQgaXMgZGlzcGxheWVkLlsvZW5dXG4gICAqIFtqYV3jg4DjgqTjgqLjg63jgrDjgYzooajnpLrjgZXjgozjgZ/nm7TlvozjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuYWN0aW9uU2hlZXRcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHByZWhpZGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFtlbl1GaXJlZCBqdXN0IGJlZm9yZSB0aGUgYWN0aW9uIHNoZWV0IGlzIGhpZGRlbi5bL2VuXVxuICAgKiBbamFd44OA44Kk44Ki44Ot44Kw44GM6Zqg44KM44KL55u05YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmFjdGlvblNoZWV0XG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUV4ZWN1dGUgdGhpcyBmdW5jdGlvbiB0byBzdG9wIHRoZSBhY3Rpb24gc2hlZXQgZnJvbSBiZWluZyBoaWRkZW4uWy9lbl1cbiAgICogICBbamFd44GT44Gu6Zai5pWw44KS5a6f6KGM44GZ44KL44Go44CB44OA44Kk44Ki44Ot44Kw44Gu6Z2e6KGo56S644GM44Kt44Oj44Oz44K744Or44GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBwb3N0aGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIGFjdGlvbiBzaGVldCBpcyBoaWRkZW4uWy9lbl1cbiAgICogW2phXeODgOOCpOOCouODreOCsOOBjOmaoOOCjOOBn+W+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5hY3Rpb25TaGVldFxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHRpdGxlXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXU9wdGlvbmFsIHRpdGxlIG9mIHRoZSBhY3Rpb24gc2hlZXQuIEEgbmV3IGVsZW1lbnQgd2lsbCBiZSBjcmVhdGVkIGNvbnRhaW5pbmcgdGhpcyBzdHJpbmcuWy9lbl1cbiAgICogIFtqYV3jgqLjgq/jgrfjg6fjg7Pjgrfjg7zjg4jjga7jgr/jgqTjg4jjg6vjgpLmjIflrprjgZfjgb7jgZnjgILjgZPjgZPjgafmjIflrprjgZfjgZ/mloflrZfliJfjgpLlkKvjgoDmlrDjgZfjgYTopoHntKDjgYzkvZzmiJDjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgYWN0aW9uIHNoZWV0LlsvZW5dXG4gICAqICBbamFd44OA44Kk44Ki44Ot44Kw44Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgY2FuY2VsYWJsZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGFjdGlvbiBzaGVldCBjYW4gYmUgY2xvc2VkIGJ5IHRhcHBpbmcgdGhlIGJhY2tncm91bmQgb3IgYnkgcHJlc3NpbmcgdGhlIGJhY2sgYnV0dG9uIG9uIEFuZHJvaWQgZGV2aWNlcy5bL2VuXVxuICAgKiAgW2phXeOBk+OBruWxnuaAp+OBjOioreWumuOBleOCjOOCi+OBqOOAgeOCouOCr+OCt+ODp+ODs+OCt+ODvOODiOOBruiDjOaZr+OChEFuZHJvaWTjg4fjg5DjgqTjgrnjga7jg5Djg4Pjgq/jg5zjgr/jg7PjgpLmjqjjgZnjgZPjgajjgafjgqLjgq/jgrfjg6fjg7Pjgrfjg7zjg4jjgYzplonjgZjjgovjgojjgYbjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXNhYmxlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGFjdGlvbiBzaGVldCBpcyBkaXNhYmxlZC5bL2VuXVxuICAgKiAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+aZguOAgeODgOOCpOOCouODreOCsOOBr2Rpc2FibGVk54q25oWL44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGRlZmF1bHRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFuaW1hdGlvbiB1c2VkIHdoZW4gc2hvd2luZyBhbmQgaGlkaW5nIHRoZSBhY3Rpb24gc2hlZXQuIENhbiBiZSBlaXRoZXIgYFwibm9uZVwiYCBvciBgXCJkZWZhdWx0XCJgLlsvZW5dXG4gICAqICBbamFd44OA44Kk44Ki44Ot44Kw44KS6KGo56S644GZ44KL6Zqb44Gu44Ki44OL44Oh44O844K344On44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCXCJub25lXCLjgoLjgZfjgY/jga9cImRlZmF1bHRcIuOCkuaMh+WumuOBp+OBjeOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGFuaW1hdGlvbi1vcHRpb25zXG4gICAqIEB0eXBlIHtFeHByZXNzaW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgdGltaW5nIGFuZCBkZWxheSB3aXRoIGFuIG9iamVjdCBsaXRlcmFsLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgdGltaW5nLCBkZWxheeOCkuOCquODluOCuOOCp+OCr+ODiOODquODhuODqeODq+OBp+aMh+WumuOBl+OBvuOBmeOAgmUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9YFsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1hc2stY29sb3JcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgcmdiYSgwLCAwLCAwLCAwLjIpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXUNvbG9yIG9mIHRoZSBiYWNrZ3JvdW5kIG1hc2suIERlZmF1bHQgaXMgYFwicmdiYSgwLCAwLCAwLCAwLjIpXCJgLlsvZW5dXG4gICAqICBbamFd6IOM5pmv44Gu44Oe44K544Kv44Gu6Imy44KS5oyH5a6a44GX44G+44GZ44CCXCJyZ2JhKDAsIDAsIDAsIDAuMilcIuOBjOODh+ODleOCqeODq+ODiOWApOOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fY29tcGlsZSgpKTtcbiAgfVxuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHJldHVybiBzY2hlbWU7XG4gIH1cblxuICBnZXQgX21hc2soKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICcuYWN0aW9uLXNoZWV0LW1hc2snKTtcbiAgfVxuXG4gIGdldCBfc2hlZXQoKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICcuYWN0aW9uLXNoZWV0Jyk7XG4gIH1cblxuICBnZXQgX3RpdGxlKCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3IoJy5hY3Rpb24tc2hlZXQtdGl0bGUnKTtcbiAgfVxuXG4gIF91cGRhdGVBbmltYXRvckZhY3RvcnkoKSB7XG4gICAgcmV0dXJuIG5ldyBBbmltYXRvckZhY3Rvcnkoe1xuICAgICAgYW5pbWF0b3JzOiBfYW5pbWF0b3JEaWN0LFxuICAgICAgYmFzZUNsYXNzOiBBY3Rpb25TaGVldEFuaW1hdG9yLFxuICAgICAgYmFzZUNsYXNzTmFtZTogJ0FjdGlvblNoZWV0QW5pbWF0b3InLFxuICAgICAgZGVmYXVsdEFuaW1hdGlvbjogdGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpXG4gICAgfSk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICB0aGlzLnN0eWxlLnpJbmRleCA9IDEwMDAxO1xuXG4gICAgLyogRXhwZWN0ZWQgcmVzdWx0OlxuICAgICAqICAgPG9ucy1hY3Rpb24tc2hlZXQ+XG4gICAgICogICAgIDxkaXYgY2xhc3M9XCJhY3Rpb24tc2hlZXQtbWFza1wiPjwvZGl2PlxuICAgICAqICAgICA8ZGl2IGNsYXNzPVwiYWN0aW9uLXNoZWV0XCI+XG4gICAgICogICAgICAgPGRpdiBjbGFzcz1cImFjdGlvbi1zaGVldC10aXRsZT48L2Rpdj5cbiAgICAgKiAgICAgICAuLi5cbiAgICAgKiAgICAgPC9kaXY+XG4gICAgICogICA8L29ucy1hY3Rpb24tc2hlZXQ+XG4gICAgICovXG5cbiAgICBpZiAoIXRoaXMuX3NoZWV0KSB7XG4gICAgICBjb25zdCBzaGVldCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgc2hlZXQuY2xhc3NMaXN0LmFkZCgnYWN0aW9uLXNoZWV0Jyk7XG5cbiAgICAgIHdoaWxlICh0aGlzLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgc2hlZXQuYXBwZW5kQ2hpbGQodGhpcy5maXJzdENoaWxkKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5hcHBlbmRDaGlsZChzaGVldCk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLl90aXRsZSAmJiB0aGlzLmhhc0F0dHJpYnV0ZSgndGl0bGUnKSkge1xuICAgICAgY29uc3QgdGl0bGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIHRpdGxlLmlubmVySFRNTCA9IHRoaXMuZ2V0QXR0cmlidXRlKCd0aXRsZScpO1xuICAgICAgdGl0bGUuY2xhc3NMaXN0LmFkZCgnYWN0aW9uLXNoZWV0LXRpdGxlJyk7XG4gICAgICB0aGlzLl9zaGVldC5pbnNlcnRCZWZvcmUodGl0bGUsIHRoaXMuX3NoZWV0LmZpcnN0Q2hpbGQpO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5fbWFzaykge1xuICAgICAgY29uc3QgbWFzayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgbWFzay5jbGFzc0xpc3QuYWRkKCdhY3Rpb24tc2hlZXQtbWFzaycpO1xuICAgICAgdGhpcy5pbnNlcnRCZWZvcmUobWFzaywgdGhpcy5maXJzdENoaWxkKTtcbiAgICB9XG5cbiAgICB0aGlzLl9zaGVldC5zdHlsZS56SW5kZXggPSAyMDAwMTtcbiAgICB0aGlzLl9tYXNrLnN0eWxlLnpJbmRleCA9IDIwMDAwO1xuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCB0aGlzLl9zY2hlbWUpO1xuICB9XG5cbiAgX3VwZGF0ZVRpdGxlKCkge1xuICAgIGlmICh0aGlzLl90aXRsZSkge1xuICAgICAgdGhpcy5fdGl0bGUuaW5uZXJIVE1MID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3RpdGxlJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvbkRldmljZUJhY2tCdXR0b25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUJhY2stYnV0dG9uIGhhbmRsZXIuWy9lbl1cbiAgICogICBbamFd44OQ44OD44Kv44Oc44K/44Oz44OP44Oz44OJ44Op44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBtZXRob2Qgc2hvd1xuICAgKiBAc2lnbmF0dXJlIHNob3coW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJub25lXCJgIGFuZCBgXCJzbGlkZVwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcIm5vbmVcIiwgXCJzbGlkZVwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gIFsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1UaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBhZnRlciB0aGUgYWN0aW9uIHNoZWV0IGhhcyBiZWVuIHJldmVhbGVkLlsvZW5dXG4gICAqICAgW2phXeODgOOCpOOCouODreOCsOOBjOihqOekuuOBleOCjOe1guOCj+OBo+OBn+W+jOOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNob3cgdGhlIGFjdGlvbiBzaGVldC5bL2VuXVxuICAgKiAgW2phXeODgOOCpOOCouODreOCsOOCkumWi+OBjeOBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IFJlc29sdmVzIHRvIHRoZSBkaXNwbGF5ZWQgZWxlbWVudC5cbiAgICovXG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaGlkZVxuICAgKiBAc2lnbmF0dXJlIGhpZGUoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJub25lXCJgIGFuZCBgXCJzbGlkZVwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcIm5vbmVcIiwgXCJzbGlkZVwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXVRoaXMgZnVuY3Rpb25zIGlzIGNhbGxlZCBhZnRlciB0aGUgYWN0aW9uIHNoZWV0IGhhcyBiZWVuIGhpZGRlbi5bL2VuXVxuICAgKiAgIFtqYV3jg4DjgqTjgqLjg63jgrDjgYzpmqDjgozjgZ/lvozjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSGlkZSB0aGUgYWN0aW9uIHNoZWV0LlsvZW5dXG4gICAqICAgW2phXeODgOOCpOOCouODreOCsOOCkumWieOBmOOBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVJlc29sdmVzIHRvIHRoZSBoaWRkZW4gZWxlbWVudFsvZW5dXG4gICAqICAgW2phXemaoOOCjOOBn+imgee0oOOCkuino+axuuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdmlzaWJsZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBhY3Rpb24gc2hlZXQgaXMgdmlzaWJsZSBvciBub3QuWy9lbl1cbiAgICogICBbamFd6KaB57Sg44GM6KaL44GI44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGFjdGlvbiBzaGVldCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBjYW5jZWxhYmxlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgYWN0aW9uIHNoZWV0IGlzIGNhbmNlbGFibGUgb3Igbm90LiBBIGNhbmNlbGFibGUgYWN0aW9uIHNoZWV0IGNhbiBiZSBjbG9zZWQgYnkgdGFwcGluZyB0aGUgYmFja2dyb3VuZCBvciBieSBwcmVzc2luZyB0aGUgYmFjayBidXR0b24gb24gQW5kcm9pZCBkZXZpY2VzLlsvZW5dXG4gICAqICAgW2phXeOCouOCr+OCt+ODp+ODs+OCt+ODvOODiOOBjOOCreODo+ODs+OCu+ODq+WPr+iDveOBi+OBqeOBhuOBi+OCkuioreWumuOBl+OBvuOBmeOAguOCreODo+ODs+OCu+ODq+WPr+iDveOBquOCouOCr+OCt+ODp+ODs+OCt+ODvOODiOOBr+OAgeiDjOaZr+OCkuOCv+ODg+ODl+OBl+OBn+OCikFuZHJvaWTjg4fjg5DjgqTjgrnjga7jg5Djg4Pjgq/jg5zjgr/jg7PjgpLmjqjjgZnjgZPjgajjgafplonjgZjjgovjgojjgYbjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWy4uLnN1cGVyLm9ic2VydmVkQXR0cmlidXRlcywgJ3RpdGxlJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIGlmIChuYW1lID09PSAndGl0bGUnKSB7XG4gICAgICB0aGlzLl91cGRhdGVUaXRsZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdXBlci5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7QWN0aW9uU2hlZXRBbmltYXRvcn0gQW5pbWF0b3JcbiAgICovXG4gIHN0YXRpYyByZWdpc3RlckFuaW1hdG9yKG5hbWUsIEFuaW1hdG9yKSB7XG4gICAgaWYgKCEoQW5pbWF0b3IucHJvdG90eXBlIGluc3RhbmNlb2YgQWN0aW9uU2hlZXRBbmltYXRvcikpIHtcbiAgICAgIHV0aWwudGhyb3dBbmltYXRvcignQWN0aW9uU2hlZXQnKTtcbiAgICB9XG4gICAgX2FuaW1hdG9yRGljdFtuYW1lXSA9IEFuaW1hdG9yO1xuICB9XG5cbiAgc3RhdGljIGdldCBhbmltYXRvcnMoKSB7XG4gICAgcmV0dXJuIF9hbmltYXRvckRpY3Q7XG4gIH1cblxuICBzdGF0aWMgZ2V0IEFjdGlvblNoZWV0QW5pbWF0b3IoKSB7XG4gICAgcmV0dXJuIEFjdGlvblNoZWV0QW5pbWF0b3I7XG4gIH1cbn1cblxub25zRWxlbWVudHMuQWN0aW9uU2hlZXQgPSBBY3Rpb25TaGVldEVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1hY3Rpb24tc2hlZXQnLCBBY3Rpb25TaGVldEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uLy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uLy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi8uLi9vbnMvY29udGVudC1yZWFkeSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UtZWxlbWVudCc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJhc2VCdXR0b25FbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHV0aWwudGhyb3dNZW1iZXIoKTtcbiAgfVxuXG4gIGdldCBfZGVmYXVsdENsYXNzTmFtZSgpIHtcbiAgICB1dGlsLnRocm93TWVtYmVyKCk7XG4gIH1cblxuICBnZXQgX3JpcHBsZU9wdCgpIHtcbiAgICByZXR1cm4gW3RoaXNdO1xuICB9XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yID09PSBCYXNlQnV0dG9uRWxlbWVudCkge1xuICAgICAgdXRpbC50aHJvd0Fic3RyYWN0KCk7XG4gICAgfVxuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX2NvbXBpbGUoKSk7XG4gIH1cblxuICBzZXQgZGlzYWJsZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2Rpc2FibGVkJywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IGRpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKTtcbiAgfVxuXG4gIGdldCBfaWNvbigpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJ29ucy1pY29uJyk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIHRoaXMuY2xhc3NMaXN0LmFkZCh0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lKTtcblxuICAgIGlmICghdGhpcy5faWNvbiAmJiB0aGlzLmhhc0F0dHJpYnV0ZSgnaWNvbicpKSB7XG4gICAgICB1dGlsLmNoZWNrTWlzc2luZ0ltcG9ydCgnSWNvbicpO1xuICAgICAgY29uc3QgaWNvbiA9IHV0aWwuY3JlYXRlRWxlbWVudChgPG9ucy1pY29uIGljb249XCIke3RoaXMuZ2V0QXR0cmlidXRlKCdpY29uJyl9XCI+PC9vbnMtaWNvbj5gKTtcbiAgICAgIGljb24uY2xhc3NMaXN0LmFkZCh0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lLnJlcGxhY2UoJ2J1dHRvbicsICdpY29uJykpO1xuICAgICAgdGhpcy5pbnNlcnRCZWZvcmUoaWNvbiwgdGhpcy5maXJzdENoaWxkKTtcbiAgICB9XG5cbiAgICB0aGlzLl91cGRhdGVSaXBwbGUoKTtcblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgdGhpcy5fc2NoZW1lKTtcbiAgfVxuXG4gIF91cGRhdGVJY29uKCkge1xuICAgIGlmICh0aGlzLl9pY29uKSB7XG4gICAgICB0aGlzLl9pY29uLnNldEF0dHJpYnV0ZSgnaWNvbicsIHRoaXMuZ2V0QXR0cmlidXRlKCdpY29uJykpO1xuICAgIH1cbiAgfVxuXG4gIF91cGRhdGVSaXBwbGUoKSB7XG4gICAgdGhpcy5fcmlwcGxlT3B0ICYmIHV0aWwudXBkYXRlUmlwcGxlKC4uLnRoaXMuX3JpcHBsZU9wdCk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllcicsICdjbGFzcycsICdpY29uJywgJ3JpcHBsZSddO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBzd2l0Y2ggKG5hbWUpIHtcbiAgICAgIGNhc2UgJ2NsYXNzJzpcbiAgICAgICAgdXRpbC5yZXN0b3JlQ2xhc3ModGhpcywgdGhpcy5fZGVmYXVsdENsYXNzTmFtZSwgdGhpcy5fc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdtb2RpZmllcic6XG4gICAgICAgIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCB0aGlzLl9zY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2ljb24nOlxuICAgICAgICB0aGlzLl91cGRhdGVJY29uKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncmlwcGxlJzpcbiAgICAgICAgdGhpcy5jbGFzc0xpc3QuY29udGFpbnModGhpcy5fZGVmYXVsdENsYXNzTmFtZSkgJiYgdGhpcy5fdXBkYXRlUmlwcGxlKCk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgQmFzZUJ1dHRvbkVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtYnV0dG9uJztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtYWN0aW9uLXNoZWV0LWJ1dHRvblxuICogQGNhdGVnb3J5IGRpYWxvZ1xuICogQG1vZGlmaWVyIGRlc3RydWN0aXZlXG4gKiAgIFtlbl1TaG93cyBhIFwiZGVzdHJ1Y3RpdmVcIiBidXR0b24gKG9ubHkgZm9yIGlPUykuWy9lbl1cbiAqICAgW2phXVwiZGVzdHJ1Y3RpdmVcIuOBquODnOOCv+ODs+OCkuihqOekuuOBl+OBvuOBmShpT1Pjgafjga7jgb/mnInlirkp44CCWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dQ29tcG9uZW50IHRoYXQgcmVwcmVzZW50IGVhY2ggYnV0dG9uIG9mIHRoZSBhY3Rpb24gc2hlZXQuWy9lbl1cbiAqICAgW2phXeOCouOCr+OCt+ODp+ODs+OCt+ODvOODiOOBq+ihqOekuuOBleOCjOOCi+WQhOODnOOCv+ODs+OCkuihqOePvuOBmeOCi+OCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAglsvamFdXG4gKiBAc2VlYWxzbyBvbnMtYWN0aW9uLXNoZWV0XG4gKiAgIFtlbl1UaGUgYDxvbnMtYWN0aW9uLXNoZWV0PmAgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1hY3Rpb24tc2hlZXTjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLWxpc3QtaXRlbVxuICogICBbZW5dVGhlIGA8b25zLWxpc3QtaXRlbT5gIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtbGlzdC1pdGVt44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1pY29uXG4gKiAgIFtlbl1UaGUgYDxvbnMtaWNvbj5gIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtaWNvbuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvYWN0aW9uLXNoZWV0XG4gKiBAZ3VpZGUgYXBwc2l6ZS5odG1sI3JlbW92aW5nLWljb24tcGFja3MgW2VuXVJlbW92aW5nIGljb24gcGFja3MuWy9lbl1bamFdWy9qYV1cbiAqIEBndWlkZSBmYXEuaHRtbCNob3ctY2FuLWktdXNlLWN1c3RvbS1pY29uLXBhY2tzIFtlbl1BZGRpbmcgY3VzdG9tIGljb24gcGFja3MuWy9lbl1bamFdWy9qYV1cbiAqIEBtb2RpZmllciBtYXRlcmlhbFxuICogICBbZW5dRGlzcGxheSBhIE1hdGVyaWFsIERlc2lnbiBhY3Rpb24gc2hlZXQgYnV0dG9uLlsvZW5dXG4gKiAgIFtqYV3jg57jg4bjg6rjgqLjg6vjg4fjgrbjgqTjg7Pjga7jgqLjgq/jgrfjg6fjg7Pjgrfjg7zjg4jnlKjjga7jg5zjgr/jg7PjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtYWN0aW9uLXNoZWV0IGlkPVwic2hlZXRcIj5cbiAqICAgPG9ucy1hY3Rpb24tc2hlZXQtYnV0dG9uPkxhYmVsPC9vbnMtYWN0aW9uLXNoZWV0LWJ1dHRvbj5cbiAqICAgPG9ucy1hY3Rpb24tc2hlZXQtYnV0dG9uPkxhYmVsPC9vbnMtYWN0aW9uLXNoZWV0LWJ1dHRvbj5cbiAqIDwvb25zLWFjdGlvbi1zaGVldD5cbiAqXG4gKiA8c2NyaXB0PlxuICogICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc2hlZXQnKS5zaG93KCk7XG4gKiA8L3NjcmlwdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQWN0aW9uU2hlZXRCdXR0b25FbGVtZW50IGV4dGVuZHMgQmFzZUJ1dHRvbkVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGljb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dQ3JlYXRlcyBhbiBgb25zLWljb25gIGNvbXBvbmVudCB3aXRoIHRoaXMgc3RyaW5nLiBPbmx5IHZpc2libGUgb24gQW5kcm9pZC4gQ2hlY2sgW1NlZSBhbHNvXSgjc2VlYWxzbykgc2VjdGlvbiBmb3IgbW9yZSBpbmZvcm1hdGlvbi5bL2VuXVxuICAgKiAgW2phXWBvbnMtaWNvbmDjgrPjg7Pjg53jg7zjg43jg7Pjg4jjgpLmgqrmgKfjgZfjgb7jgZnjgIJBbmRyb2lk44Gn44Gu44G/6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBhY3Rpb24gc2hlZXQgYnV0dG9uLlsvZW5dXG4gICAqICAgW2phXeOCouOCr+OCt+ODp+ODs+OCt+ODvOODiOODnOOCv+ODs+OBruimi+OBn+ebruOCkuioreWumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHJldHVybiB7XG4gICAgICAnJzogJ2FjdGlvbi1zaGVldC1idXR0b24tLSonLFxuICAgICAgJy5hY3Rpb24tc2hlZXQtaWNvbic6ICdhY3Rpb24tc2hlZXQtaWNvbi0tKidcbiAgICB9O1xuICB9XG5cbiAgZ2V0IF9kZWZhdWx0Q2xhc3NOYW1lKCkge1xuICAgIHJldHVybiAnYWN0aW9uLXNoZWV0LWJ1dHRvbic7XG4gIH1cblxuICBnZXQgX3JpcHBsZU9wdCgpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLkFjdGlvblNoZWV0QnV0dG9uID0gQWN0aW9uU2hlZXRCdXR0b25FbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtYWN0aW9uLXNoZWV0LWJ1dHRvbicsIEFjdGlvblNoZWV0QnV0dG9uRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuaW1wb3J0IEJhc2VBbmltYXRvciBmcm9tICcuLi8uLi9vbnMvYmFzZS1hbmltYXRvcic7XG5cbmV4cG9ydCBjbGFzcyBBbGVydERpYWxvZ0FuaW1hdG9yIGV4dGVuZHMgQmFzZUFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7dGltaW5nID0gJ2xpbmVhcicsIGRlbGF5ID0gMCwgZHVyYXRpb24gPSAwLjJ9ID0ge30pIHtcbiAgICBzdXBlcih7IHRpbWluZywgZGVsYXksIGR1cmF0aW9uIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBzaG93KGRpYWxvZywgZG9uZSkge1xuICAgIGRvbmUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZG9uZVxuICAgKi9cbiAgaGlkZShkaWFsb2csIGRvbmUpIHtcbiAgICBkb25lKCk7XG4gIH1cbn1cblxuLyoqXG4gKiBBbmRyb2lkIHN0eWxlIGFuaW1hdG9yIGZvciBhbGVydCBkaWFsb2cuXG4gKi9cbmV4cG9ydCBjbGFzcyBBbmRyb2lkQWxlcnREaWFsb2dBbmltYXRvciBleHRlbmRzIEFsZXJ0RGlhbG9nQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnY3ViaWMtYmV6aWVyKC4xLCAuNywgLjQsIDEpJywgZHVyYXRpb24gPSAwLjIsIGRlbGF5ID0gMH0gPSB7fSkge1xuICAgIHN1cGVyKHtkdXJhdGlvbiwgdGltaW5nLCBkZWxheX0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHNob3coZGlhbG9nLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9tYXNrLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAwIH0sIHsgb3BhY2l0eTogMSB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fZGlhbG9nLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKSBzY2FsZTNkKC45LCAuOSwgMSknLCBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKSBzY2FsZTNkKDEsIDEsIDEpJywgb3BhY2l0eTogMSB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgaGlkZShkaWFsb2csIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjayA/IGNhbGxiYWNrIDogZnVuY3Rpb24oKSB7fTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX21hc2ssIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdCh7IG9wYWNpdHk6IDEgfSwgeyBvcGFjaXR5OiAwIH0pLFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9kaWFsb2csIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC01MCUsIC01MCUsIDApIHNjYWxlM2QoMSwgMSwgMSknLCBvcGFjaXR5OiAxIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKSBzY2FsZTNkKC45LCAuOSwgMSknLCBvcGFjaXR5OiAwIH1cbiAgICAgICAgKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIGlPUyBzdHlsZSBhbmltYXRvciBmb3IgYWxlcnQgZGlhbG9nLlxuICovXG5leHBvcnQgY2xhc3MgSU9TQWxlcnREaWFsb2dBbmltYXRvciBleHRlbmRzIEFsZXJ0RGlhbG9nQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnY3ViaWMtYmV6aWVyKC4xLCAuNywgLjQsIDEpJywgZHVyYXRpb24gPSAwLjIsIGRlbGF5ID0gMH0gPSB7fSkge1xuICAgIHN1cGVyKHtkdXJhdGlvbiwgdGltaW5nLCBkZWxheX0pO1xuICB9XG5cbiAgLypcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgc2hvdyhkaWFsb2csIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjayA/IGNhbGxiYWNrIDogZnVuY3Rpb24oKSB7fTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX21hc2ssIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdCh7IG9wYWNpdHk6IDAgfSwgeyBvcGFjaXR5OiAxIH0pLFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9kaWFsb2csIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC01MCUsIC01MCUsIDApIHNjYWxlM2QoMS4zLCAxLjMsIDEpJywgb3BhY2l0eTogMCB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoLTUwJSwgLTUwJSwgMCkgc2NhbGUzZCgxLCAxLCAxKScsIG9wYWNpdHk6IDEgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUoZGlhbG9nLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9tYXNrLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAxIH0sIHsgb3BhY2l0eTogMCB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fZGlhbG9nLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAxIH0sIHsgb3BhY2l0eTogMCB9KVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uLy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uLy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQW5pbWF0b3JGYWN0b3J5IGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9hbmltYXRvci1mYWN0b3J5JztcbmltcG9ydCB7IEFsZXJ0RGlhbG9nQW5pbWF0b3IsIElPU0FsZXJ0RGlhbG9nQW5pbWF0b3IsIEFuZHJvaWRBbGVydERpYWxvZ0FuaW1hdG9yIH0gZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vLi4vb25zL3BsYXRmb3JtJztcbmltcG9ydCBCYXNlRGlhbG9nRWxlbWVudCBmcm9tICcuLi9iYXNlL2Jhc2UtZGlhbG9nJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBzY2hlbWUgPSB7XG4gICcuYWxlcnQtZGlhbG9nJzogJ2FsZXJ0LWRpYWxvZy0tKicsXG4gICcuYWxlcnQtZGlhbG9nLWNvbnRhaW5lcic6ICdhbGVydC1kaWFsb2ctY29udGFpbmVyLS0qJyxcbiAgJy5hbGVydC1kaWFsb2ctdGl0bGUnOiAnYWxlcnQtZGlhbG9nLXRpdGxlLS0qJyxcbiAgJy5hbGVydC1kaWFsb2ctY29udGVudCc6ICdhbGVydC1kaWFsb2ctY29udGVudC0tKicsXG4gICcuYWxlcnQtZGlhbG9nLWZvb3Rlcic6ICdhbGVydC1kaWFsb2ctZm9vdGVyLS0qJyxcbiAgJy5hbGVydC1kaWFsb2ctZm9vdGVyLS1yb3dmb290ZXInOiAnYWxlcnQtZGlhbG9nLWZvb3Rlci0tcm93Zm9vdGVyLS0qJyxcbiAgJy5hbGVydC1kaWFsb2ctYnV0dG9uLS1yb3dmb290ZXInOiAnYWxlcnQtZGlhbG9nLWJ1dHRvbi0tcm93Zm9vdGVyLS0qJyxcbiAgJy5hbGVydC1kaWFsb2ctYnV0dG9uLS1wcmltYWwnOiAnYWxlcnQtZGlhbG9nLWJ1dHRvbi0tcHJpbWFsLS0qJyxcbiAgJy5hbGVydC1kaWFsb2ctYnV0dG9uJzogJ2FsZXJ0LWRpYWxvZy1idXR0b24tLSonLFxuICAnb25zLWFsZXJ0LWRpYWxvZy1idXR0b24nOiAnYWxlcnQtZGlhbG9nLWJ1dHRvbi0tKicsXG4gICcuYWxlcnQtZGlhbG9nLW1hc2snOiAnYWxlcnQtZGlhbG9nLW1hc2stLSonLFxuICAnLnRleHQtaW5wdXQnOiAndGV4dC1pbnB1dC0tKidcbn07XG5cbmNvbnN0IF9hbmltYXRvckRpY3QgPSB7XG4gICdub25lJzogQWxlcnREaWFsb2dBbmltYXRvcixcbiAgJ2RlZmF1bHQnOiAoKSA9PiBwbGF0Zm9ybS5pc0FuZHJvaWQoKSA/IEFuZHJvaWRBbGVydERpYWxvZ0FuaW1hdG9yIDogSU9TQWxlcnREaWFsb2dBbmltYXRvcixcbiAgJ2ZhZGUnOiAoKSA9PiBwbGF0Zm9ybS5pc0FuZHJvaWQoKSA/IEFuZHJvaWRBbGVydERpYWxvZ0FuaW1hdG9yIDogSU9TQWxlcnREaWFsb2dBbmltYXRvclxufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtYWxlcnQtZGlhbG9nXG4gKiBAY2F0ZWdvcnkgZGlhbG9nXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIEFsZXJ0IGRpYWxvZyB0aGF0IGlzIGRpc3BsYXllZCBvbiB0b3Agb2YgdGhlIGN1cnJlbnQgc2NyZWVuLiBVc2VmdWwgZm9yIGRpc3BsYXlpbmcgcXVlc3Rpb25zLCB3YXJuaW5ncyBvciBlcnJvciBtZXNzYWdlcyB0byB0aGUgdXNlci4gVGhlIHRpdGxlLCBjb250ZW50IGFuZCBidXR0b25zIGNhbiBiZSBlYXNpbHkgY3VzdG9taXplZCBhbmQgaXQgd2lsbCBhdXRvbWF0aWNhbGx5IHN3aXRjaCBzdHlsZSBiYXNlZCBvbiB0aGUgcGxhdGZvcm0uXG4gKlxuICogICAgIFRvIHVzZSB0aGUgZWxlbWVudCBpdCBjYW4gZWl0aGVyIGJlIGF0dGFjaGVkIGRpcmVjdGx5IHRvIHRoZSBgPGJvZHk+YCBlbGVtZW50IG9yIGR5bmFtaWNhbGx5IGNyZWF0ZWQgZnJvbSBhIHRlbXBsYXRlIHVzaW5nIHRoZSBgb25zLmNyZWF0ZUFsZXJ0RGlhbG9nKHRlbXBsYXRlKWAgdXRpbGl0eSBmdW5jdGlvbiBhbmQgdGhlIGA8dGVtcGxhdGU+YCB0YWcuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1cbiAqICAgICDnj77lnKjjga7jgrnjgq/jg6rjg7zjg7Pjga7kuIrjgavooajnpLrjgZnjgovjgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjgafjgZnjgILjg6bjg7zjgrbjgavlr77jgZnjgovllY/jgYTjgYvjgZHjgIHorablkYrjgIHjgqjjg6njg7zjg6Hjg4Pjgrvjg7zjgrjjgpLooajnpLrjgZnjgovjga7jgavliKnnlKjjgafjgY3jgb7jgZnjgILjgr/jgqTjg4jjg6vjgoTjgrPjg7Pjg4bjg7Pjg4TjgoTjg5zjgr/jg7Pjga/nsKHljZjjgavjgqvjgrnjgr/jg57jgqTjgrrjgafjgY3jgIHlrp/ooYzjgZfjgabjgYTjgovjg5fjg6njg4Pjg4jjg5Xjgqnjg7zjg6DjgavkvbXjgZvjgabjgrnjgr/jgqTjg6vjgYzoh6rli5XnmoTjgavliIfjgormm7/jgo/jgorjgb7jgZnjgIJcbiAqICAgWy9qYV1cbiAqIEBjb2RlcGVuIFF3d3h5cFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2FsZXJ0LWRpYWxvZ1xuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1NYXRlcmlhbCBEZXNpZ24gc3R5bGVbL2VuXVxuICogICBbamFd44Oe44OG44Oq44Ki44Or44OH44K244Kk44Oz44Gu44K544K/44Kk44OrWy9qYV1cbiAqIEBtb2RpZmllciByb3dmb290ZXJcbiAqICAgW2VuXUhvcml6b250YWxseSBhbGlnbnMgdGhlIGZvb3RlciBidXR0b25zLlsvZW5dXG4gKiAgIFtqYV3jg5Xjg4Pjgr/jg7zjga7opIfmlbDjga7jg5zjgr/jg7PjgpLmsLTlubPjgavphY3nva5bL2phXVxuICogQHNlZWFsc28gb25zLWRpYWxvZ1xuICogICBbZW5db25zLWRpYWxvZyBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLWRpYWxvZ+OCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtcG9wb3ZlclxuICogICBbZW5db25zLXBvcG92ZXIgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1kaWFsb2fjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLm5vdGlmaWNhdGlvblxuICogICBbZW5dVXNpbmcgb25zLm5vdGlmaWNhdGlvbiB1dGlsaXR5IGZ1bmN0aW9ucy5bL2VuXVxuICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44KS6KGo56S644GZ44KL44Gr44Gv44CBb25zLm5vdGlmaWNhdGlvbuOCquODluOCuOOCp+OCr+ODiOOBruODoeOCveODg+ODieOCkuS9v+OBhuOBk+OBqOOCguOBp+OBjeOBvuOBmeOAglsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1hbGVydC1kaWFsb2cgaWQ9XCJhbGVydC1kaWFsb2dcIj5cbiAqICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZy10aXRsZVwiPldhcm5pbmchPC9kaXY+XG4gKiAgIDxkaXYgY2xhc3M9XCJhbGVydC1kaWFsb2ctY29udGVudFwiPlxuICogICAgIEFuIGVycm9yIGhhcyBvY2N1cnJlZCFcbiAqICAgPC9kaXY+XG4gKiAgIDxkaXYgY2xhc3M9XCJhbGVydC1kaWFsb2ctZm9vdGVyXCI+XG4gKiAgICAgPGJ1dHRvbiBpZD1cImFsZXJ0LWRpYWxvZy1idXR0b25cIiBjbGFzcz1cImFsZXJ0LWRpYWxvZy1idXR0b25cIj5PSzwvYnV0dG9uPlxuICogICA8L2Rpdj5cbiAqIDwvb25zLWFsZXJ0LWRpYWxvZz5cbiAqIDxzY3JpcHQ+XG4gKiAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhbGVydC1kaWFsb2cnKS5zaG93KCk7XG4gKiA8L3NjcmlwdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQWxlcnREaWFsb2dFbGVtZW50IGV4dGVuZHMgQmFzZURpYWxvZ0VsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlc2hvd1xuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQganVzdCBiZWZvcmUgdGhlIGFsZXJ0IGRpYWxvZyBpcyBkaXNwbGF5ZWQuWy9lbl1cbiAgICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44GM6KGo56S644GV44KM44KL55u05YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmFsZXJ0RGlhbG9nXG4gICAqICAgW2VuXUFsZXJ0IGRpYWxvZyBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUV4ZWN1dGUgdG8gc3RvcCB0aGUgZGlhbG9nIGZyb20gc2hvd2luZy5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7plqLmlbDjgpLlrp/ooYzjgZnjgovjgajjgIHjgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjga7ooajnpLrjgpLmraLjgoHjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHBvc3RzaG93XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGFmdGVyIHRoZSBhbGVydCBkaWFsb2cgaXMgZGlzcGxheWVkLlsvZW5dXG4gICAqICAgW2phXeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBjOihqOekuuOBleOCjOOBn+ebtOW+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5hbGVydERpYWxvZ1xuICAgKiAgIFtlbl1BbGVydCBkaWFsb2cgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlaGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQganVzdCBiZWZvcmUgdGhlIGFsZXJ0IGRpYWxvZyBpcyBoaWRkZW4uWy9lbl1cbiAgICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44GM6Zqg44KM44KL55u05YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmFsZXJ0RGlhbG9nXG4gICAqICAgW2VuXUFsZXJ0IGRpYWxvZyBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUV4ZWN1dGUgdG8gc3RvcCB0aGUgZGlhbG9nIGZyb20gaGlkaW5nLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWun+ihjOOBmeOCi+OBqOOAgeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBjOmWieOBmOOCiOOBhuOBqOOBmeOCi+OBruOCkuatouOCgeOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdGhpZGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFtlbl1GaXJlZCBqdXN0IGFmdGVyIHRoZSBhbGVydCBkaWFsb2cgaXMgaGlkZGVuLlsvZW5dXG4gICAqIFtqYV3jgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjgYzpmqDjgozjgZ/lvozjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuYWxlcnREaWFsb2dcbiAgICogICBbZW5dQWxlcnQgZGlhbG9nIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgZGlhbG9nLlsvZW5dXG4gICAqICBbamFd44OA44Kk44Ki44Ot44Kw44Gu6KaL44Gf55uu44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgY2FuY2VsYWJsZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGRpYWxvZyBjYW4gYmUgY2xvc2VkIGJ5IHRhcHBpbmcgdGhlIGJhY2tncm91bmQgb3IgYnkgcHJlc3NpbmcgdGhlIGJhY2sgYnV0dG9uIG9uIEFuZHJvaWQgZGV2aWNlcy5bL2VuXVxuICAgKiAgW2phXeOBk+OBruWxnuaAp+OCkuioreWumuOBmeOCi+OBqOOAgeODgOOCpOOCouODreOCsOOBruiDjOaZr+OCkuOCv+ODg+ODl+OBl+OBn+OCikFuZHJvaWTjg4fjg5DjgqTjgrnjga7jg5Djg4Pjgq/jg5zjgr/jg7PjgpLmirzjgZnjgajjg4DjgqTjgqLjg63jgrDjgYzplonjgZjjgovjgojjgYbjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXNhYmxlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGRpYWxvZyBpcyBkaXNhYmxlZC5bL2VuXVxuICAgKiAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+aZguOAgeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBr2Rpc2FibGVk54q25oWL44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGRlZmF1bHRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFuaW1hdGlvbiB1c2VkIHdoZW4gc2hvd2luZyBhbmQgaGlkaW5nIHRoZSBkaWFsb2cuIENhbiBiZSBlaXRoZXIgYFwibm9uZVwiYCBvciBgXCJkZWZhdWx0XCJgLlsvZW5dXG4gICAqICBbamFd44OA44Kk44Ki44Ot44Kw44KS6KGo56S644GZ44KL6Zqb44Gu44Ki44OL44Oh44O844K344On44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CC44OH44OV44Kp44Or44OI44Gn44GvXCJub25lXCLjgYtcImRlZmF1bHRcIuOBjOaMh+WumuOBp+OBjeOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGFuaW1hdGlvbi1vcHRpb25zXG4gICAqIEB0eXBlIHtFeHByZXNzaW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgdGltaW5nIGFuZCBkZWxheSB3aXRoIGFuIG9iamVjdCBsaXRlcmFsLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgdGltaW5nLCBkZWxheeOCkuOCquODluOCuOOCp+OCr+ODiOODquODhuODqeODq+OBp+aMh+WumuOBl+OBvuOBmeOAguS+i++8mntkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9Wy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbWFzay1jb2xvclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCByZ2JhKDAsIDAsIDAsIDAuMilcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dQ29sb3Igb2YgdGhlIGJhY2tncm91bmQgbWFzay4gRGVmYXVsdCBpcyBcInJnYmEoMCwgMCwgMCwgMC4yKVwiLlsvZW5dXG4gICAqICBbamFd6IOM5pmv44Gu44Oe44K544Kv44Gu6Imy44KS5oyH5a6a44GX44G+44GZ44CCXCJyZ2JhKDAsIDAsIDAsIDAuMilcIuOBjOODh+ODleOCqeODq+ODiOWApOOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fY29tcGlsZSgpKTtcbiAgfVxuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHJldHVybiBzY2hlbWU7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7RWxlbWVudH1cbiAgICovXG4gIGdldCBfbWFzaygpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJy5hbGVydC1kaWFsb2ctbWFzaycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0VsZW1lbnR9XG4gICAqL1xuICBnZXQgX2RpYWxvZygpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJy5hbGVydC1kaWFsb2cnKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0VsZW1lbnR9XG4gICAqL1xuICBnZXQgX3RpdGxlRWxlbWVudCgpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcy5fZGlhbG9nLmNoaWxkcmVuWzBdLCAnLmFsZXJ0LWRpYWxvZy10aXRsZScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0VsZW1lbnR9XG4gICAqL1xuICBnZXQgX2NvbnRlbnRFbGVtZW50KCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLl9kaWFsb2cuY2hpbGRyZW5bMF0sICcuYWxlcnQtZGlhbG9nLWNvbnRlbnQnKTtcbiAgfVxuXG4gIF91cGRhdGVBbmltYXRvckZhY3RvcnkoKSB7XG4gICAgcmV0dXJuIG5ldyBBbmltYXRvckZhY3Rvcnkoe1xuICAgICAgYW5pbWF0b3JzOiBfYW5pbWF0b3JEaWN0LFxuICAgICAgYmFzZUNsYXNzOiBBbGVydERpYWxvZ0FuaW1hdG9yLFxuICAgICAgYmFzZUNsYXNzTmFtZTogJ0FsZXJ0RGlhbG9nQW5pbWF0b3InLFxuICAgICAgZGVmYXVsdEFuaW1hdGlvbjogdGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpXG4gICAgfSk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICB0aGlzLnN0eWxlLnpJbmRleCA9IDEwMDAxO1xuXG4gICAgLyoqXG4gICAgICogRXhwZWN0ZWQgcmVzdWx0IGFmdGVyIGNvbXBpbGU6XG4gICAgICpcbiAgICAgKiA8b25zLWFsZXJ0LWRpYWxvZyBzdHlsZT1cIm5vbmVcIj5cbiAgICAgKiAgIDxkaXYgY2xhc3M9XCJhbGVydC1kaWFsb2ctbWFza1wiPjwvZGl2PlxuICAgICAqICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZ1wiPlxuICAgICAqICAgICA8ZGl2IGNsYXNzPVwiYWxlcnQtZGlhbG9nLWNvbnRhaW5lclwiPi4uLjwvZGl2PlxuICAgICAqICAgPC9kaXY+XG4gICAgICogPC9vbnMtYWxlcnQtZGlhbG9nPlxuICAgICAqL1xuXG4gICAgY29uc3QgY29udGVudCA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtcblxuICAgIGlmICghdGhpcy5fbWFzayAmJiAhdGhpcy5fZGlhbG9nKSB7XG4gICAgICB3aGlsZSAodGhpcy5maXJzdENoaWxkKSB7XG4gICAgICAgIGNvbnRlbnQuYXBwZW5kQ2hpbGQodGhpcy5maXJzdENoaWxkKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuX21hc2spIHtcbiAgICAgIGNvbnN0IG1hc2sgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIG1hc2suY2xhc3NMaXN0LmFkZCgnYWxlcnQtZGlhbG9nLW1hc2snKTtcbiAgICAgIHRoaXMuaW5zZXJ0QmVmb3JlKG1hc2ssIHRoaXMuY2hpbGRyZW5bMF0pO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5fZGlhbG9nKSB7XG4gICAgICBjb25zdCBkaWFsb2cgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIGRpYWxvZy5jbGFzc0xpc3QuYWRkKCdhbGVydC1kaWFsb2cnKTtcbiAgICAgIHRoaXMuaW5zZXJ0QmVmb3JlKGRpYWxvZywgbnVsbCk7XG4gICAgfVxuXG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZCh0aGlzLl9kaWFsb2csICcuYWxlcnQtZGlhbG9nLWNvbnRhaW5lcicpKSB7XG4gICAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIGNvbnRhaW5lci5jbGFzc0xpc3QuYWRkKCdhbGVydC1kaWFsb2ctY29udGFpbmVyJyk7XG4gICAgICB0aGlzLl9kaWFsb2cuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcbiAgICB9XG5cbiAgICB0aGlzLl9kaWFsb2cuY2hpbGRyZW5bMF0uYXBwZW5kQ2hpbGQoY29udGVudCk7XG5cbiAgICB0aGlzLl9kaWFsb2cuc3R5bGUuekluZGV4ID0gMjAwMDE7XG4gICAgdGhpcy5fbWFzay5zdHlsZS56SW5kZXggPSAyMDAwMDtcblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgdGhpcy5fc2NoZW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGNhbmNlbGFibGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBkaWFsb2cgaXMgY2FuY2VsYWJsZSBvciBub3QuIEEgY2FuY2VsYWJsZSBkaWFsb2cgY2FuIGJlIGNsb3NlZCBieSB0YXBwaW5nIHRoZSBiYWNrZ3JvdW5kIG9yIGJ5IHByZXNzaW5nIHRoZSBiYWNrIGJ1dHRvbiBvbiBBbmRyb2lkIGRldmljZXMuWy9lbl1cbiAgICogICBbamFd44Gd44Gu44OA44Kk44Ki44Ot44Kw44GM44Kt44Oj44Oz44K744Or5Y+v6IO944GL44Gp44GG44GL44KS6KGo44GX44G+44GZ44CC44Kt44Oj44Oz44K744Or5Y+v6IO944Gq44OA44Kk44Ki44Ot44Kw44Gv44CB6IOM5pmv44KS44K/44OD44OX44GZ44KL44GLQW5kcm9pZOODh+ODkOOCpOOCueOBruODkOODg+OCr+ODnOOCv+ODs+OCkuaKvOOBmeOBk+OBqOOBp+mWieOBmOOCi+OBk+OBqOOBjOWHuuadpeOCi+OCiOOBhuOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHNob3dcbiAgICogQHNpZ25hdHVyZSBzaG93KFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUFuaW1hdGlvbiBuYW1lLiBBdmFpbGFibGUgYW5pbWF0aW9ucyBhcmUgYFwiZmFkZVwiYCBhbmQgYFwibm9uZVwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgILmjIflrprjgafjgY3jgovjga7jga/jgIFcImZhZGVcIiwgXCJub25lXCLjga7jgYTjgZrjgozjgYvjgafjgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gPGNvZGU+e2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfTwvY29kZT4gWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXUZ1bmN0aW9uIHRvIGV4ZWN1dGUgYWZ0ZXIgdGhlIGRpYWxvZyBoYXMgYmVlbiByZXZlYWxlZC5bL2VuXVxuICAgKiAgIFtqYV3jg4DjgqTjgqLjg63jgrDjgYzooajnpLrjgZXjgozntYLjgo/jgaPjgZ/mmYLjgavlkbzjgbPlh7rjgZXjgozjgovjgrPjg7zjg6vjg5Djg4Pjgq/jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyB0aGUgYWxlcnQgZGlhbG9nLlsvZW5dXG4gICAqICAgW2phXeODgOOCpOOCouODreOCsOOCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXUEgYFByb21pc2VgIG9iamVjdCB0aGF0IHJlc29sdmVzIHRvIHRoZSBkaXNwbGF5ZWQgZWxlbWVudC5bL2VuXVxuICAgKiAgIFtqYV3ooajnpLrjgZXjgozjgovopoHntKDjgpLop6PmsbrjgZnjgotgUHJvbWlzZWDjgqrjg5bjgrjjgqfjgq/jg4jjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQG1ldGhvZCBoaWRlXG4gICAqIEBzaWduYXR1cmUgaGlkZShbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcImZhZGVcImAgYW5kIGBcIm5vbmVcImAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCXCJmYWRlXCIsIFwibm9uZVwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuICA8Y29kZT57ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9PC9jb2RlPlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiA8Y29kZT57ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9PC9jb2RlPiBbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogICBbZW5dRnVuY3Rpb24gdG8gZXhlY3V0ZSBhZnRlciB0aGUgZGlhbG9nIGhhcyBiZWVuIGhpZGRlbi5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jg4DjgqTjgqLjg63jgrDjgYzplonjgZjjgZ/mmYLjgavlkbzjgbPlh7rjgZXjgozjgovjgrPjg7zjg6vjg5Djg4Pjgq/jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSGlkZSB0aGUgYWxlcnQgZGlhbG9nLlsvZW5dXG4gICAqICAgW2phXeODgOOCpOOCouODreOCsOOCkumWieOBmOOBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVJlc29sdmVzIHRvIHRoZSBoaWRkZW4gZWxlbWVudFsvZW5dXG4gICAqICAgW2phXemaoOOCjOOBn+imgee0oOOCkuino+axuuOBmeOCi2BQcm9taXNlYOOCquODluOCuOOCp+OCr+ODiOOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdmlzaWJsZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBkaWFsb2cgaXMgdmlzaWJsZSBvciBub3QuWy9lbl1cbiAgICogICBbamFd6KaB57Sg44GM6KaL44GI44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvbkRldmljZUJhY2tCdXR0b25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUJhY2stYnV0dG9uIGhhbmRsZXIuWy9lbl1cbiAgICogICBbamFd44OQ44OD44Kv44Oc44K/44Oz44OP44Oz44OJ44Op44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7RGlhbG9nQW5pbWF0b3J9IEFuaW1hdG9yXG4gICAqL1xuICBzdGF0aWMgcmVnaXN0ZXJBbmltYXRvcihuYW1lLCBBbmltYXRvcikge1xuICAgIGlmICghKEFuaW1hdG9yLnByb3RvdHlwZSBpbnN0YW5jZW9mIEFsZXJ0RGlhbG9nQW5pbWF0b3IpKSB7XG4gICAgICB1dGlsLnRocm93QW5pbWF0b3IoJ0FsZXJ0RGlhbG9nJyk7XG4gICAgfVxuICAgIF9hbmltYXRvckRpY3RbbmFtZV0gPSBBbmltYXRvcjtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgYW5pbWF0b3JzKCkge1xuICAgIHJldHVybiBfYW5pbWF0b3JEaWN0O1xuICB9XG5cbiAgc3RhdGljIGdldCBBbGVydERpYWxvZ0FuaW1hdG9yKCkge1xuICAgIHJldHVybiBBbGVydERpYWxvZ0FuaW1hdG9yO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLkFsZXJ0RGlhbG9nID0gQWxlcnREaWFsb2dFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtYWxlcnQtZGlhbG9nJywgQWxlcnREaWFsb2dFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IEJhc2VCdXR0b25FbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWJ1dHRvbic7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWFsZXJ0LWRpYWxvZy1idXR0b25cbiAqIEBtb2RpZmllciBtYXRlcmlhbFxuICogICBbZW5dTWF0ZXJpYWwgRGVzaWduIGFsZXJ0LWRpYWxvZyBidXR0b24uWy9lbl1cbiAqICAgW2phXeODnuODhuODquOCouODq+ODh+OCtuOCpOODs+OBruODnOOCv+ODs+OCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLWFsZXJ0LWRpYWxvZ1xuICogICBbZW5dVGhlIGA8b25zLWFsZXJ0LWRpYWxvZz5gIGNvbXBvbmVudCBkaXNwbGF5cyBhIGFsZXJ0IGRpYWxvZy5bL2VuXVxuICogICBbamFdb25zLWFsZXJ0LWRpYWxvZ+OCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogIDxvbnMtYWxlcnQtZGlhbG9nPlxuICogICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZy10aXRsZVwiPldhcm5pbmchPC9kaXY+XG4gKiAgICA8ZGl2IGNsYXNzPVwiYWxlcnQtZGlhbG9nLWNvbnRlbnRcIj5cbiAqICAgICAgQW4gZXJyb3IgaGFzIG9jY3VycmVkIVxuICogICAgPC9kaXY+XG4gKiAgICA8ZGl2IGNsYXNzPVwiYWxlcnQtZGlhbG9nLWZvb3RlclwiPlxuICogICAgICA8YWxlcnQtZGlhbG9nLWJ1dHRvbiBvbmNsaWNrPVwiYXBwLmNsb3NlKClcIj5DYW5jZWw8L2FsZXJ0LWRpYWxvZy1idXR0b24+XG4gKiAgICAgIDxhbGVydC1kaWFsb2ctYnV0dG9uIGNsYXNzPVwiYWxlcnQtZGlhbG9nLWJ1dHRvblwiIG9uY2xpY2s9XCJhcHAuY2xvc2UoKVwiPk9LPC9hbGVydC1kaWFsb2ctYnV0dG9uPlxuICogICAgPC9kaXY+XG4gKiAgPC9vbnMtYWxlcnQtZGlhbG9nPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBbGVydERpYWxvZ0J1dHRvbkVsZW1lbnQgZXh0ZW5kcyBCYXNlQnV0dG9uRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBidXR0b24uWy9lbl1cbiAgICogICBbamFd44Oc44K/44Oz44Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZGlzYWJsZWRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgaWYgYnV0dG9uIHNob3VsZCBiZSBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3jg5zjgr/jg7PjgpLnhKHlirnljJbjgZnjgovloLTlkIjjga/mjIflrprjgZfjgabjgY/jgaDjgZXjgYTjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZWxlbWVudCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgcmV0dXJuIHsgJyc6ICdhbGVydC1kaWFsb2ctYnV0dG9uLS0qJyB9O1xuICB9XG5cbiAgZ2V0IF9kZWZhdWx0Q2xhc3NOYW1lKCkge1xuICAgIHJldHVybiAnYWxlcnQtZGlhbG9nLWJ1dHRvbic7XG4gIH1cblxuICBnZXQgX3JpcHBsZU9wdCgpIHtcbiAgICByZXR1cm4gW3RoaXMsIHVuZGVmaW5lZCwgeyAnbW9kaWZpZXInOiAnbGlnaHQtZ3JheScgfV07XG4gIH1cbn1cblxub25zRWxlbWVudHMuQWxlcnREaWFsb2dCdXR0b24gPSBBbGVydERpYWxvZ0J1dHRvbkVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1hbGVydC1kaWFsb2ctYnV0dG9uJywgQWxlcnREaWFsb2dCdXR0b25FbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5pbXBvcnQgaW9zQmFja0J1dHRvbkljb24gZnJvbSAnLi4vLi4vaW1hZ2VzL2lvcy1iYWNrLWJ1dHRvbi1pY29uLnN2Zyc7XG5pbXBvcnQgbWRCYWNrQnV0dG9uSWNvbiBmcm9tICcuLi8uLi9pbWFnZXMvbWQtYmFjay1idXR0b24taWNvbi5zdmcnO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ2JhY2stYnV0dG9uJztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ2JhY2stYnV0dG9uLS0qJyxcbiAgJy5iYWNrLWJ1dHRvbl9faWNvbic6ICdiYWNrLWJ1dHRvbi0tKl9faWNvbicsXG4gICcuYmFjay1idXR0b25fX2xhYmVsJzogJ2JhY2stYnV0dG9uLS0qX19sYWJlbCdcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWJhY2stYnV0dG9uXG4gKiBAY2F0ZWdvcnkgbmF2aWdhdGlvblxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBCYWNrIGJ1dHRvbiBjb21wb25lbnQgZm9yIGA8b25zLXRvb2xiYXI+YC4gUHV0IGl0IGluIHRoZSBsZWZ0IHBhcnQgb2YgdGhlIGA8b25zLXRvb2xiYXI+YC5cbiAqXG4gKiAgICAgSXQgd2lsbCBmaW5kIHRoZSBwYXJlbnQgYDxvbnMtbmF2aWdhdG9yPmAgZWxlbWVudCBhbmQgcG9wIGEgcGFnZSB3aGVuIGNsaWNrZWQuIFRoaXMgYmVoYXZpb3IgY2FuIGJlIG92ZXJyaWRlbiBieSBzcGVjaWZ5aW5nIHRoZSBgb25DbGlja2AgcHJvcGVydHkuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGNvZGVwZW4gYUhtR0xcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9iYWNrLWJ1dHRvblxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1NYXRlcmlhbCBEZXNpZ24gc3R5bGVbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy10b29sYmFyXG4gKiAgIFtlbl1vbnMtdG9vbGJhciBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLXRvb2xiYXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLW5hdmlnYXRvclxuICogICBbZW5db25zLW5hdmlnYXRvciBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLW5hdmlnYXRvcuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy10b29sYmFyPlxuICogICA8ZGl2IGNsYXNzPVwibGVmdFwiPlxuICogICAgIDxvbnMtYmFjay1idXR0b24+QmFjazwvb25zLWJhY2stYnV0dG9uPlxuICogICA8L2Rpdj5cbiAqICAgPGRpdiBjbGFzcz1cImNlbnRlclwiPlxuICogICAgIFRpdGxlXG4gKiAgIDxkaXY+XG4gKiA8L29ucy10b29sYmFyPlxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJhY2tCdXR0b25FbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgYmFjayBidXR0b24uWy9lbl1cbiAgICogIFtqYV3jg5Djg4Pjgq/jg5zjgr/jg7Pjga7opovjgZ/nm67jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2NvbXBpbGUoKTtcbiAgICB9KTtcblxuICAgIHRoaXMuX29wdGlvbnMgPSB7fTtcbiAgICB0aGlzLl9ib3VuZE9uQ2xpY2sgPSB0aGlzLl9vbkNsaWNrLmJpbmQodGhpcyk7XG4gIH1cblxuICBfdXBkYXRlSWNvbihpY29uID0gdXRpbC5maW5kQ2hpbGQodGhpcywgJy5iYWNrLWJ1dHRvbl9faWNvbicpKSB7XG4gICAgaWNvbi5pbm5lckhUTUwgPSBhdXRvU3R5bGUuZ2V0UGxhdGZvcm0odGhpcykgPT09ICdhbmRyb2lkJyB8fCB1dGlsLmhhc01vZGlmaWVyKHRoaXMsICdtYXRlcmlhbCcpID8gbWRCYWNrQnV0dG9uSWNvbiA6IGlvc0JhY2tCdXR0b25JY29uO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG5cbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG5cbiAgICBpZiAoIXV0aWwuZmluZENoaWxkKHRoaXMsICcuYmFjay1idXR0b25fX2xhYmVsJykpIHtcbiAgICAgIGNvbnN0IGxhYmVsID0gdXRpbC5jcmVhdGUoJ3NwYW4uYmFjay1idXR0b25fX2xhYmVsJyk7XG5cbiAgICAgIHdoaWxlICh0aGlzLmNoaWxkTm9kZXNbMF0pIHtcbiAgICAgICAgbGFiZWwuYXBwZW5kQ2hpbGQodGhpcy5jaGlsZE5vZGVzWzBdKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuYXBwZW5kQ2hpbGQobGFiZWwpO1xuICAgIH1cblxuICAgIGlmICghdXRpbC5maW5kQ2hpbGQodGhpcywgJy5iYWNrLWJ1dHRvbl9faWNvbicpKSB7XG4gICAgICBjb25zdCBpY29uID0gdXRpbC5jcmVhdGUoJ3NwYW4uYmFjay1idXR0b25fX2ljb24nKTtcbiAgICAgIHRoaXMuX3VwZGF0ZUljb24oaWNvbik7XG5cbiAgICAgIHRoaXMuaW5zZXJ0QmVmb3JlKGljb24sIHRoaXMuY2hpbGRyZW5bMF0pO1xuICAgIH1cblxuICAgIHV0aWwudXBkYXRlUmlwcGxlKHRoaXMsIHVuZGVmaW5lZCwge2NlbnRlcjogJycsICdzaXplJzogJ2NvbnRhaW4nLCAnYmFja2dyb3VuZCc6ICd0cmFuc3BhcmVudCd9KTtcblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb3B0aW9uc1xuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dT3B0aW9ucyBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvcHRpb25zLmFuaW1hdGlvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBcInNsaWRlXCIsIFwibGlmdFwiLCBcImZhZGVcIiBhbmQgXCJub25lXCIuXG4gICAqICAgICBUaGVzZSBhcmUgcGxhdGZvcm0gYmFzZWQgYW5pbWF0aW9ucy4gRm9yIGZpeGVkIGFuaW1hdGlvbnMsIGFkZCBcIi1pb3NcIiBvciBcIi1tZFwiXG4gICAqICAgICBzdWZmaXggdG8gdGhlIGFuaW1hdGlvbiBuYW1lLiBFLmcuIFwibGlmdC1pb3NcIiwgXCJsaWZ0LW1kXCIuIERlZmF1bHRzIHZhbHVlcyBhcmUgXCJzbGlkZS1pb3NcIiBhbmQgXCJmYWRlLW1kXCIuXG4gICAqICAgWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuICBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWBbL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gIFsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb3B0aW9ucy5jYWxsYmFja1xuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgd2hlbiB0aGUgdHJhbnNpdGlvbiBoYXMgZW5kZWQuWy9lbl1cbiAgICogICBbamFd44GT44Gu44Oh44K944OD44OJ44Gr44KI44KL55S76Z2i6YG356e744GM57WC5LqG44GX44Gf6Zqb44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgZ2V0IG9wdGlvbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX29wdGlvbnM7XG4gIH1cblxuICBzZXQgb3B0aW9ucyhvYmplY3QpIHtcbiAgICB0aGlzLl9vcHRpb25zID0gb2JqZWN0O1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvbkNsaWNrXG4gICAqIEB0eXBlIHtGdW5jdGlvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVVzZWQgdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgYmFjayBidXR0b24gYmVoYXZpb3IuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIF9vbkNsaWNrKCkge1xuICAgIGlmICh0aGlzLm9uQ2xpY2spIHtcbiAgICAgIHRoaXMub25DbGljay5hcHBseSh0aGlzKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICBjb25zdCBuYXZpZ2F0b3IgPSB1dGlsLmZpbmRQYXJlbnQodGhpcywgJ29ucy1uYXZpZ2F0b3InKTtcbiAgICAgIGlmIChuYXZpZ2F0b3IpIHtcbiAgICAgICAgbmF2aWdhdG9yLnBvcFBhZ2UodGhpcy5vcHRpb25zKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5fYm91bmRPbkNsaWNrLCBmYWxzZSk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllcicsICdjbGFzcyddO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBzd2l0Y2ggKG5hbWUpIHtcbiAgICAgIGNhc2UgJ2NsYXNzJzpcbiAgICAgICAgdXRpbC5yZXN0b3JlQ2xhc3ModGhpcywgZGVmYXVsdENsYXNzTmFtZSwgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ21vZGlmaWVyJzoge1xuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKSAmJiB0aGlzLl91cGRhdGVJY29uKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9ib3VuZE9uQ2xpY2ssIGZhbHNlKTtcbiAgfVxuXG4gIHNob3coKSB7XG4gICAgdGhpcy5zdHlsZS5kaXNwbGF5ID0gJ2lubGluZS1ibG9jayc7XG4gIH1cblxuICBoaWRlKCkge1xuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgfVxufVxuXG5vbnNFbGVtZW50cy5CYWNrQnV0dG9uID0gQmFja0J1dHRvbkVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1iYWNrLWJ1dHRvbicsIEJhY2tCdXR0b25FbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ2JvdHRvbS1iYXInO1xuY29uc3Qgc2NoZW1lID0geycnOiAnYm90dG9tLWJhci0tKid9O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1ib3R0b20tdG9vbGJhclxuICogQGNhdGVnb3J5IHBhZ2VcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dVG9vbGJhciBjb21wb25lbnQgdGhhdCBpcyBwb3NpdGlvbmVkIGF0IHRoZSBib3R0b20gb2YgdGhlIHBhZ2UuIFNpbmNlIGJvdHRvbSB0b29sYmFycyBhcmUgdmVyeSB2ZXJzYXRpbGUgZWxlbWVudHMsIGBvbnMtYm90dG9tLXRvb2xiYXJgIGRvZXMgbm90IHByb3ZpZGUgYW55IHNwZWNpZmljIGxheW91dCBzeW50YXggZm9yIGl0cyBjaGlsZHJlbi4gTW9kaWZpZXJzIG9yIGN1c3RvbSBDU1MgbXVzdCBiZSB1c2VkLlsvZW5dXG4gKiAgIFtqYV3jg5rjg7zjgrjkuIvpg6jjgavphY3nva7jgZXjgozjgovjg4Tjg7zjg6vjg5Djg7znlKjjgrPjg7Pjg53jg7zjg43jg7Pjg4jjgafjgZnjgIJbL2phXVxuICogQG1vZGlmaWVyIHRyYW5zcGFyZW50XG4gKiAgIFtlbl1NYWtlIHRoZSB0b29sYmFyIHRyYW5zcGFyZW50LlsvZW5dXG4gKiAgIFtqYV3jg4Tjg7zjg6vjg5Djg7zjga7og4zmma/jgpLpgI/mmI7jgavjgZfjgabooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQG1vZGlmaWVyIGFsaWduZWRcbiAqICAgW2VuXVZlcnRpY2FsbHkgYWxpZ25zIGl0cyBjaGlsZHJlbiBhbmQgYXBwbGllcyBmbGV4Ym94IGZvciBibG9jayBlbGVtZW50cy4gYGp1c3RpZnktY29udGVudGAgQ1NTIHJ1bGUgY2FuIGJlIHVzZWQgdG8gY2hhbmdlIGhvcml6b250YWwgYWxpZ24uWy9lbl1cbiAqICAgW2phXeODhOODvOODq+ODkOODvOOBruiDjOaZr+OCkumAj+aYjuOBq+OBl+OBpuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAc2VlYWxzbyBvbnMtdG9vbGJhciBbZW5db25zLXRvb2xiYXIgY29tcG9uZW50Wy9lbl1bamFdb25zLXRvb2xiYXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtYm90dG9tLXRvb2xiYXI+XG4gKiAgIENvbnRlbnRcbiAqIDwvb25zLWJvdHRvbS10b29sYmFyPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCb3R0b21Ub29sYmFyRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSB0b29sYmFyLlsvZW5dXG4gICAqICAgW2phXeODhOODvOODq+ODkOODvOOBruimi+OBn+ebruOBruihqOePvuOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbn1cblxub25zRWxlbWVudHMuQm90dG9tVG9vbGJhciA9IEJvdHRvbVRvb2xiYXJFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtYm90dG9tLXRvb2xiYXInLCBCb3R0b21Ub29sYmFyRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCBCYXNlQnV0dG9uRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1idXR0b24nO1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1idXR0b25cbiAqIEBjYXRlZ29yeSBmb3JtXG4gKiBAbW9kaWZpZXIgb3V0bGluZVxuICogICBbZW5dQnV0dG9uIHdpdGggb3V0bGluZSBhbmQgdHJhbnNwYXJlbnQgYmFja2dyb3VuZFsvZW5dXG4gKiAgIFtqYV3jgqLjgqbjg4jjg6njgqTjg7PjgpLmjIHjgaPjgZ/jg5zjgr/jg7PjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQG1vZGlmaWVyIGxpZ2h0XG4gKiAgIFtlbl1CdXR0b24gdGhhdCBkb2Vzbid0IHN0YW5kIG91dC5bL2VuXVxuICogICBbamFd55uu56uL44Gf44Gq44GE44Oc44K/44Oz44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBtb2RpZmllciBxdWlldFxuICogICBbZW5dQnV0dG9uIHdpdGggbm8gb3V0bGluZSBhbmQgb3IgYmFja2dyb3VuZC4uWy9lbl1cbiAqICAgW2phXeaeoOe3muOChOiDjOaZr+OBjOeEoeOBhOaWh+Wtl+OBoOOBkeOBruODnOOCv+ODs+OCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAbW9kaWZpZXIgY3RhXG4gKiAgIFtlbl1CdXR0b24gdGhhdCByZWFsbHkgc3RhbmRzIG91dC5bL2VuXVxuICogICBbamFd55uu56uL44Gk44Oc44K/44Oz44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBtb2RpZmllciBsYXJnZVxuICogICBbZW5dTGFyZ2UgYnV0dG9uIHRoYXQgY292ZXJzIHRoZSB3aWR0aCBvZiB0aGUgc2NyZWVuLlsvZW5dXG4gKiAgIFtqYV3mqKrjgYTjgaPjgbHjgYTjgavluoPjgYzjgovlpKfjgY3jgarjg5zjgr/jg7PjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQG1vZGlmaWVyIGxhcmdlLS1xdWlldFxuICogICBbZW5dTGFyZ2UgcXVpZXQgYnV0dG9uLlsvZW5dXG4gKiAgIFtqYV3mqKrjgYTjgaPjgbHjgYTjgavluoPjgYzjgotxdWlldOODnOOCv+ODs+OCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAbW9kaWZpZXIgbGFyZ2UtLWN0YVxuICogICBbZW5dTGFyZ2UgY2FsbCB0byBhY3Rpb24gYnV0dG9uLlsvZW5dXG4gKiAgIFtqYV3mqKrjgYTjgaPjgbHjgYTjgavluoPjgYzjgotjdGHjg5zjgr/jg7PjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1NYXRlcmlhbCBEZXNpZ24gYnV0dG9uWy9lbl1cbiAqICAgW2phXeODnuODhuODquOCouODq+ODh+OCtuOCpOODs+OBruODnOOCv+ODs1svamFdXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWwtLWZsYXRcbiAqICAgW2VuXU1hdGVyaWFsIERlc2lnbiBmbGF0IGJ1dHRvblsvZW5dXG4gKiAgIFtqYV3jg57jg4bjg6rjgqLjg6vjg4fjgrbjgqTjg7Pjga7jg5Xjg6njg4Pjg4jjg5zjgr/jg7NbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBCdXR0b24gY29tcG9uZW50LiBJZiB5b3Ugd2FudCB0byBwbGFjZSBhIGJ1dHRvbiBpbiBhIHRvb2xiYXIsIHVzZSBgPG9ucy10b29sYmFyLWJ1dHRvbj5gIG9yIGA8b25zLWJhY2stYnV0dG9uPmAgaW5zdGVhZC5cbiAqXG4gKiAgICAgV2lsbCBhdXRvbWF0aWNhbGx5IGRpc3BsYXkgYXMgYSBNYXRlcmlhbCBEZXNpZ24gYnV0dG9uIHdpdGggYSByaXBwbGUgZWZmZWN0IG9uIEFuZHJvaWQuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV3jg5zjgr/jg7PnlKjjgrPjg7Pjg53jg7zjg43jg7Pjg4jjgILjg4Tjg7zjg6vjg5Djg7zjgavjg5zjgr/jg7PjgpLoqK3nva7jgZnjgovloLTlkIjjga/jgIFvbnMtdG9vbGJhci1idXR0b27jgoLjgZfjgY/jga9vbnMtYmFjay1idXR0b27jgrPjg7Pjg53jg7zjg43jg7Pjg4jjgpLkvb/nlKjjgZfjgb7jgZnjgIJbL2phXVxuICogQGNvZGVwZW4gaExheXhcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9idXR0b25cbiAqIEBndWlkZSB0aGVtaW5nLmh0bWwjbW9kaWZpZXJzIFtlbl1Nb3JlIGRldGFpbHMgYWJvdXQgdGhlIGBtb2RpZmllcmAgYXR0cmlidXRlWy9lbl1bamFdbW9kaWZpZXLlsZ7mgKfjga7kvb/jgYTmlrlbL2phXVxuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNjcm9zcy1wbGF0Zm9ybS1zdHlsaW5nLWF1dG9zdHlsaW5nIFtlbl1JbmZvcm1hdGlvbiBhYm91dCBjcm9zcyBwbGF0Zm9ybSBzdHlsaW5nWy9lbl1bamFdSW5mb3JtYXRpb24gYWJvdXQgY3Jvc3MgcGxhdGZvcm0gc3R5bGluZ1svamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1idXR0b24gbW9kaWZpZXI9XCJsYXJnZS0tY3RhXCI+XG4gKiAgIFRhcCBNZVxuICogPC9vbnMtYnV0dG9uPlxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJ1dHRvbkVsZW1lbnQgZXh0ZW5kcyBCYXNlQnV0dG9uRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIGJ1dHRvbi5bL2VuXVxuICAgKiAgW2phXeODnOOCv+ODs+OBruihqOePvuOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHJpcHBsZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBkZWZpbmVkLCB0aGUgYnV0dG9uIHdpbGwgaGF2ZSBhIHJpcHBsZSBlZmZlY3QuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXNhYmxlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU3BlY2lmeSBpZiBidXR0b24gc2hvdWxkIGJlIGRpc2FibGVkLlsvZW5dXG4gICAqICAgW2phXeODnOOCv+ODs+OCkueEoeWKueWMluOBmeOCi+WgtOWQiOOBr+aMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBidXR0b24gaXMgZGlzYWJsZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeeEoeWKueWMluOBleOCjOOBpuOBhOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHJldHVybiB7ICcnOiAnYnV0dG9uLS0qJyB9O1xuICB9XG5cbiAgZ2V0IF9kZWZhdWx0Q2xhc3NOYW1lKCkge1xuICAgIHJldHVybiAnYnV0dG9uJztcbiAgfVxufVxuXG5vbnNFbGVtZW50cy5CdXR0b24gPSBCdXR0b25FbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtYnV0dG9uJywgQnV0dG9uRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ2NhcmQnO1xuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ2NhcmQtLSonLFxuICAnLmNhcmRfX3RpdGxlJzogJ2NhcmQtLSpfX3RpdGxlJyxcbiAgJy5jYXJkX19jb250ZW50JzogJ2NhcmQtLSpfX2NvbnRlbnQnXG59O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1jYXJkXG4gKiBAY2F0ZWdvcnkgdmlzdWFsXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXUEgY2FyZCB3aXRoIG1hdGVyaWFsIGRlc2lnbi5bL2VuXVxuICogICBbamFd44Oq44K544OI44Gu5LiK5LiL44Gu44Oc44O844OA44O844GM54Sh44GE44Oq44K544OI44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICBDb21wb25lbnQgdG8gY3JlYXRlIGEgY2FyZCB0aGF0IGRpc3BsYXlzIHNvbWUgaW5mb3JtYXRpb24uXG4gKlxuICogICAgVGhlIGNhcmQgbWF5IGJlIGNvbXBvc2VkIGJ5IGRpdnMgd2l0aCBzcGVjaWFsbHkgcHJlcGFyZWQgY2xhc3NlcyBgdGl0bGVgIGFuZC9vciBgY29udGVudGAuIFlvdSBjYW4gYWxzbyBhZGQgeW91ciBvd24gY29udGVudCBhcyB5b3UgcGxlYXNlLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2NhcmRcbiAqIEBleGFtcGxlXG4gKiA8b25zLWNhcmQ+XG4gKiAgIDxwPlNvbWUgY29udGVudDwvcD5cbiAqIDwvb25zLWNhcmQ+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENhcmRFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgY2FyZC5bL2VuXVxuICAgKiAgIFtqYV3jg6rjgrnjg4jjga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2NvbXBpbGUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIGxldCB0aXRsZSwgY29udGVudDtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgZWwgPSB0aGlzLmNoaWxkcmVuW2ldO1xuXG4gICAgICBpZiAoZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCd0aXRsZScpKSB7XG4gICAgICAgIGVsLmNsYXNzTGlzdC5hZGQoJ2NhcmRfX3RpdGxlJyk7XG4gICAgICAgIHRpdGxlID0gZWw7XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChlbC5jbGFzc0xpc3QuY29udGFpbnMoJ2NvbnRlbnQnKSkge1xuICAgICAgICBlbC5jbGFzc0xpc3QuYWRkKCdjYXJkX19jb250ZW50Jyk7XG4gICAgICAgIGNvbnRlbnQgPSBlbDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG59XG5cbm9uc0VsZW1lbnRzLkNhcmQgPSBDYXJkRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWNhcmQnLCBDYXJkRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuY29uc3Qgc2NoZW1lID0geycnOiAnY2Fyb3VzZWwtaXRlbS0tKid9O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1jYXJvdXNlbC1pdGVtXG4gKiBAY2F0ZWdvcnkgY2Fyb3VzZWxcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgQ2Fyb3VzZWwgaXRlbSBjb21wb25lbnQuIFVzZWQgYXMgYSBjaGlsZCBvZiB0aGUgYDxvbnMtY2Fyb3VzZWw+YCBlbGVtZW50LlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIHhiYnpPUVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2Nhcm91c2VsXG4gKiBAc2VlYWxzbyBvbnMtY2Fyb3VzZWxcbiAqICAgW2VuXWA8b25zLWNhcm91c2VsPmAgY29tcG9uZW50c1svZW5dXG4gKiAgIFtqYV08b25zLWNhcm91c2VsPuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1jYXJvdXNlbCBzdHlsZT1cIndpZHRoOiAxMDAlOyBoZWlnaHQ6IDIwMHB4XCI+XG4gKiAgIDxvbnMtY2Fyb3VzZWwtaXRlbT5cbiAqICAgIC4uLlxuICogICA8L29ucy1jYXJvdXNlbC1pdGVtPlxuICogICA8b25zLWNhcm91c2VsLWl0ZW0+XG4gKiAgICAuLi5cbiAqICAgPC9vbnMtY2Fyb3VzZWwtaXRlbT5cbiAqIDwvb25zLWNhcm91c2VsPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDYXJvdXNlbEl0ZW1FbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLnN0eWxlLndpZHRoID0gJzEwMCUnO1xuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJ11cbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdtb2RpZmllcicpIHtcbiAgICAgIHJldHVybiBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICB9XG4gIH1cbn1cblxub25zRWxlbWVudHMuQ2Fyb3VzZWxJdGVtID0gQ2Fyb3VzZWxJdGVtRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWNhcm91c2VsLWl0ZW0nLCBDYXJvdXNlbEl0ZW1FbGVtZW50KTtcbiIsImltcG9ydCB1dGlsIGZyb20gJy4uL3V0aWwnO1xuaW1wb3J0IHBsYXRmb3JtIGZyb20gJy4uL3BsYXRmb3JtJztcbmltcG9ydCBhbmltaXQgZnJvbSAnLi4vYW5pbWl0JztcbmltcG9ydCBHZXN0dXJlRGV0ZWN0b3IgZnJvbSAnLi4vZ2VzdHVyZS1kZXRlY3Rvcic7XG5cbmNvbnN0IGRpcmVjdGlvbk1hcCA9IHtcbiAgdmVydGljYWw6IHtcbiAgICBheGlzOiAnWScsXG4gICAgc2l6ZTogJ0hlaWdodCcsXG4gICAgZGlyOiBbJ3VwJywgJ2Rvd24nXSxcbiAgICB0M2Q6IFsnMHB4LCAnLCAncHgsIDBweCddXG4gIH0sXG4gIGhvcml6b250YWw6IHtcbiAgICBheGlzOiAnWCcsXG4gICAgc2l6ZTogJ1dpZHRoJyxcbiAgICBkaXI6IFsnbGVmdCcsICdyaWdodCddLFxuICAgIHQzZDogWycnLCAncHgsIDBweCwgMHB4J11cbiAgfVxufTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3dpcGVyIHtcbiAgY29uc3RydWN0b3IocGFyYW1zKSB7XG4gICAgLy8gUGFyYW1ldGVyc1xuICAgIGNvbnN0IEZBTFNFID0gKCgpID0+IGZhbHNlKTtcbiAgICBgZ2V0SW5pdGlhbEluZGV4IGdldEJ1YmJsZVdpZHRoIGlzVmVydGljYWwgaXNPdmVyU2Nyb2xsYWJsZSBpc0NlbnRlcmVkXG4gICAgaXNBdXRvU2Nyb2xsYWJsZSByZWZyZXNoSG9vayBwcmVDaGFuZ2VIb29rIHBvc3RDaGFuZ2VIb29rIG92ZXJTY3JvbGxIb29rYFxuICAgICAgLnNwbGl0KC9cXHMrLylcbiAgICAgIC5mb3JFYWNoKGtleSA9PiB0aGlzW2tleV0gPSBwYXJhbXNba2V5XSB8fCBGQUxTRSk7XG5cbiAgICB0aGlzLmdldEVsZW1lbnQgPSBwYXJhbXMuZ2V0RWxlbWVudDsgLy8gUmVxdWlyZWRcbiAgICB0aGlzLnNjcm9sbEhvb2sgPSBwYXJhbXMuc2Nyb2xsSG9vazsgLy8gT3B0aW9uYWxcbiAgICB0aGlzLml0ZW1TaXplID0gcGFyYW1zLml0ZW1TaXplIHx8ICcxMDAlJztcblxuICAgIHRoaXMuZ2V0QXV0b1Njcm9sbFJhdGlvID0gKC4uLmFyZ3MpID0+IHtcbiAgICAgIGxldCByYXRpbyA9IHBhcmFtcy5nZXRBdXRvU2Nyb2xsUmF0aW8gJiYgcGFyYW1zLmdldEF1dG9TY3JvbGxSYXRpbyguLi5hcmdzKTtcbiAgICAgIHJhdGlvID0gdHlwZW9mIHJhdGlvID09PSAnbnVtYmVyJyAmJiByYXRpbyA9PT0gcmF0aW8gPyByYXRpbyA6IC41O1xuICAgICAgaWYgKHJhdGlvIDwgMC4wIHx8IHJhdGlvID4gMS4wKSB7XG4gICAgICAgIHV0aWwudGhyb3coJ0ludmFsaWQgYXV0by1zY3JvbGwtcmF0aW8gJyArIHJhdGlvICsgJy4gTXVzdCBiZSBiZXR3ZWVuIDAgYW5kIDEnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByYXRpbztcbiAgICB9O1xuXG4gICAgLy8gUHJldmVudCBjbGlja3Mgb25seSBvbiBkZXNrdG9wXG4gICAgdGhpcy5zaG91bGRCbG9jayA9IHV0aWwuZ2xvYmFscy5hY3R1YWxNb2JpbGVPUyA9PT0gJ290aGVyJztcblxuICAgIC8vIEJpbmQgaGFuZGxlcnNcbiAgICB0aGlzLm9uRHJhZ1N0YXJ0ID0gdGhpcy5vbkRyYWdTdGFydC5iaW5kKHRoaXMpO1xuICAgIHRoaXMub25EcmFnID0gdGhpcy5vbkRyYWcuYmluZCh0aGlzKTtcbiAgICB0aGlzLm9uRHJhZ0VuZCA9IHRoaXMub25EcmFnRW5kLmJpbmQodGhpcyk7XG4gICAgdGhpcy5vblJlc2l6ZSA9IHRoaXMub25SZXNpemUuYmluZCh0aGlzKTtcblxuICAgIHRoaXMuX3Nob3VsZEZpeFNjcm9sbCA9IHV0aWwuZ2xvYmFscy5hY3R1YWxNb2JpbGVPUyA9PT0gJ2lvcyc7XG4gIH1cblxuICBpbml0KHsgc3dpcGVhYmxlLCBhdXRvUmVmcmVzaCB9ID0ge30pIHtcbiAgICB0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICB0aGlzLnRhcmdldCA9IHRoaXMuZ2V0RWxlbWVudCgpLmNoaWxkcmVuWzBdO1xuICAgIHRoaXMuYmxvY2tlciA9IHRoaXMuZ2V0RWxlbWVudCgpLmNoaWxkcmVuWzFdO1xuICAgIGlmICghdGhpcy50YXJnZXQgfHwgIXRoaXMuYmxvY2tlcikge1xuICAgICAgdXRpbC50aHJvdygnRXhwZWN0ZWQgXCJ0YXJnZXRcIiBhbmQgXCJibG9ja2VyXCIgZWxlbWVudHMgdG8gZXhpc3QgYmVmb3JlIGluaXRpYWxpemluZyBTd2lwZXInKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuc2hvdWxkQmxvY2spIHtcbiAgICAgIHRoaXMuYmxvY2tlci5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIH1cblxuICAgIC8vIEFkZCBjbGFzc2VzXG4gICAgdGhpcy5nZXRFbGVtZW50KCkuY2xhc3NMaXN0LmFkZCgnb25zLXN3aXBlcicpO1xuICAgIHRoaXMudGFyZ2V0LmNsYXNzTGlzdC5hZGQoJ29ucy1zd2lwZXItdGFyZ2V0Jyk7XG4gICAgdGhpcy5ibG9ja2VyLmNsYXNzTGlzdC5hZGQoJ29ucy1zd2lwZXItYmxvY2tlcicpO1xuXG4gICAgLy8gU2V0dXAgbGlzdGVuZXJzXG4gICAgdGhpcy5fZ2VzdHVyZURldGVjdG9yID0gbmV3IEdlc3R1cmVEZXRlY3Rvcih0aGlzLmdldEVsZW1lbnQoKSxcbiAgICAgIHsgZHJhZ01pbkRpc3RhbmNlOiAxLCBkcmFnTG9ja1RvQXhpczogdHJ1ZSwgcGFzc2l2ZTogIXRoaXMuX3Nob3VsZEZpeFNjcm9sbCB9XG4gICAgKTtcbiAgICB0aGlzLl9tdXRhdGlvbk9ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoKCkgPT4gdGhpcy5yZWZyZXNoKCkpO1xuICAgIHRoaXMudXBkYXRlU3dpcGVhYmxlKHN3aXBlYWJsZSk7XG4gICAgdGhpcy51cGRhdGVBdXRvUmVmcmVzaChhdXRvUmVmcmVzaCk7XG5cbiAgICAvLyBTZXR1cCBpbml0aWFsIGxheW91dFxuICAgIHRoaXMuX3Njcm9sbCA9IHRoaXMuX29mZnNldCA9IHRoaXMuX2xhc3RBY3RpdmVJbmRleCA9IDA7XG4gICAgdGhpcy5fdXBkYXRlTGF5b3V0KCk7XG4gICAgdGhpcy5fc2V0dXBJbml0aWFsSW5kZXgoKTtcbiAgICBzZXRJbW1lZGlhdGUoKCkgPT4gdGhpcy5pbml0aWFsaXplZCAmJiB0aGlzLl9zZXR1cEluaXRpYWxJbmRleCgpKTtcblxuICAgIC8vIEZpeCByZW5kZXJpbmcgZ2xpdGNoIG9uIEFuZHJvaWQgNC4xXG4gICAgLy8gRml4IGZvciBpZnJhbWVzIHdoZXJlIHRoZSB3aWR0aCBpcyBpbmNvbnNpc3RlbnQgYXQgdGhlIGJlZ2lubmluZ1xuICAgIGlmICh3aW5kb3cgIT09IHdpbmRvdy5wYXJlbnQgfHwgdGhpcy5vZmZzZXRIZWlnaHQgPT09IDApIHtcbiAgICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4gdGhpcy5pbml0aWFsaXplZCAmJiB0aGlzLm9uUmVzaXplKCkpO1xuICAgIH1cbiAgfVxuXG4gIGRpc3Bvc2UoKSB7XG4gICAgdGhpcy5pbml0aWFsaXplZCA9IGZhbHNlO1xuICAgIHRoaXMudXBkYXRlU3dpcGVhYmxlKGZhbHNlKTtcbiAgICB0aGlzLnVwZGF0ZUF1dG9SZWZyZXNoKGZhbHNlKTtcblxuICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvciAmJiB0aGlzLl9nZXN0dXJlRGV0ZWN0b3IuZGlzcG9zZSgpO1xuICAgIHRoaXMudGFyZ2V0ID0gdGhpcy5ibG9ja2VyID0gdGhpcy5fZ2VzdHVyZURldGVjdG9yID0gdGhpcy5fbXV0YXRpb25PYnNlcnZlciA9IG51bGw7XG5cbiAgICB0aGlzLnNldHVwUmVzaXplKGZhbHNlKTtcbiAgfVxuXG4gIG9uUmVzaXplKCkge1xuICAgIGNvbnN0IGkgPSB0aGlzLl9zY3JvbGwgLyB0aGlzLnRhcmdldFNpemU7XG4gICAgdGhpcy5fcmVzZXQoKTtcbiAgICB0aGlzLnNldEFjdGl2ZUluZGV4KGkpO1xuICAgIHRoaXMucmVmcmVzaCgpO1xuICB9XG5cbiAgZ2V0IGl0ZW1Db3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy50YXJnZXQuY2hpbGRyZW4ubGVuZ3RoO1xuICB9XG5cbiAgZ2V0IGl0ZW1OdW1TaXplKCkge1xuICAgIGlmICh0eXBlb2YgdGhpcy5faXRlbU51bVNpemUgIT09ICdudW1iZXInIHx8IHRoaXMuX2l0ZW1OdW1TaXplICE9PSB0aGlzLl9pdGVtTnVtU2l6ZSkge1xuICAgICAgdGhpcy5faXRlbU51bVNpemUgPSB0aGlzLl9jYWxjdWxhdGVJdGVtU2l6ZSgpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5faXRlbU51bVNpemU7XG4gIH1cblxuICBnZXQgbWF4U2Nyb2xsKCkge1xuICAgIGNvbnN0IG1heCA9IHRoaXMuaXRlbUNvdW50ICogdGhpcy5pdGVtTnVtU2l6ZSAtIHRoaXMudGFyZ2V0U2l6ZTtcbiAgICByZXR1cm4gTWF0aC5jZWlsKG1heCA8IDAgPyAwIDogbWF4KTsgLy8gTmVlZCB0byByZXR1cm4gYW4gaW50ZWdlciB2YWx1ZS5cbiAgfVxuXG4gIF9jYWxjdWxhdGVJdGVtU2l6ZSgpIHtcbiAgICBjb25zdCBtYXRjaGVzID0gdGhpcy5pdGVtU2l6ZS5tYXRjaCgvXihcXGQrKShweHwlKS8pO1xuXG4gICAgaWYgKCFtYXRjaGVzKSB7XG4gICAgICB1dGlsLnRocm93KGBJbnZhbGlkIHN0YXRlOiBzd2lwZXIncyBzaXplIHVuaXQgbXVzdCBiZSAnJScgb3IgJ3B4J2ApO1xuICAgIH1cblxuICAgIGNvbnN0IHZhbHVlID0gcGFyc2VJbnQobWF0Y2hlc1sxXSwgMTApO1xuICAgIHJldHVybiBtYXRjaGVzWzJdID09PSAnJScgPyBNYXRoLnJvdW5kKHZhbHVlIC8gMTAwICogdGhpcy50YXJnZXRTaXplKSA6IHZhbHVlO1xuICB9XG5cbiAgX3NldHVwSW5pdGlhbEluZGV4KCkge1xuICAgIHRoaXMuX3Jlc2V0KCk7XG4gICAgdGhpcy5fbGFzdEFjdGl2ZUluZGV4ID0gTWF0aC5tYXgoTWF0aC5taW4oTnVtYmVyKHRoaXMuZ2V0SW5pdGlhbEluZGV4KCkpLCB0aGlzLml0ZW1Db3VudCksIDApO1xuICAgIHRoaXMuX3Njcm9sbCA9IHRoaXMuX29mZnNldCArIHRoaXMuaXRlbU51bVNpemUgKiB0aGlzLl9sYXN0QWN0aXZlSW5kZXg7XG4gICAgdGhpcy5fc2Nyb2xsVG8odGhpcy5fc2Nyb2xsKTtcbiAgfVxuXG4gIF9zZXRTd2lwaW5nKHRvZ2dsZSkge1xuICAgIHRoaXMudGFyZ2V0LmNsYXNzTGlzdC50b2dnbGUoJ3N3aXBpbmcnLCB0b2dnbGUpOyAvLyBIaWRlcyBldmVyeXRoaW5nIGV4Y2VwdCBzaG93biBwYWdlc1xuICB9XG5cbiAgc2V0QWN0aXZlSW5kZXgoaW5kZXgsIG9wdGlvbnMgPSB7fSkge1xuICAgIHRoaXMuX3NldFN3aXBpbmcodHJ1ZSk7XG4gICAgaW5kZXggPSBNYXRoLm1heCgwLCBNYXRoLm1pbihpbmRleCwgdGhpcy5pdGVtQ291bnQgLSAxKSk7XG4gICAgY29uc3Qgc2Nyb2xsID0gTWF0aC5tYXgoMCwgTWF0aC5taW4odGhpcy5tYXhTY3JvbGwsIHRoaXMuX29mZnNldCArIHRoaXMuaXRlbU51bVNpemUgKiBpbmRleCkpO1xuXG4gICAgaWYgKHBsYXRmb3JtLmlzVUlXZWJWaWV3KCkpIHtcbiAgICAgIC8qIERpcnR5IGZpeCBmb3IgIzIyMzEoaHR0cHM6Ly9naXRodWIuY29tL09uc2VuVUkvT25zZW5VSS9pc3N1ZXMvMjIzMSkuIGJlZ2luICovXG4gICAgICBjb25zdCBjb25jYXQgPSBhcnJheU9mQXJyYXkgPT4gQXJyYXkucHJvdG90eXBlLmNvbmNhdC5hcHBseShbXSwgYXJyYXlPZkFycmF5KTtcbiAgICAgIGNvbnN0IGNvbnRlbnRzID0gY29uY2F0KFxuICAgICAgICB1dGlsLmFycmF5RnJvbSh0aGlzLnRhcmdldC5jaGlsZHJlbikubWFwKHBhZ2UgPT4ge1xuICAgICAgICAgIHJldHVybiB1dGlsLmFycmF5RnJvbShwYWdlLmNoaWxkcmVuKVxuICAgICAgICAgICAgLmZpbHRlcihjaGlsZCA9PiBjaGlsZC5jbGFzc0xpc3QuY29udGFpbnMoJ3BhZ2VfX2NvbnRlbnQnKSk7XG4gICAgICAgIH0pXG4gICAgICApO1xuXG4gICAgICBjb25zdCBtYXAgPSBuZXcgTWFwKCk7XG4gICAgICByZXR1cm4gKFxuICAgICAgICBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgICBjb250ZW50cy5mb3JFYWNoKGNvbnRlbnQgPT4ge1xuICAgICAgICAgICAgbWFwLnNldChjb250ZW50LCBjb250ZW50LmdldEF0dHJpYnV0ZSgnY2xhc3MnKSk7XG4gICAgICAgICAgICBjb250ZW50LmNsYXNzTGlzdC5hZGQoJ3BhZ2VfX2NvbnRlbnQtLXN1cHByZXNzLWxheWVyLWNyZWF0aW9uJylcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUocmVzb2x2ZSk7XG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKCgpID0+IHRoaXMuX2NoYW5nZVRvKHNjcm9sbCwgb3B0aW9ucykpXG4gICAgICAgIC50aGVuKCgpID0+IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgICAgIGNvbnRlbnRzLmZvckVhY2goY29udGVudCA9PiB7XG4gICAgICAgICAgICBjb250ZW50LnNldEF0dHJpYnV0ZSgnY2xhc3MnLCBtYXAuZ2V0KGNvbnRlbnQpKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUocmVzb2x2ZSk7XG4gICAgICAgIH0pKVxuICAgICAgKTtcbiAgICAgIC8qIGVuZCAqL1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5fY2hhbmdlVG8oc2Nyb2xsLCBvcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICBnZXRBY3RpdmVJbmRleChzY3JvbGwgPSB0aGlzLl9zY3JvbGwpIHtcbiAgICBzY3JvbGwgLT0gdGhpcy5fb2Zmc2V0O1xuICAgIGNvbnN0IGNvdW50ID0gdGhpcy5pdGVtQ291bnQsXG4gICAgICBzaXplID0gdGhpcy5pdGVtTnVtU2l6ZTtcblxuICAgIGlmICh0aGlzLml0ZW1OdW1TaXplID09PSAwIHx8ICF1dGlsLmlzSW50ZWdlcihzY3JvbGwpKSB7XG4gICAgICByZXR1cm4gdGhpcy5fbGFzdEFjdGl2ZUluZGV4O1xuICAgIH1cblxuICAgIGlmIChzY3JvbGwgPD0gMCkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICBpZiAoc2l6ZSAqIGkgPD0gc2Nyb2xsICYmIHNpemUgKiAoaSArIDEpID4gc2Nyb2xsKSB7XG4gICAgICAgIHJldHVybiBpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb3VudCAtIDE7XG4gIH1cblxuICBzZXR1cFJlc2l6ZShhZGQpIHtcbiAgICB3aW5kb3dbKGFkZCA/ICdhZGQnIDogJ3JlbW92ZScpICsgJ0V2ZW50TGlzdGVuZXInXSgncmVzaXplJywgdGhpcy5vblJlc2l6ZSwgdHJ1ZSk7XG4gIH1cblxuICBzaG93KCkge1xuICAgIHRoaXMuc2V0dXBSZXNpemUodHJ1ZSk7XG4gICAgdGhpcy5vblJlc2l6ZSgpO1xuICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy50YXJnZXQgJiYgdGhpcy50YXJnZXQuY2xhc3NMaXN0LmFkZCgnYWN0aXZlJyksIDEwMDAvNjApOyAvLyBIaWRlIGVsZW1lbnRzIGFmdGVyIGFuaW1hdGlvbnNcbiAgfVxuXG4gIGhpZGUoKSB7XG4gICAgdGhpcy5zZXR1cFJlc2l6ZShmYWxzZSk7XG4gICAgdGhpcy50YXJnZXQuY2xhc3NMaXN0LnJlbW92ZSgnYWN0aXZlJyk7IC8vIFNob3cgZWxlbWVudHMgYmVmb3JlIGFuaW1hdGlvbnNcbiAgfVxuXG4gIHVwZGF0ZVN3aXBlYWJsZShzaG91bGRVcGRhdGUpIHtcbiAgICBpZiAodGhpcy5fZ2VzdHVyZURldGVjdG9yKSB7XG4gICAgICBjb25zdCBhY3Rpb24gPSBzaG91bGRVcGRhdGUgPyAnb24nIDogJ29mZic7XG4gICAgICB0aGlzLl9nZXN0dXJlRGV0ZWN0b3JbYWN0aW9uXSgnZHJhZycsIHRoaXMub25EcmFnKTtcbiAgICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvclthY3Rpb25dKCdkcmFnc3RhcnQnLCB0aGlzLm9uRHJhZ1N0YXJ0KTtcbiAgICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvclthY3Rpb25dKCdkcmFnZW5kJywgdGhpcy5vbkRyYWdFbmQpO1xuICAgIH1cbiAgfVxuXG4gIHVwZGF0ZUF1dG9SZWZyZXNoKHNob3VsZFdhdGNoKSB7XG4gICAgaWYgKHRoaXMuX211dGF0aW9uT2JzZXJ2ZXIpIHtcbiAgICAgIHNob3VsZFdhdGNoXG4gICAgICAgID8gdGhpcy5fbXV0YXRpb25PYnNlcnZlci5vYnNlcnZlKHRoaXMudGFyZ2V0LCB7IGNoaWxkTGlzdDogdHJ1ZSB9KVxuICAgICAgICA6IHRoaXMuX211dGF0aW9uT2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuICAgIH1cbiAgfVxuXG4gIHVwZGF0ZUl0ZW1TaXplKG5ld1NpemUpIHtcbiAgICB0aGlzLml0ZW1TaXplID0gbmV3U2l6ZSB8fCAnMTAwJSc7XG4gICAgdGhpcy5yZWZyZXNoKCk7XG4gIH1cblxuICB0b2dnbGVCbG9ja2VyKGJsb2NrKSB7XG4gICAgdGhpcy5ibG9ja2VyLnN0eWxlLnBvaW50ZXJFdmVudHMgPSBibG9jayA/ICdhdXRvJyA6ICdub25lJztcbiAgfVxuXG4gIF9jYW5Db25zdW1lR2VzdHVyZShnZXN0dXJlKSB7XG4gICAgY29uc3QgZCA9IGdlc3R1cmUuZGlyZWN0aW9uO1xuICAgIGNvbnN0IGlzRmlyc3QgPSB0aGlzLl9zY3JvbGwgPT09IDAgJiYgIXRoaXMuaXNPdmVyU2Nyb2xsYWJsZSgpO1xuICAgIGNvbnN0IGlzTGFzdCA9IHRoaXMuX3Njcm9sbCA9PT0gdGhpcy5tYXhTY3JvbGwgJiYgIXRoaXMuaXNPdmVyU2Nyb2xsYWJsZSgpO1xuXG4gICAgcmV0dXJuIHRoaXMuaXNWZXJ0aWNhbCgpXG4gICAgICA/ICgoZCA9PT0gJ2Rvd24nICYmICFpc0ZpcnN0KSB8fCAoZCA9PT0gJ3VwJyAmJiAhaXNMYXN0KSlcbiAgICAgIDogKChkID09PSAncmlnaHQnICYmICFpc0ZpcnN0KSB8fCAoZCA9PT0gJ2xlZnQnICYmICFpc0xhc3QpKTtcbiAgfVxuXG4gIG9uRHJhZ1N0YXJ0KGV2ZW50KSB7XG4gICAgdGhpcy5faWdub3JlRHJhZyA9IGV2ZW50LmNvbnN1bWVkIHx8ICF1dGlsLmlzVmFsaWRHZXN0dXJlKGV2ZW50KTtcblxuICAgIGlmICghdGhpcy5faWdub3JlRHJhZykge1xuICAgICAgY29uc3QgY29uc3VtZSA9IGV2ZW50LmNvbnN1bWU7XG4gICAgICBldmVudC5jb25zdW1lID0gKCkgPT4geyBjb25zdW1lICYmIGNvbnN1bWUoKTsgdGhpcy5faWdub3JlRHJhZyA9IHRydWU7IH07XG5cbiAgICAgIGlmICh0aGlzLl9jYW5Db25zdW1lR2VzdHVyZShldmVudC5nZXN0dXJlKSkge1xuICAgICAgICBjb25zdCBzdGFydFggPSBldmVudC5nZXN0dXJlLmNlbnRlciAmJiBldmVudC5nZXN0dXJlLmNlbnRlci5jbGllbnRYIHx8IDAsXG4gICAgICAgICAgZGlzdEZyb21FZGdlID0gdGhpcy5nZXRCdWJibGVXaWR0aCgpIHx8IDAsXG4gICAgICAgICAgc3RhcnQgPSAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdW1lICYmIGNvbnN1bWUoKTtcbiAgICAgICAgICAgIGV2ZW50LmNvbnN1bWVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuX3N0YXJ0ZWQgPSB0cnVlOyAvLyBBdm9pZCBzdGFydGluZyBkcmFnIGZyb20gb3V0c2lkZVxuICAgICAgICAgICAgdGhpcy5zaG91bGRCbG9jayAmJiB0aGlzLnRvZ2dsZUJsb2NrZXIodHJ1ZSk7XG4gICAgICAgICAgICB0aGlzLl9zZXRTd2lwaW5nKHRydWUpO1xuICAgICAgICAgICAgdXRpbC5pb3NQcmV2ZW50U2Nyb2xsKHRoaXMuX2dlc3R1cmVEZXRlY3Rvcik7XG4gICAgICAgICAgfTtcblxuICAgICAgICAvLyBMZXQgcGFyZW50IGVsZW1lbnRzIGNvbnN1bWUgdGhlIGdlc3R1cmUgb3IgY29uc3VtZSBpdCByaWdodCBhd2F5XG4gICAgICAgIHN0YXJ0WCA8IGRpc3RGcm9tRWRnZSB8fCBzdGFydFggPiAodGhpcy50YXJnZXRTaXplIC0gZGlzdEZyb21FZGdlKVxuICAgICAgICAgID8gc2V0SW1tZWRpYXRlKCgpID0+ICF0aGlzLl9pZ25vcmVEcmFnICYmIHN0YXJ0KCkpXG4gICAgICAgICAgOiBzdGFydCgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG9uRHJhZyhldmVudCkge1xuICAgIGlmICghZXZlbnQuZ2VzdHVyZSB8fCB0aGlzLl9pZ25vcmVEcmFnIHx8ICF0aGlzLl9zdGFydGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fY29udGludWVkID0gdHJ1ZTsgLy8gRml4IGZvciByYW5kb20gJ2RyYWdlbmQnIHdpdGhvdXQgJ2RyYWcnXG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICB0aGlzLl9zY3JvbGxUbyh0aGlzLl9zY3JvbGwgLSB0aGlzLl9nZXREZWx0YShldmVudCksIHsgdGhyb3R0bGU6IHRydWUgfSk7XG4gIH1cblxuICBvbkRyYWdFbmQoZXZlbnQpIHtcbiAgICB0aGlzLl9zdGFydGVkID0gZmFsc2U7XG4gICAgaWYgKCFldmVudC5nZXN0dXJlIHx8IHRoaXMuX2lnbm9yZURyYWcgfHwgIXRoaXMuX2NvbnRpbnVlZCkge1xuICAgICAgdGhpcy5faWdub3JlRHJhZyA9IHRydWU7IC8vIG9uRHJhZ0VuZCBtaWdodCBmaXJlIGJlZm9yZSBvbkRyYWdTdGFydCdzIHNldEltbWVkaWF0ZVxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX2NvbnRpbnVlZCA9IGZhbHNlO1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgY29uc3Qgc2Nyb2xsID0gdGhpcy5fc2Nyb2xsIC0gdGhpcy5fZ2V0RGVsdGEoZXZlbnQpO1xuICAgIGNvbnN0IG5vcm1hbGl6ZWRTY3JvbGwgPSB0aGlzLl9ub3JtYWxpemVTY3JvbGwoc2Nyb2xsKTtcbiAgICBzY3JvbGwgPT09IG5vcm1hbGl6ZWRTY3JvbGwgPyB0aGlzLl9zdGFydE1vbWVudHVtU2Nyb2xsKHNjcm9sbCwgZXZlbnQpIDogdGhpcy5fa2lsbE92ZXJTY3JvbGwobm9ybWFsaXplZFNjcm9sbCk7XG4gICAgdGhpcy5zaG91bGRCbG9jayAmJiB0aGlzLnRvZ2dsZUJsb2NrZXIoZmFsc2UpO1xuICB9XG5cbiAgX3N0YXJ0TW9tZW50dW1TY3JvbGwoc2Nyb2xsLCBldmVudCkge1xuICAgIGNvbnN0IHZlbG9jaXR5ID0gdGhpcy5fZ2V0VmVsb2NpdHkoZXZlbnQpLFxuICAgICAgbWF0Y2hlc0RpcmVjdGlvbiA9IGV2ZW50Lmdlc3R1cmUuaW50ZXJpbURpcmVjdGlvbiA9PT0gdGhpcy5kTS5kaXJbdGhpcy5fZ2V0RGVsdGEoZXZlbnQpIDwgMCA/IDAgOiAxXTtcblxuICAgIGNvbnN0IG5leHRTY3JvbGwgPSB0aGlzLl9nZXRBdXRvU2Nyb2xsKHNjcm9sbCwgdmVsb2NpdHksIG1hdGNoZXNEaXJlY3Rpb24pO1xuICAgIGxldCBkdXJhdGlvbiA9IE1hdGguYWJzKG5leHRTY3JvbGwgLSBzY3JvbGwpIC8gKHZlbG9jaXR5ICsgMC4wMSkgLyAxMDAwO1xuICAgIGR1cmF0aW9uID0gTWF0aC5taW4oLjI1LCBNYXRoLm1heCguMSwgZHVyYXRpb24pKTtcblxuICAgIHRoaXMuX2NoYW5nZVRvKG5leHRTY3JvbGwsIHsgc3dpcGU6IHRydWUsIGFuaW1hdGlvbk9wdGlvbnM6IHsgZHVyYXRpb24sIHRpbWluZzogJ2N1YmljLWJlemllciguNCwgLjcsIC41LCAxKScgfSB9KTtcbiAgfVxuXG4gIF9raWxsT3ZlclNjcm9sbChzY3JvbGwpIHtcbiAgICB0aGlzLl9zY3JvbGwgPSBzY3JvbGw7XG4gICAgY29uc3QgZGlyZWN0aW9uID0gdGhpcy5kTS5kaXJbTnVtYmVyKHNjcm9sbCA+IDApXTtcbiAgICBjb25zdCBraWxsT3ZlclNjcm9sbCA9ICgpID0+IHRoaXMuX2NoYW5nZVRvKHNjcm9sbCwgeyBhbmltYXRpb25PcHRpb25zOiB7IGR1cmF0aW9uOiAuNCwgdGltaW5nOiAnY3ViaWMtYmV6aWVyKC4xLCAuNCwgLjEsIDEpJyB9IH0pO1xuICAgIHRoaXMub3ZlclNjcm9sbEhvb2soeyBkaXJlY3Rpb24sIGtpbGxPdmVyU2Nyb2xsIH0pIHx8IGtpbGxPdmVyU2Nyb2xsKCk7XG4gIH1cblxuICBfY2hhbmdlVG8oc2Nyb2xsLCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBlID0geyBhY3RpdmVJbmRleDogdGhpcy5nZXRBY3RpdmVJbmRleChzY3JvbGwpLCBsYXN0QWN0aXZlSW5kZXg6IHRoaXMuX2xhc3RBY3RpdmVJbmRleCwgc3dpcGU6IG9wdGlvbnMuc3dpcGUgfHwgZmFsc2UgfTtcbiAgICBjb25zdCBjaGFuZ2UgPSBlLmFjdGl2ZUluZGV4ICE9PSBlLmxhc3RBY3RpdmVJbmRleDtcbiAgICBjb25zdCBjYW5jZWxlZCA9IGNoYW5nZSA/IHRoaXMucHJlQ2hhbmdlSG9vayhlKSA6IGZhbHNlO1xuXG4gICAgdGhpcy5fc2Nyb2xsID0gY2FuY2VsZWQgPyB0aGlzLl9vZmZzZXQgKyBlLmxhc3RBY3RpdmVJbmRleCAqIHRoaXMuaXRlbU51bVNpemUgOiBzY3JvbGw7XG4gICAgdGhpcy5fbGFzdEFjdGl2ZUluZGV4ID0gY2FuY2VsZWQgPyBlLmxhc3RBY3RpdmVJbmRleCA6IGUuYWN0aXZlSW5kZXg7XG5cbiAgICByZXR1cm4gdGhpcy5fc2Nyb2xsVG8odGhpcy5fc2Nyb2xsLCBvcHRpb25zKS50aGVuKCgpID0+IHtcbiAgICAgIGlmIChzY3JvbGwgPT09IHRoaXMuX3Njcm9sbCAmJiAhY2FuY2VsZWQpIHtcbiAgICAgICAgdGhpcy5fc2V0U3dpcGluZyhmYWxzZSk7XG4gICAgICAgIGNoYW5nZSAmJiB0aGlzLnBvc3RDaGFuZ2VIb29rKGUpO1xuICAgICAgfSBlbHNlIGlmIChvcHRpb25zLnJlamVjdCkge1xuICAgICAgICB0aGlzLl9zZXRTd2lwaW5nKGZhbHNlKTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdDYW5jZWxlZCcpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgX3Njcm9sbFRvKHNjcm9sbCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgaWYgKG9wdGlvbnMudGhyb3R0bGUpIHtcbiAgICAgIGNvbnN0IHJhdGlvID0gMC4zNTtcbiAgICAgIGlmIChzY3JvbGwgPCAwKSB7XG4gICAgICAgIHNjcm9sbCA9IHRoaXMuaXNPdmVyU2Nyb2xsYWJsZSgpID8gTWF0aC5yb3VuZChzY3JvbGwgKiByYXRpbykgOiAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgbWF4U2Nyb2xsID0gdGhpcy5tYXhTY3JvbGw7XG4gICAgICAgIGlmIChtYXhTY3JvbGwgPCBzY3JvbGwpIHtcbiAgICAgICAgICBzY3JvbGwgPSB0aGlzLmlzT3ZlclNjcm9sbGFibGUoKSA/IG1heFNjcm9sbCArIE1hdGgucm91bmQoKHNjcm9sbCAtIG1heFNjcm9sbCkgKiByYXRpbykgOiBtYXhTY3JvbGw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBvcHQgPSBvcHRpb25zLmFuaW1hdGlvbiAgPT09ICdub25lJyA/IHt9IDogb3B0aW9ucy5hbmltYXRpb25PcHRpb25zO1xuICAgIHRoaXMuc2Nyb2xsSG9vayAmJiB0aGlzLml0ZW1OdW1TaXplID4gMCAmJiB0aGlzLnNjcm9sbEhvb2soKHNjcm9sbCAvIHRoaXMuaXRlbU51bVNpemUpLnRvRml4ZWQoMiksIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyB8fCB7fSk7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PlxuICAgICAgYW5pbWl0KHRoaXMudGFyZ2V0KVxuICAgICAgICAucXVldWUoeyB0cmFuc2Zvcm06IHRoaXMuX2dldFRyYW5zZm9ybShzY3JvbGwpIH0sIG9wdClcbiAgICAgICAgLnBsYXkocmVzb2x2ZSlcbiAgICApO1xuICB9XG5cbiAgX2dldEF1dG9TY3JvbGwoc2Nyb2xsLCB2ZWxvY2l0eSwgbWF0Y2hlc0RpcmVjdGlvbikge1xuICAgIGNvbnN0IG1heCA9IHRoaXMubWF4U2Nyb2xsLFxuICAgICAgb2Zmc2V0ID0gdGhpcy5fb2Zmc2V0LFxuICAgICAgc2l6ZSA9IHRoaXMuaXRlbU51bVNpemU7XG5cbiAgICBpZiAoIXRoaXMuaXNBdXRvU2Nyb2xsYWJsZSgpKSB7XG4gICAgICByZXR1cm4gTWF0aC5tYXgoMCwgTWF0aC5taW4obWF4LCBzY3JvbGwpKTtcbiAgICB9XG5cbiAgICBsZXQgYXJyID0gW107XG4gICAgZm9yIChsZXQgcyA9IG9mZnNldDsgcyA8IG1heDsgcyArPSBzaXplKSB7XG4gICAgICBhcnIucHVzaChzKTtcbiAgICB9XG4gICAgYXJyLnB1c2gobWF4KTtcblxuICAgIGFyciA9IGFyclxuICAgICAgLnNvcnQoKGxlZnQsIHJpZ2h0KSA9PiBNYXRoLmFicyhsZWZ0IC0gc2Nyb2xsKSAtIE1hdGguYWJzKHJpZ2h0IC0gc2Nyb2xsKSlcbiAgICAgIC5maWx0ZXIoKGl0ZW0sIHBvcykgPT4gIXBvcyB8fCBpdGVtICE9PSBhcnJbcG9zIC0gMV0pO1xuXG4gICAgbGV0IHJlc3VsdCA9IGFyclswXTtcbiAgICBjb25zdCBsYXN0U2Nyb2xsID0gdGhpcy5fbGFzdEFjdGl2ZUluZGV4ICogc2l6ZSArIG9mZnNldDtcbiAgICBjb25zdCBzY3JvbGxSYXRpbyA9IE1hdGguYWJzKHNjcm9sbCAtIGxhc3RTY3JvbGwpIC8gc2l6ZTtcblxuICAgIGlmIChzY3JvbGxSYXRpbyA8PSB0aGlzLmdldEF1dG9TY3JvbGxSYXRpbyhtYXRjaGVzRGlyZWN0aW9uLCB2ZWxvY2l0eSwgc2l6ZSkpIHtcbiAgICAgIHJlc3VsdCA9IGxhc3RTY3JvbGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChzY3JvbGxSYXRpbyA8IDEuMCAmJiBhcnJbMF0gPT09IGxhc3RTY3JvbGwgJiYgYXJyLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgcmVzdWx0ID0gYXJyWzFdO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gTWF0aC5tYXgoMCwgTWF0aC5taW4obWF4LCByZXN1bHQpKTtcbiAgfVxuXG4gIF9yZXNldCgpIHtcbiAgICB0aGlzLl90YXJnZXRTaXplID0gdGhpcy5faXRlbU51bVNpemUgPSB1bmRlZmluZWQ7XG4gIH1cblxuICBfbm9ybWFsaXplU2Nyb2xsKHNjcm9sbCkge1xuICAgIHJldHVybiBNYXRoLm1heCggTWF0aC5taW4oc2Nyb2xsLCB0aGlzLm1heFNjcm9sbCksIDApXG4gIH1cblxuICByZWZyZXNoKCkge1xuICAgIHRoaXMuX3Jlc2V0KCk7XG4gICAgdGhpcy5fdXBkYXRlTGF5b3V0KCk7XG5cbiAgICBpZiAodXRpbC5pc0ludGVnZXIodGhpcy5fc2Nyb2xsKSkge1xuICAgICAgY29uc3Qgc2Nyb2xsID0gdGhpcy5fbm9ybWFsaXplU2Nyb2xsKHRoaXMuX3Njcm9sbCk7XG4gICAgICBzY3JvbGwgIT09IHRoaXMuX3Njcm9sbCA/IHRoaXMuX2tpbGxPdmVyU2Nyb2xsKHNjcm9sbCkgOiB0aGlzLl9jaGFuZ2VUbyhzY3JvbGwpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9zZXR1cEluaXRpYWxJbmRleCgpO1xuICAgIH1cblxuICAgIHRoaXMucmVmcmVzaEhvb2soKTtcbiAgfVxuXG4gIGdldCB0YXJnZXRTaXplKCkge1xuICAgIGlmICghdGhpcy5fdGFyZ2V0U2l6ZSkge1xuICAgICAgdGhpcy5fdGFyZ2V0U2l6ZSA9IHRoaXMudGFyZ2V0W2BvZmZzZXQke3RoaXMuZE0uc2l6ZX1gXTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3RhcmdldFNpemU7XG4gIH1cblxuICBfZ2V0RGVsdGEoZXZlbnQpIHtcbiAgICByZXR1cm4gZXZlbnQuZ2VzdHVyZVtgZGVsdGEke3RoaXMuZE0uYXhpc31gXTtcbiAgfVxuXG4gIF9nZXRWZWxvY2l0eShldmVudCkge1xuICAgIHJldHVybiBldmVudC5nZXN0dXJlW2B2ZWxvY2l0eSR7dGhpcy5kTS5heGlzfWBdO1xuICB9XG5cbiAgX2dldFRyYW5zZm9ybShzY3JvbGwpIHtcbiAgICByZXR1cm4gYHRyYW5zbGF0ZTNkKCR7dGhpcy5kTS50M2RbMF19JHstc2Nyb2xsfSR7dGhpcy5kTS50M2RbMV19KWA7XG4gIH1cblxuICBfdXBkYXRlTGF5b3V0KCkge1xuICAgIHRoaXMuZE0gPSBkaXJlY3Rpb25NYXBbdGhpcy5pc1ZlcnRpY2FsKCkgPyAndmVydGljYWwnIDogJ2hvcml6b250YWwnXTtcbiAgICB0aGlzLnRhcmdldC5jbGFzc0xpc3QudG9nZ2xlKCdvbnMtc3dpcGVyLXRhcmdldC0tdmVydGljYWwnLCB0aGlzLmlzVmVydGljYWwoKSk7XG5cbiAgICBmb3IgKGxldCBjID0gdGhpcy50YXJnZXQuY2hpbGRyZW5bMF07IGM7IGMgPSBjLm5leHRFbGVtZW50U2libGluZykge1xuICAgICAgYy5zdHlsZVt0aGlzLmRNLnNpemUudG9Mb3dlckNhc2UoKV0gPSB0aGlzLml0ZW1TaXplO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmlzQ2VudGVyZWQoKSkge1xuICAgICAgdGhpcy5fb2Zmc2V0ID0gKHRoaXMudGFyZ2V0U2l6ZSAtIHRoaXMuaXRlbU51bVNpemUpIC8gLTIgfHwgMDtcbiAgICB9XG4gIH1cbn1cblxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcbmltcG9ydCBTd2lwZXIgZnJvbSAnLi4vb25zL2ludGVybmFsL3N3aXBlcic7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWNhcm91c2VsXG4gKiBAY2F0ZWdvcnkgY2Fyb3VzZWxcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgQ2Fyb3VzZWwgY29tcG9uZW50LiBBIGNhcm91c2VsIGNhbiBiZSB1c2VkIHRvIGRpc3BsYXkgc2V2ZXJhbCBpdGVtcyBpbiB0aGUgc2FtZSBzcGFjZS5cbiAqXG4gKiAgICAgVGhlIGNvbXBvbmVudCBzdXBwb3J0cyBkaXNwbGF5aW5nIGNvbnRlbnQgYm90aCBob3Jpem9udGFsbHkgYW5kIHZlcnRpY2FsbHkuIFRoZSB1c2VyIGNhbiBzY3JvbGwgdGhyb3VnaCB0aGUgaXRlbXMgYnkgZHJhZ2dpbmcgYW5kIGl0IGNhbiBhbHNvIGJlIGNvbnRyb2xsZXIgcHJvZ3JhbW1hdGljYWxseS5cbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAY29kZXBlbiB4YmJ6T1FcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9jYXJvdXNlbFxuICogQHNlZWFsc28gb25zLWNhcm91c2VsLWl0ZW1cbiAqICAgW2VuXWA8b25zLWNhcm91c2VsLWl0ZW0+YCBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLWNhcm91c2VsLWl0ZW3jgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtY2Fyb3VzZWwgc3R5bGU9XCJ3aWR0aDogMTAwJTsgaGVpZ2h0OiAyMDBweFwiPlxuICogICA8b25zLWNhcm91c2VsLWl0ZW0+XG4gKiAgICAuLi5cbiAqICAgPC9vbnMtY2Fyb3VzZWwtaXRlbT5cbiAqICAgPG9ucy1jYXJvdXNlbC1pdGVtPlxuICogICAgLi4uXG4gKiAgIDwvb25zLWNhcm91c2VsLWl0ZW0+XG4gKiA8L29ucy1jYXJvdXNlbD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ2Fyb3VzZWxFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdGNoYW5nZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQganVzdCBhZnRlciB0aGUgY3VycmVudCBjYXJvdXNlbCBpdGVtIGhhcyBjaGFuZ2VkLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOihqOekuuOBl+OBpuOBhOOCi+OCq+ODq+ODvOOCu+ODq+OBruimgee0oOOBjOWkieOCj+OBo+OBn+aZguOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmNhcm91c2VsXG4gICAqICAgW2VuXUNhcm91c2VsIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgYznmbrngavjgZfjgZ9DYXJvdXNlbOOCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBldmVudC5hY3RpdmVJbmRleFxuICAgKiAgIFtlbl1DdXJyZW50IGFjdGl2ZSBpbmRleC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjgqLjgq/jg4bjgqPjg5bjgavjgarjgaPjgabjgYTjgovopoHntKDjga7jgqTjg7Pjg4fjg4Pjgq/jgrnjgIJbL2phXVxuICAgKiBAcGFyYW0ge051bWJlcn0gZXZlbnQubGFzdEFjdGl2ZUluZGV4XG4gICAqICAgW2VuXVByZXZpb3VzIGFjdGl2ZSBpbmRleC5bL2VuXVxuICAgKiAgIFtqYV3ku6XliY3jgqLjgq/jg4bjgqPjg5bjgaDjgaPjgZ/opoHntKDjga7jgqTjg7Pjg4fjg4Pjgq/jgrnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHJlZnJlc2hcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIGNhcm91c2VsIGhhcyBiZWVuIHJlZnJlc2hlZC5bL2VuXVxuICAgKiAgIFtqYV3jgqvjg6vjg7zjgrvjg6vjgYzmm7TmlrDjgZXjgozjgZ/mmYLjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnRcbiAgICogICBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCpOODmeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5jYXJvdXNlbFxuICAgKiAgIFtlbl1DYXJvdXNlbCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44GM55m654Gr44GX44GfQ2Fyb3VzZWzjgqrjg5bjgrjjgqfjgq/jg4jjgafjgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IG92ZXJzY3JvbGxcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIGNhcm91c2VsIGhhcyBiZWVuIG92ZXJzY3JvbGxlZC5bL2VuXVxuICAgKiAgIFtqYV3jgqvjg6vjg7zjgrvjg6vjgYzjgqrjg7zjg5Djg7zjgrnjgq/jg63jg7zjg6vjgZfjgZ/mmYLjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnRcbiAgICogICBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCpOODmeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5jYXJvdXNlbFxuICAgKiAgIFtlbl1GaXJlZCB3aGVuIHRoZSBjYXJvdXNlbCBoYXMgYmVlbiByZWZyZXNoZWQuWy9lbl1cbiAgICogICBbamFd44Kr44Or44O844K744Or44GM5pu05paw44GV44KM44Gf5pmC44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGV2ZW50LmFjdGl2ZUluZGV4XG4gICAqICAgW2VuXUN1cnJlbnQgYWN0aXZlIGluZGV4LlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOCouOCr+ODhuOCo+ODluOBq+OBquOBo+OBpuOBhOOCi+imgee0oOOBruOCpOODs+ODh+ODg+OCr+OCueOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBldmVudC5kaXJlY3Rpb25cbiAgICogICBbZW5dQ2FuIGJlIG9uZSBvZiBlaXRoZXIgXCJ1cFwiLCBcImRvd25cIiwgXCJsZWZ0XCIgb3IgXCJyaWdodFwiLlsvZW5dXG4gICAqICAgW2phXeOCquODvOODkOODvOOCueOCr+ODreODvOODq+OBleOCjOOBn+aWueWQkeOBjOW+l+OCieOCjOOBvuOBmeOAglwidXBcIiwgXCJkb3duXCIsIFwibGVmdFwiLCBcInJpZ2h0XCLjga7jgYTjgZrjgozjgYvjga7mlrnlkJHjgYzmuKHjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC53YWl0VG9SZXR1cm5cbiAgICogICBbZW5dVGFrZXMgYSA8Y29kZT5Qcm9taXNlPC9jb2RlPiBvYmplY3QgYXMgYW4gYXJndW1lbnQuIFRoZSBjYXJvdXNlbCB3aWxsIG5vdCBzY3JvbGwgYmFjayB1bnRpbCB0aGUgcHJvbWlzZSBoYXMgYmVlbiByZXNvbHZlZCBvciByZWplY3RlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7plqLmlbDjga9Qcm9taXNl44Kq44OW44K444Kn44Kv44OI44KS5byV5pWw44Go44GX44Gm5Y+X44GR5Y+W44KK44G+44GZ44CC5rih44GX44GfUHJvbWlzZeOCquODluOCuOOCp+OCr+ODiOOBjHJlc29sdmXjgZXjgozjgovjgYtyZWplY3TjgZXjgozjgovjgb7jgafjgIHjgqvjg6vjg7zjgrvjg6vjga/jgrnjgq/jg63jg7zjg6vjg5Djg4Pjgq/jgZfjgb7jgZvjgpPjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXJlY3Rpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBkaXJlY3Rpb24gb2YgdGhlIGNhcm91c2VsLiBDYW4gYmUgZWl0aGVyIFwiaG9yaXpvbnRhbFwiIG9yIFwidmVydGljYWxcIi4gRGVmYXVsdCBpcyBcImhvcml6b250YWxcIi5bL2VuXVxuICAgKiAgIFtqYV3jgqvjg6vjg7zjgrvjg6vjga7mlrnlkJHjgpLmjIflrprjgZfjgb7jgZnjgIJcImhvcml6b250YWxcIuOBi1widmVydGljYWxcIuOCkuaMh+WumuOBp+OBjeOBvuOBmeOAglwiaG9yaXpvbnRhbFwi44GM44OH44OV44Kp44Or44OI5YCk44Gn44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZnVsbHNjcmVlblxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRoZSBjYXJvdXNlbCB3aWxsIGNvdmVyIHRoZSB3aG9sZSBzY3JlZW4uWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM44GC44KL44Go44CBYWJzb2x1dGXjg53jgrjjgrfjg6fjg7PjgpLkvb/jgaPjgabjgqvjg6vjg7zjgrvjg6vjgYzoh6rli5XnmoTjgavnlLvpnaLjgYTjgaPjgbHjgYTjgavluoPjgYzjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBvdmVyc2Nyb2xsYWJsZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRoZSBjYXJvdXNlbCB3aWxsIGJlIHNjcm9sbGFibGUgb3ZlciB0aGUgZWRnZS4gSXQgd2lsbCBib3VuY2UgYmFjayB3aGVuIHJlbGVhc2VkLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+aZguOAgeOCv+ODg+ODgeOChOODieODqeODg+OCsOOBp+err+OBvuOBp+OCueOCr+ODreODvOODq+OBl+OBn+aZguOBq+OAgeODkOOCpuODs+ODieOBmeOCi+OCiOOBhuOBquWKueaenOOBjOW9k+OBn+OCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGNlbnRlcmVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGNhcm91c2VsIHRoZW4gdGhlIHNlbGVjdGVkIGl0ZW0gd2lsbCBiZSBpbiB0aGUgY2VudGVyIG9mIHRoZSBjYXJvdXNlbCBpbnN0ZWFkIG9mIHRoZSBiZWdpbm5pbmcuIFVzZWZ1bCBvbmx5IHdoZW4gdGhlIGl0ZW1zIGFyZSBzbWFsbGVyIHRoYW4gdGhlIGNhcm91c2VsLiBbL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovmmYLjgIHpgbjjgpPjgafjgYTjgotvbnMtY2Fyb3VzZWwtaXRlbeOBr+OCq+ODq+ODvOOCu+ODq+OBruecn+OCk+S4reOBuOihjOOBjeOBvuOBmeOAgumgheebruOBjOOCq+ODq+ODvOOCu+ODq+OCiOOCiuOCguWwj+OBleOBhOWgtOWQiOOBq+OBruOBv+OAgeOBk+OCjOOBr+S+v+WIqeOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGl0ZW0td2lkdGhcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgIFtlbl1vbnMtY2Fyb3VzZWwtaXRlbSdzIHdpZHRoLiBPbmx5IHdvcmtzIHdoZW4gdGhlIGRpcmVjdGlvbiBpcyBzZXQgdG8gXCJob3Jpem9udGFsXCIuWy9lbl1cbiAgICogICAgW2phXW9ucy1jYXJvdXNlbC1pdGVt44Gu5bmF44KS5oyH5a6a44GX44G+44GZ44CC44GT44Gu5bGe5oCn44Gv44CBZGlyZWN0aW9u5bGe5oCn44GrXCJob3Jpem9udGFsXCLjgpLmjIflrprjgZfjgZ/mmYLjga7jgb/mnInlirnjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBpdGVtLWhlaWdodFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5db25zLWNhcm91c2VsLWl0ZW0ncyBoZWlnaHQuIE9ubHkgd29ya3Mgd2hlbiB0aGUgZGlyZWN0aW9uIGlzIHNldCB0byBcInZlcnRpY2FsXCIuWy9lbl1cbiAgICogICBbamFdb25zLWNhcm91c2VsLWl0ZW3jga7pq5jjgZXjgpLmjIflrprjgZfjgb7jgZnjgILjgZPjga7lsZ7mgKfjga/jgIFkaXJlY3Rpb27lsZ7mgKfjgatcInZlcnRpY2FsXCLjgpLmjIflrprjgZfjgZ/mmYLjga7jgb/mnInlirnjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhdXRvLXNjcm9sbFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRoZSBjYXJvdXNlbCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgc2Nyb2xsZWQgdG8gdGhlIGNsb3Nlc3QgaXRlbSBib3JkZXIgd2hlbiByZWxlYXNlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovmmYLjgIHkuIDnlarov5HjgYRjYXJvdXNlbC1pdGVt44Gu5aKD55WM44G+44Gn6Ieq5YuV55qE44Gr44K544Kv44Ot44O844Or44GZ44KL44KI44GG44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYXV0by1zY3JvbGwtcmF0aW9cbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgIFtlbl1BIG51bWJlciBiZXR3ZWVuIDAuMCBhbmQgMS4wIHRoYXQgc3BlY2lmaWVzIGhvdyBtdWNoIHRoZSB1c2VyIG11c3QgZHJhZyB0aGUgY2Fyb3VzZWwgaW4gb3JkZXIgZm9yIGl0IHRvIGF1dG8gc2Nyb2xsIHRvIHRoZSBuZXh0IGl0ZW0uWy9lbl1cbiAgICogICAgW2phXTAuMOOBi+OCiTEuMOOBvuOBp+OBruWApOOCkuaMh+WumuOBl+OBvuOBmeOAguOCq+ODq+ODvOOCu+ODq+OBruimgee0oOOCkuOBqeOCjOOBkOOCieOBhOOBruWJsuWQiOOBvuOBp+ODieODqeODg+OCsOOBmeOCi+OBqOasoeOBruimgee0oOOBq+iHquWLleeahOOBq+OCueOCr+ODreODvOODq+OBmeOCi+OBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHN3aXBlYWJsZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRoZSBjYXJvdXNlbCBjYW4gYmUgc2Nyb2xsZWQgYnkgZHJhZyBvciBzd2lwZS5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovmmYLjgIHjgqvjg6vjg7zjgrvjg6vjgpLjgrnjg6/jgqTjg5fjgoTjg4njg6njg4PjgrDjgafnp7vli5XjgafjgY3jgovjgojjgYbjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXNhYmxlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRoZSBjYXJvdXNlbCBpcyBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovmmYLjgIFkcmFn44KEdG91Y2jjgoRzd2lwZeOCkuWPl+OBkeS7mOOBkeOBquOBj+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGluaXRpYWwtaW5kZXhcbiAgICogQGluaXRvbmx5XG4gICAqIEBkZWZhdWx0IDBcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGluZGV4IG9mIHRoZSBvbnMtY2Fyb3VzZWwtaXRlbSB0byBzaG93IGluaXRpYWxseS4gRGVmYXVsdCBpcyAwLlsvZW5dXG4gICAqICAgW2phXeacgOWIneOBq+ihqOekuuOBmeOCi29ucy1jYXJvdXNlbC1pdGVt44KSMOWni+OBvuOCiuOBruOCpOODs+ODh+ODg+OCr+OCueOBp+aMh+WumuOBl+OBvuOBmeOAguODh+ODleOCqeODq+ODiOWApOOBryAwIOOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGF1dG8tcmVmcmVzaFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hlbiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGNhcm91c2VsIHdpbGwgYXV0b21hdGljYWxseSByZWZyZXNoIHdoZW4gdGhlIG51bWJlciBvZiBjaGlsZCBub2RlcyBjaGFuZ2UuWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM44GC44KL5pmC44CB5a2Q6KaB57Sg44Gu5pWw44GM5aSJ44KP44KL44Go44Kr44Or44O844K744Or44Gv6Ieq5YuV55qE44Gr5pu05paw44GV44KM44KL44KI44GG44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdG8gYFwibm9uZVwiYCB0aGUgdHJhbnNpdGlvbnMgd2lsbCBub3QgYmUgYW5pbWF0ZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uLW9wdGlvbnNcbiAgICogQHR5cGUge0V4cHJlc3Npb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgdGltaW5nIGFuZCBkZWxheSB3aXRoIGFuIG9iamVjdCBsaXRlcmFsLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIHRpbWluZywgZGVsYXnjgpLjgqrjg5bjgrjjgqfjgq/jg4jjg6rjg4bjg6njg6vjgafmjIflrprjgZfjgb7jgZnjgILkvovvvJp7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fY29tcGlsZSgpKTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIGNvbnN0IHRhcmdldCA9IHRoaXMuY2hpbGRyZW5bMF0gJiYgdGhpcy5jaGlsZHJlblswXS50YWdOYW1lICE9PSAnT05TLUNBUk9VU0VMLUlURU0nICYmIHRoaXMuY2hpbGRyZW5bMF0gfHwgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgaWYgKCF0YXJnZXQucGFyZW50Tm9kZSkge1xuICAgICAgd2hpbGUgKHRoaXMuZmlyc3RDaGlsZCkge1xuICAgICAgICB0YXJnZXQuYXBwZW5kQ2hpbGQodGhpcy5maXJzdENoaWxkKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuYXBwZW5kQ2hpbGQodGFyZ2V0KTtcbiAgICB9XG5cbiAgICAhdGhpcy5jaGlsZHJlblsxXSAmJiB0aGlzLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpKTtcblxuICAgIHRoaXMuYXBwZW5kQ2hpbGQgPSB0aGlzLmFwcGVuZENoaWxkLmJpbmQodGFyZ2V0KTtcbiAgICB0aGlzLmluc2VydEJlZm9yZSA9IHRoaXMuaW5zZXJ0QmVmb3JlLmJpbmQodGFyZ2V0KTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGlmICghdGhpcy5fc3dpcGVyKSB7XG4gICAgICB0aGlzLl9zd2lwZXIgPSBuZXcgU3dpcGVyKHtcbiAgICAgICAgZ2V0RWxlbWVudDogKCkgPT4gdGhpcyxcbiAgICAgICAgZ2V0SW5pdGlhbEluZGV4OiAoKSA9PiB0aGlzLmdldEF0dHJpYnV0ZSgnaW5pdGlhbC1pbmRleCcpLFxuICAgICAgICBnZXRBdXRvU2Nyb2xsUmF0aW86ICgpID0+IHRoaXMuYXV0b1Njcm9sbFJhdGlvLFxuICAgICAgICBpc1ZlcnRpY2FsOiAoKSA9PiB0aGlzLnZlcnRpY2FsLFxuICAgICAgICBpc092ZXJTY3JvbGxhYmxlOiAoKSA9PiB0aGlzLm92ZXJzY3JvbGxhYmxlLFxuICAgICAgICBpc0NlbnRlcmVkOiAoKSA9PiB0aGlzLmNlbnRlcmVkLFxuICAgICAgICBpc0F1dG9TY3JvbGxhYmxlOiAoKSA9PiB0aGlzLmF1dG9TY3JvbGwsXG4gICAgICAgIGl0ZW1TaXplOiB0aGlzLml0ZW1TaXplLFxuICAgICAgICBvdmVyU2Nyb2xsSG9vazogdGhpcy5fb25PdmVyU2Nyb2xsLmJpbmQodGhpcyksXG4gICAgICAgIHByZUNoYW5nZUhvb2s6IHRoaXMuX29uQ2hhbmdlLmJpbmQodGhpcywgJ3ByZWNoYW5nZScpLFxuICAgICAgICBwb3N0Q2hhbmdlSG9vazogdGhpcy5fb25DaGFuZ2UuYmluZCh0aGlzLCAncG9zdGNoYW5nZScpLFxuICAgICAgICByZWZyZXNoSG9vazogdGhpcy5fb25SZWZyZXNoLmJpbmQodGhpcyksXG4gICAgICAgIHNjcm9sbEhvb2s6ICguLi5hcmdzKSA9PiB0aGlzLl9vblN3aXBlICYmIHRoaXMuX29uU3dpcGUoLi4uYXJncylcbiAgICAgIH0pO1xuXG4gICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fc3dpcGVyLmluaXQoe1xuICAgICAgICBzd2lwZWFibGU6IHRoaXMuaGFzQXR0cmlidXRlKCdzd2lwZWFibGUnKSxcbiAgICAgICAgYXV0b1JlZnJlc2g6IHRoaXMuaGFzQXR0cmlidXRlKCdhdXRvLXJlZnJlc2gnKVxuICAgICAgfSkpO1xuICAgIH1cbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGlmICh0aGlzLl9zd2lwZXIgJiYgdGhpcy5fc3dpcGVyLmluaXRpYWxpemVkKSB7XG4gICAgICB0aGlzLl9zd2lwZXIuZGlzcG9zZSgpO1xuICAgICAgdGhpcy5fc3dpcGVyID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydzd2lwZWFibGUnLCAnYXV0by1yZWZyZXNoJywgJ2RpcmVjdGlvbicsICdpdGVtLWhlaWdodCcsICdpdGVtLXdpZHRoJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIGlmICghdGhpcy5fc3dpcGVyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdzd2lwZWFibGUnOlxuICAgICAgICB0aGlzLl9zd2lwZXIudXBkYXRlU3dpcGVhYmxlKHRoaXMuaGFzQXR0cmlidXRlKCdzd2lwZWFibGUnKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnYXV0by1yZWZyZXNoJzpcbiAgICAgICAgdGhpcy5fc3dpcGVyLnVwZGF0ZUF1dG9SZWZyZXNoKHRoaXMuaGFzQXR0cmlidXRlKCdhdXRvLXJlZnJlc2gnKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaXRlbS1oZWlnaHQnOlxuICAgICAgICB0aGlzLnZlcnRpY2FsICYmIHRoaXMuX3N3aXBlci51cGRhdGVJdGVtU2l6ZSh0aGlzLml0ZW1TaXplKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdpdGVtLXdpZHRoJzpcbiAgICAgICAgdGhpcy52ZXJ0aWNhbCB8fCB0aGlzLl9zd2lwZXIudXBkYXRlSXRlbVNpemUodGhpcy5pdGVtU2l6ZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnZGlyZWN0aW9uJzpcbiAgICAgICAgdGhpcy5fc3dpcGVyLnJlZnJlc2goKTtcbiAgICB9XG4gIH1cblxuICBfc2hvdygpIHtcbiAgICB0aGlzLl9zd2lwZXIuc2hvdygpO1xuICB9XG5cbiAgX2hpZGUoKSB7XG4gICAgdGhpcy5fc3dpcGVyLmhpZGUoKTtcbiAgfVxuXG4gIF9vbk92ZXJTY3JvbGwoeyBkaXJlY3Rpb24sIGtpbGxPdmVyU2Nyb2xsIH0pIHtcbiAgICBsZXQgd2FpdEZvckFjdGlvbiA9IGZhbHNlO1xuICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnb3ZlcnNjcm9sbCcsIHtcbiAgICAgIGNhcm91c2VsOiB0aGlzLFxuICAgICAgYWN0aXZlSW5kZXg6IHRoaXMuZ2V0QWN0aXZlSW5kZXgoKSxcbiAgICAgIGRpcmVjdGlvbixcbiAgICAgIHdhaXRUb1JldHVybjogcHJvbWlzZSA9PiB7XG4gICAgICAgIHdhaXRGb3JBY3Rpb24gPSB0cnVlO1xuICAgICAgICBwcm9taXNlLnRoZW4oa2lsbE92ZXJTY3JvbGwpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHdhaXRGb3JBY3Rpb247XG4gIH1cblxuICBfb25DaGFuZ2UoZXZlbnROYW1lLCB7IGFjdGl2ZUluZGV4LCBsYXN0QWN0aXZlSW5kZXggfSkge1xuICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCBldmVudE5hbWUsIHsgY2Fyb3VzZWw6IHRoaXMsIGFjdGl2ZUluZGV4LCBsYXN0QWN0aXZlSW5kZXggfSk7XG4gIH1cblxuICBfb25SZWZyZXNoKCkge1xuICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAncmVmcmVzaCcsIHsgY2Fyb3VzZWw6IHRoaXMgfSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBzZXRBY3RpdmVJbmRleFxuICAgKiBAc2lnbmF0dXJlIHNldEFjdGl2ZUluZGV4KGluZGV4LCBbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBpbmRleFxuICAgKiAgIFtlbl1UaGUgaW5kZXggdGhhdCB0aGUgY2Fyb3VzZWwgc2hvdWxkIGJlIHNldCB0by5bL2VuXVxuICAgKiAgIFtqYV1jYXJvdXNlbOimgee0oOOBruOCpOODs+ODh+ODg+OCr+OCueOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogICBbZW5dQSBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgY2FsbGVkIGFmdGVyIHRoZSBhbmltYXRpb24gaXMgZmluaXNoZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRvIGBcIm5vbmVcImAgdGhlIHRyYW5zaXRpb25zIHdpbGwgbm90IGJlIGFuaW1hdGVkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucy5hbmltYXRpb25PcHRpb25zXVxuICAgKiAgIFtlbl1BbiBvYmplY3QgdGhhdCBjYW4gYmUgdXNlZCB0byBzcGVjaWZ5IGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nIGZ1bmN0aW9uIG9mIHRoZSBhbmltYXRpb24uWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGluZGV4IG9mIHRoZSBgPG9ucy1jYXJvdXNlbC1pdGVtPmAgdG8gc2hvdy5bL2VuXVxuICAgKiAgIFtqYV3ooajnpLrjgZnjgotvbnMtY2Fyb3VzZWwtaXRlbeOCkmluZGV444Gn5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGNhcm91c2VsIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIHNldEFjdGl2ZUluZGV4KGluZGV4LCBvcHRpb25zID0ge30pIHtcbiAgICBvcHRpb25zID0ge1xuICAgICAgYW5pbWF0aW9uOiB0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uJyksXG4gICAgICBhbmltYXRpb25PcHRpb25zOiB0aGlzLmhhc0F0dHJpYnV0ZSgnYW5pbWF0aW9uLW9wdGlvbnMnKVxuICAgICAgICA/IHV0aWwuYW5pbWF0aW9uT3B0aW9uc1BhcnNlKHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24tb3B0aW9ucycpKVxuICAgICAgICA6IHsgZHVyYXRpb246IC4zLCB0aW1pbmc6ICdjdWJpYy1iZXppZXIoLjQsIC43LCAuNSwgMSknIH0sXG4gICAgICAuLi5vcHRpb25zXG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLl9zd2lwZXIuc2V0QWN0aXZlSW5kZXgoaW5kZXgsIG9wdGlvbnMpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIG9wdGlvbnMuY2FsbGJhY2sgaW5zdGFuY2VvZiBGdW5jdGlvbiAmJiBvcHRpb25zLmNhbGxiYWNrKHRoaXMpO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBnZXRBY3RpdmVJbmRleFxuICAgKiBAc2lnbmF0dXJlIGdldEFjdGl2ZUluZGV4KClcbiAgICogQHJldHVybiB7TnVtYmVyfVxuICAgKiAgIFtlbl1UaGUgY3VycmVudCBjYXJvdXNlbCBpdGVtIGluZGV4LlsvZW5dXG4gICAqICAgW2phXeePvuWcqOihqOekuuOBl+OBpuOBhOOCi+OCq+ODq+ODvOOCu+ODq+imgee0oOOBruOCpOODs+ODh+ODg+OCr+OCueOBjOi/lOOBleOCjOOBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgY3VycmVudGx5IHZpc2libGUgYDxvbnMtY2Fyb3VzZWwtaXRlbT5gLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOihqOekuuOBleOCjOOBpuOBhOOCi29ucy1jYXJvdXNlbC1pdGVt6KaB57Sg44Gu44Kk44Oz44OH44OD44Kv44K544KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGdldEFjdGl2ZUluZGV4KCkge1xuICAgIHJldHVybiB0aGlzLl9zd2lwZXIuZ2V0QWN0aXZlSW5kZXgoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIG5leHRcbiAgICogQHNpZ25hdHVyZSBuZXh0KFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1BIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBleGVjdXRlZCBhZnRlciB0aGUgYW5pbWF0aW9uIGhhcyBmaW5pc2hlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdG8gYFwibm9uZVwiYCB0aGUgdHJhbnNpdGlvbnMgd2lsbCBub3QgYmUgYW5pbWF0ZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXUFuIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHRvIHNwZWNpZnkgdGhlIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nIGZ1bmN0aW9uIG9mIHRoZSBhbmltYXRpb24uWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGNhcm91c2VsIGVsZW1lbnRbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyBuZXh0IGA8b25zLWNhcm91c2VsLWl0ZW0+YC5bL2VuXVxuICAgKiAgIFtqYV3mrKHjga5vbnMtY2Fyb3VzZWwtaXRlbeOCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBuZXh0KG9wdGlvbnMpIHtcbiAgICByZXR1cm4gdGhpcy5zZXRBY3RpdmVJbmRleCh0aGlzLmdldEFjdGl2ZUluZGV4KCkgKyAxLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHByZXZcbiAgICogQHNpZ25hdHVyZSBwcmV2KFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1BIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBleGVjdXRlZCBhZnRlciB0aGUgYW5pbWF0aW9uIGhhcyBmaW5pc2hlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdG8gYFwibm9uZVwiYCB0aGUgdHJhbnNpdGlvbnMgd2lsbCBub3QgYmUgYW5pbWF0ZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXUFuIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHRvIHNwZWNpZnkgdGhlIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nIGZ1bmN0aW9uIG9mIHRoZSBhbmltYXRpb24uWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGNhcm91c2VsIGVsZW1lbnRbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyBwcmV2aW91cyBgPG9ucy1jYXJvdXNlbC1pdGVtPmAuWy9lbl1cbiAgICogICBbamFd5YmN44Gub25zLWNhcm91c2VsLWl0ZW3jgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgcHJldihvcHRpb25zKSB7XG4gICAgcmV0dXJuIHRoaXMuc2V0QWN0aXZlSW5kZXgodGhpcy5nZXRBY3RpdmVJbmRleCgpIC0gMSwgb3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBmaXJzdFxuICAgKiBAc2lnbmF0dXJlIGZpcnN0KClcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1BIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBleGVjdXRlZCBhZnRlciB0aGUgYW5pbWF0aW9uIGhhcyBmaW5pc2hlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1JZiB0aGlzIGlzIHNldCB0byBgXCJub25lXCJgLCB0aGUgdHJhbnNpdGlvbnMgd2lsbCBub3QgYmUgYW5pbWF0ZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXUFuIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHRvIHNwZWNpZnkgdGhlIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nIGZ1bmN0aW9uIG9mIHRoZSBhbmltYXRpb24uWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGNhcm91c2VsIGVsZW1lbnRbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyBmaXJzdCBgPG9ucy1jYXJvdXNlbC1pdGVtPmAuWy9lbl1cbiAgICogICBbamFd5pyA5Yid44Gub25zLWNhcm91c2VsLWl0ZW3jgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZmlyc3Qob3B0aW9ucykge1xuICAgIHJldHVybiB0aGlzLnNldEFjdGl2ZUluZGV4KDAsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgbGFzdFxuICAgKiBAc2lnbmF0dXJlIGxhc3QoKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXUEgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGV4ZWN1dGVkIGFmdGVyIHRoZSBhbmltYXRpb24gaGFzIGZpbmlzaGVkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHNldCB0byBgXCJub25lXCJgIHRoZSB0cmFuc2l0aW9ucyB3aWxsIG5vdCBiZSBhbmltYXRlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dQW4gb2JqZWN0IHRoYXQgY2FuIGJlIHVzZWQgdG8gc3BlY2lmeSB0aGUgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcgZnVuY3Rpb24gb2YgdGhlIGFuaW1hdGlvbi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgY2Fyb3VzZWwgZWxlbWVudFsvZW5dXG4gICAqICAgW2phXVJlc29sdmVzIHRvIHRoZSBjYXJvdXNlbCBlbGVtZW50Wy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNob3cgbGFzdCBvbnMtY2Fyb3VzZWwgaXRlbS5bL2VuXVxuICAgKiAgIFtqYV3mnIDlvozjga5vbnMtY2Fyb3VzZWwtaXRlbeOCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBsYXN0KG9wdGlvbnMpIHtcbiAgICB0aGlzLnNldEFjdGl2ZUluZGV4KE1hdGgubWF4KHRoaXMuaXRlbUNvdW50IC0gMSwgMCksIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgcmVmcmVzaFxuICAgKiBAc2lnbmF0dXJlIHJlZnJlc2goKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVXBkYXRlIHRoZSBsYXlvdXQgb2YgdGhlIGNhcm91c2VsLiBVc2VkIHdoZW4gYWRkaW5nIGA8b25zLWNhcm91c2VsLWl0ZW1zPmAgZHluYW1pY2FsbHkgb3IgdG8gYXV0b21hdGljYWxseSBhZGp1c3QgdGhlIHNpemUuWy9lbl1cbiAgICogICBbamFd44Os44Kk44Ki44Km44OI44KE5YaF6YOo44Gu54q25oWL44KS5pyA5paw44Gu44KC44Gu44Gr5pu05paw44GX44G+44GZ44CCb25zLWNhcm91c2VsLWl0ZW3jgpLli5XnmoTjgavlopfjgoTjgZfjgZ/jgorjgIFvbnMtY2Fyb3VzZWzjga7lpKfjgY3jgZXjgpLli5XnmoTjgavlpInjgYjjgovpmpvjgavliKnnlKjjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgcmVmcmVzaCgpIHtcbiAgICB0aGlzLl9zd2lwZXIucmVmcmVzaCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBpdGVtQ291bnRcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgbnVtYmVyIG9mIGNhcm91c2VsIGl0ZW1zLlsvZW5dXG4gICAqICAgW2phXeOCq+ODq+ODvOOCu+ODq+imgee0oOOBruaVsOOBp+OBmeOAglsvamFdXG4gICAqL1xuICBnZXQgaXRlbUNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLl9zd2lwZXIuaXRlbUNvdW50O1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBzd2lwZWFibGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl10cnVlIGlmIHRoZSBjYXJvdXNlbCBpcyBzd2lwZWFibGUuWy9lbl1cbiAgICogICBbamFdc3dpcGVhYmxl44Gn44GC44KM44GwdHJ1ZeOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBnZXQgc3dpcGVhYmxlKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnc3dpcGVhYmxlJyk7XG4gIH1cblxuICBzZXQgc3dpcGVhYmxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdzd2lwZWFibGUnLCB2YWx1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9uU3dpcGVcbiAgICogQHR5cGUge0Z1bmN0aW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSG9vayBjYWxsZWQgd2hlbmV2ZXIgdGhlIHVzZXIgc2xpZGVzIHRoZSBjYXJvdXNlbC4gSXQgZ2V0cyBhIGRlY2ltYWwgaW5kZXggYW5kIGFuIGFuaW1hdGlvbk9wdGlvbnMgb2JqZWN0IGFzIGFyZ3VtZW50cy5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgZ2V0IG9uU3dpcGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX29uU3dpcGU7XG4gIH1cblxuICBzZXQgb25Td2lwZSh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSAmJiAhKHZhbHVlIGluc3RhbmNlb2YgRnVuY3Rpb24pKSB7XG4gICAgICB1dGlsLnRocm93KGBcIm9uU3dpcGVcIiBtdXN0IGJlIGEgZnVuY3Rpb25gKVxuICAgIH1cbiAgICB0aGlzLl9vblN3aXBlID0gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGF1dG9TY3JvbGxcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl10cnVlIGlmIGF1dG8gc2Nyb2xsIGlzIGVuYWJsZWQuWy9lbl1cbiAgICogICBbamFd44Kq44O844OI44K544Kv44Ot44O844Or44GM5pyJ5Yq544Gn44GC44KM44GwdHJ1ZeOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBnZXQgYXV0b1Njcm9sbCgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2F1dG8tc2Nyb2xsJyk7XG4gIH1cblxuICBzZXQgYXV0b1Njcm9sbCh2YWx1ZSkge1xuICAgIHJldHVybiB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnYXV0by1zY3JvbGwnLCB2YWx1ZSk7XG4gIH1cblxuICBnZXQgdmVydGljYWwoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QXR0cmlidXRlKCdkaXJlY3Rpb24nKSA9PT0gJ3ZlcnRpY2FsJztcbiAgfVxuXG4gIGdldCBpdGVtU2l6ZSgpIHtcbiAgICBjb25zdCBpdGVtU2l6ZUF0dHIgPSAodGhpcy5nZXRBdHRyaWJ1dGUoYGl0ZW0tJHt0aGlzLnZlcnRpY2FsID8gJ2hlaWdodCcgOiAnd2lkdGgnfWApIHx8ICcnKS50cmltKCk7XG4gICAgcmV0dXJuIGl0ZW1TaXplQXR0ci5tYXRjaCgvXlxcZCsocHh8JSkkLykgPyBpdGVtU2l6ZUF0dHIgOiAnMTAwJSc7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGF1dG9TY3JvbGxSYXRpb1xuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGN1cnJlbnQgYXV0byBzY3JvbGwgcmF0aW8uIFsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBruOCquODvOODiOOCueOCr+ODreODvOODq+OBrnJhdGlv5YCk44CCWy9qYV1cbiAgICovXG4gIGdldCBhdXRvU2Nyb2xsUmF0aW8oKSB7XG4gICAgcmV0dXJuIHBhcnNlRmxvYXQodGhpcy5nZXRBdHRyaWJ1dGUoJ2F1dG8tc2Nyb2xsLXJhdGlvJykpO1xuICB9XG5cbiAgc2V0IGF1dG9TY3JvbGxSYXRpbyhyYXRpbykge1xuICAgIHRoaXMuc2V0QXR0cmlidXRlKCdhdXRvLXNjcm9sbC1yYXRpbycsIHJhdGlvKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBjYXJvdXNlbCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG4gIGdldCBkaXNhYmxlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gIH1cblxuICBzZXQgZGlzYWJsZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2Rpc2FibGVkJywgdmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvdmVyc2Nyb2xsYWJsZVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGNhcm91c2VsIGlzIG92ZXJzY3JvbGxhYmxlIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV1vdmVyc2Nyb2xs44Gn44GN44KM44GwdHJ1ZeOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBnZXQgb3ZlcnNjcm9sbGFibGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdvdmVyc2Nyb2xsYWJsZScpO1xuICB9XG5cbiAgc2V0IG92ZXJzY3JvbGxhYmxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdvdmVyc2Nyb2xsYWJsZScsIHZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgY2VudGVyZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBjYXJvdXNlbCBpcyBjZW50ZXJlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFdY2VudGVyZWTnirbmhYvjgavjgarjgaPjgabjgYTjgozjgbB0cnVl44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGdldCBjZW50ZXJlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2NlbnRlcmVkJyk7XG4gIH1cblxuICBzZXQgY2VudGVyZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2NlbnRlcmVkJywgdmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIGdldCBldmVudHMoKSB7XG4gICAgcmV0dXJuIFsncG9zdGNoYW5nZScsICdyZWZyZXNoJywgJ292ZXJzY3JvbGwnXTtcbiAgfVxufVxuXG5vbnNFbGVtZW50cy5DYXJvdXNlbCA9IENhcm91c2VsRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWNhcm91c2VsJywgQ2Fyb3VzZWxFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHN0eWxlciBmcm9tICcuLi9vbnMvc3R5bGVyJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtY29sXG4gKiBAY2F0ZWdvcnkgZ3JpZFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1SZXByZXNlbnRzIGEgY29sdW1uIGluIHRoZSBncmlkIHN5c3RlbS4gVXNlIHdpdGggYDxvbnMtcm93PmAgdG8gbGF5b3V0IGNvbXBvbmVudHMuWy9lbl1cbiAqICAgW2phXeOCsOODquODg+ODieOCt+OCueODhuODoOOBq+OBpuWIl+OCkuWumue+qeOBl+OBvuOBmeOAgm9ucy1yb3fjgajjgajjgoLjgavkvb/nlKjjgZfjgIHjgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jg6zjgqTjgqLjgqbjg4jjgavliKnnlKjjgZfjgb7jgZnjgIJbL2phXVxuICogQG5vdGVcbiAqICAgW2VuXUZvciBBbmRyb2lkIDQuMyBhbmQgZWFybGllciwgYW5kIGlPUzYgYW5kIGVhcmxpZXIsIHdoZW4gdXNpbmcgbWl4ZWQgYWxpZ25tZW50IHdpdGggb25zLXJvdyBhbmQgb25zLWNvbHVtbiwgdGhleSBtYXkgbm90IGJlIGRpc3BsYXllZCBjb3JyZWN0bHkuIFlvdSBjYW4gdXNlIG9ubHkgb25lIGFsaWdubWVudC5bL2VuXVxuICogICBbamFdQW5kcm9pZCA0LjPku6XliY3jgIHjgoLjgZfjgY/jga9pT1MgNuS7peWJjeOBrk9T44Gu5aC05ZCI44CBb25zLXJvd+OBqG9ucy1jb2x1bW7jgpLntYTjgb/lkIjjgo/jgZvjgZ/loLTlkIjjgavmj4/nlLvjgYzltKnjgozjgovloLTlkIjjgYzjgYLjgorjgb7jgZnjgIJbL2phXVxuICogQGNvZGVwZW4gR2d1akMge3dpZGV9XG4gKiBAZ3VpZGUgdGhlbWluZy5odG1sIFtlbl1MYXlvdXRpbmcgZ3VpZGVbL2VuXVtqYV3jg6zjgqTjgqLjgqbjg4jmqZ/og71bL2phXVxuICogQHNlZWFsc28gb25zLXJvd1xuICogICBbZW5dVGhlIGA8b25zLXJvdz5gIGNvbXBvbmVudCBpcyB0aGUgcGFyZW50IG9mIGA8b25zLWNvbD5gLlsvZW5dXG4gKiAgIFtqYV1vbnMtcm9344Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXJvdz5cbiAqICAgPG9ucy1jb2wgd2lkdGg9XCI1MHB4XCI+PG9ucy1pY29uIGljb249XCJmYS10d2l0dGVyXCI+PC9vbnMtaWNvbj48L29ucy1jb2w+XG4gKiAgIDxvbnMtY29sPlRleHQ8L29ucy1jb2w+XG4gKiA8L29ucy1yb3c+XG4gKi9cblxuLyoqXG4gKiBAYXR0cmlidXRlIHZlcnRpY2FsLWFsaWduXG4gKiBAdHlwZSB7U3RyaW5nfVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1WZXJ0aWNhbCBhbGlnbm1lbnQgb2YgdGhlIGNvbHVtbi4gVmFsaWQgdmFsdWVzIGFyZSBcInRvcFwiLCBcImNlbnRlclwiLCBhbmQgXCJib3R0b21cIi5bL2VuXVxuICogICBbamFd57im44Gu6YWN572u44KS5oyH5a6a44GZ44KL44CCXCJ0b3BcIiwgXCJjZW50ZXJcIiwgXCJib3R0b21cIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKi9cblxuLyoqXG4gKiBAYXR0cmlidXRlIHdpZHRoXG4gKiBAdHlwZSB7U3RyaW5nfVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1UaGUgd2lkdGggb2YgdGhlIGNvbHVtbi4gVmFsaWQgdmFsdWVzIGFyZSBjc3Mgd2lkdGggdmFsdWVzIChcIjEwJVwiLCBcIjUwcHhcIikuWy9lbl1cbiAqICAgW2phXeOCq+ODqeODoOOBruaoquW5heOCkuaMh+WumuOBmeOCi+OAguODkeODvOOCu+ODs+ODiOOCguOBl+OBj+OBr+ODlOOCr+OCu+ODq+OBp+aMh+WumuOBl+OBvuOBme+8iDEwJeOChDUwcHjvvInjgIJbL2phXVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDb2xFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodGhpcy5nZXRBdHRyaWJ1dGUoJ3dpZHRoJykpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZVdpZHRoKCk7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnd2lkdGgnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICd3aWR0aCcpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZVdpZHRoKCk7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZVdpZHRoKCkge1xuICAgIGxldCB3aWR0aCA9IHRoaXMuZ2V0QXR0cmlidXRlKCd3aWR0aCcpO1xuICAgIGlmICghd2lkdGgpIHtcbiAgICAgIHN0eWxlci5jbGVhcih0aGlzLCAnZmxleCBtYXhXaWR0aCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aWR0aCA9IHdpZHRoLnRyaW0oKS5tYXRjaCgvXlxcZCskLykgPyB3aWR0aCArICclJyA6IHdpZHRoO1xuXG4gICAgICBzdHlsZXIodGhpcywge1xuICAgICAgICBmbGV4OiAnMCAwICcgKyB3aWR0aCxcbiAgICAgICAgbWF4V2lkdGg6IHdpZHRoXG4gICAgICB9KTtcbiAgICB9XG4gIH1cbn1cblxub25zRWxlbWVudHMuQ29sID0gQ29sRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWNvbCcsIENvbEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi8uLi9vbnMvYW5pbWl0JztcbmltcG9ydCBCYXNlQW5pbWF0b3IgZnJvbSAnLi4vLi4vb25zL2Jhc2UtYW5pbWF0b3InXG5cbmV4cG9ydCBjbGFzcyBEaWFsb2dBbmltYXRvciBleHRlbmRzIEJhc2VBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdsaW5lYXInLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC4yfSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBzaG93KGRpYWxvZywgZG9uZSkge1xuICAgIGRvbmUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZG9uZVxuICAgKi9cbiAgaGlkZShkaWFsb2csIGRvbmUpIHtcbiAgICBkb25lKCk7XG4gIH1cbn1cblxuLyoqXG4gKiBBbmRyb2lkIHN0eWxlIGFuaW1hdG9yIGZvciBkaWFsb2cuXG4gKi9cbmV4cG9ydCBjbGFzcyBBbmRyb2lkRGlhbG9nQW5pbWF0b3IgZXh0ZW5kcyBEaWFsb2dBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdlYXNlLWluLW91dCcsIGRlbGF5ID0gMCwgZHVyYXRpb24gPSAwLjN9ID0ge30pIHtcbiAgICBzdXBlcih7dGltaW5nLCBkZWxheSwgZHVyYXRpb259KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZGlhbG9nXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBzaG93KGRpYWxvZywgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrID8gY2FsbGJhY2sgOiBmdW5jdGlvbigpIHt9O1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fbWFzaywgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KHsgb3BhY2l0eTogMCB9LCB7IG9wYWNpdHk6IDEgfSksXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX2RpYWxvZywgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoLTUwJSwgLTYwJSwgMCknLCBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKScsIG9wYWNpdHk6IDEgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUoZGlhbG9nLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9tYXNrLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAxIH0sIHsgb3BhY2l0eTogMCB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fZGlhbG9nLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKScsIG9wYWNpdHk6IDEgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC01MCUsIC02MCUsIDApJywgb3BhY2l0eTogMCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBpT1Mgc3R5bGUgYW5pbWF0b3IgZm9yIGRpYWxvZy5cbiAqL1xuZXhwb3J0IGNsYXNzIElPU0RpYWxvZ0FuaW1hdG9yIGV4dGVuZHMgRGlhbG9nQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnZWFzZS1pbi1vdXQnLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC4yfSA9IHt9KSB7XG4gICAgc3VwZXIoe3RpbWluZywgZGVsYXksIGR1cmF0aW9ufSk7XG5cbiAgICB0aGlzLmJvZHlIZWlnaHQgPSBkb2N1bWVudC5ib2R5LmNsaWVudEhlaWdodDsgLy8gYXZvaWQgRm9yY2VkIFN5bmNocm9ub3VzIExheW91dFxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHNob3coZGlhbG9nLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9tYXNrLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAwIH0sIHsgb3BhY2l0eTogMSB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fZGlhbG9nLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgtNTAlLCAke3RoaXMuYm9keUhlaWdodCAvIDIuMCAtIDF9cHgsIDApYCB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoLTUwJSwgLTUwJSwgMCknIH1cbiAgICAgICAgKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZGlhbG9nXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBoaWRlKGRpYWxvZywgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrID8gY2FsbGJhY2sgOiBmdW5jdGlvbigpIHt9O1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fbWFzaywgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KHsgb3BhY2l0eTogMSB9LCB7IG9wYWNpdHk6IDAgfSksXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX2RpYWxvZywgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoLTUwJSwgLTUwJSwgMCknIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgtNTAlLCAke3RoaXMuYm9keUhlaWdodCAvIDIuMCAtIDF9cHgsIDApYCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBTbGlkZSBhbmltYXRvciBmb3IgZGlhbG9nLlxuICovXG5leHBvcnQgY2xhc3MgU2xpZGVEaWFsb2dBbmltYXRvciBleHRlbmRzIERpYWxvZ0FuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7dGltaW5nID0gJ2N1YmljLWJlemllciguMSwgLjcsIC40LCAxKScsIGRlbGF5ID0gMCwgZHVyYXRpb24gPSAwLjJ9ID0ge30pIHtcbiAgICBzdXBlcih7dGltaW5nLCBkZWxheSwgZHVyYXRpb259KTtcblxuICAgIHRoaXMuYm9keUhlaWdodCA9IGRvY3VtZW50LmJvZHkuY2xpZW50SGVpZ2h0OyAvLyBhdm9pZCBGb3JjZWQgU3luY2hyb25vdXMgTGF5b3V0XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgc2hvdyhkaWFsb2csIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjayA/IGNhbGxiYWNrIDogZnVuY3Rpb24oKSB7fTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX21hc2ssIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdCh7IG9wYWNpdHk6IDAgfSwgeyBvcGFjaXR5OiAxIH0pLFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9kaWFsb2csIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICAvLyBGSVhNRTogVGhpcyBzaG91bGQgYXZvaWQgRm9yY2VkIFN5bmNocm9ub3VzIExheW91dC4gT3RoZXJ3aXNlLCBmYWRlIGFuaW1hdGlvbiBvZiBtYXNrIHdpbGwgYmUgYnJva2VuLlxuICAgICAgICAgIHsgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoLTUwJSwgJHstICh0aGlzLmJvZHlIZWlnaHQgLyAyLjApICsgMSAtIGRpYWxvZy5fZGlhbG9nLmNsaWVudEhlaWdodH1weCwgMClgIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKScgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUoZGlhbG9nLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9tYXNrLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAxIH0sIHsgb3BhY2l0eTogMCB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fZGlhbG9nLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKScgfSxcbiAgICAgICAgICAvLyBGSVhNRTogVGhpcyBzaG91bGQgYXZvaWQgRm9yY2VkIFN5bmNocm9ub3VzIExheW91dC4gT3RoZXJ3aXNlLCBmYWRlIGFuaW1hdGlvbiBvZiBtYXNrIHdpbGwgYmUgYnJva2VuLlxuICAgICAgICAgIHsgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoLTUwJSwgJHstICh0aGlzLmJvZHlIZWlnaHQgLyAyLjApICsgMSAtIGRpYWxvZy5fZGlhbG9nLmNsaWVudEhlaWdodH1weCwgMClgIH1cbiAgICAgICAgKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uLy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uLy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQW5pbWF0b3JGYWN0b3J5IGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9hbmltYXRvci1mYWN0b3J5JztcbmltcG9ydCB7IERpYWxvZ0FuaW1hdG9yLCBJT1NEaWFsb2dBbmltYXRvciwgQW5kcm9pZERpYWxvZ0FuaW1hdG9yLCBTbGlkZURpYWxvZ0FuaW1hdG9yIH0gZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vLi4vb25zL3BsYXRmb3JtJztcbmltcG9ydCBCYXNlRGlhbG9nRWxlbWVudCBmcm9tICcuLi9iYXNlL2Jhc2UtZGlhbG9nJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBzY2hlbWUgPSB7XG4gICcuZGlhbG9nJzogJ2RpYWxvZy0tKicsXG4gICcuZGlhbG9nLWNvbnRhaW5lcic6ICdkaWFsb2ctY29udGFpbmVyLS0qJyxcbiAgJy5kaWFsb2ctbWFzayc6ICdkaWFsb2ctbWFzay0tKidcbn07XG5cbmNvbnN0IF9hbmltYXRvckRpY3QgPSB7XG4gICdkZWZhdWx0JzogKCkgPT4gcGxhdGZvcm0uaXNBbmRyb2lkKCkgPyBBbmRyb2lkRGlhbG9nQW5pbWF0b3IgOiBJT1NEaWFsb2dBbmltYXRvcixcbiAgJ3NsaWRlJzogU2xpZGVEaWFsb2dBbmltYXRvcixcbiAgJ25vbmUnOiBEaWFsb2dBbmltYXRvclxufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtZGlhbG9nXG4gKiBAY2F0ZWdvcnkgZGlhbG9nXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIERpYWxvZyB0aGF0IGlzIGRpc3BsYXllZCBvbiB0b3Agb2YgY3VycmVudCBzY3JlZW4uIEFzIG9wcG9zZWQgdG8gdGhlIGA8b25zLWFsZXJ0LWRpYWxvZz5gIGVsZW1lbnQsIHRoaXMgY29tcG9uZW50IGNhbiBjb250YWluIGFueSBraW5kIG9mIGNvbnRlbnQuXG4gKlxuICogICAgIFRvIHVzZSB0aGUgZWxlbWVudCBpdCBjYW4gZWl0aGVyIGJlIGF0dGFjaGVkIGRpcmVjdGx5IHRvIHRoZSBgPGJvZHk+YCBlbGVtZW50IG9yIGR5bmFtaWNhbGx5IGNyZWF0ZWQgZnJvbSBhIHRlbXBsYXRlIHVzaW5nIHRoZSBgb25zLmNyZWF0ZURpYWxvZyh0ZW1wbGF0ZSlgIHV0aWxpdHkgZnVuY3Rpb24gYW5kIHRoZSBgPHRlbXBsYXRlPmAgdGFnLlxuICpcbiAqICAgICBUaGUgZGlhbG9nIGlzIHVzZWZ1bCBmb3IgZGlzcGxheWluZyBtZW51cywgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBvciB0byBhc2sgdGhlIHVzZXIgdG8gbWFrZSBhIGRlY2lzaW9uLlxuICpcbiAqICAgICBJdCB3aWxsIGF1dG9tYXRpY2FsbHkgYmUgZGlzcGxheWVkIGFzIE1hdGVyaWFsIERlc2lnbiB3aGVuIHJ1bm5pbmcgb24gYW4gQW5kcm9pZCBkZXZpY2UuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1EaXNwbGF5IGEgTWF0ZXJpYWwgRGVzaWduIGRpYWxvZy5bL2VuXVxuICogICBbamFd44Oe44OG44Oq44Ki44Or44OH44K244Kk44Oz44Gu44OA44Kk44Ki44Ot44Kw44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBjb2RlcGVuIHp4eGFHYVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2RpYWxvZ1xuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNtb2RpZmllcnMgW2VuXU1vcmUgZGV0YWlscyBhYm91dCB0aGUgYG1vZGlmaWVyYCBhdHRyaWJ1dGVbL2VuXVtqYV1tb2RpZmllcuWxnuaAp+OBruS9v+OBhOaWuVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtYWxlcnQtZGlhbG9nXG4gKiAgIFtlbl1gPG9ucy1hbGVydC1kaWFsb2c+YCBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLWFsZXJ0LWRpYWxvZ+OCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtcG9wb3ZlclxuICogICBbZW5dYDxvbnMtcG9wb3Zlcj5gIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtcG9wb3ZlcuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtbW9kYWxcbiAqICAgW2VuXWA8b25zLW1vZGFsPmAgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1tb2RhbOOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1kaWFsb2cgaWQ9XCJkaWFsb2dcIj5cbiAqICAgPHA+VGhpcyBpcyBhIGRpYWxvZyE8L3A+XG4gKiA8L29ucy1kaWFsb2c+XG4gKlxuICogPHNjcmlwdD5cbiAqICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RpYWxvZycpLnNob3coKTtcbiAqIDwvc2NyaXB0PlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBEaWFsb2dFbGVtZW50IGV4dGVuZHMgQmFzZURpYWxvZ0VsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlc2hvd1xuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYmVmb3JlIHRoZSBkaWFsb2cgaXMgZGlzcGxheWVkLlsvZW5dXG4gICAqIFtqYV3jg4DjgqTjgqLjg63jgrDjgYzooajnpLrjgZXjgozjgovnm7TliY3jgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuZGlhbG9nXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUV4ZWN1dGUgdGhpcyBmdW5jdGlvbiB0byBzdG9wIHRoZSBkaWFsb2cgZnJvbSBiZWluZyBzaG93bi5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7plqLmlbDjgpLlrp/ooYzjgZnjgovjgajjgIHjg4DjgqTjgqLjg63jgrDjga7ooajnpLrjgYzjgq3jg6Pjg7Pjgrvjg6vjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHBvc3RzaG93XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBbZW5dRmlyZWQganVzdCBhZnRlciB0aGUgZGlhbG9nIGlzIGRpc3BsYXllZC5bL2VuXVxuICAgKiBbamFd44OA44Kk44Ki44Ot44Kw44GM6KGo56S644GV44KM44Gf55u05b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmRpYWxvZ1xuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlaGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYmVmb3JlIHRoZSBkaWFsb2cgaXMgaGlkZGVuLlsvZW5dXG4gICAqIFtqYV3jg4DjgqTjgqLjg63jgrDjgYzpmqDjgozjgovnm7TliY3jgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuZGlhbG9nXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUV4ZWN1dGUgdGhpcyBmdW5jdGlvbiB0byBzdG9wIHRoZSBkaWFsb2cgZnJvbSBiZWluZyBoaWRkZW4uWy9lbl1cbiAgICogICBbamFd44GT44Gu6Zai5pWw44KS5a6f6KGM44GZ44KL44Go44CB44OA44Kk44Ki44Ot44Kw44Gu6Z2e6KGo56S644GM44Kt44Oj44Oz44K744Or44GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBwb3N0aGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIGRpYWxvZyBpcyBoaWRkZW4uWy9lbl1cbiAgICogW2phXeODgOOCpOOCouODreOCsOOBjOmaoOOCjOOBn+W+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5kaWFsb2dcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgZGlhbG9nLlsvZW5dXG4gICAqICBbamFd44OA44Kk44Ki44Ot44Kw44Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgY2FuY2VsYWJsZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGRpYWxvZyBjYW4gYmUgY2xvc2VkIGJ5IHRhcHBpbmcgdGhlIGJhY2tncm91bmQgb3IgYnkgcHJlc3NpbmcgdGhlIGJhY2sgYnV0dG9uIG9uIEFuZHJvaWQgZGV2aWNlcy5bL2VuXVxuICAgKiAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpc2FibGVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHNldCB0aGUgZGlhbG9nIGlzIGRpc2FibGVkLlsvZW5dXG4gICAqICBbamFd44GT44Gu5bGe5oCn44GM44GC44KL5pmC44CB44OA44Kk44Ki44Ot44Kw44GvZGlzYWJsZWTnirbmhYvjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhbmltYXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgZGVmYXVsdFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgYW5pbWF0aW9uIHVzZWQgd2hlbiBzaG93aW5nIGFuZCBoaWRpbmcgdGhlIGRpYWxvZy4gQ2FuIGJlIGVpdGhlciBgXCJub25lXCJgIG9yIGBcImRlZmF1bHRcImAuWy9lbl1cbiAgICogIFtqYV3jg4DjgqTjgqLjg63jgrDjgpLooajnpLrjgZnjgovpmpvjga7jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcIm5vbmVcIuOCguOBl+OBj+OBr1wiZGVmYXVsdFwi44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uLW9wdGlvbnNcbiAgICogQHR5cGUge0V4cHJlc3Npb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCB0aW1pbmcgYW5kIGRlbGF5IHdpdGggYW4gb2JqZWN0IGxpdGVyYWwuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCB0aW1pbmcsIGRlbGF544KS44Kq44OW44K444Kn44Kv44OI44Oq44OG44Op44Or44Gn5oyH5a6a44GX44G+44GZ44CCZS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAxLCB0aW1pbmc6ICdlYXNlLWluJ31gWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbWFzay1jb2xvclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCByZ2JhKDAsIDAsIDAsIDAuMilcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dQ29sb3Igb2YgdGhlIGJhY2tncm91bmQgbWFzay4gRGVmYXVsdCBpcyBgXCJyZ2JhKDAsIDAsIDAsIDAuMilcImAuWy9lbl1cbiAgICogIFtqYV3og4zmma/jga7jg57jgrnjgq/jga7oibLjgpLmjIflrprjgZfjgb7jgZnjgIJcInJnYmEoMCwgMCwgMCwgMC4yKVwi44GM44OH44OV44Kp44Or44OI5YCk44Gn44GZ44CCWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl9jb21waWxlKCkpO1xuICB9XG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgcmV0dXJuIHNjaGVtZTtcbiAgfVxuXG4gIGdldCBfbWFzaygpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJy5kaWFsb2ctbWFzaycpO1xuICB9XG5cbiAgZ2V0IF9kaWFsb2coKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICcuZGlhbG9nJyk7XG4gIH1cblxuICBfdXBkYXRlQW5pbWF0b3JGYWN0b3J5KCkge1xuICAgIHJldHVybiBuZXcgQW5pbWF0b3JGYWN0b3J5KHtcbiAgICAgIGFuaW1hdG9yczogX2FuaW1hdG9yRGljdCxcbiAgICAgIGJhc2VDbGFzczogRGlhbG9nQW5pbWF0b3IsXG4gICAgICBiYXNlQ2xhc3NOYW1lOiAnRGlhbG9nQW5pbWF0b3InLFxuICAgICAgZGVmYXVsdEFuaW1hdGlvbjogdGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpXG4gICAgfSk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICB0aGlzLnN0eWxlLnpJbmRleCA9IDEwMDAxO1xuXG4gICAgLyogRXhwZWN0ZWQgcmVzdWx0OlxuICAgICAqICAgPG9ucy1kaWFsb2c+XG4gICAgICogICAgIDxkaXYgY2xhc3M9XCJkaWFsb2ctbWFza1wiPjwvZGl2PlxuICAgICAqICAgICA8ZGl2IGNsYXNzPVwiZGlhbG9nXCI+XG4gICAgICogICAgICAgPGRpdiBjbGFzcz1cImRpYWxvZy1jb250YWluZXJcIj4uLi48L2Rpdj5cbiAgICAgKiAgICAgPC9kaXY+XG4gICAgICogICA8L29ucy1kaWFsb2c+XG4gICAgICovXG5cbiAgICBpZiAoIXRoaXMuX2RpYWxvZykge1xuICAgICAgY29uc3QgZGlhbG9nID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICBkaWFsb2cuY2xhc3NMaXN0LmFkZCgnZGlhbG9nJyk7XG5cbiAgICAgIGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoJ2RpYWxvZy1jb250YWluZXInKTtcbiAgICAgIHdoaWxlICh0aGlzLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKHRoaXMuZmlyc3RDaGlsZCk7XG4gICAgICB9XG4gICAgICBkaWFsb2cuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcblxuICAgICAgdGhpcy5hcHBlbmRDaGlsZChkaWFsb2cpO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5fbWFzaykge1xuICAgICAgY29uc3QgbWFzayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgbWFzay5jbGFzc0xpc3QuYWRkKCdkaWFsb2ctbWFzaycpO1xuICAgICAgdGhpcy5pbnNlcnRCZWZvcmUobWFzaywgdGhpcy5maXJzdENoaWxkKTtcbiAgICB9XG5cbiAgICB0aGlzLl9kaWFsb2cuc3R5bGUuekluZGV4ID0gMjAwMDE7XG4gICAgdGhpcy5fbWFzay5zdHlsZS56SW5kZXggPSAyMDAwMDtcblxuICAgIHRoaXMuc2V0QXR0cmlidXRlKCdzdGF0dXMtYmFyLWZpbGwnLCAnJyk7XG5cbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHRoaXMuX3NjaGVtZSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9uRGV2aWNlQmFja0J1dHRvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQmFjay1idXR0b24gaGFuZGxlci5bL2VuXVxuICAgKiAgIFtqYV3jg5Djg4Pjgq/jg5zjgr/jg7Pjg4/jg7Pjg4njg6njgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQG1ldGhvZCBzaG93XG4gICAqIEBzaWduYXR1cmUgc2hvdyhbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcIm5vbmVcImAgYW5kIGBcInNsaWRlXCJgLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAglwibm9uZVwiLCBcInNsaWRlXCLjga7jgYTjgZrjgozjgYvjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWAgWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXVRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIGFmdGVyIHRoZSBkaWFsb2cgaGFzIGJlZW4gcmV2ZWFsZWQuWy9lbl1cbiAgICogICBbamFd44OA44Kk44Ki44Ot44Kw44GM6KGo56S644GV44KM57WC44KP44Gj44Gf5b6M44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU2hvdyB0aGUgZGlhbG9nLlsvZW5dXG4gICAqICBbamFd44OA44Kk44Ki44Ot44Kw44KS6ZaL44GN44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX0gUmVzb2x2ZXMgdG8gdGhlIGRpc3BsYXllZCBlbGVtZW50LlxuICAgKi9cblxuICAvKipcbiAgICogQG1ldGhvZCBoaWRlXG4gICAqIEBzaWduYXR1cmUgaGlkZShbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcIm5vbmVcImAgYW5kIGBcInNsaWRlXCJgLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAglwibm9uZVwiLCBcInNsaWRlXCLjga7jgYTjgZrjgozjgYvjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWBbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogICBbZW5dVGhpcyBmdW5jdGlvbnMgaXMgY2FsbGVkIGFmdGVyIHRoZSBkaWFsb2cgaGFzIGJlZW4gaGlkZGVuLlsvZW5dXG4gICAqICAgW2phXeODgOOCpOOCouODreOCsOOBjOmaoOOCjOOBn+W+jOOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1IaWRlIHRoZSBkaWFsb2cuWy9lbl1cbiAgICogICBbamFd44OA44Kk44Ki44Ot44Kw44KS6ZaJ44GY44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGhpZGRlbiBlbGVtZW50Wy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB2aXNpYmxlXG4gICAqIEByZWFkb25seVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGRpYWxvZyBpcyB2aXNpYmxlIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3opoHntKDjgYzopovjgYjjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZGlhbG9nIGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGNhbmNlbGFibGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBkaWFsb2cgaXMgY2FuY2VsYWJsZSBvciBub3QuIEEgY2FuY2VsYWJsZSBkaWFsb2cgY2FuIGJlIGNsb3NlZCBieSB0YXBwaW5nIHRoZSBiYWNrZ3JvdW5kIG9yIGJ5IHByZXNzaW5nIHRoZSBiYWNrIGJ1dHRvbiBvbiBBbmRyb2lkIGRldmljZXMuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7RGlhbG9nQW5pbWF0b3J9IEFuaW1hdG9yXG4gICAqL1xuICBzdGF0aWMgcmVnaXN0ZXJBbmltYXRvcihuYW1lLCBBbmltYXRvcikge1xuICAgIGlmICghKEFuaW1hdG9yLnByb3RvdHlwZSBpbnN0YW5jZW9mIERpYWxvZ0FuaW1hdG9yKSkge1xuICAgICAgdXRpbC50aHJvd0FuaW1hdG9yKCdEaWFsb2cnKTtcbiAgICB9XG4gICAgX2FuaW1hdG9yRGljdFtuYW1lXSA9IEFuaW1hdG9yO1xuICB9XG5cbiAgc3RhdGljIGdldCBhbmltYXRvcnMoKSB7XG4gICAgcmV0dXJuIF9hbmltYXRvckRpY3Q7XG4gIH1cblxuICBzdGF0aWMgZ2V0IERpYWxvZ0FuaW1hdG9yKCkge1xuICAgIHJldHVybiBEaWFsb2dBbmltYXRvcjtcbiAgfVxufVxuXG5vbnNFbGVtZW50cy5EaWFsb2cgPSBEaWFsb2dFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtZGlhbG9nJywgRGlhbG9nRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgc3R5bGVyIGZyb20gJy4uL29ucy9zdHlsZXInO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IGRlZmF1bHRDbGFzc05hbWUgPSAnZmFiJztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ2ZhYi0tKicsXG4gICcuZmFiX19pY29uJzogJ2ZhYi0tKl9faWNvbidcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWZhYlxuICogQGNhdGVnb3J5IGZvcm1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgVGhlIEZsb2F0aW5nIGFjdGlvbiBidXR0b24gaXMgYSBjaXJjdWxhciBidXR0b24gZGVmaW5lZCBpbiB0aGUgW01hdGVyaWFsIERlc2lnbiBzcGVjaWZpY2F0aW9uXShodHRwczovL3d3dy5nb29nbGUuY29tL2Rlc2lnbi9zcGVjL2NvbXBvbmVudHMvYnV0dG9ucy1mbG9hdGluZy1hY3Rpb24tYnV0dG9uLmh0bWwpLiBUaGV5IGFyZSBvZnRlbiB1c2VkIHRvIHByb21vdGUgdGhlIHByaW1hcnkgYWN0aW9uIG9mIHRoZSBhcHAuXG4gKlxuICogICAgIEl0IGNhbiBiZSBkaXNwbGF5ZWQgZWl0aGVyIGFzIGFuIGlubGluZSBlbGVtZW50IG9yIGluIG9uZSBvZiB0aGUgY29ybmVycy4gTm9ybWFsbHkgaXQgd2lsbCBiZSBwb3NpdGlvbmVkIGluIHRoZSBsb3dlciByaWdodCBjb3JuZXIgb2YgdGhlIHNjcmVlbi5cbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvZmFiXG4gKiBAbW9kaWZpZXIgbWluaVxuICogICBbZW5dTWFrZXMgdGhlIGBvbnMtZmFiYCBzbWFsbGVyLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNjcm9zcy1wbGF0Zm9ybS1zdHlsaW5nLWF1dG9zdHlsaW5nIFtlbl1JbmZvcm1hdGlvbiBhYm91dCBjcm9zcyBwbGF0Zm9ybSBzdHlsaW5nWy9lbl1bamFdSW5mb3JtYXRpb24gYWJvdXQgY3Jvc3MgcGxhdGZvcm0gc3R5bGluZ1svamFdXG4gKiBAc2VlYWxzbyBvbnMtc3BlZWQtZGlhbFxuICogICBbZW5dVGhlIGA8b25zLXNwZWVkLWRpYWw+YCBjb21wb25lbnQgaXMgYSBGbG9hdGluZyBhY3Rpb24gYnV0dG9uIHRoYXQgZGlzcGxheXMgYSBtZW51IHdoZW4gdGFwcGVkLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBGYWJFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBidXR0b24uWy9lbl1cbiAgICogIFtqYV3jg5zjgr/jg7Pjga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSByaXBwbGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgZGVmaW5lZCwgdGhlIGJ1dHRvbiB3aWxsIGhhdmUgYSByaXBwbGUgZWZmZWN0IHdoZW4gdGFwcGVkLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgcG9zaXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIHBvc2l0aW9uIG9mIHRoZSBidXR0b24uIFNob3VsZCBiZSBhIHN0cmluZyBsaWtlIGBcImJvdHRvbSByaWdodFwiYCBvciBgXCJ0b3AgbGVmdFwiYC4gSWYgdGhpcyBhdHRyaWJ1dGUgaXMgbm90IGRlZmluZWQgaXQgd2lsbCBiZSBkaXNwbGF5ZWQgYXMgYW4gaW5saW5lIGVsZW1lbnQuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXNhYmxlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU3BlY2lmeSBpZiBidXR0b24gc2hvdWxkIGJlIGRpc2FibGVkLlsvZW5dXG4gICAqICAgW2phXeODnOOCv+ODs+OCkueEoeWKueWMluOBmeOCi+WgtOWQiOOBr+aMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICAvLyBUaGUgZm9sbG93aW5nIHN0YXRlbWVudHMgY2FuIGJlIGV4ZWN1dGVkIGJlZm9yZSBjb250ZW50UmVhZHlcbiAgICAvLyBzaW5jZSB0aGVzZSBkbyBub3QgYWNjZXNzIHRoZSBjaGlsZHJlblxuICAgIHRoaXMuX2hpZGUoKTtcbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fY29tcGlsZSgpO1xuICAgIH0pO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG5cbiAgICBpZiAoIXV0aWwuZmluZENoaWxkKHRoaXMsICcuZmFiX19pY29uJykpIHtcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XG4gICAgICBjb250ZW50LmNsYXNzTGlzdC5hZGQoJ2ZhYl9faWNvbicpO1xuXG4gICAgICB1dGlsLmFycmF5RnJvbSh0aGlzLmNoaWxkTm9kZXMpLmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICAgIGlmICghZWxlbWVudC50YWdOYW1lIHx8IGVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpICE9PSAnb25zLXJpcHBsZScpIHtcbiAgICAgICAgICBjb250ZW50LmFwcGVuZENoaWxkKGVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHRoaXMuYXBwZW5kQ2hpbGQoY29udGVudCk7XG4gICAgfVxuXG4gICAgdGhpcy5fdXBkYXRlUmlwcGxlKCk7XG5cbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHNjaGVtZSk7XG5cbiAgICB0aGlzLl91cGRhdGVQb3NpdGlvbigpO1xuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgc2V0SW1tZWRpYXRlKCgpID0+IHRoaXMuX3Nob3coKSk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllcicsICdyaXBwbGUnLCAncG9zaXRpb24nLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdyaXBwbGUnOlxuICAgICAgICB0aGlzLl91cGRhdGVSaXBwbGUoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdwb3NpdGlvbic6XG4gICAgICAgIHRoaXMuX3VwZGF0ZVBvc2l0aW9uKCk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIF9zaG93KCkge1xuICAgIGlmICghdGhpcy5fbWFudWFsbHlIaWRkZW4pIHsgLy8gaWYgdXNlciBoYXMgbm90IGNhbGxlZCBvbnMtZmFiLmhpZGUoKVxuICAgICAgdGhpcy5fdG9nZ2xlKHRydWUpO1xuICAgIH1cbiAgfVxuXG4gIF9oaWRlKCkge1xuICAgIHNldEltbWVkaWF0ZSgoKSA9PiB0aGlzLl90b2dnbGUoZmFsc2UpKTtcbiAgfVxuXG4gIF91cGRhdGVSaXBwbGUoKSB7XG4gICAgdXRpbC51cGRhdGVSaXBwbGUodGhpcyk7XG4gIH1cblxuICBfdXBkYXRlUG9zaXRpb24oKSB7XG4gICAgY29uc3QgcG9zaXRpb24gPSB0aGlzLmdldEF0dHJpYnV0ZSgncG9zaXRpb24nKTtcbiAgICB0aGlzLmNsYXNzTGlzdC5yZW1vdmUoXG4gICAgICAnZmFiLS10b3BfX2xlZnQnLFxuICAgICAgJ2ZhYi0tYm90dG9tX19yaWdodCcsXG4gICAgICAnZmFiLS1ib3R0b21fX2xlZnQnLFxuICAgICAgJ2ZhYi0tdG9wX19yaWdodCcsXG4gICAgICAnZmFiLS10b3BfX2NlbnRlcicsXG4gICAgICAnZmFiLS1ib3R0b21fX2NlbnRlcicpO1xuICAgIHN3aXRjaCAocG9zaXRpb24pIHtcbiAgICAgIGNhc2UgJ3RvcCByaWdodCc6XG4gICAgICBjYXNlICdyaWdodCB0b3AnOlxuICAgICAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2ZhYi0tdG9wX19yaWdodCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3RvcCBsZWZ0JzpcbiAgICAgIGNhc2UgJ2xlZnQgdG9wJzpcbiAgICAgICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdmYWItLXRvcF9fbGVmdCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2JvdHRvbSByaWdodCc6XG4gICAgICBjYXNlICdyaWdodCBib3R0b20nOlxuICAgICAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2ZhYi0tYm90dG9tX19yaWdodCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2JvdHRvbSBsZWZ0JzpcbiAgICAgIGNhc2UgJ2xlZnQgYm90dG9tJzpcbiAgICAgICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdmYWItLWJvdHRvbV9fbGVmdCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2NlbnRlciB0b3AnOlxuICAgICAgY2FzZSAndG9wIGNlbnRlcic6XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnZmFiLS10b3BfX2NlbnRlcicpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2NlbnRlciBib3R0b20nOlxuICAgICAgY2FzZSAnYm90dG9tIGNlbnRlcic6XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnZmFiLS1ib3R0b21fX2NlbnRlcicpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHNob3dcbiAgICogQHNpZ25hdHVyZSBzaG93KClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU2hvdyB0aGUgZmxvYXRpbmcgYWN0aW9uIGJ1dHRvbi5bL2VuXVxuICAgKiAgW2phXVsvamFdXG4gICAqL1xuICBzaG93KCkge1xuICAgIHRoaXMudG9nZ2xlKHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaGlkZVxuICAgKiBAc2lnbmF0dXJlIGhpZGUoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1IaWRlIHRoZSBmbG9hdGluZyBhY3Rpb24gYnV0dG9uLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG4gIGhpZGUoKSB7XG4gICAgdGhpcy50b2dnbGUoZmFsc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgdG9nZ2xlXG4gICAqIEBzaWduYXR1cmUgdG9nZ2xlKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRvZ2dsZSB0aGUgdmlzaWJpbGl0eSBvZiB0aGUgYnV0dG9uLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICB0b2dnbGUoYWN0aW9uID0gIXRoaXMudmlzaWJsZSkge1xuICAgIHRoaXMuX21hbnVhbGx5SGlkZGVuID0gIWFjdGlvbjtcbiAgICB0aGlzLl90b2dnbGUoYWN0aW9uKTtcbiAgfVxuXG4gIF90b2dnbGUoYWN0aW9uID0gIXRoaXMudmlzaWJsZSkge1xuICAgIGNvbnN0IGlzQm90dG9tID0gKHRoaXMuZ2V0QXR0cmlidXRlKCdwb3NpdGlvbicpIHx8ICcnKS5pbmRleE9mKCdib3R0b20nKSA+PSAwO1xuICAgIGNvbnN0IHRyYW5zbGF0ZSA9IGlzQm90dG9tID8gYHRyYW5zbGF0ZTNkKDBweCwgLSR7dXRpbC5nbG9iYWxzLmZhYk9mZnNldCB8fCAwfXB4LCAwcHgpYCA6ICcnO1xuXG4gICAgc3R5bGVyKHRoaXMsIHsgdHJhbnNmb3JtOiBgJHt0cmFuc2xhdGV9IHNjYWxlKCR7TnVtYmVyKGFjdGlvbil9KWAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZWxlbWVudCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG4gIHNldCBkaXNhYmxlZCh2YWx1ZSkge1xuICAgIHJldHVybiB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnZGlzYWJsZWQnLCB2YWx1ZSk7XG4gIH1cblxuICBnZXQgZGlzYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdkaXNhYmxlZCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB2aXNpYmxlXG4gICAqIEByZWFkb25seVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgdmlzaWJsZSBvciBub3QuWy9lbl1cbiAgICogICBbamFd6KaB57Sg44GM6KaL44GI44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG4gIGdldCB2aXNpYmxlKCkge1xuICAgIHJldHVybiB0aGlzLnN0eWxlLnRyYW5zZm9ybS5pbmRleE9mKCdzY2FsZSgwKScpID09PSAtMSAmJiB0aGlzLnN0eWxlLmRpc3BsYXkgIT09ICdub25lJztcbiAgfVxufVxuXG5vbnNFbGVtZW50cy5GYWIgPSBGYWJFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtZmFiJywgRmFiRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBHZXN0dXJlRGV0ZWN0b3IgZnJvbSAnLi4vb25zL2dlc3R1cmUtZGV0ZWN0b3InO1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1nZXN0dXJlLWRldGVjdG9yXG4gKiBAY2F0ZWdvcnkgZ2VzdHVyZVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBDb21wb25lbnQgdG8gZGV0ZWN0IGZpbmdlciBnZXN0dXJlcyB3aXRoaW4gdGhlIHdyYXBwZWQgZWxlbWVudC4gRm9sbG93aW5nIGdlc3R1cmVzIGFyZSBzdXBwb3J0ZWQ6XG4gKiAgICAgLSBEcmFnIGdlc3R1cmVzOiBgZHJhZ2AsIGBkcmFnbGVmdGAsIGBkcmFncmlnaHRgLCBgZHJhZ3VwYCwgYGRyYWdkb3duYFxuICogICAgIC0gSG9sZCBnZXN0dXJlczogYGhvbGRgLCBgcmVsZWFzZWBcbiAqICAgICAtIFN3aXBlIGdlc3R1cmVzOiBgc3dpcGVgLCBgc3dpcGVsZWZ0YCwgYHN3aXBlcmlnaHRgLCBgc3dpcGV1cGAsIGBzd2lwZWRvd25gXG4gKiAgICAgLSBUYXAgZ2VzdHVyZXM6IGB0YXBgLCBgZG91YmxldGFwYFxuICogICAgIC0gUGluY2ggZ2VzdHVyZXM6IGBwaW5jaGAsIGBwaW5jaGluYCwgYHBpbmNob3V0YFxuICogICAgIC0gT3RoZXIgZ2VzdHVyZXM6IGB0b3VjaGAsIGB0cmFuc2Zvcm1gLCBgcm90YXRlYFxuICogICBbL2VuXVxuICogICBbamFd6KaB57Sg5YaF44Gu44K444Kn44K544OB44Oj44O85pON5L2c44KS5qSc55+l44GX44G+44GZ44CC6Kmz44GX44GP44Gv44Ks44Kk44OJ44KS5Y+C54Wn44GX44Gm44GP44Gg44GV44GE44CCWy9qYV1cbiAqIEBndWlkZSBmZWF0dXJlcy5odG1sI2dlc3R1cmUtZGV0ZWN0aW9uXG4gKiAgIFtlbl1EZXRlY3RpbmcgZmluZ2VyIGdlc3R1cmVzWy9lbl1cbiAqICAgW2phXeOCuOOCp+OCueODgeODo+ODvOaTjeS9nOOBruaknOefpVsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1nZXN0dXJlLWRldGVjdG9yPlxuICogICA8ZGl2IGlkPVwiZGV0ZWN0LWFyZWFcIiBzdHlsZT1cIndpZHRoOiAxMDBweDsgaGVpZ2h0OiAxMDBweDtcIj5cbiAqICAgICBTd2lwZSBIZXJlXG4gKiAgIDwvZGl2PlxuICogPC9vbnMtZ2VzdHVyZS1kZXRlY3Rvcj5cbiAqXG4gKiA8c2NyaXB0PlxuICogICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdzd2lwZWxlZnQnLCBmdW5jdGlvbihldmVudCkge1xuICogICAgIGlmIChldmVudC50YXJnZXQubWF0Y2hlcygnI2RldGVjdC1hcmVhJykpIHtcbiAqICAgICAgIGNvbnNvbGUubG9nKCdTd2lwZSBsZWZ0IGlzIGRldGVjdGVkLicpO1xuICogICAgIH1cbiAqICAgfSk7XG4gKiA8L3NjcmlwdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgR2VzdHVyZURldGVjdG9yRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvciA9IG5ldyBHZXN0dXJlRGV0ZWN0b3IodGhpcywgeyBwYXNzaXZlOiB0cnVlIH0pO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLkdlc3R1cmVEZXRlY3RvciA9IEdlc3R1cmVEZXRlY3RvckVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1nZXN0dXJlLWRldGVjdG9yJywgR2VzdHVyZURldGVjdG9yRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcblxubGV0IGF1dG9QcmVmaXggPSAnZmEnOyAvLyBGSVhNRTogVG8gYmUgcmVtb3ZlZCBpbiB2M1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1pY29uXG4gKiBAY2F0ZWdvcnkgdmlzdWFsXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIERpc3BsYXlzIGFuIGljb24uIFRoZSBmb2xsb3dpbmcgaWNvbiBzdWl0ZXMgYXJlIGF2YWlsYWJsZTpcbiAqXG4gKiAgICAgKiBbRm9udCBBd2Vzb21lXShodHRwczovL2ZvcnRhd2Vzb21lLmdpdGh1Yi5pby9Gb250LUF3ZXNvbWUvKVxuICogICAgICogW0lvbmljb25zXShodHRwOi8vaW9uaWNvbnMuY29tLylcbiAqICAgICAqIFtNYXRlcmlhbCBEZXNpZ24gSWNvbmljIEZvbnRdKGh0dHA6Ly96YXZvbG9rbG9tLmdpdGh1Yi5pby9tYXRlcmlhbC1kZXNpZ24taWNvbmljLWZvbnQvKVxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIHhBaHZnXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvaWNvblxuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNjcm9zcy1wbGF0Zm9ybS1zdHlsaW5nLWF1dG9zdHlsaW5nIFtlbl1JbmZvcm1hdGlvbiBhYm91dCBjcm9zcyBwbGF0Zm9ybSBzdHlsaW5nWy9lbl1bamFdWy9qYV1cbiAqIEBndWlkZSBhcHBzaXplLmh0bWwjcmVtb3ZpbmctaWNvbi1wYWNrcyBbZW5dUmVtb3ZpbmcgaWNvbiBwYWNrcy5bL2VuXVtqYV1bL2phXVxuICogQGd1aWRlIGZhcS5odG1sI2hvdy1jYW4taS11c2UtY3VzdG9tLWljb24tcGFja3MgW2VuXUFkZGluZyBjdXN0b20gaWNvbiBwYWNrcy5bL2VuXVtqYV1bL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtaWNvblxuICogICBpY29uPVwibWQtY2FyXCJcbiAqICAgc2l6ZT1cIjIwcHhcIlxuICogICBzdHlsZT1cImNvbG9yOiByZWRcIj5cbiAqIDwvb25zLWljb24+XG4gKlxuICogPG9ucy1idXR0b24+XG4gKiAgIDxvbnMtaWNvbiBpY29uPVwibWQtY2FyXCI+PC9vbnMtaWNvbj5cbiAqICAgQ2FyXG4gKiA8L29ucy1idXR0b24+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEljb25FbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGljb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgVGhlIGljb24gbmFtZS4gYFwibWQtXCJgIHByZWZpeCBmb3IgTWF0ZXJpYWwgSWNvbnMsIGBcImZhLVwiYCBmb3IgRm9udCBBd2Vzb21lIGFuZCBgXCJpb24tXCJgIHByZWZpeCBmb3IgSW9uaWNvbnMuXG4gICAqXG4gICAqICAgICBTZWUgYWxsIGF2YWlsYWJsZSBpY29ucyBvbiB0aGUgZWxlbWVudCBkZXNjcmlwdGlvbiAoYXQgdGhlIHRvcCkuXG4gICAqXG4gICAqICAgICBJY29ucyBjYW4gYWxzbyBiZSBzdHlsZWQgYmFzZWQgb24gbW9kaWZpZXIgcHJlc2VuY2UuIEFkZCBjb21tYS1zZXBhcmF0ZWQgaWNvbnMgd2l0aCBgXCJtb2RpZmllck5hbWU6XCJgIHByZWZpeC5cbiAgICpcbiAgICogICAgIFRoZSBjb2RlIGA8b25zLWljb24gaWNvbj1cImlvbi1lZGl0LCBtYXRlcmlhbDptZC1lZGl0XCI+PC9vbnMtaWNvbj5gIHdpbGwgZGlzcGxheSBgXCJtZC1lZGl0XCJgIGZvciBNYXRlcmlhbCBEZXNpZ24gYW5kIGBcImlvbi1lZGl0XCJgIGFzIHRoZSBkZWZhdWx0IGljb24uXG4gICAqXG4gICAqICAgICBgZmEtYCBwcmVmaXggaXMgYWRkZWQgYXV0b21hdGljYWxseSBpZiBub25lIGlzIHByb3ZpZGVkLiBDaGVjayBbU2VlIGFsc29dKCNzZWVhbHNvKSBzZWN0aW9uIGZvciBtb3JlIGluZm9ybWF0aW9uLlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHNpemVcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgVGhlIHNpemVzIG9mIHRoZSBpY29uLiBWYWxpZCB2YWx1ZXMgYXJlIGxnLCAyeCwgM3gsIDR4LCA1eCwgb3IgaW4gdGhlIHNpemUgaW4gcGl4ZWxzLlxuICAgKiAgICAgSWNvbnMgY2FuIGFsc28gYmUgc3R5bGVkIGJhc2VkIG9uIG1vZGlmaWVyIHByZXNlbmNlLiBBZGQgY29tbWEtc2VwYXJhdGVkIGljb25zIHdpdGggYFwibW9kaWZpZXJOYW1lOlwiYCBwcmVmaXguXG4gICAqXG4gICAqICAgICBUaGUgY29kZTpcbiAgICpcbiAgICogICAgIGBgYFxuICAgKiAgICAgPG9ucy1pY29uXG4gICAqICAgICAgIGljb249XCJpb24tZWRpdFwiXG4gICAqICAgICAgIHNpemU9XCIzMnB4LCBtYXRlcmlhbDoyNHB4XCI+XG4gICAqICAgICA8L29ucy1pY29uPlxuICAgKiAgICAgYGBgXG4gICAqXG4gICAqICAgICB3aWxsIHJlbmRlciBhcyBhIGAyNHB4YCBpY29uIGlmIHRoZSBgXCJtYXRlcmlhbFwiYCBtb2RpZmllciBpcyBwcmVzZW50IGFuZCBgMzJweGAgb3RoZXJ3aXNlLlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHJvdGF0ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dTnVtYmVyIG9mIGRlZ3JlZXMgdG8gcm90YXRlIHRoZSBpY29uLiBWYWxpZCB2YWx1ZXMgYXJlIDkwLCAxODAgYW5kIDI3MC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjgqTjgrPjg7PjgpLlm57ou6LjgZfjgabooajnpLrjgZfjgb7jgZnjgII5MCwgMTgwLCAyNzDjgYvjgonmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBmaXhlZC13aWR0aFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dV2hlbiB1c2VkIGluIGEgbGlzdCwgeW91IHdhbnQgdGhlIGljb25zIHRvIGhhdmUgdGhlIHNhbWUgd2lkdGggc28gdGhhdCB0aGV5IGFsaWduIHZlcnRpY2FsbHkgYnkgZGVmaW5pbmcgdGhpcyBhdHRyaWJ1dGUuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBzcGluXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IHdoZXRoZXIgdGhlIGljb24gc2hvdWxkIGJlIHNwaW5uaW5nLlsvZW5dXG4gICAqICAgW2phXeOCouOCpOOCs+ODs+OCkuWbnui7ouOBmeOCi+OBi+OBqeOBhuOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fY29tcGlsZSgpO1xuICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnaWNvbicsICdzaXplJywgJ21vZGlmaWVyJywgJ2NsYXNzJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHRoaXMuX2NsZWFuQ2xhc3NBdHRyaWJ1dGUobmFtZSA9PT0gJ2ljb24nID8gbGFzdCA6IHRoaXMuZ2V0QXR0cmlidXRlKCdpY29uJyksIG5hbWUgPT09ICdtb2RpZmllcicgPyBsYXN0IDogdW5kZWZpbmVkKTtcbiAgICB0aGlzLl91cGRhdGUoKTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIGF1dG9TdHlsZS5wcmVwYXJlKHRoaXMpO1xuICAgIHRoaXMuX3VwZGF0ZSgpO1xuICB9XG5cbiAgX3VwZGF0ZSgpIHtcbiAgICBjb25zdCB7Y2xhc3NMaXN0LCBzdHlsZX0gPSB0aGlzLl9idWlsZENsYXNzQW5kU3R5bGUodGhpcy5fcGFyc2VBdHRyKCdpY29uJyksIHRoaXMuX3BhcnNlQXR0cignc2l6ZScpKTtcbiAgICB1dGlsLmV4dGVuZCh0aGlzLnN0eWxlLCBzdHlsZSk7XG5cbiAgICBjbGFzc0xpc3QuZm9yRWFjaChjbGFzc05hbWUgPT4gdGhpcy5jbGFzc0xpc3QuYWRkKGNsYXNzTmFtZSkpO1xuICB9XG5cbiAgX3BhcnNlQXR0cihhdHRyTmFtZSwgbW9kaWZpZXIgPSB0aGlzLmdldEF0dHJpYnV0ZSgnbW9kaWZpZXInKSB8fCAnJykge1xuICAgIGNvbnN0IGF0dHIgPSB0aGlzLmdldEF0dHJpYnV0ZShhdHRyTmFtZSkgfHwgYXR0ck5hbWUgfHwgJydcbiAgICBjb25zdCBwYXJ0cyA9IGF0dHIuc3BsaXQoL1xccyosXFxzKi8pO1xuICAgIGNvbnN0IGRlZiA9IHBhcnRzWzBdO1xuICAgIGxldCBtZCA9IHBhcnRzWzFdO1xuICAgIG1kID0gKG1kIHx8ICcnKS5zcGxpdCgvXFxzKjpcXHMqLyk7XG5cbiAgICByZXR1cm4gKG1vZGlmaWVyICYmIChSZWdFeHAoYChefFxcXFxzKykke21kWzBdfSgkfFxcXFxzKylgLCAnaScpLnRlc3QobW9kaWZpZXIpKSA/IG1kWzFdIDogZGVmKSB8fCAnJztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgdW5uZWVkZWQgY2xhc3MgdmFsdWUuXG4gICAqL1xuICBfY2xlYW5DbGFzc0F0dHJpYnV0ZShsYXN0SWNvbiwgbGFzdE1vZGlmaWVyKSB7XG4gICAgY29uc3QgeyBjbGFzc05hbWUsIHByZWZpeCB9ID0gdGhpcy5fcHJlZml4SWNvbih0aGlzLl9wYXJzZUF0dHIobGFzdEljb24sIGxhc3RNb2RpZmllcikpO1xuICAgIGNvbnN0IGN1c3RvbVByZWZpeFJFID0gY2xhc3NOYW1lICE9PSBwcmVmaXggPyBgfCR7cHJlZml4fSR8JHtwcmVmaXh9LWAgOiBgfCR7Y2xhc3NOYW1lfSRgIHx8ICcnO1xuICAgIGNvbnN0IHJlID0gbmV3IFJlZ0V4cChgXihmYSR8ZmEtfGlvbi18em1kaSR8em1kaS18b25zLWljb24tLSR7Y3VzdG9tUHJlZml4UkV9KWApO1xuXG4gICAgdXRpbC5hcnJheUZyb20odGhpcy5jbGFzc0xpc3QpXG4gICAgICAuZmlsdGVyKGNsYXNzTmFtZSA9PiByZS50ZXN0KGNsYXNzTmFtZSkpXG4gICAgICAuZm9yRWFjaChjbGFzc05hbWUgPT4gdGhpcy5jbGFzc0xpc3QucmVtb3ZlKGNsYXNzTmFtZSkpO1xuICB9XG5cbiAgX3ByZWZpeEljb24oaWNvbk5hbWUpIHtcbiAgICBjb25zdCBjbGFzc05hbWUgPSBhdXRvUHJlZml4ICsgKGF1dG9QcmVmaXggPyAnLScgOiAnJykgKyBpY29uTmFtZTtcbiAgICByZXR1cm4geyBjbGFzc05hbWUsIHByZWZpeDogY2xhc3NOYW1lLnNwbGl0KCctJylbMF0gfTtcbiAgfVxuXG4gIF9idWlsZENsYXNzQW5kU3R5bGUoaWNvbk5hbWUsIHNpemUpIHtcbiAgICBjb25zdCBjbGFzc0xpc3QgPSBbJ29ucy1pY29uJ107XG4gICAgY29uc3Qgc3R5bGUgPSB7fTtcblxuICAgIC8vIEljb25cbiAgICBpZiAoaWNvbk5hbWUuaW5kZXhPZignaW9uLScpID09PSAwKSB7XG4gICAgICBjbGFzc0xpc3QucHVzaChpY29uTmFtZSk7XG4gICAgICBjbGFzc0xpc3QucHVzaCgnb25zLWljb24tLWlvbicpO1xuICAgIH0gZWxzZSBpZiAoaWNvbk5hbWUuaW5kZXhPZignZmEtJykgPT09IDApIHtcbiAgICAgIGNsYXNzTGlzdC5wdXNoKGljb25OYW1lKTtcbiAgICAgIC8vIGRlZmF1bHQgaWNvbiBzdHlsZSB0byBGb250IEF3ZXNvbWUgU29saWQgaWYgaWNvbiBzdHlsZSBpcyBub3Qgc3BlY2lmaWVkIGFscmVhZHlcbiAgICAgIGlmICghKHRoaXMuY2xhc3NMaXN0LmNvbnRhaW5zKCdmYXInKSB8fCB0aGlzLmNsYXNzTGlzdC5jb250YWlucygnZmFiJykgfHwgdGhpcy5jbGFzc0xpc3QuY29udGFpbnMoJ2ZhbCcpKSkge1xuICAgICAgICBjbGFzc0xpc3QucHVzaCgnZmEnKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGljb25OYW1lLmluZGV4T2YoJ21kLScpID09PSAwKSAge1xuICAgICAgY2xhc3NMaXN0LnB1c2goJ3ptZGknKTtcbiAgICAgIGNsYXNzTGlzdC5wdXNoKCd6bWRpLScgKyBpY29uTmFtZS5zcGxpdCgvLSguKyk/LylbMV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB7IGNsYXNzTmFtZSwgcHJlZml4IH0gPSB0aGlzLl9wcmVmaXhJY29uKGljb25OYW1lKTtcbiAgICAgIHByZWZpeCAmJiBjbGFzc0xpc3QucHVzaChwcmVmaXgpO1xuICAgICAgY2xhc3NOYW1lICYmIGNsYXNzTGlzdC5wdXNoKGNsYXNzTmFtZSk7XG4gICAgfVxuXG4gICAgLy8gU2l6ZVxuICAgIGlmIChzaXplLm1hdGNoKC9eWzEtNV14fGxnJC8pKSB7XG4gICAgICBjbGFzc0xpc3QucHVzaCgnb25zLWljb24tLScgKyBzaXplKTtcbiAgICAgIHRoaXMuc3R5bGUucmVtb3ZlUHJvcGVydHkoJ2ZvbnQtc2l6ZScpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdHlsZS5mb250U2l6ZSA9IHNpemU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNsYXNzTGlzdDogY2xhc3NMaXN0LFxuICAgICAgc3R5bGU6IHN0eWxlXG4gICAgfTtcbiAgfVxuXG4gIHN0YXRpYyBzZXRBdXRvUHJlZml4KHByZWZpeCkge1xuICAgIGF1dG9QcmVmaXggPSBwcmVmaXggPyAodHlwZW9mIHByZWZpeCA9PT0gJ3N0cmluZycgJiYgcHJlZml4IHx8ICdmYScpIDogJyc7XG4gIH1cbn1cblxub25zRWxlbWVudHMuSWNvbiA9IEljb25FbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtaWNvbicsIEljb25FbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4uL3V0aWwnO1xuaW1wb3J0IHBsYXRmb3JtIGZyb20gJy4uL3BsYXRmb3JtJztcblxuZXhwb3J0IGNsYXNzIExhenlSZXBlYXREZWxlZ2F0ZSB7XG5cbiAgY29uc3RydWN0b3IodXNlckRlbGVnYXRlLCB0ZW1wbGF0ZUVsZW1lbnQgPSBudWxsKSB7XG4gICAgaWYgKHR5cGVvZiB1c2VyRGVsZWdhdGUgIT09ICdvYmplY3QnIHx8IHVzZXJEZWxlZ2F0ZSA9PT0gbnVsbCkge1xuICAgICAgdXRpbC50aHJvdygnXCJkZWxlZ2F0ZVwiIHBhcmFtZXRlciBtdXN0IGJlIGFuIG9iamVjdCcpO1xuICAgIH1cbiAgICB0aGlzLl91c2VyRGVsZWdhdGUgPSB1c2VyRGVsZWdhdGU7XG5cbiAgICBpZiAoISh0ZW1wbGF0ZUVsZW1lbnQgaW5zdGFuY2VvZiBFbGVtZW50KSAmJiB0ZW1wbGF0ZUVsZW1lbnQgIT09IG51bGwpIHtcbiAgICAgIHV0aWwudGhyb3coJ1widGVtcGxhdGVFbGVtZW50XCIgcGFyYW1ldGVyIG11c3QgYmUgYW4gaW5zdGFuY2Ugb2YgRWxlbWVudCBvciBudWxsJyk7XG4gICAgfVxuICAgIHRoaXMuX3RlbXBsYXRlRWxlbWVudCA9IHRlbXBsYXRlRWxlbWVudDtcbiAgfVxuXG4gIGdldCBpdGVtSGVpZ2h0KCkge1xuICAgIHJldHVybiB0aGlzLl91c2VyRGVsZWdhdGUuaXRlbUhlaWdodDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgaGFzUmVuZGVyRnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX3VzZXJEZWxlZ2F0ZS5fcmVuZGVyIGluc3RhbmNlb2YgRnVuY3Rpb247XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIF9yZW5kZXIoKSB7XG4gICAgdGhpcy5fdXNlckRlbGVnYXRlLl9yZW5kZXIuYXBwbHkodGhpcy5fdXNlckRlbGVnYXRlLCBhcmd1bWVudHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBpbmRleFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lIEEgZnVuY3Rpb24gdGhhdCB0YWtlIGl0ZW0gb2JqZWN0IGFzIHBhcmFtZXRlci5cbiAgICovXG4gIGxvYWRJdGVtRWxlbWVudChpbmRleCwgZG9uZSkge1xuICAgIGlmICh0aGlzLl91c2VyRGVsZWdhdGUubG9hZEl0ZW1FbGVtZW50IGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHRoaXMuX3VzZXJEZWxlZ2F0ZS5sb2FkSXRlbUVsZW1lbnQoaW5kZXgsIGRvbmUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5fdXNlckRlbGVnYXRlLmNyZWF0ZUl0ZW1Db250ZW50KGluZGV4LCB0aGlzLl90ZW1wbGF0ZUVsZW1lbnQpO1xuICAgICAgaWYgKCEoZWxlbWVudCBpbnN0YW5jZW9mIEVsZW1lbnQpKSB7XG4gICAgICAgIHV0aWwudGhyb3coJ1wiY3JlYXRlSXRlbUNvbnRlbnRcIiBtdXN0IHJldHVybiBhbiBpbnN0YW5jZSBvZiBFbGVtZW50Jyk7XG4gICAgICB9XG5cbiAgICAgIGRvbmUoe2VsZW1lbnR9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7TnVtYmVyfVxuICAgKi9cbiAgY291bnRJdGVtcygpIHtcbiAgICBjb25zdCBjb3VudCA9IHRoaXMuX3VzZXJEZWxlZ2F0ZS5jb3VudEl0ZW1zKCk7XG4gICAgaWYgKHR5cGVvZiBjb3VudCAhPT0gJ251bWJlcicpIHtcbiAgICAgIHV0aWwudGhyb3coJ1wiY291bnRJdGVtc1wiIG11c3QgcmV0dXJuIGEgbnVtYmVyJyk7XG4gICAgfVxuICAgIHJldHVybiBjb3VudDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogQHBhcmFtIHtPYmplY3R9IGl0ZW1cbiAgICogQHBhcmFtIHtFbGVtZW50fSBpdGVtLmVsZW1lbnRcbiAgICovXG4gIHVwZGF0ZUl0ZW0oaW5kZXgsIGl0ZW0pIHtcbiAgICBpZiAodGhpcy5fdXNlckRlbGVnYXRlLnVwZGF0ZUl0ZW1Db250ZW50IGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHRoaXMuX3VzZXJEZWxlZ2F0ZS51cGRhdGVJdGVtQ29udGVudChpbmRleCwgaXRlbSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge051bWJlcn1cbiAgICovXG4gIGNhbGN1bGF0ZUl0ZW1IZWlnaHQoaW5kZXgpIHtcbiAgICBpZiAodGhpcy5fdXNlckRlbGVnYXRlLmNhbGN1bGF0ZUl0ZW1IZWlnaHQgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5fdXNlckRlbGVnYXRlLmNhbGN1bGF0ZUl0ZW1IZWlnaHQoaW5kZXgpO1xuXG4gICAgICBpZiAodHlwZW9mIGhlaWdodCAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgdXRpbC50aHJvdygnXCJjYWxjdWxhdGVJdGVtSGVpZ2h0XCIgbXVzdCByZXR1cm4gYSBudW1iZXInKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGhlaWdodDtcbiAgICB9XG5cbiAgICByZXR1cm4gMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogQHBhcmFtIHtPYmplY3R9IGl0ZW1cbiAgICovXG4gIGRlc3Ryb3lJdGVtKGluZGV4LCBpdGVtKSB7XG4gICAgaWYgKHRoaXMuX3VzZXJEZWxlZ2F0ZS5kZXN0cm95SXRlbSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICB0aGlzLl91c2VyRGVsZWdhdGUuZGVzdHJveUl0ZW0oaW5kZXgsIGl0ZW0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgZGVzdHJveSgpIHtcbiAgICBpZiAodGhpcy5fdXNlckRlbGVnYXRlLmRlc3Ryb3kgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgdGhpcy5fdXNlckRlbGVnYXRlLmRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICB0aGlzLl91c2VyRGVsZWdhdGUgPSB0aGlzLl90ZW1wbGF0ZUVsZW1lbnQgPSBudWxsO1xuICB9XG59XG5cbi8qKlxuICogVGhpcyBjbGFzcyBwcm92aWRlIGNvcmUgZnVuY3Rpb25zIGZvciBvbnMtbGF6eS1yZXBlYXQuXG4gKi9cbmV4cG9ydCBjbGFzcyBMYXp5UmVwZWF0UHJvdmlkZXIge1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IHdyYXBwZXJFbGVtZW50XG4gICAqIEBwYXJhbSB7TGF6eVJlcGVhdERlbGVnYXRlfSBkZWxlZ2F0ZVxuICAgKi9cbiAgY29uc3RydWN0b3Iod3JhcHBlckVsZW1lbnQsIGRlbGVnYXRlKSB7XG4gICAgaWYgKCEoZGVsZWdhdGUgaW5zdGFuY2VvZiBMYXp5UmVwZWF0RGVsZWdhdGUpKSB7XG4gICAgICB1dGlsLnRocm93KCdcImRlbGVnYXRlXCIgcGFyYW1ldGVyIG11c3QgYmUgYW4gaW5zdGFuY2Ugb2YgTGF6eVJlcGVhdERlbGVnYXRlJyk7XG4gICAgfVxuXG4gICAgdGhpcy5fd3JhcHBlckVsZW1lbnQgPSB3cmFwcGVyRWxlbWVudDtcbiAgICB0aGlzLl9kZWxlZ2F0ZSA9IGRlbGVnYXRlO1xuICAgIHRoaXMuX2luc2VydEluZGV4ID0gKHRoaXMuX3dyYXBwZXJFbGVtZW50LmNoaWxkcmVuWzBdICYmIHRoaXMuX3dyYXBwZXJFbGVtZW50LmNoaWxkcmVuWzBdLnRhZ05hbWUgPT09ICdPTlMtTEFaWS1SRVBFQVQnKSA/IDEgOiAwO1xuXG4gICAgaWYgKHdyYXBwZXJFbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ29ucy1saXN0Jykge1xuICAgICAgd3JhcHBlckVsZW1lbnQuY2xhc3NMaXN0LmFkZCgnbGF6eS1saXN0Jyk7XG4gICAgfVxuXG4gICAgdGhpcy5fcGFnZUNvbnRlbnQgPSB0aGlzLl9maW5kUGFnZUNvbnRlbnRFbGVtZW50KHdyYXBwZXJFbGVtZW50KTtcblxuICAgIGlmICghdGhpcy5fcGFnZUNvbnRlbnQpIHtcbiAgICAgIHV0aWwudGhyb3coJ0xhenlSZXBlYXQgbXVzdCBiZSBkZXNjZW5kYW50IG9mIGEgUGFnZSBlbGVtZW50Jyk7XG4gICAgfVxuXG4gICAgdGhpcy5sYXN0U2Nyb2xsVG9wID0gdGhpcy5fcGFnZUNvbnRlbnQuc2Nyb2xsVG9wO1xuICAgIHRoaXMucGFkZGluZyA9IDA7XG4gICAgdGhpcy5fdG9wUG9zaXRpb25zID0gWzBdO1xuICAgIHRoaXMuX3JlbmRlcmVkSXRlbXMgPSB7fTtcblxuICAgIGlmICghdGhpcy5fZGVsZWdhdGUuaXRlbUhlaWdodCAmJiAhdGhpcy5fZGVsZWdhdGUuY2FsY3VsYXRlSXRlbUhlaWdodCgwKSkge1xuICAgICAgdGhpcy5fdW5rbm93bkl0ZW1IZWlnaHQgPSB0cnVlO1xuICAgIH1cblxuICAgIHRoaXMuX2FkZEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgdGhpcy5fb25DaGFuZ2UoKTtcbiAgfVxuXG4gIGdldCBwYWRkaW5nKCkge1xuICAgIHJldHVybiBwYXJzZUludCh0aGlzLl93cmFwcGVyRWxlbWVudC5zdHlsZS5wYWRkaW5nVG9wLCAxMCk7XG4gIH1cblxuICBzZXQgcGFkZGluZyhuZXdWYWx1ZSkge1xuICAgIHRoaXMuX3dyYXBwZXJFbGVtZW50LnN0eWxlLnBhZGRpbmdUb3AgPSBuZXdWYWx1ZSArICdweCc7XG4gIH1cblxuICBfZmluZFBhZ2VDb250ZW50RWxlbWVudCh3cmFwcGVyRWxlbWVudCkge1xuICAgIGNvbnN0IHBhZ2VDb250ZW50ID0gdXRpbC5maW5kUGFyZW50KHdyYXBwZXJFbGVtZW50LCAnLnBhZ2VfX2NvbnRlbnQnKTtcblxuICAgIGlmIChwYWdlQ29udGVudCkge1xuICAgICAgcmV0dXJuIHBhZ2VDb250ZW50O1xuICAgIH1cblxuICAgIGNvbnN0IHBhZ2UgPSB1dGlsLmZpbmRQYXJlbnQod3JhcHBlckVsZW1lbnQsICdvbnMtcGFnZScpO1xuICAgIGlmIChwYWdlKSB7XG4gICAgICBjb25zdCBjb250ZW50ID0gdXRpbC5maW5kQ2hpbGQocGFnZSwgJy5jb250ZW50Jyk7XG4gICAgICBpZiAoY29udGVudCkge1xuICAgICAgICByZXR1cm4gY29udGVudDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIF9jaGVja0l0ZW1IZWlnaHQoY2FsbGJhY2spIHtcbiAgICB0aGlzLl9kZWxlZ2F0ZS5sb2FkSXRlbUVsZW1lbnQoMCwgaXRlbSA9PiB7XG4gICAgICBpZiAoIXRoaXMuX3Vua25vd25JdGVtSGVpZ2h0KSB7XG4gICAgICAgIHV0aWwudGhyb3coJ0ludmFsaWQgc3RhdGUnKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fd3JhcHBlckVsZW1lbnQuYXBwZW5kQ2hpbGQoaXRlbS5lbGVtZW50KTtcblxuICAgICAgY29uc3QgZG9uZSA9ICgpID0+IHtcbiAgICAgICAgdGhpcy5fZGVsZWdhdGUuZGVzdHJveUl0ZW0oMCwgaXRlbSk7XG4gICAgICAgIGl0ZW0uZWxlbWVudCAmJiBpdGVtLmVsZW1lbnQucmVtb3ZlKCk7XG4gICAgICAgIGRlbGV0ZSB0aGlzLl91bmtub3duSXRlbUhlaWdodDtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgIH07XG5cbiAgICAgIHRoaXMuX2l0ZW1IZWlnaHQgPSBpdGVtLmVsZW1lbnQub2Zmc2V0SGVpZ2h0O1xuXG4gICAgICBpZiAodGhpcy5faXRlbUhlaWdodCA+IDApIHtcbiAgICAgICAgZG9uZSgpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIHJldHJ5IHRvIG1lYXN1cmUgb2Zmc2V0IGhlaWdodFxuICAgICAgLy8gZGlydHkgZml4IGZvciBhbmd1bGFyMiBkaXJlY3RpdmVcbiAgICAgIHRoaXMuX3dyYXBwZXJFbGVtZW50LnN0eWxlLnZpc2liaWxpdHkgPSAnaGlkZGVuJztcbiAgICAgIGl0ZW0uZWxlbWVudC5zdHlsZS52aXNpYmlsaXR5ID0gJ2hpZGRlbic7XG5cbiAgICAgIHNldEltbWVkaWF0ZSgoKSA9PiB7XG4gICAgICAgIHRoaXMuX2l0ZW1IZWlnaHQgPSBpdGVtLmVsZW1lbnQub2Zmc2V0SGVpZ2h0O1xuICAgICAgICBpZiAodGhpcy5faXRlbUhlaWdodCA9PSAwKSB7XG4gICAgICAgICAgdXRpbC50aHJvdygnSW52YWxpZCBzdGF0ZTogXCJpdGVtSGVpZ2h0XCIgbXVzdCBiZSBncmVhdGVyIHRoYW4gemVybycpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3dyYXBwZXJFbGVtZW50LnN0eWxlLnZpc2liaWxpdHkgPSAnJztcbiAgICAgICAgZG9uZSgpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBnZXQgc3RhdGljSXRlbUhlaWdodCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZGVsZWdhdGUuaXRlbUhlaWdodCB8fCB0aGlzLl9pdGVtSGVpZ2h0O1xuICB9XG4gIF9jb3VudEl0ZW1zKCkge1xuICAgIHJldHVybiB0aGlzLl9kZWxlZ2F0ZS5jb3VudEl0ZW1zKCk7XG4gIH1cblxuICBfZ2V0SXRlbUhlaWdodChpKSB7XG4gICAgLy8gSXRlbSBpcyByZW5kZXJlZFxuICAgIGlmICh0aGlzLl9yZW5kZXJlZEl0ZW1zLmhhc093blByb3BlcnR5KGkpKSB7XG4gICAgICBpZiAoIXRoaXMuX3JlbmRlcmVkSXRlbXNbaV0uaGFzT3duUHJvcGVydHkoJ2hlaWdodCcpKSB7XG4gICAgICAgIHRoaXMuX3JlbmRlcmVkSXRlbXNbaV0uaGVpZ2h0ID0gdGhpcy5fcmVuZGVyZWRJdGVtc1tpXS5lbGVtZW50Lm9mZnNldEhlaWdodDtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLl9yZW5kZXJlZEl0ZW1zW2ldLmhlaWdodDtcbiAgICB9XG5cbiAgICAvLyBJdGVtIGlzIG5vdCByZW5kZXJlZCwgc2Nyb2xsIHVwXG4gICAgaWYgKHRoaXMuX3RvcFBvc2l0aW9uc1tpICsgMV0gJiYgdGhpcy5fdG9wUG9zaXRpb25zW2ldKSB7XG4gICAgICByZXR1cm4gdGhpcy5fdG9wUG9zaXRpb25zW2kgKyAxXSAtIHRoaXMuX3RvcFBvc2l0aW9uc1tpXTtcbiAgICB9XG4gICAgLy8gSXRlbSBpcyBub3QgcmVuZGVyZWQsIHNjcm9sbCBkb3duXG4gICAgcmV0dXJuIHRoaXMuc3RhdGljSXRlbUhlaWdodCB8fCB0aGlzLl9kZWxlZ2F0ZS5jYWxjdWxhdGVJdGVtSGVpZ2h0KGkpO1xuICB9XG5cbiAgX2NhbGN1bGF0ZVJlbmRlcmVkSGVpZ2h0KCkge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLl9yZW5kZXJlZEl0ZW1zKS5yZWR1Y2UoKGEsIGIpID0+IGEgKyB0aGlzLl9nZXRJdGVtSGVpZ2h0KCsoYikpLCAwKVxuICB9XG5cbiAgX29uQ2hhbmdlKCkge1xuICAgIHRoaXMuX3JlbmRlcigpO1xuICB9XG5cbiAgX2xhc3RJdGVtUmVuZGVyZWQoKSB7XG4gICAgcmV0dXJuIE1hdGgubWF4KC4uLk9iamVjdC5rZXlzKHRoaXMuX3JlbmRlcmVkSXRlbXMpKTtcbiAgfVxuXG4gIF9maXJzdEl0ZW1SZW5kZXJlZCgpIHtcbiAgICByZXR1cm4gTWF0aC5taW4oLi4uT2JqZWN0LmtleXModGhpcy5fcmVuZGVyZWRJdGVtcykpO1xuICB9XG5cbiAgcmVmcmVzaCgpIHtcbiAgICBjb25zdCBmb3JjZVJlbmRlciA9IHsgZm9yY2VTY3JvbGxEb3duOiB0cnVlIH07XG4gICAgY29uc3QgZmlyc3RJdGVtSW5kZXggPSB0aGlzLl9maXJzdEl0ZW1SZW5kZXJlZCgpO1xuXG4gICAgaWYgKHV0aWwuaXNJbnRlZ2VyKGZpcnN0SXRlbUluZGV4KSkge1xuICAgICAgdGhpcy5fd3JhcHBlckVsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gdGhpcy5fdG9wUG9zaXRpb25zW2ZpcnN0SXRlbUluZGV4XSArIHRoaXMuX2NhbGN1bGF0ZVJlbmRlcmVkSGVpZ2h0KCkgKyAncHgnO1xuICAgICAgdGhpcy5wYWRkaW5nID0gdGhpcy5fdG9wUG9zaXRpb25zW2ZpcnN0SXRlbUluZGV4XTtcbiAgICAgIGZvcmNlUmVuZGVyLmZvcmNlRmlyc3RJbmRleCA9IGZpcnN0SXRlbUluZGV4O1xuICAgIH1cblxuICAgIHRoaXMuX3JlbW92ZUFsbEVsZW1lbnRzKCk7XG4gICAgdGhpcy5fcmVuZGVyKGZvcmNlUmVuZGVyKTtcbiAgICB0aGlzLl93cmFwcGVyRWxlbWVudC5zdHlsZS5oZWlnaHQgPSAnaW5oZXJpdCc7XG4gIH1cblxuICBfcmVuZGVyKHtmb3JjZVNjcm9sbERvd24gPSBmYWxzZSwgZm9yY2VGaXJzdEluZGV4LCBmb3JjZUxhc3RJbmRleH0gPSB7fSkge1xuICAgIGlmICh0aGlzLl91bmtub3duSXRlbUhlaWdodCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2NoZWNrSXRlbUhlaWdodCh0aGlzLl9yZW5kZXIuYmluZCh0aGlzLCBhcmd1bWVudHNbMF0pKTtcbiAgICB9XG5cbiAgICBjb25zdCBpc1Njcm9sbFVwID0gIWZvcmNlU2Nyb2xsRG93biAmJiB0aGlzLmxhc3RTY3JvbGxUb3AgPiB0aGlzLl9wYWdlQ29udGVudC5zY3JvbGxUb3A7XG4gICAgdGhpcy5sYXN0U2Nyb2xsVG9wID0gdGhpcy5fcGFnZUNvbnRlbnQuc2Nyb2xsVG9wO1xuICAgIGNvbnN0IGtlZXAgPSB7fTtcblxuICAgIGNvbnN0IG9mZnNldCA9IHRoaXMuX3dyYXBwZXJFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcDtcbiAgICBjb25zdCBsaW1pdCA9IDQgKiB3aW5kb3cuaW5uZXJIZWlnaHQgLSBvZmZzZXQ7XG4gICAgY29uc3QgY291bnQgPSB0aGlzLl9jb3VudEl0ZW1zKCk7XG5cbiAgICBjb25zdCBpdGVtcyA9IFtdO1xuICAgIGNvbnN0IHN0YXJ0ID0gZm9yY2VGaXJzdEluZGV4IHx8IE1hdGgubWF4KDAsIHRoaXMuX2NhbGN1bGF0ZVN0YXJ0SW5kZXgob2Zmc2V0KSAtIDMwKTsgLy8gUmVjYWxjdWxhdGUgZm9yIDAgb3IgdW5kZWZpbmVkXG4gICAgbGV0IGkgPSBzdGFydDtcblxuICAgIGZvciAobGV0IHRvcCA9IHRoaXMuX3RvcFBvc2l0aW9uc1tpXTsgaSA8IGNvdW50ICYmIHRvcCA8IGxpbWl0OyBpKyspIHtcbiAgICAgIGlmIChpID49IHRoaXMuX3RvcFBvc2l0aW9ucy5sZW5ndGgpIHsgLy8gcGVyZiBvcHRpbWl6YXRpb25cbiAgICAgICAgdGhpcy5fdG9wUG9zaXRpb25zLmxlbmd0aCArPSAxMDA7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3RvcFBvc2l0aW9uc1tpXSA9IHRvcDtcbiAgICAgIHRvcCArPSB0aGlzLl9nZXRJdGVtSGVpZ2h0KGkpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9kZWxlZ2F0ZS5oYXNSZW5kZXJGdW5jdGlvbiAmJiB0aGlzLl9kZWxlZ2F0ZS5oYXNSZW5kZXJGdW5jdGlvbigpKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZGVsZWdhdGUuX3JlbmRlcihzdGFydCwgaSwgKCkgPT4ge1xuICAgICAgICB0aGlzLnBhZGRpbmcgPSB0aGlzLl90b3BQb3NpdGlvbnNbc3RhcnRdO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKGlzU2Nyb2xsVXApIHtcbiAgICAgIGZvciAobGV0IGogPSBpIC0gMTsgaiA+PSBzdGFydDsgai0tKSB7XG4gICAgICAgIGtlZXBbal0gPSB0cnVlO1xuICAgICAgICB0aGlzLl9yZW5kZXJFbGVtZW50KGosIGlzU2Nyb2xsVXApO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBsYXN0SW5kZXggPSBmb3JjZUxhc3RJbmRleCB8fCBNYXRoLm1heChpIC0gMSwgLi4uT2JqZWN0LmtleXModGhpcy5fcmVuZGVyZWRJdGVtcykpOyAvLyBSZWNhbGN1bGF0ZSBmb3IgMCBvciB1bmRlZmluZWRcbiAgICAgIGZvciAobGV0IGogPSBzdGFydDsgaiA8PSBsYXN0SW5kZXg7IGorKykge1xuICAgICAgICBrZWVwW2pdID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5fcmVuZGVyRWxlbWVudChqLCBpc1Njcm9sbFVwKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBPYmplY3Qua2V5cyh0aGlzLl9yZW5kZXJlZEl0ZW1zKS5mb3JFYWNoKGtleSA9PiBrZWVwW2tleV0gfHwgdGhpcy5fcmVtb3ZlRWxlbWVudChrZXksIGlzU2Nyb2xsVXApKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogQHBhcmFtIHtCb29sZWFufSBpc1Njcm9sbFVwXG4gICAqL1xuICBfcmVuZGVyRWxlbWVudChpbmRleCwgaXNTY3JvbGxVcCkge1xuICAgIGNvbnN0IGl0ZW0gPSB0aGlzLl9yZW5kZXJlZEl0ZW1zW2luZGV4XTtcbiAgICBpZiAoaXRlbSkge1xuICAgICAgdGhpcy5fZGVsZWdhdGUudXBkYXRlSXRlbShpbmRleCwgaXRlbSk7IC8vIHVwZGF0ZSBpZiBpdCBleGlzdHNcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9kZWxlZ2F0ZS5sb2FkSXRlbUVsZW1lbnQoaW5kZXgsIGl0ZW0gPT4ge1xuICAgICAgaWYgKGlzU2Nyb2xsVXApIHtcbiAgICAgICAgdGhpcy5fd3JhcHBlckVsZW1lbnQuaW5zZXJ0QmVmb3JlKGl0ZW0uZWxlbWVudCwgdGhpcy5fd3JhcHBlckVsZW1lbnQuY2hpbGRyZW5bdGhpcy5faW5zZXJ0SW5kZXhdKVxuICAgICAgICB0aGlzLnBhZGRpbmcgPSB0aGlzLl90b3BQb3NpdGlvbnNbaW5kZXhdO1xuICAgICAgICBpdGVtLmhlaWdodCA9IHRoaXMuX3RvcFBvc2l0aW9uc1tpbmRleCArIDFdIC0gdGhpcy5fdG9wUG9zaXRpb25zW2luZGV4XTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX3dyYXBwZXJFbGVtZW50LmFwcGVuZENoaWxkKGl0ZW0uZWxlbWVudCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3JlbmRlcmVkSXRlbXNbaW5kZXhdID0gaXRlbTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogQHBhcmFtIHtCb29sZWFufSBpc1Njcm9sbFVwXG4gICAqL1xuICBfcmVtb3ZlRWxlbWVudChpbmRleCwgaXNTY3JvbGxVcCA9IHRydWUpIHtcbiAgICBpbmRleCA9ICsoaW5kZXgpO1xuICAgIGNvbnN0IGl0ZW0gPSB0aGlzLl9yZW5kZXJlZEl0ZW1zW2luZGV4XTtcbiAgICB0aGlzLl9kZWxlZ2F0ZS5kZXN0cm95SXRlbShpbmRleCwgaXRlbSk7XG5cbiAgICBpZiAoaXNTY3JvbGxVcCkge1xuICAgICAgdGhpcy5fdG9wUG9zaXRpb25zW2luZGV4ICsgMV0gPSB1bmRlZmluZWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucGFkZGluZyA9IHRoaXMucGFkZGluZyArIHRoaXMuX2dldEl0ZW1IZWlnaHQoaW5kZXgpO1xuICAgIH1cblxuICAgIGlmIChpdGVtLmVsZW1lbnQucGFyZW50RWxlbWVudCkge1xuICAgICAgaXRlbS5lbGVtZW50LnBhcmVudEVsZW1lbnQucmVtb3ZlQ2hpbGQoaXRlbS5lbGVtZW50KTtcbiAgICB9XG5cbiAgICBkZWxldGUgdGhpcy5fcmVuZGVyZWRJdGVtc1tpbmRleF07XG4gIH1cblxuICBfcmVtb3ZlQWxsRWxlbWVudHMoKSB7XG4gICAgT2JqZWN0LmtleXModGhpcy5fcmVuZGVyZWRJdGVtcykuZm9yRWFjaChrZXkgPT4gdGhpcy5fcmVtb3ZlRWxlbWVudChrZXkpKTtcbiAgfVxuXG4gIF9yZWNhbGN1bGF0ZVRvcFBvc2l0aW9ucyhzdGFydCwgZW5kKSB7XG4gICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDw9IGVuZDsgaSsrKSB7XG4gICAgICB0aGlzLl90b3BQb3NpdGlvbnNbaSArIDFdID0gdGhpcy5fdG9wUG9zaXRpb25zW2ldICsgdGhpcy5fZ2V0SXRlbUhlaWdodChpKTtcbiAgICB9XG4gIH1cblxuICBfY2FsY3VsYXRlU3RhcnRJbmRleChjdXJyZW50KSB7XG4gICAgY29uc3QgZmlyc3RJdGVtSW5kZXggPSB0aGlzLl9maXJzdEl0ZW1SZW5kZXJlZCgpO1xuICAgIGNvbnN0IGxhc3RJdGVtSW5kZXggPSB0aGlzLl9sYXN0SXRlbVJlbmRlcmVkKCk7XG5cbiAgICAvLyBGaXggZm9yIFNhZmFyaSBzY3JvbGwgYW5kIEFuZ3VsYXIgMlxuICAgIHRoaXMuX3JlY2FsY3VsYXRlVG9wUG9zaXRpb25zKGZpcnN0SXRlbUluZGV4LCBsYXN0SXRlbUluZGV4KTtcblxuICAgIGxldCBzdGFydCA9IDA7XG4gICAgbGV0IGVuZCA9IHRoaXMuX2NvdW50SXRlbXMoKSAtIDE7XG5cbiAgICAvLyBCaW5hcnkgc2VhcmNoIGZvciBpbmRleCBhdCB0b3Agb2Ygc2NyZWVuIHNvIHdlIGNhbiBzcGVlZCB1cCByZW5kZXJpbmcuXG4gICAgZm9yICg7Oykge1xuICAgICAgY29uc3QgbWlkZGxlID0gTWF0aC5mbG9vcigoc3RhcnQgKyBlbmQpIC8gMik7XG4gICAgICBjb25zdCB2YWx1ZSA9IGN1cnJlbnQgKyB0aGlzLl90b3BQb3NpdGlvbnNbbWlkZGxlXTtcblxuICAgICAgaWYgKGVuZCA8IHN0YXJ0KSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfSBlbHNlIGlmICh2YWx1ZSA8PSAwICYmIHZhbHVlICsgdGhpcy5fZ2V0SXRlbUhlaWdodChtaWRkbGUpID4gMCkge1xuICAgICAgICByZXR1cm4gbWlkZGxlO1xuICAgICAgfSBlbHNlIGlmIChpc05hTih2YWx1ZSkgfHwgdmFsdWUgPj0gMCkge1xuICAgICAgICBlbmQgPSBtaWRkbGUgLSAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RhcnQgPSBtaWRkbGUgKyAxO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIF9kZWJvdW5jZShmdW5jLCB3YWl0LCBpbW1lZGlhdGUpIHtcbiAgICBsZXQgdGltZW91dDtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICBjb25zdCBjYWxsTm93ID0gaW1tZWRpYXRlICYmICF0aW1lb3V0O1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgaWYgKGNhbGxOb3cpIHtcbiAgICAgICAgZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgIGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfSwgd2FpdCk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIF9kb3VibGVGaXJlT25Ub3VjaGVuZCgpIHtcbiAgICB0aGlzLl9yZW5kZXIoKTtcbiAgICB0aGlzLl9kZWJvdW5jZSh0aGlzLl9yZW5kZXIuYmluZCh0aGlzKSwgMTAwKTtcbiAgfVxuXG4gIF9hZGRFdmVudExpc3RlbmVycygpIHtcbiAgICB1dGlsLmJpbmRMaXN0ZW5lcnModGhpcywgWydfb25DaGFuZ2UnLCAnX2RvdWJsZUZpcmVPblRvdWNoZW5kJ10pO1xuXG4gICAgaWYgKHBsYXRmb3JtLmlzSU9TKCkpIHtcbiAgICAgIHRoaXMuX2JvdW5kT25DaGFuZ2UgPSB0aGlzLl9kZWJvdW5jZSh0aGlzLl9ib3VuZE9uQ2hhbmdlLCAzMCk7XG4gICAgfVxuXG4gICAgdGhpcy5fcGFnZUNvbnRlbnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgdHJ1ZSk7XG5cbiAgICBpZiAocGxhdGZvcm0uaXNJT1MoKSkge1xuICAgICAgdXRpbC5hZGRFdmVudExpc3RlbmVyKHRoaXMuX3BhZ2VDb250ZW50LCAndG91Y2htb3ZlJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgeyBjYXB0dXJlOiB0cnVlLCBwYXNzaXZlOiB0cnVlIH0pO1xuICAgICAgdGhpcy5fcGFnZUNvbnRlbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLl9ib3VuZERvdWJsZUZpcmVPblRvdWNoZW5kLCB0cnVlKTtcbiAgICB9XG5cbiAgICB3aW5kb3cuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgdHJ1ZSk7XG4gIH1cblxuICBfcmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgdGhpcy5fcGFnZUNvbnRlbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgdHJ1ZSk7XG5cbiAgICBpZiAocGxhdGZvcm0uaXNJT1MoKSkge1xuICAgICAgdXRpbC5yZW1vdmVFdmVudExpc3RlbmVyKHRoaXMuX3BhZ2VDb250ZW50LCAndG91Y2htb3ZlJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgeyBjYXB0dXJlOiB0cnVlLCBwYXNzaXZlOiB0cnVlIH0pO1xuICAgICAgdGhpcy5fcGFnZUNvbnRlbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLl9ib3VuZERvdWJsZUZpcmVPblRvdWNoZW5kLCB0cnVlKTtcbiAgICB9XG5cbiAgICB3aW5kb3cuZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgdHJ1ZSk7XG4gIH1cblxuICBkZXN0cm95KCkge1xuICAgIHRoaXMuX3JlbW92ZUFsbEVsZW1lbnRzKCk7XG4gICAgdGhpcy5fZGVsZWdhdGUuZGVzdHJveSgpO1xuICAgIHRoaXMuX3BhcmVudEVsZW1lbnQgPSB0aGlzLl9kZWxlZ2F0ZSA9IHRoaXMuX3JlbmRlcmVkSXRlbXMgPSBudWxsO1xuICAgIHRoaXMuX3JlbW92ZUV2ZW50TGlzdGVuZXJzKCk7XG4gIH1cbn1cblxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uL29ucy9pbnRlcm5hbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgeyBMYXp5UmVwZWF0RGVsZWdhdGUsIExhenlSZXBlYXRQcm92aWRlciB9IGZyb20gJy4uL29ucy9pbnRlcm5hbC9sYXp5LXJlcGVhdCc7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWxhenktcmVwZWF0XG4gKiBAY2F0ZWdvcnkgbGlzdFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBVc2luZyB0aGlzIGNvbXBvbmVudCBhIGxpc3Qgd2l0aCBtaWxsaW9ucyBvZiBpdGVtcyBjYW4gYmUgcmVuZGVyZWQgd2l0aG91dCBhIGRyb3AgaW4gcGVyZm9ybWFuY2UuXG4gKiAgICAgSXQgZG9lcyB0aGF0IGJ5IFwibGF6aWx5XCIgbG9hZGluZyBlbGVtZW50cyBpbnRvIHRoZSBET00gd2hlbiB0aGV5IGNvbWUgaW50byB2aWV3IGFuZFxuICogICAgIHJlbW92aW5nIGl0ZW1zIGZyb20gdGhlIERPTSB3aGVuIHRoZXkgYXJlIG5vdCB2aXNpYmxlLlxuICogICBbL2VuXVxuICogICBbamFdXG4gKiAgICAg44GT44Gu44Kz44Oz44Od44O844ON44Oz44OI5YaF44Gn5o+P55S744GV44KM44KL44Ki44Kk44OG44Og44GuRE9N6KaB57Sg44Gu6Kqt44G/6L6844G/44Gv44CB55S76Z2i44Gr6KaL44GI44Gd44GG44Gr44Gq44Gj44Gf5pmC44G+44Gn6Ieq5YuV55qE44Gr6YGF5bu244GV44KM44CBXG4gKiAgICAg55S76Z2i44GL44KJ6KaL44GI44Gq44GP44Gq44Gj44Gf5aC05ZCI44Gr44Gv44Gd44Gu6KaB57Sg44Gv5YuV55qE44Gr44Ki44Oz44Ot44O844OJ44GV44KM44G+44GZ44CCXG4gKiAgICAg44GT44Gu44Kz44Oz44Od44O844ON44Oz44OI44KS5L2/44GG44GT44Go44Gn44CB44OR44OV44Kp44O844Oe44Oz44K544KS5Yqj5YyW44GV44Gb44KL44GT44Go54Sh44GX44Gr5beo5aSn44Gq5pWw44Gu6KaB57Sg44KS5o+P55S744Gn44GN44G+44GZ44CCXG4gKiAgIFsvamFdXG4gKiBAY29kZXBlbiBRd3JHQm1cbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9sYXp5LXJlcGVhdFxuICogQHNlZWFsc28gb25zLWxpc3RcbiAqICAgW2VuXVRoZSBgPG9ucy1saXN0PmAgZWxlbWVudCBpcyB1c2VkIHRvIHJlbmRlciBhIGxpc3QuWy9lbl1cbiAqICAgW2phXWA8b25zLWxpc3Q+YOimgee0oOOBr+ODquOCueODiOOCkuaPj+eUu+OBmeOCi+OBruOBq+S9v+OCj+OCjOOBvuOBmeOAglsvamFdXG4gKiBAZXhhbXBsZVxuICogPHNjcmlwdD5cbiAqICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCBmdW5jdGlvbigpIHtcbiAqICAgICB2YXIgbGF6eVJlcGVhdCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNsaXN0Jyk7XG4gKiAgICAgbGF6eVJlcGVhdC5kZWxlZ2F0ZSA9IHtcbiAqICAgICAgY3JlYXRlSXRlbUNvbnRlbnQ6IGZ1bmN0aW9uKGksIHRlbXBsYXRlKSB7XG4gKiAgICAgICAgdmFyIGRvbSA9IHRlbXBsYXRlLmNsb25lTm9kZSh0cnVlKTtcbiAqICAgICAgICBkb20uaW5uZXJUZXh0ID0gaTtcbiAqXG4gKiAgICAgICAgcmV0dXJuIGRvbTtcbiAqICAgICAgfSxcbiAqICAgICAgY291bnRJdGVtczogZnVuY3Rpb24oKSB7XG4gKiAgICAgICAgcmV0dXJuIDEwMDAwMDAwO1xuICogICAgICB9LFxuICogICAgICBkZXN0cm95SXRlbTogZnVuY3Rpb24oaW5kZXgsIGl0ZW0pIHtcbiAqICAgICAgICBjb25zb2xlLmxvZygnRGVzdHJveWVkIGl0ZW0gd2l0aCBpbmRleDogJyArIGluZGV4KTtcbiAqICAgICAgfVxuICogICAgIH07XG4gKiAgIH0pO1xuICogPC9zY3JpcHQ+XG4gKlxuICogPG9ucy1saXN0IGlkPVwibGlzdFwiPlxuICogICA8b25zLWxhenktcmVwZWF0PlxuICogICAgIDxvbnMtbGlzdC1pdGVtPjwvb25zLWxpc3QtaXRlbT5cbiAqICAgPC9vbnMtbGF6eS1yZXBlYXQ+XG4gKiA8L29ucy1saXN0PlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMYXp5UmVwZWF0RWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICAvLyBub3QgdmVyeSBnb29kIGlkZWEgYW5kIGFsc28gbm90IGRvY3VtZW50ZWRcbiAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ2RlbGVnYXRlJykpIHtcbiAgICAgIHRoaXMuZGVsZWdhdGUgPSB3aW5kb3dbdGhpcy5nZXRBdHRyaWJ1dGUoJ2RlbGVnYXRlJyldO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGVsZWdhdGVcbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU3BlY2lmeSBhIGRlbGVnYXRlIG9iamVjdCB0byBsb2FkIGFuZCB1bmxvYWQgaXRlbSBlbGVtZW50cy5bL2VuXVxuICAgKiAgW2phXeimgee0oOOBruODreODvOODieOAgeOCouODs+ODreODvOODieOBquOBqeOBruWHpueQhuOCkuWnlOitsuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGVsZWdhdGUuY3JlYXRlSXRlbUNvbnRlbnRcbiAgICogQHR5cGUge0Z1bmN0aW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dXG4gICAqICAgICBUaGlzIGZ1bmN0aW9uIHNob3VsZCByZXR1cm4gYSBgSFRNTEVsZW1lbnRgLlxuICAgKlxuICAgKiAgICAgVG8gaGVscCByZW5kZXJpbmcgdGhlIGVsZW1lbnQsIHRoZSBjdXJyZW50IGluZGV4IGFuZCBhIHRlbXBsYXRlIGlzIHN1cHBsaWVkIGFzIGFyZ3VtZW50cy4gVGhlIHRlbXBsYXRlIGlzIHRoZSBpbml0aWFsIGNvbnRlbnQgb2YgdGhlIGA8b25zLWxhenktcmVwZWF0PmAgZWxlbWVudC5cbiAgICogICBbL2VuXVxuICAgKiAgIFtqYV1cbiAgICogICAgIOOBk+OBrumWouaVsOOBr2BIVE1MRWxlbWVudGDjgpLov5TjgZfjgabjgY/jgaDjgZXjgYTjgIJcbiAgICogICAgIOimgee0oOOCkueUn+aIkOOBl+OChOOBmeOBj+OBmeOCi+OBn+OCgeOBq+OAgeePvuWcqOOBruOCouOCpOODhuODoOOBruOCpOODs+ODh+ODg+OCr+OCueOBqOODhuODs+ODl+ODrOODvOODiOOBjOW8leaVsOOBq+a4oeOBleOCjOOBvuOBmeOAglxuICAgKiAgICAg44GT44Gu44OG44Oz44OX44Os44O844OI44Gv44CBYDxvbnMtbGF6eS1yZXBlYXQ+YOimgee0oOOBruOCs+ODs+ODhuODs+ODhOOBjOa4oeOBleOCjOOBvuOBmeOAglxuICAgKiAgIFsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGVsZWdhdGUuY291bnRJdGVtc1xuICAgKiBAdHlwZSB7RnVuY3Rpb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TaG91bGQgcmV0dXJuIHRoZSBudW1iZXIgb2YgaXRlbXMgaW4gdGhlIGxpc3QuWy9lbl1cbiAgICogICBbamFd44Oq44K544OI5YaF44Gu44Ki44Kk44OG44Og5pWw44KS6L+U44GX44Gm44GP44Gg44GV44GE44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkZWxlZ2F0ZS5jYWxjdWxhdGVJdGVtSGVpZ2h0XG4gICAqIEB0eXBlIHtGdW5jdGlvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgU2hvdWxkIHJldHVybiB0aGUgaGVpZ2h0IG9mIGFuIGl0ZW0uIFRoZSBpbmRleCBpcyBwcm92aWRlZCBhcyBhbiBhcmd1bWVudC5cbiAgICpcbiAgICogICAgIFRoaXMgaXMgaW1wb3J0YW50IHdoZW4gcmVuZGVyaW5nIGxpc3RzIHdoZXJlIHRoZSBpdGVtcyBoYXZlIGRpZmZlcmVudCBoZWlnaHQuXG4gICAqXG4gICAqICAgICBUaGUgZnVuY3Rpb24gaXMgb3B0aW9uYWwgYW5kIGlmIGl0IGlzbid0IHByZXNlbnQgdGhlIGhlaWdodCBvZiB0aGUgZmlyc3QgaXRlbSB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgY2FsY3VsYXRlZCBhbmQgdXNlZCBmb3IgYWxsIG90aGVyIGl0ZW1zLlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXVxuICAgKiAgICAg44Ki44Kk44OG44Og44Gu6auY44GVKOODlOOCr+OCu+ODqynjgpLov5TjgZfjgabjgY/jgaDjgZXjgYTjgILjgqLjgqTjg4bjg6Djga7jgqTjg7Pjg4fjg4Pjgq/jgrnlgKTjga/lvJXmlbDjgafmuKHjgZXjgozjgb7jgZnjgIJcbiAgICogICAgIOOBk+OBrumWouaVsOOBr+OAgeOBneOCjOOBnuOCjOOBruOCouOCpOODoOOBjOmBleOBo+OBn+mrmOOBleOCkuaMgeOBpOODquOCueODiOOCkuODrOODs+ODgOODquODs+OCsOOBmeOCi+mam+OBq+mHjeimgeOBp+OBmeOAglxuICAgKiAgICAg44GT44Gu6Zai5pWw44Gv44Kq44OX44K344On44OK44Or44Gn44GZ44CC44KC44GX44GT44Gu6Zai5pWw44GM54Sh44GE5aC05ZCI44Gr44Gv44CBXG4gICAqICAgICDmnIDliJ3jga7jgqLjgqTjg4bjg6Djga7pq5jjgZXjgYzku5bjga7jgZnjgbnjgabjga7jgqLjgqTjg4bjg6Djga7pq5jjgZXjgajjgZfjgabliKnnlKjjgZXjgozjgb7jgZnjgIJcbiAgICogICBbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRlbGVnYXRlLmRlc3Ryb3lJdGVtXG4gICAqIEB0eXBlIHtGdW5jdGlvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgVGhpcyBmdW5jdGlvbiBpcyB1c2VkIGNhbGxlZCB3aGVuIGFuIGl0ZW0gaXMgcmVtb3ZlZCBmcm9tIHRoZSBET00uIFRoZSBpbmRleCBhbmQgRE9NIGVsZW1lbnQgaXMgcHJvdmlkZWQgYXMgYXJndW1lbnRzLlxuICAgKlxuICAgKiAgICAgVGhlIGZ1bmN0aW9uIGlzIG9wdGlvbmFsIGJ1dCBtYXkgYmUgaW1wb3J0YW50IGluIG9yZGVyIHRvIGF2b2lkIG1lbW9yeSBsZWFrcy5cbiAgICogICBbL2VuXVxuICAgKiAgIFtqYV1cbiAgICogICAgIOOBk+OBrumWouaVsOOBr+OAgeOBguOCi+OCouOCpOODhuODoOOBjERPTeODhOODquODvOOBi+OCiemZpOOBi+OCjOOBn+aZguOBq+WRvOOBs+WHuuOBleOCjOOBvuOBmeOAglxuICAgKiAgICAg44Ki44Kk44OG44Og44Gu44Kk44Oz44OH44OD44Kv44K55YCk44GoRE9N6KaB57Sg44GM5byV5pWw44Go44GX44Gm5rih44GV44KM44G+44GZ44CCXG4gICAqICAgICDjgZPjga7plqLmlbDjga/jgqrjg5fjgrfjg6fjg4rjg6vjgafjgZnjgYzjgIHlkITjgqLjgqTjg4bjg6Djga7lvozlh6bnkIbjgYzlv4XopoHjgarloLTlkIjjgavjga/jg6Hjg6Ljg6rjg7zjg6rjg7zjgq/jgpLpgb/jgZHjgovjgZ/jgoHjgavph43opoHjgafjgZnjgIJcbiAgICogICBbL2phXVxuICAgKi9cblxuICBzZXQgZGVsZWdhdGUodXNlckRlbGVnYXRlKSB7XG4gICAgdGhpcy5fbGF6eVJlcGVhdFByb3ZpZGVyICYmIHRoaXMuX2xhenlSZXBlYXRQcm92aWRlci5kZXN0cm95KCk7XG5cbiAgICBpZiAoIXRoaXMuX3RlbXBsYXRlRWxlbWVudCAmJiB0aGlzLmNoaWxkcmVuWzBdKSB7XG4gICAgICB0aGlzLl90ZW1wbGF0ZUVsZW1lbnQgPSB0aGlzLnJlbW92ZUNoaWxkKHRoaXMuY2hpbGRyZW5bMF0pO1xuICAgIH1cblxuICAgIGNvbnN0IGRlbGVnYXRlID0gbmV3IExhenlSZXBlYXREZWxlZ2F0ZSh1c2VyRGVsZWdhdGUsIHRoaXMuX3RlbXBsYXRlRWxlbWVudCB8fCBudWxsKTtcbiAgICB0aGlzLl9sYXp5UmVwZWF0UHJvdmlkZXIgPSBuZXcgTGF6eVJlcGVhdFByb3ZpZGVyKHRoaXMucGFyZW50RWxlbWVudCwgZGVsZWdhdGUpO1xuICB9XG5cbiAgZ2V0IGRlbGVnYXRlKCkge1xuICAgIHV0aWwudGhyb3coJ05vIGRlbGVnYXRlIGdldHRlcicpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgcmVmcmVzaFxuICAgKiBAc2lnbmF0dXJlIHJlZnJlc2goKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmVmcmVzaCB0aGUgbGlzdC4gVXNlIHRoaXMgbWV0aG9kIHdoZW4gdGhlIGRhdGEgaGFzIGNoYW5nZWQuWy9lbl1cbiAgICogICBbamFd44Oq44K544OI44KS5pu05paw44GX44G+44GZ44CC44KC44GX44OH44O844K/44GM5aSJ44KP44Gj44Gf5aC05ZCI44Gr44Gv44GT44Gu44Oh44K944OD44OJ44KS5L2/44Gj44Gm44GP44Gg44GV44GE44CCWy9qYV1cbiAgICovXG4gIHJlZnJlc2goKSB7XG4gICAgdGhpcy5fbGF6eVJlcGVhdFByb3ZpZGVyICYmIHRoaXMuX2xhenlSZXBlYXRQcm92aWRlci5yZWZyZXNoKCk7XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge31cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBpZiAodGhpcy5fbGF6eVJlcGVhdFByb3ZpZGVyKSB7XG4gICAgICB0aGlzLl9sYXp5UmVwZWF0UHJvdmlkZXIuZGVzdHJveSgpO1xuICAgICAgdGhpcy5fbGF6eVJlcGVhdFByb3ZpZGVyID0gbnVsbDtcbiAgICB9XG4gIH1cblxufVxuXG5pbnRlcm5hbC5MYXp5UmVwZWF0RGVsZWdhdGUgPSBMYXp5UmVwZWF0RGVsZWdhdGU7XG5pbnRlcm5hbC5MYXp5UmVwZWF0UHJvdmlkZXIgPSBMYXp5UmVwZWF0UHJvdmlkZXI7XG5cbm9uc0VsZW1lbnRzLkxhenlSZXBlYXQgPSBMYXp5UmVwZWF0RWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWxhenktcmVwZWF0JywgTGF6eVJlcGVhdEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5cbmNvbnN0IGRlZmF1bHRDbGFzc05hbWUgPSAnbGlzdC1oZWFkZXInO1xuY29uc3Qgc2NoZW1lID0geycnOiAnbGlzdC1oZWFkZXItLSonfTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtbGlzdC1oZWFkZXJcbiAqIEBjYXRlZ29yeSBsaXN0XG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXUhlYWRlciBlbGVtZW50IGZvciBsaXN0IGl0ZW1zLiBNdXN0IGJlIHB1dCBpbnNpZGUgdGhlIGA8b25zLWxpc3Q+YCBjb21wb25lbnQuWy9lbl1cbiAqICAgW2phXeODquOCueODiOimgee0oOOBq+S9v+eUqOOBmeOCi+ODmOODg+ODgOODvOeUqOOCs+ODs+ODneODvOODjeODs+ODiOOAgm9ucy1saXN044Go5YWx44Gr5L2/55So44GX44G+44GZ44CCWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1saXN0XG4gKiAgIFtlbl1UaGUgYDxvbnMtbGlzdD5gIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtbGlzdOOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtbGlzdC1pdGVtXG4gKiAgIFtlbl1UaGUgYDxvbnMtbGlzdC1pdGVtPmAgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1saXN0LWl0ZW3jgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGNvZGVwZW4geXhjQ3RcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9saXN0XG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXURpc3BsYXkgYSBNYXRlcmlhbCBEZXNpZ24gbGlzdCBoZWFkZXIuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1saXN0PlxuICogICA8b25zLWxpc3QtaGVhZGVyPkhlYWRlciBUZXh0PC9vbnMtbGlzdC1oZWFkZXI+XG4gKiAgIDxvbnMtbGlzdC1pdGVtPkl0ZW08L29ucy1saXN0LWl0ZW0+XG4gKiAgIDxvbnMtbGlzdC1pdGVtPkl0ZW08L29ucy1saXN0LWl0ZW0+XG4gKiA8L29ucy1saXN0PlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMaXN0SGVhZGVyRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIGxpc3QgaGVhZGVyLlsvZW5dXG4gICAqICAgW2phXeODmOODg+ODgOODvOOBruihqOePvuOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9jb21waWxlKCk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG59XG5cbm9uc0VsZW1lbnRzLkxpc3RIZWFkZXIgPSBMaXN0SGVhZGVyRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWxpc3QtaGVhZGVyJywgTGlzdEhlYWRlckVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5cbmNvbnN0IGRlZmF1bHRDbGFzc05hbWUgPSAnbGlzdC10aXRsZSc7XG5jb25zdCBzY2hlbWUgPSB7Jyc6ICdsaXN0LXRpdGxlLS0qJ307XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWxpc3QtdGl0bGVcbiAqIEBjYXRlZ29yeSBsaXN0XG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVJlcHJlc2VudHMgYSBsaXN0IHRpdGxlLlsvZW5dXG4gKiAgIFtqYV3jg6rjgrnjg4jjga7jgr/jgqTjg4jjg6vjgpLooajnj77jgZfjgb7jgZnjgIJbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtbGlzdC10aXRsZT5MaXN0IFRpdGxlPC9vbnMtbGlzdC10aXRsZT5cbiAqIDxvbnMtbGlzdD5cbiAqICAgPG9ucy1saXN0LWl0ZW0+SXRlbTwvb25zLWxpc3QtaXRlbT5cbiAqIDwvb25zLWxpc3Q+XG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXURpc3BsYXkgYSBNYXRlcmlhbCBEZXNpZ24gbGlzdCB0aXRsZS5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqL1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMaXN0VGl0bGVFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9jb21waWxlKCk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG59XG5cbm9uc0VsZW1lbnRzLkxpc3RUaXRsZSA9IExpc3RUaXRsZUVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1saXN0LXRpdGxlJywgTGlzdFRpdGxlRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxOCBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi8uLi9vbnMvYW5pbWl0JztcbmltcG9ydCBCYXNlQW5pbWF0b3IgZnJvbSAnLi4vLi4vb25zL2Jhc2UtYW5pbWF0b3InXG5cbmV4cG9ydCBjbGFzcyBMaXN0SXRlbUFuaW1hdG9yIGV4dGVuZHMgQmFzZUFuaW1hdG9yIHtcbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdsaW5lYXInLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC4yfSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcbiAgfVxuXG4gIHNob3dFeHBhbnNpb24obGlzdEl0ZW0sIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIGhpZGVFeHBhbnNpb24obGlzdEl0ZW0sIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgU2xpZGVMaXN0SXRlbUFuaW1hdG9yIGV4dGVuZHMgTGlzdEl0ZW1BbmltYXRvciB7XG5cbiAgc2hvd0V4cGFuc2lvbihsaXN0SXRlbSwgY2FsbGJhY2spIHtcbiAgICB0aGlzLl9hbmltYXRlRXhwYW5zaW9uKGxpc3RJdGVtLCB0cnVlLCBjYWxsYmFjayk7XG4gIH1cblxuICBoaWRlRXhwYW5zaW9uKGxpc3RJdGVtLCBjYWxsYmFjaykge1xuICAgIHRoaXMuX2FuaW1hdGVFeHBhbnNpb24obGlzdEl0ZW0sIGZhbHNlLCBjYWxsYmFjayk7XG4gIH1cblxuICBfYW5pbWF0ZUV4cGFuc2lvbihsaXN0SXRlbSwgc2hvdWxkT3BlbiwgY2FsbGJhY2spIHtcbiAgICAvLyBUbyBhbmltYXRlIHRoZSBvcGVuaW5nIG9mIHRoZSBleHBhbnNpb24gcGFuZWwgY29ycmVjdGx5LCB3ZSBuZWVkIHRvIGtub3cgaXRzXG4gICAgLy8gaGVpZ2h0LiBUbyBjYWxjdWxhdGUgdGhpcywgd2Ugc2V0IGl0cyBoZWlnaHQgdG8gYXV0bywgYW5kIHRoZW4gZ2V0IHRoZSBjb21wdXRlZFxuICAgIC8vIGhlaWdodCBhbmQgcGFkZGluZy4gT25jZSB0aGlzIGlzIGRvbmUsIHdlIHNldCB0aGUgaGVpZ2h0IGJhY2sgdG8gaXRzIG9yaWdpbmFsIHZhbHVlLlxuICAgIGNvbnN0IG9sZEhlaWdodCA9IGxpc3RJdGVtLmV4cGFuZGFibGVDb250ZW50LnN0eWxlLmhlaWdodDtcbiAgICBjb25zdCBvbGREaXNwbGF5ID0gbGlzdEl0ZW0uZXhwYW5kYWJsZUNvbnRlbnQuc3R5bGUuZGlzcGxheTtcbiAgICBsaXN0SXRlbS5leHBhbmRhYmxlQ29udGVudC5zdHlsZS5oZWlnaHQgPSAnYXV0byc7XG4gICAgbGlzdEl0ZW0uZXhwYW5kYWJsZUNvbnRlbnQuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgY29uc3QgY29tcHV0ZWRTdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGxpc3RJdGVtLmV4cGFuZGFibGVDb250ZW50KTtcblxuICAgIGNvbnN0IGV4cGFuc2lvbk9wZW5UcmFuc2l0aW9uID0gW1xuICAgICAgeyBoZWlnaHQ6IDAsIHBhZGRpbmdUb3A6IDAsIHBhZGRpbmdCb3R0b206IDAgfSxcbiAgICAgIHtcbiAgICAgICAgaGVpZ2h0OiBjb21wdXRlZFN0eWxlLmhlaWdodCxcbiAgICAgICAgcGFkZGluZ1RvcDogY29tcHV0ZWRTdHlsZS5wYWRkaW5nVG9wLFxuICAgICAgICBwYWRkaW5nQm90dG9tOiBjb21wdXRlZFN0eWxlLnBhZGRpbmdCb3R0b20sXG4gICAgICB9XG4gICAgXTtcbiAgICBjb25zdCBpY29uT3BlblRyYW5zaXRpb24gPSBbe3RyYW5zZm9ybTogJ3JvdGF0ZSg0NWRlZyknfSwge3RyYW5zZm9ybTogJ3JvdGF0ZSgyMjVkZWcpJ31dO1xuXG4gICAgLy8gTm93IHRoYXQgd2UgaGF2ZSB0aGUgdmFsdWVzIHdlIG5lZWQsIHJlc2V0IHRoZSBoZWlnaHQgYmFjayB0byBpdHMgb3JpZ2luYWwgc3RhdGVcbiAgICBsaXN0SXRlbS5leHBhbmRhYmxlQ29udGVudC5zdHlsZS5oZWlnaHQgPSBvbGRIZWlnaHQ7XG5cbiAgICBhbmltaXQobGlzdEl0ZW0uZXhwYW5kYWJsZUNvbnRlbnQsIHsgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sIHByb3BlcnR5OiAnaGVpZ2h0IHBhZGRpbmctdG9wIHBhZGRpbmctYm90dG9tJyB9KVxuICAgICAgLmRlZmF1bHQoLi4uKHNob3VsZE9wZW4gPyBleHBhbnNpb25PcGVuVHJhbnNpdGlvbiA6IGV4cGFuc2lvbk9wZW5UcmFuc2l0aW9uLnJldmVyc2UoKSkpXG4gICAgICAucGxheSgoKSA9PiB7XG4gICAgICAgIGxpc3RJdGVtLmV4cGFuZGFibGVDb250ZW50LnN0eWxlLmRpc3BsYXkgPSBvbGREaXNwbGF5O1xuICAgICAgICBjYWxsYmFjayAmJiBjYWxsYmFjaygpO1xuICAgICAgfSk7XG5cbiAgICBpZiAobGlzdEl0ZW0uZXhwYW5kQ2hldnJvbikge1xuICAgICAgYW5pbWl0KGxpc3RJdGVtLmV4cGFuZENoZXZyb24sIHsgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sIHByb3BlcnR5OiAndHJhbnNmb3JtJyB9KVxuICAgICAgICAuZGVmYXVsdCguLi4oc2hvdWxkT3BlbiA/IGljb25PcGVuVHJhbnNpdGlvbiA6IGljb25PcGVuVHJhbnNpdGlvbi5yZXZlcnNlKCkpKVxuICAgICAgICAucGxheSgpO1xuICAgIH1cbiAgfVxuXG59IiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uLy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IHN0eWxlciBmcm9tICcuLi8uLi9vbnMvc3R5bGVyJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBBbmltYXRvckZhY3RvcnkgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL2FuaW1hdG9yLWZhY3RvcnknO1xuaW1wb3J0IHsgTGlzdEl0ZW1BbmltYXRvciwgU2xpZGVMaXN0SXRlbUFuaW1hdG9yIH0gZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi8uLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IGRlZmF1bHRDbGFzc05hbWUgPSAnbGlzdC1pdGVtJztcbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy5saXN0LWl0ZW0nOiAnbGlzdC1pdGVtLS0qJyxcbiAgJy5saXN0LWl0ZW1fX2xlZnQnOiAnbGlzdC1pdGVtLS0qX19sZWZ0JyxcbiAgJy5saXN0LWl0ZW1fX2NlbnRlcic6ICdsaXN0LWl0ZW0tLSpfX2NlbnRlcicsXG4gICcubGlzdC1pdGVtX19yaWdodCc6ICdsaXN0LWl0ZW0tLSpfX3JpZ2h0JyxcbiAgJy5saXN0LWl0ZW1fX2xhYmVsJzogJ2xpc3QtaXRlbS0tKl9fbGFiZWwnLFxuICAnLmxpc3QtaXRlbV9fdGl0bGUnOiAnbGlzdC1pdGVtLS0qX190aXRsZScsXG4gICcubGlzdC1pdGVtX19zdWJ0aXRsZSc6ICdsaXN0LWl0ZW0tLSpfX3N1YnRpdGxlJyxcbiAgJy5saXN0LWl0ZW1fX3RodW1ibmFpbCc6ICdsaXN0LWl0ZW0tLSpfX3RodW1ibmFpbCcsXG4gICcubGlzdC1pdGVtX19pY29uJzogJ2xpc3QtaXRlbS0tKl9faWNvbidcbn07XG5cbmNvbnN0IF9hbmltYXRvckRpY3QgPSB7XG4gICdkZWZhdWx0JzogU2xpZGVMaXN0SXRlbUFuaW1hdG9yLFxuICAnbm9uZSc6IExpc3RJdGVtQW5pbWF0b3Jcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWxpc3QtaXRlbVxuICogQGNhdGVnb3J5IGxpc3RcbiAqIEBtb2RpZmllciB0YXBwYWJsZVxuICogICBbZW5dTWFrZSB0aGUgbGlzdCBpdGVtIGNoYW5nZSBhcHBlYXJhbmNlIHdoZW4gaXQncyB0YXBwZWQuIE9uIGlPUyBpdCBpcyBiZXR0ZXIgdG8gdXNlIHRoZSBcInRhcHBhYmxlXCIgYW5kIFwidGFwLWJhY2tncm91bmQtY29sb3JcIiBhdHRyaWJ1dGUgZm9yIGJldHRlciBiZWhhdmlvciB3aGVuIHNjcm9sbGluZy5bL2VuXVxuICogICBbamFd44K/44OD44OX44KE44Kv44Oq44OD44Kv44GX44Gf5pmC44Gr5Yq55p6c44GM6KGo56S644GV44KM44KL44KI44GG44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAqIEBtb2RpZmllciBjaGV2cm9uXG4gKiAgIFtlbl1EaXNwbGF5IGEgY2hldnJvbiBhdCB0aGUgcmlnaHQgZW5kIG9mIHRoZSBsaXN0IGl0ZW0gYW5kIG1ha2UgaXQgY2hhbmdlIGFwcGVhcmFuY2Ugd2hlbiB0YXBwZWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAbW9kaWZpZXIgbG9uZ2RpdmlkZXJcbiAqICAgW2VuXURpc3BsYXlzIGEgbG9uZyBob3Jpem9udGFsIGRpdmlkZXIgYmV0d2VlbiBpdGVtcy5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBtb2RpZmllciBub2RpdmlkZXJcbiAqICAgW2VuXVJlbW92ZXMgdGhlIGRpdmlkZXIgYmV0d2VlbiBsaXN0IGl0ZW1zLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1EaXNwbGF5IGEgTWF0ZXJpYWwgRGVzaWduIGxpc3QgaXRlbS5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgQ29tcG9uZW50IHRoYXQgcmVwcmVzZW50cyBlYWNoIGl0ZW0gaW4gYSBsaXN0LiBUaGUgbGlzdCBpdGVtIGlzIGNvbXBvc2VkIG9mIGZvdXIgcGFydHMgdGhhdCBhcmUgcmVwcmVzZW50ZWQgd2l0aCB0aGUgYGxlZnRgLCBgY2VudGVyYCwgYHJpZ2h0YCBhbmQgYGV4cGFuZGFibGUtY29udGVudGAgY2xhc3Nlcy4gVGhlc2UgY2xhc3NlcyBjYW4gYmUgdXNlZCB0byBlbnN1cmUgdGhhdCB0aGUgY29udGVudCBvZiB0aGUgbGlzdCBpdGVtcyBpcyBwcm9wZXJseSBhbGlnbmVkLlxuICpcbiAqICAgICBgYGBcbiAqICAgICA8b25zLWxpc3QtaXRlbT5cbiAqICAgICAgIDxkaXYgY2xhc3M9XCJsZWZ0XCI+TGVmdDwvZGl2PlxuICogICAgICAgPGRpdiBjbGFzcz1cImNlbnRlclwiPkNlbnRlcjwvZGl2PlxuICogICAgICAgPGRpdiBjbGFzcz1cInJpZ2h0XCI+UmlnaHQ8L2Rpdj5cbiAqICAgICAgIDxkaXYgY2xhc3M9XCJleHBhbmRhYmxlLWNvbnRlbnRcIj5FeHBhbmRhYmxlIGNvbnRlbnQ8L2Rpdj5cbiAqICAgICA8L29ucy1saXN0LWl0ZW0+XG4gKiAgICAgYGBgXG4gKlxuICogICAgIFRoZXJlIGFyZSBhbHNvIGEgbnVtYmVyIG9mIGNsYXNzZXMgKHByZWZpeGVkIHdpdGggYGxpc3QtaXRlbV9fKmApIHRoYXQgaGVscCB3aGVuIHB1dHRpbmcgdGhpbmdzIGxpa2UgaWNvbnMgYW5kIHRodW1ibmFpbHMgaW50byB0aGUgbGlzdCBpdGVtcy5cbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtbGlzdFxuICogICBbZW5db25zLWxpc3QgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1saXN044Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1saXN0LWhlYWRlclxuICogICBbZW5db25zLWxpc3QtaGVhZGVyIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtbGlzdC1oZWFkZXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGNvZGVwZW4geXhjQ3RcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9saXN0XG4gKiBAZXhhbXBsZVxuICogPG9ucy1saXN0LWl0ZW0+XG4gKiAgIDxkaXYgY2xhc3M9XCJsZWZ0XCI+XG4gKiAgICAgPG9ucy1pY29uIGljb249XCJtZC1mYWNlXCIgY2xhc3M9XCJsaXN0LWl0ZW1fX2ljb25cIj48L29ucy1pY29uPlxuICogICA8L2Rpdj5cbiAqICAgPGRpdiBjbGFzcz1cImNlbnRlclwiPlxuICogICAgIDxkaXYgY2xhc3M9XCJsaXN0LWl0ZW1fX3RpdGxlXCI+VGl0bGU8L2Rpdj5cbiAqICAgICA8ZGl2IGNsYXNzPVwibGlzdC1pdGVtX19zdWJ0aXRsZVwiPlN1YnRpdGxlPC9kaXY+XG4gKiAgIDwvZGl2PlxuICogICA8ZGl2IGNsYXNzPVwicmlnaHRcIj5cbiAqICAgICA8b25zLXN3aXRjaD48L29ucy1zd2l0Y2g+XG4gKiAgIDwvZGl2PlxuICogPC9vbnMtbGlzdC1pdGVtPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMaXN0SXRlbUVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBsaXN0IGl0ZW0uWy9lbl1cbiAgICogICBbamFd5ZCE6KaB57Sg44Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbG9jay1vbi1kcmFnXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1QcmV2ZW50IHZlcnRpY2FsIHNjcm9sbGluZyB3aGVuIHRoZSB1c2VyIGRyYWdzIGhvcml6b250YWxseS5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovjgajjgIHjg6bjg7zjgrbjg7zjgYzjgZPjga7opoHntKDjgpLmqKrmlrnlkJHjgavjg4njg6njg4PjgrDjgZfjgabjgYTjgovmmYLjgavjgIHnuKbmlrnlkJHjga7jgrnjgq/jg63jg7zjg6vjgYzotbfjgY3jgarjgYTjgojjgYbjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSB0YXBwYWJsZVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXU1ha2VzIHRoZSBlbGVtZW50IHJlYWN0IHRvIHRhcHMuIGBwcmV2ZW50LXRhcGAgYXR0cmlidXRlIGNhbiBiZSBhZGRlZCB0byBjaGlsZCBlbGVtZW50cyBsaWtlIGJ1dHRvbnMgb3IgaW5wdXRzIHRvIHByZXZlbnQgdGhpcyBlZmZlY3QuIGBvbnMtKmAgZWxlbWVudHMgYXJlIGlnbm9yZWQgYnkgZGVmYXVsdC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSB0YXAtYmFja2dyb3VuZC1jb2xvclxuICAgKiBAdHlwZSB7Q29sb3J9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl0gQ2hhbmdlcyB0aGUgYmFja2dyb3VuZCBjb2xvciB3aGVuIHRhcHBlZC4gRm9yIHRoaXMgdG8gd29yaywgdGhlIGF0dHJpYnV0ZSBcInRhcHBhYmxlXCIgbmVlZHMgdG8gYmUgc2V0LiBUaGUgZGVmYXVsdCBjb2xvciBpcyBcIiNkOWQ5ZDlcIi4gSXQgd2lsbCBkaXNwbGF5IGFzIGEgcmlwcGxlIGVmZmVjdCBvbiBBbmRyb2lkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGV4cGFuZGFibGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1NYWtlcyB0aGUgZWxlbWVudCBhYmxlIHRvIGJlIGV4cGFuZGVkIHRvIHJldmVhbCBleHRyYSBjb250ZW50LiBGb3IgdGhpcyB0byB3b3JrLCB0aGUgZXhwYW5kYWJsZSBjb250ZW50IG11c3QgYmUgZGVmaW5lZCBpbiBgZGl2LmV4cGFuZGFibGUtY29udGVudGAuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGRlZmF1bHRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFuaW1hdGlvbiB1c2VkIHdoZW4gc2hvd2luZyBhbmQgaGlkaW5nIHRoZSBleHBhbmRhYmxlIGNvbnRlbnQuIENhbiBiZSBlaXRoZXIgYFwiZGVmYXVsdFwiYCBvciBgXCJub25lXCJgLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX2FuaW1hdG9yRmFjdG9yeSA9IHRoaXMuX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSgpO1xuICAgIHRoaXMudG9nZ2xlRXhwYW5zaW9uID0gdGhpcy50b2dnbGVFeHBhbnNpb24uYmluZCh0aGlzKTtcblxuICAgIC8vIEVsZW1lbnRzIGlnbm9yZWQgd2hlbiB0YXBwaW5nXG4gICAgY29uc3QgcmUgPSAvXm9ucy0oPyFjb2wkfHJvdyR8aWYkKS9pO1xuICAgIHRoaXMuX3Nob3VsZElnbm9yZVRhcCA9IGUgPT4gZS5oYXNBdHRyaWJ1dGUoJ3ByZXZlbnQtdGFwJykgfHwgcmUudGVzdChlLnRhZ05hbWUpO1xuXG4gICAgLy8gc2hvdyBhbmQgaGlkZSBmdW5jdGlvbnMgZm9yIFZ1ZSBoaWRhYmxlIG1peGluXG4gICAgdGhpcy5zaG93ID0gdGhpcy5zaG93RXhwYW5zaW9uO1xuICAgIHRoaXMuaGlkZSA9IHRoaXMuaGlkZUV4cGFuc2lvbjtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9jb21waWxlKCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ29tcGlsZXMgdGhlIGxpc3QgaXRlbS5cbiAgICpcbiAgICogVmFyaW91cyBlbGVtZW50cyBhcmUgYWxsb3dlZCBpbiB0aGUgYm9keSBvZiBhIGxpc3QgaXRlbTpcbiAgICpcbiAgICogIC0gZGl2LmxlZnQsIGRpdi5yaWdodCwgYW5kIGRpdi5jZW50ZXIgYXJlIGFsbG93ZWQgYXMgZGlyZWN0IGNoaWxkcmVuXG4gICAqICAtIGlmIGRpdi5jZW50ZXIgaXMgbm90IGRlZmluZWQsIGFueXRoaW5nIHRoYXQgaXNuJ3QgZGl2LmxlZnQsIGRpdi5yaWdodCBvciBkaXYuZXhwYW5kYWJsZS1jb250ZW50IHdpbGwgYmUgcHV0IGluIGEgZGl2LmNlbnRlclxuICAgKiAgLSBpZiBkaXYuY2VudGVyIGlzIGRlZmluZWQsIGFueXRoaW5nIHRoYXQgaXNuJ3QgZGl2LmxlZnQsIGRpdi5yaWdodCBvciBkaXYuZXhwYW5kYWJsZS1jb250ZW50IHdpbGwgYmUgaWdub3JlZFxuICAgKiAgLSBpZiBsaXN0IGl0ZW0gaGFzIGV4cGFuZGFibGUgYXR0cmlidXRlOlxuICAgKiAgICAgIC0gZGl2LmV4cGFuZGFibGUtY29udGVudCBpcyBhbGxvd2VkIGFzIGEgZGlyZWN0IGNoaWxkXG4gICAqICAgICAgLSBkaXYudG9wIGlzIGFsbG93ZWQgYXMgZGlyZWN0IGNoaWxkXG4gICAqICAgICAgLSBpZiBkaXYudG9wIGlzIGRlZmluZWQsIGFueXRoaW5nIHRoYXQgaXNuJ3QgZGl2LmV4cGFuZGFibGUtY29udGVudCBzaG91bGQgYmUgaW5zaWRlIGRpdi50b3AgLSBhbnl0aGluZyBlbHNlIHdpbGwgYmUgaWdub3JlZFxuICAgKiAgICAgIC0gaWYgZGl2LnJpZ2h0IGlzIG5vdCBkZWZpbmVkLCBhIGRpdi5yaWdodCB3aWxsIGJlIGNyZWF0ZWQgd2l0aCBhIGRyb3AtZG93biBjaGV2cm9uXG4gICAqXG4gICAqIFNlZSB0aGUgdGVzdHMgZm9yIGV4YW1wbGVzLlxuICAgKi9cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKGRlZmF1bHRDbGFzc05hbWUpO1xuXG4gICAgbGV0IHRvcCwgZXhwYW5kYWJsZUNvbnRlbnQ7XG4gICAgbGV0IHRvcENvbnRlbnQgPSBbXTtcbiAgICBBcnJheS5mcm9tKHRoaXMuY2hpbGROb2RlcykuZm9yRWFjaChub2RlID0+IHtcbiAgICAgIGlmIChub2RlLm5vZGVUeXBlICE9PSBOb2RlLkVMRU1FTlRfTk9ERSkge1xuICAgICAgICB0b3BDb250ZW50LnB1c2gobm9kZSk7XG4gICAgICB9IGVsc2UgaWYgKG5vZGUuY2xhc3NMaXN0LmNvbnRhaW5zKCd0b3AnKSkge1xuICAgICAgICB0b3AgPSBub2RlO1xuICAgICAgfSBlbHNlIGlmIChub2RlLmNsYXNzTGlzdC5jb250YWlucygnZXhwYW5kYWJsZS1jb250ZW50JykpIHtcbiAgICAgICAgZXhwYW5kYWJsZUNvbnRlbnQgPSBub2RlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdG9wQ29udGVudC5wdXNoKG5vZGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAobm9kZS5ub2RlTmFtZSAhPT0gJ09OUy1SSVBQTEUnKSB7XG4gICAgICAgIG5vZGUucmVtb3ZlKCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgdG9wQ29udGVudCA9IHRvcCA/IEFycmF5LmZyb20odG9wLmNoaWxkTm9kZXMpIDogdG9wQ29udGVudDtcblxuICAgIGxldCBsZWZ0LCByaWdodCwgY2VudGVyO1xuICAgIGNvbnN0IGNlbnRlckNvbnRlbnQgPSBbXTtcbiAgICB0b3BDb250ZW50LmZvckVhY2gobm9kZSA9PiB7XG4gICAgICBpZiAobm9kZS5ub2RlVHlwZSAhPT0gTm9kZS5FTEVNRU5UX05PREUpIHtcbiAgICAgICAgY2VudGVyQ29udGVudC5wdXNoKG5vZGUpO1xuICAgICAgfSBlbHNlIGlmIChub2RlLmNsYXNzTGlzdC5jb250YWlucygnbGVmdCcpKSB7XG4gICAgICAgIGxlZnQgPSBub2RlO1xuICAgICAgfSBlbHNlIGlmIChub2RlLmNsYXNzTGlzdC5jb250YWlucygncmlnaHQnKSkge1xuICAgICAgICByaWdodCA9IG5vZGU7XG4gICAgICB9IGVsc2UgaWYgKG5vZGUuY2xhc3NMaXN0LmNvbnRhaW5zKCdjZW50ZXInKSkge1xuICAgICAgICBjZW50ZXIgPSBub2RlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2VudGVyQ29udGVudC5wdXNoKG5vZGUpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdleHBhbmRhYmxlJykpIHtcbiAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnbGlzdC1pdGVtLS1leHBhbmRhYmxlJyk7XG5cbiAgICAgIGlmICghdG9wKSB7XG4gICAgICAgIHRvcCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICB0b3AuY2xhc3NMaXN0LmFkZCgndG9wJyk7XG4gICAgICB9XG4gICAgICB0b3AuY2xhc3NMaXN0LmFkZCgnbGlzdC1pdGVtX190b3AnKTtcbiAgICAgIHRoaXMuYXBwZW5kQ2hpbGQodG9wKTtcbiAgICAgIHRoaXMuX3RvcCA9IHRvcDtcblxuICAgICAgaWYgKGV4cGFuZGFibGVDb250ZW50KSB7XG4gICAgICAgIGV4cGFuZGFibGVDb250ZW50LmNsYXNzTGlzdC5hZGQoJ2xpc3QtaXRlbV9fZXhwYW5kYWJsZS1jb250ZW50Jyk7XG4gICAgICAgIHRoaXMuYXBwZW5kQ2hpbGQoZXhwYW5kYWJsZUNvbnRlbnQpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXJpZ2h0KSB7XG4gICAgICAgIHJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIHJpZ2h0LmNsYXNzTGlzdC5hZGQoJ2xpc3QtaXRlbV9fcmlnaHQnLCAncmlnaHQnKTtcblxuICAgICAgICAvLyBXZSBjYW5ub3QgdXNlIGEgcHNldWRvLWVsZW1lbnQgZm9yIHRoaXMgY2hldnJvbiwgYXMgd2UgY2Fubm90IGFuaW1hdGUgaXQgdXNpbmdcbiAgICAgICAgLy8gSlMuIFNvLCB3ZSBtYWtlIGEgY2hldnJvbiBzcGFuIGluc3RlYWQuXG4gICAgICAgIGNvbnN0IGNoZXZyb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XG4gICAgICAgIGNoZXZyb24uY2xhc3NMaXN0LmFkZCgnbGlzdC1pdGVtX19leHBhbmQtY2hldnJvbicpO1xuICAgICAgICByaWdodC5hcHBlbmRDaGlsZChjaGV2cm9uKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdG9wID0gdGhpcztcbiAgICB9XG5cbiAgICBpZiAoIWNlbnRlcikge1xuICAgICAgY2VudGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICBjZW50ZXIuY2xhc3NMaXN0LmFkZCgnY2VudGVyJyk7XG4gICAgICBjZW50ZXJDb250ZW50LmZvckVhY2gobm9kZSA9PiBjZW50ZXIuYXBwZW5kQ2hpbGQobm9kZSkpO1xuICAgIH1cbiAgICBjZW50ZXIuY2xhc3NMaXN0LmFkZCgnbGlzdC1pdGVtX19jZW50ZXInKTtcbiAgICB0b3AuYXBwZW5kQ2hpbGQoY2VudGVyKTtcblxuICAgIGlmIChsZWZ0KSB7XG4gICAgICBsZWZ0LmNsYXNzTGlzdC5hZGQoJ2xpc3QtaXRlbV9fbGVmdCcpO1xuICAgICAgdG9wLmFwcGVuZENoaWxkKGxlZnQpO1xuICAgIH1cbiAgICBpZiAocmlnaHQpIHtcbiAgICAgIHJpZ2h0LmNsYXNzTGlzdC5hZGQoJ2xpc3QtaXRlbV9fcmlnaHQnKTtcbiAgICAgIHRvcC5hcHBlbmRDaGlsZChyaWdodCk7XG4gICAgfVxuXG4gICAgdXRpbC51cGRhdGVSaXBwbGUodGhpcyk7XG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2Qgc2hvd0V4cGFuc2lvblxuICAgKiBAc2lnbmF0dXJlIHNob3dFeHBhbnNpb24oKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyB0aGUgZXhwYW5kYWJsZSBjb250ZW50IGlmIHRoZSBlbGVtZW50IGlzIGV4cGFuZGFibGUuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIHNob3dFeHBhbnNpb24oKSB7XG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdleHBhbmRhYmxlJykgJiYgIXRoaXMuX2V4cGFuZGluZykge1xuICAgICAgdGhpcy5leHBhbmRlZCA9IHRydWU7XG4gICAgICB0aGlzLl9leHBhbmRpbmcgPSB0cnVlO1xuXG4gICAgICBjb25zdCBhbmltYXRvciA9IHRoaXMuX2FuaW1hdG9yRmFjdG9yeS5uZXdBbmltYXRvcigpO1xuICAgICAgYW5pbWF0b3Iuc2hvd0V4cGFuc2lvbih0aGlzLCAoKSA9PiB7XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnZXhwYW5kZWQnKTtcbiAgICAgICAgdGhpcy5fZXhwYW5kaW5nID0gZmFsc2U7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBoaWRlRXhwYW5zaW9uXG4gICAqIEBzaWduYXR1cmUgaGlkZUV4cGFuc2lvbigpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1IaWRlIHRoZSBleHBhbmRhYmxlIGNvbnRlbnQgaWYgdGhlIGVsZW1lbnQgZXhwYW5kYWJsZS5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgaGlkZUV4cGFuc2lvbigpIHtcbiAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ2V4cGFuZGFibGUnKSAmJiAhdGhpcy5fZXhwYW5kaW5nKSB7XG4gICAgICB0aGlzLmV4cGFuZGVkID0gZmFsc2U7XG4gICAgICB0aGlzLl9leHBhbmRpbmcgPSB0cnVlO1xuXG4gICAgICBjb25zdCBhbmltYXRvciA9IHRoaXMuX2FuaW1hdG9yRmFjdG9yeS5uZXdBbmltYXRvcigpO1xuICAgICAgYW5pbWF0b3IuaGlkZUV4cGFuc2lvbih0aGlzLCAoKSA9PiB7XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LnJlbW92ZSgnZXhwYW5kZWQnKTtcbiAgICAgICAgdGhpcy5fZXhwYW5kaW5nID0gZmFsc2U7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICB0b2dnbGVFeHBhbnNpb24oKSB7XG4gICAgdGhpcy5jbGFzc0xpc3QuY29udGFpbnMoJ2V4cGFuZGVkJykgPyB0aGlzLmhpZGVFeHBhbnNpb24oKSA6IHRoaXMuc2hvd0V4cGFuc2lvbigpO1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2V4cGFuc2lvbicpKTtcbiAgfVxuXG4gIF91cGRhdGVBbmltYXRvckZhY3RvcnkoKSB7XG4gICAgcmV0dXJuIG5ldyBBbmltYXRvckZhY3Rvcnkoe1xuICAgICAgYW5pbWF0b3JzOiBfYW5pbWF0b3JEaWN0LFxuICAgICAgYmFzZUNsYXNzOiBMaXN0SXRlbUFuaW1hdG9yLFxuICAgICAgYmFzZUNsYXNzTmFtZTogJ0xpc3RJdGVtQW5pbWF0b3InLFxuICAgICAgZGVmYXVsdEFuaW1hdGlvbjogdGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpIHx8ICdkZWZhdWx0J1xuICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnY2xhc3MnLCAncmlwcGxlJywgJ2FuaW1hdGlvbiddO1xuICB9XG5cbiAgZ2V0IGV4cGFuZGFibGVDb250ZW50KCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3IoJy5saXN0LWl0ZW1fX2V4cGFuZGFibGUtY29udGVudCcpO1xuICB9XG5cbiAgZ2V0IGV4cGFuZENoZXZyb24oKSB7XG4gICAgcmV0dXJuIHRoaXMucXVlcnlTZWxlY3RvcignLmxpc3QtaXRlbV9fZXhwYW5kLWNoZXZyb24nKTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdyaXBwbGUnOlxuICAgICAgICB1dGlsLnVwZGF0ZVJpcHBsZSh0aGlzKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdhbmltYXRpb24nOlxuICAgICAgICB0aGlzLl9hbmltYXRvckZhY3RvcnkgPSB0aGlzLl91cGRhdGVBbmltYXRvckZhY3RvcnkoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX3NldHVwTGlzdGVuZXJzKHRydWUpO1xuICAgICAgdGhpcy5fb3JpZ2luYWxCYWNrZ3JvdW5kQ29sb3IgPSB0aGlzLnN0eWxlLmJhY2tncm91bmRDb2xvcjtcbiAgICAgIHRoaXMudGFwcGVkID0gZmFsc2U7XG4gICAgfSk7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLl9zZXR1cExpc3RlbmVycyhmYWxzZSk7XG4gIH1cblxuICBfc2V0dXBMaXN0ZW5lcnMoYWRkKSB7XG4gICAgY29uc3QgYWN0aW9uID0gKGFkZCA/ICdhZGQnIDogJ3JlbW92ZScpICsgJ0V2ZW50TGlzdGVuZXInO1xuICAgIHV0aWxbYWN0aW9uXSh0aGlzLCAndG91Y2hzdGFydCcsIHRoaXMuX29uVG91Y2gsIHsgcGFzc2l2ZTogdHJ1ZSB9KTtcbiAgICB1dGlsW2FjdGlvbl0odGhpcywgJ3RvdWNobW92ZScsIHRoaXMuX29uUmVsZWFzZSwgeyBwYXNzaXZlOiB0cnVlIH0pO1xuICAgIHRoaXNbYWN0aW9uXSgndG91Y2hjYW5jZWwnLCB0aGlzLl9vblJlbGVhc2UpO1xuICAgIHRoaXNbYWN0aW9uXSgndG91Y2hlbmQnLCB0aGlzLl9vblJlbGVhc2UpO1xuICAgIHRoaXNbYWN0aW9uXSgndG91Y2hsZWF2ZScsIHRoaXMuX29uUmVsZWFzZSk7XG4gICAgdGhpc1thY3Rpb25dKCdkcmFnJywgdGhpcy5fb25EcmFnKTtcbiAgICB0aGlzW2FjdGlvbl0oJ21vdXNlZG93bicsIHRoaXMuX29uVG91Y2gpO1xuICAgIHRoaXNbYWN0aW9uXSgnbW91c2V1cCcsIHRoaXMuX29uUmVsZWFzZSk7XG4gICAgdGhpc1thY3Rpb25dKCdtb3VzZW91dCcsIHRoaXMuX29uUmVsZWFzZSk7XG5cbiAgICBpZiAodGhpcy5fdG9wKSB7XG4gICAgICB0aGlzLl90b3BbYWN0aW9uXSgnY2xpY2snLCB0aGlzLnRvZ2dsZUV4cGFuc2lvbik7XG4gICAgfVxuICB9XG5cbiAgX29uRHJhZyhldmVudCkge1xuICAgIGNvbnN0IGdlc3R1cmUgPSBldmVudC5nZXN0dXJlO1xuICAgIC8vIFByZXZlbnQgdmVydGljYWwgc2Nyb2xsaW5nIGlmIHRoZSB1c2VycyBwYW5zIGxlZnQgb3IgcmlnaHQuXG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdsb2NrLW9uLWRyYWcnKSAmJiBbJ2xlZnQnLCAncmlnaHQnXS5pbmRleE9mKGdlc3R1cmUuZGlyZWN0aW9uKSA+IC0xKSB7XG4gICAgICBnZXN0dXJlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuICB9XG5cbiAgX29uVG91Y2goZSkge1xuICAgIGlmICh0aGlzLnRhcHBlZCB8fFxuICAgICAgKHRoaXMgIT09IGUudGFyZ2V0ICYmICh0aGlzLl9zaG91bGRJZ25vcmVUYXAoZS50YXJnZXQpIHx8IHV0aWwuZmluZFBhcmVudChlLnRhcmdldCwgdGhpcy5fc2hvdWxkSWdub3JlVGFwLCBwID0+IHAgPT09IHRoaXMpKSlcbiAgICApIHtcbiAgICAgIHJldHVybjsgLy8gSWdub3JlIHRhcFxuICAgIH1cblxuICAgIHRoaXMudGFwcGVkID0gdHJ1ZTtcbiAgICBjb25zdCB0b3VjaFN0eWxlID0geyB0cmFuc2l0aW9uOiAnYmFja2dyb3VuZC1jb2xvciAwLjBzIGxpbmVhciAwLjAycywgYm94LXNoYWRvdyAwLjBzIGxpbmVhciAwLjAycycgfTtcblxuICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZSgndGFwcGFibGUnKSkge1xuICAgICAgaWYgKHRoaXMuc3R5bGUuYmFja2dyb3VuZENvbG9yKSB7XG4gICAgICAgIHRoaXMuX29yaWdpbmFsQmFja2dyb3VuZENvbG9yID0gdGhpcy5zdHlsZS5iYWNrZ3JvdW5kQ29sb3I7XG4gICAgICB9XG5cbiAgICAgIHRvdWNoU3R5bGUuYmFja2dyb3VuZENvbG9yID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3RhcC1iYWNrZ3JvdW5kLWNvbG9yJykgfHwgJyNkOWQ5ZDknO1xuICAgICAgdG91Y2hTdHlsZS5ib3hTaGFkb3cgPSBgMHB4IC0xcHggMHB4IDBweCAke3RvdWNoU3R5bGUuYmFja2dyb3VuZENvbG9yfWA7XG4gICAgfVxuXG4gICAgc3R5bGVyKHRoaXMsIHRvdWNoU3R5bGUpO1xuICB9XG5cbiAgX29uUmVsZWFzZSgpIHtcbiAgICB0aGlzLnRhcHBlZCA9IGZhbHNlO1xuICAgIHRoaXMuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gdGhpcy5fb3JpZ2luYWxCYWNrZ3JvdW5kQ29sb3IgfHwgJyc7XG4gICAgc3R5bGVyLmNsZWFyKHRoaXMsICd0cmFuc2l0aW9uIGJveFNoYWRvdycpO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLkxpc3RJdGVtID0gTGlzdEl0ZW1FbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtbGlzdC1pdGVtJywgTGlzdEl0ZW1FbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ2xpc3QnO1xuY29uc3Qgc2NoZW1lID0geycnOiAnbGlzdC0tKid9O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1saXN0XG4gKiBAY2F0ZWdvcnkgbGlzdFxuICogQG1vZGlmaWVyIGluc2V0XG4gKiAgIFtlbl1JbnNldCBsaXN0IHRoYXQgZG9lc24ndCBjb3ZlciB0aGUgd2hvbGUgd2lkdGggb2YgdGhlIHBhcmVudC5bL2VuXVxuICogICBbamFd6Kaq6KaB57Sg44Gu55S76Z2i44GE44Gj44Gx44GE44Gr5bqD44GM44KJ44Gq44GE44Oq44K544OI44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBtb2RpZmllciBub2JvcmRlclxuICogICBbZW5dQSBsaXN0IHdpdGggbm8gYm9yZGVycyBhdCB0aGUgdG9wIGFuZCBib3R0b20uWy9lbl1cbiAqICAgW2phXeODquOCueODiOOBruS4iuS4i+OBruODnOODvOODgOODvOOBjOeEoeOBhOODquOCueODiOOCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXUNvbXBvbmVudCB0byBkZWZpbmUgYSBsaXN0LCBhbmQgdGhlIGNvbnRhaW5lciBmb3Igb25zLWxpc3QtaXRlbShzKS5bL2VuXVxuICogICBbamFd44Oq44K544OI44KS6KGo54++44GZ44KL44Gf44KB44Gu44Kz44Oz44Od44O844ON44Oz44OI44CCb25zLWxpc3QtaXRlbeOBruOCs+ODs+ODhuODiuOBqOOBl+OBpuS9v+eUqOOBl+OBvuOBmeOAglsvamFdXG4gKiBAc2VlYWxzbyBvbnMtbGlzdC1pdGVtXG4gKiAgIFtlbl1vbnMtbGlzdC1pdGVtIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtbGlzdC1pdGVt44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1saXN0LWhlYWRlclxuICogICBbZW5db25zLWxpc3QtaGVhZGVyIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtbGlzdC1oZWFkZXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLWxhenktcmVwZWF0XG4gKiAgIFtlbl1vbnMtbGF6eS1yZXBlYXQgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1sYXp5LXJlcGVhdOOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAY29kZXBlbiB5eGNDdFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2xpc3RcbiAqIEBleGFtcGxlXG4gKiA8b25zLWxpc3Q+XG4gKiAgIDxvbnMtbGlzdC1oZWFkZXI+SGVhZGVyIFRleHQ8L29ucy1saXN0LWhlYWRlcj5cbiAqICAgPG9ucy1saXN0LWl0ZW0+SXRlbTwvb25zLWxpc3QtaXRlbT5cbiAqICAgPG9ucy1saXN0LWl0ZW0+SXRlbTwvb25zLWxpc3QtaXRlbT5cbiAqIDwvb25zLWxpc3Q+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIExpc3RFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgbGlzdC5bL2VuXVxuICAgKiAgIFtqYV3jg6rjgrnjg4jjga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fY29tcGlsZSgpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKGRlZmF1bHRDbGFzc05hbWUpO1xuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJywgJ2NsYXNzJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnY2xhc3MnOlxuICAgICAgICB1dGlsLnJlc3RvcmVDbGFzcyh0aGlzLCBkZWZhdWx0Q2xhc3NOYW1lLCBzY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ21vZGlmaWVyJzpcbiAgICAgICAgTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxufVxuXG5vbnNFbGVtZW50cy5MaXN0ID0gTGlzdEVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1saXN0JywgTGlzdEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uLy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3QgSU5QVVRfQVRUUklCVVRFUyA9IFtcbiAgJ2F1dG9jYXBpdGFsaXplJyxcbiAgJ2F1dG9jb21wbGV0ZScsXG4gICdhdXRvY29ycmVjdCcsXG4gICdhdXRvZm9jdXMnLFxuICAnZGlzYWJsZWQnLFxuICAnaW5wdXRtb2RlJyxcbiAgJ21heCcsXG4gICdtYXhsZW5ndGgnLFxuICAnbWluJyxcbiAgJ21pbmxlbmd0aCcsXG4gICduYW1lJyxcbiAgJ3BhdHRlcm4nLFxuICAncGxhY2Vob2xkZXInLFxuICAncmVhZG9ubHknLFxuICAncmVxdWlyZWQnLFxuICAnc2l6ZScsXG4gICdzdGVwJyxcbiAgJ3ZhbGlkYXRvcicsXG4gICd2YWx1ZSdcbl07XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJhc2VJbnB1dEVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgX3VwZGF0ZSgpIHt9IC8vIE9wdGlvbmFsbHkgaW1wbGVtZW50ZWRcblxuICBnZXQgX3NjaGVtZSgpIHtcbiAgICB1dGlsLnRocm93TWVtYmVyKCk7XG4gIH1cblxuICBnZXQgX3RlbXBsYXRlKCkge1xuICAgIHV0aWwudGhyb3dNZW1iZXIoKTtcbiAgfVxuXG4gIGdldCB0eXBlKCkge1xuICAgIHV0aWwudGhyb3dNZW1iZXIoKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodGhpcy5jb25zdHJ1Y3RvciA9PT0gQmFzZUlucHV0RWxlbWVudCkge1xuICAgICAgdXRpbC50aHJvd0Fic3RyYWN0KCk7XG4gICAgfVxuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX2NvbXBpbGUoKSk7XG4gICAgdGhpcy5fYm91bmREZWxlZ2F0ZUV2ZW50ID0gdGhpcy5fZGVsZWdhdGVFdmVudC5iaW5kKHRoaXMpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgdGhpcy5fZGVmYXVsdENsYXNzTmFtZSAmJiB0aGlzLmNsYXNzTGlzdC5hZGQodGhpcy5fZGVmYXVsdENsYXNzTmFtZSk7XG5cbiAgICBpZiAodGhpcy5jaGlsZHJlbi5sZW5ndGggIT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmFwcGVuZENoaWxkKHV0aWwuY3JlYXRlRnJhZ21lbnQodGhpcy5fdGVtcGxhdGUpKTtcblxuICAgIHRoaXMuX3NldElucHV0SWQoKTtcblxuICAgIHRoaXMuX3VwZGF0ZUJvdW5kQXR0cmlidXRlcygpO1xuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCB0aGlzLl9zY2hlbWUpO1xuICB9XG5cbiAgX3VwZGF0ZUJvdW5kQXR0cmlidXRlcygpIHtcbiAgICBJTlBVVF9BVFRSSUJVVEVTLmZvckVhY2goYXR0ciA9PiB7XG4gICAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoYXR0cikpIHtcbiAgICAgICAgdGhpcy5faW5wdXQuc2V0QXR0cmlidXRlKGF0dHIsIHRoaXMuZ2V0QXR0cmlidXRlKGF0dHIpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX2lucHV0LnJlbW92ZUF0dHJpYnV0ZShhdHRyKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRoaXMuX3VwZGF0ZSgpO1xuICB9XG5cbiAgX2RlbGVnYXRlRXZlbnQoZXZlbnQpIHtcbiAgICBjb25zdCBlID0gbmV3IEN1c3RvbUV2ZW50KGV2ZW50LnR5cGUsIHtcbiAgICAgIGJ1YmJsZXM6IGZhbHNlLFxuICAgICAgY2FuY2VsYWJsZTogdHJ1ZVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuZGlzcGF0Y2hFdmVudChlKTtcbiAgfVxuXG4gIF9zZXRJbnB1dElkKCkge1xuICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZSgnaW5wdXQtaWQnKSkge1xuICAgICAgdGhpcy5faW5wdXQuaWQgPSB0aGlzLmdldEF0dHJpYnV0ZSgnaW5wdXQtaWQnKTtcbiAgICB9XG4gIH1cblxuICBnZXQgX2RlZmF1bHRDbGFzc05hbWUoKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgZ2V0IF9pbnB1dCgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKCdpbnB1dCcpO1xuICB9XG5cbiAgZ2V0IHZhbHVlKCkge1xuICAgIHJldHVybiB0aGlzLl9pbnB1dCA9PT0gbnVsbFxuICAgICAgPyB0aGlzLmdldEF0dHJpYnV0ZSgndmFsdWUnKVxuICAgICAgOiB0aGlzLl9pbnB1dC52YWx1ZTtcbiAgfVxuXG4gIHNldCB2YWx1ZSh2YWwpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgaWYgKHZhbCBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgdmFsID0gdmFsLnRvSVNPU3RyaW5nKCkuc3Vic3RyaW5nKDAsIDEwKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX2lucHV0LnZhbHVlID0gdmFsO1xuICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgfSk7XG4gIH1cblxuICBzZXQgZGlzYWJsZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2Rpc2FibGVkJywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IGRpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9pbnB1dC5hZGRFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuX2JvdW5kRGVsZWdhdGVFdmVudCk7XG4gICAgICB0aGlzLl9pbnB1dC5hZGRFdmVudExpc3RlbmVyKCdibHVyJywgdGhpcy5fYm91bmREZWxlZ2F0ZUV2ZW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9pbnB1dC5yZW1vdmVFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuX2JvdW5kRGVsZWdhdGVFdmVudCk7XG4gICAgICB0aGlzLl9pbnB1dC5yZW1vdmVFdmVudExpc3RlbmVyKCdibHVyJywgdGhpcy5fYm91bmREZWxlZ2F0ZUV2ZW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJywgJ2lucHV0LWlkJywgJ2NsYXNzJywgLi4uSU5QVVRfQVRUUklCVVRFU107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHRoaXMuX3NjaGVtZSkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2lucHV0LWlkJzpcbiAgICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX3NldElucHV0SWQoKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnY2xhc3MnOlxuICAgICAgICB1dGlsLnJlc3RvcmVDbGFzcyh0aGlzLCB0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lLCB0aGlzLl9zY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICBpZiAoSU5QVVRfQVRUUklCVVRFUy5pbmRleE9mKG5hbWUpID49IDApIHtcbiAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl91cGRhdGVCb3VuZEF0dHJpYnV0ZXMoKSk7XG4gICAgfVxuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgQmFzZUlucHV0RWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1pbnB1dCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnLnRleHQtaW5wdXQnOiAndGV4dC1pbnB1dC0tKicsXG4gICcudGV4dC1pbnB1dF9fbGFiZWwnOiAndGV4dC1pbnB1dC0tKl9fbGFiZWwnXG59O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1pbnB1dFxuICogQGNhdGVnb3J5IGZvcm1cbiAqIEBtb2RpZmllciBtYXRlcmlhbFxuICogIFtlbl1EaXNwbGF5cyBhIE1hdGVyaWFsIERlc2lnbiBpbnB1dC5bL2VuXVxuICogIFtqYV1bL2phXVxuICogQG1vZGlmaWVyIHVuZGVyYmFyXG4gKiAgW2VuXURpc3BsYXlzIGEgaG9yaXpvbnRhbCBsaW5lIHVuZGVybmVhdGggYSB0ZXh0IGlucHV0LlsvZW5dXG4gKiAgW2phXVsvamFdXG4gKiBAbW9kaWZpZXIgdHJhbnNwYXJlbnRcbiAqICBbZW5dRGlzcGxheXMgYSB0cmFuc3BhcmVudCBpbnB1dC4gV29ya3MgZm9yIE1hdGVyaWFsIERlc2lnbi5bL2VuXVxuICogIFtqYV1bL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgW2VuXVxuICogICAgQW4gaW5wdXQgZWxlbWVudC4gVGhlIGB0eXBlYCBhdHRyaWJ1dGUgY2FuIGJlIHVzZWQgdG8gY2hhbmdlIHRoZSBpbnB1dCB0eXBlLiBBbGwgdGV4dCBpbnB1dCB0eXBlcyBhcmUgc3VwcG9ydGVkLlxuICpcbiAqICAgIFRoZSBjb21wb25lbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHJlbmRlciBhcyBhIE1hdGVyaWFsIERlc2lnbiBpbnB1dCBvbiBBbmRyb2lkIGRldmljZXMuXG4gKlxuICogICAgTW9zdCBhdHRyaWJ1dGVzIHRoYXQgY2FuIGJlIHVzZWQgZm9yIGEgbm9ybWFsIGA8aW5wdXQ+YCBlbGVtZW50IGNhbiBhbHNvIGJlIHVzZWQgb24gdGhlIGA8b25zLWlucHV0PmAgZWxlbWVudC5cbiAqICBbL2VuXVxuICogIFtqYV1bL2phXVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2lucHV0XG4gKiBAc2VlYWxzbyBvbnMtY2hlY2tib3hcbiAqICAgW2VuXVRoZSBgPG9ucy1jaGVja2JveD5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgY2hlY2tib3guWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtcmFkaW9cbiAqICAgW2VuXVRoZSBgPG9ucy1yYWRpbz5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgcmFkaW8gYnV0dG9uLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLXJhbmdlXG4gKiAgIFtlbl1UaGUgYDxvbnMtcmFuZ2U+YCBlbGVtZW50IGlzIHVzZWQgdG8gZGlzcGxheSBhIHJhbmdlIHNsaWRlci5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zd2l0Y2hcbiAqICAgW2VuXVRoZSBgPG9ucy1zd2l0Y2g+YCBlbGVtZW50IGlzIHVzZWQgdG8gZGlzcGxheSBhIGRyYWdnYWJsZSB0b2dnbGUgc3dpdGNoLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLXNlbGVjdFxuICogICBbZW5dVGhlIGA8b25zLXNlbGVjdD5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgc2VsZWN0IGJveC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBndWlkZSB0aGVtaW5nLmh0bWwjbW9kaWZpZXJzIFtlbl1Nb3JlIGRldGFpbHMgYWJvdXQgdGhlIGBtb2RpZmllcmAgYXR0cmlidXRlWy9lbl1bamFdbW9kaWZpZXLlsZ7mgKfjga7kvb/jgYTmlrlbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtaW5wdXQgcGxhY2Vob2xkZXI9XCJVc2VybmFtZVwiIGZsb2F0Pjwvb25zLWlucHV0PlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJbnB1dEVsZW1lbnQgZXh0ZW5kcyBCYXNlSW5wdXRFbGVtZW50IHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fYm91bmRPbklucHV0ID0gdGhpcy5fdXBkYXRlLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fYm91bmRPbkZvY3VzaW4gPSB0aGlzLl91cGRhdGUuYmluZCh0aGlzKTtcbiAgfVxuXG4gIC8qIEluaGVyaXRlZCBwcm9wcyAqL1xuXG4gIF91cGRhdGUoKSB7XG4gICAgdGhpcy5fdXBkYXRlTGFiZWwoKTtcbiAgICB0aGlzLl91cGRhdGVMYWJlbENsYXNzKCk7XG4gIH1cblxuICBnZXQgX3NjaGVtZSgpIHtcbiAgICByZXR1cm4gc2NoZW1lO1xuICB9XG5cbiAgZ2V0IF90ZW1wbGF0ZSgpIHtcbiAgICByZXR1cm4gYFxuICAgICAgPGlucHV0IHR5cGU9XCIke3RoaXMudHlwZX1cIiBjbGFzcz1cInRleHQtaW5wdXRcIj5cbiAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1pbnB1dF9fbGFiZWxcIj48L3NwYW4+XG4gICAgYDtcbiAgfVxuXG4gIGdldCB0eXBlKCkge1xuICAgIGNvbnN0IHR5cGUgPSB0aGlzLmdldEF0dHJpYnV0ZSgndHlwZScpO1xuICAgIHJldHVybiAoWydjaGVja2JveCcsICdyYWRpbyddLmluZGV4T2YodHlwZSkgPCAwKSAmJiB0eXBlIHx8ICd0ZXh0JztcbiAgfVxuXG4gIC8qIE93biBwcm9wcyAqL1xuXG4gIF91cGRhdGVMYWJlbCgpIHtcbiAgICBjb25zdCBsYWJlbCA9IHRoaXMuZ2V0QXR0cmlidXRlKCdwbGFjZWhvbGRlcicpIHx8ICcnO1xuXG4gICAgaWYgKHR5cGVvZiB0aGlzLl9oZWxwZXIudGV4dENvbnRlbnQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aGlzLl9oZWxwZXIudGV4dENvbnRlbnQgPSBsYWJlbDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5faGVscGVyLmlubmVyVGV4dCA9IGxhYmVsO1xuICAgIH1cbiAgfVxuXG4gIF91cGRhdGVMYWJlbENsYXNzKCkge1xuICAgIGlmICh0aGlzLnZhbHVlID09PSAnJykge1xuICAgICAgdGhpcy5faGVscGVyLmNsYXNzTGlzdC5yZW1vdmUoJ3RleHQtaW5wdXQtLW1hdGVyaWFsX19sYWJlbC0tYWN0aXZlJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2hlbHBlci5jbGFzc0xpc3QuYWRkKCd0ZXh0LWlucHV0LS1tYXRlcmlhbF9fbGFiZWwtLWFjdGl2ZScpO1xuICAgIH1cbiAgfVxuXG4gIGdldCBfaGVscGVyKCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3IoJ3NwYW4nKTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHN1cGVyLmNvbm5lY3RlZENhbGxiYWNrKCk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5faW5wdXQuYWRkRXZlbnRMaXN0ZW5lcignaW5wdXQnLCB0aGlzLl9ib3VuZE9uSW5wdXQpO1xuICAgICAgdGhpcy5faW5wdXQuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXNpbicsIHRoaXMuX2JvdW5kT25Gb2N1c2luKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHR5cGUgPSB0aGlzLmdldEF0dHJpYnV0ZSgndHlwZScpO1xuICAgIGlmIChbJ2NoZWNrYm94JywgJ3JhZGlvJ10uaW5kZXhPZih0eXBlKSA+PSAwKSB7XG4gICAgICB1dGlsLndhcm4oYFdhcm46IDxvbnMtaW5wdXQgdHlwZT1cIiR7dHlwZX1cIj4gaXMgZGVwcmVjYXRlZCBzaW5jZSB2Mi40LjAuIFVzZSA8b25zLSR7dHlwZX0+IGluc3RlYWQuYClcbiAgICB9XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBzdXBlci5kaXNjb25uZWN0ZWRDYWxsYmFjaygpO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2lucHV0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2lucHV0JywgdGhpcy5fYm91bmRPbklucHV0KTtcbiAgICAgIHRoaXMuX2lucHV0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2ZvY3VzaW4nLCB0aGlzLl9ib3VuZE9uRm9jdXNpbik7XG4gICAgfSk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWy4uLnN1cGVyLm9ic2VydmVkQXR0cmlidXRlcywgJ3R5cGUnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICd0eXBlJzpcbiAgICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX2lucHV0LnNldEF0dHJpYnV0ZSgndHlwZScsIHRoaXMudHlwZSkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHN1cGVyLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBwbGFjZWhvbGRlclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUGxhY2Vob2xkZXIgdGV4dC4gSW4gTWF0ZXJpYWwgRGVzaWduLCB0aGlzIHBsYWNlaG9sZGVyIHdpbGwgYmUgYSBmbG9hdGluZyBsYWJlbC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBmbG9hdFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBwcmVzZW50LCB0aGUgcGxhY2Vob2xkZXIgd2lsbCBiZSBhbmltYXRlZCBpbiBNYXRlcmlhbCBEZXNpZ24uWy9lbl1cbiAgICogIFtqYV3jgZPjga7lsZ7mgKfjgYzoqK3lrprjgZXjgozjgZ/mmYLjgIHjg6njg5njg6vjga/jgqLjg4vjg6Hjg7zjgrfjg6fjg7PjgZnjgovjgojjgYbjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSB0eXBlXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVxuICAgKiAgICBTcGVjaWZ5IHRoZSBpbnB1dCB0eXBlLiBUaGlzIGlzIHRoZSBzYW1lIGFzIHRoZSBcInR5cGVcIiBhdHRyaWJ1dGUgZm9yIG5vcm1hbCBpbnB1dHMuIEl0IGV4cGVjdHMgc3RyaWN0IHRleHQgdHlwZXMgc3VjaCBhcyBgdGV4dGAsIGBwYXNzd29yZGAsIGV0Yy4gRm9yIGNoZWNrYm94LCByYWRpbyBidXR0b24sIHNlbGVjdCBvciByYW5nZSwgcGxlYXNlIGhhdmUgYSBsb29rIGF0IHRoZSBjb3JyZXNwb25kaW5nIGVsZW1lbnRzLlxuICAgKlxuICAgKiAgICBQbGVhc2UgdGFrZSBhIGxvb2sgYXQgW01ETl0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSFRNTC9FbGVtZW50L2lucHV0I2F0dHItdHlwZSkgZm9yIGFuIGV4aGF1c3RpdmUgbGlzdCBvZiBwb3NzaWJsZSB2YWx1ZXMuIERlcGVuZGluZyBvbiB0aGUgcGxhdGZvcm0gYW5kIGJyb3dzZXIgdmVyc2lvbiBzb21lIG9mIHRoZXNlIG1pZ2h0IG5vdCB3b3JrLlxuICAgKiAgWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBpbnB1dC1pZFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBcImlkXCIgYXR0cmlidXRlIG9mIHRoZSBpbm5lciBgPGlucHV0PmAgZWxlbWVudC4gVGhpcyBpcyB1c2VmdWwgd2hlbiB1c2luZyBgPGxhYmVsIGZvcj1cIi4uLlwiPmAgZWxlbWVudHMuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZhbHVlXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgaW5wdXQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGlucHV0IGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cbn1cblxub25zRWxlbWVudHMuSW5wdXQgPSBJbnB1dEVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1pbnB1dCcsIElucHV0RWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IEJhc2VJbnB1dEVsZW1lbnQgZnJvbSAnLi9iYXNlLWlucHV0JztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCYXNlQ2hlY2tib3hFbGVtZW50IGV4dGVuZHMgQmFzZUlucHV0RWxlbWVudCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yID09PSBCYXNlQ2hlY2tib3hFbGVtZW50KSB7XG4gICAgICB1dGlsLnRocm93QWJzdHJhY3QoKTtcbiAgICB9XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2soJ2NoZWNrZWQnLCBudWxsLCB0aGlzLmdldEF0dHJpYnV0ZSgnY2hlY2tlZCcpKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qIEluaGVyaXRlZCBwcm9wcyAqL1xuXG4gIGdldCBfdGVtcGxhdGUoKSB7XG4gICAgcmV0dXJuIGBcbiAgICAgIDxpbnB1dCB0eXBlPVwiJHt0aGlzLnR5cGV9XCIgY2xhc3M9XCIke3RoaXMuX2RlZmF1bHRDbGFzc05hbWV9X19pbnB1dFwiPlxuICAgICAgPHNwYW4gY2xhc3M9XCIke3RoaXMuX2RlZmF1bHRDbGFzc05hbWV9X19jaGVja21hcmtcIj48L3NwYW4+XG4gICAgYDtcbiAgfVxuXG4gIC8qIE93biBwcm9wcyAqL1xuXG4gIGdldCBfaGVscGVyKCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3IoJ3NwYW4nKTtcbiAgfVxuXG4gIGdldCBjaGVja2VkKCkge1xuICAgIHJldHVybiB0aGlzLl9pbnB1dC5jaGVja2VkO1xuICB9XG5cbiAgc2V0IGNoZWNrZWQodmFsKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2lucHV0LmNoZWNrZWQgPSB2YWw7XG4gICAgfSk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWy4uLnN1cGVyLm9ic2VydmVkQXR0cmlidXRlcywgJ2NoZWNrZWQnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjaGVja2VkJzpcbiAgICAgICAgdGhpcy5jaGVja2VkID0gY3VycmVudCAhPT0gbnVsbDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBzdXBlci5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCk7XG4gICAgfVxuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgQmFzZUNoZWNrYm94RWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1jaGVja2JveCc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy5jaGVja2JveCc6ICdjaGVja2JveC0tKicsXG4gICcuY2hlY2tib3hfX2lucHV0JzogJ2NoZWNrYm94LS0qX19pbnB1dCcsXG4gICcuY2hlY2tib3hfX2NoZWNrbWFyayc6ICdjaGVja2JveC0tKl9fY2hlY2ttYXJrJ1xufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtY2hlY2tib3hcbiAqIEBjYXRlZ29yeSBmb3JtXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICBbZW5dRGlzcGxheXMgYSBNYXRlcmlhbCBEZXNpZ24gY2hlY2tib3guWy9lbl1cbiAqICBbamFdWy9qYV1cbiAqIEBtb2RpZmllciBub2JvcmRlclxuICogIFtlbl1pT1MgYm9yZGVybGVzcyBjaGVja2JveC5bL2VuXVxuICogIFtqYV1bL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgW2VuXVxuICogICAgQSBjaGVja2JveCBlbGVtZW50LiBUaGUgY29tcG9uZW50IHdpbGwgYXV0b21hdGljYWxseSByZW5kZXIgYXMgYSBNYXRlcmlhbCBEZXNpZ24gY2hlY2tib3ggb24gQW5kcm9pZCBkZXZpY2VzLlxuICpcbiAqICAgIE1vc3QgYXR0cmlidXRlcyB0aGF0IGNhbiBiZSB1c2VkIGZvciBhIG5vcm1hbCBgPGlucHV0IHR5cGU9XCJjaGVja2JveFwiPmAgZWxlbWVudCBjYW4gYWxzbyBiZSB1c2VkIG9uIHRoZSBgPG9ucy1jaGVja2JveD5gIGVsZW1lbnQuXG4gKiAgWy9lbl1cbiAqICBbamFdWy9qYV1cbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9jaGVja2JveFxuICogQHNlZWFsc28gb25zLXN3aXRjaFxuICogICBbZW5dVGhlIGA8b25zLXN3aXRjaD5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgZHJhZ2dhYmxlIHRvZ2dsZSBzd2l0Y2guWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtcmFkaW9cbiAqICAgW2VuXVRoZSBgPG9ucy1yYWRpbz5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgcmFkaW8gYnV0dG9uLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLWlucHV0XG4gKiAgIFtlbl1UaGUgYDxvbnMtaW5wdXQ+YCBlbGVtZW50IGlzIHVzZWQgdG8gZGlzcGxheSBhIHRleHQgaW5wdXQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtc2VhcmNoLWlucHV0XG4gKiAgIFtlbl1UaGUgYDxvbnMtc2VhcmNoLWlucHV0PmAgZWxlbWVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSBzZWFyY2ggaW5wdXQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtcmFuZ2VcbiAqICAgW2VuXVRoZSBgPG9ucy1yYW5nZT5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgcmFuZ2Ugc2xpZGVyLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLXNlbGVjdFxuICogICBbZW5dVGhlIGA8b25zLXNlbGVjdD5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgc2VsZWN0IGJveC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBndWlkZSB0aGVtaW5nLmh0bWwjbW9kaWZpZXJzIFtlbl1Nb3JlIGRldGFpbHMgYWJvdXQgdGhlIGBtb2RpZmllcmAgYXR0cmlidXRlWy9lbl1bamFdbW9kaWZpZXLlsZ7mgKfjga7kvb/jgYTmlrlbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtY2hlY2tib3ggY2hlY2tlZD48L29ucy1jaGVja2JveD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ2hlY2tib3hFbGVtZW50IGV4dGVuZHMgQmFzZUNoZWNrYm94RWxlbWVudCB7XG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgcmV0dXJuIHNjaGVtZTtcbiAgfVxuXG4gIGdldCBfZGVmYXVsdENsYXNzTmFtZSgpIHtcbiAgICByZXR1cm4gJ2NoZWNrYm94JztcbiAgfVxuXG4gIGdldCB0eXBlKCkge1xuICAgIHJldHVybiAnY2hlY2tib3gnO1xuICB9XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgaW5wdXQtaWRcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU3BlY2lmeSB0aGUgXCJpZFwiIGF0dHJpYnV0ZSBvZiB0aGUgaW5uZXIgYDxpbnB1dD5gIGVsZW1lbnQuIFRoaXMgaXMgdXNlZnVsIHdoZW4gdXNpbmcgYDxsYWJlbCBmb3I9XCIuLi5cIj5gIGVsZW1lbnRzLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB2YWx1ZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIGNoZWNrYm94LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgY2hlY2tlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGNoZWNrYm94IGlzIGNoZWNrZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBjaGVja2JveCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG59XG5cbm9uc0VsZW1lbnRzLkNoZWNrYm94ID0gQ2hlY2tib3hFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtY2hlY2tib3gnLCBDaGVja2JveEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IEJhc2VDaGVja2JveEVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtY2hlY2tib3gnO1xuXG5jb25zdCBzY2hlbWUgPSB7XG4gICcucmFkaW8tYnV0dG9uJzogJ3JhZGlvLWJ1dHRvbi0tKicsXG4gICcucmFkaW8tYnV0dG9uX19pbnB1dCc6ICdyYWRpby1idXR0b24tLSpfX2lucHV0JyxcbiAgJy5yYWRpby1idXR0b25fX2NoZWNrbWFyayc6ICdyYWRpby1idXR0b24tLSpfX2NoZWNrbWFyaydcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXJhZGlvXG4gKiBAY2F0ZWdvcnkgZm9ybVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgW2VuXURpc3BsYXlzIGEgTWF0ZXJpYWwgRGVzaWduIHJhZGlvIGJ1dHRvbi5bL2VuXVxuICogIFtqYV1bL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgW2VuXVxuICogICAgQSByYWRpbyBidXR0b24gZWxlbWVudC4gVGhlIGNvbXBvbmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgcmVuZGVyIGFzIGEgTWF0ZXJpYWwgRGVzaWduIHJhZGlvIGJ1dHRvbiBvbiBBbmRyb2lkIGRldmljZXMuXG4gKlxuICogICAgTW9zdCBhdHRyaWJ1dGVzIHRoYXQgY2FuIGJlIHVzZWQgZm9yIGEgbm9ybWFsIGA8aW5wdXQgdHlwZT1cInJhZGlvXCI+YCBlbGVtZW50IGNhbiBhbHNvIGJlIHVzZWQgb24gdGhlIGA8b25zLXJhZGlvPmAgZWxlbWVudC5cbiAqICBbL2VuXVxuICogIFtqYV1bL2phXVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3JhZGlvXG4gKiBAc2VlYWxzbyBvbnMtc2VsZWN0XG4gKiAgIFtlbl1UaGUgYDxvbnMtc2VsZWN0PmAgZWxlbWVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSBzZWxlY3QgYm94LlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLWNoZWNrYm94XG4gKiAgIFtlbl1UaGUgYDxvbnMtY2hlY2tib3g+YCBlbGVtZW50IGlzIHVzZWQgdG8gZGlzcGxheSBhIGNoZWNrYm94LlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLXN3aXRjaFxuICogICBbZW5dVGhlIGA8b25zLXN3aXRjaD5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgZHJhZ2dhYmxlIHRvZ2dsZSBzd2l0Y2guWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtaW5wdXRcbiAqICAgW2VuXVRoZSBgPG9ucy1pbnB1dD5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgdGV4dCBpbnB1dC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zZWFyY2gtaW5wdXRcbiAqICAgW2VuXVRoZSBgPG9ucy1zZWFyY2gtaW5wdXQ+YCBlbGVtZW50IGlzIHVzZWQgdG8gZGlzcGxheSBhIHNlYXJjaCBpbnB1dC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1yYW5nZVxuICogICBbZW5dVGhlIGA8b25zLXJhbmdlPmAgZWxlbWVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSByYW5nZSBzbGlkZXIuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZ3VpZGUgdGhlbWluZy5odG1sI21vZGlmaWVycyBbZW5dTW9yZSBkZXRhaWxzIGFib3V0IHRoZSBgbW9kaWZpZXJgIGF0dHJpYnV0ZVsvZW5dW2phXW1vZGlmaWVy5bGe5oCn44Gu5L2/44GE5pa5Wy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXJhZGlvIGNoZWNrZWQ+PC9vbnMtcmFkaW8+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJhZGlvRWxlbWVudCBleHRlbmRzIEJhc2VDaGVja2JveEVsZW1lbnQge1xuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHJldHVybiBzY2hlbWU7XG4gIH1cblxuICBnZXQgX2RlZmF1bHRDbGFzc05hbWUoKSB7XG4gICAgcmV0dXJuICdyYWRpby1idXR0b24nO1xuICB9XG5cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuICdyYWRpbyc7XG4gIH1cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBpbnB1dC1pZFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBcImlkXCIgYXR0cmlidXRlIG9mIHRoZSBpbm5lciBgPGlucHV0PmAgZWxlbWVudC4gVGhpcyBpcyB1c2VmdWwgd2hlbiB1c2luZyBgPGxhYmVsIGZvcj1cIi4uLlwiPmAgZWxlbWVudHMuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZhbHVlXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgcmFkaW8gYnV0dG9uLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgY2hlY2tlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIHJhZGlvIGJ1dHRvbiBpcyBjaGVja2VkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgcmFkaW8gYnV0dG9uIGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cbn1cblxub25zRWxlbWVudHMuUmFkaW8gPSBSYWRpb0VsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1yYWRpbycsIFJhZGlvRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgQmFzZUlucHV0RWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1pbnB1dCc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy5zZWFyY2gtaW5wdXQnOiAnc2VhcmNoLWlucHV0LS0qJ1xufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtc2VhcmNoLWlucHV0XG4gKiBAY2F0ZWdvcnkgZm9ybVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgW2VuXURpc3BsYXlzIGEgTWF0ZXJpYWwgRGVzaWduIHNlYXJjaCBpbnB1dC5bL2VuXVxuICogIFtqYV1bL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgW2VuXVxuICogICAgQSBzZWFyY2ggaW5wdXQgZWxlbWVudC4gVGhlIGNvbXBvbmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgcmVuZGVyIGFzIGEgTWF0ZXJpYWwgRGVzaWduIHNlYXJjaCBpbnB1dCBvbiBBbmRyb2lkIGRldmljZXMuXG4gKlxuICogICAgTW9zdCBhdHRyaWJ1dGVzIHRoYXQgY2FuIGJlIHVzZWQgZm9yIGEgbm9ybWFsIGA8aW5wdXQ+YCBlbGVtZW50IGNhbiBhbHNvIGJlIHVzZWQgb24gdGhlIGA8b25zLXNlYXJjaC1pbnB1dD5gIGVsZW1lbnQuXG4gKiAgWy9lbl1cbiAqICBbamFdWy9qYV1cbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9zZWFyY2gtaW5wdXRcbiAqIEBzZWVhbHNvIG9ucy1pbnB1dFxuICogICBbZW5dVGhlIGA8b25zLWlucHV0PmAgZWxlbWVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSB0ZXh0IGlucHV0LlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLXJhbmdlXG4gKiAgIFtlbl1UaGUgYDxvbnMtcmFuZ2U+YCBlbGVtZW50IGlzIHVzZWQgdG8gZGlzcGxheSBhIHJhbmdlIHNsaWRlci5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zd2l0Y2hcbiAqICAgW2VuXVRoZSBgPG9ucy1zd2l0Y2g+YCBlbGVtZW50IGlzIHVzZWQgdG8gZGlzcGxheSBhIGRyYWdnYWJsZSB0b2dnbGUgc3dpdGNoLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLXNlbGVjdFxuICogICBbZW5dVGhlIGA8b25zLXNlbGVjdD5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgc2VsZWN0IGJveC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1jaGVja2JveFxuICogICBbZW5dVGhlIGA8b25zLWNoZWNrYm94PmAgZWxlbWVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSBjaGVja2JveC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1yYWRpb1xuICogICBbZW5dVGhlIGA8b25zLXJhZGlvPmAgZWxlbWVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSByYWRpbyBidXR0b24uWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZ3VpZGUgdGhlbWluZy5odG1sI21vZGlmaWVycyBbZW5dTW9yZSBkZXRhaWxzIGFib3V0IHRoZSBgbW9kaWZpZXJgIGF0dHJpYnV0ZVsvZW5dW2phXW1vZGlmaWVy5bGe5oCn44Gu5L2/44GE5pa5Wy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXNlYXJjaC1pbnB1dCBwbGFjZWhvbGRlcj1cIlNlYXJjaFwiPjwvb25zLXNlYXJjaC1pbnB1dD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2VhcmNoSW5wdXRFbGVtZW50IGV4dGVuZHMgQmFzZUlucHV0RWxlbWVudCB7XG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgcmV0dXJuIHNjaGVtZTtcbiAgfVxuXG4gIGdldCBfdGVtcGxhdGUoKSB7XG4gICAgcmV0dXJuIGBcbiAgICAgIDxpbnB1dCB0eXBlPVwiJHt0aGlzLnR5cGV9XCIgY2xhc3M9XCJzZWFyY2gtaW5wdXRcIj5cbiAgICBgO1xuICB9XG5cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuICdzZWFyY2gnO1xuICB9XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgaW5wdXQtaWRcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU3BlY2lmeSB0aGUgXCJpZFwiIGF0dHJpYnV0ZSBvZiB0aGUgaW5uZXIgYDxpbnB1dD5gIGVsZW1lbnQuIFRoaXMgaXMgdXNlZnVsIHdoZW4gdXNpbmcgYDxsYWJlbCBmb3I9XCIuLi5cIj5gIGVsZW1lbnRzLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB2YWx1ZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIGlucHV0LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBpbnB1dCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG59XG5cbm9uc0VsZW1lbnRzLlNlYXJjaElucHV0ID0gU2VhcmNoSW5wdXRFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtc2VhcmNoLWlucHV0JywgU2VhcmNoSW5wdXRFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBCYXNlQW5pbWF0b3IgZnJvbSAnLi4vLi4vb25zL2Jhc2UtYW5pbWF0b3InO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNb2RhbEFuaW1hdG9yIGV4dGVuZHMgQmFzZUFuaW1hdG9yIHtcblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICogQHBhcmFtIHtTdHJpbmd9IG9wdGlvbnMudGltaW5nXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBvcHRpb25zLmR1cmF0aW9uXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBvcHRpb25zLmRlbGF5XG4gICAqL1xuICBjb25zdHJ1Y3Rvcih7dGltaW5nID0gJ2xpbmVhcicsIGRlbGF5ID0gMCwgZHVyYXRpb24gPSAwLjJ9ID0ge30pIHtcbiAgICBzdXBlcih7IHRpbWluZywgZGVsYXksIGR1cmF0aW9uIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IG1vZGFsXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBzaG93KG1vZGFsLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrKCk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gbW9kYWxcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUobW9kYWwsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxufVxuIiwiXG4vKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuaW1wb3J0IE1vZGFsQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5cbi8qKlxuICogaU9TIHN0eWxlIGFuaW1hdG9yIGZvciBkaWFsb2cuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEZhZGVNb2RhbEFuaW1hdG9yIGV4dGVuZHMgTW9kYWxBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdsaW5lYXInLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC4zfSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBtb2RhbFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgc2hvdyhtb2RhbCwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrID8gY2FsbGJhY2sgOiBmdW5jdGlvbigpIHt9O1xuXG4gICAgYW5pbWl0KG1vZGFsLCB0aGlzLmRlZilcbiAgICAgIC5kZWZhdWx0KHsgb3BhY2l0eTogMCB9LCB7IG9wYWNpdHk6IDEgfSlcbiAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgZG9uZSgpO1xuICAgICAgfSlcbiAgICAgIC5wbGF5KCk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gbW9kYWxcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUobW9kYWwsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjayA/IGNhbGxiYWNrIDogZnVuY3Rpb24oKSB7fTtcblxuICAgIGFuaW1pdChtb2RhbCwgdGhpcy5kZWYpXG4gICAgICAuZGVmYXVsdCh7IG9wYWNpdHk6IDEgfSwgeyBvcGFjaXR5OiAwIH0pXG4gICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIGRvbmUoKTtcbiAgICAgIH0pXG4gICAgICAucGxheSgpO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuaW1wb3J0IE1vZGFsQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5cbi8qKlxuICogaU9TIHN0eWxlIGFuaW1hdG9yIGZvciBtb2RhbC5cbiAqL1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMaWZ0TW9kYWxBbmltYXRvciBleHRlbmRzIE1vZGFsQW5pbWF0b3JcbntcbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdjdWJpYy1iZXppZXIoIC4xLCAuNywgLjEsIDEpJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuNH0gPSB7fSkge1xuICAgIHN1cGVyKHsgdGltaW5nLCBkZWxheSwgZHVyYXRpb24gfSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gbW9kYWxcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHNob3cobW9kYWwsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjayA/IGNhbGxiYWNrIDogZnVuY3Rpb24oKSB7fTtcblxuICAgIGFuaW1pdChtb2RhbCwgdGhpcy5kZWYpXG4gICAgICAuZGVmYXVsdChcbiAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAxMDAlLCAwKScgfSxcbiAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKScgfVxuICAgICAgKVxuICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICBkb25lKCk7XG4gICAgICB9KVxuICAgICAgLnBsYXkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBtb2RhbFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgaGlkZShtb2RhbCwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrID8gY2FsbGJhY2sgOiBmdW5jdGlvbigpIHt9O1xuXG4gICAgYW5pbWl0KG1vZGFsLCB0aGlzLmRlZilcbiAgICAgIC5kZWZhdWx0KFxuICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDAsIDApJyB9LFxuICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDEwMCUsIDApJyB9XG4gICAgICApXG4gICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIGRvbmUoKTtcbiAgICAgIH0pXG4gICAgICAucGxheSgpO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEFuaW1hdG9yRmFjdG9yeSBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvYW5pbWF0b3ItZmFjdG9yeSc7XG5pbXBvcnQgTW9kYWxBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcbmltcG9ydCBGYWRlTW9kYWxBbmltYXRvciBmcm9tICcuL2ZhZGUtYW5pbWF0b3InO1xuaW1wb3J0IExpZnRNb2RhbEFuaW1hdG9yIGZyb20gJy4vbGlmdC1hbmltYXRvcic7XG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vLi4vb25zL3BsYXRmb3JtJztcbmltcG9ydCBCYXNlRGlhbG9nRWxlbWVudCBmcm9tICcuLi9iYXNlL2Jhc2UtZGlhbG9nJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBzY2hlbWUgPSB7XG4gICcnOiAnbW9kYWwtLSonLFxuICAnbW9kYWxfX2NvbnRlbnQnOiAnbW9kYWwtLSpfX2NvbnRlbnQnXG59O1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ21vZGFsJztcblxuY29uc3QgX2FuaW1hdG9yRGljdCA9IHtcbiAgJ2RlZmF1bHQnOiBNb2RhbEFuaW1hdG9yLFxuICAnZmFkZSc6IEZhZGVNb2RhbEFuaW1hdG9yLFxuICAnbGlmdCc6IExpZnRNb2RhbEFuaW1hdG9yLFxuICAnbm9uZSc6IE1vZGFsQW5pbWF0b3Jcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLW1vZGFsXG4gKiBAY2F0ZWdvcnkgZGlhbG9nXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIE1vZGFsIGNvbXBvbmVudCB0aGF0IG1hc2tzIGN1cnJlbnQgc2NyZWVuLiBVbmRlcmx5aW5nIGNvbXBvbmVudHMgYXJlIG5vdCBzdWJqZWN0IHRvIGFueSBldmVudHMgd2hpbGUgdGhlIG1vZGFsIGNvbXBvbmVudCBpcyBzaG93bi5cbiAqXG4gKiAgICAgVGhpcyBjb21wb25lbnQgY2FuIGJlIHVzZWQgdG8gYmxvY2sgdXNlciBpbnB1dCB3aGlsZSBzb21lIG9wZXJhdGlvbiBpcyBydW5uaW5nIG9yIHRvIHNob3cgc29tZSBpbmZvcm1hdGlvbiB0byB0aGUgdXNlci5cbiAqICAgWy9lbl1cbiAqICAgW2phXVxuICogICAgIOeUu+mdouWFqOS9k+OCkuODnuOCueOCr+OBmeOCi+ODouODvOODgOODq+eUqOOCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAguS4i+WBtOOBq+OBguOCi+OCs+ODs+ODneODvOODjeODs+ODiOOBr+OAgVxuICogICAgIOODouODvOODgOODq+OBjOihqOekuuOBleOCjOOBpuOBhOOCi+mWk+OBr+OCpOODmeODs+ODiOmAmuefpeOBjOihjOOCj+OCjOOBvuOBm+OCk+OAglxuICogICBbL2phXVxuICogQHNlZWFsc28gb25zLWRpYWxvZ1xuICogICBbZW5dVGhlIGA8b25zLWRpYWxvZz5gIGNvbXBvbmVudCBjYW4gYmUgdXNlZCB0byBjcmVhdGUgYSBtb2RhbCBkaWFsb2cuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAY29kZXBlbiBkZXZJZ1xuICogQHR1dG9yaWFsIHZhbmlsbGEvcmVmZXJlbmNlL21vZGFsXG4gKiBAZXhhbXBsZVxuICogPG9ucy1tb2RhbCBpZD1cIm1vZGFsXCI+XG4gKiAgIE1vZGFsIGNvbnRlbnRcbiAqIDwvb25zLW1vZGFsPlxuICogPHNjcmlwdD5cbiAqICAgdmFyIG1vZGFsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ21vZGFsJyk7XG4gKiAgIG1vZGFsLnNob3coKTtcbiAqIDwvc2NyaXB0PlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNb2RhbEVsZW1lbnQgZXh0ZW5kcyBCYXNlRGlhbG9nRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBldmVudCBwcmVzaG93XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBbZW5dRmlyZWQganVzdCBiZWZvcmUgdGhlIG1vZGFsIGlzIGRpc3BsYXllZC5bL2VuXVxuICAgKiBbamFd44Oi44O844OA44Or44GM6KGo56S644GV44KM44KL55u05YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50Lm1vZGFsXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUV4ZWN1dGUgdGhpcyBmdW5jdGlvbiB0byBzdG9wIHRoZSBtb2RhbCBmcm9tIGJlaW5nIHNob3duLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWun+ihjOOBmeOCi+OBqOOAgeODgOOCpOOCouODreOCsOOBruihqOekuuOBjOOCreODo+ODs+OCu+ODq+OBleOCjOOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdHNob3dcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFtlbl1GaXJlZCBqdXN0IGFmdGVyIHRoZSBtb2RhbCBpcyBkaXNwbGF5ZWQuWy9lbl1cbiAgICogW2phXeODouODvOODgOODq+OBjOihqOekuuOBleOCjOOBn+ebtOW+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5tb2RhbFxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlaGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYmVmb3JlIHRoZSBtb2RhbCBpcyBoaWRkZW4uWy9lbl1cbiAgICogW2phXeODouODvOODgOODq+OBjOmaoOOCjOOCi+ebtOWJjeOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5tb2RhbFxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGV2ZW50LmNhbmNlbFxuICAgKiAgIFtlbl1FeGVjdXRlIHRoaXMgZnVuY3Rpb24gdG8gc3RvcCB0aGUgbW9kYWwgZnJvbSBiZWluZyBoaWRkZW4uWy9lbl1cbiAgICogICBbamFd44GT44Gu6Zai5pWw44KS5a6f6KGM44GZ44KL44Go44CB44OA44Kk44Ki44Ot44Kw44Gu6Z2e6KGo56S644GM44Kt44Oj44Oz44K744Or44GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBwb3N0aGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIG1vZGFsIGlzIGhpZGRlbi5bL2VuXVxuICAgKiBbamFd44Oi44O844OA44Or44GM6Zqg44KM44Gf5b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50Lm1vZGFsXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGRlZmF1bHRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFuaW1hdGlvbiB1c2VkIHdoZW4gc2hvd2luZyBhbmQgaGlkaW5nIHRoZSBtb2RhbC4gQ2FuIGJlIGVpdGhlciBgXCJub25lXCJgLCBgXCJmYWRlXCJgIG9yIGBcImxpZnRcImAuWy9lbl1cbiAgICogIFtqYV3jg6Ljg7zjg4Djg6vjgpLooajnpLrjgZnjgovpmpvjga7jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcIm5vbmVcIuOCguOBl+OBj+OBr1wiZmFkZVwiLFwibGlmdFwi44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uLW9wdGlvbnNcbiAgICogQHR5cGUge0V4cHJlc3Npb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCB0aW1pbmcgYW5kIGRlbGF5IHdpdGggYW4gb2JqZWN0IGxpdGVyYWwuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCB0aW1pbmcsIGRlbGF544KS44Kq44OW44K444Kn44Kv44OI44Oq44OG44Op44Or44Gn5oyH5a6a44GX44G+44GZ44CCZS5nLiA8Y29kZT57ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfTwvY29kZT5bL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fZGVmYXVsdERCQiA9ICgpID0+IHVuZGVmaW5lZDtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fY29tcGlsZSgpKTtcbiAgfVxuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHJldHVybiBzY2hlbWU7XG4gIH1cblxuICBfdXBkYXRlQW5pbWF0b3JGYWN0b3J5KCkge1xuICAgIHJldHVybiBuZXcgQW5pbWF0b3JGYWN0b3J5KHtcbiAgICAgIGFuaW1hdG9yczogX2FuaW1hdG9yRGljdCxcbiAgICAgIGJhc2VDbGFzczogTW9kYWxBbmltYXRvcixcbiAgICAgIGJhc2VDbGFzc05hbWU6ICdNb2RhbEFuaW1hdG9yJyxcbiAgICAgIGRlZmF1bHRBbmltYXRpb246IHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24nKVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvbkRldmljZUJhY2tCdXR0b25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUJhY2stYnV0dG9uIGhhbmRsZXIuWy9lbl1cbiAgICogICBbamFd44OQ44OD44Kv44Oc44K/44Oz44OP44Oz44OJ44Op44CCWy9qYV1cbiAgICovXG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgdGhpcy5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIHRoaXMuc3R5bGUuekluZGV4ID0gMTAwMDE7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKGRlZmF1bHRDbGFzc05hbWUpO1xuXG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLm1vZGFsX19jb250ZW50JykpIHtcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIGNvbnRlbnQuY2xhc3NMaXN0LmFkZCgnbW9kYWxfX2NvbnRlbnQnKTtcblxuICAgICAgd2hpbGUgKHRoaXMuY2hpbGROb2Rlc1swXSkge1xuICAgICAgICBjb25zdCBub2RlID0gdGhpcy5jaGlsZE5vZGVzWzBdO1xuICAgICAgICB0aGlzLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICBjb250ZW50Lmluc2VydEJlZm9yZShub2RlLCBudWxsKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5hcHBlbmRDaGlsZChjb250ZW50KTtcbiAgICB9XG5cbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHRoaXMuX3NjaGVtZSk7XG4gIH1cblxuICBfdG9nZ2xlU3R5bGUoc2hvdWxkU2hvdykge1xuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9IHNob3VsZFNob3cgPyAndGFibGUnIDogJ25vbmUnO1xuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgc3VwZXIuY29ubmVjdGVkQ2FsbGJhY2soKTtcbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHN1cGVyLmRpc2Nvbm5lY3RlZENhbGxiYWNrKCk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZpc2libGVcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZWxlbWVudCBpcyB2aXNpYmxlIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3opoHntKDjgYzopovjgYjjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQG1ldGhvZCBzaG93XG4gICAqIEBzaWduYXR1cmUgc2hvdyhbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcIm5vbmVcImAgYW5kIGBcImZhZGVcImAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCXCJub25lXCIsIFwiZmFkZVwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4ge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1UaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBhZnRlciB0aGUgbW9kYWwgaGFzIGJlZW4gcmV2ZWFsZWQuWy9lbl1cbiAgICogICBbamFd44Oi44O844OA44Or44GM6KGo56S644GV44KM57WC44KP44Gj44Gf5b6M44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNob3cgbW9kYWwuWy9lbl1cbiAgICogICBbamFd44Oi44O844OA44Or44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGRpc3BsYXllZCBlbGVtZW50Wy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBtZXRob2QgdG9nZ2xlXG4gICAqIEBzaWduYXR1cmUgdG9nZ2xlKFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUFuaW1hdGlvbiBuYW1lLiBBdmFpbGFibGUgYW5pbWF0aW9ucyBhcmUgYFwibm9uZVwiYCBhbmQgYFwiZmFkZVwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcIm5vbmVcIiwgXCJmYWRlXCLjga7jgYTjgZrjgozjgYvjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9Wy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXVRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIGFmdGVyIHRoZSBtb2RhbCBoYXMgYmVlbiByZXZlYWxlZC5bL2VuXVxuICAgKiAgIFtqYV3jg6Ljg7zjg4Djg6vjgYzooajnpLrjgZXjgozntYLjgo/jgaPjgZ/lvozjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVG9nZ2xlIG1vZGFsIHZpc2liaWxpdHkuWy9lbl1cbiAgICogICBbamFd44Oi44O844OA44Or44Gu6KGo56S644KS5YiH44KK5pu/44GI44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaGlkZVxuICAgKiBAc2lnbmF0dXJlIGhpZGUoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJub25lXCJgIGFuZCBgXCJmYWRlXCJgLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAglwibm9uZVwiLCBcImZhZGVcIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25PcHRpb25zXVxuICAgKiAgIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgZGVsYXkgYW5kIHRpbWluZy4gRS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIGRlbGF5LCB0aW1pbmfjgpLmjIflrprjgZfjgb7jgZnjgIJlLmcuIHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31bL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogICBbZW5dVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgYWZ0ZXIgdGhlIG1vZGFsIGhhcyBiZWVuIHJldmVhbGVkLlsvZW5dXG4gICAqICAgW2phXeODouODvOODgOODq+OBjOihqOekuuOBleOCjOe1guOCj+OBo+OBn+W+jOOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1IaWRlIG1vZGFsLlsvZW5dXG4gICAqICAgW2phXeODouODvOODgOODq+OCkumdnuihqOekuuOBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVJlc29sdmVzIHRvIHRoZSBoaWRkZW4gZWxlbWVudFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbLi4uc3VwZXIub2JzZXJ2ZWRBdHRyaWJ1dGVzLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdjbGFzcycpIHtcbiAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN1cGVyLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gQW5pbWF0b3JcbiAgICovXG4gIHN0YXRpYyByZWdpc3RlckFuaW1hdG9yKG5hbWUsIEFuaW1hdG9yKSB7XG4gICAgaWYgKCEoQW5pbWF0b3IucHJvdG90eXBlIGluc3RhbmNlb2YgTW9kYWxBbmltYXRvcikpIHtcbiAgICAgIHV0aWwudGhyb3dBbmltYXRvcignTW9kYWwnKTtcbiAgICB9XG4gICAgX2FuaW1hdG9yRGljdFtuYW1lXSA9IEFuaW1hdG9yO1xuICB9XG5cbiAgc3RhdGljIGdldCBhbmltYXRvcnMoKSB7XG4gICAgcmV0dXJuIF9hbmltYXRvckRpY3Q7XG4gIH1cblxuICBzdGF0aWMgZ2V0IE1vZGFsQW5pbWF0b3IoKSB7XG4gICAgcmV0dXJuIE1vZGFsQW5pbWF0b3I7XG4gIH1cbn1cblxub25zRWxlbWVudHMuTW9kYWwgPSBNb2RhbEVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1tb2RhbCcsIE1vZGFsRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgR2VzdHVyZURldGVjdG9yIGZyb20gJy4uLy4uL29ucy9nZXN0dXJlLWRldGVjdG9yJztcblxuY29uc3Qgd2lkdGhUb1B4ID0gKHdpZHRoKSA9PiB7XG4gIGNvbnN0IFt2YWx1ZSwgcHhdID0gW3BhcnNlSW50KHdpZHRoLCAxMCksIC9weC8udGVzdCh3aWR0aCldO1xuICByZXR1cm4gcHggPyB2YWx1ZSA6IE1hdGgucm91bmQoZG9jdW1lbnQuYm9keS5vZmZzZXRXaWR0aCAqIHZhbHVlIC8gMTAwKTtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN3aXBlUmV2ZWFsIHtcblxuICBjb25zdHJ1Y3RvcihwYXJhbXMpIHtcbiAgICAnZWxlbWVudCBpZ25vcmVTd2lwZSBpc0luaXRpYWxTdGF0ZSBvbkRyYWdDYWxsYmFjayBzd2lwZU1heCBzd2lwZU1pbiBzd2lwZU1pZCdcbiAgICAgIC5zcGxpdCgvXFxzKy8pLmZvckVhY2goa2V5ID0+IHRoaXNba2V5XSA9IHBhcmFtc1trZXldKTtcblxuICAgIHRoaXMuZWxlbWVudEhhbmRsZXIgPSBwYXJhbXMuZWxlbWVudEhhbmRsZXIgfHwgcGFyYW1zLmVsZW1lbnQ7XG4gICAgdGhpcy5nZXRUaHJlc2hvbGQgPSBwYXJhbXMuZ2V0VGhyZXNob2xkIHx8ICgoKSA9PiAuNSk7XG4gICAgdGhpcy5nZXRTaWRlID0gcGFyYW1zLmdldFNpZGUgfHwgKCgpID0+ICdsZWZ0Jyk7XG5cbiAgICB0aGlzLmhhbmRsZUdlc3R1cmUgPSB0aGlzLmhhbmRsZUdlc3R1cmUuYmluZCh0aGlzKTtcblxuICAgIHRoaXMuX3Nob3VsZEZpeFNjcm9sbCA9IHV0aWwuZ2xvYmFscy5hY3R1YWxNb2JpbGVPUyA9PT0gJ2lvcyc7XG4gIH1cblxuICB1cGRhdGUoc3dpcGVhYmxlID0gdGhpcy5lbGVtZW50Lmhhc0F0dHJpYnV0ZSgnc3dpcGVhYmxlJykpIHtcbiAgICBpZiAoIXRoaXMuZ2VzdHVyZURldGVjdG9yKSB7XG4gICAgICB0aGlzLmdlc3R1cmVEZXRlY3RvciA9IG5ldyBHZXN0dXJlRGV0ZWN0b3IodGhpcy5lbGVtZW50SGFuZGxlciwgeyBkcmFnTWluRGlzdGFuY2U6IDEsIHBhc3NpdmU6ICF0aGlzLl9zaG91bGRGaXhTY3JvbGwgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgYWN0aW9uID0gc3dpcGVhYmxlID8gJ29uJyA6ICdvZmYnO1xuICAgIHRoaXMuZ2VzdHVyZURldGVjdG9yW2FjdGlvbl0oJ2RyYWcgZHJhZ3N0YXJ0IGRyYWdlbmQnLCB0aGlzLmhhbmRsZUdlc3R1cmUpO1xuICB9XG5cbiAgaGFuZGxlR2VzdHVyZShlKSB7XG4gICAgaWYgKGUuZ2VzdHVyZSkge1xuICAgICAgaWYgKGUudHlwZSA9PT0gJ2RyYWdzdGFydCcpIHtcbiAgICAgICAgdGhpcy5vbkRyYWdTdGFydChlKTtcbiAgICAgIH0gZWxzZSBpZiAoIXRoaXMuX2lnbm9yZURyYWcpIHtcbiAgICAgICAgZS50eXBlID09PSAnZHJhZ2VuZCcgPyB0aGlzLm9uRHJhZ0VuZChlKSA6IHRoaXMub25EcmFnKGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG9uRHJhZ1N0YXJ0KGV2ZW50KSB7XG4gICAgY29uc3QgZ2V0RGlzdGFuY2UgPSAoKSA9PiB0aGlzLmdldFNpZGUoKSA9PT0gJ2xlZnQnID8gZXZlbnQuZ2VzdHVyZS5jZW50ZXIuY2xpZW50WCA6IHdpbmRvdy5pbm5lcldpZHRoIC0gZXZlbnQuZ2VzdHVyZS5jZW50ZXIuY2xpZW50WDtcbiAgICB0aGlzLl9pZ25vcmVEcmFnID0gZXZlbnQuY29uc3VtZWQgfHwgIXV0aWwuaXNWYWxpZEdlc3R1cmUoZXZlbnQpIHx8IHRoaXMuaWdub3JlU3dpcGUoZXZlbnQsIGdldERpc3RhbmNlKCkpO1xuXG4gICAgaWYgKCF0aGlzLl9pZ25vcmVEcmFnKSB7XG4gICAgICBldmVudC5jb25zdW1lICYmIGV2ZW50LmNvbnN1bWUoKTtcbiAgICAgIGV2ZW50LmNvbnN1bWVkID0gdHJ1ZTtcblxuICAgICAgdGhpcy5fd2lkdGggPSB3aWR0aFRvUHgodGhpcy5lbGVtZW50LnN0eWxlLndpZHRoIHx8ICcxMDAlJyk7XG4gICAgICB0aGlzLl9zdGFydERpc3RhbmNlID0gdGhpcy5fZGlzdGFuY2UgPSAoISh0aGlzLmlzSW5pdGlhbFN0YXRlIGluc3RhbmNlb2YgRnVuY3Rpb24pIHx8IHRoaXMuaXNJbml0aWFsU3RhdGUoKSkgPyAwIDogdGhpcy5fd2lkdGg7XG5cbiAgICAgIHV0aWwuaW9zUHJldmVudFNjcm9sbCh0aGlzLmdlc3R1cmVEZXRlY3Rvcik7XG4gICAgfVxuICB9XG5cbiAgb25EcmFnKGV2ZW50KSB7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICBjb25zdCBkZWx0YSA9IHRoaXMuZ2V0U2lkZSgpID09PSAnbGVmdCcgPyBldmVudC5nZXN0dXJlLmRlbHRhWCA6IC1ldmVudC5nZXN0dXJlLmRlbHRhWDtcbiAgICBjb25zdCBkaXN0YW5jZSA9IE1hdGgubWF4KDAsIE1hdGgubWluKHRoaXMuX3dpZHRoLCB0aGlzLl9zdGFydERpc3RhbmNlICsgZGVsdGEpKTtcbiAgICBpZiAoZGlzdGFuY2UgIT09IHRoaXMuX2Rpc3RhbmNlKSB7XG4gICAgICB0aGlzLl9kaXN0YW5jZSA9IGRpc3RhbmNlO1xuICAgICAgdGhpcy5zd2lwZU1pZCh0aGlzLl9kaXN0YW5jZSwgdGhpcy5fd2lkdGgpO1xuICAgIH1cbiAgfVxuXG4gIG9uRHJhZ0VuZChldmVudCkge1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgY29uc3QgZGlyZWN0aW9uID0gZXZlbnQuZ2VzdHVyZS5pbnRlcmltRGlyZWN0aW9uO1xuICAgIGNvbnN0IGlzU3dpcGVNYXggPSB0aGlzLmdldFNpZGUoKSAhPT0gZGlyZWN0aW9uICYmIHRoaXMuX2Rpc3RhbmNlID4gdGhpcy5fd2lkdGggKiB0aGlzLmdldFRocmVzaG9sZCgpO1xuICAgIGlzU3dpcGVNYXggPyB0aGlzLnN3aXBlTWF4KCkgOiB0aGlzLnN3aXBlTWluKCk7XG4gIH1cblxuICBkaXNwb3NlKCkge1xuICAgIHRoaXMuZ2VzdHVyZURldGVjdG9yICYmIHRoaXMuZ2VzdHVyZURldGVjdG9yLmRpc3Bvc2UoKTtcbiAgICB0aGlzLmdlc3R1cmVEZXRlY3RvciA9IHRoaXMuZWxlbWVudCA9IHRoaXMuZWxlbWVudEhhbmRsZXIgPSBudWxsO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgQmFzZUFuaW1hdG9yIGZyb20gJy4uLy4uL29ucy9iYXNlLWFuaW1hdG9yJ1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBOYXZpZ2F0b3JBbmltYXRvciBleHRlbmRzIEJhc2VBbmltYXRvciB7XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnRpbWluZ1xuICAgKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5kdXJhdGlvblxuICAgKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5kZWxheVxuICAgKi9cbiAgY29uc3RydWN0b3Iob3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICB0aW1pbmc6ICdsaW5lYXInLFxuICAgICAgZHVyYXRpb246ICcwLjQnLFxuICAgICAgZGVsYXk6ICcwJ1xuICAgIH0sIG9wdGlvbnMgfHwge30pO1xuXG4gICAgc3VwZXIob3B0aW9ucyk7XG4gIH1cblxuICBwdXNoKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrKCk7XG4gIH1cblxuICBwb3AoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIGJsb2NrKHBhZ2UpIHtcbiAgICBjb25zdCBibG9ja2VyID0gdXRpbC5jcmVhdGVFbGVtZW50KGBcbiAgICAgIDxkaXYgc3R5bGU9XCJwb3NpdGlvbjogYWJzb2x1dGU7IGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50OyB3aWR0aDogMTAwJTsgaGVpZ2h0OiAxMDAlOyB6LWluZGV4OiAxMDAwMDBcIj48L2Rpdj5cbiAgICBgKTtcbiAgICBwYWdlLnBhcmVudE5vZGUuYXBwZW5kQ2hpbGQoYmxvY2tlcik7XG4gICAgcmV0dXJuICgpID0+IGJsb2NrZXIucmVtb3ZlKCk7XG4gIH1cbn1cblxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IE5hdmlnYXRvckFuaW1hdG9yIGZyb20gJy4vYW5pbWF0b3InO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi8uLi9vbnMvYW5pbWl0JztcblxuLyoqXG4gKiBBYnN0cmFjdCBzd2lwZSBhbmltYXRvciBmb3IgaU9TIG5hdmlnYXRvciB0cmFuc2l0aW9uLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJT1NTd2lwZU5hdmlnYXRvckFuaW1hdG9yIGV4dGVuZHMgTmF2aWdhdG9yQW5pbWF0b3Ige1xuXG4gIHN0YXRpYyBnZXQgc3dpcGVhYmxlKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgY29uc3RydWN0b3IoeyBkdXJhdGlvblJlc3RvcmUgPSAwLjEsIGR1cmF0aW9uU3dpcGUgPSAwLjE1LCB0aW1pbmdTd2lwZSA9ICdsaW5lYXInLCAuLi5yZXN0IH0gPSB7fSkge1xuICAgIHN1cGVyKHsuLi5yZXN0fSk7XG5cbiAgICBpZiAodGhpcy5jb25zdHJ1Y3RvciA9PT0gSU9TU3dpcGVOYXZpZ2F0b3JBbmltYXRvcikge1xuICAgICAgdXRpbC50aHJvd0Fic3RyYWN0KCk7XG4gICAgfVxuXG4gICAgdGhpcy5kdXJhdGlvblJlc3RvcmUgPSBkdXJhdGlvblJlc3RvcmU7XG4gICAgdGhpcy5kdXJhdGlvblN3aXBlID0gZHVyYXRpb25Td2lwZTtcbiAgICB0aGlzLnRpbWluZ1N3aXBlID0gdGltaW5nU3dpcGU7XG5cbiAgICB0aGlzLm9wdFN3aXBlID0geyB0aW1pbmc6IHRpbWluZ1N3aXBlLCBkdXJhdGlvbjogZHVyYXRpb25Td2lwZSB9O1xuICAgIHRoaXMub3B0UmVzdG9yZSA9IHsgdGltaW5nOiB0aW1pbmdTd2lwZSwgZHVyYXRpb246IGR1cmF0aW9uUmVzdG9yZSB9O1xuXG4gICAgdGhpcy5zd2lwZVNoYWRvdyA9IHV0aWwuY3JlYXRlRWxlbWVudChcbiAgICAgIGA8ZGl2IHN0eWxlPVwicG9zaXRpb246IGFic29sdXRlOyBoZWlnaHQ6IDEwMCU7IHdpZHRoOiAxMnB4OyByaWdodDogMTAwJTsgdG9wOiAwOyBib3R0b206IDA7IHotaW5kZXg6IC0xO2AgK1xuICAgICAgICBgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KHRvIHJpZ2h0LCB0cmFuc3BhcmVudCAwLCByZ2JhKDAsMCwwLC4wNCkgNDAlLCByZ2JhKDAsMCwwLC4xMikgODAlLCByZ2JhKDAsMCwwLC4xNikgMTAwJSk7XCI+PC9kaXY+YFxuICAgICk7XG5cbiAgICB0aGlzLmlzRHJhZ1N0YXJ0ID0gdHJ1ZTtcbiAgfVxuXG4gIF9kZWNvbXBvc2UoKSB7XG4gICAgdXRpbC50aHJvd01lbWJlcigpO1xuICB9XG5cbiAgX3Nob3VsZEFuaW1hdGVUb29sYmFyKCkge1xuICAgIHV0aWwudGhyb3dNZW1iZXIoKTtcbiAgfVxuXG4gIF9jYWxjdWxhdGVEZWx0YSgpIHtcbiAgICB1dGlsLnRocm93TWVtYmVyKCk7XG4gIH1cblxuICBfZHJhZ1N0YXJ0U2V0dXAoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UpIHtcbiAgICB0aGlzLmlzRHJhZ1N0YXJ0ID0gZmFsc2U7XG5cbiAgICAvLyBBdm9pZCBjb250ZW50IGNsaWNrc1xuICAgIHRoaXMudW5ibG9jayA9IHN1cGVyLmJsb2NrKGxlYXZlUGFnZSk7XG5cbiAgICAvLyBNYXNrXG4gICAgZW50ZXJQYWdlLnBhcmVudEVsZW1lbnQuaW5zZXJ0QmVmb3JlKHRoaXMuYmFja2dyb3VuZE1hc2ssIGVudGVyUGFnZSk7XG5cbiAgICAvLyBEZWNvbXBvc2l0aW9uXG4gICAgdGhpcy50YXJnZXQgPSB7XG4gICAgICBlbnRlcjogdXRpbC5maW5kVG9vbGJhclBhZ2UoZW50ZXJQYWdlKSB8fCBlbnRlclBhZ2UsXG4gICAgICBsZWF2ZTogdXRpbC5maW5kVG9vbGJhclBhZ2UobGVhdmVQYWdlKSB8fCBsZWF2ZVBhZ2UsXG4gICAgfTtcbiAgICB0aGlzLmRlY29tcCA9IHtcbiAgICAgIGVudGVyOiB0aGlzLl9kZWNvbXBvc2UodGhpcy50YXJnZXQuZW50ZXIpLFxuICAgICAgbGVhdmU6IHRoaXMuX2RlY29tcG9zZSh0aGlzLnRhcmdldC5sZWF2ZSlcbiAgICB9O1xuXG4gICAgLy8gQW5pbWF0aW9uIHZhbHVlc1xuICAgIHRoaXMuZGVsdGEgPSB0aGlzLl9jYWxjdWxhdGVEZWx0YShsZWF2ZVBhZ2UsIHRoaXMuZGVjb21wLmxlYXZlKTtcbiAgICB0aGlzLnNob3VsZEFuaW1hdGVUb29sYmFyID0gdGhpcy5fc2hvdWxkQW5pbWF0ZVRvb2xiYXIodGhpcy50YXJnZXQuZW50ZXIsIHRoaXMudGFyZ2V0LmxlYXZlKTtcblxuICAgIC8vIFNoYWRvdyAmJiBzdHlsZXNcbiAgICBpZiAodGhpcy5zaG91bGRBbmltYXRlVG9vbGJhcikge1xuICAgICAgdGhpcy5zd2lwZVNoYWRvdy5zdHlsZS50b3AgPSB0aGlzLmRlY29tcC5sZWF2ZS50b29sYmFyLm9mZnNldEhlaWdodCArICdweCc7XG4gICAgICB0aGlzLnRhcmdldC5sZWF2ZS5hcHBlbmRDaGlsZCh0aGlzLnN3aXBlU2hhZG93KTtcbiAgICAgIHRoaXMuX3NhdmVTdHlsZSh0aGlzLnRhcmdldC5lbnRlciwgdGhpcy50YXJnZXQubGVhdmUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZWF2ZVBhZ2UuYXBwZW5kQ2hpbGQodGhpcy5zd2lwZVNoYWRvdyk7XG4gICAgICB0aGlzLl9zYXZlU3R5bGUoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UpO1xuICAgIH1cbiAgICBsZWF2ZVBhZ2UuY2xhc3NMaXN0LmFkZCgnb3ZlcmZsb3ctdmlzaWJsZScpO1xuICAgIHRoaXMub3ZlcmZsb3dFbGVtZW50ID0gbGVhdmVQYWdlO1xuICAgIHRoaXMuZGVjb21wLmxlYXZlLmNvbnRlbnQuY2xhc3NMaXN0LmFkZCgnY29udGVudC1zd2lwaW5nJyk7XG5cbiAgfVxuXG4gIHRyYW5zbGF0ZShkaXN0YW5jZSwgbWF4V2lkdGgsIGVudGVyUGFnZSwgbGVhdmVQYWdlKSB7XG4gICAgdGhpcy5pc1N3aXBpbmcgPSB0cnVlO1xuXG4gICAgaWYgKGVudGVyUGFnZS5zdHlsZS5kaXNwbGF5ID09PSAnbm9uZScpIHtcbiAgICAgIGVudGVyUGFnZS5zdHlsZS5kaXNwbGF5ID0gJyc7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaXNEcmFnU3RhcnQpIHtcbiAgICAgIHRoaXMubWF4V2lkdGggPSBtYXhXaWR0aDtcbiAgICAgIHRoaXMuX2RyYWdTdGFydFNldHVwKGVudGVyUGFnZSwgbGVhdmVQYWdlKTtcbiAgICB9XG5cbiAgICBjb25zdCBzd2lwZVJhdGlvID0gKGRpc3RhbmNlIC0gbWF4V2lkdGgpIC8gbWF4V2lkdGg7XG5cbiAgICBpZiAodGhpcy5zaG91bGRBbmltYXRlVG9vbGJhcikge1xuXG4gICAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICAgIC8qIEVudGVyIHBhZ2UgKi9cblxuICAgICAgICBhbmltaXQoW3RoaXMuZGVjb21wLmVudGVyLmNvbnRlbnQsIHRoaXMuZGVjb21wLmVudGVyLmJvdHRvbVRvb2xiYXIsIHRoaXMuZGVjb21wLmVudGVyLmJhY2tncm91bmRdKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgke3N3aXBlUmF0aW8gKiAyNX0lLCAwLCAwKWAsXG4gICAgICAgICAgICBvcGFjaXR5OiAxICsgc3dpcGVSYXRpbyAqIDEwIC8gMTAwIC8vIDAuOSAtPiAxXG4gICAgICAgICAgfSksXG5cbiAgICAgICAgYW5pbWl0KHRoaXMuZGVjb21wLmVudGVyLnRvb2xiYXJDZW50ZXIpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKCR7dGhpcy5kZWx0YS50aXRsZSAqIHN3aXBlUmF0aW99cHgsIDAsIDApYCxcbiAgICAgICAgICAgIG9wYWNpdHk6IDEgKyBzd2lwZVJhdGlvIC8vIDAgLT4gMVxuICAgICAgICAgIH0pLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLmRlY29tcC5lbnRlci5iYWNrQnV0dG9uTGFiZWwpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIG9wYWNpdHk6IDEgKyBzd2lwZVJhdGlvICogMTAgLyAxMDAsIC8vIDAuOSAtPiAxXG4gICAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgke3RoaXMuZGVsdGEubGFiZWwgKiBzd2lwZVJhdGlvfXB4LCAwLCAwKWBcbiAgICAgICAgICB9KSxcblxuICAgICAgICBhbmltaXQodGhpcy5kZWNvbXAuZW50ZXIub3RoZXIpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIG9wYWNpdHk6IDEgKyBzd2lwZVJhdGlvIC8vIDAgLT4gMVxuICAgICAgICAgIH0pLFxuXG4gICAgICAgIC8qIExlYXZlIHBhZ2UgKi9cblxuICAgICAgICBhbmltaXQoW3RoaXMuZGVjb21wLmxlYXZlLmNvbnRlbnQsIHRoaXMuZGVjb21wLmxlYXZlLmJvdHRvbVRvb2xiYXIsIHRoaXMuZGVjb21wLmxlYXZlLmJhY2tncm91bmQsIHRoaXMuc3dpcGVTaGFkb3ddKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgke2Rpc3RhbmNlfXB4LCAwLCAwKWBcbiAgICAgICAgICB9KSxcblxuICAgICAgICBhbmltaXQodGhpcy5kZWNvbXAubGVhdmUudG9vbGJhcilcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgb3BhY2l0eTogLTEgKiBzd2lwZVJhdGlvIC8vIDEgLT4gMFxuICAgICAgICAgIH0pLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLmRlY29tcC5sZWF2ZS50b29sYmFyQ2VudGVyKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgkeygxICsgc3dpcGVSYXRpbykgKiAxMjV9JSwgMCwgMClgXG4gICAgICAgICAgfSksXG5cbiAgICAgICAgYW5pbWl0KHRoaXMuZGVjb21wLmxlYXZlLmJhY2tCdXR0b25MYWJlbClcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgb3BhY2l0eTogLTEgKiBzd2lwZVJhdGlvLCAvLyAxIC0+IDBcbiAgICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKCR7dGhpcy5kZWx0YS50aXRsZSAqICgxICsgc3dpcGVSYXRpbyl9cHgsIDAsIDApYFxuICAgICAgICAgIH0pLFxuXG5cbiAgICAgICAgLyogT3RoZXIgKi9cblxuICAgICAgICBhbmltaXQodGhpcy5zd2lwZVNoYWRvdylcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgb3BhY2l0eTogLTEgKiBzd2lwZVJhdGlvIC8vIDEgLT4gMFxuICAgICAgICAgIH0pXG4gICAgICApO1xuXG5cbiAgICB9IGVsc2Uge1xuICAgICAgYW5pbWl0LnJ1bkFsbChcbiAgICAgICAgYW5pbWl0KGxlYXZlUGFnZSlcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoJHtkaXN0YW5jZX1weCwgMCwgMClgXG4gICAgICAgICAgfSksXG5cbiAgICAgICAgYW5pbWl0KGVudGVyUGFnZSlcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoJHtzd2lwZVJhdGlvICogMjV9JSwgMCwgMClgLFxuICAgICAgICAgICAgb3BhY2l0eTogMSArIHN3aXBlUmF0aW8gKiAxMCAvIDEwMCAvLyAwLjkgLT4gMVxuICAgICAgICAgIH0pLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLnN3aXBlU2hhZG93KVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBvcGFjaXR5OiAtMSAqIHN3aXBlUmF0aW8gLy8gMSAtPiAwXG4gICAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcmVzdG9yZShlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcbiAgICBpZiAodGhpcy5pc0RyYWdTdGFydCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnNob3VsZEFuaW1hdGVUb29sYmFyKSB7XG5cbiAgICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgICAgLyogRW50ZXIgcGFnZSAqL1xuXG4gICAgICAgIGFuaW1pdChbdGhpcy5kZWNvbXAuZW50ZXIuY29udGVudCwgdGhpcy5kZWNvbXAuZW50ZXIuYm90dG9tVG9vbGJhciwgdGhpcy5kZWNvbXAuZW50ZXIuYmFja2dyb3VuZF0pXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC0yNSUsIDAsIDApJyxcbiAgICAgICAgICAgIG9wYWNpdHk6IDAuOVxuICAgICAgICAgIH0sIHRoaXMub3B0UmVzdG9yZSksXG5cbiAgICAgICAgYW5pbWl0KHRoaXMuZGVjb21wLmVudGVyLnRvb2xiYXJDZW50ZXIpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKC0ke3RoaXMuZGVsdGEudGl0bGV9cHgsIDAsIDApYCxcbiAgICAgICAgICAgIHRyYW5zaXRpb246IGBvcGFjaXR5ICR7dGhpcy5kdXJhdGlvblJlc3RvcmV9cyBsaW5lYXIsIHRyYW5zZm9ybSAke3RoaXMuZHVyYXRpb25SZXN0b3JlfXMgJHt0aGlzLnRpbWluZ1N3aXBlfWAsXG4gICAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgICAgfSksXG5cbiAgICAgICAgYW5pbWl0KHRoaXMuZGVjb21wLmVudGVyLmJhY2tCdXR0b25MYWJlbClcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoLSR7dGhpcy5kZWx0YS5sYWJlbH1weCwgMCwgMClgXG4gICAgICAgICAgfSwgdGhpcy5vcHRSZXN0b3JlKSxcblxuICAgICAgICBhbmltaXQodGhpcy5kZWNvbXAuZW50ZXIub3RoZXIpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIG9wYWNpdHk6IDBcbiAgICAgICAgICB9LCB0aGlzLm9wdFJlc3RvcmUpLFxuXG4gICAgICAgIC8qIExlYXZlIHBhZ2UgKi9cblxuICAgICAgICBhbmltaXQoW3RoaXMuZGVjb21wLmxlYXZlLmNvbnRlbnQsIHRoaXMuZGVjb21wLmxlYXZlLmJvdHRvbVRvb2xiYXIsIHRoaXMuZGVjb21wLmxlYXZlLmJhY2tncm91bmQsIHRoaXMuc3dpcGVTaGFkb3ddKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCAwLCAwKWBcbiAgICAgICAgICB9LCB0aGlzLm9wdFJlc3RvcmUpLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLmRlY29tcC5sZWF2ZS50b29sYmFyKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBvcGFjaXR5OiAxXG4gICAgICAgICAgfSwgdGhpcy5vcHRSZXN0b3JlKSxcblxuICAgICAgICBhbmltaXQodGhpcy5kZWNvbXAubGVhdmUudG9vbGJhckNlbnRlcilcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoMCwgMCwgMClgXG4gICAgICAgICAgfSwgdGhpcy5vcHRSZXN0b3JlKSxcblxuICAgICAgICBhbmltaXQodGhpcy5kZWNvbXAubGVhdmUuYmFja0J1dHRvbkxhYmVsKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBvcGFjaXR5OiAxLFxuICAgICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoMCwgMCwgMClgLFxuICAgICAgICAgICAgdHJhbnNpdGlvbjogYG9wYWNpdHkgJHt0aGlzLmR1cmF0aW9uUmVzdG9yZX1zIGxpbmVhciwgdHJhbnNmb3JtICR7dGhpcy5kdXJhdGlvblJlc3RvcmV9cyAke3RoaXMudGltaW5nU3dpcGV9YFxuICAgICAgICAgIH0pLFxuXG5cbiAgICAgICAgLyogT3RoZXIgKi9cblxuICAgICAgICBhbmltaXQodGhpcy5zd2lwZVNoYWRvdylcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICAgIH0sIHRoaXMub3B0UmVzdG9yZSlcbiAgICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9yZXNldCh0aGlzLnRhcmdldC5lbnRlciwgdGhpcy50YXJnZXQubGVhdmUpO1xuICAgICAgICAgICAgZW50ZXJQYWdlLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgICBjYWxsYmFjayAmJiBjYWxsYmFjaygpO1xuICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgIH0pXG4gICAgICApO1xuXG5cbiAgICB9IGVsc2Uge1xuICAgICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgICBhbmltaXQoZW50ZXJQYWdlKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKC0yNSUsIDAsIDApJyxcbiAgICAgICAgICBvcGFjaXR5OiAwLjlcbiAgICAgICAgfSwgdGhpcy5vcHRSZXN0b3JlKSxcblxuICAgICAgICBhbmltaXQobGVhdmVQYWdlKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDAsIDApJ1xuICAgICAgICB9LCB0aGlzLm9wdFJlc3RvcmUpXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICB0aGlzLl9yZXNldChlbnRlclBhZ2UsIGxlYXZlUGFnZSk7XG4gICAgICAgICAgZW50ZXJQYWdlLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHBvcFN3aXBlKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLmlzRHJhZ1N0YXJ0KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2hvdWxkQW5pbWF0ZVRvb2xiYXIpIHtcblxuICAgICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgICAvKiBFbnRlciBwYWdlICovXG5cbiAgICAgICAgYW5pbWl0KFt0aGlzLmRlY29tcC5lbnRlci5jb250ZW50LCB0aGlzLmRlY29tcC5lbnRlci5ib3R0b21Ub29sYmFyLCB0aGlzLmRlY29tcC5lbnRlci5iYWNrZ3JvdW5kXSlcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknLFxuICAgICAgICAgICAgb3BhY2l0eTogMVxuICAgICAgICAgIH0sIHRoaXMub3B0U3dpcGUpLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLmRlY29tcC5lbnRlci50b29sYmFyQ2VudGVyKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCAwLCAwKWAsXG4gICAgICAgICAgICB0cmFuc2l0aW9uOiBgb3BhY2l0eSAke3RoaXMuZHVyYXRpb25Td2lwZX1zIGxpbmVhciwgdHJhbnNmb3JtICR7dGhpcy5kdXJhdGlvblN3aXBlfXMgJHt0aGlzLnRpbWluZ1N3aXBlfWAsXG4gICAgICAgICAgICBvcGFjaXR5OiAxXG4gICAgICAgICAgfSksXG5cbiAgICAgICAgYW5pbWl0KHRoaXMuZGVjb21wLmVudGVyLmJhY2tCdXR0b25MYWJlbClcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoMCwgMCwgMClgXG4gICAgICAgICAgfSwgdGhpcy5vcHRTd2lwZSksXG5cbiAgICAgICAgYW5pbWl0KHRoaXMuZGVjb21wLmVudGVyLm90aGVyKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBvcGFjaXR5OiAxXG4gICAgICAgICAgfSwgdGhpcy5vcHRTd2lwZSksXG5cbiAgICAgICAgLyogTGVhdmUgcGFnZSAqL1xuXG4gICAgICAgIGFuaW1pdChbdGhpcy5kZWNvbXAubGVhdmUuY29udGVudCwgdGhpcy5kZWNvbXAubGVhdmUuYm90dG9tVG9vbGJhciwgdGhpcy5kZWNvbXAubGVhdmUuYmFja2dyb3VuZF0pXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDEwMCUsIDAsIDApYFxuICAgICAgICAgIH0sIHRoaXMub3B0U3dpcGUpLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLmRlY29tcC5sZWF2ZS50b29sYmFyKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgICAgfSwgdGhpcy5vcHRTd2lwZSksXG5cbiAgICAgICAgYW5pbWl0KHRoaXMuZGVjb21wLmxlYXZlLnRvb2xiYXJDZW50ZXIpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDEyNSUsIDAsIDApYFxuICAgICAgICAgIH0sIHRoaXMub3B0U3dpcGUpLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLmRlY29tcC5sZWF2ZS5iYWNrQnV0dG9uTGFiZWwpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIG9wYWNpdHk6IDAsXG4gICAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgke3RoaXMuZGVsdGEudGl0bGV9cHgsIDAsIDApYCxcbiAgICAgICAgICAgIHRyYW5zaXRpb246IGBvcGFjaXR5ICR7dGhpcy5kdXJhdGlvblN3aXBlfXMgbGluZWFyLCB0cmFuc2Zvcm0gJHt0aGlzLmR1cmF0aW9uU3dpcGV9cyAke3RoaXMudGltaW5nU3dpcGV9YFxuICAgICAgICAgIH0pLFxuXG5cbiAgICAgICAgLyogT3RoZXIgKi9cblxuICAgICAgICBhbmltaXQodGhpcy5zd2lwZVNoYWRvdylcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgb3BhY2l0eTogMCxcbiAgICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKCR7dGhpcy5tYXhXaWR0aH1weCwgMCwgMClgXG4gICAgICAgICAgfSwgdGhpcy5vcHRTd2lwZSlcbiAgICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9yZXNldCh0aGlzLnRhcmdldC5lbnRlciwgdGhpcy50YXJnZXQubGVhdmUpO1xuICAgICAgICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgICB9KVxuICAgICAgKTtcblxuICAgIH0gZWxzZSB7XG4gICAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICAgIGFuaW1pdChlbnRlclBhZ2UpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMCwgMCknLFxuICAgICAgICAgIG9wYWNpdHk6IDEuMFxuICAgICAgICB9LCB0aGlzLm9wdFN3aXBlKSxcblxuICAgICAgICBhbmltaXQobGVhdmVQYWdlKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDEwMCUsIDAsIDApJ1xuICAgICAgICB9LCB0aGlzLm9wdFN3aXBlKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgdGhpcy5fcmVzZXQoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UpO1xuICAgICAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBfc2F2ZVN0eWxlKC4uLmFyZ3MpIHtcbiAgICB0aGlzLl9zYXZlZFN0eWxlID0gbmV3IFdlYWtNYXAoKTtcbiAgICBjb25zdCBzYXZlID0gZWwgPT4gdGhpcy5fc2F2ZWRTdHlsZS5zZXQoZWwsIGVsLmdldEF0dHJpYnV0ZSgnc3R5bGUnKSk7XG4gICAgYXJncy5mb3JFYWNoKHNhdmUpO1xuXG4gICAgT2JqZWN0LmtleXModGhpcy5kZWNvbXApLmZvckVhY2gocCA9PiB7XG4gICAgICBPYmplY3Qua2V5cyh0aGlzLmRlY29tcFtwXSkuZm9yRWFjaChrID0+IHtcbiAgICAgICAgKHRoaXMuZGVjb21wW3BdW2tdIGluc3RhbmNlb2YgQXJyYXkgPyB0aGlzLmRlY29tcFtwXVtrXSA6IFt0aGlzLmRlY29tcFtwXVtrXV0pLmZvckVhY2goc2F2ZSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIF9yZXN0b3JlU3R5bGUoLi4uYXJncykge1xuICAgIGNvbnN0IHJlc3RvcmUgPSBlbCA9PiB7XG4gICAgICB0aGlzLl9zYXZlZFN0eWxlLmdldChlbCkgPT09IG51bGwgPyBlbC5yZW1vdmVBdHRyaWJ1dGUoJ3N0eWxlJykgOiBlbC5zZXRBdHRyaWJ1dGUoJ3N0eWxlJywgdGhpcy5fc2F2ZWRTdHlsZS5nZXQoZWwpKVxuICAgICAgdGhpcy5fc2F2ZWRTdHlsZS5kZWxldGUoZWwpXG4gICAgfTtcbiAgICBhcmdzLmZvckVhY2gocmVzdG9yZSk7XG5cbiAgICBPYmplY3Qua2V5cyh0aGlzLmRlY29tcCkuZm9yRWFjaChwID0+IHtcbiAgICAgIE9iamVjdC5rZXlzKHRoaXMuZGVjb21wW3BdKS5mb3JFYWNoKGsgPT4ge1xuICAgICAgICAodGhpcy5kZWNvbXBbcF1ba10gaW5zdGFuY2VvZiBBcnJheSA/IHRoaXMuZGVjb21wW3BdW2tdIDogW3RoaXMuZGVjb21wW3BdW2tdXSkuZm9yRWFjaChyZXN0b3JlKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgX3Jlc2V0KC4uLmFyZ3MpIHtcbiAgICB0aGlzLmlzU3dpcGluZyA9IGZhbHNlO1xuICAgIHRoaXMuX3NhdmVkU3R5bGUgJiYgdGhpcy5fcmVzdG9yZVN0eWxlKC4uLmFyZ3MpO1xuICAgIHRoaXMudW5ibG9jayAmJiB0aGlzLnVuYmxvY2soKTtcbiAgICB0aGlzLnN3aXBlU2hhZG93LnJlbW92ZSgpO1xuICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgdGhpcy5vdmVyZmxvd0VsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZSgnb3ZlcmZsb3ctdmlzaWJsZScpO1xuICAgIHRoaXMuZGVjb21wLmxlYXZlLmNvbnRlbnQuY2xhc3NMaXN0LnJlbW92ZSgnY29udGVudC1zd2lwaW5nJyk7XG4gICAgdGhpcy5kZWNvbXAgPSB0aGlzLnRhcmdldCA9IHRoaXMub3ZlcmZsb3dFbGVtZW50ID0gdGhpcy5fc2F2ZWRTdHlsZSA9IG51bGw7XG4gICAgdGhpcy5pc0RyYWdTdGFydCA9IHRydWU7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBJT1NTd2lwZU5hdmlnYXRvckFuaW1hdG9yIGZyb20gJy4vaW9zLXN3aXBlLWFuaW1hdG9yJztcbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBhbmltaXQgZnJvbSAnLi4vLi4vb25zL2FuaW1pdCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3QgdHJhbnNsYXRlM2QgPSAoeCA9IDAsIHkgPSAwLCB6ID0gMCkgPT4gYHRyYW5zbGF0ZTNkKCR7eH0sICR7eX0sICR7en0pYDtcblxuLyoqXG4gKiBTbGlkZSBhbmltYXRvciBmb3IgbmF2aWdhdG9yIHRyYW5zaXRpb24gbGlrZSBpT1MncyBzY3JlZW4gc2xpZGUgdHJhbnNpdGlvbi5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSU9TU2xpZGVOYXZpZ2F0b3JBbmltYXRvciBleHRlbmRzIElPU1N3aXBlTmF2aWdhdG9yQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHsgdGltaW5nID0gJ2N1YmljLWJlemllcigwLjMsIC40LCAwLCAuOSknLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC40LCAuLi5yZXN0IH0gPSB7fSkge1xuICAgIHN1cGVyKHsgdGltaW5nLCBkZWxheSwgZHVyYXRpb24sIC4uLnJlc3QgfSk7XG5cbiAgICB0aGlzLmJhY2tncm91bmRNYXNrID0gdXRpbC5jcmVhdGVFbGVtZW50KFxuICAgICAgYDxkaXYgc3R5bGU9XCJwb3NpdGlvbjogYWJzb2x1dGU7IHdpZHRoOiAxMDAlOyBoZWlnaHQ6IDEwMCU7YCArXG4gICAgICAgIGBiYWNrZ3JvdW5kLWNvbG9yOiBibGFjazsgei1pbmRleDogMlwiPjwvZGl2PmBcbiAgICApO1xuICB9XG5cbiAgX2RlY29tcG9zZShwYWdlKSB7XG4gICAgY29uc3QgdG9vbGJhciA9IHBhZ2UuX2dldFRvb2xiYXJFbGVtZW50KCk7XG4gICAgY29uc3QgbGVmdCA9IHRvb2xiYXIuX2dldFRvb2xiYXJMZWZ0SXRlbXNFbGVtZW50KCk7XG4gICAgY29uc3QgcmlnaHQgPSB0b29sYmFyLl9nZXRUb29sYmFyUmlnaHRJdGVtc0VsZW1lbnQoKTtcblxuICAgIGNvbnN0IGV4Y2x1ZGVCYWNrQnV0dG9uID0gZnVuY3Rpb24oZWxlbWVudHMpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChlbGVtZW50c1tpXS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpICE9PSAnb25zLWJhY2stYnV0dG9uJykge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKGVsZW1lbnRzW2ldKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICBjb25zdCBvdGhlciA9IFtdXG4gICAgICAuY29uY2F0KGxlZnQuY2hpbGRyZW4ubGVuZ3RoID09PSAwID8gbGVmdCA6IGV4Y2x1ZGVCYWNrQnV0dG9uKGxlZnQuY2hpbGRyZW4pKVxuICAgICAgLmNvbmNhdChyaWdodC5jaGlsZHJlbi5sZW5ndGggPT09IDAgPyByaWdodCA6IGV4Y2x1ZGVCYWNrQnV0dG9uKHJpZ2h0LmNoaWxkcmVuKSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdG9vbGJhckNlbnRlcjogdG9vbGJhci5fZ2V0VG9vbGJhckNlbnRlckl0ZW1zRWxlbWVudCgpLFxuICAgICAgYmFja0J1dHRvbkljb246IHRvb2xiYXIuX2dldFRvb2xiYXJCYWNrQnV0dG9uSWNvbkVsZW1lbnQoKSxcbiAgICAgIGJhY2tCdXR0b25MYWJlbDogdG9vbGJhci5fZ2V0VG9vbGJhckJhY2tCdXR0b25MYWJlbEVsZW1lbnQoKSxcbiAgICAgIG90aGVyOiBvdGhlcixcbiAgICAgIGNvbnRlbnQ6IHBhZ2UuX2dldENvbnRlbnRFbGVtZW50KCksXG4gICAgICBiYWNrZ3JvdW5kOiBwYWdlLl9nZXRCYWNrZ3JvdW5kRWxlbWVudCgpLFxuICAgICAgdG9vbGJhcjogdG9vbGJhcixcbiAgICAgIGJvdHRvbVRvb2xiYXI6IHBhZ2UuX2dldEJvdHRvbVRvb2xiYXJFbGVtZW50KClcbiAgICB9O1xuICB9XG5cbiAgX3Nob3VsZEFuaW1hdGVUb29sYmFyKGVudGVyUGFnZSwgbGVhdmVQYWdlKSB7XG4gICAgY29uc3QgdG9vbGJhcnMgPSBlbnRlclBhZ2UuX2NhbkFuaW1hdGVUb29sYmFyKCkgJiYgbGVhdmVQYWdlLl9jYW5BbmltYXRlVG9vbGJhcigpO1xuXG4gICAgY29uc3QgZW50ZXJUb29sYmFyID0gZW50ZXJQYWdlLl9nZXRUb29sYmFyRWxlbWVudCgpO1xuICAgIGNvbnN0IGxlYXZlVG9vbGJhciA9IGxlYXZlUGFnZS5fZ2V0VG9vbGJhckVsZW1lbnQoKTtcblxuICAgIGNvbnN0IGlzU3RhdGljID0gZW50ZXJUb29sYmFyLmhhc0F0dHJpYnV0ZSgnc3RhdGljJykgfHwgbGVhdmVUb29sYmFyLmhhc0F0dHJpYnV0ZSgnc3RhdGljJyk7XG4gICAgY29uc3QgaXNNYXRlcmlhbCA9IHV0aWwuaGFzTW9kaWZpZXIoZW50ZXJUb29sYmFyLCAnbWF0ZXJpYWwnKSB8fCB1dGlsLmhhc01vZGlmaWVyKGxlYXZlVG9vbGJhciwgJ21hdGVyaWFsJyk7XG4gICAgY29uc3QgaXNUcmFuc3BhcmVudCA9IHV0aWwuaGFzTW9kaWZpZXIoZW50ZXJUb29sYmFyLCAndHJhbnNwYXJlbnQnKSB8fCB1dGlsLmhhc01vZGlmaWVyKGxlYXZlVG9vbGJhciwgJ3RyYW5zcGFyZW50Jyk7XG5cbiAgICByZXR1cm4gdG9vbGJhcnMgJiYgIWlzU3RhdGljICYmICFpc01hdGVyaWFsICYmICFpc1RyYW5zcGFyZW50O1xuICB9XG5cbiAgX2NhbGN1bGF0ZURlbHRhKGVsZW1lbnQsIGRlY29tcG9zaXRpb24pIHtcbiAgICBsZXQgdGl0bGUsIGxhYmVsO1xuXG4gICAgY29uc3QgcGFnZVJlY3QgPSBlbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIGlmIChkZWNvbXBvc2l0aW9uLmJhY2tCdXR0b25MYWJlbC5jbGFzc0xpc3QuY29udGFpbnMoJ2JhY2stYnV0dG9uX19sYWJlbCcpKSB7XG4gICAgICBjb25zdCBsYWJlbFJlY3QgPSBkZWNvbXBvc2l0aW9uLmJhY2tCdXR0b25MYWJlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIHRpdGxlID0gTWF0aC5yb3VuZChwYWdlUmVjdC53aWR0aCAvIDIgLSBsYWJlbFJlY3Qud2lkdGggLyAyIC0gbGFiZWxSZWN0LmxlZnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aXRsZSA9IE1hdGgucm91bmQoKHBhZ2VSZWN0LndpZHRoIC8gMikgKiAwLjYpO1xuICAgIH1cblxuICAgIGlmIChkZWNvbXBvc2l0aW9uLmJhY2tCdXR0b25JY29uLmNsYXNzTGlzdC5jb250YWlucygnYmFjay1idXR0b25fX2ljb24nKSkge1xuICAgICAgbGFiZWwgPSBkZWNvbXBvc2l0aW9uLmJhY2tCdXR0b25JY29uLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnJpZ2h0IC0gMjtcbiAgICB9XG5cbiAgICByZXR1cm4ge3RpdGxlLCBsYWJlbH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZW50ZXJQYWdlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBsZWF2ZVBhZ2VcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHB1c2goZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgdGhpcy5iYWNrZ3JvdW5kTWFzay5yZW1vdmUoKTtcbiAgICBsZWF2ZVBhZ2UucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUodGhpcy5iYWNrZ3JvdW5kTWFzaywgbGVhdmVQYWdlKTtcblxuICAgIGNvbnN0IHVuYmxvY2sgPSBzdXBlci5ibG9jayhlbnRlclBhZ2UpO1xuXG4gICAgY29udGVudFJlYWR5KGVudGVyUGFnZSwgKCkgPT4ge1xuICAgICAgY29uc3QgZW50ZXJQYWdlVGFyZ2V0ID0gdXRpbC5maW5kVG9vbGJhclBhZ2UoZW50ZXJQYWdlKSB8fCBlbnRlclBhZ2U7XG4gICAgICBjb25zdCBsZWF2ZVBhZ2VUYXJnZXQgPSB1dGlsLmZpbmRUb29sYmFyUGFnZShsZWF2ZVBhZ2UpIHx8IGxlYXZlUGFnZTtcbiAgICAgIGNvbnN0IGVudGVyUGFnZURlY29tcG9zaXRpb24gPSB0aGlzLl9kZWNvbXBvc2UoZW50ZXJQYWdlVGFyZ2V0KTtcbiAgICAgIGNvbnN0IGxlYXZlUGFnZURlY29tcG9zaXRpb24gPSB0aGlzLl9kZWNvbXBvc2UobGVhdmVQYWdlVGFyZ2V0KTtcblxuICAgICAgY29uc3QgZGVsdGEgPSB0aGlzLl9jYWxjdWxhdGVEZWx0YShsZWF2ZVBhZ2UsIGVudGVyUGFnZURlY29tcG9zaXRpb24pO1xuXG4gICAgICBjb25zdCBzaG91bGRBbmltYXRlVG9vbGJhciA9IHRoaXMuX3Nob3VsZEFuaW1hdGVUb29sYmFyKGVudGVyUGFnZVRhcmdldCwgbGVhdmVQYWdlVGFyZ2V0KTtcblxuICAgICAgaWYgKHNob3VsZEFuaW1hdGVUb29sYmFyKSB7XG5cbiAgICAgICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgICAgIGFuaW1pdChbZW50ZXJQYWdlRGVjb21wb3NpdGlvbi5jb250ZW50LCBlbnRlclBhZ2VEZWNvbXBvc2l0aW9uLmJvdHRvbVRvb2xiYXIsIGVudGVyUGFnZURlY29tcG9zaXRpb24uYmFja2dyb3VuZF0sIHRoaXMuZGVmKVxuICAgICAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgICAgIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgnMTAwJScpIH0sXG4gICAgICAgICAgICAgIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgpIH1cbiAgICAgICAgICAgICksXG5cbiAgICAgICAgICBhbmltaXQoZW50ZXJQYWdlRGVjb21wb3NpdGlvbi50b29sYmFyLCB0aGlzLmRlZilcbiAgICAgICAgICAgIC5kZWZhdWx0KHsgb3BhY2l0eTogMCB9LCB7IG9wYWNpdHk6IDEgfSksXG5cbiAgICAgICAgICBhbmltaXQoZW50ZXJQYWdlRGVjb21wb3NpdGlvbi50b29sYmFyQ2VudGVyLCB0aGlzLmRlZilcbiAgICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoJzEyNSUnKSwgb3BhY2l0eTogMSB9LFxuICAgICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoKSwgb3BhY2l0eTogMSB9XG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgYW5pbWl0KGVudGVyUGFnZURlY29tcG9zaXRpb24uYmFja0J1dHRvbkxhYmVsLCB0aGlzLmRlZilcbiAgICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoYCR7ZGVsdGEudGl0bGV9cHhgKSwgb3BhY2l0eTogMCB9LFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgpLFxuICAgICAgICAgICAgICAgIG9wYWNpdHk6IDEsXG4gICAgICAgICAgICAgICAgdHJhbnNpdGlvbjogYG9wYWNpdHkgJHt0aGlzLmR1cmF0aW9ufXMgbGluZWFyLCB0cmFuc2Zvcm0gJHt0aGlzLmR1cmF0aW9ufXMgJHt0aGlzLnRpbWluZ31gXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICksXG5cbiAgICAgICAgICBhbmltaXQoZW50ZXJQYWdlRGVjb21wb3NpdGlvbi5vdGhlciwgdGhpcy5kZWYpXG4gICAgICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICAgICAgeyBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgICAgIHsgY3NzOiB7IG9wYWNpdHk6IDEgfSwgdGltaW5nOiAnbGluZWFyJyB9XG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgYW5pbWl0KFtsZWF2ZVBhZ2VEZWNvbXBvc2l0aW9uLmNvbnRlbnQsIGxlYXZlUGFnZURlY29tcG9zaXRpb24uYm90dG9tVG9vbGJhciwgbGVhdmVQYWdlRGVjb21wb3NpdGlvbi5iYWNrZ3JvdW5kXSwgdGhpcy5kZWYpXG4gICAgICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICAgICAgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKCksIG9wYWNpdHk6IDEgfSxcbiAgICAgICAgICAgICAgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKCctMjUlJyksIG9wYWNpdHk6IDAuOSB9XG4gICAgICAgICAgICApXG4gICAgICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgICAgIHVuYmxvY2soKTtcbiAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgICAgfSksXG5cbiAgICAgICAgICBhbmltaXQobGVhdmVQYWdlRGVjb21wb3NpdGlvbi50b29sYmFyQ2VudGVyLCB0aGlzLmRlZilcbiAgICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoKSwgb3BhY2l0eTogMSB9LFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZChgLSR7ZGVsdGEudGl0bGV9cHhgKSxcbiAgICAgICAgICAgICAgICBvcGFjaXR5OiAwLFxuICAgICAgICAgICAgICAgIHRyYW5zaXRpb246IGBvcGFjaXR5ICR7dGhpcy5kdXJhdGlvbn1zIGxpbmVhciwgdHJhbnNmb3JtICR7dGhpcy5kdXJhdGlvbn1zICR7dGhpcy50aW1pbmd9YFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgYW5pbWl0KGxlYXZlUGFnZURlY29tcG9zaXRpb24uYmFja0J1dHRvbkxhYmVsLCB0aGlzLmRlZilcbiAgICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoKSwgb3BhY2l0eTogMSB9LFxuICAgICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoYC0ke2RlbHRhLmxhYmVsfXB4YCksIG9wYWNpdHk6IDAgfVxuICAgICAgICAgICAgKSxcblxuICAgICAgICAgIGFuaW1pdChsZWF2ZVBhZ2VEZWNvbXBvc2l0aW9uLm90aGVyLCB0aGlzLmRlZilcbiAgICAgICAgICAgIC5kZWZhdWx0KCB7IG9wYWNpdHk6IDEgfSwgeyBjc3M6IHsgb3BhY2l0eTogMCB9LCB0aW1pbmc6ICdsaW5lYXInIH0pXG5cbiAgICAgICAgKTtcblxuICAgICAgfSBlbHNlIHtcblxuICAgICAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICAgICAgYW5pbWl0KGVudGVyUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgICAgICAuZGVmYXVsdCggeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKCcxMDAlJyksIH0sIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgpIH0pLFxuXG4gICAgICAgICAgYW5pbWl0KGxlYXZlUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgICAgICAuZGVmYXVsdCggeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKCksIG9wYWNpdHk6IDEgfSwgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKCctMjUlJyksIG9wYWNpdHk6IC45IH0pXG4gICAgICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgICAgIHVuYmxvY2soKTtcbiAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcblxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcG9wKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLmlzU3dpcGluZykge1xuICAgICAgcmV0dXJuIHRoaXMucG9wU3dpcGUoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgIGVudGVyUGFnZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh0aGlzLmJhY2tncm91bmRNYXNrLCBlbnRlclBhZ2UpO1xuXG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBjb25zdCBlbnRlclBhZ2VUYXJnZXQgPSB1dGlsLmZpbmRUb29sYmFyUGFnZShlbnRlclBhZ2UpIHx8IGVudGVyUGFnZTtcbiAgICBjb25zdCBsZWF2ZVBhZ2VUYXJnZXQgPSB1dGlsLmZpbmRUb29sYmFyUGFnZShsZWF2ZVBhZ2UpIHx8IGxlYXZlUGFnZTtcbiAgICBjb25zdCBlbnRlclBhZ2VEZWNvbXBvc2l0aW9uID0gdGhpcy5fZGVjb21wb3NlKGVudGVyUGFnZVRhcmdldCk7XG4gICAgY29uc3QgbGVhdmVQYWdlRGVjb21wb3NpdGlvbiA9IHRoaXMuX2RlY29tcG9zZShsZWF2ZVBhZ2VUYXJnZXQpO1xuXG4gICAgY29uc3QgZGVsdGEgPSB0aGlzLl9jYWxjdWxhdGVEZWx0YShsZWF2ZVBhZ2UsIGxlYXZlUGFnZURlY29tcG9zaXRpb24pO1xuXG4gICAgY29uc3Qgc2hvdWxkQW5pbWF0ZVRvb2xiYXIgPSB0aGlzLl9zaG91bGRBbmltYXRlVG9vbGJhcihlbnRlclBhZ2VUYXJnZXQsIGxlYXZlUGFnZVRhcmdldCk7XG5cbiAgICBpZiAoc2hvdWxkQW5pbWF0ZVRvb2xiYXIpIHtcbiAgICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgICAgYW5pbWl0KFtlbnRlclBhZ2VEZWNvbXBvc2l0aW9uLmNvbnRlbnQsIGVudGVyUGFnZURlY29tcG9zaXRpb24uYm90dG9tVG9vbGJhciwgZW50ZXJQYWdlRGVjb21wb3NpdGlvbi5iYWNrZ3JvdW5kXSwgdGhpcy5kZWYpXG4gICAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoJy0yNSUnKSwgb3BhY2l0eTogLjkgfSxcbiAgICAgICAgICAgIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgpLCBvcGFjaXR5OiAxIH1cbiAgICAgICAgICApLFxuXG4gICAgICAgIGFuaW1pdChlbnRlclBhZ2VEZWNvbXBvc2l0aW9uLnRvb2xiYXJDZW50ZXIsIHRoaXMuZGVmKVxuICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKGAtJHtkZWx0YS50aXRsZX1weGApLCBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoKSxcbiAgICAgICAgICAgICAgb3BhY2l0eTogMSxcbiAgICAgICAgICAgICAgdHJhbnNpdGlvbjogYG9wYWNpdHkgJHt0aGlzLmR1cmF0aW9ufXMgbGluZWFyLCB0cmFuc2Zvcm0gJHt0aGlzLmR1cmF0aW9ufXMgJHt0aGlzLnRpbWluZ31gXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKSxcblxuICAgICAgICBhbmltaXQoZW50ZXJQYWdlRGVjb21wb3NpdGlvbi5iYWNrQnV0dG9uTGFiZWwsIHRoaXMuZGVmKVxuICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKGAtJHtkZWx0YS5sYWJlbH1weGApIH0sXG4gICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoKSB9XG4gICAgICAgICAgKSxcblxuICAgICAgICBhbmltaXQoZW50ZXJQYWdlRGVjb21wb3NpdGlvbi5vdGhlciwgdGhpcy5kZWYpXG4gICAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgICB7IG9wYWNpdHk6IDAgfSxcbiAgICAgICAgICAgIHsgY3NzOiB7IG9wYWNpdHk6IDEgfSwgdGltaW5nOiAnbGluZWFyJyB9XG4gICAgICAgICAgKSxcblxuICAgICAgICBhbmltaXQoW2xlYXZlUGFnZURlY29tcG9zaXRpb24uY29udGVudCwgbGVhdmVQYWdlRGVjb21wb3NpdGlvbi5ib3R0b21Ub29sYmFyLCBsZWF2ZVBhZ2VEZWNvbXBvc2l0aW9uLmJhY2tncm91bmRdLCB0aGlzLmRlZilcbiAgICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICAgIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgpIH0sXG4gICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoJzEwMCUnKSB9XG4gICAgICAgICAgKVxuICAgICAgICAgIC53YWl0KDApXG4gICAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgICAgdGhpcy5iYWNrZ3JvdW5kTWFzay5yZW1vdmUoKTtcbiAgICAgICAgICAgIHVuYmxvY2soKTtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICBkb25lKCk7XG4gICAgICAgICAgfSksXG5cbiAgICAgICAgYW5pbWl0KGxlYXZlUGFnZURlY29tcG9zaXRpb24udG9vbGJhciwgdGhpcy5kZWYpXG4gICAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgICB7IG9wYWNpdHk6IDEgfSxcbiAgICAgICAgICAgIHsgb3BhY2l0eTogMCB9XG4gICAgICAgICAgKSxcblxuICAgICAgICBhbmltaXQobGVhdmVQYWdlRGVjb21wb3NpdGlvbi50b29sYmFyQ2VudGVyLCB0aGlzLmRlZilcbiAgICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICAgIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgpIH0sXG4gICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoJzEyNSUnKSB9XG4gICAgICAgICAgKSxcblxuICAgICAgICBhbmltaXQobGVhdmVQYWdlRGVjb21wb3NpdGlvbi5iYWNrQnV0dG9uTGFiZWwsIHRoaXMuZGVmKVxuICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKCksIG9wYWNpdHk6IDEgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZChgJHtkZWx0YS50aXRsZX1weGApLFxuICAgICAgICAgICAgICBvcGFjaXR5OiAwLFxuICAgICAgICAgICAgICB0cmFuc2l0aW9uOiBgb3BhY2l0eSAke3RoaXMuZHVyYXRpb259cyBsaW5lYXIsIHRyYW5zZm9ybSAke3RoaXMuZHVyYXRpb259cyAke3RoaXMudGltaW5nfWBcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICAgIGFuaW1pdChlbnRlclBhZ2UsIHRoaXMuZGVmKVxuICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKCctMjUlJyksIG9wYWNpdHk6IC45IH0sXG4gICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoKSwgb3BhY2l0eTogMSB9XG4gICAgICAgICAgKSxcblxuICAgICAgICBhbmltaXQobGVhdmVQYWdlLCB0aGlzLmRlZilcbiAgICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICAgIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgpIH0sXG4gICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoJzEwMCUnKSB9XG4gICAgICAgICAgKVxuICAgICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgICB1bmJsb2NrKCk7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IE5hdmlnYXRvckFuaW1hdG9yIGZyb20gJy4vYW5pbWF0b3InO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi8uLi9vbnMvYW5pbWl0JztcblxuLyoqXG4gKiBMaWZ0IHNjcmVlbiB0cmFuc2l0aW9uLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJT1NMaWZ0TmF2aWdhdG9yQW5pbWF0b3IgZXh0ZW5kcyBOYXZpZ2F0b3JBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdjdWJpYy1iZXppZXIoLjEsIC43LCAuMSwgMSknLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC40fSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcblxuICAgIHRoaXMuYmFja2dyb3VuZE1hc2sgPSB1dGlsLmNyZWF0ZUVsZW1lbnQoXG4gICAgICAnPGRpdiBzdHlsZT1cInBvc2l0aW9uOiBhYnNvbHV0ZTsgd2lkdGg6IDEwMCU7IGhlaWdodDogMTAwJTsnICtcbiAgICAgICAgJ2JhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudChibGFjaywgd2hpdGUpO1wiPjwvZGl2PidcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcHVzaChlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcbiAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgIGxlYXZlUGFnZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh0aGlzLmJhY2tncm91bmRNYXNrLCBsZWF2ZVBhZ2UpO1xuXG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZW50ZXJQYWdlLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAxMDAlLCAwKScgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDAsIDApJyB9XG4gICAgICAgICksXG5cbiAgICAgIGFuaW1pdChsZWF2ZVBhZ2UsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDAsIDApJywgb3BhY2l0eTogMSB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgLTEwJSwgMCknLCBvcGFjaXR5OiAuOSB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgdW5ibG9jaygpO1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGVudGVyUGFnZVxuICAgKiBAcGFyYW0ge09iamVjdH0gbGVhdmVQYWdlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBwb3AoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgdGhpcy5iYWNrZ3JvdW5kTWFzay5yZW1vdmUoKTtcbiAgICBlbnRlclBhZ2UucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUodGhpcy5iYWNrZ3JvdW5kTWFzaywgZW50ZXJQYWdlKTtcblxuICAgIGNvbnN0IHVuYmxvY2sgPSBzdXBlci5ibG9jayhlbnRlclBhZ2UpO1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KGVudGVyUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgLTQzcHgsIDApJywgb3BhY2l0eTogLjkgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDAsIDApJywgb3BhY2l0eTogMSB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgdW5ibG9jaygpO1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KGxlYXZlUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMCwgMCknIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAxMDAlLCAwKScgfVxuICAgICAgICApXG4gICAgKTtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IE5hdmlnYXRvckFuaW1hdG9yIGZyb20gJy4vYW5pbWF0b3InO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi8uLi9vbnMvYW5pbWl0JztcblxuY29uc3QgdHJhbnNmb3JtID0gJ3RyYW5zbGF0ZTNkKDAsIDAsIDApJztcblxuLyoqXG4gKiBGYWRlLWluIHNjcmVlbiB0cmFuc2l0aW9uLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJT1NGYWRlTmF2aWdhdG9yQW5pbWF0b3IgZXh0ZW5kcyBOYXZpZ2F0b3JBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdsaW5lYXInLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC40fSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZW50ZXJQYWdlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBsZWF2ZVBhZ2VcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHB1c2goZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZW50ZXJQYWdlLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm0sIG9wYWNpdHk6IDAgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybSwgb3BhY2l0eTogMSB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHVuYmxvY2soKTtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSksXG4gICAgKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBwb3AoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQobGVhdmVQYWdlLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm0sIG9wYWNpdHk6IDEgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybSwgb3BhY2l0eTogMCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHVuYmxvY2soKTtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgTmF2aWdhdG9yQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuXG4vKipcbiAqIFNsaWRlIGFuaW1hdG9yIGZvciBuYXZpZ2F0b3IgdHJhbnNpdGlvbi5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTURTbGlkZU5hdmlnYXRvckFuaW1hdG9yIGV4dGVuZHMgTmF2aWdhdG9yQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnY3ViaWMtYmV6aWVyKC4xLCAuNywgLjQsIDEpJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuM30gPSB7fSkge1xuICAgIHN1cGVyKHt0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbn0pO1xuXG4gICAgdGhpcy5ibGFja01hc2tPcGFjaXR5ID0gMC40O1xuICAgIHRoaXMuYmFja2dyb3VuZE1hc2sgPSB1dGlsLmNyZWF0ZUVsZW1lbnQoXG4gICAgICAnPGRpdiBzdHlsZT1cInBvc2l0aW9uOiBhYnNvbHV0ZTsgd2lkdGg6IDEwMCU7IGhlaWdodDogMTAwJTsgei1pbmRleDogMjsnICtcbiAgICAgICAgJ2JhY2tncm91bmQtY29sb3I6IGJsYWNrOyBvcGFjaXR5OiAwO1wiPjwvZGl2PidcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcHVzaChlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcbiAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgIGxlYXZlUGFnZS5wYXJlbnRFbGVtZW50Lmluc2VydEJlZm9yZSh0aGlzLmJhY2tncm91bmRNYXNrLCBsZWF2ZVBhZ2UubmV4dFNpYmxpbmcpO1xuXG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQodGhpcy5iYWNrZ3JvdW5kTWFzaywgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknLCBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgeyBvcGFjaXR5OiB0aGlzLmJsYWNrTWFza09wYWNpdHkgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSksXG5cbiAgICAgIGFuaW1pdChlbnRlclBhZ2UsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDEwMCUsIDAsIDApJyB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknIH1cbiAgICAgICAgKSxcblxuICAgICAgYW5pbWl0KGxlYXZlUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNDUlLCAwLCAwKScgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICB1bmJsb2NrKCk7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZW50ZXJQYWdlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBsZWF2ZVBhZ2VcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHBvcChlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcbiAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgIGVudGVyUGFnZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh0aGlzLmJhY2tncm91bmRNYXNrLCBlbnRlclBhZ2UubmV4dFNpYmxpbmcpO1xuXG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQodGhpcy5iYWNrZ3JvdW5kTWFzaywgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknLCBvcGFjaXR5OiB0aGlzLmJsYWNrTWFza09wYWNpdHkgfSxcbiAgICAgICAgICB7IG9wYWNpdHk6IDAgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSksXG5cbiAgICAgIGFuaW1pdChlbnRlclBhZ2UsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC00NSUsIDAsIDApJywgb3BhY2l0eTogLjkgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDAsIDApJywgb3BhY2l0eTogMSB9XG4gICAgICAgICksXG5cbiAgICAgIGFuaW1pdChsZWF2ZVBhZ2UsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDAsIDApJyB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMTAwJSwgMCwgMCknIH1cbiAgICAgICAgKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgdW5ibG9jaygpO1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBOYXZpZ2F0b3JBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBhbmltaXQgZnJvbSAnLi4vLi4vb25zL2FuaW1pdCc7XG5cbi8qKlxuICogTGlmdCBzY3JlZW4gdHJhbnNpdGlvbi5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTURMaWZ0TmF2aWdhdG9yQW5pbWF0b3IgZXh0ZW5kcyBOYXZpZ2F0b3JBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdjdWJpYy1iZXppZXIoLjEsIC43LCAuMSwgMSknLCBkZWxheSA9IDAuMDUsIGR1cmF0aW9uID0gMC40fSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcblxuICAgIHRoaXMuYmFja2dyb3VuZE1hc2sgPSB1dGlsLmNyZWF0ZUVsZW1lbnQoXG4gICAgICAnPGRpdiBzdHlsZT1cInBvc2l0aW9uOiBhYnNvbHV0ZTsgd2lkdGg6IDEwMCU7IGhlaWdodDogMTAwJTsnICtcbiAgICAgICAgJ2JhY2tncm91bmQtY29sb3I6IGJsYWNrO1wiPjwvZGl2PidcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcHVzaChlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcbiAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgIGxlYXZlUGFnZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh0aGlzLmJhY2tncm91bmRNYXNrLCBsZWF2ZVBhZ2UpO1xuXG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBjb25zdCBtYXNrQ2xlYXIgPSBhbmltaXQodGhpcy5iYWNrZ3JvdW5kTWFzaylcbiAgICAgIC53YWl0KHRoaXMuZGVsYXkgKyB0aGlzLmR1cmF0aW9uKVxuICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgICAgICBkb25lKCk7XG4gICAgICB9KTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIG1hc2tDbGVhcixcblxuICAgICAgYW5pbWl0KGVudGVyUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMTAwJSwgMCknIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKScgfVxuICAgICAgICApLFxuXG4gICAgICBhbmltaXQobGVhdmVQYWdlLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAxIH0sIHsgb3BhY2l0eTogLjQgfSlcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHVuYmxvY2soKTtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcG9wKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBjYWxsYmFjaykge1xuICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgZW50ZXJQYWdlLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHRoaXMuYmFja2dyb3VuZE1hc2ssIGVudGVyUGFnZSk7XG5cbiAgICBjb25zdCB1bmJsb2NrID0gc3VwZXIuYmxvY2soZW50ZXJQYWdlKTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdCh0aGlzLmJhY2tncm91bmRNYXNrKVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5ICsgdGhpcy5kdXJhdGlvbilcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KGVudGVyUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KHsgb3BhY2l0eTogLjQgfSwgeyBvcGFjaXR5OiAxIH0pXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICB1bmJsb2NrKCk7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQobGVhdmVQYWdlLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKScgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDEwMCUsIDApJyB9XG4gICAgICAgIClcbiAgICApO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgTmF2aWdhdG9yQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuXG4vKipcbiAqIEZhZGUtaW4gKyBMaWZ0IHNjcmVlbiB0cmFuc2l0aW9uLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNREZhZGVOYXZpZ2F0b3JBbmltYXRvciBleHRlbmRzIE5hdmlnYXRvckFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7dGltaW5nID0gJ2N1YmljLWJlemllcigwLjQsIDAsIDAuMiwgMSknLCB0aW1pbmdQb3AgPSAnY3ViaWMtYmV6aWVyKDAuNCwgMCwgMSwgMSknLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC4yfSA9IHt9KSB7XG4gICAgc3VwZXIoe3RpbWluZywgZGVsYXksIGR1cmF0aW9ufSk7XG4gICAgdGhpcy50aW1pbmdQb3AgPSB0aW1pbmdQb3A7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGVudGVyUGFnZVxuICAgKiBAcGFyYW0ge09iamVjdH0gbGVhdmVQYWdlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBwdXNoKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBjYWxsYmFjaykge1xuICAgIGNvbnN0IHVuYmxvY2sgPSBzdXBlci5ibG9jayhlbnRlclBhZ2UpO1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KGVudGVyUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgNDJweCwgMCknLCBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAwLCAwKScsIG9wYWNpdHk6IDEgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICB1bmJsb2NrKCk7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBwb3AoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQobGVhdmVQYWdlLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAwLCAwKScsIG9wYWNpdHk6IDEgfSxcbiAgICAgICAgICB7IGNzczogeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAzOHB4LCAwKScsIG9wYWNpdHk6IDAgfSwgdGltaW5nOiB0aGlzLnRpbWluZ1BvcCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHVuYmxvY2soKTtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgTmF2aWdhdG9yQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE5vbmVOYXZpZ2F0b3JBbmltYXRvciBleHRlbmRzIE5hdmlnYXRvckFuaW1hdG9yIHtcbiAgY29uc3RydWN0b3Iob3B0aW9ucykge1xuICAgIHN1cGVyKG9wdGlvbnMpO1xuICB9XG4gIHB1c2goZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIHBvcChlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjaygpO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBpbnRlcm5hbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwnO1xuaW1wb3J0IFN3aXBlUmV2ZWFsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9zd2lwZS1yZXZlYWwnO1xuaW1wb3J0IEFuaW1hdG9yRmFjdG9yeSBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvYW5pbWF0b3ItZmFjdG9yeSc7XG5pbXBvcnQgTmF2aWdhdG9yQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgSU9TU2xpZGVOYXZpZ2F0b3JBbmltYXRvciBmcm9tICcuL2lvcy1zbGlkZS1hbmltYXRvcic7XG5pbXBvcnQgSU9TTGlmdE5hdmlnYXRvckFuaW1hdG9yIGZyb20gJy4vaW9zLWxpZnQtYW5pbWF0b3InO1xuaW1wb3J0IElPU0ZhZGVOYXZpZ2F0b3JBbmltYXRvciBmcm9tICcuL2lvcy1mYWRlLWFuaW1hdG9yJztcbmltcG9ydCBNRFNsaWRlTmF2aWdhdG9yQW5pbWF0b3IgZnJvbSAnLi9tZC1zbGlkZS1hbmltYXRvcic7XG5pbXBvcnQgTURMaWZ0TmF2aWdhdG9yQW5pbWF0b3IgZnJvbSAnLi9tZC1saWZ0LWFuaW1hdG9yJztcbmltcG9ydCBNREZhZGVOYXZpZ2F0b3JBbmltYXRvciBmcm9tICcuL21kLWZhZGUtYW5pbWF0b3InO1xuaW1wb3J0IE5vbmVOYXZpZ2F0b3JBbmltYXRvciBmcm9tICcuL25vbmUtYW5pbWF0b3InO1xuaW1wb3J0IHBsYXRmb3JtIGZyb20gJy4uLy4uL29ucy9wbGF0Zm9ybSc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL2RldmljZS1iYWNrLWJ1dHRvbi1kaXNwYXRjaGVyJztcbmltcG9ydCB7UGFnZUxvYWRlciwgZGVmYXVsdFBhZ2VMb2FkZXIsIGluc3RhbnRQYWdlTG9hZGVyfSBmcm9tICcuLi8uLi9vbnMvcGFnZS1sb2FkZXInO1xuXG5jb25zdCBfYW5pbWF0b3JEaWN0ID0ge1xuICAnZGVmYXVsdCc6ICgpID0+IHBsYXRmb3JtLmlzQW5kcm9pZCgpID8gTURGYWRlTmF2aWdhdG9yQW5pbWF0b3IgOiBJT1NTbGlkZU5hdmlnYXRvckFuaW1hdG9yLFxuICAnc2xpZGUnOiAoKSA9PiBwbGF0Zm9ybS5pc0FuZHJvaWQoKSA/IE1EU2xpZGVOYXZpZ2F0b3JBbmltYXRvciA6IElPU1NsaWRlTmF2aWdhdG9yQW5pbWF0b3IsXG4gICdsaWZ0JzogKCkgPT4gcGxhdGZvcm0uaXNBbmRyb2lkKCkgPyBNRExpZnROYXZpZ2F0b3JBbmltYXRvciA6IElPU0xpZnROYXZpZ2F0b3JBbmltYXRvcixcbiAgJ2ZhZGUnOiAoKSA9PiBwbGF0Zm9ybS5pc0FuZHJvaWQoKSA/IE1ERmFkZU5hdmlnYXRvckFuaW1hdG9yIDogSU9TRmFkZU5hdmlnYXRvckFuaW1hdG9yLFxuICAnc2xpZGUtaW9zJzogSU9TU2xpZGVOYXZpZ2F0b3JBbmltYXRvcixcbiAgJ3NsaWRlLW1kJzogTURTbGlkZU5hdmlnYXRvckFuaW1hdG9yLFxuICAnbGlmdC1pb3MnOiBJT1NMaWZ0TmF2aWdhdG9yQW5pbWF0b3IsXG4gICdsaWZ0LW1kJzogTURMaWZ0TmF2aWdhdG9yQW5pbWF0b3IsXG4gICdmYWRlLWlvcyc6IElPU0ZhZGVOYXZpZ2F0b3JBbmltYXRvcixcbiAgJ2ZhZGUtbWQnOiBNREZhZGVOYXZpZ2F0b3JBbmltYXRvcixcbiAgJ25vbmUnOiBOb25lTmF2aWdhdG9yQW5pbWF0b3Jcbn07XG5cbmNvbnN0IHJld3JpdGFibGVzID0ge1xuICAvKipcbiAgICogQHBhcmFtIHtFbGVtZW50fSBuYXZpZ2F0b3JTaWRlRWxlbWVudFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcmVhZHkobmF2aWdhdG9yRWxlbWVudCwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjaygpO1xuICB9XG59O1xuXG5jb25zdCB2ZXJpZnlQYWdlRWxlbWVudCA9IGVsID0+IChlbC5ub2RlTmFtZSAhPT0gJ09OUy1QQUdFJykgJiYgdXRpbC50aHJvdyggJ09ubHkgcGFnZSBlbGVtZW50cyBjYW4gYmUgY2hpbGRyZW4gb2YgbmF2aWdhdG9yJyk7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLW5hdmlnYXRvclxuICogQGNhdGVnb3J5IG5hdmlnYXRpb25cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgQSBjb21wb25lbnQgdGhhdCBwcm92aWRlcyBwYWdlIHN0YWNrIG1hbmFnZW1lbnQgYW5kIG5hdmlnYXRpb24uIFN0YWNrIG5hdmlnYXRpb24gaXMgdGhlIG1vc3QgY29tbW9uIG5hdmlnYXRpb24gcGF0dGVybiBmb3IgbW9iaWxlIGFwcHMuXG4gKlxuICogICAgIFdoZW4gYSBwYWdlIGlzIHB1c2hlZCBvbiB0b3Agb2YgdGhlIHN0YWNrIGl0IGlzIGRpc3BsYXllZCB3aXRoIGEgdHJhbnNpdGlvbiBhbmltYXRpb24uIFdoZW4gdGhlIHVzZXIgcmV0dXJucyB0byB0aGUgcHJldmlvdXMgcGFnZSB0aGUgdG9wIHBhZ2Ugd2lsbCBiZSBwb3BwZWQgZnJvbSB0aGUgdG9wIG9mIHRoZSBzdGFjayBhbmQgaGlkZGVuIHdpdGggYW4gb3Bwb3NpdGUgdHJhbnNpdGlvbiBhbmltYXRpb24uXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGNvZGVwZW4geXJodHZcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9uYXZpZ2F0b3JcbiAqIEBndWlkZSBsaWZlY3ljbGUuaHRtbCNldmVudHNcbiAqICAgW2VuXU92ZXJ2aWV3IG9mIHBhZ2UgZXZlbnRzWy9lbl1cbiAqICAgW2phXU92ZXJ2aWV3IG9mIHBhZ2UgZXZlbnRzWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy10b29sYmFyXG4gKiAgIFtlbl1UaGUgYDxvbnMtdG9vbGJhcj5gIGNvbXBvbmVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSB0b29sYmFyIG9uIHRoZSB0b3Agb2YgYSBwYWdlLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLWJhY2stYnV0dG9uXG4gKiAgIFtlbl1UaGUgYDxvbnMtYmFjay1idXR0b24+YCBjb21wb25lbnQgbGV0cyB0aGUgdXNlciByZXR1cm4gdG8gdGhlIHByZXZpb3VzIHBhZ2UuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1uYXZpZ2F0b3IgaWQ9XCJuYXZpZ2F0b3JcIj5cbiAqICAgPG9ucy1wYWdlPlxuICogICAgIDxvbnMtdG9vbGJhcj5cbiAqICAgICAgIDxkaXYgY2xhc3M9XCJjZW50ZXJcIj5cbiAqICAgICAgICAgVGl0bGVcbiAqICAgICAgIDwvZGl2PlxuICogICAgIDwvb25zLXRvb2xiYXI+XG4gKiAgICAgPHA+XG4gKiAgICAgICA8b25zLWJ1dHRvblxuICogICAgICAgICBvbmNsaWNrPVwiZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ25hdmlnYXRvcicpLnB1c2hQYWdlKCdwYWdlLmh0bWwnKVwiPlxuICogICAgICAgICBQdXNoIHBhZ2VcbiAqICAgICAgIDwvb25zLWJ1dHRvbj5cbiAqICAgICA8L3A+XG4gKiAgIDwvb25zLXBhZ2U+XG4gKiA8L29ucy1uYXZpZ2F0b3I+XG4gKlxuICogPHRlbXBsYXRlIGlkPVwicGFnZS5odG1sXCI+XG4gKiAgIDxvbnMtcGFnZT5cbiAqICAgICA8b25zLXRvb2xiYXI+XG4gKiAgICAgICA8ZGl2IGNsYXNzPVwibGVmdFwiPlxuICogICAgICAgICA8b25zLWJhY2stYnV0dG9uPkJhY2s8L29ucy1iYWNrLWJ1dHRvbj5cbiAqICAgICAgIDwvZGl2PlxuICogICAgICAgPGRpdiBjbGFzcz1cImNlbnRlclwiPlxuICogICAgICAgICBBbm90aGVyIHBhZ2VcbiAqICAgICAgIDwvZGl2PlxuICogICAgIDwvb25zLXRvb2xiYXI+XG4gKiAgIDwvb25zLXBhZ2U+XG4gKiA8L3RlbXBsYXRlPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBOYXZpZ2F0b3JFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHBhZ2VcbiAgICogQGluaXRvbmx5XG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJzdCBwYWdlIHRvIHNob3cgd2hlbiBuYXZpZ2F0b3IgaXMgaW5pdGlhbGl6ZWQuWy9lbl1cbiAgICogICBbamFd44OK44OT44Ky44O844K/44O844GM5Yid5pyf5YyW44GV44KM44Gf5pmC44Gr6KGo56S644GZ44KL44Oa44O844K444KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc3dpcGVhYmxlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRW5hYmxlIGlPUyBcInN3aXBlIHRvIHBvcFwiIGZlYXR1cmUuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc3dpcGUtdGFyZ2V0LXdpZHRoXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IDIwcHhcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSB3aWR0aCBvZiBzd2lwZWFibGUgYXJlYSBjYWxjdWxhdGVkIGZyb20gdGhlIGVkZ2UgKGluIHBpeGVscykuIFVzZSB0aGlzIHRvIGVuYWJsZSBzd2lwZSBvbmx5IHdoZW4gdGhlIGZpbmdlciB0b3VjaCBvbiB0aGUgc2NyZWVuIGVkZ2UuWy9lbl1cbiAgICogICBbamFd44K544Ov44Kk44OX44Gu5Yik5a6a6aCY5Z+f44KS44OU44Kv44K744Or5Y2Y5L2N44Gn5oyH5a6a44GX44G+44GZ44CC55S76Z2i44Gu56uv44GL44KJ5oyH5a6a44GX44Gf6Led6Zui44Gr6YGU44GZ44KL44Go44Oa44O844K444GM6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc3dpcGUtdGhyZXNob2xkXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IDAuMlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IGhvdyBtdWNoIHRoZSBwYWdlIG5lZWRzIHRvIGJlIHN3aXBlZCBiZWZvcmUgcG9wcGluZy4gQSB2YWx1ZSBiZXR3ZWVuIGAwYCBhbmQgYDFgLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGRlZmF1bHRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJzbGlkZVwiYCwgYFwibGlmdFwiYCwgYFwiZmFkZVwiYCBhbmQgYFwibm9uZVwiYC5cbiAgICpcbiAgICogICAgIFRoZXNlIGFyZSBwbGF0Zm9ybSBiYXNlZCBhbmltYXRpb25zLiBGb3IgZml4ZWQgYW5pbWF0aW9ucywgYWRkIGBcIi1pb3NcImAgb3IgYFwiLW1kXCJgIHN1ZmZpeCB0byB0aGUgYW5pbWF0aW9uIG5hbWUuIEUuZy4gYFwibGlmdC1pb3NcImAsIGBcImxpZnQtbWRcImAuIERlZmF1bHRzIHZhbHVlcyBhcmUgYFwic2xpZGUtaW9zXCJgIGFuZCBgXCJmYWRlLW1kXCJgIGRlcGVuZGluZyBvbiB0aGUgcGxhdGZvcm0uXG4gICAqICAgWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uLW9wdGlvbnNcbiAgICogQHR5cGUge0V4cHJlc3Npb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCB0aW1pbmcgYW5kIGRlbGF5IHdpdGggYW4gb2JqZWN0IGxpdGVyYWwuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9YFsvZW5dXG4gICAqICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIHRpbWluZywgZGVsYXnjgpLjgqrjg5bjgrjjgqfjgq/jg4jjg6rjg4bjg6njg6vjgafmjIflrprjgZfjgb7jgZnjgIJlLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWBbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHByZXB1c2hcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYmVmb3JlIGEgcGFnZSBpcyBwdXNoZWQuWy9lbl1cbiAgICogICBbamFdcGFnZeOBjHB1c2jjgZXjgozjgovnm7TliY3jgavnmbrngavjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQubmF2aWdhdG9yXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmN1cnJlbnRQYWdlXG4gICAqICAgW2VuXUN1cnJlbnQgcGFnZSBvYmplY3QuWy9lbl1cbiAgICogICBbamFd54++5Zyo44GucGFnZeOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGV2ZW50LmNhbmNlbFxuICAgKiAgIFtlbl1DYWxsIHRoaXMgZnVuY3Rpb24gdG8gY2FuY2VsIHRoZSBwdXNoLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWRvOOBs+WHuuOBmeOBqOOAgXB1c2jlh6bnkIbjgYzjgq3jg6Pjg7Pjgrvjg6vjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHByZXBvcFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQganVzdCBiZWZvcmUgYSBwYWdlIGlzIHBvcHBlZC5bL2VuXVxuICAgKiAgIFtqYV1wYWdl44GMcG9w44GV44KM44KL55u05YmN44Gr55m654Gr44GV44KM44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50Lm5hdmlnYXRvclxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5jdXJyZW50UGFnZVxuICAgKiAgIFtlbl1DdXJyZW50IHBhZ2Ugb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBrnBhZ2Xjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC5jYW5jZWxcbiAgICogICBbZW5dQ2FsbCB0aGlzIGZ1bmN0aW9uIHRvIGNhbmNlbCB0aGUgcG9wLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWRvOOBs+WHuuOBmeOBqOOAgXBhZ2Xjga5wb3DjgYzjgq3jg6Pjg7Pjgrvjg6vjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHBvc3RwdXNoXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGFmdGVyIGEgcGFnZSBpcyBwdXNoZWQuWy9lbl1cbiAgICogICBbamFdcGFnZeOBjHB1c2jjgZXjgozjgabjgqLjg4vjg6Hjg7zjgrfjg6fjg7PjgYzntYLkuobjgZfjgabjgYvjgonnmbrngavjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQubmF2aWdhdG9yXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmVudGVyUGFnZVxuICAgKiAgIFtlbl1PYmplY3Qgb2YgdGhlIG5leHQgcGFnZS5bL2VuXVxuICAgKiAgIFtqYV1wdXNo44GV44KM44GfcGFnZeOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5sZWF2ZVBhZ2VcbiAgICogICBbZW5dT2JqZWN0IG9mIHRoZSBwcmV2aW91cyBwYWdlLlsvZW5dXG4gICAqICAgW2phXeS7peWJjeOBrnBhZ2Xjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHBvc3Rwb3BcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgYSBwYWdlIGlzIHBvcHBlZC5bL2VuXVxuICAgKiAgIFtqYV1wYWdl44GMcG9w44GV44KM44Gm44Ki44OL44Oh44O844K344On44Oz44GM57WC44KP44Gj44Gf5b6M44Gr55m654Gr44GV44KM44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50Lm5hdmlnYXRvclxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5lbnRlclBhZ2VcbiAgICogICBbZW5dT2JqZWN0IG9mIHRoZSBuZXh0IHBhZ2UuWy9lbl1cbiAgICogICBbamFdcG9w44GV44KM44Gm6KGo56S644GV44KM44KL44Oa44O844K444Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmxlYXZlUGFnZVxuICAgKiAgIFtlbl1PYmplY3Qgb2YgdGhlIHByZXZpb3VzIHBhZ2UuWy9lbl1cbiAgICogICBbamFdcG9w44GV44KM44Gm5raI44GI44KL44Oa44O844K444Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICovXG5cbiAgZ2V0IGFuaW1hdG9yRmFjdG9yeSgpIHtcbiAgICByZXR1cm4gdGhpcy5fYW5pbWF0b3JGYWN0b3J5O1xuICB9XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX2lzUnVubmluZyA9IGZhbHNlO1xuICAgIHRoaXMuX2luaXRpYWxpemVkID0gZmFsc2U7XG4gICAgdGhpcy5fcGFnZUxvYWRlciA9IGRlZmF1bHRQYWdlTG9hZGVyO1xuICAgIHRoaXMuX3BhZ2VNYXAgPSBuZXcgV2Vha01hcCgpO1xuXG4gICAgdGhpcy5fdXBkYXRlQW5pbWF0b3JGYWN0b3J5KCk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHBhZ2VMb2FkZXJcbiAgICogQHR5cGUge1BhZ2VMb2FkZXJ9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1QYWdlTG9hZGVyIGluc3RhbmNlLiBJdCBjYW4gYmUgb3ZlcnJpZGVuIHRvIGNoYW5nZSB0aGUgd2F5IHBhZ2VzIGFyZSBsb2FkZWQgYnkgdGhpcyBlbGVtZW50LiBVc2VmdWwgZm9yIGxpYiBkZXZlbG9wZXJzLlsvZW5dXG4gICAqICAgW2phXVBhZ2VMb2FkZXLjgqTjg7Pjgrnjgr/jg7PjgrnjgpLmoLzntI3jgZfjgabjgYTjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZ2V0IHBhZ2VMb2FkZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BhZ2VMb2FkZXI7XG4gIH1cblxuICBzZXQgcGFnZUxvYWRlcihwYWdlTG9hZGVyKSB7XG4gICAgaWYgKCEocGFnZUxvYWRlciBpbnN0YW5jZW9mIFBhZ2VMb2FkZXIpKSB7XG4gICAgICB1dGlsLnRocm93UGFnZUxvYWRlcigpO1xuICAgIH1cbiAgICB0aGlzLl9wYWdlTG9hZGVyID0gcGFnZUxvYWRlcjtcbiAgfVxuXG4gIF9nZXRQYWdlVGFyZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLl9wYWdlIHx8IHRoaXMuZ2V0QXR0cmlidXRlKCdwYWdlJyk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHBhZ2VcbiAgICogQHR5cGUgeyp9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IHRoZSBwYWdlIHRvIGJlIGxvYWRlZCBkdXJpbmcgaW5pdGlhbGl6YXRpb24uIFRoaXMgdmFsdWUgdGFrZXMgcHJlY2VkZW5jZSBvdmVyIHRoZSBgcGFnZWAgYXR0cmlidXRlLiBVc2VmdWwgZm9yIGxpYiBkZXZlbG9wZXJzLlsvZW5dXG4gICAqICAgW2phXeWIneacn+WMluaZguOBq+iqreOBv+i+vOOCgOODmuODvOOCuOOCkuaMh+WumuOBl+OBvuOBmeOAgmBwYWdlYOWxnuaAp+OBp+aMh+WumuOBl+OBn+WApOOCiOOCiuOCgmBwYWdlYOODl+ODreODkeODhuOCo+OBq+aMh+WumuOBl+OBn+WApOOCkuWEquWFiOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBnZXQgcGFnZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fcGFnZTtcbiAgfVxuXG4gIHNldCBwYWdlKHBhZ2UpIHtcbiAgICB0aGlzLl9wYWdlID0gcGFnZTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMub25EZXZpY2VCYWNrQnV0dG9uID0gdGhpcy5fb25EZXZpY2VCYWNrQnV0dG9uLmJpbmQodGhpcyk7XG5cbiAgICBpZiAoIXBsYXRmb3JtLmlzQW5kcm9pZCgpIHx8IHRoaXMuZ2V0QXR0cmlidXRlKCdzd2lwZWFibGUnKSA9PT0gJ2ZvcmNlJykge1xuICAgICAgbGV0IHN3aXBlQW5pbWF0b3I7XG5cbiAgICAgIHRoaXMuX3N3aXBlID0gbmV3IFN3aXBlUmV2ZWFsKHtcbiAgICAgICAgZWxlbWVudDogdGhpcyxcbiAgICAgICAgZ2V0VGhyZXNob2xkOiAoKSA9PiBNYXRoLm1heCgwLjIsIHBhcnNlRmxvYXQodGhpcy5nZXRBdHRyaWJ1dGUoJ3N3aXBlLXRocmVzaG9sZCcpKSB8fCAwKSxcblxuICAgICAgICBzd2lwZU1heDogKCkgPT4ge1xuICAgICAgICAgIHRoaXMuX29uU3dpcGUgJiYgdGhpcy5fb25Td2lwZSgxLCB7IGR1cmF0aW9uOiBzd2lwZUFuaW1hdG9yLmR1cmF0aW9uU3dpcGUsIHRpbWluZzogc3dpcGVBbmltYXRvci50aW1pbmdTd2lwZSB9KTtcbiAgICAgICAgICB0aGlzW3RoaXMuc3dpcGVNYXggPyAnc3dpcGVNYXgnIDogJ3BvcFBhZ2UnXSh7IGFuaW1hdG9yOiBzd2lwZUFuaW1hdG9yIH0pO1xuICAgICAgICAgIHN3aXBlQW5pbWF0b3IgPSBudWxsO1xuICAgICAgICB9LFxuICAgICAgICBzd2lwZU1pZDogKGRpc3RhbmNlLCB3aWR0aCkgPT4ge1xuICAgICAgICAgIHRoaXMuX29uU3dpcGUgJiYgdGhpcy5fb25Td2lwZShkaXN0YW5jZS93aWR0aCk7XG4gICAgICAgICAgc3dpcGVBbmltYXRvci50cmFuc2xhdGUoZGlzdGFuY2UsIHdpZHRoLCB0aGlzLnRvcFBhZ2UucHJldmlvdXNFbGVtZW50U2libGluZywgdGhpcy50b3BQYWdlKTtcbiAgICAgICAgfSxcbiAgICAgICAgc3dpcGVNaW46ICgpID0+IHtcbiAgICAgICAgICB0aGlzLl9vblN3aXBlICYmIHRoaXMuX29uU3dpcGUoMCwgeyBkdXJhdGlvbjogc3dpcGVBbmltYXRvci5kdXJhdGlvblJlc3RvcmUsIHRpbWluZzogc3dpcGVBbmltYXRvci50aW1pbmdTd2lwZSB9KTtcbiAgICAgICAgICBzd2lwZUFuaW1hdG9yLnJlc3RvcmUodGhpcy50b3BQYWdlLnByZXZpb3VzRWxlbWVudFNpYmxpbmcsIHRoaXMudG9wUGFnZSk7XG4gICAgICAgICAgc3dpcGVBbmltYXRvciA9IG51bGw7XG4gICAgICAgIH0sXG5cbiAgICAgICAgaWdub3JlU3dpcGU6IChldmVudCwgZGlzdGFuY2UpID0+IHtcbiAgICAgICAgICAvLyBCYXNpYyBjb25kaXRpb25zXG4gICAgICAgICAgaWYgKCF0aGlzLl9pc1J1bm5pbmcgJiYgdGhpcy5jaGlsZHJlbi5sZW5ndGggPiAxKSB7XG5cbiAgICAgICAgICAgIC8vIEFyZWEgb3IgZGlyZWN0aW9uYWwgaXNzdWVzXG4gICAgICAgICAgICBjb25zdCBhcmVhID0gcGFyc2VJbnQodGhpcy5nZXRBdHRyaWJ1dGUoJ3N3aXBlLXRhcmdldC13aWR0aCcpIHx8IDI1LCAxMCk7XG4gICAgICAgICAgICBpZiAoZXZlbnQuZ2VzdHVyZS5kaXJlY3Rpb24gPT09ICAncmlnaHQnICYmIGFyZWEgPiBkaXN0YW5jZSkge1xuXG4gICAgICAgICAgICAgIC8vIFN3aXBlcyBvbiBvbnMtYmFjay1idXR0b24gYW5kIGl0cyBjaGlsZHJlblxuICAgICAgICAgICAgICBjb25zdCBpc0JCID0gZWwgPT4gL29ucy1iYWNrLWJ1dHRvbi9pLnRlc3QoZWwudGFnTmFtZSk7XG4gICAgICAgICAgICAgIGlmICghaXNCQihldmVudC50YXJnZXQpICYmICF1dGlsLmZpbmRQYXJlbnQoZXZlbnQudGFyZ2V0LCBpc0JCLCBwID0+IC9vbnMtcGFnZS9pLnRlc3QocC50YWdOYW1lKSkpIHtcblxuICAgICAgICAgICAgICAgIC8vIEFuaW1hdG9yIGlzIHN3aXBlYWJsZVxuICAgICAgICAgICAgICAgIGNvbnN0IGFuaW1hdGlvbiA9ICh0aGlzLnRvcFBhZ2UucHVzaGVkT3B0aW9ucyB8fCB7fSkuYW5pbWF0aW9uIHx8IHRoaXMuYW5pbWF0b3JGYWN0b3J5Ll9hbmltYXRpb247XG4gICAgICAgICAgICAgICAgY29uc3QgQW5pbWF0b3IgPSBfYW5pbWF0b3JEaWN0W2FuaW1hdGlvbl0gaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgICAgICAgICAgICAgPyBfYW5pbWF0b3JEaWN0W2FuaW1hdGlvbl0uY2FsbCgpXG4gICAgICAgICAgICAgICAgICA6IF9hbmltYXRvckRpY3RbYW5pbWF0aW9uXTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgQW5pbWF0b3IgIT09ICd1bmRlZmluZWQnICYmIEFuaW1hdG9yLnN3aXBlYWJsZSkge1xuICAgICAgICAgICAgICAgICAgc3dpcGVBbmltYXRvciA9IG5ldyBBbmltYXRvcigpOyAvLyBQcmVwYXJlIGZvciB0aGUgc3dpcGVcbiAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gdHJ1ZTsgLy8gSWdub3JlIHN3aXBlXG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaygnc3dpcGVhYmxlJyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2luaXRpYWxpemVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5faW5pdGlhbGl6ZWQgPSB0cnVlO1xuXG4gICAgY29uc3QgZGVmZXJyZWQgPSB1dGlsLmRlZmVyKCk7XG4gICAgdGhpcy5sb2FkZWQgPSBkZWZlcnJlZC5wcm9taXNlO1xuXG4gICAgcmV3cml0YWJsZXMucmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgY29uc3Qgc2hvdyA9ICF1dGlsLmhhc0FueUNvbXBvbmVudEFzUGFyZW50KHRoaXMpO1xuICAgICAgY29uc3Qgb3B0aW9ucyA9IHsgYW5pbWF0aW9uOiAnbm9uZScsIHNob3cgfTtcblxuICAgICAgaWYgKHRoaXMucGFnZXMubGVuZ3RoID09PSAwICYmIHRoaXMuX2dldFBhZ2VUYXJnZXQoKSkge1xuICAgICAgICB0aGlzLnB1c2hQYWdlKHRoaXMuX2dldFBhZ2VUYXJnZXQoKSwgb3B0aW9ucykudGhlbigoKSA9PiBkZWZlcnJlZC5yZXNvbHZlKCkpO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLnBhZ2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnBhZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmVyaWZ5UGFnZUVsZW1lbnQodGhpcy5wYWdlc1tpXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy50b3BQYWdlKSB7XG4gICAgICAgICAgY29udGVudFJlYWR5KHRoaXMudG9wUGFnZSwgKCkgPT5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgIHNob3cgJiYgdGhpcy50b3BQYWdlLl9zaG93KCk7XG4gICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZUxhc3RQYWdlQmFja0J1dHRvbigpO1xuICAgICAgICAgICAgfSwgMClcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICAgIGlmICh0aGlzLnBhZ2VzLmxlbmd0aCA9PT0gMCAmJiB0aGlzLl9nZXRQYWdlVGFyZ2V0KCkpIHtcbiAgICAgICAgICAgIHRoaXMucHVzaFBhZ2UodGhpcy5fZ2V0UGFnZVRhcmdldCgpLCBvcHRpb25zKS50aGVuKCgpID0+IGRlZmVycmVkLnJlc29sdmUoKSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRlZmVycmVkLnJlc29sdmUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSgpIHtcbiAgICB0aGlzLl9hbmltYXRvckZhY3RvcnkgPSBuZXcgQW5pbWF0b3JGYWN0b3J5KHtcbiAgICAgIGFuaW1hdG9yczogX2FuaW1hdG9yRGljdCxcbiAgICAgIGJhc2VDbGFzczogTmF2aWdhdG9yQW5pbWF0b3IsXG4gICAgICBiYXNlQ2xhc3NOYW1lOiAnTmF2aWdhdG9yQW5pbWF0b3InLFxuICAgICAgZGVmYXVsdEFuaW1hdGlvbjogdGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpXG4gICAgfSk7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlci5kZXN0cm95KCk7XG4gICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIgPSBudWxsO1xuXG4gICAgdGhpcy5fc3dpcGUgJiYgdGhpcy5fc3dpcGUuZGlzcG9zZSgpO1xuICAgIHRoaXMuX3N3aXBlID0gbnVsbDtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ2FuaW1hdGlvbicsICdzd2lwZWFibGUnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdhbmltYXRpb24nOlxuICAgICAgICB0aGlzLl91cGRhdGVBbmltYXRvckZhY3RvcnkoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdzd2lwZWFibGUnOlxuICAgICAgICB0aGlzLl9zd2lwZSAmJiB0aGlzLl9zd2lwZS51cGRhdGUoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgcG9wUGFnZVxuICAgKiBAc2lnbmF0dXJlIHBvcFBhZ2UoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dXG4gICAqICAgICBBbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcInNsaWRlXCJgLCBgXCJsaWZ0XCJgLCBgXCJmYWRlXCJgIGFuZCBgXCJub25lXCJgLlxuICAgKlxuICAgKiAgICAgVGhlc2UgYXJlIHBsYXRmb3JtIGJhc2VkIGFuaW1hdGlvbnMuIEZvciBmaXhlZCBhbmltYXRpb25zLCBhZGQgYFwiLWlvc1wiYCBvciBgXCItbWRcImAgc3VmZml4IHRvIHRoZSBhbmltYXRpb24gbmFtZS4gRS5nLiBgXCJsaWZ0LWlvc1wiYCwgYFwibGlmdC1tZFwiYC4gRGVmYXVsdHMgdmFsdWVzIGFyZSBgXCJzbGlkZS1pb3NcImAgYW5kIGBcImZhZGUtbWRcImAuXG4gICAqICAgWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4ge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1GdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCB3aGVuIHRoZSB0cmFuc2l0aW9uIGhhcyBlbmRlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jg6Hjgr3jg4Pjg4njgavjgojjgovnlLvpnaLpgbfnp7vjgYzntYLkuobjgZfjgZ/pmpvjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuZGF0YV1cbiAgICogICBbZW5dQ3VzdG9tIGRhdGEgdGhhdCB3aWxsIGJlIHN0b3JlZCBpbiB0aGUgbmV3IHBhZ2UgZWxlbWVudC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMudGltZXNdXG4gICAqICAgW2VuXU51bWJlciBvZiBwYWdlcyB0byBiZSBwb3BwZWQuIE9ubHkgb25lIGFuaW1hdGlvbiB3aWxsIGJlIHNob3duLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgdG8gdGhlIHJldmVhbGVkIHBhZ2UuWy9lbl1cbiAgICogICBbamFd5piO44KJ44GL44Gr44GX44Gf44Oa44O844K444KS6Kej5rG644GZ44KLUHJvbWlzZeOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Qb3BzIHRoZSBjdXJyZW50IHBhZ2UgZnJvbSB0aGUgcGFnZSBzdGFjay4gVGhlIHByZXZpb3VzIHBhZ2Ugd2lsbCBiZSBkaXNwbGF5ZWQuWy9lbl1cbiAgICogICBbamFd54++5Zyo6KGo56S65Lit44Gu44Oa44O844K444KS44Oa44O844K444K544K/44OD44Kv44GL44KJ5Y+W44KK6Zmk44GN44G+44GZ44CC5LiA44Gk5YmN44Gu44Oa44O844K444Gr5oi744KK44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHBvcFBhZ2Uob3B0aW9ucyA9IHt9KSB7XG4gICAgKHtvcHRpb25zfSA9IHRoaXMuX3ByZXBhcmVQYWdlQW5kT3B0aW9ucyhudWxsLCBvcHRpb25zKSk7XG5cbiAgICBpZiAodXRpbC5pc0ludGVnZXIob3B0aW9ucy50aW1lcykgJiYgb3B0aW9ucy50aW1lcyA+IDEpIHtcbiAgICAgIHRoaXMuX3JlbW92ZVBhZ2VzKG9wdGlvbnMudGltZXMpO1xuICAgIH1cblxuICAgIGNvbnN0IHBvcFVwZGF0ZSA9ICgpID0+IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICB0aGlzLl9wYWdlTG9hZGVyLnVubG9hZCh0aGlzLnBhZ2VzW3RoaXMucGFnZXMubGVuZ3RoIC0gMV0pO1xuICAgICAgcmVzb2x2ZSgpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuX3BvcFBhZ2Uob3B0aW9ucywgcG9wVXBkYXRlKTtcbiAgfVxuXG4gIF9wb3BQYWdlKG9wdGlvbnMsIHVwZGF0ZSA9ICgpID0+IFByb21pc2UucmVzb2x2ZSgpKSB7XG4gICAgaWYgKHRoaXMuX2lzUnVubmluZykge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdwb3BQYWdlIGlzIGFscmVhZHkgcnVubmluZy4nKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wYWdlcy5sZW5ndGggPD0gMSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdvbnMtbmF2aWdhdG9yXFwncyBwYWdlIHN0YWNrIGlzIGVtcHR5LicpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9lbWl0UHJlUG9wRXZlbnQoKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdDYW5jZWxlZCBpbiBwcmVwb3AgZXZlbnQuJyk7XG4gICAgfVxuXG4gICAgY29uc3QgbGVuZ3RoID0gdGhpcy5wYWdlcy5sZW5ndGg7XG5cbiAgICB0aGlzLl9pc1J1bm5pbmcgPSB0cnVlO1xuXG4gICAgdGhpcy5wYWdlc1tsZW5ndGggLSAyXS51cGRhdGVCYWNrQnV0dG9uKChsZW5ndGggLSAyKSA+IDApO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgY29uc3QgbGVhdmVQYWdlID0gdGhpcy5wYWdlc1tsZW5ndGggLSAxXTtcbiAgICAgIGNvbnN0IGVudGVyUGFnZSA9IHRoaXMucGFnZXNbbGVuZ3RoIC0gMl07XG5cbiAgICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7fSwgdGhpcy5vcHRpb25zIHx8IHt9LCBsZWF2ZVBhZ2UucHVzaGVkT3B0aW9ucyB8fCB7fSwgb3B0aW9ucyk7XG5cbiAgICAgIGlmIChvcHRpb25zLmRhdGEpIHtcbiAgICAgICAgZW50ZXJQYWdlLmRhdGEgPSB1dGlsLmV4dGVuZCh7fSwgZW50ZXJQYWdlLmRhdGEgfHwge30sIG9wdGlvbnMuZGF0YSB8fCB7fSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRvbmUgPSAoKSA9PiB7XG4gICAgICAgIHVwZGF0ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHRoaXMuX2lzUnVubmluZyA9IGZhbHNlO1xuXG4gICAgICAgICAgZW50ZXJQYWdlLl9zaG93KCk7XG4gICAgICAgICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdwb3N0cG9wJywge2xlYXZlUGFnZSwgZW50ZXJQYWdlLCBuYXZpZ2F0b3I6IHRoaXN9KTtcblxuICAgICAgICAgIG9wdGlvbnMuY2FsbGJhY2sgJiYgb3B0aW9ucy5jYWxsYmFjayhlbnRlclBhZ2UpO1xuXG4gICAgICAgICAgcmVzb2x2ZShlbnRlclBhZ2UpO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIGxlYXZlUGFnZS5faGlkZSgpO1xuICAgICAgZW50ZXJQYWdlLnN0eWxlLmRpc3BsYXkgPSAnJztcblxuICAgICAgY29uc3QgYW5pbWF0b3IgPSBvcHRpb25zLmFuaW1hdG9yIHx8IHRoaXMuX2FuaW1hdG9yRmFjdG9yeS5uZXdBbmltYXRvcihvcHRpb25zKTtcbiAgICAgIGFuaW1hdG9yLnBvcCh0aGlzLnBhZ2VzW2xlbmd0aCAtIDJdLCB0aGlzLnBhZ2VzW2xlbmd0aCAtIDFdLCBkb25lKTtcbiAgICB9KS5jYXRjaCgoKSA9PiB0aGlzLl9pc1J1bm5pbmcgPSBmYWxzZSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHB1c2hQYWdlXG4gICAqIEBzaWduYXR1cmUgcHVzaFBhZ2UocGFnZSwgW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge1N0cmluZ30gcGFnZVxuICAgKiAgIFtlbl1QYWdlIFVSTC4gQ2FuIGJlIGVpdGhlciBhIEhUTUwgZG9jdW1lbnQgb3IgYSB0ZW1wbGF0ZSBkZWZpbmVkIHdpdGggdGhlIGA8dGVtcGxhdGU+YCB0YWcuWy9lbl1cbiAgICogICBbamFdcGFnZeOBrlVSTOOBi+OAgeOCguOBl+OBj+OBr2A8dGVtcGxhdGU+YOOBp+Wuo+iogOOBl+OBn+ODhuODs+ODl+ODrOODvOODiOOBrmlk5bGe5oCn44Gu5YCk44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5wYWdlXVxuICAgKiAgIFtlbl1QYWdlIFVSTC4gT25seSBuZWNlc3NhcnkgaWYgYHBhZ2VgIHBhcmFtZXRlciBpcyBudWxsIG9yIHVuZGVmaW5lZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMucGFnZUhUTUxdXG4gICAqICAgW2VuXUhUTUwgY29kZSB0aGF0IHdpbGwgYmUgY29tcHV0ZWQgYXMgYSBuZXcgcGFnZS4gT3ZlcndyaXRlcyBgcGFnZWAgcGFyYW1ldGVyLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXVxuICAgKiAgICAgQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJzbGlkZVwiYCwgYFwibGlmdFwiYCwgYFwiZmFkZVwiYCBhbmQgYFwibm9uZVwiYC5cbiAgICpcbiAgICogICAgIFRoZXNlIGFyZSBwbGF0Zm9ybSBiYXNlZCBhbmltYXRpb25zLiBGb3IgZml4ZWQgYW5pbWF0aW9ucywgYWRkIGBcIi1pb3NcImAgb3IgYFwiLW1kXCJgIHN1ZmZpeCB0byB0aGUgYW5pbWF0aW9uIG5hbWUuIEUuZy4gYFwibGlmdC1pb3NcImAsIGBcImxpZnQtbWRcImAuIERlZmF1bHRzIHZhbHVlcyBhcmUgYFwic2xpZGUtaW9zXCJgIGFuZCBgXCJmYWRlLW1kXCJgLlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25PcHRpb25zXVxuICAgKiAgIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgZGVsYXkgYW5kIHRpbWluZy4gRS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWBbL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gIFsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1GdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCB3aGVuIHRoZSB0cmFuc2l0aW9uIGhhcyBlbmRlZC5bL2VuXVxuICAgKiAgIFtqYV1wdXNoUGFnZSgp44Gr44KI44KL55S76Z2i6YG356e744GM57WC5LqG44GX44Gf5pmC44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmRhdGFdXG4gICAqICAgW2VuXUN1c3RvbSBkYXRhIHRoYXQgd2lsbCBiZSBzdG9yZWQgaW4gdGhlIG5ldyBwYWdlIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUHJvbWlzZSB3aGljaCByZXNvbHZlcyB0byB0aGUgcHVzaGVkIHBhZ2UuWy9lbl1cbiAgICogICBbamFd6L+95Yqg44GX44Gf44Oa44O844K444KS6Kej5rG644GZ44KLUHJvbWlzZeOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1QdXNoZXMgdGhlIHNwZWNpZmllZCBwYWdlIGludG8gdGhlIHN0YWNrLlsvZW5dXG4gICAqICAgW2phXeaMh+WumuOBl+OBn3BhZ2XjgpLmlrDjgZfjgYTjg5rjg7zjgrjjgrnjgr/jg4Pjgq/jgavov73liqDjgZfjgb7jgZnjgILmlrDjgZfjgYTjg5rjg7zjgrjjgYzooajnpLrjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgcHVzaFBhZ2UocGFnZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgKHtwYWdlLCBvcHRpb25zfSA9IHRoaXMuX3ByZXBhcmVQYWdlQW5kT3B0aW9ucyhwYWdlLCBvcHRpb25zKSk7XG5cbiAgICBjb25zdCBwcmVwYXJlID0gcGFnZUVsZW1lbnQgPT4ge1xuICAgICAgdmVyaWZ5UGFnZUVsZW1lbnQocGFnZUVsZW1lbnQpO1xuICAgICAgdGhpcy5fcGFnZU1hcC5zZXQocGFnZUVsZW1lbnQsIHBhZ2UpO1xuICAgICAgcGFnZUVsZW1lbnQgPSB1dGlsLmV4dGVuZChwYWdlRWxlbWVudCwge1xuICAgICAgICBkYXRhOiBvcHRpb25zLmRhdGFcbiAgICAgIH0pO1xuICAgICAgcGFnZUVsZW1lbnQuc3R5bGUudmlzaWJpbGl0eSA9ICdoaWRkZW4nO1xuICAgIH07XG5cbiAgICBpZiAob3B0aW9ucy5wYWdlSFRNTCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3B1c2hQYWdlKG9wdGlvbnMsICgpID0+IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgICBpbnN0YW50UGFnZUxvYWRlci5sb2FkKHtwYWdlOiBvcHRpb25zLnBhZ2VIVE1MLCBwYXJlbnQ6IHRoaXMsIHBhcmFtczogb3B0aW9ucy5kYXRhfSwgcGFnZUVsZW1lbnQgPT4ge1xuICAgICAgICAgIHByZXBhcmUocGFnZUVsZW1lbnQpO1xuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgICB9KSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX3B1c2hQYWdlKG9wdGlvbnMsICgpID0+IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgdGhpcy5fcGFnZUxvYWRlci5sb2FkKHtwYWdlLCBwYXJlbnQ6IHRoaXMsIHBhcmFtczogb3B0aW9ucy5kYXRhfSwgcGFnZUVsZW1lbnQgPT4ge1xuICAgICAgICBwcmVwYXJlKHBhZ2VFbGVtZW50KTtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfSk7XG4gICAgfSkpO1xuICB9XG5cbiAgX3B1c2hQYWdlKG9wdGlvbnMgPSB7fSwgdXBkYXRlID0gKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCkpIHtcbiAgICBpZiAodGhpcy5faXNSdW5uaW5nKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ3B1c2hQYWdlIGlzIGFscmVhZHkgcnVubmluZy4nKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fZW1pdFByZVB1c2hFdmVudCgpKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ0NhbmNlbGVkIGluIHByZXB1c2ggZXZlbnQuJyk7XG4gICAgfVxuXG4gICAgdGhpcy5faXNSdW5uaW5nID0gdHJ1ZTtcblxuICAgIGNvbnN0IGFuaW1hdGlvbk9wdGlvbnMgPSBBbmltYXRvckZhY3RvcnkucGFyc2VBbmltYXRpb25PcHRpb25zU3RyaW5nKHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24tb3B0aW9ucycpKTtcbiAgICBvcHRpb25zID0gdXRpbC5leHRlbmQoe30sIHRoaXMub3B0aW9ucyB8fCB7fSwge2FuaW1hdGlvbk9wdGlvbnN9LCBvcHRpb25zKTtcblxuICAgIGNvbnN0IGFuaW1hdG9yID0gdGhpcy5fYW5pbWF0b3JGYWN0b3J5Lm5ld0FuaW1hdG9yKG9wdGlvbnMpO1xuXG4gICAgcmV0dXJuIHVwZGF0ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgY29uc3QgcGFnZUxlbmd0aCA9IHRoaXMucGFnZXMubGVuZ3RoO1xuXG4gICAgICBjb25zdCBlbnRlclBhZ2UgID0gdGhpcy5wYWdlc1twYWdlTGVuZ3RoIC0gMV07XG4gICAgICBjb25zdCBsZWF2ZVBhZ2UgPSBvcHRpb25zLmxlYXZlUGFnZSB8fCB0aGlzLnBhZ2VzW3BhZ2VMZW5ndGggLSAyXTtcblxuICAgICAgdmVyaWZ5UGFnZUVsZW1lbnQoZW50ZXJQYWdlKTtcblxuICAgICAgZW50ZXJQYWdlLnVwZGF0ZUJhY2tCdXR0b24ocGFnZUxlbmd0aCA+IChvcHRpb25zLl9yZXBsYWNlUGFnZSA/IDIgOiAxKSk7XG5cbiAgICAgIGVudGVyUGFnZS5wdXNoZWRPcHRpb25zID0gdXRpbC5leHRlbmQoe30sIGVudGVyUGFnZS5wdXNoZWRPcHRpb25zIHx8IHt9LCBvcHRpb25zIHx8IHt9KTtcbiAgICAgIGVudGVyUGFnZS5kYXRhID0gdXRpbC5leHRlbmQoe30sIGVudGVyUGFnZS5kYXRhIHx8IHt9LCBvcHRpb25zLmRhdGEgfHwge30pO1xuICAgICAgZW50ZXJQYWdlLnVubG9hZCA9IGVudGVyUGFnZS51bmxvYWQgfHwgb3B0aW9ucy51bmxvYWQ7XG5cbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgY29uc3QgZG9uZSA9ICgpID0+IHtcbiAgICAgICAgICB0aGlzLl9pc1J1bm5pbmcgPSBmYWxzZTtcblxuICAgICAgICAgIG9wdGlvbnMuc2hvdyAhPT0gZmFsc2UgJiYgc2V0SW1tZWRpYXRlKCgpID0+IGVudGVyUGFnZS5fc2hvdygpKTtcbiAgICAgICAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ3Bvc3RwdXNoJywge2xlYXZlUGFnZSwgZW50ZXJQYWdlLCBuYXZpZ2F0b3I6IHRoaXN9KTtcblxuICAgICAgICAgIGlmIChsZWF2ZVBhZ2UpIHtcbiAgICAgICAgICAgIGxlYXZlUGFnZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIG9wdGlvbnMuY2FsbGJhY2sgJiYgb3B0aW9ucy5jYWxsYmFjayhlbnRlclBhZ2UpO1xuXG4gICAgICAgICAgcmVzb2x2ZShlbnRlclBhZ2UpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGVudGVyUGFnZS5zdHlsZS52aXNpYmlsaXR5ID0gJyc7XG4gICAgICAgIGlmIChsZWF2ZVBhZ2UpIHtcbiAgICAgICAgICBsZWF2ZVBhZ2UuX2hpZGUoKTtcbiAgICAgICAgICBhbmltYXRvci5wdXNoKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBkb25lKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgdGhpcy5faXNSdW5uaW5nID0gZmFsc2U7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHJlcGxhY2VQYWdlXG4gICAqIEBzaWduYXR1cmUgcmVwbGFjZVBhZ2UocGFnZSwgW29wdGlvbnNdKVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1Qcm9taXNlIHdoaWNoIHJlc29sdmVzIHRvIHRoZSBuZXcgcGFnZS5bL2VuXVxuICAgKiAgIFtqYV3mlrDjgZfjgYTjg5rjg7zjgrjjgpLop6PmsbrjgZnjgotQcm9taXNl44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJlcGxhY2VzIHRoZSBjdXJyZW50IHRvcCBwYWdlIHdpdGggdGhlIHNwZWNpZmllZCBvbmUuIEV4dGVuZHMgYHB1c2hQYWdlKClgIHBhcmFtZXRlcnMuWy9lbl1cbiAgICogICBbamFd54++5Zyo6KGo56S65Lit44Gu44Oa44O844K444KS44KS5oyH5a6a44GX44Gf44Oa44O844K444Gr572u44GN5o+b44GI44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHJlcGxhY2VQYWdlKHBhZ2UsIG9wdGlvbnMgPSB7fSkge1xuICAgIHJldHVybiB0aGlzLnB1c2hQYWdlKHBhZ2UsIG9wdGlvbnMpXG4gICAgICAudGhlbihyZXNvbHZlZFZhbHVlID0+IHtcbiAgICAgICAgaWYgKHRoaXMucGFnZXMubGVuZ3RoID4gMSkge1xuICAgICAgICAgIHRoaXMuX3BhZ2VMb2FkZXIudW5sb2FkKHRoaXMucGFnZXNbdGhpcy5wYWdlcy5sZW5ndGggLSAyXSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fdXBkYXRlTGFzdFBhZ2VCYWNrQnV0dG9uKCk7XG5cbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXNvbHZlZFZhbHVlKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaW5zZXJ0UGFnZVxuICAgKiBAc2lnbmF0dXJlIGluc2VydFBhZ2UoaW5kZXgsIHBhZ2UsIFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGluZGV4XG4gICAqICAgW2VuXVRoZSBpbmRleCB3aGVyZSBpdCBzaG91bGQgYmUgaW5zZXJ0ZWQuWy9lbl1cbiAgICogICBbamFd44K544K/44OD44Kv44Gr5oy/5YWl44GZ44KL5L2N572u44Gu44Kk44Oz44OH44OD44Kv44K544KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUHJvbWlzZSB3aGljaCByZXNvbHZlcyB0byB0aGUgaW5zZXJ0ZWQgcGFnZS5bL2VuXVxuICAgKiAgIFtqYV3mjIflrprjgZfjgZ/jg5rjg7zjgrjjgpLop6PmsbrjgZnjgotQcm9taXNl44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUluc2VydCB0aGUgc3BlY2lmaWVkIHBhZ2UgaW50byB0aGUgc3RhY2sgd2l0aCBhdCBhIHBvc2l0aW9uIGRlZmluZWQgYnkgdGhlIGBpbmRleGAgYXJndW1lbnQuIEV4dGVuZHMgYHB1c2hQYWdlKClgIHBhcmFtZXRlcnMuWy9lbl1cbiAgICogICBbamFd5oyH5a6a44GX44GfcGFnZeOCkuODmuODvOOCuOOCueOCv+ODg+OCr+OBrmluZGV444Gn5oyH5a6a44GX44Gf5L2N572u44Gr6L+95Yqg44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGluc2VydFBhZ2UoaW5kZXgsIHBhZ2UsIG9wdGlvbnMgPSB7fSkge1xuICAgICh7cGFnZSwgb3B0aW9uc30gPSB0aGlzLl9wcmVwYXJlUGFnZUFuZE9wdGlvbnMocGFnZSwgb3B0aW9ucykpO1xuICAgIGluZGV4ID0gdGhpcy5fbm9ybWFsaXplSW5kZXgoaW5kZXgpO1xuXG4gICAgaWYgKGluZGV4ID49IHRoaXMucGFnZXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gdGhpcy5wdXNoUGFnZShwYWdlLCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICBwYWdlID0gdHlwZW9mIG9wdGlvbnMucGFnZUhUTUwgPT09ICdzdHJpbmcnID8gb3B0aW9ucy5wYWdlSFRNTCA6IHBhZ2U7XG4gICAgY29uc3QgbG9hZGVyID0gdHlwZW9mIG9wdGlvbnMucGFnZUhUTUwgPT09ICdzdHJpbmcnID8gaW5zdGFudFBhZ2VMb2FkZXIgOiB0aGlzLl9wYWdlTG9hZGVyO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgbG9hZGVyLmxvYWQoe3BhZ2UsIHBhcmVudDogdGhpc30sIHBhZ2VFbGVtZW50ID0+IHtcbiAgICAgICAgdmVyaWZ5UGFnZUVsZW1lbnQocGFnZUVsZW1lbnQpO1xuICAgICAgICB0aGlzLl9wYWdlTWFwLnNldChwYWdlRWxlbWVudCwgcGFnZSk7XG4gICAgICAgIHBhZ2VFbGVtZW50ID0gdXRpbC5leHRlbmQocGFnZUVsZW1lbnQsIHtcbiAgICAgICAgICBkYXRhOiBvcHRpb25zLmRhdGEsXG4gICAgICAgICAgcHVzaGVkT3B0aW9uczogb3B0aW9uc1xuICAgICAgICB9KTtcblxuICAgICAgICBvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnMgPSB1dGlsLmV4dGVuZChcbiAgICAgICAgICB7fSxcbiAgICAgICAgICBBbmltYXRvckZhY3RvcnkucGFyc2VBbmltYXRpb25PcHRpb25zU3RyaW5nKHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24tb3B0aW9ucycpKSxcbiAgICAgICAgICBvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnMgfHwge31cbiAgICAgICAgKTtcblxuICAgICAgICBwYWdlRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICB0aGlzLmluc2VydEJlZm9yZShwYWdlRWxlbWVudCwgdGhpcy5wYWdlc1tpbmRleF0pO1xuICAgICAgICB0aGlzLnRvcFBhZ2UudXBkYXRlQmFja0J1dHRvbih0cnVlKTtcblxuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICBwYWdlRWxlbWVudCA9IG51bGw7XG4gICAgICAgICAgcmVzb2x2ZSh0aGlzLnBhZ2VzW2luZGV4XSk7XG4gICAgICAgIH0sIDEwMDAgLyA2MCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHJlbW92ZVBhZ2VcbiAgICogQHNpZ25hdHVyZSByZW1vdmVQYWdlKGluZGV4LCBbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBpbmRleFxuICAgKiAgIFtlbl1UaGUgaW5kZXggd2hlcmUgaXQgc2hvdWxkIGJlIHJlbW92ZWQuWy9lbl1cbiAgICogICBbamFd44K544K/44OD44Kv44GL44KJ5YmK6Zmk44GZ44KL44Oa44O844K444Gu44Kk44Oz44OH44OD44Kv44K544KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUHJvbWlzZSB3aGljaCByZXNvbHZlcyB0byB0aGUgcmV2ZWFsZWQgcGFnZS5bL2VuXVxuICAgKiAgIFtqYV3liYrpmaTjgavjgojjgaPjgabooajnpLrjgZXjgozjgZ/jg5rjg7zjgrjjgpLop6PmsbrjgZnjgotQcm9taXNl44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJlbW92ZSB0aGUgc3BlY2lmaWVkIHBhZ2UgYXQgYSBwb3NpdGlvbiBpbiB0aGUgc3RhY2sgZGVmaW5lZCBieSB0aGUgYGluZGV4YCBhcmd1bWVudC4gRXh0ZW5kcyBgcG9wUGFnZSgpYCBwYXJhbWV0ZXJzLlsvZW5dXG4gICAqICAgW2phXeaMh+WumuOBl+OBn+OCpOODs+ODh+ODg+OCr+OCueOBq+OBguOCi+ODmuODvOOCuOOCkuWJiumZpOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICByZW1vdmVQYWdlKGluZGV4LCBvcHRpb25zID0ge30pIHtcbiAgICBpbmRleCA9IHRoaXMuX25vcm1hbGl6ZUluZGV4KGluZGV4KTtcblxuICAgIGlmIChpbmRleCA8IHRoaXMucGFnZXMubGVuZ3RoIC0gMSkge1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgICBjb25zdCBsZWF2ZVBhZ2UgPSB0aGlzLnBhZ2VzW2luZGV4XTtcbiAgICAgICAgY29uc3QgZW50ZXJQYWdlID0gdGhpcy50b3BQYWdlO1xuXG4gICAgICAgIHRoaXMuX3BhZ2VNYXAuZGVsZXRlKGxlYXZlUGFnZSk7XG4gICAgICAgIHRoaXMuX3BhZ2VMb2FkZXIudW5sb2FkKGxlYXZlUGFnZSk7XG4gICAgICAgIGlmICh0aGlzLnBhZ2VzLmxlbmd0aCA9PT0gMSkgeyAvLyBlZGdlIGNhc2VcbiAgICAgICAgICB0aGlzLnRvcFBhZ2UudXBkYXRlQmFja0J1dHRvbihmYWxzZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXNvbHZlKGVudGVyUGFnZSk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMucG9wUGFnZShvcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCByZXNldFRvUGFnZVxuICAgKiBAc2lnbmF0dXJlIHJlc2V0VG9QYWdlKHBhZ2UsIFtvcHRpb25zXSlcbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUHJvbWlzZSB3aGljaCByZXNvbHZlcyB0byB0aGUgbmV3IHRvcCBwYWdlLlsvZW5dXG4gICAqICAgW2phXeaWsOOBl+OBhOODiOODg+ODl+ODmuODvOOCuOOCkuino+axuuOBmeOCi1Byb21pc2XjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLnBvcF1cbiAgICogICBbZW5dUGVyZm9ybXMgJ3BvcCcgZWZmZWN0IGlmIGB0cnVlYCBpbnN0ZWFkIG9mICdwdXNoJyBvciBub25lLiBUaGlzIGFsc28gc2V0cyBgb3B0aW9ucy5hbmltYXRpb25gIHZhbHVlIHRvIGBkZWZhdWx0YCBpbnN0ZWFkIG9mIGBub25lYC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ2xlYXJzIHBhZ2Ugc3RhY2sgYW5kIGFkZHMgdGhlIHNwZWNpZmllZCBwYWdlIHRvIHRoZSBzdGFjay4gRXh0ZW5kcyBgcHVzaFBhZ2UoKWAgcGFyYW1ldGVycy5bL2VuXVxuICAgKiAgIFtqYV3jg5rjg7zjgrjjgrnjgr/jg4Pjgq/jgpLjg6rjgrvjg4Pjg4jjgZfjgIHmjIflrprjgZfjgZ/jg5rjg7zjgrjjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgcmVzZXRUb1BhZ2UocGFnZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgKHtwYWdlLCBvcHRpb25zfSA9IHRoaXMuX3ByZXBhcmVQYWdlQW5kT3B0aW9ucyhwYWdlLCBvcHRpb25zKSk7XG5cbiAgICBpZiAoIW9wdGlvbnMuYW5pbWF0b3IgJiYgIW9wdGlvbnMuYW5pbWF0aW9uICYmICFvcHRpb25zLnBvcCkge1xuICAgICAgb3B0aW9ucy5hbmltYXRpb24gPSAnbm9uZSc7XG4gICAgfVxuXG4gICAgaWYgKCFvcHRpb25zLnBhZ2UgJiYgIW9wdGlvbnMucGFnZUhUTUwgJiYgdGhpcy5fZ2V0UGFnZVRhcmdldCgpKSB7XG4gICAgICBwYWdlID0gb3B0aW9ucy5wYWdlID0gdGhpcy5fZ2V0UGFnZVRhcmdldCgpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLnBvcCkge1xuICAgICAgdGhpcy5fcmVtb3ZlUGFnZXMoKVxuICAgICAgcmV0dXJuIHRoaXMuaW5zZXJ0UGFnZSgwLCBwYWdlLCB7IGRhdGE6IG9wdGlvbnMuZGF0YSB9KVxuICAgICAgICAudGhlbigoKSA9PiB0aGlzLnBvcFBhZ2Uob3B0aW9ucykpO1xuICAgIH1cblxuICAgIC8vIFRpcDogY2FsbGJhY2sgcnVucyBiZWZvcmUgcmVzb2x2ZWQgcHJvbWlzZVxuICAgIGNvbnN0IGNhbGxiYWNrID0gb3B0aW9ucy5jYWxsYmFjaztcbiAgICBvcHRpb25zLmNhbGxiYWNrID0gbmV3UGFnZSA9PiB7XG4gICAgICB0aGlzLl9yZW1vdmVQYWdlcygpXG4gICAgICBuZXdQYWdlLnVwZGF0ZUJhY2tCdXR0b24oZmFsc2UpO1xuICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2sobmV3UGFnZSk7XG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLnB1c2hQYWdlKHBhZ2UsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgYnJpbmdQYWdlVG9wXG4gICAqIEBzaWduYXR1cmUgYnJpbmdQYWdlVG9wKGl0ZW0sIFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSBpdGVtXG4gICAqICAgW2VuXVBhZ2UgVVJMIG9yIGluZGV4IG9mIGFuIGV4aXN0aW5nIHBhZ2UgaW4gbmF2aWdhdG9yJ3Mgc3RhY2suWy9lbl1cbiAgICogICBbamFd44Oa44O844K444GuVVJM44GL44KC44GX44GP44Gvb25zLW5hdmlnYXRvcuOBruODmuODvOOCuOOCueOCv+ODg+OCr+OBruOCpOODs+ODh+ODg+OCr+OCueWApOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgdG8gdGhlIG5ldyB0b3AgcGFnZS5bL2VuXVxuICAgKiAgIFtqYV3mlrDjgZfjgYTjg4jjg4Pjg5fjg5rjg7zjgrjjgpLop6PmsbrjgZnjgotQcm9taXNl44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUJyaW5ncyB0aGUgZ2l2ZW4gcGFnZSB0byB0aGUgdG9wIG9mIHRoZSBwYWdlIHN0YWNrIGlmIGl0IGFscmVhZHkgZXhpc3RzIG9yIHB1c2hlcyBpdCBpbnRvIHRoZSBzdGFjayBpZiBkb2Vzbid0LiBFeHRlbmRzIGBwdXNoUGFnZSgpYCBwYXJhbWV0ZXJzLlsvZW5dXG4gICAqICAgW2phXeaMh+WumuOBl+OBn+ODmuODvOOCuOOCkuODmuODvOOCuOOCueOCv+ODg+OCr+OBruS4gOeVquS4iuOBq+enu+WLleOBl+OBvuOBmeOAguOCguOBl+aMh+WumuOBl+OBn+ODmuODvOOCuOOBjOeEoeOBi+OBo+OBn+WgtOWQiOaWsOOBl+OBj3B1c2jjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgYnJpbmdQYWdlVG9wKGl0ZW0sIG9wdGlvbnMgPSB7fSkge1xuICAgIGlmIChbJ251bWJlcicsICdzdHJpbmcnXS5pbmRleE9mKHR5cGVvZiBpdGVtKSA9PT0gLTEpIHtcbiAgICAgIHV0aWwudGhyb3coJ0ZpcnN0IGFyZ3VtZW50IG11c3QgYmUgYSBwYWdlIG5hbWUgb3IgdGhlIGluZGV4IG9mIGFuIGV4aXN0aW5nIHBhZ2UuIFlvdSBzdXBwbGllZCAnICsgaXRlbSk7XG4gICAgfVxuICAgIGNvbnN0IGluZGV4ID0gdHlwZW9mIGl0ZW0gPT09ICdudW1iZXInID8gdGhpcy5fbm9ybWFsaXplSW5kZXgoaXRlbSkgOiB0aGlzLl9sYXN0SW5kZXhPZlBhZ2UoaXRlbSk7XG4gICAgY29uc3QgcGFnZSA9IHRoaXMucGFnZXNbaW5kZXhdO1xuXG4gICAgaWYgKGluZGV4IDwgMCkge1xuICAgICAgcmV0dXJuIHRoaXMucHVzaFBhZ2UoaXRlbSwgb3B0aW9ucyk7XG4gICAgfVxuICAgICh7b3B0aW9uc30gPSB0aGlzLl9wcmVwYXJlUGFnZUFuZE9wdGlvbnMocGFnZSwgb3B0aW9ucykpO1xuXG4gICAgaWYgKGluZGV4ID09PSB0aGlzLnBhZ2VzLmxlbmd0aCAtIDEpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocGFnZSk7XG4gICAgfVxuICAgIGlmICghcGFnZSkge1xuICAgICAgdXRpbC50aHJvdygnRmFpbGVkIHRvIGZpbmQgaXRlbSAnICsgaXRlbSk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9pc1J1bm5pbmcpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgncHVzaFBhZ2UgaXMgYWxyZWFkeSBydW5uaW5nLicpO1xuICAgIH1cbiAgICBpZiAodGhpcy5fZW1pdFByZVB1c2hFdmVudCgpKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ0NhbmNlbGVkIGluIHByZXB1c2ggZXZlbnQuJyk7XG4gICAgfVxuXG4gICAgcGFnZS5zdHlsZS5kaXNwbGF5ID0gJyc7XG4gICAgcGFnZS5zdHlsZS52aXNpYmlsaXR5ID0gJ2hpZGRlbic7XG4gICAgcGFnZS5wYXJlbnROb2RlLmFwcGVuZENoaWxkKHBhZ2UpO1xuICAgIHJldHVybiB0aGlzLl9wdXNoUGFnZShvcHRpb25zKTtcbiAgfVxuXG4gIF9wcmVwYXJlUGFnZUFuZE9wdGlvbnMocGFnZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgaWYgKHR5cGVvZiBvcHRpb25zICE9ICdvYmplY3QnKSB7XG4gICAgICB1dGlsLnRocm93KCdvcHRpb25zIG11c3QgYmUgYW4gb2JqZWN0LiBZb3Ugc3VwcGxpZWQgJyArIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIGlmICgocGFnZSA9PT0gbnVsbCB8fCBwYWdlID09PSB1bmRlZmluZWQpICYmIG9wdGlvbnMucGFnZSkge1xuICAgICAgcGFnZSA9IG9wdGlvbnMucGFnZTtcbiAgICB9XG5cbiAgICBvcHRpb25zID0gdXRpbC5leHRlbmQoe30sIHRoaXMub3B0aW9ucyB8fCB7fSwgb3B0aW9ucywge3BhZ2V9KTtcblxuICAgIHJldHVybiB7cGFnZSwgb3B0aW9uc307XG4gIH1cblxuICBfcmVtb3ZlUGFnZXModGltZXMpIHtcbiAgICBjb25zdCBwYWdlcyA9IHRoaXMucGFnZXM7XG4gICAgbGV0IHVudGlsID0gdGltZXMgPT09IHVuZGVmaW5lZCA/IDAgOiBwYWdlcy5sZW5ndGggLSB0aW1lcztcbiAgICB1bnRpbCA9IHVudGlsIDwgMCA/IDEgOiB1bnRpbDtcblxuICAgIGZvciAobGV0IGkgPSBwYWdlcy5sZW5ndGggLSAyOyBpID49IHVudGlsOyBpLS0pIHtcbiAgICAgIHRoaXMuX3BhZ2VNYXAuZGVsZXRlKHBhZ2VzW2ldKTtcbiAgICAgIHRoaXMuX3BhZ2VMb2FkZXIudW5sb2FkKHBhZ2VzW2ldKTtcbiAgICB9XG4gIH1cblxuICBfdXBkYXRlTGFzdFBhZ2VCYWNrQnV0dG9uKCkge1xuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5wYWdlcy5sZW5ndGggLSAxO1xuICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICB0aGlzLnBhZ2VzW2luZGV4XS51cGRhdGVCYWNrQnV0dG9uKGluZGV4ID4gMCk7XG4gICAgfVxuICB9XG5cbiAgX25vcm1hbGl6ZUluZGV4KGluZGV4KSB7XG4gICAgcmV0dXJuIGluZGV4ID49IDAgPyBpbmRleCA6IE1hdGguYWJzKHRoaXMucGFnZXMubGVuZ3RoICsgaW5kZXgpICUgdGhpcy5wYWdlcy5sZW5ndGg7XG4gIH1cblxuICBfb25EZXZpY2VCYWNrQnV0dG9uKGV2ZW50KSB7XG4gICAgaWYgKHRoaXMucGFnZXMubGVuZ3RoID4gMSkge1xuICAgICAgdGhpcy5wb3BQYWdlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGV2ZW50LmNhbGxQYXJlbnRIYW5kbGVyKCk7XG4gICAgfVxuICB9XG5cbiAgX2xhc3RJbmRleE9mUGFnZShwYWdlTmFtZSkge1xuICAgIGxldCBpbmRleDtcbiAgICBmb3IgKGluZGV4ID0gdGhpcy5wYWdlcy5sZW5ndGggLSAxOyBpbmRleCA+PSAwOyBpbmRleC0tKSB7XG4gICAgICBpZiAocGFnZU5hbWUgPT09IHRoaXMuX3BhZ2VNYXAuZ2V0KHRoaXMucGFnZXNbaW5kZXhdKSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGluZGV4O1xuICB9XG5cbiAgX2VtaXRQcmVFdmVudChuYW1lLCBkYXRhID0ge30pIHtcbiAgICBsZXQgaXNDYW5jZWxlZCA9IGZhbHNlO1xuXG4gICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdwcmUnICsgbmFtZSwgdXRpbC5leHRlbmQoe1xuICAgICAgbmF2aWdhdG9yOiB0aGlzLFxuICAgICAgY3VycmVudFBhZ2U6IHRoaXMucGFnZXNbdGhpcy5wYWdlcy5sZW5ndGggLSAxXSxcbiAgICAgIGNhbmNlbDogKCkgPT4gaXNDYW5jZWxlZCA9IHRydWVcbiAgICB9LCBkYXRhKSk7XG5cbiAgICByZXR1cm4gaXNDYW5jZWxlZDtcbiAgfVxuXG4gIF9lbWl0UHJlUHVzaEV2ZW50KCkge1xuICAgIHJldHVybiB0aGlzLl9lbWl0UHJlRXZlbnQoJ3B1c2gnKTtcbiAgfVxuXG4gIF9lbWl0UHJlUG9wRXZlbnQoKSB7XG4gICAgY29uc3QgbCA9IHRoaXMucGFnZXMubGVuZ3RoO1xuICAgIHJldHVybiB0aGlzLl9lbWl0UHJlRXZlbnQoJ3BvcCcsIHtcbiAgICAgIGxlYXZlUGFnZTogdGhpcy5wYWdlc1tsIC0gMV0sXG4gICAgICBlbnRlclBhZ2U6IHRoaXMucGFnZXNbbCAtIDJdXG4gICAgfSk7XG4gIH1cblxuICAvLyBUT0RPOiDmm7jjgY3nm7TjgZlcbiAgX2NyZWF0ZVBhZ2VFbGVtZW50KHRlbXBsYXRlSFRNTCkge1xuICAgIGNvbnN0IHBhZ2VFbGVtZW50ID0gdXRpbC5jcmVhdGVFbGVtZW50KGludGVybmFsLm5vcm1hbGl6ZVBhZ2VIVE1MKHRlbXBsYXRlSFRNTCkpO1xuICAgIHZlcmlmeVBhZ2VFbGVtZW50KHBhZ2VFbGVtZW50KTtcbiAgICByZXR1cm4gcGFnZUVsZW1lbnQ7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9uRGV2aWNlQmFja0J1dHRvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQmFjay1idXR0b24gaGFuZGxlci5bL2VuXVxuICAgKiAgIFtqYV3jg5Djg4Pjgq/jg5zjgr/jg7Pjg4/jg7Pjg4njg6njgIJbL2phXVxuICAgKi9cbiAgZ2V0IG9uRGV2aWNlQmFja0J1dHRvbigpIHtcbiAgICByZXR1cm4gdGhpcy5fYmFja0J1dHRvbkhhbmRsZXI7XG4gIH1cblxuICBzZXQgb25EZXZpY2VCYWNrQnV0dG9uKGNhbGxiYWNrKSB7XG4gICAgaWYgKHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyKSB7XG4gICAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlci5kZXN0cm95KCk7XG4gICAgfVxuXG4gICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIgPSBkZXZpY2VCYWNrQnV0dG9uRGlzcGF0Y2hlci5jcmVhdGVIYW5kbGVyKHRoaXMsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdG9wUGFnZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0hUTUxFbGVtZW50fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCB0b3AgcGFnZSBlbGVtZW50LiBVc2UgdGhpcyBtZXRob2QgdG8gYWNjZXNzIG9wdGlvbnMgcGFzc2VkIGJ5IGBwdXNoUGFnZSgpYC1saWtlIG1ldGhvZHMuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Gu44Oa44O844K444KS5Y+W5b6X44GX44G+44GZ44CCcHVzaFBhZ2UoKeOChHJlc2V0VG9QYWdlKCnjg6Hjgr3jg4Pjg4njga7lvJXmlbDjgpLlj5blvpfjgafjgY3jgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZ2V0IHRvcFBhZ2UoKSB7XG4gICAgbGV0IGxhc3QgPSB0aGlzLmxhc3RFbGVtZW50Q2hpbGQ7XG4gICAgd2hpbGUgKGxhc3QgJiYgbGFzdC50YWdOYW1lICE9PSAnT05TLVBBR0UnKSB7IGxhc3QgPSBsYXN0LnByZXZpb3VzRWxlbWVudFNpYmxpbmc7IH1cbiAgICByZXR1cm4gbGFzdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgcGFnZXNcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtBcnJheX1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUNvcHkgb2YgdGhlIG5hdmlnYXRvcidzIHBhZ2Ugc3RhY2suWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGdldCBwYWdlcygpIHtcbiAgICByZXR1cm4gdXRpbC5hcnJheUZyb20odGhpcy5jaGlsZHJlbilcbiAgICAgIC5maWx0ZXIoZWxlbWVudCA9PiBlbGVtZW50LnRhZ05hbWUgPT09ICdPTlMtUEFHRScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvblN3aXBlXG4gICAqIEB0eXBlIHtGdW5jdGlvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUhvb2sgY2FsbGVkIHdoZW5ldmVyIHRoZSB1c2VyIHNsaWRlcyB0aGUgbmF2aWdhdG9yIChzd2lwZS10by1wb3ApLiBJdCBnZXRzIGEgZGVjaW1hbCByYXRpbyAoMC0xKSBhbmQgYW4gYW5pbWF0aW9uT3B0aW9ucyBvYmplY3QgYXMgYXJndW1lbnRzLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgb25Td2lwZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fb25Td2lwZTtcbiAgfVxuXG4gIHNldCBvblN3aXBlKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICYmICEodmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHV0aWwudGhyb3coJ1wib25Td2lwZVwiIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgIH1cbiAgICB0aGlzLl9vblN3aXBlID0gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9wdGlvbnNcbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXURlZmF1bHQgb3B0aW9ucyBvYmplY3QuIEF0dHJpYnV0ZXMgaGF2ZSBwcmlvcml0eSBvdmVyIHRoaXMgcHJvcGVydHkuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvcHRpb25zLmFuaW1hdGlvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dXG4gICAqICAgICBBbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcInNsaWRlXCJgLCBgXCJsaWZ0XCJgLCBgXCJmYWRlXCJgIGFuZCBgXCJub25lXCJgLlxuICAgKiAgICAgVGhlc2UgYXJlIHBsYXRmb3JtIGJhc2VkIGFuaW1hdGlvbnMuIEZvciBmaXhlZCBhbmltYXRpb25zLCBhZGQgYFwiLWlvc1wiYCBvciBgXCItbWRcImAgc3VmZml4IHRvIHRoZSBhbmltYXRpb24gbmFtZS4gRS5nLiBgXCJsaWZ0LWlvc1wiYCwgYFwibGlmdC1tZFwiYC4gRGVmYXVsdHMgdmFsdWVzIGFyZSBgXCJzbGlkZS1pb3NcImAgYW5kIGBcImZhZGUtbWRcImAuXG4gICAqICAgWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gIFsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb3B0aW9ucy5jYWxsYmFja1xuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgd2hlbiB0aGUgdHJhbnNpdGlvbiBoYXMgZW5kZWQuWy9lbl1cbiAgICogICBbamFd44GT44Gu44Oh44K944OD44OJ44Gr44KI44KL55S76Z2i6YG356e744GM57WC5LqG44GX44Gf6Zqb44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgZ2V0IG9wdGlvbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX29wdGlvbnM7XG4gIH1cbiAgc2V0IG9wdGlvbnMob2JqZWN0KSB7XG4gICAgdGhpcy5fb3B0aW9ucyA9IG9iamVjdDtcbiAgfVxuXG4gIHNldCBfaXNSdW5uaW5nKHZhbHVlKSB7XG4gICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ19pcy1ydW5uaW5nJywgdmFsdWUgPyAndHJ1ZScgOiAnZmFsc2UnKTtcbiAgfVxuICBnZXQgX2lzUnVubmluZygpIHtcbiAgIHJldHVybiBKU09OLnBhcnNlKHRoaXMuZ2V0QXR0cmlidXRlKCdfaXMtcnVubmluZycpKTtcbiAgfVxuXG4gIF9zaG93KCkge1xuICAgIHRoaXMubG9hZGVkLnRoZW4oKCkgPT4gdGhpcy50b3BQYWdlICYmIHRoaXMudG9wUGFnZS5fc2hvdygpKVxuICB9XG5cbiAgX2hpZGUoKSB7XG4gICAgdGhpcy50b3BQYWdlICYmIHRoaXMudG9wUGFnZS5faGlkZSgpXG4gIH1cblxuICBfZGVzdHJveSgpIHtcbiAgICBmb3IgKGxldCBpID0gdGhpcy5wYWdlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgdGhpcy5fcGFnZUxvYWRlci51bmxvYWQodGhpcy5wYWdlc1tpXSk7XG4gICAgfVxuXG4gICAgdGhpcy5yZW1vdmUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBBbmltYXRvclxuICAgKi9cbiAgc3RhdGljIHJlZ2lzdGVyQW5pbWF0b3IobmFtZSwgQW5pbWF0b3IpIHtcbiAgICBpZiAoIShBbmltYXRvci5wcm90b3R5cGUgaW5zdGFuY2VvZiBOYXZpZ2F0b3JBbmltYXRvcikpIHtcbiAgICAgIHV0aWwudGhyb3dBbmltYXRvcignTmF2aWdhdG9yJyk7XG4gICAgfVxuXG4gICAgX2FuaW1hdG9yRGljdFtuYW1lXSA9IEFuaW1hdG9yO1xuICB9XG5cbiAgc3RhdGljIGdldCBhbmltYXRvcnMoKSB7XG4gICAgcmV0dXJuIF9hbmltYXRvckRpY3Q7XG4gIH1cblxuICBzdGF0aWMgZ2V0IE5hdmlnYXRvckFuaW1hdG9yKCkge1xuICAgIHJldHVybiBOYXZpZ2F0b3JBbmltYXRvcjtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgZXZlbnRzKCkge1xuICAgIHJldHVybiBbJ3ByZXB1c2gnLCAncG9zdHB1c2gnLCAncHJlcG9wJywgJ3Bvc3Rwb3AnXTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgcmV3cml0YWJsZXMoKSB7XG4gICAgcmV0dXJuIHJld3JpdGFibGVzO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLk5hdmlnYXRvciA9IE5hdmlnYXRvckVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1uYXZpZ2F0b3InLCBOYXZpZ2F0b3JFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uL29ucy9pbnRlcm5hbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3QgZGVmYXVsdENsYXNzTmFtZSA9ICd0b29sYmFyJztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ3Rvb2xiYXItLSonLFxuICAnLnRvb2xiYXJfX2xlZnQnOiAndG9vbGJhci0tKl9fbGVmdCcsXG4gICcudG9vbGJhcl9fY2VudGVyJzogJ3Rvb2xiYXItLSpfX2NlbnRlcicsXG4gICcudG9vbGJhcl9fcmlnaHQnOiAndG9vbGJhci0tKl9fcmlnaHQnXG59O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy10b29sYmFyXG4gKiBAY2F0ZWdvcnkgcGFnZVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1NYXRlcmlhbCBEZXNpZ24gdG9vbGJhci5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBtb2RpZmllciB0cmFuc3BhcmVudFxuICogICBbZW5dVHJhbnNwYXJlbnQgdG9vbGJhci5bL2VuXVxuICogICBbamFd6YCP5piO44Gq6IOM5pmv44KS5oyB44Gk44OE44O844Or44OQ44O844KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBtb2RpZmllciBjb3Zlci1jb250ZW50XG4gKiAgIFtlbl1EaXNwbGF5cyB0aGUgdG9vbGJhciBvbiB0b3Agb2YgdGhlIHBhZ2UncyBjb250ZW50LiBTaG91bGQgYmUgY29tYmluZWQgd2l0aCBgdHJhbnNwYXJlbnRgIG1vZGlmaWVyLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQG1vZGlmaWVyIG5vc2hhZG93XG4gKiAgIFtlbl1Ub29sYmFyIHdpdGhvdXQgc2hhZG93LlsvZW5dXG4gKiAgIFtqYV3jg4Tjg7zjg6vjg5Djg7zjgavlvbHjgpLku5jjgZHjgZrjgavooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBUb29sYmFyIGNvbXBvbmVudCB0aGF0IGNhbiBiZSB1c2VkIHdpdGggbmF2aWdhdGlvbi5cbiAqXG4gKiAgICAgTGVmdCwgY2VudGVyIGFuZCByaWdodCBjb250YWluZXJzIGNhbiBiZSBzcGVjaWZpZWQgYnkgY2xhc3MgbmFtZXMuXG4gKlxuICogICAgIFRoaXMgY29tcG9uZW50IHdpbGwgYXV0b21hdGljYWxseSBkaXNwbGF5IGFzIGEgTWF0ZXJpYWwgRGVzaWduIHRvb2xiYXIgd2hlbiBydW5uaW5nIG9uIEFuZHJvaWQgZGV2aWNlcy5cbiAqICAgWy9lbl1cbiAqICAgW2phXeODiuODk+OCsuODvOOCt+ODp+ODs+OBp+S9v+eUqOOBmeOCi+ODhOODvOODq+ODkOODvOeUqOOCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAguOCr+ODqeOCueWQjeOBq+OCiOOCiuOAgeW3puOAgeS4reWkruOAgeWPs+OBruOCs+ODs+ODhuODiuOCkuaMh+WumuOBp+OBjeOBvuOBmeOAglsvamFdXG4gKiBAY29kZXBlbiBhSG1HTFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3Rvb2xiYXJcbiAqIEBndWlkZSBjb21waWxhdGlvbi5odG1sI3Rvb2xiYXItY29tcGlsYXRpb24gW2VuXUFkZGluZyBhIHRvb2xiYXJbL2VuXVtqYV3jg4Tjg7zjg6vjg5Djg7zjga7ov73liqBbL2phXVxuICogQHNlZWFsc28gb25zLWJvdHRvbS10b29sYmFyXG4gKiAgIFtlbl1UaGUgYDxvbnMtYm90dG9tLXRvb2xiYXI+YCBkaXNwbGF5cyBhIHRvb2xiYXIgb24gdGhlIGJvdHRvbSBvZiB0aGUgcGFnZS5bL2VuXVxuICogICBbamFdb25zLWJvdHRvbS10b29sYmFy44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1iYWNrLWJ1dHRvblxuICogICBbZW5dVGhlIGA8b25zLWJhY2stYnV0dG9uPmAgY29tcG9uZW50IGRpc3BsYXlzIGEgYmFjayBidXR0b24gaW5zaWRlIHRoZSB0b29sYmFyLlsvZW5dXG4gKiAgIFtqYV1vbnMtYmFjay1idXR0b27jgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLXRvb2xiYXItYnV0dG9uXG4gKiAgIFtlbl1UaGUgYDxvbnMtdG9vbGJhci1idXR0b24+YCBjb21wb25lbnQgZGlzcGxheXMgYSB0b29sYmFyIGJ1dHRvbiBpbnNpZGUgdGhlIHRvb2xiYXIuWy9lbl1cbiAqICAgW2phXW9ucy10b29sYmFyLWJ1dHRvbuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1wYWdlPlxuICogICA8b25zLXRvb2xiYXI+XG4gKiAgICAgPGRpdiBjbGFzcz1cImxlZnRcIj5cbiAqICAgICAgIDxvbnMtYmFjay1idXR0b24+XG4gKiAgICAgICAgIEJhY2tcbiAqICAgICAgIDwvb25zLWJhY2stYnV0dG9uPlxuICogICAgIDwvZGl2PlxuICogICAgIDxkaXYgY2xhc3M9XCJjZW50ZXJcIj5cbiAqICAgICAgIFRpdGxlXG4gKiAgICAgPC9kaXY+XG4gKiAgICAgPGRpdiBjbGFzcz1cInJpZ2h0XCI+XG4gKiAgICAgICA8b25zLXRvb2xiYXItYnV0dG9uPlxuICogICAgICAgICA8b25zLWljb24gaWNvbj1cIm1kLW1lbnVcIj48L29ucy1pY29uPlxuICogICAgICAgPC9vbnMtdG9vbGJhci1idXR0b24+XG4gKiAgICAgPC9kaXY+XG4gKiAgIDwvb25zLXRvb2xiYXI+XG4gKiA8L29ucy1wYWdlPlxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRvb2xiYXJFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGlubGluZVxuICAgKiBAaW5pdG9ubHlcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXURpc3BsYXkgdGhlIHRvb2xiYXIgYXMgYW4gaW5saW5lIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFd44OE44O844Or44OQ44O844KS44Kk44Oz44Op44Kk44Oz44Gr572u44GN44G+44GZ44CC44K544Kv44Ot44O844Or6aCY5Z+f5YaF44Gr44Gd44Gu44G+44G+6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc3RhdGljXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TdGF0aWMgdG9vbGJhcnMgYXJlIG5vdCBhbmltYXRlZCBieSBgb25zLW5hdmlnYXRvcmAgd2hlbiBwdXNoaW5nIG9yIHBvcHBpbmcgcGFnZXMuIFRoaXMgY2FuIGJlIHVzZWZ1bCB0byBpbXByb3ZlIHBlcmZvcm1hbmNlIGluIHNvbWUgc2l0dWF0aW9ucy5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIHRvb2xiYXIuWy9lbl1cbiAgICogICBbamFd44OE44O844Or44OQ44O844Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9jb21waWxlKCk7XG4gICAgfSk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllcicsICdjbGFzcyddO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBzd2l0Y2ggKG5hbWUpIHtcbiAgICAgIGNhc2UgJ2NsYXNzJzpcbiAgICAgICAgdXRpbC5yZXN0b3JlQ2xhc3ModGhpcywgZGVmYXVsdENsYXNzTmFtZSwgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdtb2RpZmllcic6XG4gICAgICAgIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCBzY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBzZXRWaXNpYmlsaXR5XG4gICAqIEBzaWduYXR1cmUgc2V0VmlzaWJpbGl0eSh2aXNpYmxlKVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IHZpc2libGVcbiAgICogICBbZW5dU2V0IHRvIHRydWUgdG8gc2hvdyB0aGUgdG9vbGJhciwgZmFsc2UgdG8gaGlkZSBpdFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TaG93cyB0aGUgdG9vbGJhciBpZiB2aXNpYmxlIGlzIHRydWUsIG90aGVyd2lzZSBoaWRlcyBpdC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgc2V0VmlzaWJpbGl0eSh2aXNpYmxlKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9IHZpc2libGUgPyAnJyA6ICdub25lJztcblxuICAgICAgaWYgKHRoaXMucGFyZW50Tm9kZSkge1xuICAgICAgICBjb25zdCBzaWJsaW5nQmFja2dyb3VuZCA9IHV0aWwuZmluZENoaWxkKHRoaXMucGFyZW50Tm9kZSwgJy5wYWdlX19iYWNrZ3JvdW5kJyk7XG4gICAgICAgIGlmIChzaWJsaW5nQmFja2dyb3VuZCkge1xuICAgICAgICAgIHNpYmxpbmdCYWNrZ3JvdW5kLnN0eWxlLnRvcCA9IHZpc2libGUgPyBudWxsIDogMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNpYmxpbmdDb250ZW50ID0gdXRpbC5maW5kQ2hpbGQodGhpcy5wYXJlbnROb2RlLCAnLnBhZ2VfX2NvbnRlbnQnKTtcbiAgICAgICAgaWYgKHNpYmxpbmdDb250ZW50KSB7XG4gICAgICAgICAgc2libGluZ0NvbnRlbnQuc3R5bGUudG9wID0gdmlzaWJsZSA/IG51bGwgOiAwO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBzaG93XG4gICAqIEBzaWduYXR1cmUgc2hvdygpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TaG93IHRoZSB0b29sYmFyLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBzaG93KCkge1xuICAgIHRoaXMuc2V0VmlzaWJpbGl0eSh0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGhpZGVcbiAgICogQHNpZ25hdHVyZSBoaWRlKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUhpZGUgdGhlIHRvb2xiYXIuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGhpZGUoKSB7XG4gICAgdGhpcy5zZXRWaXNpYmlsaXR5KGZhbHNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtIVE1MRWxlbWVudH1cbiAgICovXG4gIF9nZXRUb29sYmFyTGVmdEl0ZW1zRWxlbWVudCgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKCcubGVmdCcpIHx8IGludGVybmFsLm51bGxFbGVtZW50O1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0hUTUxFbGVtZW50fVxuICAgKi9cbiAgX2dldFRvb2xiYXJDZW50ZXJJdGVtc0VsZW1lbnQoKSB7XG4gICAgcmV0dXJuIHRoaXMucXVlcnlTZWxlY3RvcignLmNlbnRlcicpIHx8IGludGVybmFsLm51bGxFbGVtZW50O1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0hUTUxFbGVtZW50fVxuICAgKi9cbiAgX2dldFRvb2xiYXJSaWdodEl0ZW1zRWxlbWVudCgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKCcucmlnaHQnKSB8fCBpbnRlcm5hbC5udWxsRWxlbWVudDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtIVE1MRWxlbWVudH1cbiAgICovXG4gIF9nZXRUb29sYmFyQmFja0J1dHRvbkxhYmVsRWxlbWVudCgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKCdvbnMtYmFjay1idXR0b24gLmJhY2stYnV0dG9uX19sYWJlbCcpIHx8IGludGVybmFsLm51bGxFbGVtZW50O1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0hUTUxFbGVtZW50fVxuICAgKi9cbiAgX2dldFRvb2xiYXJCYWNrQnV0dG9uSWNvbkVsZW1lbnQoKSB7XG4gICAgcmV0dXJuIHRoaXMucXVlcnlTZWxlY3Rvcignb25zLWJhY2stYnV0dG9uIC5iYWNrLWJ1dHRvbl9faWNvbicpIHx8IGludGVybmFsLm51bGxFbGVtZW50O1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKGRlZmF1bHRDbGFzc05hbWUpO1xuICAgIHRoaXMuX2Vuc3VyZVRvb2xiYXJJdGVtRWxlbWVudHMoKTtcbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHNjaGVtZSk7XG4gIH1cblxuICBfZW5zdXJlVG9vbGJhckl0ZW1FbGVtZW50cygpIHtcbiAgICBmb3IgKGxldCBpID0gdGhpcy5jaGlsZE5vZGVzLmxlbmd0aCAtIDE7IGkgPj0gMCA7IGktLSkge1xuICAgICAgLy8gY2FzZSBvZiBub3QgZWxlbWVudFxuICAgICAgaWYgKHRoaXMuY2hpbGROb2Rlc1tpXS5ub2RlVHlwZSAhPSAxKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlQ2hpbGQodGhpcy5jaGlsZE5vZGVzW2ldKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBjZW50ZXIgPSB0aGlzLl9lbnN1cmVUb29sYmFyRWxlbWVudCgnY2VudGVyJyk7XG4gICAgY2VudGVyLmNsYXNzTGlzdC5hZGQoJ3Rvb2xiYXJfX3RpdGxlJyk7XG5cbiAgICBpZiAodGhpcy5jaGlsZHJlbi5sZW5ndGggIT09IDEgfHwgIXRoaXMuY2hpbGRyZW5bMF0uY2xhc3NMaXN0LmNvbnRhaW5zKCdjZW50ZXInKSkge1xuICAgICAgY29uc3QgbGVmdCA9IHRoaXMuX2Vuc3VyZVRvb2xiYXJFbGVtZW50KCdsZWZ0Jyk7XG4gICAgICBjb25zdCByaWdodCA9IHRoaXMuX2Vuc3VyZVRvb2xiYXJFbGVtZW50KCdyaWdodCcpO1xuXG4gICAgICBpZiAodGhpcy5jaGlsZHJlblswXSAhPT0gbGVmdCB8fCB0aGlzLmNoaWxkcmVuWzFdICE9PSBjZW50ZXIgfHwgdGhpcy5jaGlsZHJlblsyXSAhPT0gcmlnaHQpIHtcbiAgICAgICAgdGhpcy5hcHBlbmRDaGlsZChsZWZ0KTtcbiAgICAgICAgdGhpcy5hcHBlbmRDaGlsZChjZW50ZXIpO1xuICAgICAgICB0aGlzLmFwcGVuZENoaWxkKHJpZ2h0KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBfZW5zdXJlVG9vbGJhckVsZW1lbnQobmFtZSkge1xuICAgIGlmICh1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnRvb2xiYXJfXycgKyBuYW1lKSkge1xuICAgICAgY29uc3QgZWxlbWVudCA9IHV0aWwuZmluZENoaWxkKHRoaXMsICcudG9vbGJhcl9fJyArIG5hbWUpO1xuICAgICAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKG5hbWUpO1xuICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgY29uc3QgZWxlbWVudCA9IHV0aWwuZmluZENoaWxkKHRoaXMsICcuJyArIG5hbWUpIHx8IHV0aWwuY3JlYXRlKCcuJyArIG5hbWUpO1xuICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZCgndG9vbGJhcl9fJyArIG5hbWUpO1xuXG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cbn1cblxub25zRWxlbWVudHMuVG9vbGJhciA9IFRvb2xiYXJFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtdG9vbGJhcicsIFRvb2xiYXJFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uL29ucy9pbnRlcm5hbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIgZnJvbSAnLi4vb25zL2ludGVybmFsL2RldmljZS1iYWNrLWJ1dHRvbi1kaXNwYXRjaGVyJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5pbXBvcnQgJy4vb25zLXRvb2xiYXInOyAvLyBlbnN1cmVzIHRoYXQgJ29ucy10b29sYmFyJyBlbGVtZW50IGlzIHJlZ2lzdGVyZWRcblxuY29uc3QgZGVmYXVsdENsYXNzTmFtZSA9ICdwYWdlJztcbmNvbnN0IHNjaGVtZSA9IHtcbiAgJyc6ICdwYWdlLS0qJyxcbiAgJy5wYWdlX19jb250ZW50JzogJ3BhZ2UtLSpfX2NvbnRlbnQnLFxuICAnLnBhZ2VfX2JhY2tncm91bmQnOiAncGFnZS0tKl9fYmFja2dyb3VuZCdcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXBhZ2VcbiAqIEBjYXRlZ29yeSBwYWdlXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXU1hdGVyaWFsIERlc2lnbiBzdHlsZVsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBUaGlzIGNvbXBvbmVudCBkZWZpbmVzIHRoZSByb290IG9mIGVhY2ggcGFnZS4gSWYgdGhlIGNvbnRlbnQgaXMgbGFyZ2UgaXQgd2lsbCBiZWNvbWUgc2Nyb2xsYWJsZS5cbiAqXG4gKiAgICAgQSBuYXZpZ2F0aW9uIGJhciBjYW4gYmUgYWRkZWQgdG8gdGhlIHRvcCBvZiB0aGUgcGFnZSB1c2luZyB0aGUgYDxvbnMtdG9vbGJhcj5gIGVsZW1lbnQuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV3jg5rjg7zjgrjlrprnvqnjga7jgZ/jgoHjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjgafjgZnjgILjgZPjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7lhoXlrrnjga/jgrnjgq/jg63jg7zjg6vjgYzoqLHlj6/jgZXjgozjgb7jgZnjgIJbL2phXVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3BhZ2VcbiAqIEBndWlkZSBsaWZlY3ljbGUuaHRtbCNldmVudHNcbiAqICAgW2VuXU92ZXJ2aWV3IG9mIHBhZ2UgZXZlbnRzWy9lbl1cbiAqICAgW2phXU92ZXJ2aWV3IG9mIHBhZ2UgZXZlbnRzWy9qYV1cbiAqIEBndWlkZSBmdW5kYW1lbnRhbHMuaHRtbCNtYW5hZ2luZy1wYWdlc1xuICogICBbZW5dTWFuYWdpbmcgbXVsdGlwbGUgcGFnZXNbL2VuXVxuICogICBbamFd6KSH5pWw44Gu44Oa44O844K444KS566h55CG44GZ44KLWy9qYV1cbiAqIEBndWlkZSB0aGVtaW5nLmh0bWwjbW9kaWZpZXJzIFtlbl1Nb3JlIGRldGFpbHMgYWJvdXQgdGhlIGBtb2RpZmllcmAgYXR0cmlidXRlWy9lbl1bamFdbW9kaWZpZXLlsZ7mgKfjga7kvb/jgYTmlrlbL2phXVxuICogQHNlZWFsc28gb25zLXRvb2xiYXJcbiAqICAgW2VuXVVzZSB0aGUgYDxvbnMtdG9vbGJhcj5gIGVsZW1lbnQgdG8gYWRkIGEgbmF2aWdhdGlvbiBiYXIgdG8gdGhlIHRvcCBvZiB0aGUgcGFnZS5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXBhZ2U+XG4gKiAgIDxvbnMtdG9vbGJhcj5cbiAqICAgICA8ZGl2IGNsYXNzPVwibGVmdFwiPlxuICogICAgICAgPG9ucy1iYWNrLWJ1dHRvbj5CYWNrPC9vbnMtYmFjay1idXR0b24+XG4gKiAgICAgPC9kaXY+XG4gKiAgICAgPGRpdiBjbGFzcz1cImNlbnRlclwiPlRpdGxlPC9kaXY+XG4gKiAgICAgPGRpdiBjbGFzcz1cInJpZ2h0XCI+XG4gKiAgICAgICA8b25zLXRvb2xiYXItYnV0dG9uPlxuICogICAgICAgICA8b25zLWljb24gaWNvbj1cIm1kLW1lbnVcIj48L29ucy1pY29uPlxuICogICAgICAgPC9vbnMtdG9vbGJhci1idXR0b24+XG4gKiAgICAgPC9kaXY+XG4gKiAgIDwvb25zLXRvb2xiYXI+XG4gKlxuICogICA8cD5QYWdlIGNvbnRlbnQ8L3A+XG4gKiA8L29ucy1wYWdlPlxuICpcbiAqIEBleGFtcGxlXG4gKiA8c2NyaXB0PlxuICogICBteUFwcC5oYW5kbGVyID0gZnVuY3Rpb24oZG9uZSkge1xuICogICAgIGxvYWRNb3JlKCkudGhlbihkb25lKTtcbiAqICAgfVxuICogPC9zY3JpcHQ+XG4gKlxuICogPG9ucy1wYWdlIG9uLWluZmluaXRlLXNjcm9sbD1cIm15QXBwLmhhbmRsZXJcIj5cbiAqICAgPG9ucy10b29sYmFyPlxuICogICAgIDxkaXYgY2xhc3M9XCJjZW50ZXJcIj5MaXN0PC9kaXY+XG4gKiAgIDwvb25zLXRvb2xiYXI+XG4gKlxuICogICA8b25zLWxpc3Q+XG4gKiAgICAgPG9ucy1saXN0LWl0ZW0+IzE8L29ucy1saXN0LWl0ZW0+XG4gKiAgICAgPG9ucy1saXN0LWl0ZW0+IzI8L29ucy1saXN0LWl0ZW0+XG4gKiAgICAgPG9ucy1saXN0LWl0ZW0+IzM8L29ucy1saXN0LWl0ZW0+XG4gKiAgICAgLi4uXG4gKiAgIDwvb25zLWxpc3Q+XG4gKiA8L29ucy1wYWdlPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQYWdlRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGV2ZW50IGluaXRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHJpZ2h0IGFmdGVyIHRoZSBwYWdlIGlzIGF0dGFjaGVkLlsvZW5dXG4gICAqICAgW2phXeODmuODvOOCuOOBjOOCouOCv+ODg+ODgeOBleOCjOOBn+W+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgc2hvd1xuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQgcmlnaHQgYWZ0ZXIgdGhlIHBhZ2UgaXMgc2hvd24uWy9lbl1cbiAgICogICBbamFd44Oa44O844K444GM6KGo56S644GV44KM44Gf5b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBoaWRlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCByaWdodCBhZnRlciB0aGUgcGFnZSBpcyBoaWRkZW4uWy9lbl1cbiAgICogICBbamFd44Oa44O844K444GM6Zqg44KM44Gf5b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBkZXN0cm95XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCByaWdodCBiZWZvcmUgdGhlIHBhZ2UgaXMgZGVzdHJveWVkLlsvZW5dXG4gICAqICAgW2phXeODmuODvOOCuOOBjOegtOajhOOBleOCjOOCi+WJjeOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IG1vZGlmaWVyIG5hbWUgdG8gc3BlY2lmeSBjdXN0b20gc3R5bGVzLlsvZW5dXG4gICAqICAgW2phXeOCueOCv+OCpOODq+Wumue+qeOCkuOCq+OCueOCv+ODnuOCpOOCuuOBmeOCi+OBn+OCgeOBruWQjeWJjeOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG9uLWluZmluaXRlLXNjcm9sbFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUGF0aCBvZiB0aGUgZnVuY3Rpb24gdG8gYmUgZXhlY3V0ZWQgb24gaW5maW5pdGUgc2Nyb2xsaW5nLiBFeGFtcGxlOiBgYXBwLmxvYWREYXRhYC4gVGhlIGZ1bmN0aW9uIHJlY2VpdmVzIGEgZG9uZSBjYWxsYmFjayB0aGF0IG11c3QgYmUgY2FsbGVkIHdoZW4gaXQncyBmaW5pc2hlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fZGVyaXZlSG9va3MoKTtcblxuICAgIHRoaXMuX2RlZmF1bHRDbGFzc05hbWUgPSBkZWZhdWx0Q2xhc3NOYW1lO1xuICAgIHRoaXMuY2xhc3NMaXN0LmFkZChkZWZhdWx0Q2xhc3NOYW1lKTtcblxuICAgIHRoaXMuX2luaXRpYWxpemVkID0gZmFsc2U7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fY29tcGlsZSgpO1xuXG4gICAgICB0aGlzLl9pc1Nob3duID0gZmFsc2U7XG4gICAgICB0aGlzLl9jb250ZW50RWxlbWVudCA9IHRoaXMuX2dldENvbnRlbnRFbGVtZW50KCk7XG4gICAgICB0aGlzLl9iYWNrZ3JvdW5kRWxlbWVudCA9IHRoaXMuX2dldEJhY2tncm91bmRFbGVtZW50KCk7XG4gICAgfSk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIGNvbnN0IHRvb2xiYXIgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnb25zLXRvb2xiYXInKTtcblxuICAgIGNvbnN0IGJhY2tncm91bmQgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnBhZ2VfX2JhY2tncm91bmQnKSB8fCB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLmJhY2tncm91bmQnKSB8fCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBiYWNrZ3JvdW5kLmNsYXNzTGlzdC5hZGQoJ3BhZ2VfX2JhY2tncm91bmQnKTtcbiAgICB0aGlzLmluc2VydEJlZm9yZShiYWNrZ3JvdW5kLCAhdG9vbGJhciAmJiB0aGlzLmZpcnN0Q2hpbGQgfHwgdG9vbGJhciAmJiB0b29sYmFyLm5leHRTaWJsaW5nKTtcblxuICAgIGNvbnN0IGNvbnRlbnQgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnBhZ2VfX2NvbnRlbnQnKSB8fCB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLmNvbnRlbnQnKSB8fCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBjb250ZW50LmNsYXNzTGlzdC5hZGQoJ3BhZ2VfX2NvbnRlbnQnKTtcbiAgICBpZiAoIWNvbnRlbnQucGFyZW50RWxlbWVudCkge1xuICAgICAgdXRpbC5hcnJheUZyb20odGhpcy5jaGlsZE5vZGVzKS5mb3JFYWNoKG5vZGUgPT4ge1xuICAgICAgICBpZiAobm9kZS5ub2RlVHlwZSAhPT0gMSB8fCB0aGlzLl9lbGVtZW50U2hvdWxkQmVNb3ZlZChub2RlKSkge1xuICAgICAgICAgIGNvbnRlbnQuYXBwZW5kQ2hpbGQobm9kZSk7IC8vIENhbiB0cmlnZ2VyIGRldGFjaGVkIGNvbm5lY3RlZENhbGxiYWNrc1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLl90cnlUb0ZpbGxTdGF0dXNCYXIoY29udGVudCk7IC8vIE11c3QgcnVuIGJlZm9yZSBjaGlsZCBwYWdlcyB0cnkgdG8gZmlsbCBzdGF0dXMgYmFyLlxuICAgIHRoaXMuaW5zZXJ0QmVmb3JlKGNvbnRlbnQsIGJhY2tncm91bmQubmV4dFNpYmxpbmcpOyAvLyBDYW4gdHJpZ2dlciBhdHRhY2hlZCBjb25uZWN0ZWRDYWxsYmFja3NcblxuICAgIGlmICgoIXRvb2xiYXIgfHwgIXV0aWwuaGFzTW9kaWZpZXIodG9vbGJhciwgJ3RyYW5zcGFyZW50JykpXG4gICAgICAmJiBjb250ZW50LmNoaWxkcmVuLmxlbmd0aCA9PT0gMVxuICAgICAgJiYgdXRpbC5pc1BhZ2VDb250cm9sKGNvbnRlbnQuY2hpbGRyZW5bMF0pXG4gICAgKSB7XG4gICAgICB0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lICs9ICcgcGFnZS0td3JhcHBlcic7XG4gICAgICB0aGlzLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaygnY2xhc3MnKTtcbiAgICB9XG5cbiAgICBjb25zdCBib3R0b21Ub29sYmFyID0gdXRpbC5maW5kQ2hpbGQodGhpcywgJ29ucy1ib3R0b20tdG9vbGJhcicpO1xuICAgIGlmIChib3R0b21Ub29sYmFyKSB7XG4gICAgICB0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lICs9ICcgcGFnZS13aXRoLWJvdHRvbS10b29sYmFyJztcbiAgICAgIHRoaXMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKCdjbGFzcycpO1xuICAgIH1cblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIF9lbGVtZW50U2hvdWxkQmVNb3ZlZChlbCkge1xuICAgIGlmIChlbC5jbGFzc0xpc3QuY29udGFpbnMoJ3BhZ2VfX2JhY2tncm91bmQnKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCB0YWdOYW1lID0gZWwudGFnTmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgIGlmICh0YWdOYW1lID09PSAnb25zLWZhYicpIHtcbiAgICAgIHJldHVybiAhZWwuaGFzQXR0cmlidXRlKCdwb3NpdGlvbicpO1xuICAgIH1cbiAgICBjb25zdCBmaXhlZEVsZW1lbnRzID0gWydzY3JpcHQnLCAnb25zLXRvb2xiYXInLCAnb25zLWJvdHRvbS10b29sYmFyJywgJ29ucy1tb2RhbCcsICdvbnMtc3BlZWQtZGlhbCcsICdvbnMtZGlhbG9nJywgJ29ucy1hbGVydC1kaWFsb2cnLCAnb25zLXBvcG92ZXInLCAnb25zLWFjdGlvbi1zaGVldCddO1xuICAgIHJldHVybiBlbC5oYXNBdHRyaWJ1dGUoJ2lubGluZScpIHx8IGZpeGVkRWxlbWVudHMuaW5kZXhPZih0YWdOYW1lKSA9PT0gLTE7XG4gIH1cblxuICBfdHJ5VG9GaWxsU3RhdHVzQmFyKGNvbnRlbnQgPSB0aGlzLl9jb250ZW50RWxlbWVudCkge1xuICAgIGludGVybmFsLmF1dG9TdGF0dXNCYXJGaWxsKCgpID0+IHtcbiAgICAgIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdzdGF0dXMtYmFyLWZpbGwnLFxuICAgICAgICAhdXRpbC5maW5kUGFyZW50KHRoaXMsIGUgPT4gZS5oYXNBdHRyaWJ1dGUoJ3N0YXR1cy1iYXItZmlsbCcpKSAvLyBOb3QgYWxyZWFkeSBmaWxsZWRcbiAgICAgICAgJiYgKHRoaXMuX2NhbkFuaW1hdGVUb29sYmFyKGNvbnRlbnQpIHx8ICF1dGlsLmZpbmRDaGlsZChjb250ZW50LCB1dGlsLmlzUGFnZUNvbnRyb2wpKSAvLyBIYXMgdG9vbGJhciBvciBjYW5ub3QgZGVsZWdhdGVcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBfY2FuQW5pbWF0ZVRvb2xiYXIoY29udGVudCA9IHRoaXMuX2NvbnRlbnRFbGVtZW50KSB7XG4gICAgaWYgKHV0aWwuZmluZENoaWxkKHRoaXMsICdvbnMtdG9vbGJhcicpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gISF1dGlsLmZpbmRDaGlsZChjb250ZW50LCBlbCA9PiB7XG4gICAgICByZXR1cm4gdXRpbC5tYXRjaChlbCwgJ29ucy10b29sYmFyJykgJiYgIWVsLmhhc0F0dHJpYnV0ZSgnaW5saW5lJyk7XG4gICAgfSk7XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBpZiAoIXV0aWwuaXNBdHRhY2hlZCh0aGlzKSkgeyAvLyBBdm9pZCBkZXRhY2hlZCBjYWxsc1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl90cnlUb0ZpbGxTdGF0dXNCYXIoKTsgLy8gRW5zdXJlIHN0YXR1cyBiYXIgd2hlbiB0aGUgZWxlbWVudCB3YXMgY29tcGlsZWQgYmVmb3JlIGNvbm5lY3RlZFxuXG4gICAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ29uLWluZmluaXRlLXNjcm9sbCcpKSB7XG4gICAgICAgIHRoaXMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKCdvbi1pbmZpbml0ZS1zY3JvbGwnLCBudWxsLCB0aGlzLmdldEF0dHJpYnV0ZSgnb24taW5maW5pdGUtc2Nyb2xsJykpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXRoaXMuX2luaXRpYWxpemVkKSB7XG4gICAgICAgIHRoaXMuX2luaXRpYWxpemVkID0gdHJ1ZTtcblxuICAgICAgICBzZXRJbW1lZGlhdGUoKCkgPT4ge1xuICAgICAgICAgIHRoaXMub25Jbml0ICYmIHRoaXMub25Jbml0KCk7XG4gICAgICAgICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdpbml0Jyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICghdXRpbC5oYXNBbnlDb21wb25lbnRBc1BhcmVudCh0aGlzKSkge1xuICAgICAgICAgIHNldEltbWVkaWF0ZSgoKSA9PiB0aGlzLl9zaG93KCkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICB1cGRhdGVCYWNrQnV0dG9uKHNob3cpIHtcbiAgICBpZiAodGhpcy5iYWNrQnV0dG9uKSB7XG4gICAgICBzaG93ID8gdGhpcy5iYWNrQnV0dG9uLnNob3coKSA6IHRoaXMuYmFja0J1dHRvbi5oaWRlKCk7XG4gICAgfVxuICB9XG5cbiAgc2V0IG5hbWUoc3RyKSB7XG4gICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ25hbWUnLCBzdHIpO1xuICB9XG5cbiAgZ2V0IG5hbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QXR0cmlidXRlKCduYW1lJyk7XG4gIH1cblxuICBnZXQgYmFja0J1dHRvbigpIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKCdvbnMtYmFjay1idXR0b24nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb25JbmZpbml0ZVNjcm9sbFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1GdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuIHNjcm9sbGluZyB0byB0aGUgYm90dG9tIG9mIHRoZSBwYWdlLiBUaGUgZnVuY3Rpb24gcmVjZWl2ZXMgYSBkb25lIGNhbGxiYWNrIGFzIGFuIGFyZ3VtZW50IHRoYXQgbXVzdCBiZSBjYWxsZWQgd2hlbiBpdCdzIGZpbmlzaGVkLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG4gIHNldCBvbkluZmluaXRlU2Nyb2xsKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICYmICEodmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHV0aWwudGhyb3coJ1wib25JbmZpbml0ZVNjcm9sbFwiIG11c3QgYmUgZnVuY3Rpb24gb3IgbnVsbCcpO1xuICAgIH1cblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICBpZiAoIXZhbHVlKSB7XG4gICAgICAgIHRoaXMuX2NvbnRlbnRFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuX2JvdW5kT25TY3JvbGwpO1xuICAgICAgfSBlbHNlIGlmICghdGhpcy5fb25JbmZpbml0ZVNjcm9sbCkge1xuICAgICAgICB0aGlzLl9pbmZpbml0ZVNjcm9sbExpbWl0ID0gMC45O1xuICAgICAgICB0aGlzLl9ib3VuZE9uU2Nyb2xsID0gdGhpcy5fb25TY3JvbGwuYmluZCh0aGlzKTtcbiAgICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHRoaXMuX2NvbnRlbnRFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuX2JvdW5kT25TY3JvbGwpKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX29uSW5maW5pdGVTY3JvbGwgPSB2YWx1ZTtcbiAgICB9KTtcbiAgfVxuXG4gIGdldCBvbkluZmluaXRlU2Nyb2xsKCkge1xuICAgIHJldHVybiB0aGlzLl9vbkluZmluaXRlU2Nyb2xsO1xuICB9XG5cbiAgX29uU2Nyb2xsKCkge1xuICAgIGNvbnN0IGMgPSB0aGlzLl9jb250ZW50RWxlbWVudCxcbiAgICAgIG92ZXJMaW1pdCA9IChjLnNjcm9sbFRvcCArIGMuY2xpZW50SGVpZ2h0KSAvIGMuc2Nyb2xsSGVpZ2h0ID49IHRoaXMuX2luZmluaXRlU2Nyb2xsTGltaXQ7XG5cbiAgICBpZiAodGhpcy5fb25JbmZpbml0ZVNjcm9sbCAmJiAhdGhpcy5fbG9hZGluZ0NvbnRlbnQgJiYgb3ZlckxpbWl0KSB7XG4gICAgICB0aGlzLl9sb2FkaW5nQ29udGVudCA9IHRydWU7XG4gICAgICB0aGlzLl9vbkluZmluaXRlU2Nyb2xsKCgpID0+IHRoaXMuX2xvYWRpbmdDb250ZW50ID0gZmFsc2UpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb25EZXZpY2VCYWNrQnV0dG9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1CYWNrLWJ1dHRvbiBoYW5kbGVyLlsvZW5dXG4gICAqICAgW2phXeODkOODg+OCr+ODnOOCv+ODs+ODj+ODs+ODieODqeOAglsvamFdXG4gICAqL1xuICBnZXQgb25EZXZpY2VCYWNrQnV0dG9uKCkge1xuICAgIHJldHVybiB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlcjtcbiAgfVxuXG4gIHNldCBvbkRldmljZUJhY2tCdXR0b24oY2FsbGJhY2spIHtcbiAgICBpZiAodGhpcy5fYmFja0J1dHRvbkhhbmRsZXIpIHtcbiAgICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyLmRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlciA9IGRldmljZUJhY2tCdXR0b25EaXNwYXRjaGVyLmNyZWF0ZUhhbmRsZXIodGhpcywgY2FsbGJhY2spO1xuICB9XG5cbiAgZ2V0IHNjcm9sbFRvcCgpIHtcbiAgICByZXR1cm4gdGhpcy5fY29udGVudEVsZW1lbnQuc2Nyb2xsVG9wO1xuICB9XG5cbiAgc2V0IHNjcm9sbFRvcChuZXdWYWx1ZSkge1xuICAgIHRoaXMuX2NvbnRlbnRFbGVtZW50LnNjcm9sbFRvcCA9IG5ld1ZhbHVlO1xuICB9XG5cbiAgX2dldENvbnRlbnRFbGVtZW50KCkge1xuICAgIGNvbnN0IHJlc3VsdCA9IHV0aWwuZmluZENoaWxkKHRoaXMsICcucGFnZV9fY29udGVudCcpO1xuICAgIGlmIChyZXN1bHQpIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICAgIHV0aWwudGhyb3coJ0ZhaWwgdG8gZ2V0IFwiLnBhZ2VfX2NvbnRlbnRcIiBlbGVtZW50Jyk7XG4gIH1cblxuICBfZ2V0QmFja2dyb3VuZEVsZW1lbnQoKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gdXRpbC5maW5kQ2hpbGQodGhpcywgJy5wYWdlX19iYWNrZ3JvdW5kJyk7XG4gICAgaWYgKHJlc3VsdCkge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gICAgdXRpbC50aHJvdygnRmFpbCB0byBnZXQgXCIucGFnZV9fYmFja2dyb3VuZFwiIGVsZW1lbnQnKTtcbiAgfVxuXG4gIF9nZXRCb3R0b21Ub29sYmFyRWxlbWVudCgpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJ29ucy1ib3R0b20tdG9vbGJhcicpIHx8IGludGVybmFsLm51bGxFbGVtZW50O1xuICB9XG5cbiAgX2dldFRvb2xiYXJFbGVtZW50KCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnb25zLXRvb2xiYXInKSB8fCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdvbnMtdG9vbGJhcicpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnb24taW5maW5pdGUtc2Nyb2xsJywgJ2NsYXNzJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnY2xhc3MnOlxuICAgICAgICB1dGlsLnJlc3RvcmVDbGFzcyh0aGlzLCB0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lLCBzY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ21vZGlmaWVyJzpcbiAgICAgICAgTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnb24taW5maW5pdGUtc2Nyb2xsJzpcbiAgICAgICAgaWYgKGN1cnJlbnQgPT09IG51bGwpIHtcbiAgICAgICAgICB0aGlzLm9uSW5maW5pdGVTY3JvbGwgPSBudWxsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMub25JbmZpbml0ZVNjcm9sbCA9IChkb25lKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBmID0gdXRpbC5maW5kRnJvbVBhdGgoY3VycmVudCk7XG4gICAgICAgICAgICB0aGlzLm9uSW5maW5pdGVTY3JvbGwgPSBmO1xuICAgICAgICAgICAgZihkb25lKTtcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIF9zaG93KCkge1xuICAgIGlmICghdGhpcy5faXNTaG93biAmJiB1dGlsLmlzQXR0YWNoZWQodGhpcykpIHtcbiAgICAgIHRoaXMuX2lzU2hvd24gPSB0cnVlO1xuICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ3Nob3duJywgJycpO1xuICAgICAgdGhpcy5vblNob3cgJiYgdGhpcy5vblNob3coKTtcbiAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnc2hvdycpO1xuICAgICAgdXRpbC5wcm9wYWdhdGVBY3Rpb24odGhpcywgJ19zaG93Jyk7XG4gICAgfVxuICB9XG5cbiAgX2hpZGUoKSB7XG4gICAgaWYgKHRoaXMuX2lzU2hvd24pIHtcbiAgICAgIHRoaXMuX2lzU2hvd24gPSBmYWxzZTtcbiAgICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlKCdzaG93bicpO1xuICAgICAgdGhpcy5vbkhpZGUgJiYgdGhpcy5vbkhpZGUoKTtcbiAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnaGlkZScpO1xuICAgICAgdXRpbC5wcm9wYWdhdGVBY3Rpb24odGhpcywgJ19oaWRlJyk7XG4gICAgfVxuICB9XG5cbiAgX2Rlc3Ryb3koKSB7XG4gICAgdGhpcy5faGlkZSgpO1xuXG4gICAgdGhpcy5vbkRlc3Ryb3kgJiYgdGhpcy5vbkRlc3Ryb3koKTtcbiAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ2Rlc3Ryb3knKTtcblxuICAgIGlmICh0aGlzLm9uRGV2aWNlQmFja0J1dHRvbikge1xuICAgICAgdGhpcy5vbkRldmljZUJhY2tCdXR0b24uZGVzdHJveSgpO1xuICAgIH1cblxuICAgIHV0aWwucHJvcGFnYXRlQWN0aW9uKHRoaXMsICdfZGVzdHJveScpO1xuXG4gICAgdGhpcy5yZW1vdmUoKTtcbiAgfVxuXG4gIF9kZXJpdmVIb29rcygpIHtcbiAgICB0aGlzLmNvbnN0cnVjdG9yLmV2ZW50cy5mb3JFYWNoKGV2ZW50ID0+IHtcbiAgICAgIGNvbnN0IGtleSA9ICdvbicgKyBldmVudC5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIGV2ZW50LnNsaWNlKDEpO1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIGtleSwge1xuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGdldDogKCkgPT4gdGhpc1tgXyR7a2V5fWBdLFxuICAgICAgICBzZXQ6IHZhbHVlID0+IHtcbiAgICAgICAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSkge1xuICAgICAgICAgICAgdXRpbC50aHJvdyhgXCIke2tleX1cIiBob29rIG11c3QgYmUgYSBmdW5jdGlvbmApO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzW2BfJHtrZXl9YF0gPSB2YWx1ZS5iaW5kKHRoaXMpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgZXZlbnRzKCkge1xuICAgIHJldHVybiBbJ2luaXQnLCAnc2hvdycsICdoaWRlJywgJ2Rlc3Ryb3knXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGF0YVxuICAgKiBAdHlwZSB7Kn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVVzZXIncyBjdXN0b20gZGF0YSBwYXNzZWQgdG8gYHB1c2hQYWdlKClgLWxpa2UgbWV0aG9kcy5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbn1cblxub25zRWxlbWVudHMuUGFnZSA9IFBhZ2VFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtcGFnZScsIFBhZ2VFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuaW1wb3J0IEJhc2VBbmltYXRvciBmcm9tICcuLi8uLi9vbnMvYmFzZS1hbmltYXRvcic7XG5cbmV4cG9ydCBjbGFzcyBQb3BvdmVyQW5pbWF0b3IgZXh0ZW5kcyBCYXNlQW5pbWF0b3Ige1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICAgKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy50aW1pbmdcbiAgICogQHBhcmFtIHtOdW1iZXJ9IG9wdGlvbnMuZHVyYXRpb25cbiAgICogQHBhcmFtIHtOdW1iZXJ9IG9wdGlvbnMuZGVsYXlcbiAgICovXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnY3ViaWMtYmV6aWVyKC4xLCAuNywgLjQsIDEpJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuMn0gPSB7fSkge1xuICAgIHN1cGVyKHsgdGltaW5nLCBkZWxheSwgZHVyYXRpb24gfSk7XG4gIH1cblxuICBzaG93KHBvcG92ZXIsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIGhpZGUocG9wb3ZlciwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjaygpO1xuICB9XG5cbiAgX2FuaW1hdGUoZWxlbWVudCwge2Zyb20sIHRvLCBvcHRpb25zLCBjYWxsYmFjaywgcmVzdG9yZSA9IGZhbHNlLCBhbmltYXRpb259KSB7XG4gICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHt9LCB0aGlzLm9wdGlvbnMsIG9wdGlvbnMpO1xuXG4gICAgaWYgKGFuaW1hdGlvbikge1xuICAgICAgZnJvbSA9IGFuaW1hdGlvbi5mcm9tO1xuICAgICAgdG8gPSBhbmltYXRpb24udG87XG4gICAgfVxuXG4gICAgYW5pbWF0aW9uID0gYW5pbWl0KGVsZW1lbnQpO1xuICAgIGlmIChyZXN0b3JlKSB7XG4gICAgICBhbmltYXRpb24gPSBhbmltYXRpb24uc2F2ZVN0eWxlKCk7XG4gICAgfVxuICAgIGFuaW1hdGlvbiA9IGFuaW1hdGlvbi5xdWV1ZShmcm9tKS53YWl0KHRoaXMuZGVsYXkpLnF1ZXVlKHtcbiAgICAgIGNzczogdG8sXG4gICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICB9KTtcbiAgICBpZiAocmVzdG9yZSkge1xuICAgICAgYW5pbWF0aW9uID0gYW5pbWF0aW9uLnJlc3RvcmVTdHlsZSgpO1xuICAgIH1cbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIGFuaW1hdGlvbiA9IGFuaW1hdGlvbi5xdWV1ZSgoZG9uZSkgPT4ge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICBkb25lKCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGFuaW1hdGlvbjtcbiAgfVxuXG4gIF9hbmltYXRlQWxsKGVsZW1lbnQsIGFuaW1hdGlvbnMpIHtcbiAgICBPYmplY3Qua2V5cyhhbmltYXRpb25zKS5mb3JFYWNoKGtleSA9PiB0aGlzLl9hbmltYXRlKGVsZW1lbnRba2V5XSwgYW5pbWF0aW9uc1trZXldKS5wbGF5KCkpO1xuICB9XG5cbn1cblxuY29uc3QgZmFkZSA9IHtcbiAgb3V0OiB7XG4gICAgZnJvbToge29wYWNpdHk6IDEuMH0sXG4gICAgdG86IHtvcGFjaXR5OiAwfVxuICB9LFxuICBpbjoge1xuICAgIGZyb206IHtvcGFjaXR5OiAwfSxcbiAgICB0bzoge29wYWNpdHk6IDEuMH1cbiAgfVxufTtcblxuZXhwb3J0IGNsYXNzIE1ERmFkZVBvcG92ZXJBbmltYXRvciBleHRlbmRzIFBvcG92ZXJBbmltYXRvciB7XG4gIHNob3cocG9wb3ZlciwgY2FsbGJhY2spIHtcbiAgICB0aGlzLl9hbmltYXRlQWxsKHBvcG92ZXIsIHtcbiAgICAgIF9tYXNrOiBmYWRlLmluLFxuICAgICAgX3BvcG92ZXI6IHthbmltYXRpb246IGZhZGUuaW4sIHJlc3RvcmU6IHRydWUsIGNhbGxiYWNrfVxuICAgIH0pO1xuICB9XG5cbiAgaGlkZShwb3BvdmVyLCBjYWxsYmFjaykge1xuICAgIHRoaXMuX2FuaW1hdGVBbGwocG9wb3Zlciwge1xuICAgICAgX21hc2s6IGZhZGUub3V0LFxuICAgICAgX3BvcG92ZXI6IHthbmltYXRpb246IGZhZGUub3V0LCByZXN0b3JlOiB0cnVlLCBjYWxsYmFja31cbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgSU9TRmFkZVBvcG92ZXJBbmltYXRvciBleHRlbmRzIE1ERmFkZVBvcG92ZXJBbmltYXRvciB7XG4gIHNob3cocG9wb3ZlciwgY2FsbGJhY2spIHtcbiAgICB0aGlzLl9hbmltYXRlQWxsKHBvcG92ZXIsIHtcbiAgICAgIF9tYXNrOiBmYWRlLmluLFxuICAgICAgX3BvcG92ZXI6IHtcbiAgICAgICAgZnJvbToge1xuICAgICAgICAgIHRyYW5zZm9ybTogJ3NjYWxlM2QoMS4zLCAxLjMsIDEuMCknLFxuICAgICAgICAgIG9wYWNpdHk6IDBcbiAgICAgICAgfSxcbiAgICAgICAgdG86IHtcbiAgICAgICAgICB0cmFuc2Zvcm06ICdzY2FsZTNkKDEuMCwgMS4wLCAgMS4wKScsXG4gICAgICAgICAgb3BhY2l0eTogMS4wXG4gICAgICAgIH0sXG4gICAgICAgIHJlc3RvcmU6IHRydWUsXG4gICAgICAgIGNhbGxiYWNrXG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi8uLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi8uLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEFuaW1hdG9yRmFjdG9yeSBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvYW5pbWF0b3ItZmFjdG9yeSc7XG5pbXBvcnQgeyBQb3BvdmVyQW5pbWF0b3IsIElPU0ZhZGVQb3BvdmVyQW5pbWF0b3IsIE1ERmFkZVBvcG92ZXJBbmltYXRvciB9IGZyb20gJy4vYW5pbWF0b3InO1xuaW1wb3J0IHBsYXRmb3JtIGZyb20gJy4uLy4uL29ucy9wbGF0Zm9ybSc7XG5pbXBvcnQgaVBob25lWFBhdGNoIGZyb20gJy4uLy4uL29ucy9pcGhvbmV4LXBhdGNoJztcbmltcG9ydCBCYXNlRGlhbG9nRWxlbWVudCBmcm9tICcuLi9iYXNlL2Jhc2UtZGlhbG9nJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBzY2hlbWUgPSB7XG4gICcucG9wb3Zlcic6ICdwb3BvdmVyLS0qJyxcbiAgJy5wb3BvdmVyLW1hc2snOiAncG9wb3Zlci1tYXNrLS0qJyxcbiAgJy5wb3BvdmVyX19jb250ZW50JzogJ3BvcG92ZXItLSpfX2NvbnRlbnQnLFxuICAnLnBvcG92ZXJfX2Fycm93JzogJ3BvcG92ZXItLSpfX2Fycm93J1xufTtcblxuY29uc3QgX2FuaW1hdG9yRGljdCA9IHtcbiAgJ2RlZmF1bHQnOiAoKSA9PiBwbGF0Zm9ybS5pc0FuZHJvaWQoKSA/IE1ERmFkZVBvcG92ZXJBbmltYXRvciA6IElPU0ZhZGVQb3BvdmVyQW5pbWF0b3IsXG4gICdub25lJzogUG9wb3ZlckFuaW1hdG9yLFxuICAnZmFkZS1pb3MnOiBJT1NGYWRlUG9wb3ZlckFuaW1hdG9yLFxuICAnZmFkZS1tZCc6IE1ERmFkZVBvcG92ZXJBbmltYXRvclxufTtcblxuY29uc3QgcG9zaXRpb25zID0ge1xuICB1cDogJ2JvdHRvbScsXG4gIGxlZnQ6ICdyaWdodCcsXG4gIGRvd246ICd0b3AnLFxuICByaWdodDogJ2xlZnQnXG59O1xuXG5jb25zdCBkaXJlY3Rpb25zID0gT2JqZWN0LmtleXMocG9zaXRpb25zKTtcbi8qKlxuICogQGVsZW1lbnQgb25zLXBvcG92ZXJcbiAqIEBjYXRlZ29yeSBkaWFsb2dcbiAqIEBkZXNjcmlwdGlvblxuICogIFtlbl1cbiAqICAgIEEgY29tcG9uZW50IHRoYXQgZGlzcGxheXMgYSBwb3BvdmVyIG5leHQgdG8gYW4gZWxlbWVudC4gVGhlIHBvcG92ZXIgY2FuIGJlIHVzZWQgdG8gZGlzcGxheSBleHRyYSBpbmZvcm1hdGlvbiBhYm91dCBhIGNvbXBvbmVudCBvciBhIHRvb2x0aXAuXG4gKlxuICogICAgVG8gdXNlIHRoZSBlbGVtZW50IGl0IGNhbiBlaXRoZXIgYmUgYXR0YWNoZWQgZGlyZWN0bHkgdG8gdGhlIGA8Ym9keT5gIGVsZW1lbnQgb3IgZHluYW1pY2FsbHkgY3JlYXRlZCBmcm9tIGEgdGVtcGxhdGUgdXNpbmcgdGhlIGBvbnMuY3JlYXRlUG9wb3Zlcih0ZW1wbGF0ZSlgIHV0aWxpdHkgZnVuY3Rpb24gYW5kIHRoZSBgPHRlbXBsYXRlPmAgdGFnLlxuICpcbiAqICAgIEFub3RoZXIgY29tbW9uIHdheSB0byB1c2UgdGhlIHBvcG92ZXIgaXMgdG8gZGlzcGxheSBhIG1lbnUgd2hlbiBhIGJ1dHRvbiBvbiB0aGUgc2NyZWVuIGlzIHRhcHBlZC4gRm9yIE1hdGVyaWFsIERlc2lnbiwgcG9wb3ZlciBsb29rcyBleGFjdGx5IGFzIGEgZHJvcGRvd24gbWVudS5cbiAqICBbL2VuXVxuICogIFtqYV3jgYLjgovopoHntKDjgpLlr77osaHjgajjgZnjgovjg53jg4Pjg5fjgqrjg7zjg5Djg7zjgpLooajnpLrjgZnjgovjgrPjg7Pjg53jg7zjg43jg7Pjg4jjgafjgZnjgIJbL2phXVxuICogQGNvZGVwZW4gWllZUktvXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvcG9wb3ZlclxuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNtb2RpZmllcnMgW2VuXU1vcmUgZGV0YWlscyBhYm91dCB0aGUgYG1vZGlmaWVyYCBhdHRyaWJ1dGVbL2VuXVtqYV1tb2RpZmllcuWxnuaAp+OBruS9v+OBhOaWuVsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1idXR0b24gb25jbGljaz1cInNob3dQb3BvdmVyKHRoaXMpXCI+XG4gKiAgIENsaWNrIG1lIVxuICogPC9vbnMtYnV0dG9uPlxuICpcbiAqIDxvbnMtcG9wb3ZlciBkaXJlY3Rpb249XCJkb3duXCIgaWQ9XCJwb3BvdmVyXCI+XG4gKiAgIDxwPlRoaXMgaXMgYSBwb3BvdmVyITwvcD5cbiAqIDwvb25zLXBvcG92ZXI+XG4gKlxuICogPHNjcmlwdD5cbiAqICAgdmFyIHNob3dQb3BvdmVyID0gZnVuY3Rpb24oZWxlbWVudCkge1xuICogICAgIHZhciBwb3BvdmVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3BvcG92ZXInKTtcbiAqICAgICBwb3BvdmVyLnNob3coZWxlbWVudCk7XG4gKiAgIH07XG4gKiA8L3NjcmlwdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUG9wb3ZlckVsZW1lbnQgZXh0ZW5kcyBCYXNlRGlhbG9nRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBldmVudCBwcmVzaG93XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGJlZm9yZSB0aGUgcG9wb3ZlciBpcyBkaXNwbGF5ZWQuWy9lbl1cbiAgICogICBbamFd44Od44OD44OX44Kq44O844OQ44O844GM6KGo56S644GV44KM44KL55u05YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnBvcG92ZXJcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC5jYW5jZWxcbiAgICogICBbZW5dQ2FsbCB0aGlzIGZ1bmN0aW9uIHRvIHN0b3AgdGhlIHBvcG92ZXIgZnJvbSBiZWluZyBzaG93bi5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7plqLmlbDjgpLlkbzjgbPlh7rjgZnjgajjgIHjg53jg4Pjg5fjgqrjg7zjg5Djg7zjga7ooajnpLrjgYzjgq3jg6Pjg7Pjgrvjg6vjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHBvc3RzaG93XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGFmdGVyIHRoZSBwb3BvdmVyIGlzIGRpc3BsYXllZC5bL2VuXVxuICAgKiAgIFtqYV3jg53jg4Pjg5fjgqrjg7zjg5Djg7zjgYzooajnpLrjgZXjgozjgZ/nm7TlvozjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQucG9wb3ZlclxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlaGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQganVzdCBiZWZvcmUgdGhlIHBvcG92ZXIgaXMgaGlkZGVuLlsvZW5dXG4gICAqICAgW2phXeODneODg+ODl+OCquODvOODkOODvOOBjOmaoOOCjOOCi+ebtOWJjeOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5wb3BvdmVyXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUNhbGwgdGhpcyBmdW5jdGlvbiB0byBzdG9wIHRoZSBwb3BvdmVyIGZyb20gYmVpbmcgaGlkZGVuLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWRvOOBs+WHuuOBmeOBqOOAgeODneODg+ODl+OCquODvOODkOODvOOBjOmaoOOCjOOCi+WHpueQhuOCkuOCreODo+ODs+OCu+ODq+OBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdGhpZGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIHBvcG92ZXIgaXMgaGlkZGVuLlsvZW5dXG4gICAqICAgW2phXeODneODg+ODl+OCquODvOODkOODvOOBjOmaoOOCjOOBn+W+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5wb3BvdmVyXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIHBvcG92ZXIuWy9lbl1cbiAgICogIFtqYV3jg53jg4Pjg5fjgqrjg7zjg5Djg7zjga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXJlY3Rpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dXG4gICAqICAgIEEgc3BhY2Ugc2VwYXJhdGVkIGxpc3Qgb2YgZGlyZWN0aW9ucy4gSWYgbW9yZSB0aGFuIG9uZSBkaXJlY3Rpb24gaXMgc3BlY2lmaWVkLFxuICAgKiAgICBpdCB3aWxsIGJlIGNob3NlbiBhdXRvbWF0aWNhbGx5LiBWYWxpZCBkaXJlY3Rpb25zIGFyZSBgXCJ1cFwiYCwgYFwiZG93blwiYCwgYFwibGVmdFwiYCBhbmQgYFwicmlnaHRcImAuXG4gICAqICBbL2VuXVxuICAgKiAgW2phXVxuICAgKiAgICDjg53jg4Pjg5fjgqrjg7zjg5Djg7zjgpLooajnpLrjgZnjgovmlrnlkJHjgpLnqbrnmb3ljLrliIfjgorjgafopIfmlbDmjIflrprjgafjgY3jgb7jgZnjgIJcbiAgICogICAg5oyH5a6a44Gn44GN44KL5pa55ZCR44Gv44CBXCJ1cFwiLCBcImRvd25cIiwgXCJsZWZ0XCIsIFwicmlnaHRcIuOBrjTjgaTjgafjgZnjgILnqbrnmb3ljLrliIfjgorjgafopIfmlbDmjIflrprjgZnjgovjgZPjgajjgoLjgafjgY3jgb7jgZnjgIJcbiAgICogICAg6KSH5pWw5oyH5a6a44GV44KM44Gf5aC05ZCI44CB5a++6LGh44Go44GZ44KL6KaB57Sg44Gr5ZCI44KP44Gb44Gm5oyH5a6a44GX44Gf5YCk44GL44KJ6Ieq5YuV55qE44Gr6YG45oqe44GV44KM44G+44GZ44CCXG4gICAqICBbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBjYW5jZWxhYmxlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIHBvcG92ZXIgY2FuIGJlIGNsb3NlZCBieSB0YXBwaW5nIHRoZSBiYWNrZ3JvdW5kIG9yIGJ5IHByZXNzaW5nIHRoZSBiYWNrIGJ1dHRvbi5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovjgajjgIHjg53jg4Pjg5fjgqrjg7zjg5Djg7zjgYzooajnpLrjgZXjgozjgZ/mmYLjgavjgIHog4zmma/jgoTjg5Djg4Pjgq/jg5zjgr/jg7PjgpLjgr/jg4Pjg5fjgZfjgZ/mmYLjgavjgpLjg53jg4Pjg5fjgqrjg7zjg5Djg7zplonjgZjjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBjb3Zlci10YXJnZXRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUlmIHNldCB0aGUgcG9wb3ZlciB3aWxsIGNvdmVyIHRoZSB0YXJnZXQgb24gdGhlIHNjcmVlbi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhbmltYXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhbmltYXRpb24gdXNlZCB3aGVuIHNob3dpbmcgYW4gaGlkaW5nIHRoZSBwb3BvdmVyLiBDYW4gYmUgZWl0aGVyIGBcIm5vbmVcImAsIGBcImRlZmF1bHRcImAsIGBcImZhZGUtaW9zXCJgIG9yIGBcImZhZGUtbWRcImAuWy9lbl1cbiAgICogICBbamFd44Od44OD44OX44Kq44O844OQ44O844KS6KGo56S644GZ44KL6Zqb44Gu44Ki44OL44Oh44O844K344On44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uLW9wdGlvbnNcbiAgICogQHR5cGUge0V4cHJlc3Npb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCB0aW1pbmcgYW5kIGRlbGF5IHdpdGggYW4gb2JqZWN0IGxpdGVyYWwuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCB0aW1pbmcsIGRlbGF544KS44Kq44OW44K444Kn44Kv44OI44Oq44OG44Op44Or44Gn5oyH5a6a44GX44G+44GZ44CCZS5nLiB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1hc2stY29sb3JcbiAgICogQHR5cGUge0NvbG9yfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ29sb3Igb2YgdGhlIGJhY2tncm91bmQgbWFzay4gRGVmYXVsdCBpcyBgXCJyZ2JhKDAsIDAsIDAsIDAuMilcImAuWy9lbl1cbiAgICogICBbamFd6IOM5pmv44Gu44Oe44K544Kv44Gu6Imy44KS5oyH5a6a44GX44G+44GZ44CC44OH44OV44Kp44Or44OI44GvXCJyZ2JhKDAsIDAsIDAsIDAuMilcIuOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9ib3VuZE9uQ2hhbmdlID0gdGhpcy5fb25DaGFuZ2UuYmluZCh0aGlzKTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9jb21waWxlKCk7XG4gICAgICB0aGlzLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgfSk7XG4gIH1cblxuICBnZXQgX3NjaGVtZSgpIHtcbiAgICByZXR1cm4gc2NoZW1lO1xuICB9XG5cbiAgZ2V0IF9tYXNrKCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnBvcG92ZXItbWFzaycpO1xuICB9XG5cbiAgZ2V0IF9wb3BvdmVyKCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnBvcG92ZXInKTtcbiAgfVxuXG4gIGdldCBfY29udGVudCgpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcy5fcG9wb3ZlciwgJy5wb3BvdmVyX19jb250ZW50Jyk7XG4gIH1cblxuICBnZXQgX2Fycm93KCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLl9wb3BvdmVyLCAnLnBvcG92ZXJfX2Fycm93Jyk7XG4gIH1cblxuICBfdXBkYXRlQW5pbWF0b3JGYWN0b3J5KCkge1xuICAgIHJldHVybiBuZXcgQW5pbWF0b3JGYWN0b3J5KHtcbiAgICAgIGFuaW1hdG9yczogX2FuaW1hdG9yRGljdCxcbiAgICAgIGJhc2VDbGFzczogUG9wb3ZlckFuaW1hdG9yLFxuICAgICAgYmFzZUNsYXNzTmFtZTogJ1BvcG92ZXJBbmltYXRvcicsXG4gICAgICBkZWZhdWx0QW5pbWF0aW9uOiB0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uJykgfHwgJ2RlZmF1bHQnXG4gICAgfSk7XG4gIH1cblxuICBfdG9nZ2xlU3R5bGUoc2hvdWxkU2hvdywgb3B0aW9ucyA9IHt9KSB7XG4gICAgaWYgKHNob3VsZFNob3cpIHtcbiAgICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgICB0aGlzLl9jdXJyZW50VGFyZ2V0ID0gb3B0aW9ucy50YXJnZXQ7XG4gICAgICB0aGlzLl9wb3NpdGlvblBvcG92ZXIob3B0aW9ucy50YXJnZXQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICB0aGlzLl9jbGVhclN0eWxlcygpO1xuICAgIH1cbiAgfVxuXG4gIF9wb3NpdGlvblBvcG92ZXIodGFyZ2V0KSB7XG4gICAgY29uc3Qge19yYWRpdXM6IHJhZGl1cywgX2NvbnRlbnQ6IGNvbnRlbnRFbGVtZW50LCBfbWFyZ2luOiBtYXJnaW59ID0gdGhpcztcbiAgICBjb25zdCBzYWZlQXJlYUxlbmd0aHMgPSBpUGhvbmVYUGF0Y2guZ2V0U2FmZUFyZWFMZW5ndGhzKCk7XG4gICAgY29uc3Qgc2FmZUFyZWFSZWN0ID0gaVBob25lWFBhdGNoLmdldFNhZmVBcmVhRE9NUmVjdCgpO1xuICAgIGNvbnN0IHRhcmdldFJlY3QgPSB0YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgY29uc3QgaXNNRCA9IHV0aWwuaGFzTW9kaWZpZXIodGhpcywgJ21hdGVyaWFsJyk7XG4gICAgY29uc3QgY292ZXIgPSBpc01EICYmIHRoaXMuaGFzQXR0cmlidXRlKCdjb3Zlci10YXJnZXQnKTtcbiAgICBjb25zdCBwYXJlbnQgPSB1dGlsLmZpbmRQYXJlbnQodGhpcywgJ29ucy1wYWdlJykgfHwgZG9jdW1lbnQuYm9keTtcbiAgICBjb25zdCBwYXJlbnREaW1lbnNpb25zID0gcGFyZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIGNvbnN0IG1heFBvc2l0aW9ucyA9IHtcbiAgICAgIHRvcDogTWF0aC5tYXgocGFyZW50RGltZW5zaW9ucy50b3AsIHNhZmVBcmVhUmVjdC50b3ApLFxuICAgICAgbGVmdDogTWF0aC5tYXgocGFyZW50RGltZW5zaW9ucy5sZWZ0LCBzYWZlQXJlYVJlY3QubGVmdCksXG4gICAgICBib3R0b206IE1hdGgubWluKHBhcmVudERpbWVuc2lvbnMuYm90dG9tLCBzYWZlQXJlYVJlY3QuYm90dG9tKSxcbiAgICAgIHJpZ2h0OiBNYXRoLm1pbihwYXJlbnREaW1lbnNpb25zLnJpZ2h0LCBzYWZlQXJlYVJlY3QucmlnaHQpLFxuICAgIH07XG5cbiAgICAvLyBEaXN0YW5jZSBmcm9tIGVhY2ggc2lkZSBvZiB0aGUgc2FmZSBhcmVhICh3aXRoIG1hcmdpbikgdG8gdGhlIHRhcmdldCBlbGVtZW50XG4gICAgY29uc3QgdGFyZ2V0RGlzdGFuY2UgPSB7XG4gICAgICB0b3A6IHRhcmdldFJlY3QudG9wIC0gKG1heFBvc2l0aW9ucy50b3AgKyBtYXJnaW4pLFxuICAgICAgbGVmdDogdGFyZ2V0UmVjdC5sZWZ0IC0gKG1heFBvc2l0aW9ucy5sZWZ0ICsgbWFyZ2luKSxcbiAgICAgIGJvdHRvbTogKG1heFBvc2l0aW9ucy5ib3R0b20gLSBtYXJnaW4pIC0gdGFyZ2V0UmVjdC5ib3R0b20sXG4gICAgICByaWdodDogKG1heFBvc2l0aW9ucy5yaWdodCAtIG1hcmdpbikgLSB0YXJnZXRSZWN0LnJpZ2h0XG4gICAgfTtcblxuICAgIC8vIERpc3RhbmNlIGZyb20gZWFjaCBzaWRlIG9mIHRoZSBzYWZlIGFyZWEgKHdpdGggbWFyZ2luKSB0byB0aGUgZ2VvbWV0cmljIGNlbnRlciBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICBjb25zdCB0YXJnZXRDZW50ZXJEaXN0YW5jZUZyb20gPSB7XG4gICAgICB0b3A6IHRhcmdldFJlY3QudG9wICsgTWF0aC5yb3VuZCh0YXJnZXRSZWN0LmhlaWdodCAvIDIpIC0gKG1heFBvc2l0aW9ucy50b3AgKyBtYXJnaW4pLFxuICAgICAgbGVmdDogdGFyZ2V0UmVjdC5sZWZ0ICsgTWF0aC5yb3VuZCh0YXJnZXRSZWN0LndpZHRoIC8gMikgLSAobWF4UG9zaXRpb25zLmxlZnQgKyBtYXJnaW4pLFxuICAgICAgYm90dG9tOiAobWF4UG9zaXRpb25zLmJvdHRvbSAtIG1hcmdpbikgLSB0YXJnZXRSZWN0LmJvdHRvbSArIE1hdGgucm91bmQodGFyZ2V0UmVjdC5oZWlnaHQgLyAyKSxcbiAgICAgIHJpZ2h0OiAobWF4UG9zaXRpb25zLnJpZ2h0IC0gbWFyZ2luKSAtIHRhcmdldFJlY3QucmlnaHQgKyBNYXRoLnJvdW5kKHRhcmdldFJlY3Qud2lkdGggLyAyKVxuICAgIH07XG5cbiAgICBjb25zdCB7dmVydGljYWwsIHByaW1hcnk6IHByaW1hcnlEaXJlY3Rpb24sIHNlY29uZGFyeTogc2Vjb25kYXJ5RGlyZWN0aW9ufSA9IHRoaXMuX2NhbGN1bGF0ZURpcmVjdGlvbnModGFyZ2V0RGlzdGFuY2UpO1xuICAgIHRoaXMuX2N1cnJlbnREaXJlY3Rpb24gPSBwcmltYXJ5RGlyZWN0aW9uO1xuICAgIHV0aWwuYWRkTW9kaWZpZXIodGhpcywgcHJpbWFyeURpcmVjdGlvbik7XG5cbiAgICBjb25zdCBzaXplTmFtZSA9IHZlcnRpY2FsID8gJ3dpZHRoJyA6ICdoZWlnaHQnO1xuICAgIC8vIEdldCAucG9wb3Zlcl9fY29udGVudCBzaXplXG4gICAgY29uc3QgY29udGVudFNpemUgPSAoc3R5bGUgPT4gKHtcbiAgICAgIHdpZHRoOiBwYXJzZUludChzdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKCd3aWR0aCcpLCAxMCksXG4gICAgICBoZWlnaHQ6IHBhcnNlSW50KHN0eWxlLmdldFByb3BlcnR5VmFsdWUoJ2hlaWdodCcpLCAxMClcbiAgICB9KSkod2luZG93LmdldENvbXB1dGVkU3R5bGUoY29udGVudEVsZW1lbnQpKTtcblxuICAgIC8vIFNldHRpbmcgLnBvcG92ZXIgcG9zaXRpb24uXG4gICAgY29uc3QgdGFyZ2V0QW5kQXJyb3dMZW5ndGggPSBjb3ZlciA/IDAgOiAodmVydGljYWwgPyB0YXJnZXRSZWN0LmhlaWdodCA6IHRhcmdldFJlY3Qud2lkdGgpICsgKGlzTUQgPyAwIDogMTQpO1xuICAgIGNvbnN0IHByaW1hcnlPZmZzZXQgPSBNYXRoLm1heChcbiAgICAgIHNhZmVBcmVhTGVuZ3Roc1twcmltYXJ5RGlyZWN0aW9uXSArIG1hcmdpbixcbiAgICAgIHNhZmVBcmVhTGVuZ3Roc1twcmltYXJ5RGlyZWN0aW9uXSArIG1hcmdpbiArIHRhcmdldERpc3RhbmNlW3ByaW1hcnlEaXJlY3Rpb25dICsgdGFyZ2V0QW5kQXJyb3dMZW5ndGhcbiAgICApO1xuICAgIGNvbnN0IHNlY29uZGFyeU9mZnNldCA9IE1hdGgubWF4KFxuICAgICAgc2FmZUFyZWFMZW5ndGhzW3NlY29uZGFyeURpcmVjdGlvbl0gKyBtYXJnaW4sXG4gICAgICBzYWZlQXJlYUxlbmd0aHNbc2Vjb25kYXJ5RGlyZWN0aW9uXSArIG1hcmdpbiArIHRhcmdldENlbnRlckRpc3RhbmNlRnJvbVtzZWNvbmRhcnlEaXJlY3Rpb25dIC0gKGNvbnRlbnRTaXplW3NpemVOYW1lXSAvIDIpXG4gICAgKTtcbiAgICB0aGlzLl9wb3BvdmVyLnN0eWxlW3ByaW1hcnlEaXJlY3Rpb25dID0gcHJpbWFyeU9mZnNldCArICdweCc7XG4gICAgdGhpcy5fcG9wb3Zlci5zdHlsZVtzZWNvbmRhcnlEaXJlY3Rpb25dID0gc2Vjb25kYXJ5T2Zmc2V0ICsgJ3B4JztcblxuICAgIC8vIFNldHRpbmcgLnBvcG92ZXJfX2Fycm93IHBvc2l0aW9uLlxuICAgIHRoaXMuX2Fycm93LnN0eWxlW3NlY29uZGFyeURpcmVjdGlvbl0gPSBNYXRoLm1heChcbiAgICAgIHJhZGl1cyxcbiAgICAgIChzYWZlQXJlYUxlbmd0aHNbc2Vjb25kYXJ5RGlyZWN0aW9uXSArIG1hcmdpbikgKyB0YXJnZXRDZW50ZXJEaXN0YW5jZUZyb21bc2Vjb25kYXJ5RGlyZWN0aW9uXSAtIHNlY29uZGFyeU9mZnNldFxuICAgICkgKyAncHgnO1xuICB9XG5cbiAgX2NhbGN1bGF0ZURpcmVjdGlvbnMoZGlzdGFuY2UpIHtcbiAgICBjb25zdCBvcHRpb25zID0gKHRoaXMuZ2V0QXR0cmlidXRlKCdkaXJlY3Rpb24nKSB8fCAndXAgZG93biBsZWZ0IHJpZ2h0Jykuc3BsaXQoL1xccysvKS5tYXAoZSA9PiBwb3NpdGlvbnNbZV0pO1xuICAgIGNvbnN0IHByaW1hcnkgPSBvcHRpb25zLnNvcnQoKGEsIGIpID0+IGRpc3RhbmNlW2FdIC0gZGlzdGFuY2VbYl0pWzBdO1xuICAgIGNvbnN0IHZlcnRpY2FsID0gJ3RvcCcgPT0gcHJpbWFyeSB8fCAnYm90dG9tJyA9PSBwcmltYXJ5O1xuICAgIGxldCBzZWNvbmRhcnk7XG5cbiAgICBpZiAodmVydGljYWwpIHtcbiAgICAgIHNlY29uZGFyeSA9IGRpc3RhbmNlLmxlZnQgPCBkaXN0YW5jZS5yaWdodCA/ICdsZWZ0JyA6ICdyaWdodCc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNlY29uZGFyeSA9IGRpc3RhbmNlLnRvcCA8IGRpc3RhbmNlLmJvdHRvbSA/ICd0b3AnIDogJ2JvdHRvbSc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHt2ZXJ0aWNhbCwgcHJpbWFyeSwgc2Vjb25kYXJ5fTtcbiAgfVxuXG4gIF9jbGVhclN0eWxlcygpIHtcbiAgICB0aGlzLl9jdXJyZW50RGlyZWN0aW9uID0gbnVsbDtcbiAgICBbJ3RvcCcsICdib3R0b20nLCAnbGVmdCcsICdyaWdodCddLmZvckVhY2goZSA9PiB7XG4gICAgICB0aGlzLl9hcnJvdy5zdHlsZVtlXSA9IHRoaXMuX2NvbnRlbnQuc3R5bGVbZV0gPSB0aGlzLl9wb3BvdmVyLnN0eWxlW2VdID0gJyc7XG4gICAgICB1dGlsLnJlbW92ZU1vZGlmaWVyKHRoaXMsIGUpO1xuICAgIH0pO1xuICB9XG5cbiAgX29uQ2hhbmdlKCkge1xuICAgIHNldEltbWVkaWF0ZSgoKSA9PiB7XG4gICAgICBpZiAodGhpcy5fY3VycmVudFRhcmdldCkge1xuICAgICAgICB0aGlzLl9wb3NpdGlvblBvcG92ZXIodGhpcy5fY3VycmVudFRhcmdldCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIGlmICh0aGlzLl9wb3BvdmVyICYmIHRoaXMuX21hc2spIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBoYXNEZWZhdWx0Q29udGFpbmVyID0gdGhpcy5fcG9wb3ZlciAmJiB0aGlzLl9jb250ZW50O1xuXG4gICAgaWYgKGhhc0RlZmF1bHRDb250YWluZXIpIHtcblxuICAgICAgaWYgKCF0aGlzLl9tYXNrKSB7XG4gICAgICAgIGNvbnN0IG1hc2sgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgbWFzay5jbGFzc0xpc3QuYWRkKCdwb3BvdmVyLW1hc2snKTtcbiAgICAgICAgdGhpcy5pbnNlcnRCZWZvcmUobWFzaywgdGhpcy5maXJzdENoaWxkKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCF0aGlzLl9hcnJvdykge1xuICAgICAgICBjb25zdCBhcnJvdyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBhcnJvdy5jbGFzc0xpc3QuYWRkKCdwb3BvdmVyX19hcnJvdycpO1xuICAgICAgICB0aGlzLl9wb3BvdmVyLmFwcGVuZENoaWxkKGFycm93KTtcbiAgICAgIH1cblxuICAgIH0gZWxzZSB7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gdXRpbC5jcmVhdGVGcmFnbWVudChgXG4gICAgICAgIDxkaXYgY2xhc3M9XCJwb3BvdmVyLW1hc2tcIj48L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInBvcG92ZXJcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwicG9wb3Zlcl9fY29udGVudFwiPjwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJwb3BvdmVyX19hcnJvd1wiPjwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIGApO1xuICAgICAgY29uc3QgY29udGVudCA9IHRlbXBsYXRlLnF1ZXJ5U2VsZWN0b3IoJy5wb3BvdmVyX19jb250ZW50Jyk7XG5cbiAgICAgIHdoaWxlICh0aGlzLmNoaWxkTm9kZXNbMF0pIHtcbiAgICAgICAgY29udGVudC5hcHBlbmRDaGlsZCh0aGlzLmNoaWxkTm9kZXNbMF0pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmFwcGVuZENoaWxkKHRlbXBsYXRlKTtcbiAgICB9XG5cbiAgICAvLyBGSVhNRSFcbiAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ3N0eWxlJykpIHtcbiAgICAgIHRoaXMuX3BvcG92ZXIuc2V0QXR0cmlidXRlKCdzdHlsZScsIHRoaXMuZ2V0QXR0cmlidXRlKCdzdHlsZScpKTtcbiAgICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlKCdzdHlsZScpO1xuICAgIH1cblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgdGhpcy5fc2NoZW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHNob3dcbiAgICogQHNpZ25hdHVyZSBzaG93KHRhcmdldCwgW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge1N0cmluZ3xFdmVudHxIVE1MRWxlbWVudH0gdGFyZ2V0XG4gICAqICAgW2VuXVRhcmdldCBlbGVtZW50LiBDYW4gYmUgZWl0aGVyIGEgQ1NTIHNlbGVjdG9yLCBhbiBldmVudCBvYmplY3Qgb3IgYSBET00gZWxlbWVudC4gSXQgY2FuIGJlIGFsc28gcHJvdmlkZWQgYXMgJ29wdGlvbnMudGFyZ2V0JyBpbnN0ZWFkLiBbL2VuXVxuICAgKiAgIFtqYV3jg53jg4Pjg5fjgqrjg7zjg5Djg7zjga7jgr/jg7zjgrLjg4Pjg4jjgajjgarjgovopoHntKDjgpLmjIflrprjgZfjgb7jgZnjgIJDU1Pjgrvjg6zjgq/jgr/jgYtldmVudOOCquODluOCuOOCp+OCr+ODiOOBi0RPTeimgee0oOOBruOBhOOBmuOCjOOBi+OCkua4oeOBm+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gIFVzZSBvbmUgb2YgYFwiZmFkZS1pb3NcImAsIGBcImZhZGUtbWRcImAsIGBcIm5vbmVcImAgYW5kIGBcImRlZmF1bHRcImAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCXCJmYWRlLWlvc1wiLCBcImZhZGUtbWRcIiwgXCJub25lXCIsIFwiZGVmYXVsdFwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4ge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1UaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBhZnRlciB0aGUgcG9wb3ZlciBoYXMgYmVlbiByZXZlYWxlZC5bL2VuXVxuICAgKiAgIFtqYV3jg53jg4Pjg5fjgqrjg7zjg5Djg7zjgYzooajnpLrjgZXjgozntYLjgo/jgaPjgZ/lvozjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dT3BlbiB0aGUgcG9wb3ZlciBhbmQgcG9pbnQgaXQgYXQgYSB0YXJnZXQuIFRoZSB0YXJnZXQgY2FuIGJlIGVpdGhlciBhbiBldmVudCwgYSBDU1Mgc2VsZWN0b3Igb3IgYSBET00gZWxlbWVudC4uWy9lbl1cbiAgICogICBbamFd5a++6LGh44Go44GZ44KL6KaB57Sg44Gr44Od44OD44OX44Kq44O844OQ44O844KS6KGo56S644GX44G+44GZ44CCdGFyZ2V05byV5pWw44Gr44Gv44CBJGV2ZW5044Kq44OW44K444Kn44Kv44OI44KERE9N44Ko44Os44Oh44Oz44OI44KEQ1NT44K744Os44Kv44K/44KS5rih44GZ44GT44Go44GM5Ye65p2l44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGRpc3BsYXllZCBlbGVtZW50Wy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIHNob3codGFyZ2V0LCBvcHRpb25zID0ge30pIHtcbiAgICAvLyBDb3B5IG9wdGlvbnMgYW5kIGluY2x1ZGUgb3B0aW9ucy50YXJnZXRcbiAgICBpZiAodGFyZ2V0ICYmIHR5cGVvZiB0YXJnZXQgPT09ICdvYmplY3QnICYmICEodGFyZ2V0IGluc3RhbmNlb2YgRXZlbnQpICYmICEodGFyZ2V0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpKSB7XG4gICAgICBvcHRpb25zID0geyAuLi50YXJnZXQgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3B0aW9ucyA9IHsgLi4ub3B0aW9ucywgdGFyZ2V0IH07XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLnRhcmdldCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIG9wdGlvbnMudGFyZ2V0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihvcHRpb25zLnRhcmdldCk7XG4gICAgfSBlbHNlIGlmIChvcHRpb25zLnRhcmdldCBpbnN0YW5jZW9mIEV2ZW50KSB7XG4gICAgICBvcHRpb25zLnRhcmdldCA9IG9wdGlvbnMudGFyZ2V0LnRhcmdldDtcbiAgICB9XG5cbiAgICBpZiAoIShvcHRpb25zLnRhcmdldCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSkge1xuICAgICB1dGlsLnRocm93KCdJbnZhbGlkIHRhcmdldCB0eXBlIG9yIHVuZGVmaW5lZCcpO1xuICAgIH1cblxuICAgIHJldHVybiBzdXBlci5zaG93KG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaGlkZVxuICAgKiBAc2lnbmF0dXJlIGhpZGUoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuICBVc2Ugb25lIG9mIGBcImZhZGUtaW9zXCJgLCBgXCJmYWRlLW1kXCJgLCBgXCJub25lXCJgIGFuZCBgXCJkZWZhdWx0XCJgLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAglwiZmFkZS1pb3NcIiwgXCJmYWRlLW1kXCIsIFwibm9uZVwiLCBcImRlZmF1bHRcIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBp+OBjeOBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25PcHRpb25zXVxuICAgKiAgIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgZGVsYXkgYW5kIHRpbWluZy4gRS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIGRlbGF5LCB0aW1pbmfjgpLmjIflrprjgZfjgb7jgZnjgIJlLmcuIHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31bL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogICBbZW5dVGhpcyBmdW5jdGlvbnMgaXMgY2FsbGVkIGFmdGVyIHRoZSBwb3BvdmVyIGhhcyBiZWVuIGhpZGRlbi5bL2VuXVxuICAgKiAgIFtqYV3jg53jg4Pjg5fjgqrjg7zjg5Djg7zjgYzpmqDjgozjgZ/lvozjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ2xvc2UgdGhlIHBvcG92ZXIuWy9lbl1cbiAgICogICBbamFd44Od44OD44OX44Kq44O844OQ44O844KS6ZaJ44GY44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGhpZGRlbiBlbGVtZW50Wy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB2aXNpYmxlXG4gICAqIEByZWFkb25seVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgdmlzaWJsZSBvciBub3QuWy9lbl1cbiAgICogICBbamFd6KaB57Sg44GM6KaL44GI44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBjYW5jZWxhYmxlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dXG4gICAqICAgICBBIGJvb2xlYW4gdmFsdWUgdGhhdCBzcGVjaWZpZXMgd2hldGhlciB0aGUgcG9wb3ZlciBpcyBjYW5jZWxhYmxlIG9yIG5vdC5cbiAgICpcbiAgICogICAgIFdoZW4gdGhlIHBvcG92ZXIgaXMgY2FuY2VsYWJsZSBpdCBjYW4gYmUgY2xvc2VkIGJ5IHRhcHBpbmcgdGhlIGJhY2tncm91bmQgb3IgYnkgcHJlc3NpbmcgdGhlIGJhY2sgYnV0dG9uIG9uIEFuZHJvaWQgZGV2aWNlcy5cbiAgICogICBbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9uRGV2aWNlQmFja0J1dHRvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQmFjay1idXR0b24gaGFuZGxlci5bL2VuXVxuICAgKiAgIFtqYV3jg5Djg4Pjgq/jg5zjgr/jg7Pjg4/jg7Pjg4njg6njgIJbL2phXVxuICAgKi9cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBzdXBlci5jb25uZWN0ZWRDYWxsYmFjaygpO1xuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIHRoaXMuX2JvdW5kT25DaGFuZ2UsIGZhbHNlKTtcbiAgICB0aGlzLl9tYXJnaW4gPSB0aGlzLl9tYXJnaW4gfHwgcGFyc2VJbnQod2luZG93LmdldENvbXB1dGVkU3R5bGUodGhpcykuZ2V0UHJvcGVydHlWYWx1ZSgndG9wJykpO1xuICAgIHRoaXMuX21hcmdpbiA9IHRoaXMuX21hcmdpbiB8fCA2OyAvLyBGaXggZm9yIGlmcmFtZXNcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9yYWRpdXMgPSBwYXJzZUludCh3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzLl9jb250ZW50KS5nZXRQcm9wZXJ0eVZhbHVlKCdib3JkZXItdG9wLWxlZnQtcmFkaXVzJykpO1xuICAgIH0pO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgc3VwZXIuZGlzY29ubmVjdGVkQ2FsbGJhY2soKTtcbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgZmFsc2UpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsuLi5zdXBlci5vYnNlcnZlZEF0dHJpYnV0ZXMsICdkaXJlY3Rpb24nXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdkaXJlY3Rpb24nKSB7XG4gICAgICByZXR1cm4gdGhpcy5fYm91bmRPbkNoYW5nZSgpO1xuICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gJ21vZGlmaWVyJykge1xuICAgICAgdGhpcy5fY3VycmVudERpcmVjdGlvbiAmJiB1dGlsLmFkZE1vZGlmaWVyKHRoaXMsIHRoaXMuX2N1cnJlbnREaXJlY3Rpb24pO1xuICAgIH1cbiAgICBzdXBlci5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtQb3BvdmVyQW5pbWF0b3J9IEFuaW1hdG9yXG4gICAqL1xuICBzdGF0aWMgcmVnaXN0ZXJBbmltYXRvcihuYW1lLCBBbmltYXRvcikge1xuICAgIGlmICghKEFuaW1hdG9yLnByb3RvdHlwZSBpbnN0YW5jZW9mIFBvcG92ZXJBbmltYXRvcikpIHtcbiAgICAgIHV0aWwudGhyb3dBbmltYXRvcignUG9wb3ZlcicpO1xuICAgIH1cbiAgICBfYW5pbWF0b3JEaWN0W25hbWVdID0gQW5pbWF0b3I7XG4gIH1cblxuICBzdGF0aWMgZ2V0IGFuaW1hdG9ycygpIHtcbiAgICByZXR1cm4gX2FuaW1hdG9yRGljdDtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgUG9wb3ZlckFuaW1hdG9yKCkge1xuICAgIHJldHVybiBQb3BvdmVyQW5pbWF0b3I7XG4gIH1cbn1cblxub25zRWxlbWVudHMuUG9wb3ZlciA9IFBvcG92ZXJFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtcG9wb3ZlcicsIFBvcG92ZXJFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy5wcm9ncmVzcy1iYXInOiAncHJvZ3Jlc3MtYmFyLS0qJyxcbiAgJy5wcm9ncmVzcy1iYXJfX3ByaW1hcnknOiAncHJvZ3Jlc3MtYmFyLS0qX19wcmltYXJ5JyxcbiAgJy5wcm9ncmVzcy1iYXJfX3NlY29uZGFyeSc6ICdwcm9ncmVzcy1iYXItLSpfX3NlY29uZGFyeSdcbn07XG5cbmNvbnN0IHRlbXBsYXRlID0gdXRpbC5jcmVhdGVFbGVtZW50KGBcbiAgPGRpdiBjbGFzcz1cInByb2dyZXNzLWJhclwiPlxuICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1iYXJfX3NlY29uZGFyeVwiPjwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1iYXJfX3ByaW1hcnlcIj48L2Rpdj5cbiAgPC9kaXY+XG5gKTtcblxuY29uc3QgSU5ERVQgPSAnaW5kZXRlcm1pbmF0ZSc7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXByb2dyZXNzLWJhclxuICogQGNhdGVnb3J5IHZpc3VhbFxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1EaXNwbGF5IGEgTWF0ZXJpYWwgRGVzaWduIHByb2dyZXNzIGJhci5bL2VuXVxuICogICBbamFd44Oe44OG44Oq44Ki44Or44OH44K244Kk44Oz44Gu44K544K/44Kk44Or44Gn44OX44Ot44Kw44Os44K544OQ44O844KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgVGhlIGNvbXBvbmVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSBsaW5lYXIgcHJvZ3Jlc3MgYmFyLiBJdCBjYW4gZWl0aGVyIGRpc3BsYXkgYSBwcm9ncmVzcyBiYXIgdGhhdCBzaG93cyB0aGUgdXNlciBob3cgbXVjaCBvZiBhIHRhc2sgaGFzIGJlZW4gY29tcGxldGVkLiBJbiB0aGUgY2FzZSB3aGVyZSB0aGUgcGVyY2VudGFnZSBpcyBub3Qga25vd24gaXQgY2FuIGJlIHVzZWQgdG8gZGlzcGxheSBhbiBhbmltYXRlZCBwcm9ncmVzcyBiYXIgc28gdGhlIHVzZXIgY2FuIHNlZSB0aGF0IGFuIG9wZXJhdGlvbiBpcyBpbiBwcm9ncmVzcy5cbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAY29kZXBlbiB6dlFiR2pcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9wcm9ncmVzc1xuICogQHNlZWFsc28gb25zLXByb2dyZXNzLWNpcmN1bGFyXG4gKiAgIFtlbl1UaGUgYDxvbnMtcHJvZ3Jlc3MtY2lyY3VsYXI+YCBjb21wb25lbnQgZGlzcGxheXMgYSBjaXJjdWxhciBwcm9ncmVzcyBpbmRpY2F0b3IuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1wcm9ncmVzcy1iYXJcbiAqICB2YWx1ZT1cIjU1XCJcbiAqICBzZWNvbmRhcnktdmFsdWU9XCI4N1wiPlxuICogPC9vbnMtcHJvZ3Jlc3MtYmFyPlxuICpcbiAqIDxvbnMtcHJvZ3Jlc3MtYmFyXG4gKiAgaW5kZXRlcm1pbmF0ZT5cbiAqIDwvb25zLXByb2dyZXNzLWJhcj5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUHJvZ3Jlc3NCYXJFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DaGFuZ2UgdGhlIGFwcGVhcmFuY2Ugb2YgdGhlIHByb2dyZXNzIGluZGljYXRvci5bL2VuXVxuICAgKiAgIFtqYV3jg5fjg63jgrDjg6zjgrnjgqTjg7PjgrjjgrHjg7zjgr/jga7opovjgZ/nm67jgpLlpInmm7TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSB2YWx1ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCBwcm9ncmVzcy4gU2hvdWxkIGJlIGEgdmFsdWUgYmV0d2VlbiAwIGFuZCAxMDAuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Gu6YCy6KGM54q25rOB44Gu5YCk44KS5oyH5a6a44GX44G+44GZ44CCMOOBi+OCiTEwMOOBrumWk+OBruWApOOCkuaMh+WumuOBl+OBpuS4i+OBleOBhOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHNlY29uZGFyeS12YWx1ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCBzZWNvbmRhcnkgcHJvZ3Jlc3MuIFNob3VsZCBiZSBhIHZhbHVlIGJldHdlZW4gMCBhbmQgMTAwLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBru+8kueVquebruOBrumAsuihjOeKtuazgeOBruWApOOCkuaMh+WumuOBl+OBvuOBmeOAgjDjgYvjgokxMDDjga7plpPjga7lgKTjgpLmjIflrprjgZfjgabkuIvjgZXjgYTjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBpbmRldGVybWluYXRlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQsIGFuIGluZmluaXRlIGxvb3BpbmcgYW5pbWF0aW9uIHdpbGwgYmUgc2hvd24uWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM6Kit5a6a44GV44KM44Gf5aC05ZCI44CB44Or44O844OX44GZ44KL44Ki44OL44Oh44O844K344On44Oz44GM6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl9jb21waWxlKCkpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgaWYgKCF0aGlzLl9pc0NvbXBpbGVkKCkpIHtcbiAgICAgIHRoaXMuX3RlbXBsYXRlID0gdGVtcGxhdGUuY2xvbmVOb2RlKHRydWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl90ZW1wbGF0ZSA9IHV0aWwuZmluZENoaWxkKHRoaXMsICcucHJvZ3Jlc3MtYmFyJyk7XG4gICAgfVxuXG4gICAgdGhpcy5fcHJpbWFyeSA9IHV0aWwuZmluZENoaWxkKHRoaXMuX3RlbXBsYXRlLCAnLnByb2dyZXNzLWJhcl9fcHJpbWFyeScpO1xuICAgIHRoaXMuX3NlY29uZGFyeSA9IHV0aWwuZmluZENoaWxkKHRoaXMuX3RlbXBsYXRlLCAnLnByb2dyZXNzLWJhcl9fc2Vjb25kYXJ5Jyk7XG5cbiAgICB0aGlzLl91cGRhdGVEZXRlcm1pbmF0ZSgpO1xuICAgIHRoaXMuX3VwZGF0ZVZhbHVlKCk7XG5cbiAgICB0aGlzLmFwcGVuZENoaWxkKHRoaXMuX3RlbXBsYXRlKTtcblxuICAgIGF1dG9TdHlsZS5wcmVwYXJlKHRoaXMpO1xuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIF9pc0NvbXBpbGVkKCkge1xuICAgIGlmICghdXRpbC5maW5kQ2hpbGQodGhpcywgJy5wcm9ncmVzcy1iYXInKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGJhckVsZW1lbnQgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnByb2dyZXNzLWJhcicpO1xuXG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZChiYXJFbGVtZW50LCAnLnByb2dyZXNzLWJhcl9fc2Vjb25kYXJ5JykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoIXV0aWwuZmluZENoaWxkKGJhckVsZW1lbnQsICcucHJvZ3Jlc3MtYmFyX19wcmltYXJ5JykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJywgJ3ZhbHVlJywgJ3NlY29uZGFyeS12YWx1ZScsIElOREVUXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdtb2RpZmllcicpIHtcbiAgICAgIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCBzY2hlbWUpO1xuICAgICAgdGhpcy5oYXNBdHRyaWJ1dGUoSU5ERVQpICYmIHRoaXMuX3VwZGF0ZURldGVybWluYXRlKCk7XG4gICAgfSBlbHNlIGlmIChuYW1lID09PSAndmFsdWUnIHx8IG5hbWUgPT09ICdzZWNvbmRhcnktdmFsdWUnKSB7XG4gICAgICB0aGlzLl91cGRhdGVWYWx1ZSgpO1xuICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gSU5ERVQpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZURldGVybWluYXRlKCk7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZURldGVybWluYXRlKCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB1dGlsLnRvZ2dsZU1vZGlmaWVyKHRoaXMsIElOREVULCB7IGZvcmNlOiB0aGlzLmhhc0F0dHJpYnV0ZShJTkRFVCkgfSkpO1xuICB9XG5cbiAgX3VwZGF0ZVZhbHVlKCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9wcmltYXJ5LnN0eWxlLndpZHRoID0gKHRoaXMuaGFzQXR0cmlidXRlKCd2YWx1ZScpKSA/IHRoaXMuZ2V0QXR0cmlidXRlKCd2YWx1ZScpICsgJyUnIDogJzAlJztcbiAgICAgIHRoaXMuX3NlY29uZGFyeS5zdHlsZS53aWR0aCA9IHRoaXMuaGFzQXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnKSA/IHRoaXMuZ2V0QXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnKSArICclJyA6ICcwJSc7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZhbHVlXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DdXJyZW50IHByb2dyZXNzLiBTaG91bGQgYmUgYSB2YWx1ZSBiZXR3ZWVuIDAgYW5kIDEwMC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjga7pgLLooYznirbms4Hjga7lgKTjgpLmjIflrprjgZfjgb7jgZnjgIIw44GL44KJMTAw44Gu6ZaT44Gu5YCk44KS5oyH5a6a44GX44Gm5LiL44GV44GE44CCWy9qYV1cbiAgICovXG4gIHNldCB2YWx1ZSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInIHx8IHZhbHVlIDwgMCB8fCB2YWx1ZSA+IDEwMCkge1xuICAgICAgdXRpbC50aHJvdygnSW52YWxpZCB2YWx1ZScpO1xuICAgIH1cblxuICAgIHRoaXMuc2V0QXR0cmlidXRlKCd2YWx1ZScsIE1hdGguZmxvb3IodmFsdWUpKTtcbiAgfVxuXG4gIGdldCB2YWx1ZSgpIHtcbiAgICByZXR1cm4gcGFyc2VJbnQodGhpcy5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykgfHwgJzAnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgc2Vjb25kYXJ5VmFsdWVcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUN1cnJlbnQgc2Vjb25kYXJ5IHByb2dyZXNzLiBTaG91bGQgYmUgYSB2YWx1ZSBiZXR3ZWVuIDAgYW5kIDEwMC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjga7vvJLnlarnm67jga7pgLLooYznirbms4Hjga7lgKTjgpLmjIflrprjgZfjgb7jgZnjgIIw44GL44KJMTAw44Gu6ZaT44Gu5YCk44KS5oyH5a6a44GX44Gm5LiL44GV44GE44CCWy9qYV1cbiAgICovXG4gIHNldCBzZWNvbmRhcnlWYWx1ZSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInIHx8IHZhbHVlIDwgMCB8fCB2YWx1ZSA+IDEwMCkge1xuICAgICAgdXRpbC50aHJvdygnSW52YWxpZCB2YWx1ZScpO1xuICAgIH1cblxuICAgIHRoaXMuc2V0QXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnLCBNYXRoLmZsb29yKHZhbHVlKSk7XG4gIH1cblxuICBnZXQgc2Vjb25kYXJ5VmFsdWUoKSB7XG4gICAgcmV0dXJuIHBhcnNlSW50KHRoaXMuZ2V0QXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnKSB8fCAnMCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBpbmRldGVybWluYXRlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBwcm9wZXJ0eSBpcyBgdHJ1ZWAsIGFuIGluZmluaXRlIGxvb3BpbmcgYW5pbWF0aW9uIHdpbGwgYmUgc2hvd24uWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM6Kit5a6a44GV44KM44Gf5aC05ZCI44CB44Or44O844OX44GZ44KL44Ki44OL44Oh44O844K344On44Oz44GM6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHNldCBpbmRldGVybWluYXRlKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlKSB7XG4gICAgICB0aGlzLnNldEF0dHJpYnV0ZShJTkRFVCwgJycpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlKElOREVUKTtcbiAgICB9XG4gIH1cblxuICBnZXQgaW5kZXRlcm1pbmF0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoSU5ERVQpO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLlByb2dyZXNzQmFyID0gUHJvZ3Jlc3NCYXJFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtcHJvZ3Jlc3MtYmFyJywgUHJvZ3Jlc3NCYXJFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy5wcm9ncmVzcy1jaXJjdWxhcic6ICdwcm9ncmVzcy1jaXJjdWxhci0tKicsXG4gICcucHJvZ3Jlc3MtY2lyY3VsYXJfX2JhY2tncm91bmQnOiAncHJvZ3Jlc3MtY2lyY3VsYXItLSpfX2JhY2tncm91bmQnLFxuICAnLnByb2dyZXNzLWNpcmN1bGFyX19wcmltYXJ5JzogJ3Byb2dyZXNzLWNpcmN1bGFyLS0qX19wcmltYXJ5JyxcbiAgJy5wcm9ncmVzcy1jaXJjdWxhcl9fc2Vjb25kYXJ5JzogJ3Byb2dyZXNzLWNpcmN1bGFyLS0qX19zZWNvbmRhcnknXG59O1xuXG5jb25zdCB0ZW1wbGF0ZSA9IHV0aWwuY3JlYXRlRWxlbWVudChgXG4gIDxzdmcgY2xhc3M9XCJwcm9ncmVzcy1jaXJjdWxhclwiPlxuICAgIDxjaXJjbGUgY2xhc3M9XCJwcm9ncmVzcy1jaXJjdWxhcl9fYmFja2dyb3VuZFwiIC8+XG4gICAgPGNpcmNsZSBjbGFzcz1cInByb2dyZXNzLWNpcmN1bGFyX19zZWNvbmRhcnlcIiBjeD1cIjUwJVwiIGN5PVwiNTAlXCIgcj1cIjQwJVwiIC8+XG4gICAgPGNpcmNsZSBjbGFzcz1cInByb2dyZXNzLWNpcmN1bGFyX19wcmltYXJ5XCIgY3g9XCI1MCVcIiBjeT1cIjUwJVwiIHI9XCI0MCVcIiAvPlxuICA8L3N2Zz5cbmApO1xuXG5jb25zdCBJTkRFVCA9ICdpbmRldGVybWluYXRlJztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtcHJvZ3Jlc3MtY2lyY3VsYXJcbiAqIEBjYXRlZ29yeSB2aXN1YWxcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgVGhpcyBjb21wb25lbnQgZGlzcGxheXMgYSBjaXJjdWxhciBwcm9ncmVzcyBpbmRpY2F0b3IuIEl0IGNhbiBlaXRoZXIgYmUgdXNlZCB0byBzaG93IGhvdyBtdWNoIG9mIGEgdGFzayBoYXMgYmVlbiBjb21wbGV0ZWQgb3IgdG8gc2hvdyBhIGxvb3BpbmcgYW5pbWF0aW9uIHRvIGluZGljYXRlIHRoYXQgYW4gb3BlcmF0aW9uIGlzIGN1cnJlbnRseSBydW5uaW5nLlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIEVWek1qUlxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3Byb2dyZXNzLWNpcmN1bGFyXG4gKiBAc2VlYWxzbyBvbnMtcHJvZ3Jlc3MtYmFyXG4gKiAgIFtlbl1UaGUgYDxvbnMtcHJvZ3Jlc3MtYmFyPmAgY29tcG9uZW50IGRpc3BsYXlzIGEgYmFyIHByb2dyZXNzIGluZGljYXRvci5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXByb2dyZXNzLWNpcmN1bGFyXG4gKiAgdmFsdWU9XCI1NVwiXG4gKiAgc2Vjb25kYXJ5LXZhbHVlPVwiODdcIj5cbiAqIDwvb25zLXByb2dyZXNzLWNpcmN1bGFyPlxuICpcbiAqIDxvbnMtcHJvZ3Jlc3MtY2lyY3VsYXJcbiAqICBpbmRldGVybWluYXRlPlxuICogPC9vbnMtcHJvZ3Jlc3MtY2lyY3VsYXI+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFByb2dyZXNzQ2lyY3VsYXJFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DaGFuZ2UgdGhlIGFwcGVhcmFuY2Ugb2YgdGhlIHByb2dyZXNzIGluZGljYXRvci5bL2VuXVxuICAgKiAgIFtqYV3jg5fjg63jgrDjg6zjgrnjgqTjg7PjgrjjgrHjg7zjgr/jga7opovjgZ/nm67jgpLlpInmm7TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSB2YWx1ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCBwcm9ncmVzcy4gU2hvdWxkIGJlIGEgdmFsdWUgYmV0d2VlbiAwIGFuZCAxMDAuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Gu6YCy6KGM54q25rOB44Gu5YCk44KS5oyH5a6a44GX44G+44GZ44CCMOOBi+OCiTEwMOOBrumWk+OBruWApOOCkuaMh+WumuOBl+OBpuS4i+OBleOBhOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHNlY29uZGFyeS12YWx1ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCBzZWNvbmRhcnkgcHJvZ3Jlc3MuIFNob3VsZCBiZSBhIHZhbHVlIGJldHdlZW4gMCBhbmQgMTAwLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBru+8kueVquebruOBrumAsuihjOeKtuazgeOBruWApOOCkuaMh+WumuOBl+OBvuOBmeOAgjDjgYvjgokxMDDjga7plpPjga7lgKTjgpLmjIflrprjgZfjgabkuIvjgZXjgYTjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBpbmRldGVybWluYXRlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQsIGFuIGluZmluaXRlIGxvb3BpbmcgYW5pbWF0aW9uIHdpbGwgYmUgc2hvd24uWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM6Kit5a6a44GV44KM44Gf5aC05ZCI44CB44Or44O844OX44GZ44KL44Ki44OL44Oh44O844K344On44Oz44GM6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl9jb21waWxlKCkpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAndmFsdWUnLCAnc2Vjb25kYXJ5LXZhbHVlJywgSU5ERVRdO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBpZiAobmFtZSA9PT0gJ21vZGlmaWVyJykge1xuICAgICAgTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSk7XG4gICAgICB0aGlzLmhhc0F0dHJpYnV0ZShJTkRFVCkgJiYgdGhpcy5fdXBkYXRlRGV0ZXJtaW5hdGUoKTtcbiAgICB9IGVsc2UgaWYgKG5hbWUgPT09ICd2YWx1ZScgfHwgbmFtZSA9PT0gJ3NlY29uZGFyeS12YWx1ZScpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZVZhbHVlKCk7XG4gICAgfSBlbHNlIGlmIChuYW1lID09PSBJTkRFVCkge1xuICAgICAgdGhpcy5fdXBkYXRlRGV0ZXJtaW5hdGUoKTtcbiAgICB9XG4gIH1cblxuICBfdXBkYXRlRGV0ZXJtaW5hdGUoKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHV0aWwudG9nZ2xlTW9kaWZpZXIodGhpcywgSU5ERVQsIHsgZm9yY2U6IHRoaXMuaGFzQXR0cmlidXRlKElOREVUKSB9KSk7XG4gIH1cblxuICBfdXBkYXRlVmFsdWUoKSB7XG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCd2YWx1ZScpKSB7XG4gICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICBjb25zdCBwZXIgPSBNYXRoLmNlaWwodGhpcy5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykgKiAyNTEuMzIgKiAwLjAxKTtcbiAgICAgICAgdGhpcy5fcHJpbWFyeS5zdHlsZVsnc3Ryb2tlLWRhc2hhcnJheSddID0gcGVyICsgJyUsIDI1MS4zMiUnO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZSgnc2Vjb25kYXJ5LXZhbHVlJykpIHtcbiAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHBlciA9ICBNYXRoLmNlaWwodGhpcy5nZXRBdHRyaWJ1dGUoJ3NlY29uZGFyeS12YWx1ZScpICogMjUxLjMyICogMC4wMSk7XG4gICAgICAgIHRoaXMuX3NlY29uZGFyeS5zdHlsZS5kaXNwbGF5ID0gbnVsbDtcbiAgICAgICAgdGhpcy5fc2Vjb25kYXJ5LnN0eWxlWydzdHJva2UtZGFzaGFycmF5J10gPSBwZXIgKyAnJSwgMjUxLjMyJSc7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgICAgdGhpcy5fc2Vjb25kYXJ5LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZhbHVlXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DdXJyZW50IHByb2dyZXNzLiBTaG91bGQgYmUgYSB2YWx1ZSBiZXR3ZWVuIDAgYW5kIDEwMC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjga7pgLLooYznirbms4Hjga7lgKTjgpLmjIflrprjgZfjgb7jgZnjgIIw44GL44KJMTAw44Gu6ZaT44Gu5YCk44KS5oyH5a6a44GX44Gm5LiL44GV44GE44CCWy9qYV1cbiAgICovXG4gIHNldCB2YWx1ZSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInIHx8IHZhbHVlIDwgMCB8fCB2YWx1ZSA+IDEwMCkge1xuICAgICAgdXRpbC50aHJvdygnSW52YWxpZCB2YWx1ZScpO1xuICAgIH1cblxuICAgIHRoaXMuc2V0QXR0cmlidXRlKCd2YWx1ZScsIE1hdGguZmxvb3IodmFsdWUpKTtcbiAgfVxuXG4gIGdldCB2YWx1ZSgpIHtcbiAgICByZXR1cm4gcGFyc2VJbnQodGhpcy5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykgfHwgJzAnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgc2Vjb25kYXJ5VmFsdWVcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUN1cnJlbnQgc2Vjb25kYXJ5IHByb2dyZXNzLiBTaG91bGQgYmUgYSB2YWx1ZSBiZXR3ZWVuIDAgYW5kIDEwMC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjga7vvJLnlarnm67jga7pgLLooYznirbms4Hjga7lgKTjgpLmjIflrprjgZfjgb7jgZnjgIIw44GL44KJMTAw44Gu6ZaT44Gu5YCk44KS5oyH5a6a44GX44Gm5LiL44GV44GE44CCWy9qYV1cbiAgICovXG4gIHNldCBzZWNvbmRhcnlWYWx1ZSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInIHx8IHZhbHVlIDwgMCB8fCB2YWx1ZSA+IDEwMCkge1xuICAgICAgdXRpbC50aHJvdygnSW52YWxpZCB2YWx1ZScpO1xuICAgIH1cblxuICAgIHRoaXMuc2V0QXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnLCBNYXRoLmZsb29yKHZhbHVlKSk7XG4gIH1cblxuICBnZXQgc2Vjb25kYXJ5VmFsdWUoKSB7XG4gICAgcmV0dXJuIHBhcnNlSW50KHRoaXMuZ2V0QXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnKSB8fCAnMCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBpbmRldGVybWluYXRlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBwcm9wZXJ0eSBpcyBgdHJ1ZWAsIGFuIGluZmluaXRlIGxvb3BpbmcgYW5pbWF0aW9uIHdpbGwgYmUgc2hvd24uWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM6Kit5a6a44GV44KM44Gf5aC05ZCI44CB44Or44O844OX44GZ44KL44Ki44OL44Oh44O844K344On44Oz44GM6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHNldCBpbmRldGVybWluYXRlKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlKSB7XG4gICAgICB0aGlzLnNldEF0dHJpYnV0ZShJTkRFVCwgJycpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlKElOREVUKTtcbiAgICB9XG4gIH1cblxuICBnZXQgaW5kZXRlcm1pbmF0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoSU5ERVQpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgaWYgKHRoaXMuX2lzQ29tcGlsZWQoKSkge1xuICAgICAgdGhpcy5fdGVtcGxhdGUgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnByb2dyZXNzLWNpcmN1bGFyJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX3RlbXBsYXRlID0gdGVtcGxhdGUuY2xvbmVOb2RlKHRydWUpO1xuICAgIH1cblxuICAgIHRoaXMuX3ByaW1hcnkgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLl90ZW1wbGF0ZSwgJy5wcm9ncmVzcy1jaXJjdWxhcl9fcHJpbWFyeScpO1xuICAgIHRoaXMuX3NlY29uZGFyeSA9IHV0aWwuZmluZENoaWxkKHRoaXMuX3RlbXBsYXRlLCAnLnByb2dyZXNzLWNpcmN1bGFyX19zZWNvbmRhcnknKTtcblxuICAgIHRoaXMuX3VwZGF0ZURldGVybWluYXRlKCk7XG4gICAgdGhpcy5fdXBkYXRlVmFsdWUoKTtcblxuICAgIHRoaXMuYXBwZW5kQ2hpbGQodGhpcy5fdGVtcGxhdGUpO1xuXG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgX2lzQ29tcGlsZWQoKSB7XG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnByb2dyZXNzLWNpcmN1bGFyJykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBzdmcgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnByb2dyZXNzLWNpcmN1bGFyJyk7XG5cbiAgICBpZiAoIXV0aWwuZmluZENoaWxkKHN2ZywgJy5wcm9ncmVzcy1jaXJjdWxhcl9fc2Vjb25kYXJ5JykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoIXV0aWwuZmluZENoaWxkKHN2ZywgJy5wcm9ncmVzcy1jaXJjdWxhcl9fcHJpbWFyeScpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cblxub25zRWxlbWVudHMuUHJvZ3Jlc3NDaXJjdWxhciA9IFByb2dyZXNzQ2lyY3VsYXJFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtcHJvZ3Jlc3MtY2lyY3VsYXInLCBQcm9ncmVzc0NpcmN1bGFyRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBzdHlsZXIgZnJvbSAnLi4vb25zL3N0eWxlcic7XG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vb25zL3BsYXRmb3JtJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBHZXN0dXJlRGV0ZWN0b3IgZnJvbSAnLi4vb25zL2dlc3R1cmUtZGV0ZWN0b3InO1xuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi9vbnMvYW5pbWl0JztcblxuY29uc3QgU1RBVEVfSU5JVElBTCA9ICdpbml0aWFsJztcbmNvbnN0IFNUQVRFX1BSRUFDVElPTiA9ICdwcmVhY3Rpb24nO1xuY29uc3QgU1RBVEVfQUNUSU9OID0gJ2FjdGlvbic7XG5cbmNvbnN0IHRocm93VHlwZSA9IChlbCwgdHlwZSkgPT4gdXRpbC50aHJvdyhgXCIke2VsfVwiIG11c3QgYmUgJHt0eXBlfWApO1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1wdWxsLWhvb2tcbiAqIEBjYXRlZ29yeSBjb250cm9sXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIENvbXBvbmVudCB0aGF0IGFkZHMgKipQdWxsIHRvIHJlZnJlc2gqKiBmdW5jdGlvbmFsaXR5IHRvIGFuIGA8b25zLXBhZ2U+YCBlbGVtZW50LlxuICpcbiAqICAgICBJdCBjYW4gYmUgdXNlZCB0byBwZXJmb3JtIGEgdGFzayB3aGVuIHRoZSB1c2VyIHB1bGxzIGRvd24gYXQgdGhlIHRvcCBvZiB0aGUgcGFnZS4gQSBjb21tb24gdXNhZ2UgaXMgdG8gcmVmcmVzaCB0aGUgZGF0YSBkaXNwbGF5ZWQgaW4gYSBwYWdlLlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIFdiSm9nTVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3B1bGwtaG9va1xuICogQGV4YW1wbGVcbiAqIDxvbnMtcGFnZT5cbiAqICAgPG9ucy1wdWxsLWhvb2s+XG4gKiAgICAgUmVsZWFzZSB0byByZWZyZXNoXG4gKiAgIDwvb25zLXB1bGwtaG9vaz5cbiAqIDwvb25zLXBhZ2U+XG4gKlxuICogPHNjcmlwdD5cbiAqICAgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcignb25zLXB1bGwtaG9vaycpLm9uQWN0aW9uID0gZnVuY3Rpb24oZG9uZSkge1xuICogICAgIHNldFRpbWVvdXQoZG9uZSwgMTAwMCk7XG4gKiAgIH07XG4gKiA8L3NjcmlwdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUHVsbEhvb2tFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgY2hhbmdlc3RhdGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIHN0YXRlIGlzIGNoYW5nZWQuIFRoZSBzdGF0ZSBjYW4gYmUgZWl0aGVyIFwiaW5pdGlhbFwiLCBcInByZWFjdGlvblwiIG9yIFwiYWN0aW9uXCIuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu54q25oWL44GM5aSJ44KP44Gj44Gf5aC05ZCI44Gr55m654Gr44GX44G+44GZ44CC54q25oWL44Gv44CBXCJpbml0aWFsXCIsIFwicHJlYWN0aW9uXCIsIFwiYWN0aW9uXCLjga7jgYTjgZrjgozjgYvjgafjgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnRcbiAgICogICBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCpOODmeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5wdWxsSG9va1xuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBldmVudC5zdGF0ZVxuICAgKiAgIFtlbl1DdXJyZW50IHN0YXRlLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBrueKtuaFi+WQjeOCkuWPgueFp+OBp+OBjeOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpc2FibGVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIFwicHVsbC10by1yZWZyZXNoXCIgZnVuY3Rpb25hbGl0eSBpcyBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovmmYLjgIFkaXNhYmxlZOeKtuaFi+OBq+OBquOCiuOCouOCr+OCt+ODp+ODs+OBjOWun+ihjOOBleOCjOOBquOBj+OBquOCiuOBvuOBmVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGhlaWdodFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgaGVpZ2h0IG9mIHRoZSBjb21wb25lbnQuIFdoZW4gcHVsbGVkIGRvd24gZnVydGhlciB0aGFuIHRoaXMgdmFsdWUgaXQgd2lsbCBzd2l0Y2ggdG8gdGhlIFwicHJlYWN0aW9uXCIgc3RhdGUuIFRoZSBkZWZhdWx0IHZhbHVlIGlzIFwiNjRweFwiLlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBrumrmOOBleOCkuaMh+WumuOBl+OBvuOBmeOAguOBk+OBrumrmOOBleS7peS4iuOBq3B1bGwgZG93buOBmeOCi+OBqFwicHJlYWN0aW9uXCLnirbmhYvjgavnp7vooYzjgZfjgb7jgZnjgILjg4fjg5Xjgqnjg6vjg4jjga7lgKTjga9cIjY0cHhcIuOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHRocmVzaG9sZC1oZWlnaHRcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIHRocmVzaG9sZCBoZWlnaHQuIFRoZSBjb21wb25lbnQgYXV0b21hdGljYWxseSBzd2l0Y2hlcyB0byB0aGUgXCJhY3Rpb25cIiBzdGF0ZSB3aGVuIHB1bGxlZCBmdXJ0aGVyIHRoYW4gdGhpcyB2YWx1ZS4gVGhlIGRlZmF1bHQgdmFsdWUgaXMgXCI5NnB4XCIuIEEgbmVnYXRpdmUgdmFsdWUgd2lsbCBkaXNhYmxlIHRoaXMgcHJvcGVydHkuIElmIHRoaXMgdmFsdWUgaXMgbG93ZXIgdGhhbiB0aGUgaGVpZ2h0LCBpdCB3aWxsIHNraXAgXCJwcmVhY3Rpb25cIiBzdGF0ZS5bL2VuXVxuICAgKiAgIFtqYV3plr7lgKTjgajjgarjgovpq5jjgZXjgpLmjIflrprjgZfjgb7jgZnjgILjgZPjga7lgKTjgafmjIflrprjgZfjgZ/pq5jjgZXjgojjgorjgoJwdWxsIGRvd27jgZnjgovjgajjgIHjgZPjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga/oh6rli5XnmoTjgatcImFjdGlvblwi54q25oWL44Gr56e76KGM44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZml4ZWQtY29udGVudFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRoZSBjb250ZW50IG9mIHRoZSBwYWdlIHdpbGwgbm90IG1vdmUgd2hlbiBwdWxsaW5nLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+aZguOAgeODl+ODq+ODleODg+OCr+OBjOW8leOBjeWHuuOBleOCjOOBpuOBhOOCi+aZguOBq+OCguOCs+ODs+ODhuODs+ODhOOBr+WLleOBjeOBvuOBm+OCk+OAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9zaG91bGRGaXhTY3JvbGwgPSB1dGlsLmdsb2JhbHMuaXNVSVdlYlZpZXc7XG5cbiAgICB0aGlzLl9vbkRyYWcgPSB0aGlzLl9vbkRyYWcuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vbkRyYWdTdGFydCA9IHRoaXMuX29uRHJhZ1N0YXJ0LmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25EcmFnRW5kID0gdGhpcy5fb25EcmFnRW5kLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25TY3JvbGwgPSB0aGlzLl9vblNjcm9sbC5iaW5kKHRoaXMpO1xuXG4gICAgdGhpcy5fc2V0U3RhdGUoU1RBVEVfSU5JVElBTCwgdHJ1ZSk7XG4gICAgdGhpcy5faGlkZSgpOyAvLyBGaXggZm9yIHRyYW5zcGFyZW50IHRvb2xiYXIgdHJhbnNpdGlvbnNcbiAgfVxuXG4gIF9zZXRTdHlsZSgpIHtcbiAgICBjb25zdCBoZWlnaHQgPSB0aGlzLmhlaWdodCArICdweCc7XG4gICAgc3R5bGVyKHRoaXMsIHsgaGVpZ2h0LCBsaW5lSGVpZ2h0OiBoZWlnaHQgfSk7XG4gICAgdGhpcy5zdHlsZS5kaXNwbGF5ID09PSAnJyAmJiB0aGlzLl9zaG93KCk7XG4gIH1cblxuICBfb25TY3JvbGwoZXZlbnQpIHtcbiAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5fcGFnZUVsZW1lbnQ7XG5cbiAgICBpZiAoZWxlbWVudC5zY3JvbGxUb3AgPCAwKSB7XG4gICAgICBlbGVtZW50LnNjcm9sbFRvcCA9IDA7XG4gICAgfVxuICB9XG5cbiAgX2NhbkNvbnN1bWVHZXN0dXJlKGdlc3R1cmUpIHtcbiAgICByZXR1cm4gZ2VzdHVyZS5kaXJlY3Rpb24gPT09ICd1cCcgfHwgZ2VzdHVyZS5kaXJlY3Rpb24gPT09ICdkb3duJztcbiAgfVxuXG4gIF9vbkRyYWdTdGFydChldmVudCkge1xuICAgIGlmICghZXZlbnQuZ2VzdHVyZSB8fCB0aGlzLmRpc2FibGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdGFwWSA9IGV2ZW50Lmdlc3R1cmUuY2VudGVyLmNsaWVudFkgKyB0aGlzLl9wYWdlRWxlbWVudC5zY3JvbGxUb3A7XG4gICAgY29uc3QgbWF4WSA9IHdpbmRvdy5pbm5lckhlaWdodDtcbiAgICAvLyBPbmx5IHVzZSBkcmFncyB0aGF0IHN0YXJ0IG5lYXIgdGhlIHB1bGxIb29rIHRvIHJlZHVjZSBmbGlja2VyaW5nc1xuICAgIGNvbnN0IGRyYWdnYWJsZUFyZWFSYXRpbyA9IHRoaXMuX3Nob3VsZEZpeFNjcm9sbCA/IC44IDogMTtcblxuICAgIHRoaXMuX2lnbm9yZURyYWcgPSBldmVudC5jb25zdW1lZCB8fCAodGFwWSA+IG1heFkgKiBkcmFnZ2FibGVBcmVhUmF0aW8pO1xuXG4gICAgaWYgKCF0aGlzLl9pZ25vcmVEcmFnKSB7XG4gICAgICBjb25zdCBjb25zdW1lID0gZXZlbnQuY29uc3VtZTtcbiAgICAgIGV2ZW50LmNvbnN1bWUgPSAoKSA9PiB7XG4gICAgICAgIGNvbnN1bWUgJiYgY29uc3VtZSgpO1xuICAgICAgICB0aGlzLl9pZ25vcmVEcmFnID0gdHJ1ZTtcbiAgICAgICAgLy8gVGhpcyBlbGVtZW50cyByZXNpemVzIC5wYWdlX19jb250ZW50IHNvIGl0IGlzIHNhZmVyXG4gICAgICAgIC8vIHRvIGhpZGUgaXQgd2hlbiBvdGhlciBjb21wb25lbnRzIGFyZSBkcmFnZ2VkLlxuICAgICAgICB0aGlzLl9oaWRlKCk7XG4gICAgICB9O1xuXG4gICAgICBpZiAodGhpcy5fY2FuQ29uc3VtZUdlc3R1cmUoZXZlbnQuZ2VzdHVyZSkpIHtcbiAgICAgICAgY29uc3VtZSAmJiBjb25zdW1lKCk7XG4gICAgICAgIGV2ZW50LmNvbnN1bWVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5fc2hvdygpOyAvLyBOb3QgZW5vdWdoIGR1ZSB0byAnZHJhZ0xvY2tBeGlzJ1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX3N0YXJ0U2Nyb2xsID0gdGhpcy5fcGFnZUVsZW1lbnQuc2Nyb2xsVG9wO1xuICB9XG5cbiAgX29uRHJhZyhldmVudCkge1xuICAgIGlmICghZXZlbnQuZ2VzdHVyZSB8fCB0aGlzLmRpc2FibGVkIHx8IHRoaXMuX2lnbm9yZURyYWcgfHwgIXRoaXMuX2NhbkNvbnN1bWVHZXN0dXJlKGV2ZW50Lmdlc3R1cmUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gTmVjZXNzYXJ5IGR1ZSB0byAnZHJhZ0xvY2tBeGlzJyAoMjVweClcbiAgICBpZiAodGhpcy5zdHlsZS5kaXNwbGF5ID09PSAnbm9uZScpIHtcbiAgICAgIHRoaXMuX3Nob3coKTtcbiAgICB9XG5cbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIGNvbnN0IHRhcFkgPSBldmVudC5nZXN0dXJlLmNlbnRlci5jbGllbnRZICsgdGhpcy5fcGFnZUVsZW1lbnQuc2Nyb2xsVG9wO1xuICAgIGNvbnN0IG1heFkgPSB3aW5kb3cuaW5uZXJIZWlnaHQ7XG5cbiAgICAvLyBIYWNrIHRvIG1ha2UgaXQgd29yayBvbiBBbmRyb2lkIDQuNCBXZWJWaWV3IGFuZCBpT1MgVUlXZWJWaWV3LiBTY3JvbGxzIG1hbnVhbGx5XG4gICAgLy8gbmVhciB0aGUgdG9wIG9mIHRoZSBwYWdlIHNvIHRoZXJlIHdpbGwgYmUgbm8gaW5lcnRpYWwgc2Nyb2xsIHdoZW4gc2Nyb2xsaW5nIGRvd24uXG4gICAgLy8gQWxsb3dpbmcgZGVmYXVsdCBzY3JvbGxpbmcgd2lsbCBraWxsIGFsbCAndG91Y2htb3ZlJyBldmVudHMuXG4gICAgaWYgKHRoaXMuX3Nob3VsZEZpeFNjcm9sbCkge1xuICAgICAgdGhpcy5fcGFnZUVsZW1lbnQuc2Nyb2xsVG9wID0gdGhpcy5fc3RhcnRTY3JvbGwgLSBldmVudC5nZXN0dXJlLmRlbHRhWTtcbiAgICAgIC8vIEFsbG93IGluZXJ0aWEgd2hlbiBzY3JvbGxpbmcgZG93biBiZWxvdyA1MCUgb2YgdGhlIHZpZXcgdG8gcmVkdWNlIGZsaWNrZXJpbmdzXG4gICAgICBpZiAoZXZlbnQuZ2VzdHVyZS5pbnRlcmltRGlyZWN0aW9uICE9PSAndXAnIHx8ICh0YXBZIDw9IG1heFkgKiAuNSkpIHtcbiAgICAgICAgZXZlbnQuZ2VzdHVyZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHNjcm9sbCA9IE1hdGgubWF4KGV2ZW50Lmdlc3R1cmUuZGVsdGFZIC0gdGhpcy5fc3RhcnRTY3JvbGwsIDApO1xuICAgIGlmIChzY3JvbGwgIT09IHRoaXMuX2N1cnJlbnRUcmFuc2xhdGlvbikge1xuXG4gICAgICBjb25zdCB0aCA9IHRoaXMudGhyZXNob2xkSGVpZ2h0O1xuICAgICAgaWYgKHRoID4gMCAmJiBzY3JvbGwgPj0gdGgpIHtcbiAgICAgICAgZXZlbnQuZ2VzdHVyZS5zdG9wRGV0ZWN0KCk7XG4gICAgICAgIHNldEltbWVkaWF0ZSgoKSA9PiB0aGlzLl9maW5pc2goKSk7XG5cbiAgICAgIH0gZWxzZSBpZiAoc2Nyb2xsID49IHRoaXMuaGVpZ2h0KSB7XG4gICAgICAgIHRoaXMuX3NldFN0YXRlKFNUQVRFX1BSRUFDVElPTik7XG5cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX3NldFN0YXRlKFNUQVRFX0lOSVRJQUwpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl90cmFuc2xhdGVUbyhzY3JvbGwpO1xuICAgIH1cbiAgfVxuXG4gIF9vbkRyYWdFbmQoZXZlbnQpIHtcbiAgICBpZiAoIWV2ZW50Lmdlc3R1cmUgfHwgdGhpcy5kaXNhYmxlZCB8fCB0aGlzLl9pZ25vcmVEcmFnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICBpZiAodGhpcy5fY3VycmVudFRyYW5zbGF0aW9uID4gMCkge1xuICAgICAgY29uc3Qgc2Nyb2xsID0gdGhpcy5fY3VycmVudFRyYW5zbGF0aW9uO1xuXG4gICAgICBpZiAoc2Nyb2xsID4gdGhpcy5oZWlnaHQpIHtcbiAgICAgICAgdGhpcy5fZmluaXNoKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl90cmFuc2xhdGVUbygwLCB7YW5pbWF0ZTogdHJ1ZX0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb25BY3Rpb25cbiAgICogQHR5cGUge0Z1bmN0aW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhpcyB3aWxsIGJlIGNhbGxlZCBpbiB0aGUgYGFjdGlvbmAgc3RhdGUgaWYgaXQgZXhpc3RzLiBUaGUgZnVuY3Rpb24gd2lsbCBiZSBnaXZlbiBhIGBkb25lYCBjYWxsYmFjayBhcyBpdCdzIGZpcnN0IGFyZ3VtZW50LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgb25BY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX29uQWN0aW9uO1xuICB9XG5cbiAgc2V0IG9uQWN0aW9uKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICYmICEodmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHRocm93VHlwZSgnb25BY3Rpb24nLCAnZnVuY3Rpb24gb3IgbnVsbCcpO1xuICAgIH1cbiAgICB0aGlzLl9vbkFjdGlvbiA9IHZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvblB1bGxcbiAgICogQHR5cGUge0Z1bmN0aW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSG9vayBjYWxsZWQgd2hlbmV2ZXIgdGhlIHVzZXIgcHVsbHMgdGhlIGVsZW1lbnQuIEl0IGdldHMgdGhlIHB1bGxlZCBkaXN0YW5jZSByYXRpbyAoc2Nyb2xsIC8gaGVpZ2h0KSBhbmQgYW4gYW5pbWF0aW9uT3B0aW9ucyBvYmplY3QgYXMgYXJndW1lbnRzLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgb25QdWxsKCkge1xuICAgIHJldHVybiB0aGlzLl9vblB1bGw7XG4gIH1cblxuICBzZXQgb25QdWxsKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICYmICEodmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHRocm93VHlwZSgnb25QdWxsJywgJ2Z1bmN0aW9uIG9yIG51bGwnKTtcbiAgICB9XG4gICAgdGhpcy5fb25QdWxsID0gdmFsdWU7XG4gIH1cblxuICBfZmluaXNoKCkge1xuICAgIHRoaXMuX3NldFN0YXRlKFNUQVRFX0FDVElPTik7XG4gICAgdGhpcy5fdHJhbnNsYXRlVG8odGhpcy5oZWlnaHQsIHthbmltYXRlOiB0cnVlfSk7XG4gICAgY29uc3QgYWN0aW9uID0gdGhpcy5vbkFjdGlvbiB8fCAoZG9uZSA9PiBkb25lKCkpO1xuICAgIGFjdGlvbigoKSA9PiB7XG4gICAgICB0aGlzLl90cmFuc2xhdGVUbygwLCB7YW5pbWF0ZTogdHJ1ZX0pO1xuICAgICAgdGhpcy5fc2V0U3RhdGUoU1RBVEVfSU5JVElBTCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGhlaWdodFxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGhlaWdodCBvZiB0aGUgcHVsbCBob29rIGluIHBpeGVscy4gVGhlIGRlZmF1bHQgdmFsdWUgaXMgYDY0cHhgLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBzZXQgaGVpZ2h0KHZhbHVlKSB7XG4gICAgaWYgKCF1dGlsLmlzSW50ZWdlcih2YWx1ZSkpIHtcbiAgICAgIHRocm93VHlwZSgnaGVpZ2h0JywgJ2ludGVnZXInKTtcbiAgICB9XG5cbiAgICB0aGlzLnNldEF0dHJpYnV0ZSgnaGVpZ2h0JywgYCR7dmFsdWV9cHhgKTtcbiAgfVxuXG4gIGdldCBoZWlnaHQoKSB7XG4gICAgcmV0dXJuIHBhcnNlSW50KHRoaXMuZ2V0QXR0cmlidXRlKCdoZWlnaHQnKSB8fCAnNjQnLCAxMCk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHRocmVzaG9sZEhlaWdodFxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIHRocmVzaG9sZEhlaWdodCBvZiB0aGUgcHVsbCBob29rIGluIHBpeGVscy4gVGhlIGRlZmF1bHQgdmFsdWUgaXMgYDk2cHhgLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBzZXQgdGhyZXNob2xkSGVpZ2h0KHZhbHVlKSB7XG4gICAgaWYgKCF1dGlsLmlzSW50ZWdlcih2YWx1ZSkpIHtcbiAgICAgIHRocm93VHlwZSgndGhyZXNob2xkSGVpZ2h0JywgJ2ludGVnZXInKTtcbiAgICB9XG5cbiAgICB0aGlzLnNldEF0dHJpYnV0ZSgndGhyZXNob2xkLWhlaWdodCcsIGAke3ZhbHVlfXB4YCk7XG4gIH1cblxuICBnZXQgdGhyZXNob2xkSGVpZ2h0KCkge1xuICAgIHJldHVybiBwYXJzZUludCh0aGlzLmdldEF0dHJpYnV0ZSgndGhyZXNob2xkLWhlaWdodCcpIHx8ICc5NicsIDEwKTtcbiAgfVxuXG4gIF9zZXRTdGF0ZShzdGF0ZSwgbm9FdmVudCkge1xuICAgIGNvbnN0IGxhc3RTdGF0ZSA9IHRoaXMuc3RhdGU7XG5cbiAgICB0aGlzLnNldEF0dHJpYnV0ZSgnc3RhdGUnLCBzdGF0ZSk7XG5cbiAgICBpZiAoIW5vRXZlbnQgJiYgbGFzdFN0YXRlICE9PSB0aGlzLnN0YXRlKSB7XG4gICAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ2NoYW5nZXN0YXRlJywge1xuICAgICAgICBwdWxsSG9vazogdGhpcyxcbiAgICAgICAgc3RhdGU6IHN0YXRlLFxuICAgICAgICBsYXN0U3RhdGU6IGxhc3RTdGF0ZVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBzdGF0ZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUN1cnJlbnQgc3RhdGUgb2YgdGhlIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGdldCBzdGF0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRBdHRyaWJ1dGUoJ3N0YXRlJyk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHB1bGxEaXN0YW5jZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBjdXJyZW50IG51bWJlciBvZiBwaXhlbHMgdGhlIHB1bGwgaG9vayBoYXMgbW92ZWQuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Gu44OX44Or44OV44OD44Kv44GM5byV44GN5Ye644GV44KM44Gf6Led6Zui44KS44OU44Kv44K744Or5pWw44CCWy9qYV1cbiAgICovXG4gIGdldCBwdWxsRGlzdGFuY2UoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2N1cnJlbnRUcmFuc2xhdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cbiAgc2V0IGRpc2FibGVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdkaXNhYmxlZCcsIHZhbHVlKTtcbiAgfVxuXG4gIGdldCBkaXNhYmxlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gIH1cblxuICBfc2hvdygpIHtcbiAgICAvLyBSdW4gYXN5bmNyaG9ub3VzbHkgdG8gYXZvaWQgY29uZmxpY3RzIHdpdGggQW5pbWl0J3Mgc3R5bGUgY2xlYW5cbiAgICBzZXRJbW1lZGlhdGUoKCkgPT4ge1xuICAgICAgdGhpcy5zdHlsZS5kaXNwbGF5ID0gJyc7XG4gICAgICBpZiAodGhpcy5fcGFnZUVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5fcGFnZUVsZW1lbnQuc3R5bGUubWFyZ2luVG9wID0gYC0ke3RoaXMuaGVpZ2h0fXB4YDtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIF9oaWRlKCkge1xuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICBpZiAodGhpcy5fcGFnZUVsZW1lbnQpIHtcbiAgICAgIHRoaXMuX3BhZ2VFbGVtZW50LnN0eWxlLm1hcmdpblRvcCA9ICcnO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge051bWJlcn0gc2Nyb2xsXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKi9cbiAgX3RyYW5zbGF0ZVRvKHNjcm9sbCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgaWYgKHRoaXMuX2N1cnJlbnRUcmFuc2xhdGlvbiA9PSAwICYmIHNjcm9sbCA9PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fY3VycmVudFRyYW5zbGF0aW9uID0gc2Nyb2xsO1xuICAgIGNvbnN0IG9wdCA9IG9wdGlvbnMuYW5pbWF0ZSA/IHsgZHVyYXRpb246IC4zLCB0aW1pbmc6ICdjdWJpYy1iZXppZXIoLjEsIC43LCAuMSwgMSknIH0gOiB7fTtcbiAgICB0aGlzLl9vblB1bGwgJiYgdGhpcy5fb25QdWxsKChzY3JvbGwgLyB0aGlzLmhlaWdodCkudG9GaXhlZCgyKSwgb3B0KTtcbiAgICBjb25zdCBzY3JvbGxFbGVtZW50ID0gIHRoaXMuaGFzQXR0cmlidXRlKCdmaXhlZC1jb250ZW50JykgPyB0aGlzIDogdGhpcy5fcGFnZUVsZW1lbnQ7XG5cbiAgICBhbmltaXQoc2Nyb2xsRWxlbWVudClcbiAgICAgIC5xdWV1ZSh7IHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDBweCwgJHtzY3JvbGx9cHgsIDBweClgIH0sIG9wdClcbiAgICAgIC5wbGF5KCgpID0+IHtcbiAgICAgICAgc2Nyb2xsID09PSAwICYmIHN0eWxlci5jbGVhcihzY3JvbGxFbGVtZW50LCAndHJhbnNpdGlvbiB0cmFuc2Zvcm0nKTtcbiAgICAgICAgb3B0aW9ucy5jYWxsYmFjayBpbnN0YW5jZW9mIEZ1bmN0aW9uICYmIG9wdGlvbnMuY2FsbGJhY2soKTtcbiAgICB9KTtcbiAgfVxuXG4gIF9kaXNhYmxlRHJhZ0xvY2soKSB7IC8vIGUyZSB0ZXN0cyBuZWVkIGl0XG4gICAgdGhpcy5fZHJhZ0xvY2tEaXNhYmxlZCA9IHRydWU7XG4gICAgdGhpcy5fc2V0dXBMaXN0ZW5lcnModHJ1ZSk7XG4gIH1cblxuICBfc2V0dXBMaXN0ZW5lcnMoYWRkKSB7XG4gICAgY29uc3Qgc2Nyb2xsVG9nZ2xlID0gYWN0aW9uID0+IHRoaXMuX3BhZ2VFbGVtZW50W2Ake2FjdGlvbn1FdmVudExpc3RlbmVyYF0oJ3Njcm9sbCcsIHRoaXMuX29uU2Nyb2xsLCBmYWxzZSk7XG4gICAgY29uc3QgZ2RUb2dnbGUgPSBhY3Rpb24gPT4ge1xuICAgICAgY29uc3QgcGFzc2l2ZSA9IHsgcGFzc2l2ZTogdHJ1ZSB9O1xuICAgICAgdGhpcy5fZ2VzdHVyZURldGVjdG9yW2FjdGlvbl0oJ2RyYWcnLCB0aGlzLl9vbkRyYWcsIHBhc3NpdmUpO1xuICAgICAgdGhpcy5fZ2VzdHVyZURldGVjdG9yW2FjdGlvbl0oJ2RyYWdzdGFydCcsIHRoaXMuX29uRHJhZ1N0YXJ0LCBwYXNzaXZlKTtcbiAgICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvclthY3Rpb25dKCdkcmFnZW5kJywgdGhpcy5fb25EcmFnRW5kLCBwYXNzaXZlKTtcbiAgICB9O1xuXG4gICAgaWYgKHRoaXMuX2dlc3R1cmVEZXRlY3Rvcikge1xuICAgICAgZ2RUb2dnbGUoJ29mZicpO1xuICAgICAgdGhpcy5fZ2VzdHVyZURldGVjdG9yLmRpc3Bvc2UoKTtcbiAgICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvciA9IG51bGw7XG4gICAgfVxuICAgIHNjcm9sbFRvZ2dsZSgncmVtb3ZlJyk7XG5cbiAgICBpZiAoYWRkKSB7XG4gICAgICB0aGlzLl9nZXN0dXJlRGV0ZWN0b3IgPSBuZXcgR2VzdHVyZURldGVjdG9yKHRoaXMuX3BhZ2VFbGVtZW50LCB7XG4gICAgICAgIGRyYWdNaW5EaXN0YW5jZTogMSxcbiAgICAgICAgZHJhZ0Rpc3RhbmNlQ29ycmVjdGlvbjogZmFsc2UsXG4gICAgICAgIGRyYWdMb2NrVG9BeGlzOiAhdGhpcy5fZHJhZ0xvY2tEaXNhYmxlZCxcbiAgICAgICAgcGFzc2l2ZTogIXRoaXMuX3Nob3VsZEZpeFNjcm9sbFxuICAgICAgfSk7XG5cbiAgICAgIGdkVG9nZ2xlKCdvbicpO1xuICAgICAgc2Nyb2xsVG9nZ2xlKCdhZGQnKTtcbiAgICB9XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLl9jdXJyZW50VHJhbnNsYXRpb24gPSAwO1xuICAgIHRoaXMuX3BhZ2VFbGVtZW50ID0gdGhpcy5wYXJlbnROb2RlO1xuXG4gICAgdGhpcy5fc2V0dXBMaXN0ZW5lcnModHJ1ZSk7XG4gICAgdGhpcy5fc2V0U3R5bGUoKTtcbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMuX2hpZGUoKTtcbiAgICB0aGlzLl9zZXR1cExpc3RlbmVycyhmYWxzZSk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydoZWlnaHQnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdoZWlnaHQnICYmIHRoaXMuX3BhZ2VFbGVtZW50KSB7XG4gICAgICB0aGlzLl9zZXRTdHlsZSgpO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBnZXQgZXZlbnRzKCkge1xuICAgIHJldHVybiBbJ2NoYW5nZXN0YXRlJ11cbiAgfVxufVxuXG5vbnNFbGVtZW50cy5QdWxsSG9vayA9IFB1bGxIb29rRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXB1bGwtaG9vaycsIFB1bGxIb29rRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgQmFzZUlucHV0RWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1pbnB1dCc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJyc6ICdyYW5nZS0tKicsXG4gICcucmFuZ2VfX2lucHV0JzogJ3JhbmdlLS0qX19pbnB1dCcsXG4gICcucmFuZ2VfX2ZvY3VzLXJpbmcnOiAncmFuZ2UtLSpfX2ZvY3VzLXJpbmcnXG59O1xuXG5jb25zdCBhY3RpdmVDbGFzc1Rva2VuID0gJ3JhbmdlX19pbnB1dC0tYWN0aXZlJztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtcmFuZ2VcbiAqIEBjYXRlZ29yeSBmb3JtXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXU1hdGVyaWFsIERlc2lnbiBzbGlkZXJbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgUmFuZ2UgaW5wdXQgY29tcG9uZW50LiBVc2VkIHRvIGRpc3BsYXkgYSBkcmFnZ2FibGUgc2xpZGVyLlxuICpcbiAqICAgICBXb3JrcyB2ZXJ5IHNpbWlsYXIgdG8gdGhlIGA8aW5wdXQgdHlwZT1cInJhbmdlXCI+YCBlbGVtZW50LlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIHhaUW9tTVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3JhbmdlXG4gKiBAZ3VpZGUgdGhlbWluZy5odG1sI21vZGlmaWVycyBbZW5dTW9yZSBkZXRhaWxzIGFib3V0IHRoZSBgbW9kaWZpZXJgIGF0dHJpYnV0ZVsvZW5dW2phXW1vZGlmaWVy5bGe5oCn44Gu5L2/44GE5pa5Wy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1pbnB1dFxuICogICBbZW5dVGhlIGA8b25zLWlucHV0PmAgY29tcG9uZW50IGlzIHVzZWQgdG8gZGlzcGxheSB0ZXh0IGlucHV0cywgcmFkaW8gYnV0dG9ucyBhbmQgY2hlY2tib3hlcy5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXJhbmdlIHZhbHVlPVwiMjBcIj48L29ucy1yYW5nZT5cbiAqIDxvbnMtcmFuZ2UgbW9kaWZpZXI9XCJtYXRlcmlhbFwiIHZhbHVlPVwiMTBcIj48L3JhbmdlPlxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJhbmdlRWxlbWVudCBleHRlbmRzIEJhc2VJbnB1dEVsZW1lbnQge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9vbk1vdXNlRG93biA9IHRoaXMuX29uTW91c2VEb3duLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25Nb3VzZVVwID0gdGhpcy5fb25Nb3VzZVVwLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25Ub3VjaFN0YXJ0ID0gdGhpcy5fb25Ub3VjaFN0YXJ0LmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25Ub3VjaEVuZCA9IHRoaXMuX29uVG91Y2hFbmQuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vbklucHV0ID0gdGhpcy5fdXBkYXRlLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25EcmFnc3RhcnQgPSB0aGlzLl9vbkRyYWdzdGFydC5iaW5kKHRoaXMpO1xuICAgIHRoaXMuX29uRHJhZ2VuZCA9IHRoaXMuX29uRHJhZ2VuZC5iaW5kKHRoaXMpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgc3VwZXIuX2NvbXBpbGUoKTtcbiAgICB0aGlzLl91cGRhdGVEaXNhYmxlZCh0aGlzLmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKSk7XG4gIH1cblxuICAvKiBJbmhlcml0ZWQgcHJvcHMgKi9cblxuICBfdXBkYXRlKCkge1xuICAgIGNvbnN0IGlucHV0ID0gdGhpcy5faW5wdXQ7XG4gICAgY29uc3QgZm9jdXNSaW5nID0gdGhpcy5fZm9jdXNSaW5nO1xuXG4gICAgaW5wdXQuc3R5bGUuYmFja2dyb3VuZFNpemUgPSBgJHsxMDAgKiB0aGlzLl9yYXRpb30lIDJweGA7XG4gICAgZm9jdXNSaW5nLnZhbHVlID0gdGhpcy52YWx1ZTtcblxuICAgIC8vIE5PVEU6IFwiX3plcm9cIiBhdHRyaWJ1dGUgaXMgdXNlZCBmb3IgQ1NTIHN0eWxpbmcuXG4gICAgaWYgKChpbnB1dC5taW4gPT09ICcnICYmIGlucHV0LnZhbHVlID09PSAnMCcpIHx8IGlucHV0Lm1pbiA9PT0gaW5wdXQudmFsdWUpIHtcbiAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgnX3plcm8nLCAnJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlucHV0LnJlbW92ZUF0dHJpYnV0ZSgnX3plcm8nKTtcbiAgICB9XG5cbiAgICBbJ21pbicsICdtYXgnXS5mb3JFYWNoKGF0dHIgPT4gZm9jdXNSaW5nW2F0dHJdID0gaW5wdXRbYXR0cl0pO1xuICB9XG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgcmV0dXJuIHNjaGVtZTtcbiAgfVxuXG4gIGdldCBfdGVtcGxhdGUoKSB7XG4gICAgcmV0dXJuIGBcbiAgICAgIDxpbnB1dCB0eXBlPVwiJHt0aGlzLnR5cGV9XCIgY2xhc3M9XCIke3RoaXMuX2RlZmF1bHRDbGFzc05hbWV9X19pbnB1dFwiPlxuICAgICAgPGlucHV0IHR5cGU9XCJyYW5nZVwiIGNsYXNzPVwicmFuZ2VfX2ZvY3VzLXJpbmdcIiB0YWJJbmRleD1cIi0xXCI+XG4gICAgYDtcbiAgfVxuXG4gIGdldCBfZGVmYXVsdENsYXNzTmFtZSgpIHtcbiAgICByZXR1cm4gJ3JhbmdlJztcbiAgfVxuXG4gIGdldCB0eXBlKCkge1xuICAgIHJldHVybiAncmFuZ2UnO1xuICB9XG5cbiAgLyogT3duIHByb3BzICovXG5cbiAgX29uTW91c2VEb3duKGUpIHtcbiAgICB0aGlzLl9pbnB1dC5jbGFzc0xpc3QuYWRkKGFjdGl2ZUNsYXNzVG9rZW4pO1xuICAgIHNldEltbWVkaWF0ZSgoKSA9PiB0aGlzLl9pbnB1dC5mb2N1cygpKTtcbiAgfVxuXG4gIF9vblRvdWNoU3RhcnQoZSkge1xuICAgIHRoaXMuX29uTW91c2VEb3duKCk7XG4gIH1cblxuICBfb25Nb3VzZVVwKGUpIHtcbiAgICB0aGlzLl9pbnB1dC5jbGFzc0xpc3QucmVtb3ZlKGFjdGl2ZUNsYXNzVG9rZW4pO1xuICB9XG5cbiAgX29uVG91Y2hFbmQoZSkge1xuICAgIHRoaXMuX29uTW91c2VVcChlKTtcbiAgfVxuXG4gIF9vbkRyYWdzdGFydChlKSB7XG4gICAgZS5jb25zdW1lZCA9IHRydWU7XG4gICAgZS5nZXN0dXJlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIHRoaXMuX2lucHV0LmNsYXNzTGlzdC5hZGQoYWN0aXZlQ2xhc3NUb2tlbik7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdkcmFnJywgdGhpcy5fb25EcmFnKTtcbiAgfVxuXG4gIF9vbkRyYWcoZSkge1xuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH1cblxuICBfb25EcmFnZW5kKGUpIHtcbiAgICB0aGlzLl9pbnB1dC5jbGFzc0xpc3QucmVtb3ZlKGFjdGl2ZUNsYXNzVG9rZW4pO1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignZHJhZycsIHRoaXMuX29uRHJhZyk7XG4gIH1cblxuICBnZXQgX2ZvY3VzUmluZygpIHtcbiAgICByZXR1cm4gdGhpcy5jaGlsZHJlblsxXTtcbiAgfVxuXG4gIGdldCBfcmF0aW8oKSB7XG4gICAgLy8gUmV0dXJucyB0aGUgY3VycmVudCByYXRpby5cbiAgICBjb25zdCBtaW4gPSB0aGlzLl9pbnB1dC5taW4gPT09ICcnID8gMCA6IHBhcnNlSW50KHRoaXMuX2lucHV0Lm1pbik7XG4gICAgY29uc3QgbWF4ID0gdGhpcy5faW5wdXQubWF4ID09PSAnJyA/IDEwMCA6IHBhcnNlSW50KHRoaXMuX2lucHV0Lm1heCk7XG5cbiAgICByZXR1cm4gKHRoaXMudmFsdWUgLSBtaW4pIC8gKG1heCAtIG1pbik7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydkaXNhYmxlZCcsIC4uLkJhc2VJbnB1dEVsZW1lbnQub2JzZXJ2ZWRBdHRyaWJ1dGVzXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdkaXNhYmxlZCcpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZURpc2FibGVkKGN1cnJlbnQpO1xuICAgIH1cbiAgICBzdXBlci5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtib29sZWFufSBkaXNhYmxlZFxuICAgKi9cbiAgX3VwZGF0ZURpc2FibGVkKGRpc2FibGVkKSB7XG4gICAgaWYgKGRpc2FibGVkKSB7XG4gICAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ3JhbmdlLS1kaXNhYmxlZCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmNsYXNzTGlzdC5yZW1vdmUoJ3JhbmdlLS1kaXNhYmxlZCcpO1xuICAgIH1cbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMuX3NldHVwTGlzdGVuZXJzKHRydWUpO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5fc2V0dXBMaXN0ZW5lcnMoZmFsc2UpO1xuICB9XG5cbiAgX3NldHVwTGlzdGVuZXJzKGFkZCkge1xuICAgIGNvbnN0IGFjdGlvbiA9IChhZGQgPyAnYWRkJyA6ICdyZW1vdmUnKSArICdFdmVudExpc3RlbmVyJztcbiAgICB1dGlsW2FjdGlvbl0odGhpcywgJ3RvdWNoc3RhcnQnLCB0aGlzLl9vblRvdWNoU3RhcnQsIHsgcGFzc2l2ZTogdHJ1ZSB9KTtcbiAgICB0aGlzW2FjdGlvbl0oJ21vdXNlZG93bicsIHRoaXMuX29uTW91c2VEb3duKTtcbiAgICB0aGlzW2FjdGlvbl0oJ21vdXNldXAnLCB0aGlzLl9vbk1vdXNlVXApO1xuICAgIHRoaXNbYWN0aW9uXSgndG91Y2hlbmQnLCB0aGlzLl9vblRvdWNoRW5kKTtcbiAgICB0aGlzW2FjdGlvbl0oJ2RyYWdzdGFydCcsIHRoaXMuX29uRHJhZ3N0YXJ0KTtcbiAgICB0aGlzW2FjdGlvbl0oJ2RyYWdlbmQnLCB0aGlzLl9vbkRyYWdlbmQpO1xuICAgIHRoaXNbYWN0aW9uXSgnaW5wdXQnLCB0aGlzLl9vbklucHV0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpc2FibGVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZWxlbWVudCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB2YWx1ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCB2YWx1ZS5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbn1cblxub25zRWxlbWVudHMuUmFuZ2UgPSBSYW5nZUVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1yYW5nZScsIFJhbmdlRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNiBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgaW50ZXJuYWwgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsJztcblxuLyoqXG4gKiBAY2xhc3MgQW5pbWF0b3JDU1MgLSBpbXBsZW1lbnRhdGlvbiBvZiBBbmltYXRvciBjbGFzcyB1c2luZyBjc3MgdHJhbnNpdGlvbnNcbiAqL1xuY2xhc3MgQW5pbWF0b3JDU1Mge1xuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGFuaW1hdGVcbiAgICogQGRlc2MgbWFpbiBhbmltYXRpb24gZnVuY3Rpb25cbiAgICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBmaW5hbENTU1xuICAgKiBAcGFyYW0ge251bWJlcn0gW2R1cmF0aW9uPTIwMF0gLSBkdXJhdGlvbiBpbiBtaWxsaXNlY29uZHNcbiAgICogQHJldHVybiB7T2JqZWN0fSByZXN1bHRcbiAgICogQHJldHVybiB7RnVuY3Rpb259IHJlc3VsdC50aGVuKGNhbGxiYWNrKSAtIHNldHMgYSBjYWxsYmFjayB0byBiZSBleGVjdXRlZCBhZnRlciB0aGUgYW5pbWF0aW9uIGhhcyBzdG9wcGVkXG4gICAqIEByZXR1cm4ge0Z1bmN0aW9ufSByZXN1bHQuc3RvcChvcHRpb25zKSAtIHN0b3BzIHRoZSBhbmltYXRpb247IGlmIG9wdGlvbnMuc3RvcE5leHQgaXMgdHJ1ZSB0aGVuIGl0IGRvZXNuJ3QgY2FsbCB0aGUgY2FsbGJhY2tcbiAgICogQHJldHVybiB7RnVuY3Rpb259IHJlc3VsdC5maW5pc2gobXMpIC0gZmluaXNoZXMgdGhlIGFuaW1hdGlvbiBpbiB0aGUgc3BlY2lmaWVkIHRpbWUgaW4gbWlsbGlzZWNvbmRzXG4gICAqIEByZXR1cm4ge0Z1bmN0aW9ufSByZXN1bHQuc3BlZWQobXMpIC0gc2V0cyB0aGUgYW5pbWF0aW9uIHNwZWVkIHNvIHRoYXQgaXQgZmluaXNoZXMgYXMgaWYgdGhlIG9yaWdpbmFsIGR1cmF0aW9uIHdhcyB0aGUgb25lIHNwZWNpZmllZCBoZXJlXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYGBcbiAgICogIHZhciByZXN1bHQgPSBhbmltYXRvci5hbmltYXRlKGVsLCB7b3BhY2l0eTogMC41fSwgMTAwMCk7XG4gICAqXG4gICAqICBlbC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKGUpe1xuICAgKiAgICByZXN1bHQuc3BlZWQoMjAwKS50aGVuKGZ1bmN0aW9uKCl7XG4gICAqICAgICAgY29uc29sZS5sb2coJ2RvbmUnKTtcbiAgICogICAgfSk7XG4gICAqICB9LCAzMDApO1xuICAgKiBgYGBgXG4gICAqL1xuICBhbmltYXRlKGVsLCBmaW5hbCwgZHVyYXRpb24gPSAyMDApIHtcbiAgICB2YXIgc3RhcnQgPSAobmV3IERhdGUoKSkuZ2V0VGltZSgpLFxuICAgICAgICBpbml0aWFsID0ge30sXG4gICAgICAgIHN0b3BwZWQgPSBmYWxzZSxcbiAgICAgICAgbmV4dCA9IGZhbHNlLFxuICAgICAgICB0aW1lb3V0ID0gZmFsc2UsXG4gICAgICAgIHByb3BlcnRpZXMgPSBPYmplY3Qua2V5cyhmaW5hbCk7XG5cbiAgICB2YXIgdXBkYXRlU3R5bGVzID0gKCkgPT4ge1xuICAgICAgbGV0IHMgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbCk7XG4gICAgICBwcm9wZXJ0aWVzLmZvckVhY2gocy5nZXRQcm9wZXJ0eVZhbHVlLmJpbmQocykpO1xuICAgICAgcyA9IGVsLm9mZnNldEhlaWdodDtcbiAgICB9O1xuXG4gICAgdmFyIHJlc3VsdCA9IHtcbiAgICAgIHN0b3A6IChvcHRpb25zID0ge30pID0+IHtcbiAgICAgICAgdGltZW91dCAmJiBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgIHZhciBrID0gTWF0aC5taW4oMSwgKChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkgLSBzdGFydCkgLyBkdXJhdGlvbik7XG4gICAgICAgIHByb3BlcnRpZXMuZm9yRWFjaChpID0+IHtcbiAgICAgICAgICBlbC5zdHlsZVtpXSA9ICgxIC0gaykgKiBpbml0aWFsW2ldICsgayAqIGZpbmFsW2ldICsgKGkgPT0gJ29wYWNpdHknID8gJycgOiAncHgnKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGVsLnN0eWxlLnRyYW5zaXRpb25EdXJhdGlvbiA9ICcwcyc7XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuc3RvcE5leHQpIHtcbiAgICAgICAgICBuZXh0ID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSBpZiAoIXN0b3BwZWQpIHtcbiAgICAgICAgICBzdG9wcGVkID0gdHJ1ZTtcbiAgICAgICAgICBuZXh0ICYmIG5leHQoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSxcbiAgICAgIHRoZW46IChjYikgPT4ge1xuICAgICAgICBuZXh0ID0gY2I7XG4gICAgICAgIGlmIChzdG9wcGVkKSB7XG4gICAgICAgICAgbmV4dCAmJiBuZXh0KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0sXG4gICAgICBzcGVlZDogKG5ld0R1cmF0aW9uKSA9PiB7XG4gICAgICAgIGlmIChpbnRlcm5hbC5jb25maWcuYW5pbWF0aW9uc0Rpc2FibGVkKSB7XG4gICAgICAgICAgbmV3RHVyYXRpb24gPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmICghc3RvcHBlZCkge1xuICAgICAgICAgIHRpbWVvdXQgJiYgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgICAgY29uc3QgcGFzc2VkID0gKG5ldyBEYXRlKCkpLmdldFRpbWUoKSAtIHN0YXJ0O1xuICAgICAgICAgIGNvbnN0ICBrID0gcGFzc2VkIC8gZHVyYXRpb247XG4gICAgICAgICAgY29uc3QgcmVtYWluaW5nID0gbmV3RHVyYXRpb24gKiAoMSAtIGspO1xuXG4gICAgICAgICAgcHJvcGVydGllcy5mb3JFYWNoKGkgPT4ge1xuICAgICAgICAgICAgZWwuc3R5bGVbaV0gPSAoMSAtIGspICogaW5pdGlhbFtpXSArIGsgKiBmaW5hbFtpXSArIChpID09ICdvcGFjaXR5JyA/ICcnIDogJ3B4Jyk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICB1cGRhdGVTdHlsZXMoKTtcblxuICAgICAgICAgIHN0YXJ0ID0gZWwuc3BlZWRVcFRpbWU7XG4gICAgICAgICAgZHVyYXRpb24gPSByZW1haW5pbmc7XG5cbiAgICAgICAgICBlbC5zdHlsZS50cmFuc2l0aW9uRHVyYXRpb24gPSBkdXJhdGlvbiAvIDEwMDAgKyAncyc7XG5cbiAgICAgICAgICBwcm9wZXJ0aWVzLmZvckVhY2goaSA9PiB7XG4gICAgICAgICAgICBlbC5zdHlsZVtpXSA9IGZpbmFsW2ldICsgKGkgPT0gJ29wYWNpdHknID8gJycgOiAncHgnKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KHJlc3VsdC5zdG9wLCByZW1haW5pbmcpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9LFxuICAgICAgZmluaXNoOiAobWlsbGlzZWNvbmRzID0gNTApID0+IHtcbiAgICAgICAgdmFyIGsgPSAoKG5ldyBEYXRlKCkpLmdldFRpbWUoKSAtIHN0YXJ0KSAvIGR1cmF0aW9uO1xuXG4gICAgICAgIHJlc3VsdC5zcGVlZChtaWxsaXNlY29uZHMgLyAoMSAtIGspKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgaWYgKGVsLmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKSB8fCBzdG9wcGVkIHx8IGludGVybmFsLmNvbmZpZy5hbmltYXRpb25zRGlzYWJsZWQpIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgdmFyIHN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWwpO1xuICAgIHByb3BlcnRpZXMuZm9yRWFjaChlID0+IHtcbiAgICAgIGNvbnN0IHYgPSBwYXJzZUZsb2F0KHN0eWxlLmdldFByb3BlcnR5VmFsdWUoZSkpO1xuICAgICAgaW5pdGlhbFtlXSA9IGlzTmFOKHYpID8gMCA6IHY7XG4gICAgfSk7XG5cblxuICAgIGlmICghc3RvcHBlZCkge1xuICAgICAgZWwuc3R5bGUudHJhbnNpdGlvblByb3BlcnR5ID0gcHJvcGVydGllcy5qb2luKCcsJyk7XG4gICAgICBlbC5zdHlsZS50cmFuc2l0aW9uRHVyYXRpb24gPSBkdXJhdGlvbiAvIDEwMDAgKyAncyc7XG5cbiAgICAgIHByb3BlcnRpZXMuZm9yRWFjaChlID0+IHtcbiAgICAgICAgZWwuc3R5bGVbZV0gPSBmaW5hbFtlXSArIChlID09ICdvcGFjaXR5JyA/ICcnIDogJ3B4Jyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aW1lb3V0ID0gc2V0VGltZW91dChyZXN1bHQuc3RvcCwgZHVyYXRpb24pO1xuICAgIHRoaXMuX29uU3RvcEFuaW1hdGlvbnMoZWwsIHJlc3VsdC5zdG9wKTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLl9xdWV1ZSA9IFtdO1xuICAgIHRoaXMuX2luZGV4ID0gMDtcbiAgfVxuXG4gIF9vblN0b3BBbmltYXRpb25zKGVsLCBsaXN0ZW5lcikge1xuICAgIHZhciBxdWV1ZSA9IHRoaXMuX3F1ZXVlO1xuICAgIHZhciBpID0gdGhpcy5faW5kZXgrKztcbiAgICBxdWV1ZVtlbF0gPSBxdWV1ZVtlbF0gfHwgW107XG4gICAgcXVldWVbZWxdW2ldID0gKG9wdGlvbnMpID0+IHtcbiAgICAgIGRlbGV0ZSBxdWV1ZVtlbF1baV07XG4gICAgICBpZiAocXVldWVbZWxdICYmIHF1ZXVlW2VsXS5sZW5ndGggPT0gMCkge1xuICAgICAgICBkZWxldGUgcXVldWVbZWxdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGxpc3RlbmVyKG9wdGlvbnMpO1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgKiBAbWV0aG9kIHN0b3BBbmltYXRpb25zXG4gICogQGRlc2Mgc3RvcHMgYWN0aXZlIGFuaW1hdGlvbnMgb24gYSBzcGVjaWZpZWQgZWxlbWVudFxuICAqIEBwYXJhbSB7RWxlbWVudHxBcnJheX0gZWxlbWVudCAtIGVsZW1lbnQgb3IgYXJyYXkgb2YgZWxlbWVudHNcbiAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dXG4gICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5zdG9wTmV4dF0gLSB0aGUgY2FsbGJhY2tzIGFmdGVyIHRoZSBhbmltYXRpb25zIHdvbid0IGJlIGNhbGxlZCBpZiB0aGlzIG9wdGlvbiBpcyB0cnVlXG4gICovXG4gIHN0b3BBbmltYXRpb25zKGVsLCBvcHRpb25zID0ge30pIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShlbCkpIHtcbiAgICAgIHJldHVybiBlbC5mb3JFYWNoKGVsID0+IHtcbiAgICAgICAgdGhpcy5zdG9wQW5pbWF0aW9ucyhlbCwgb3B0aW9ucyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAodGhpcy5fcXVldWVbZWxdIHx8IFtdKS5mb3JFYWNoKGUgPT4geyBlKG9wdGlvbnMgfHwge30pOyB9KTtcbiAgfVxuXG4gIC8qKlxuICAqIEBtZXRob2Qgc3RvcEFsbFxuICAqIEBkZXNjIHN0b3BzIGFsbCBhY3RpdmUgYW5pbWF0aW9uc1xuICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV1cbiAgKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLnN0b3BOZXh0XSAtIHRoZSBjYWxsYmFja3MgYWZ0ZXIgdGhlIGFuaW1hdGlvbnMgd29uJ3QgYmUgY2FsbGVkIGlmIHRoaXMgb3B0aW9uIGlzIHRydWVcbiAgKi9cbiAgc3RvcEFsbChvcHRpb25zID0ge30pIHtcbiAgICB0aGlzLnN0b3BBbmltYXRpb25zKE9iamVjdC5rZXlzKHRoaXMuX3F1ZXVlKSwgb3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgKiBAbWV0aG9kIGZhZGVcbiAgKiBAZGVzYyBmYWRlcyB0aGUgZWxlbWVudCAoc2hvcnQgdmVyc2lvbiBmb3IgYW5pbWF0ZShlbCwge29wYWNpdHk6IDB9KSlcbiAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAgKiBAcGFyYW0ge251bWJlcn0gW2R1cmF0aW9uPTIwMF1cbiAgKi9cbiAgZmFkZShlbCwgZHVyYXRpb24gPSAyMDApIHtcbiAgICByZXR1cm4gdGhpcy5hbmltYXRlKGVsLCB7b3BhY2l0eTogMH0sIGR1cmF0aW9uKTtcbiAgfVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IEFuaW1hdG9yQ1NTO1xuXG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBpbnRlcm5hbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4uL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yLWNzcyc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ3JpcHBsZSc7XG5jb25zdCBzY2hlbWUgPSB7XG4gICcnOiAncmlwcGxlLS0qJyxcbiAgJy5yaXBwbGVfX3dhdmUnOiAncmlwcGxlLS0qX193YXZlJyxcbiAgJy5yaXBwbGVfX2JhY2tncm91bmQnOiAncmlwcGxlLS0qX19iYWNrZ3JvdW5kJyxcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXJpcHBsZVxuICogQGNhdGVnb3J5IHZpc3VhbFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBBZGRzIGEgTWF0ZXJpYWwgRGVzaWduIFwicmlwcGxlXCIgZWZmZWN0IHRvIGFuIGVsZW1lbnQuIFRoZSByaXBwbGUgZWZmZWN0IHdpbGwgc3ByZWFkIGZyb20gdGhlIHBvc2l0aW9uIHdoZXJlIHRoZSB1c2VyIHRhcHMuXG4gKlxuICogICAgIFNvbWUgZWxlbWVudHMgc3VjaCBhcyBgPG9ucy1idXR0b24+YCBhbmQgYDxvbnMtZmFiPmAgIHN1cHBvcnQgYSBgcmlwcGxlYCBhdHRyaWJ1dGUuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV3jg57jg4bjg6rjgqLjg6vjg4fjgrbjgqTjg7Pjga7jg6rjg4Pjg5fjg6vlirnmnpzjgpJET03opoHntKDjgavov73liqDjgZfjgb7jgZnjgIJbL2phXVxuICogQGNvZGVwZW4gd0tRV2RaXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvcmlwcGxlXG4gKiBAbW9kaWZpZXIgbGlnaHQtZ3JheVxuICogICBbZW5dQ2hhbmdlIHRoZSBjb2xvciBvZiBlZmZlY3RzIHRvIGxpZ2h0IGdyYXkuWy9lbl1cbiAqICAgW2phXeOCqOODleOCp+OCr+ODiOOBruiJsuOBjOaYjuOCi+OBhOeBsOiJsuOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gKiBAZ3VpZGUgdGhlbWluZy5odG1sI2Nyb3NzLXBsYXRmb3JtLXN0eWxpbmctYXV0b3N0eWxpbmdcbiAqICBbZW5dQ3Jvc3MgcGxhdGZvcm0gc3R5bGluZ1svZW5dXG4gKiAgW2phXUNyb3NzIHBsYXRmb3JtIHN0eWxpbmdbL2phXVxuICogQGV4YW1wbGVcbiAqIDxkaXYgY2xhc3M9XCJteS1kaXZcIj5cbiAqICA8b25zLXJpcHBsZT48L29ucy1yaXBwbGU+XG4gKiA8L2Rpdj5cbiAqXG4gKiBAZXhhbXBsZVxuICogPG9ucy1idXR0b24gcmlwcGxlPkNsaWNrIG1lITwvb25zLWJ1dHRvbj5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmlwcGxlRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBjb2xvclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ29sb3Igb2YgdGhlIHJpcHBsZSBlZmZlY3QuWy9lbl1cbiAgICogICBbamFd44Oq44OD44OX44Or44Ko44OV44Kn44Kv44OI44Gu6Imy44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSByaXBwbGUgZWZmZWN0LlsvZW5dXG4gICAqICAgW2phXeOCqOODleOCp+OCr+ODiOOBruihqOePvuOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGJhY2tncm91bmRcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUNvbG9yIG9mIHRoZSBiYWNrZ3JvdW5kLlsvZW5dXG4gICAqICAgW2phXeiDjOaZr+OBruiJsuOCkuioreWumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHNpemVcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNpemluZyBvZiB0aGUgd2F2ZSBvbiByaXBwbGUgZWZmZWN0LiBTZXQgXCJjb3ZlclwiIG9yIFwiY29udGFpblwiLiBEZWZhdWx0IGlzIFwiY292ZXJcIi5bL2VuXVxuICAgKiAgIFtqYV3jgqjjg5Xjgqfjgq/jg4jjga7jgrXjgqTjgrrjgpLmjIflrprjgZfjgb7jgZnjgIJcImNvdmVyXCLjgoLjgZfjgY/jga9cImNvbnRhaW5cIuOCkuaMh+WumuOBl+OBvuOBmeOAguODh+ODleOCqeODq+ODiOOBr1wiY292ZXJcIuOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGNlbnRlclxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIHByZXNlbnRzLCBjaGFuZ2UgdGhlIHBvc2l0aW9uIG9mIHdhdmUgZWZmZWN0IHRvIGNlbnRlciBvZiB0aGUgdGFyZ2V0IGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFd44GT44Gu6KaB57Sg44KS6Kit5a6a44GZ44KL44Go44CB44Ko44OV44Kn44Kv44OI44Gu5L2N572u44GM6KaB57Sg44Gu55yf44KT5Lit44GL44KJ5aeL44G+44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZGlzYWJsZWRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHNldCwgdGhlIHJpcHBsZSBlZmZlY3Qgd2lsbCBiZSBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzoqK3lrprjgZXjgozjgZ/loLTlkIjjgIHjg6rjg4Pjg5fjg6vjgqjjg5Xjgqfjgq/jg4jjga/nhKHlirnjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fb25UYXAgPSB0aGlzLl9vblRhcC5iaW5kKHRoaXMpO1xuICAgIHRoaXMuX29uSG9sZCA9IHRoaXMuX29uSG9sZC5iaW5kKHRoaXMpO1xuICAgIHRoaXMuX29uRHJhZ1N0YXJ0ID0gdGhpcy5fb25EcmFnU3RhcnQuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vblJlbGVhc2UgPSB0aGlzLl9vblJlbGVhc2UuYmluZCh0aGlzKTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl9jb21waWxlKCkpO1xuXG4gICAgdGhpcy5fYW5pbWF0b3IgPSBuZXcgQW5pbWF0b3IoKTtcblxuICAgIFsnY29sb3InLCAnY2VudGVyJywgJ3N0YXJ0LXJhZGl1cycsICdiYWNrZ3JvdW5kJywgJ21vZGlmaWVyJ10uZm9yRWFjaChlID0+IHtcbiAgICAgIHRoaXMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKGUsIG51bGwsIHRoaXMuZ2V0QXR0cmlidXRlKGUpKTtcbiAgICB9KTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIHRoaXMuY2xhc3NMaXN0LmFkZChkZWZhdWx0Q2xhc3NOYW1lKTtcblxuICAgIHRoaXMuX3dhdmUgPSB0aGlzLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ3JpcHBsZV9fd2F2ZScpWzBdO1xuICAgIHRoaXMuX2JhY2tncm91bmQgPSB0aGlzLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ3JpcHBsZV9fYmFja2dyb3VuZCcpWzBdO1xuXG4gICAgaWYgKCEodGhpcy5fYmFja2dyb3VuZCAmJiB0aGlzLl93YXZlKSkge1xuICAgICAgdGhpcy5fd2F2ZSA9IHV0aWwuY3JlYXRlKCcucmlwcGxlX193YXZlJyk7XG4gICAgICB0aGlzLl9iYWNrZ3JvdW5kID0gdXRpbC5jcmVhdGUoJy5yaXBwbGVfX2JhY2tncm91bmQnKTtcblxuICAgICAgdGhpcy5hcHBlbmRDaGlsZCh0aGlzLl93YXZlKTtcbiAgICAgIHRoaXMuYXBwZW5kQ2hpbGQodGhpcy5fYmFja2dyb3VuZCk7XG4gICAgfVxuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgX2dldEVmZmVjdFNpemUoKSB7XG4gICAgY29uc3Qgc2l6ZXMgPSBbJ2NvdmVyJywgJ2NvbnRhaW4nXTtcbiAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ3NpemUnKSkge1xuICAgICAgY29uc3Qgc2l6ZSA9IHRoaXMuZ2V0QXR0cmlidXRlKCdzaXplJyk7XG4gICAgICBpZiAoc2l6ZXMuaW5kZXhPZihzaXplKSAhPT0gLTEpIHtcbiAgICAgICAgcmV0dXJuIHNpemU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuICdjb3Zlcic7XG4gIH1cblxuICBfY2FsY3VsYXRlQ29vcmRzKGUpIHtcbiAgICBsZXQgeCwgeSwgaCwgdywgcjtcbiAgICBjb25zdCBiID0gdGhpcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBjb25zdCBzaXplID0gdGhpcy5fZ2V0RWZmZWN0U2l6ZSgpO1xuICAgIGNvbnN0IGVycm9yID0gKCkgPT4gdXRpbC50aHJvdygnUmlwcGxlIGludmFsaWQgc3RhdGUnKTtcblxuICAgIGlmICh0aGlzLl9jZW50ZXIpIHtcbiAgICAgIHggPSBiLndpZHRoIC8gMjtcbiAgICAgIHkgPSBiLmhlaWdodCAvIDI7XG5cbiAgICAgIGlmIChzaXplID09PSAnY292ZXInKSB7XG4gICAgICAgIHIgPSBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSk7XG4gICAgICB9IGVsc2UgaWYgKHNpemUgPT09ICdjb250YWluJykge1xuICAgICAgICByID0gTWF0aC5taW4oeCwgeSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlcnJvcigpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB4ID0gKHR5cGVvZiBlLmNsaWVudFggPT09ICdudW1iZXInID8gZS5jbGllbnRYIDogZS5jaGFuZ2VkVG91Y2hlc1swXS5jbGllbnRYKSAtIGIubGVmdDtcbiAgICAgIHkgPSAodHlwZW9mIGUuY2xpZW50WSA9PT0gJ251bWJlcicgPyBlLmNsaWVudFkgOiBlLmNoYW5nZWRUb3VjaGVzWzBdLmNsaWVudFkpIC0gYi50b3A7XG4gICAgICBoID0gTWF0aC5tYXgoeSwgYi5oZWlnaHQgLSB5KTtcbiAgICAgIHcgPSBNYXRoLm1heCh4LCBiLndpZHRoIC0geCk7XG5cbiAgICAgIGlmIChzaXplID09PSAnY292ZXInKSB7XG4gICAgICAgIHIgPSBNYXRoLnNxcnQoaCAqIGggKyB3ICogdyk7XG4gICAgICB9IGVsc2UgaWYgKHNpemUgPT09ICdjb250YWluJykge1xuICAgICAgICByID0gTWF0aC5taW4oTWF0aC5yb3VuZChoIC8gMiksIE1hdGgucm91bmQodyAvIDIpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVycm9yKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHt4LCB5LCByfTtcbiAgfVxuXG4gIF9yaXBwbGVBbmltYXRpb24oZSwgZHVyYXRpb24gPSAzMDApIHtcbiAgICBjb25zdCB7X2FuaW1hdG9yLCBfd2F2ZSwgX2JhY2tncm91bmQsIF9taW5SfSA9IHRoaXM7XG4gICAgY29uc3Qge3gsIHksIHJ9ID0gdGhpcy5fY2FsY3VsYXRlQ29vcmRzKGUpO1xuXG4gICAgX2FuaW1hdG9yLnN0b3BBbGwoe3N0b3BOZXh0OiAxfSk7XG4gICAgX2FuaW1hdG9yLmFuaW1hdGUoX2JhY2tncm91bmQsIHtvcGFjaXR5OiAxfSwgZHVyYXRpb24pO1xuXG4gICAgdXRpbC5leHRlbmQoX3dhdmUuc3R5bGUsIHtcbiAgICAgIG9wYWNpdHk6IDEsXG4gICAgICB0b3A6IHkgLSBfbWluUiArICdweCcsXG4gICAgICBsZWZ0OiB4IC0gX21pblIgKyAncHgnLFxuICAgICAgd2lkdGg6IDIgKiBfbWluUiArICdweCcsXG4gICAgICBoZWlnaHQ6IDIgKiBfbWluUiArICdweCdcbiAgICB9KTtcblxuICAgIHJldHVybiBfYW5pbWF0b3IuYW5pbWF0ZShfd2F2ZSwge1xuICAgICAgdG9wOiB5IC0gcixcbiAgICAgIGxlZnQ6IHggLSByLFxuICAgICAgaGVpZ2h0OiAyICogcixcbiAgICAgIHdpZHRoOiAyICogclxuICAgIH0sIGR1cmF0aW9uKTtcbiAgfVxuXG4gIF91cGRhdGVQYXJlbnQoKSB7XG4gICAgaWYgKCF0aGlzLl9wYXJlbnRVcGRhdGVkICYmIHRoaXMucGFyZW50Tm9kZSkge1xuICAgICAgY29uc3QgY29tcHV0ZWRTdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHRoaXMucGFyZW50Tm9kZSk7XG4gICAgICBpZiAoY29tcHV0ZWRTdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKCdwb3NpdGlvbicpID09PSAnc3RhdGljJykge1xuICAgICAgICB0aGlzLnBhcmVudE5vZGUuc3R5bGUucG9zaXRpb24gPSAncmVsYXRpdmUnO1xuICAgICAgfVxuICAgICAgdGhpcy5fcGFyZW50VXBkYXRlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgX29uVGFwKGUpIHtcbiAgICBpZiAoIXRoaXMuZGlzYWJsZWQgJiYgIWUucmlwcGxlKSB7XG4gICAgICBlLnJpcHBsZSA9IHRydWU7XG4gICAgICB0aGlzLl91cGRhdGVQYXJlbnQoKTtcbiAgICAgIHRoaXMuX3JpcHBsZUFuaW1hdGlvbihlLmdlc3R1cmUuc3JjRXZlbnQpLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLl9hbmltYXRvci5mYWRlKHRoaXMuX3dhdmUpO1xuICAgICAgICB0aGlzLl9hbmltYXRvci5mYWRlKHRoaXMuX2JhY2tncm91bmQpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgX29uSG9sZChlKSB7XG4gICAgaWYgKCF0aGlzLmRpc2FibGVkICYmICFlLnJpcHBsZSkge1xuICAgICAgZS5yaXBwbGUgPSB0cnVlO1xuICAgICAgdGhpcy5fdXBkYXRlUGFyZW50KCk7XG4gICAgICB0aGlzLl9ob2xkaW5nID0gdGhpcy5fcmlwcGxlQW5pbWF0aW9uKGUuZ2VzdHVyZS5zcmNFdmVudCwgMjAwMCk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdyZWxlYXNlJywgdGhpcy5fb25SZWxlYXNlKTtcbiAgICB9XG4gIH1cblxuICBfb25SZWxlYXNlKGUpIHtcbiAgICBpZiAodGhpcy5faG9sZGluZyAmJiAhZS5yaXBwbGUpIHtcbiAgICAgIGUucmlwcGxlID0gdHJ1ZTtcbiAgICAgIHRoaXMuX2hvbGRpbmcuc3BlZWQoMzAwKS50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5fYW5pbWF0b3Iuc3RvcEFsbCh7c3RvcE5leHQ6IHRydWV9KTtcbiAgICAgICAgdGhpcy5fYW5pbWF0b3IuZmFkZSh0aGlzLl93YXZlKTtcbiAgICAgICAgdGhpcy5fYW5pbWF0b3IuZmFkZSh0aGlzLl9iYWNrZ3JvdW5kKTtcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLl9ob2xkaW5nID0gZmFsc2U7XG4gICAgfVxuXG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVsZWFzZScsIHRoaXMuX29uUmVsZWFzZSk7XG4gIH1cblxuICBfb25EcmFnU3RhcnQoZSkge1xuICAgIGlmICh0aGlzLl9ob2xkaW5nKSB7XG4gICAgICByZXR1cm4gdGhpcy5fb25SZWxlYXNlKGUpO1xuICAgIH1cbiAgICBpZiAoWydsZWZ0JywgJ3JpZ2h0J10uaW5kZXhPZihlLmdlc3R1cmUuZGlyZWN0aW9uKSAhPSAtMSkge1xuICAgICAgdGhpcy5fb25UYXAoZSk7XG4gICAgfVxuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5fcGFyZW50Tm9kZSA9IHRoaXMucGFyZW50Tm9kZTtcblxuICAgIGlmIChpbnRlcm5hbC5jb25maWcuYW5pbWF0aW9uc0Rpc2FibGVkKSB7XG4gICAgICB0aGlzLmRpc2FibGVkID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fcGFyZW50Tm9kZS5hZGRFdmVudExpc3RlbmVyKCd0YXAnLCB0aGlzLl9vblRhcCk7XG4gICAgICB0aGlzLl9wYXJlbnROb2RlLmFkZEV2ZW50TGlzdGVuZXIoJ2hvbGQnLCB0aGlzLl9vbkhvbGQpO1xuICAgICAgdGhpcy5fcGFyZW50Tm9kZS5hZGRFdmVudExpc3RlbmVyKCdkcmFnc3RhcnQnLCB0aGlzLl9vbkRyYWdTdGFydCk7XG4gICAgfVxuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgY29uc3QgcG4gPSB0aGlzLl9wYXJlbnROb2RlIHx8IHRoaXMucGFyZW50Tm9kZTtcbiAgICBwbi5yZW1vdmVFdmVudExpc3RlbmVyKCd0YXAnLCB0aGlzLl9vblRhcCk7XG4gICAgcG4ucmVtb3ZlRXZlbnRMaXN0ZW5lcignaG9sZCcsIHRoaXMuX29uSG9sZCk7XG4gICAgcG4ucmVtb3ZlRXZlbnRMaXN0ZW5lcignZHJhZ3N0YXJ0JywgdGhpcy5fb25EcmFnU3RhcnQpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnc3RhcnQtcmFkaXVzJywgJ2NvbG9yJywgJ2JhY2tncm91bmQnLCAnY2VudGVyJywgJ2NsYXNzJywgJ21vZGlmaWVyJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuXG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdtb2RpZmllcic6XG4gICAgICAgIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCBzY2hlbWUpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnc3RhcnQtcmFkaXVzJzpcbiAgICAgICAgdGhpcy5fbWluUiA9IE1hdGgubWF4KDAsIHBhcnNlRmxvYXQoY3VycmVudCkgfHwgMCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdjb2xvcic6XG4gICAgICAgIGlmIChjdXJyZW50KSB7XG4gICAgICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3dhdmUuc3R5bGUuYmFja2dyb3VuZCA9IGN1cnJlbnQ7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaGFzQXR0cmlidXRlKCdiYWNrZ3JvdW5kJykpIHtcbiAgICAgICAgICAgICAgdGhpcy5fYmFja2dyb3VuZC5zdHlsZS5iYWNrZ3JvdW5kID0gY3VycmVudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnYmFja2dyb3VuZCc6XG4gICAgICAgIGlmIChjdXJyZW50IHx8IGxhc3QpIHtcbiAgICAgICAgICBpZiAoY3VycmVudCA9PT0gJ25vbmUnKSB7XG4gICAgICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgICB0aGlzLl9iYWNrZ3JvdW5kLnNldEF0dHJpYnV0ZSgnZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgdGhpcy5fYmFja2dyb3VuZC5zdHlsZS5iYWNrZ3JvdW5kID0gJ3RyYW5zcGFyZW50JztcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgICBpZiAodGhpcy5fYmFja2dyb3VuZC5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9iYWNrZ3JvdW5kLnJlbW92ZUF0dHJpYnV0ZSgnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB0aGlzLl9iYWNrZ3JvdW5kLnN0eWxlLmJhY2tncm91bmQgPSBjdXJyZW50O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdjZW50ZXInOlxuICAgICAgICBpZiAobmFtZSA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgICB0aGlzLl9jZW50ZXIgPSBjdXJyZW50ICE9IG51bGwgJiYgY3VycmVudCAhPSAnZmFsc2UnO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgZGlzYWJsZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeeEoeWKueWMluOBleOCjOOBpuOBhOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuICBzZXQgZGlzYWJsZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2Rpc2FibGVkJywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IGRpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKTtcbiAgfVxufVxuXG5vbnNFbGVtZW50cy5SaXBwbGUgPSBSaXBwbGVFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtcmlwcGxlJywgUmlwcGxlRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtcm93XG4gKiBAY2F0ZWdvcnkgZ3JpZFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1SZXByZXNlbnRzIGEgcm93IGluIHRoZSBncmlkIHN5c3RlbS4gVXNlIHdpdGggYDxvbnMtY29sPmAgdG8gbGF5b3V0IGNvbXBvbmVudHMuWy9lbl1cbiAqICAgW2phXeOCsOODquODg+ODieOCt+OCueODhuODoOOBq+OBpuihjOOCkuWumue+qeOBl+OBvuOBmeOAgm9ucy1jb2zjgajjgajjgoLjgavkvb/nlKjjgZfjgIHjgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7phY3nva7jgavkvb/nlKjjgZfjgb7jgZnjgIJbL2phXVxuICogQGNvZGVwZW4gR2d1akMge3dpZGV9XG4gKiBAZ3VpZGUgZmVhdHVyZXMuaHRtbFxuICogICBbZW5dTGF5b3V0aW5nIGd1aWRlWy9lbl1cbiAqICAgW2phXeODrOOCpOOCouOCpuODiOiqv+aVtFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtY29sXG4gKiAgIFtlbl1UaGUgYDxvbnMtY29sPmAgY29tcG9uZW50IGlzIHVzZWQgYXMgY2hpbGRyZW4gb2YgYDxvbnMtcm93PmAuWy9lbl1cbiAqICAgW2phXW9ucy1jb2zjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQG5vdGVcbiAqICAgW2VuXUZvciBBbmRyb2lkIDQuMyBhbmQgZWFybGllciwgYW5kIGlPUzYgYW5kIGVhcmxpZXIsIHdoZW4gdXNpbmcgbWl4ZWQgYWxpZ25tZW50IHdpdGggb25zLXJvdyBhbmQgb25zLWNvbCwgdGhleSBtYXkgbm90IGJlIGRpc3BsYXllZCBjb3JyZWN0bHkuIFlvdSBjYW4gdXNlIG9ubHkgb25lIHZlcnRpY2FsLWFsaWduLlsvZW5dXG4gKiAgIFtqYV1BbmRyb2lkIDQuM+S7peWJjeOAgeOCguOBl+OBj+OBr2lPUyA25Lul5YmN44GuT1Pjga7loLTlkIjjgIFvbnMtcm9344Gob25zLWNvbOOCkue1hOOBv+WQiOOCj+OBm+OBpuOBneOCjOOBnuOCjOOBrm9ucy1jb2zopoHntKDjga52ZXJ0aWNhbC1hbGlnbuWxnuaAp+OBruWApOOBq+WIpeOAheOBruWApOOCkuaMh+WumuOBmeOCi+OBqOOAgeaPj+eUu+OBjOW0qeOCjOOCi+WgtOWQiOOBjOOBguOCiuOBvuOBmeOAgnZlcnRpY2FsLWFsaWdu5bGe5oCn44Gu5YCk44Gr44Gv5LiA44Gk44Gu5YCk44Gg44GR44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXJvdz5cbiAqICAgPG9ucy1jb2wgd2lkdGg9XCI1MHB4XCI+PG9ucy1pY29uIGljb249XCJmYS10d2l0dGVyXCI+PC9vbnMtaWNvbj48L29ucy1jb2w+XG4gKiAgIDxvbnMtY29sPlRleHQ8L29ucy1jb2w+XG4gKiA8L29ucy1yb3c+XG4gKi9cblxuLyoqXG4gKiBAYXR0cmlidXRlIHZlcnRpY2FsLWFsaWduXG4gKiBAdHlwZSB7U3RyaW5nfVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1TaG9ydCBoYW5kIGF0dHJpYnV0ZSBmb3IgYWxpZ25pbmcgdmVydGljYWxseS4gVmFsaWQgdmFsdWVzIGFyZSB0b3AsIGJvdHRvbSwgYW5kIGNlbnRlci5bL2VuXVxuICogICBbamFd57im44Gr5pW05YiX44GZ44KL44Gf44KB44Gr5oyH5a6a44GX44G+44GZ44CCdG9w44CBYm90dG9t44CBY2VudGVy44Gu44GE44Ga44KM44GL44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAqL1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSb3dFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xufVxuXG5vbnNFbGVtZW50cy5Sb3cgPSBSb3dFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtcm93JywgUm93RWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ3NlZ21lbnQnO1xuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ3NlZ21lbnQtLSonLFxuICAnLnNlZ21lbnRfX2l0ZW0nOiAnc2VnbWVudC0tKl9faXRlbScsXG4gICcuc2VnbWVudF9faW5wdXQnOiAnc2VnbWVudC0tKl9faW5wdXQnLFxuICAnLnNlZ21lbnRfX2J1dHRvbic6ICdzZWdtZW50LS0qX19idXR0b24nXG59O1xuXG5jb25zdCBnZW5lcmF0ZUlkID0gKCgpID0+IHtcbiAgbGV0IGkgPSAwO1xuICByZXR1cm4gKCkgPT4gJ29ucy1zZWdtZW50LWdlbi0nICsgKGkrKyk7XG59KSgpO1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1zZWdtZW50XG4gKiBAY2F0ZWdvcnkgY29udHJvbFxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1NYXRlcmlhbCBEZXNpZ24gc2VnbWVudFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBTZWdtZW50IGNvbXBvbmVudC4gVXNlIHRoaXMgY29tcG9uZW50IHRvIGhhdmUgYSBidXR0b24gYmFyIHdpdGggYXV0b21hdGljIHN0eWxlcyB0aGF0IHN3aXRjaCBvbiBjbGljayBvZiBhbm90aGVyIGJ1dHRvbi5cbiAqXG4gKiAgICAgV2lsbCBhdXRvbWF0aWNhbGx5IGRpc3BsYXkgYXMgYSBNYXRlcmlhbCBEZXNpZ24gc2VnbWVudCBvbiBBbmRyb2lkLlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIGhMYXl4XG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2Uvc2VnbWVudFxuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNtb2RpZmllcnMgW2VuXU1vcmUgZGV0YWlscyBhYm91dCB0aGUgYG1vZGlmaWVyYCBhdHRyaWJ1dGVbL2VuXVtqYV1tb2RpZmllcuWxnuaAp+OBruS9v+OBhOaWuVsvamFdXG4gKiBAZ3VpZGUgdGhlbWluZy5odG1sI2Nyb3NzLXBsYXRmb3JtLXN0eWxpbmctYXV0b3N0eWxpbmcgW2VuXUluZm9ybWF0aW9uIGFib3V0IGNyb3NzIHBsYXRmb3JtIHN0eWxpbmdbL2VuXVtqYV1JbmZvcm1hdGlvbiBhYm91dCBjcm9zcyBwbGF0Zm9ybSBzdHlsaW5nWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXNlZ21lbnQ+XG4gKiAgIDxvbnMtYnV0dG9uPkxhYmVsIDE8L29ucy1idXR0b24+XG4gKiAgIDxvbnMtYnV0dG9uPkxhYmVsIDI8L29ucy1idXR0b24+XG4gKiAgIDxvbnMtYnV0dG9uPkxhYmVsIDM8L29ucy1idXR0b24+XG4gKiA8L29ucy1zZWdtZW50PlxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNlZ21lbnRFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdGNoYW5nZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZXMgYWZ0ZXIgdGhlIGFjdGl2ZSBidXR0b24gaXMgY2hhbmdlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnRcbiAgICogICBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBldmVudC5pbmRleFxuICAgKiAgIFtlbl1UYXBwZWQgYnV0dG9uIGluZGV4LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5zZWdtZW50SXRlbVxuICAgKiAgIFtlbl1TZWdtZW50IGl0ZW0gb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBzZWdtZW50LlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgdGFiYmFyLWlkXG4gICAqIEBpbml0b25seVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JRCBvZiB0aGUgdGFiYmFyIGVsZW1lbnQgdG8gXCJjb25uZWN0XCIgdG8gdGhlIHNlZ21lbnQuIE11c3QgYmUgaW5zaWRlIHRoZSBzYW1lIHBhZ2UuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhY3RpdmUtaW5kZXhcbiAgICogQGluaXRvbmx5XG4gICAqIEBkZWZhdWx0IDBcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dSW5kZXggb2YgdGhlIGZpcnN0IGFjdGl2ZSBidXR0b24sIG9ubHkgd29ya3MgaWYgdGhlcmUgaXMgbm8gY29ubmVjdGVkIHRhYmJhciAoaW4gd2hpY2ggY2FzZSB0aGUgYWN0aXZlIHRhYiBzZXRzIHRoZSBhY3RpdmUgYnV0dG9uKS5bL2VuXVxuICAgKiAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpc2FibGVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IGlmIHNlZ21lbnQgc2hvdWxkIGJlIGRpc2FibGVkLlsvZW5dXG4gICAqICAgW2phXeODnOOCv+ODs+OCkueEoeWKueWMluOBmeOCi+WgtOWQiOOBr+aMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX3NlZ21lbnRJZCA9IGdlbmVyYXRlSWQoKTtcbiAgICB0aGlzLl90YWJiYXIgPSBudWxsO1xuICAgIHRoaXMuX29uQ2hhbmdlID0gdGhpcy5fb25DaGFuZ2UuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vblRhYmJhclByZUNoYW5nZSA9IHRoaXMuX29uVGFiYmFyUHJlQ2hhbmdlLmJpbmQodGhpcyk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fY29tcGlsZSgpXG4gICAgICBzZXRJbW1lZGlhdGUoKCkgPT4gdGhpcy5fbGFzdEFjdGl2ZUluZGV4ID0gdGhpcy5fdGFiYmFyID8gdGhpcy5fdGFiYmFyLmdldEFjdGl2ZVRhYkluZGV4KCkgOiB0aGlzLmdldEFjdGl2ZUJ1dHRvbkluZGV4KCkpO1xuICAgIH0pO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKGRlZmF1bHRDbGFzc05hbWUpO1xuXG4gICAgZm9yIChsZXQgaW5kZXggPSB0aGlzLmNoaWxkcmVuLmxlbmd0aCAtIDE7IGluZGV4ID49IDA7IGluZGV4LS0pIHtcbiAgICAgIGNvbnN0IGl0ZW0gPSB0aGlzLmNoaWxkcmVuW2luZGV4XTtcbiAgICAgIGl0ZW0uY2xhc3NMaXN0LmFkZCgnc2VnbWVudF9faXRlbScpO1xuXG4gICAgICBjb25zdCBpbnB1dCA9IHV0aWwuZmluZENoaWxkKGl0ZW0sICcuc2VnbWVudF9faW5wdXQnKSB8fCB1dGlsLmNyZWF0ZSgnaW5wdXQuc2VnbWVudF9faW5wdXQnKTtcbiAgICAgIGlucHV0LnR5cGUgPSAncmFkaW8nO1xuICAgICAgaW5wdXQudmFsdWUgPSBpbmRleDtcbiAgICAgIGlucHV0Lm5hbWUgPSBpbnB1dC5uYW1lIHx8IHRoaXMuX3NlZ21lbnRJZDtcbiAgICAgIGlucHV0LmNoZWNrZWQgPSAhdGhpcy5oYXNBdHRyaWJ1dGUoJ3RhYmJhci1pZCcpICYmIGluZGV4ID09PSAocGFyc2VJbnQodGhpcy5nZXRBdHRyaWJ1dGUoJ2FjdGl2ZS1pbmRleCcpKSB8fCAwKTtcblxuICAgICAgY29uc3QgYnV0dG9uID0gdXRpbC5maW5kQ2hpbGQoaXRlbSwgJy5zZWdtZW50X19idXR0b24nKSB8fCB1dGlsLmNyZWF0ZSgnLnNlZ21lbnRfX2J1dHRvbicpO1xuICAgICAgaWYgKGJ1dHRvbi5wYXJlbnRFbGVtZW50ICE9PSBpdGVtKSB7XG4gICAgICAgIHdoaWxlIChpdGVtLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgICBidXR0b24uYXBwZW5kQ2hpbGQoaXRlbS5maXJzdENoaWxkKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpdGVtLmFwcGVuZENoaWxkKGlucHV0KTtcbiAgICAgIGl0ZW0uYXBwZW5kQ2hpbGQoYnV0dG9uKTtcbiAgICB9XG5cbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHNjaGVtZSk7XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCd0YWJiYXItaWQnKSkge1xuICAgICAgICBjb25zdCBwYWdlID0gdXRpbC5maW5kUGFyZW50KHRoaXMsICdvbnMtcGFnZScpO1xuICAgICAgICB0aGlzLl90YWJiYXIgPSBwYWdlICYmIHBhZ2UucXVlcnlTZWxlY3RvcignIycgKyB0aGlzLmdldEF0dHJpYnV0ZSgndGFiYmFyLWlkJykpO1xuICAgICAgICBpZiAoIXRoaXMuX3RhYmJhciB8fCB0aGlzLl90YWJiYXIudGFnTmFtZSAhPT0gJ09OUy1UQUJCQVInKSB7XG4gICAgICAgICAgdXRpbC50aHJvdyhgTm8gdGFiYmFyIHdpdGggaWQgJHt0aGlzLmdldEF0dHJpYnV0ZSgndGFiYmFyLWlkJyl9IHdhcyBmb3VuZC5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3RhYmJhci5zZXRBdHRyaWJ1dGUoJ2hpZGUtdGFicycsICcnKTtcbiAgICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHRoaXMuX3NldENoZWNrZWQodGhpcy5fdGFiYmFyLmdldEFjdGl2ZVRhYkluZGV4KCkpKTtcblxuICAgICAgICB0aGlzLl90YWJiYXIuYWRkRXZlbnRMaXN0ZW5lcigncHJlY2hhbmdlJywgdGhpcy5fb25UYWJiYXJQcmVDaGFuZ2UpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCB0aGlzLl9vbkNoYW5nZSk7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuX3RhYmJhcikge1xuICAgICAgICB0aGlzLl90YWJiYXIucmVtb3ZlRXZlbnRMaXN0ZW5lcigncHJlY2hhbmdlJywgdGhpcy5fb25UYWJiYXJQcmVDaGFuZ2UpO1xuICAgICAgICB0aGlzLl90YWJiYXIgPSBudWxsO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgdGhpcy5fb25DaGFuZ2UpO1xuICB9XG5cbiAgX3NldENoZWNrZWQoaW5kZXgpIHtcbiAgICB0aGlzLmNoaWxkcmVuW2luZGV4XS5maXJzdEVsZW1lbnRDaGlsZC5jaGVja2VkID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHNldEFjdGl2ZUJ1dHRvblxuICAgKiBAc2lnbmF0dXJlIHNldEFjdGl2ZUJ1dHRvbihpbmRleCwgW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogICBbZW5dQnV0dG9uIGluZGV4LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdCwgd29ya3Mgb25seSBpZiB0aGVyZSBpcyBhIGNvbm5lY3RlZCB0YWJiYXIuIFN1cHBvcnRzIHRoZSBzYW1lIG9wdGlvbnMgYXMgYG9ucy10YWJiYXJgJ3MgYHNldEFjdGl2ZVRhYmAgbWV0aG9kLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1NYWtlIGJ1dHRvbiB3aXRoIHRoZSBzcGVjaWZpZWQgaW5kZXggYWN0aXZlLiBJZiB0aGVyZSBpcyBhIGNvbm5lY3RlZCB0YWJiYXIgaXQgc2hvd3MgdGhlIGNvcnJlc3BvbmRpbmcgdGFiIHBhZ2UuIEluIHRoaXMgY2FzZSBhbmltYXRpb25zIGFuZCB0aGVpciBvcHRpb25zIGNhbiBiZSBzcGVjaWZpZWQgYnkgdGhlIHNlY29uZCBwYXJhbWV0ZXIuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIHNlbGVjdGVkIGluZGV4IG9yIHRvIHRoZSBuZXcgcGFnZSBlbGVtZW50IGlmIHRoZXJlIGlzIGEgY29ubmVjdGVkIHRhYmJhci5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgc2V0QWN0aXZlQnV0dG9uKGluZGV4LCBvcHRpb25zKSB7XG4gICAgaWYgKHRoaXMuX3RhYmJhcikge1xuICAgICAgcmV0dXJuIHRoaXMuX3RhYmJhci5zZXRBY3RpdmVUYWIoaW5kZXgsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIHRoaXMuX3NldENoZWNrZWQoaW5kZXgpO1xuICAgIHRoaXMuX3Bvc3RDaGFuZ2UoaW5kZXgpO1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoaW5kZXgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgZ2V0QWN0aXZlQnV0dG9uSW5kZXhcbiAgICogQHNpZ25hdHVyZSBnZXRBY3RpdmVCdXR0b25JbmRleCgpXG4gICAqIEByZXR1cm4ge051bWJlcn1cbiAgICogICBbZW5dVGhlIGluZGV4IG9mIHRoZSBjdXJyZW50bHkgYWN0aXZlIGJ1dHRvbi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyBidXR0b24gaW5kZXggb2YgY3VycmVudCBhY3RpdmUgYnV0dG9uLiBJZiBhY3RpdmUgYnV0dG9uIGlzIG5vdCBmb3VuZCwgcmV0dXJucyAtMS5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgZ2V0QWN0aXZlQnV0dG9uSW5kZXgoKSB7XG4gICAgZm9yIChsZXQgaSA9IHRoaXMuY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHsgLy8gQXJyYXkuZmluZEluZGV4XG4gICAgICBpZiAodGhpcy5jaGlsZHJlbltpXS5maXJzdEVsZW1lbnRDaGlsZC5jaGVja2VkKSB7XG4gICAgICAgIHJldHVybiBpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gLTE7XG4gIH1cblxuICBfb25DaGFuZ2UoZXZlbnQpIHtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB0aGlzLl90YWJiYXJcbiAgICAgID8gdGhpcy5fdGFiYmFyLnNldEFjdGl2ZVRhYih0aGlzLmdldEFjdGl2ZUJ1dHRvbkluZGV4KCksIHsgcmVqZWN0OiBmYWxzZSB9KVxuICAgICAgOiB0aGlzLl9wb3N0Q2hhbmdlKHRoaXMuZ2V0QWN0aXZlQnV0dG9uSW5kZXgoKSk7XG4gIH1cblxuICBfb25UYWJiYXJQcmVDaGFuZ2UoZXZlbnQpIHtcbiAgICBzZXRJbW1lZGlhdGUoKCkgPT4ge1xuICAgICAgaWYgKCFldmVudC5kZXRhaWwuY2FuY2VsZWQpIHtcbiAgICAgICAgdGhpcy5fc2V0Q2hlY2tlZChldmVudC5pbmRleCk7XG4gICAgICAgIHRoaXMuX3Bvc3RDaGFuZ2UoZXZlbnQuaW5kZXgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgX3Bvc3RDaGFuZ2UoaW5kZXgpIHtcbiAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ3Bvc3RjaGFuZ2UnLCB7XG4gICAgICBpbmRleCxcbiAgICAgIGFjdGl2ZUluZGV4OiBpbmRleCxcbiAgICAgIGxhc3RBY3RpdmVJbmRleDogdGhpcy5fbGFzdEFjdGl2ZUluZGV4LFxuICAgICAgc2VnbWVudEl0ZW06IHRoaXMuY2hpbGRyZW5baW5kZXhdXG4gICAgfSk7XG4gICAgdGhpcy5fbGFzdEFjdGl2ZUluZGV4ID0gaW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgc2VnbWVudCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG4gIHNldCBkaXNhYmxlZCh2YWx1ZSkge1xuICAgIHJldHVybiB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnZGlzYWJsZWQnLCB2YWx1ZSk7XG4gIH1cblxuICBnZXQgZGlzYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdkaXNhYmxlZCcpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnY2xhc3MnLCAnbW9kaWZpZXInXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGdldCBldmVudHMoKSB7XG4gICAgcmV0dXJuIFsncG9zdGNoYW5nZSddO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLlNlZ21lbnQgPSBTZWdtZW50RWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXNlZ21lbnQnLCBTZWdtZW50RWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBzY2hlbWUgPSB7XG4gICcnOiAnc2VsZWN0LSogc2VsZWN0LS0qJyxcbiAgJy5zZWxlY3QtaW5wdXQnOiAnc2VsZWN0LWlucHV0LS0qJ1xufTtcblxuY29uc3QgZGVmYXVsdENsYXNzTmFtZSA9ICdzZWxlY3QnO1xuXG5jb25zdCBJTlBVVF9BVFRSSUJVVEVTID0gW1xuICAnYXV0b2ZvY3VzJyxcbiAgJ2Rpc2FibGVkJyxcbiAgJ2Zvcm0nLFxuICAnbXVsdGlwbGUnLFxuICAnbmFtZScsXG4gICdyZXF1aXJlZCcsXG4gICdzaXplJ1xuXTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtc2VsZWN0XG4gKiBAY2F0ZWdvcnkgZm9ybVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgW2VuXURpc3BsYXlzIGEgTWF0ZXJpYWwgRGVzaWduIHNlbGVjdCBpbnB1dC5bL2VuXVxuICogIFtqYV1bL2phXVxuICogQG1vZGlmaWVyIHVuZGVyYmFyXG4gKiAgW2VuXURpc3BsYXlzIGEgaG9yaXpvbnRhbCBsaW5lIHVuZGVybmVhdGggYSBzZWxlY3QgaW5wdXQuWy9lbl1cbiAqICBbamFdWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgU2VsZWN0IGNvbXBvbmVudC4gSWYgeW91IHdhbnQgdG8gcGxhY2UgYSBzZWxlY3Qgd2l0aCBhbiBJRCBvZiBgbXktaWRgIG9uIGEgcGFnZSwgdXNlIGA8b25zLXNlbGVjdCBzZWxlY3QtaWQ9XCJteS1pZFwiPmAuXG4gKlxuICogICAgIFRoZSBjb21wb25lbnQgd2lsbCBhdXRvbWF0aWNhbGx5IGRpc3BsYXkgYXMgYSBNYXRlcmlhbCBEZXNpZ24gc2VsZWN0IG9uIEFuZHJvaWQuXG4gKlxuICogICAgIE1vc3QgYXR0cmlidXRlcyB0aGF0IGNhbiBiZSB1c2VkIGZvciBhIG5vcm1hbCBgPHNlbGVjdD5gIGVsZW1lbnQgY2FuIGFsc28gYmUgdXNlZCBvbiB0aGUgYDxvbnMtc2VsZWN0PmAgZWxlbWVudC5cbiAqICAgWy9lbl1cbiAqICAgW2phXeOCu+ODrOOCr+ODiOODnOODg+OCr+OCueOCkuihqOekuuOBmeOCi+OCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAgmBzZWxlY3RgIOimgee0oOOBq+S9v+eUqOOBp+OBjeOCi+WxnuaAp+OBruWkmuOBj+OBjCBgb25zLXNlbGVjdGAg6KaB57Sg44Gn44KC5Yip55So44Gn44GN44G+44GZ44CCWy9qYV1cbiAqIEBjb2RlcGVuIGhMYXl4XG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2Uvc2VsZWN0XG4gKiBAZ3VpZGUgdGhlbWluZy5odG1sI21vZGlmaWVycyBbZW5dTW9yZSBkZXRhaWxzIGFib3V0IHRoZSBgbW9kaWZpZXJgIGF0dHJpYnV0ZVsvZW5dW2phXW1vZGlmaWVy5bGe5oCn44Gu5L2/44GE5pa5Wy9qYV1cbiAqIEBndWlkZSB0aGVtaW5nLmh0bWwjY3Jvc3MtcGxhdGZvcm0tc3R5bGluZy1hdXRvc3R5bGluZyBbZW5dSW5mb3JtYXRpb24gYWJvdXQgY3Jvc3MgcGxhdGZvcm0gc3R5bGluZ1svZW5dW2phXUluZm9ybWF0aW9uIGFib3V0IGNyb3NzIHBsYXRmb3JtIHN0eWxpbmdbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtc2VsZWN0PlxuICogICA8b3B0aW9uIHZhbHVlPVwiMVwiPjE8L29wdGlvbj5cbiAqICAgPG9wdGlvbiB2YWx1ZT1cIjJcIj4ybmQ8L29wdGlvbj5cbiAqICAgPG9wdGlvbiB2YWx1ZT1cIjNcIj4zcmQgb3B0aW9uPC9vcHRpb24+XG4gKiA8L29ucy1zZWxlY3Q+XG4gKi9cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2VsZWN0RWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhdXRvZm9jdXNcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXUVsZW1lbnQgYXV0b21hdGljYWxseSBnYWlucyBmb2N1cyBvbiBwYWdlIGxvYWQuWy9lbl1cbiAgICogIFtqYV3jg5rjg7zjgrjjg63jg7zjg4nmmYLjgavjgZPjga7jgrvjg6zjgq/jg4jjg5zjg4Pjgq/jgrnjgavjg5Xjgqnjg7zjgqvjgrnjgYznp7vjgovjgojjgYbjgavjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgaWYgc2VsZWN0IGlucHV0IHNob3VsZCBiZSBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jgrvjg6zjgq/jg4jjg5zjg4Pjgq/jgrnjgpLnhKHlirnljJbjgZnjgovloLTlkIjjgavmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBmb3JtXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Bc3NvY2lhdGUgYSBzZWxlY3QgZWxlbWVudCB0byBhbiBleGlzdGluZyBmb3JtIG9uIHRoZSBwYWdlLCBldmVuIGlmIG5vdCBuZXN0ZWQuWy9lbl1cbiAgICogICBbamFd44GT44Gu44K744Os44Kv44OI44Oc44OD44Kv44K544KS44CB5oyH5a6a44GX44GfIGBmb3JtYCDopoHntKDjgavntJDku5jjgZHjgb7jgZnjgILjgrvjg6zjgq/jg4jjg5zjg4Pjgq/jgrnjgpIgYGZvcm1gIOimgee0oOOBruWkluWBtOOBq+mFjee9ruOBmeOCi+mam+OBq+S9v+eUqOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG11bHRpcGxlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBkZWZpbmVkLCBtdWx0aXBsZSBvcHRpb25zIGNhbiBiZSBzZWxlY3RlZCBhdCBvbmNlLlsvZW5dXG4gICAqICBbamFd6YG45oqe6IKi44Gu6KSH5pWw6YG45oqe44KS5pyJ5Yq544Gr44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbmFtZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dTmFtZSB0aGUgc2VsZWN0IGVsZW1lbnQsIHVzZWZ1bCBmb3IgaW5zdGFuY2UgaWYgaXQgaXMgcGFydCBvZiBhIGZvcm0uWy9lbl1cbiAgICogICBbamFd44GT44Gu44K744Os44Kv44OI44Oc44OD44Kv44K544Gu5ZCN5YmN44KS5oyH5a6a44GX44G+44GZ44CC6YCa5bi4IGBmb3JtYCDopoHntKDjgajlhbHjgavkvb/nlKjjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSByZXF1aXJlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXU1ha2UgdGhlIHNlbGVjdCBpbnB1dCByZXF1aXJlZCBmb3Igc3VibWl0dGluZyB0aGUgZm9ybSBpdCBpcyBwYXJ0IG9mLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruOCu+ODrOOCr+ODiOODnOODg+OCr+OCueOCkuWFpeWKm+W/hemgiOOBq+OBmeOCi+WgtOWQiOOBq+aMh+WumuOBl+OBvuOBmeOAgumAmuW4uCBgZm9ybWAg6KaB57Sg44Go5YWx44Gr5L2/55So44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc2VsZWN0LWlkXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JRCBnaXZlbiB0byB0aGUgaW5uZXIgc2VsZWN0LCB1c2VmdWwgZm9yIGR5bmFtaWMgbWFuaXB1bGF0aW9uLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruOCu+ODrOOCr+ODiOODnOODg+OCr+OCueOBjOWGhemDqOOBq+aMgeOBpCBzZWxlY3Qg6KaB57Sg44Gr5LiO44GI44KLIElEIOOCkuaMh+WumuOBl+OBvuOBmeOAguOCu+ODrOOCr+ODiOODnOODg+OCr+OCueOBruWGheWuueOCkuWLleeahOOBq+WkieabtOOBmeOCi+W/heimgeOBjOOBguOCi+WgtOWQiOOBq+S9v+eUqOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHNpemVcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgMVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSG93IG1hbnkgb3B0aW9ucyBhcmUgZGlzcGxheWVkOyBpZiB0aGVyZSBhcmUgbW9yZSB0aGFuIHRoZSBzaXplIHRoZW4gYSBzY3JvbGwgYXBwZWFycyB0byBuYXZpZ2F0ZSB0aGVtLlsvZW5dXG4gICAqICAgW2phXeS4gOW6puOBq+ihqOekuuOBmeOCi+mBuOaKnuiCouOBruWAi+aVsOOCkuaMh+WumuOBl+OBvuOBmeOAgumBuOaKnuiCouOBjOOBk+OBruWxnuaAp+OBp+aMh+WumuOBl+OBn+WAi+aVsOOCiOOCiuOCguWkmuOBhOWgtOWQiOOAgeOCueOCr+ODreODvOODq+OBjOacieWKueOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fY29tcGlsZSgpKTtcblxuICAgIHRoaXMuX2Rlcml2ZUdldHRlcnMoKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJywgJ2NsYXNzJywgLi4uSU5QVVRfQVRUUklCVVRFU107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnY2xhc3MnOlxuICAgICAgICB1dGlsLnJlc3RvcmVDbGFzcyh0aGlzLCBkZWZhdWx0Q2xhc3NOYW1lLCBzY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ21vZGlmaWVyJzpcbiAgICAgICAgTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGlmIChJTlBVVF9BVFRSSUJVVEVTLmluZGV4T2YobmFtZSkgPj0gMCkge1xuICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX3VwZGF0ZUJvdW5kQXR0cmlidXRlcygpKTtcbiAgICB9XG4gIH1cblxuICBnZXQgX3NlbGVjdCgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKCdzZWxlY3QnKTtcbiAgfVxuXG4gIF91cGRhdGVCb3VuZEF0dHJpYnV0ZXMoKSB7XG4gICAgSU5QVVRfQVRUUklCVVRFUy5mb3JFYWNoKChhdHRyKSA9PiB7XG4gICAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoYXR0cikpIHtcbiAgICAgICAgdGhpcy5fc2VsZWN0LnNldEF0dHJpYnV0ZShhdHRyLCB0aGlzLmdldEF0dHJpYnV0ZShhdHRyKSk7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgdGhpcy5fc2VsZWN0LnJlbW92ZUF0dHJpYnV0ZShhdHRyKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgbGVuZ3RoXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1OdW1iZXIgb2Ygb3B0aW9ucyBpbiB0aGUgc2VsZWN0IGJveC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jgrvjg6zjgq/jg4jjg5zjg4Pjgq/jgrnjgavlkKvjgb7jgozjgovpgbjmip7ogqLjga7lgIvmlbDjgpLov5TjgZfjgb7jgZnjgIIgYHNlbGVjdGAg6KaB57SgWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvcHRpb25zXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TZXZlcmFsIG9wdGlvbnMgZm9yIGhhbmRsaW5nIHRoZSBzZWxlY3QgRE9NIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jgrvjg6zjgq/jg4jjg5zjg4Pjgq/jgrnjgavlkKvjgb7jgozjgosgYG9wdGlvbmAg6KaB57Sg44Gu6YWN5YiX44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBzZWxlY3RlZEluZGV4XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JbmRleCBvZiB0aGUgY3VycmVudGx5IHNlbGVjdGVkIG9wdGlvbi5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjpgbjmip7jgZXjgozjgabjgYTjgovpgbjmip7ogqLjga7jgqTjg7Pjg4fjg4Pjgq/jgrnjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZhbHVlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1WYWx1ZSBvZiB0aGUgY3VycmVudGx5IHNlbGVjdGVkIG9wdGlvbi5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjpgbjmip7jgZXjgozjgabjgYTjgovpgbjmip7ogqLjga7lgKTjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG5cbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG4gICAgY29uc3Qgc2VsID0gdGhpcy5fc2VsZWN0IHx8IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NlbGVjdCcpO1xuICAgIGlmICghc2VsLmlkICYmIHRoaXMuaGFzQXR0cmlidXRlKCdzZWxlY3QtaWQnKSkge1xuICAgICAgc2VsLmlkID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3NlbGVjdC1pZCcpO1xuICAgIH1cbiAgICBzZWwuY2xhc3NMaXN0LmFkZCgnc2VsZWN0LWlucHV0Jyk7XG4gICAgaWYgKCF0aGlzLl9zZWxlY3QpIHtcbiAgICAgIHV0aWwuYXJyYXlGcm9tKHRoaXMuY2hpbGROb2RlcykuZm9yRWFjaChlbGVtZW50ID0+IHNlbC5hcHBlbmRDaGlsZChlbGVtZW50KSk7XG4gICAgICB0aGlzLmFwcGVuZENoaWxkKHNlbCk7XG4gICAgfVxuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgX2Rlcml2ZUdldHRlcnMoKSB7XG4gICAgWydkaXNhYmxlZCcsICdsZW5ndGgnLCAnbXVsdGlwbGUnLCAnbmFtZScsICdvcHRpb25zJywgJ3NlbGVjdGVkSW5kZXgnLCAnc2l6ZScsICd2YWx1ZScsICdmb3JtJywgJ3R5cGUnXVxuICAgICAgLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIGtleSwge1xuICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgIGdldDogKCkgPT4gdGhpcy5fc2VsZWN0W2tleV0sXG4gICAgICAgICAgc2V0OiBbJ2Zvcm0nLCAndHlwZSddLmluZGV4T2Yoa2V5KSA9PT0gLTFcbiAgICAgICAgICAgID8gdmFsdWUgPT4gY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX3NlbGVjdFtrZXldID0gdmFsdWUpXG4gICAgICAgICAgICA6IHVuZGVmaW5lZFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgYWRkKG9wdGlvbiwgaW5kZXggPSBudWxsKSB7XG4gICAgdGhpcy5fc2VsZWN0LmFkZChvcHRpb24sIGluZGV4KTtcbiAgfVxuXG4gIHJlbW92ZShpbmRleCkge1xuICAgIHRoaXMuX3NlbGVjdC5yZW1vdmUoaW5kZXgpO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLlNlbGVjdCA9IFNlbGVjdEVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1zZWxlY3QnLCBTZWxlY3RFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcblxuY29uc3QgZGVmYXVsdENsYXNzTmFtZSA9ICdmYWIgZmFiLS1taW5pIHNwZWVkLWRpYWxfX2l0ZW0nO1xuXG5jb25zdCBzY2hlbWUgPSB7XG4gICcnOiAnZmFiLS0qIHNwZWVkLWRpYWxfX2l0ZW0tLSonXG59O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1zcGVlZC1kaWFsLWl0ZW1cbiAqIEBjYXRlZ29yeSBjb250cm9sXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIFRoaXMgY29tcG9uZW50IGRpc3BsYXlzIHRoZSBjaGlsZCBlbGVtZW50cyBvZiB0aGUgTWF0ZXJpYWwgRGVzaWduIFNwZWVkIGRpYWwgY29tcG9uZW50LlxuICogICBbL2VuXVxuICogICBbamFdXG4gKiAgICAgTWF0ZXJpYWwgRGVzaWdu44GuU3BlZWQgZGlhbOOBruWtkOimgee0oOOCkuihqOePvuOBmeOCi+imgee0oOOBp+OBmeOAglxuICogICBbL2phXVxuICogQGNvZGVwZW4gZFlRWUxnXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2Uvc3BlZWQtZGlhbFxuICogQHNlZWFsc28gb25zLXNwZWVkLWRpYWxcbiAqICAgW2VuXVRoZSBgPG9ucy1zcGVlZC1kaWFsPmAgY29tcG9uZW50LlsvZW5dXG4gKiAgIFtqYV1vbnMtc3BlZWQtZGlhbOOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtZmFiXG4gKiAgIFtlbl1vbnMtZmFiIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtZmFi44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXNwZWVkLWRpYWwgcG9zaXRpb249XCJsZWZ0IGJvdHRvbVwiPlxuICogICA8b25zLWZhYj5cbiAqICAgICA8b25zLWljb24gaWNvbj1cImZhLXR3aXR0ZXJcIj48L29ucy1pY29uPlxuICogICA8L29ucy1mYWI+XG4gKiAgIDxvbnMtc3BlZWQtZGlhbC1pdGVtPkE8L29ucy1zcGVlZC1kaWFsLWl0ZW0+XG4gKiAgIDxvbnMtc3BlZWQtZGlhbC1pdGVtPkI8L29ucy1zcGVlZC1kaWFsLWl0ZW0+XG4gKiAgIDxvbnMtc3BlZWQtZGlhbC1pdGVtPkM8L29ucy1zcGVlZC1kaWFsLWl0ZW0+XG4gKiA8L29ucy1zcGVlZC1kaWFsPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTcGVlZERpYWxJdGVtRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIGNvbXBvbmVudC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSByaXBwbGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgZGVmaW5lZCwgdGhlIGJ1dHRvbiB3aWxsIGhhdmUgYSByaXBwbGUgZWZmZWN0IHdoZW4gdGFwcGVkLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX2NvbXBpbGUoKTtcbiAgICB0aGlzLl9ib3VuZE9uQ2xpY2sgPSB0aGlzLl9vbkNsaWNrLmJpbmQodGhpcyk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllcicsICdyaXBwbGUnLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgdXRpbC5hZGRNb2RpZmllcih0aGlzLCAnbWluaScpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3JpcHBsZSc6XG4gICAgICAgIHRoaXMuX3VwZGF0ZVJpcHBsZSgpO1xuICAgIH1cbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9ib3VuZE9uQ2xpY2ssIGZhbHNlKTtcbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9ib3VuZE9uQ2xpY2ssIGZhbHNlKTtcbiAgfVxuXG4gIF91cGRhdGVSaXBwbGUoKSB7XG4gICAgdXRpbC51cGRhdGVSaXBwbGUodGhpcyk7XG4gIH1cblxuICBfb25DbGljayhlKSB7XG4gICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIGF1dG9TdHlsZS5wcmVwYXJlKHRoaXMpO1xuXG4gICAgZGVmYXVsdENsYXNzTmFtZS5zcGxpdCgvXFxzKy8pLmZvckVhY2godG9rZW4gPT4gdGhpcy5jbGFzc0xpc3QuYWRkKHRva2VuKSk7XG5cbiAgICB1dGlsLmFkZE1vZGlmaWVyKHRoaXMsICdtaW5pJyk7XG4gICAgdGhpcy5fdXBkYXRlUmlwcGxlKCk7XG5cbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHNjaGVtZSk7XG4gIH1cbn1cblxub25zRWxlbWVudHMuU3BlZWREaWFsSXRlbSA9IFNwZWVkRGlhbEl0ZW1FbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtc3BlZWQtZGlhbC1pdGVtJywgU3BlZWREaWFsSXRlbUVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5pbXBvcnQgc3R5bGVyIGZyb20gJy4uL29ucy9zdHlsZXInO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ3NwZWVkLWRpYWwnO1xuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ3NwZWVkLWRpYWwtLSonLFxufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtc3BlZWQtZGlhbFxuICogQGNhdGVnb3J5IGNvbnRyb2xcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgRWxlbWVudCB0aGF0IGRpc3BsYXlzIGEgTWF0ZXJpYWwgRGVzaWduIFNwZWVkIERpYWxvZyBjb21wb25lbnQuIEl0IGlzIHVzZWZ1bCB3aGVuIHRoZXJlIGFyZSBtb3JlIHRoYW4gb25lIHByaW1hcnkgYWN0aW9uIHRoYXQgY2FuIGJlIHBlcmZvcm1lZCBpbiBhIHBhZ2UuXG4gKlxuICogICAgIFRoZSBTcGVlZCBkaWFsIGxvb2tzIGxpa2UgYSBgPG9ucy1mYWI+YCBlbGVtZW50IGJ1dCB3aWxsIGV4cGFuZCBhIG1lbnUgd2hlbiB0YXBwZWQuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGNvZGVwZW4gZFlRWUxnXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2Uvc3BlZWQtZGlhbFxuICogQHNlZWFsc28gb25zLXNwZWVkLWRpYWwtaXRlbVxuICogICBbZW5dVGhlIGA8b25zLXNwZWVkLWRpYWwtaXRlbT5gIHJlcHJlc2VudHMgYSBtZW51IGl0ZW0uWy9lbl1cbiAqICAgW2phXW9ucy1zcGVlZC1kaWFsLWl0ZW3jgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLWZhYlxuICogICBbZW5db25zLWZhYiBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLWZhYuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1zcGVlZC1kaWFsIHBvc2l0aW9uPVwibGVmdCBib3R0b21cIj5cbiAqICAgPG9ucy1mYWI+XG4gKiAgICAgPG9ucy1pY29uIGljb249XCJmYS10d2l0dGVyXCI+PC9vbnMtaWNvbj5cbiAqICAgPC9vbnMtZmFiPlxuICogICA8b25zLXNwZWVkLWRpYWwtaXRlbT5BPC9vbnMtc3BlZWQtZGlhbC1pdGVtPlxuICogICA8b25zLXNwZWVkLWRpYWwtaXRlbT5CPC9vbnMtc3BlZWQtZGlhbC1pdGVtPlxuICogICA8b25zLXNwZWVkLWRpYWwtaXRlbT5DPC9vbnMtc3BlZWQtZGlhbC1pdGVtPlxuICogPC9vbnMtc3BlZWQtZGlhbD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3BlZWREaWFsRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGV2ZW50IG9wZW5cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIG1lbnUgaXRlbXMgYXJlIHNob3duLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgY2xvc2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIG1lbnUgaXRlbXMgYXJlIGhpZGRlbi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIGNvbXBvbmVudC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSByaXBwbGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgZGVmaW5lZCwgdGhlIGJ1dHRvbiB3aWxsIGhhdmUgYSByaXBwbGUgZWZmZWN0IHdoZW4gdGFwcGVkLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgcG9zaXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgU3BlY2lmeSB0aGUgdmVydGljYWwgYW5kIGhvcml6b250YWwgcG9zaXRpb24gb2YgdGhlIGNvbXBvbmVudC5cbiAgICogICAgIEkuZS4gdG8gZGlzcGxheSBpdCBpbiB0aGUgdG9wIHJpZ2h0IGNvcm5lciBzcGVjaWZ5IFwicmlnaHQgdG9wXCIuXG4gICAqICAgICBDaG9vc2UgZnJvbSBcInJpZ2h0XCIsIFwibGVmdFwiLCBcInRvcFwiIGFuZCBcImJvdHRvbVwiLlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXVxuICAgKiAgICAg44GT44Gu6KaB57Sg44KS6KGo56S644GZ44KL5bem5Y+z44Go5LiK5LiL44Gu5L2N572u44KS5oyH5a6a44GX44G+44GZ44CCXG4gICAqICAgICDkvovjgYjjgbDjgIHlj7PkuIrjgavooajnpLrjgZnjgovloLTlkIjjgavjga9cInJpZ2h0IHRvcFwi44KS5oyH5a6a44GX44G+44GZ44CCXG4gICAqICAgICDlt6blj7PjgajkuIrkuIvjga7kvY3nva7jga7mjIflrprjgavjga/jgIFyaWdodOOBqGxlZnTjgIF0b3Djgahib3R0b23jgYzjgZ3jgozjgZ7jgozmjIflrprjgafjgY3jgb7jgZnjgIJcbiAgICogICBbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXJlY3Rpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGRpcmVjdGlvbiB0aGUgaXRlbXMgYXJlIGRpc3BsYXllZC4gUG9zc2libGUgdmFsdWVzIGFyZSBcInVwXCIsIFwiZG93blwiLCBcImxlZnRcIiBhbmQgXCJyaWdodFwiLlsvZW5dXG4gICAqICAgW2phXVxuICAgKiAgICAg6KaB57Sg44GM6KGo56S644GZ44KL5pa55ZCR44KS5oyH5a6a44GX44G+44GZ44CCdXAsIGRvd24sIGxlZnQsIHJpZ2h044GM5oyH5a6a44Gn44GN44G+44GZ44CCXG4gICAqICAgWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZGlzYWJsZWRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgaWYgYnV0dG9uIHNob3VsZCBiZSBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZnjgovloLTlkIjjgavmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2NvbXBpbGUoKTtcbiAgICB9KTtcblxuICAgIHRoaXMuX2l0ZW1TaG93biA9IGZhbHNlO1xuICAgIHRoaXMuX2JvdW5kT25DbGljayA9IHRoaXMuX29uQ2xpY2suYmluZCh0aGlzKTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIHRoaXMuY2xhc3NMaXN0LmFkZChkZWZhdWx0Q2xhc3NOYW1lKTtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcbiAgICB0aGlzLl91cGRhdGVSaXBwbGUoKTtcbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHNjaGVtZSk7XG5cbiAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ2RpcmVjdGlvbicpKSB7XG4gICAgICB0aGlzLl91cGRhdGVEaXJlY3Rpb24odGhpcy5nZXRBdHRyaWJ1dGUoJ2RpcmVjdGlvbicpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fdXBkYXRlRGlyZWN0aW9uKCd1cCcpO1xuICAgIH1cblxuICAgIHRoaXMuX3VwZGF0ZVBvc2l0aW9uKCk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydjbGFzcycsICdtb2RpZmllcicsICdyaXBwbGUnLCAnZGlyZWN0aW9uJywgJ3Bvc2l0aW9uJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnY2xhc3MnOlxuICAgICAgICB1dGlsLnJlc3RvcmVDbGFzcyh0aGlzLCBkZWZhdWx0Q2xhc3NOYW1lLCBzY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ21vZGlmaWVyJzpcbiAgICAgICAgTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncmlwcGxlJzpcbiAgICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX3VwZGF0ZVJpcHBsZSgpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdkaXJlY3Rpb24nOlxuICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fdXBkYXRlRGlyZWN0aW9uKGN1cnJlbnQpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdwb3NpdGlvbic6XG4gICAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl91cGRhdGVQb3NpdGlvbigpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kT25DbGljaywgZmFsc2UpO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kT25DbGljaywgZmFsc2UpO1xuICB9XG5cbiAgZ2V0IGl0ZW1zKCkge1xuICAgIHJldHVybiB1dGlsLmFycmF5RnJvbSh0aGlzLnF1ZXJ5U2VsZWN0b3JBbGwoJ29ucy1zcGVlZC1kaWFsLWl0ZW0nKSk7XG4gIH1cblxuICBnZXQgX2ZhYigpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJ29ucy1mYWInKTtcbiAgfVxuXG4gIF9vbkNsaWNrKGUpIHtcbiAgICBpZiAodGhpcy5vbkNsaWNrKSB7XG4gICAgICB0aGlzLm9uQ2xpY2suYXBwbHkodGhpcyk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfSBlbHNlIGlmICghdGhpcy5kaXNhYmxlZCAmJiB0aGlzLnZpc2libGUpIHtcbiAgICAgIHJldHVybiB0aGlzLnRvZ2dsZUl0ZW1zKCk7XG4gICAgfVxuICB9XG5cbiAgX3Nob3coKSB7XG4gICAgaWYgKCF0aGlzLmlubGluZSkge1xuICAgICAgcmV0dXJuIHRoaXMuc2hvdygpO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICBfaGlkZSgpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICBpZiAoIXRoaXMuaW5saW5lKSB7XG4gICAgICAgIHNldEltbWVkaWF0ZSgoKSA9PiB0aGlzLmhpZGUoKS50aGVuKHJlc29sdmUpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgX3VwZGF0ZVJpcHBsZSgpIHtcbiAgICBpZiAodGhpcy5fZmFiKSB7XG4gICAgICB0aGlzLmhhc0F0dHJpYnV0ZSgncmlwcGxlJykgPyB0aGlzLl9mYWIuc2V0QXR0cmlidXRlKCdyaXBwbGUnLCAnJykgOiB0aGlzLl9mYWIucmVtb3ZlQXR0cmlidXRlKCdyaXBwbGUnKTtcbiAgICB9XG4gIH1cblxuICBfdXBkYXRlRGlyZWN0aW9uKGRpcmVjdGlvbikge1xuICAgIGNvbnN0IGNoaWxkcmVuID0gdGhpcy5pdGVtcztcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICBzdHlsZXIoY2hpbGRyZW5baV0sIHtcbiAgICAgICAgdHJhbnNpdGlvbkRlbGF5OiAyNSAqIGkgKyAnbXMnLFxuICAgICAgICBib3R0b206ICdhdXRvJyxcbiAgICAgICAgcmlnaHQ6ICdhdXRvJyxcbiAgICAgICAgdG9wOiAnYXV0bycsXG4gICAgICAgIGxlZnQ6ICdhdXRvJ1xuICAgICAgfSk7XG4gICAgfVxuICAgIHN3aXRjaCAoZGlyZWN0aW9uKSB7XG4gICAgICBjYXNlICd1cCc6XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBjaGlsZHJlbltpXS5zdHlsZS5ib3R0b20gPSA3MiArIDU2ICogaSArICdweCc7XG4gICAgICAgICAgY2hpbGRyZW5baV0uc3R5bGUucmlnaHQgPSAnOHB4JztcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2Rvd24nOlxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgY2hpbGRyZW5baV0uc3R5bGUudG9wID0gNzIgKyA1NiAqIGkgKyAncHgnO1xuICAgICAgICAgIGNoaWxkcmVuW2ldLnN0eWxlLmxlZnQgPSAnOHB4JztcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2xlZnQnOlxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgY2hpbGRyZW5baV0uc3R5bGUudG9wID0gJzhweCc7XG4gICAgICAgICAgY2hpbGRyZW5baV0uc3R5bGUucmlnaHQgPSA3MiArIDU2ICogaSArICdweCc7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdyaWdodCc6XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBjaGlsZHJlbltpXS5zdHlsZS50b3AgPSAnOHB4JztcbiAgICAgICAgICBjaGlsZHJlbltpXS5zdHlsZS5sZWZ0ID0gNzIgKyA1NiAqIGkgKyAncHgnO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdXRpbC50aHJvdygnQXJndW1lbnQgbXVzdCBiZSBvbmUgb2YgdXAsIGRvd24sIGxlZnQgb3IgcmlnaHQuJyk7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZVBvc2l0aW9uKCkge1xuICAgIGNvbnN0IHBvc2l0aW9uID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3Bvc2l0aW9uJyk7XG4gICAgdGhpcy5jbGFzc0xpc3QucmVtb3ZlKFxuICAgICAgJ2ZhYi0tdG9wX19sZWZ0JyxcbiAgICAgICdmYWItLWJvdHRvbV9fcmlnaHQnLFxuICAgICAgJ2ZhYi0tYm90dG9tX19sZWZ0JyxcbiAgICAgICdmYWItLXRvcF9fcmlnaHQnLFxuICAgICAgJ2ZhYi0tdG9wX19jZW50ZXInLFxuICAgICAgJ2ZhYi0tYm90dG9tX19jZW50ZXInKTtcbiAgICBzd2l0Y2ggKHBvc2l0aW9uKSB7XG4gICAgICBjYXNlICd0b3AgcmlnaHQnOlxuICAgICAgY2FzZSAncmlnaHQgdG9wJzpcbiAgICAgICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdmYWItLXRvcF9fcmlnaHQnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd0b3AgbGVmdCc6XG4gICAgICBjYXNlICdsZWZ0IHRvcCc6XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnZmFiLS10b3BfX2xlZnQnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdib3R0b20gcmlnaHQnOlxuICAgICAgY2FzZSAncmlnaHQgYm90dG9tJzpcbiAgICAgICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdmYWItLWJvdHRvbV9fcmlnaHQnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdib3R0b20gbGVmdCc6XG4gICAgICBjYXNlICdsZWZ0IGJvdHRvbSc6XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnZmFiLS1ib3R0b21fX2xlZnQnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdjZW50ZXIgdG9wJzpcbiAgICAgIGNhc2UgJ3RvcCBjZW50ZXInOlxuICAgICAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2ZhYi0tdG9wX19jZW50ZXInKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdjZW50ZXIgYm90dG9tJzpcbiAgICAgIGNhc2UgJ2JvdHRvbSBjZW50ZXInOlxuICAgICAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2ZhYi0tYm90dG9tX19jZW50ZXInKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICBfZ2V0VHJhbnNsYXRlKCkge1xuICAgIGNvbnN0IGlzQm90dG9tID0gKHRoaXMuZ2V0QXR0cmlidXRlKCdwb3NpdGlvbicpIHx8ICcnKS5pbmRleE9mKCdib3R0b20nKSA+PSAwO1xuICAgIGNvbnN0IHRyYW5zbGF0ZSA9IGlzQm90dG9tID8gYHRyYW5zbGF0ZTNkKDBweCwgLSR7dXRpbC5nbG9iYWxzLmZhYk9mZnNldCB8fCAwfXB4LCAwcHgpIGAgOiAnJztcbiAgICByZXR1cm4gdHJhbnNsYXRlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2Qgc2hvd1xuICAgKiBAc2lnbmF0dXJlIHNob3coKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyB0aGUgc3BlZWQgZGlhbC5bL2VuXVxuICAgKiAgIFtqYV1TcGVlZCBkaWFs44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHNob3coKSB7XG4gICAgdGhpcy5fZmFiLnNob3coKTtcbiAgICBzdHlsZXIodGhpcywgeyB0cmFuc2Zvcm06IHRoaXMuX2dldFRyYW5zbGF0ZSB9KTtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBoaWRlXG4gICAqIEBzaWduYXR1cmUgaGlkZSgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1IaWRlIHRoZSBzcGVlZCBkaWFsLlsvZW5dXG4gICAqICAgW2phXVNwZWVkIGRpYWzjgpLpnZ7ooajnpLrjgavjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgaGlkZSgpIHtcbiAgICByZXR1cm4gdGhpcy5oaWRlSXRlbXMoKS50aGVuKCgpPT4gdGhpcy5fZmFiLmhpZGUoKSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBzaG93SXRlbXNcbiAgICogQHNpZ25hdHVyZSBzaG93SXRlbXMoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyB0aGUgc3BlZWQgZGlhbCBpdGVtcy5bL2VuXVxuICAgKiAgIFtqYV1TcGVlZCBkaWFs44Gu5a2Q6KaB57Sg44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHNob3dJdGVtcygpIHtcbiAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ2RpcmVjdGlvbicpKSB7XG4gICAgICB0aGlzLl91cGRhdGVEaXJlY3Rpb24odGhpcy5nZXRBdHRyaWJ1dGUoJ2RpcmVjdGlvbicpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fdXBkYXRlRGlyZWN0aW9uKCd1cCcpO1xuICAgIH1cblxuICAgIGxldCB0b3RhbERlbGF5ID0gMDtcbiAgICBpZiAoIXRoaXMuX2l0ZW1TaG93bikge1xuICAgICAgY29uc3QgY2hpbGRyZW4gPSB0aGlzLml0ZW1zO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBkZWxheSA9IDI1ICogaTtcbiAgICAgICAgdG90YWxEZWxheSArPSBkZWxheTtcbiAgICAgICAgc3R5bGVyKGNoaWxkcmVuW2ldLCB7XG4gICAgICAgICAgdHJhbnNmb3JtOiAnc2NhbGUoMSknLFxuICAgICAgICAgIHRyYW5zaXRpb25EZWxheTogZGVsYXkgKyAnbXMnXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgdG90YWxEZWxheSArPSA1MDtcblxuICAgICAgdGhpcy5faXRlbVNob3duID0gdHJ1ZTtcbiAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnb3BlbicpO1xuICAgIH1cblxuICAgIGNvbnN0IGRlZmVycmVkID0gdXRpbC5kZWZlcigpO1xuICAgIHNldFRpbWVvdXQoZGVmZXJyZWQucmVzb2x2ZSwgdG90YWxEZWxheSk7XG4gICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2U7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBoaWRlSXRlbXNcbiAgICogQHNpZ25hdHVyZSBoaWRlSXRlbXMoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSGlkZSB0aGUgc3BlZWQgZGlhbCBpdGVtcy5bL2VuXVxuICAgKiAgIFtqYV1TcGVlZCBkaWFs44Gu5a2Q6KaB57Sg44KS6Z2e6KGo56S644Gr44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGhpZGVJdGVtcygpIHtcbiAgICBsZXQgdG90YWxEZWxheSA9IDA7XG4gICAgaWYgKHRoaXMuX2l0ZW1TaG93bikge1xuICAgICAgY29uc3QgY2hpbGRyZW4gPSB0aGlzLml0ZW1zO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBkZWxheSA9IDI1ICogKGNoaWxkcmVuLmxlbmd0aCAtIGkpO1xuICAgICAgICB0b3RhbERlbGF5ICs9IGRlbGF5O1xuICAgICAgICBzdHlsZXIoY2hpbGRyZW5baV0sIHtcbiAgICAgICAgICB0cmFuc2Zvcm06ICdzY2FsZSgwKScsXG4gICAgICAgICAgdHJhbnNpdGlvbkRlbGF5OiBkZWxheSArICdtcydcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICB0b3RhbERlbGF5ICs9IDUwO1xuXG4gICAgICB0aGlzLl9pdGVtU2hvd24gPSBmYWxzZTtcbiAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnY2xvc2UnKTtcbiAgICB9XG5cbiAgICBjb25zdCBkZWZlcnJlZCA9IHV0aWwuZGVmZXIoKTtcbiAgICBzZXRUaW1lb3V0KGRlZmVycmVkLnJlc29sdmUsIHRvdGFsRGVsYXkpO1xuICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgZGlzYWJsZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeeEoeWKueWMluOBleOCjOOBpuOBhOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuICBzZXQgZGlzYWJsZWQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIHRoaXMuaGlkZUl0ZW1zKCk7XG4gICAgfVxuICAgIHV0aWwuYXJyYXlGcm9tKHRoaXMuY2hpbGRyZW4pLmZvckVhY2goZSA9PiB7XG4gICAgICB1dGlsLm1hdGNoKGUsICcuZmFiJykgJiYgdXRpbC50b2dnbGVBdHRyaWJ1dGUoZSwgJ2Rpc2FibGVkJywgdmFsdWUpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdkaXNhYmxlZCcsIHZhbHVlKTtcbiAgfVxuXG4gIGdldCBkaXNhYmxlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGlubGluZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIGlubGluZSBvciBub3QuWy9lbl1cbiAgICogICBbamFd44Kk44Oz44Op44Kk44Oz6KaB57Sg44Gu5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG4gIGdldCBpbmxpbmUoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdpbmxpbmUnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdmlzaWJsZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIHZpc2libGUgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeimgee0oOOBjOimi+OBiOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuICBnZXQgdmlzaWJsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fZmFiLnZpc2libGUgJiYgdGhpcy5zdHlsZS5kaXNwbGF5ICE9PSAnbm9uZSc7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc09wZW5cbiAgICogQHNpZ25hdHVyZSBpc09wZW4oKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBtZW51IGlzIG9wZW4gb3Igbm90LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBpc09wZW4oKSB7XG4gICAgcmV0dXJuIHRoaXMuX2l0ZW1TaG93bjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHRvZ2dsZVxuICAgKiBAc2lnbmF0dXJlIHRvZ2dsZSgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Ub2dnbGUgdmlzaWJpbGl0eS5bL2VuXVxuICAgKiAgIFtqYV1TcGVlZCBkaWFs44Gu6KGo56S66Z2e6KGo56S644KS5YiH44KK5pu/44GI44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHRvZ2dsZSgpIHtcbiAgICByZXR1cm4gdGhpcy52aXNpYmxlID8gdGhpcy5oaWRlKCkgOiB0aGlzLnNob3coKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHRvZ2dsZUl0ZW1zXG4gICAqIEBzaWduYXR1cmUgdG9nZ2xlSXRlbXMoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVG9nZ2xlIGl0ZW0gdmlzaWJpbGl0eS5bL2VuXVxuICAgKiAgIFtqYV1TcGVlZCBkaWFs44Gu5a2Q6KaB57Sg44Gu6KGo56S66Z2e6KGo56S644KS5YiH44KK5pu/44GI44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHRvZ2dsZUl0ZW1zKCkge1xuICAgIHJldHVybiB0aGlzLmlzT3BlbigpID8gdGhpcy5oaWRlSXRlbXMoKSA6IHRoaXMuc2hvd0l0ZW1zKCk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IGV2ZW50cygpIHtcbiAgICByZXR1cm4gWydvcGVuJywgJ2Nsb3NlJ107XG4gIH1cbn1cblxub25zRWxlbWVudHMuU3BlZWREaWFsID0gU3BlZWREaWFsRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXNwZWVkLWRpYWwnLCBTcGVlZERpYWxFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uL29ucy9pbnRlcm5hbCc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCB7UGFnZUxvYWRlciwgZGVmYXVsdFBhZ2VMb2FkZXJ9IGZyb20gJy4uL29ucy9wYWdlLWxvYWRlcic7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3QgcmV3cml0YWJsZXMgPSB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHJlYWR5KGVsZW1lbnQsIGNhbGxiYWNrKSB7XG4gICAgc2V0SW1tZWRpYXRlKGNhbGxiYWNrKTtcbiAgfVxufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtc3BsaXR0ZXItY29udGVudFxuICogQGNhdGVnb3J5IG1lbnVcbiAqIEBkZXNjcmlwdGlvblxuICogIFtlbl1cbiAqICAgIFRoZSBgPG9ucy1zcGxpdHRlci1jb250ZW50PmAgZWxlbWVudCBpcyB1c2VkIGFzIGEgY2hpbGQgZWxlbWVudCBvZiBgPG9ucy1zcGxpdHRlcj5gLlxuICpcbiAqICAgIEl0IGNvbnRhaW5zIHRoZSBtYWluIGNvbnRlbnQgb2YgdGhlIHBhZ2Ugd2hpbGUgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGNvbnRhaW5zIHRoZSBsaXN0LlxuICogIFsvZW5dXG4gKiAgW2phXW9ucy1zcGxpdHRlci1jb250ZW506KaB57Sg44Gv44CBb25zLXNwbGl0dGVy6KaB57Sg44Gu5a2Q6KaB57Sg44Go44GX44Gm5Yip55So44GX44G+44GZ44CCWy9qYV1cbiAqIEBjb2RlcGVuIHJPUU9NTFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3NwbGl0dGVyXG4gKiBAZ3VpZGUgZnVuZGFtZW50YWxzLmh0bWwjbWFuYWdpbmctcGFnZXNcbiAqICBbZW5dTWFuYWdpbmcgbXVsdGlwbGUgcGFnZXMuWy9lbl1cbiAqICBbamFd6KSH5pWw44Gu44Oa44O844K444KS566h55CG44GZ44KLWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zcGxpdHRlclxuICogIFtlbl1UaGUgYDxvbnMtc3BsaXR0ZXI+YCBjb21wb25lbnQgaXMgdGhlIHBhcmVudCBlbGVtZW50LlsvZW5dXG4gKiAgW2phXW9ucy1zcGxpdHRlcuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtc3BsaXR0ZXItc2lkZVxuICogIFtlbl1UaGUgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGNvbXBvbmVudCBjb250YWlucyB0aGUgbWVudS5bL2VuXVxuICogIFtqYV1vbnMtc3BsaXR0ZXItc2lkZeOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1zcGxpdHRlcj5cbiAqICAgPG9ucy1zcGxpdHRlci1jb250ZW50PlxuICogICAgIC4uLlxuICogICA8L29ucy1zcGxpdHRlci1jb250ZW50PlxuICpcbiAqICAgPG9ucy1zcGxpdHRlci1zaWRlIHNpZGU9XCJsZWZ0XCIgd2lkdGg9XCI4MCVcIiBjb2xsYXBzZT5cbiAqICAgICAuLi5cbiAqICAgPC9vbnMtc3BsaXR0ZXItc2lkZT5cbiAqIDwvb25zLXNwbGl0dGVyPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTcGxpdHRlckNvbnRlbnRFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHBhZ2VcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgVGhlIHVybCBvZiB0aGUgY29udGVudCBwYWdlLiBJZiB0aGlzIGF0dHJpYnV0ZSBpcyB1c2VkIHRoZSBjb250ZW50IHdpbGwgYmUgbG9hZGVkIGZyb20gYSBgPHRlbXBsYXRlPmAgdGFnIG9yIGEgcmVtb3RlIGZpbGUuXG4gICAqXG4gICAqICAgICBJdCBpcyBhbHNvIHBvc3NpYmxlIHRvIHB1dCBgPG9ucy1wYWdlPmAgZWxlbWVudCBhcyBhIGNoaWxkIG9mIHRoZSBlbGVtZW50LlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXW9ucy1zcGxpdHRlci1jb250ZW506KaB57Sg44Gr6KGo56S644GZ44KL44Oa44O844K444GuVVJM44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX3BhZ2UgPSBudWxsO1xuICAgIHRoaXMuX3BhZ2VMb2FkZXIgPSBkZWZhdWx0UGFnZUxvYWRlcjtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICByZXdyaXRhYmxlcy5yZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHBhZ2UgPSB0aGlzLl9nZXRQYWdlVGFyZ2V0KCk7XG5cbiAgICAgICAgaWYgKHBhZ2UpIHtcbiAgICAgICAgICB0aGlzLmxvYWQocGFnZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgaWYgKCF1dGlsLm1hdGNoKHRoaXMucGFyZW50Tm9kZSwgJ29ucy1zcGxpdHRlcicpKSB7XG4gICAgICB1dGlsLnRocm93KCdcIm9ucy1zcGxpdHRlci1jb250ZW50XCIgbXVzdCBoYXZlIFwib25zLXNwbGl0dGVyXCIgYXMgcGFyZW50Jyk7XG4gICAgfVxuICB9XG5cbiAgX2dldFBhZ2VUYXJnZXQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BhZ2UgfHwgdGhpcy5nZXRBdHRyaWJ1dGUoJ3BhZ2UnKTtcbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge31cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBwYWdlXG4gICAqIEB0eXBlIHtIVE1MRWxlbWVudH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBwYWdlIHRvIGxvYWQgaW4gdGhlIHNwbGl0dGVyIGNvbnRlbnQuWy9lbl1cbiAgICogICBbamFd44GT44Gu6KaB57Sg5YaF44Gr6KGo56S644GZ44KL44Oa44O844K444KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGdldCBwYWdlKCkge1xuICAgIHJldHVybiB0aGlzLl9wYWdlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7Kn0gcGFnZVxuICAgKi9cbiAgc2V0IHBhZ2UocGFnZSkge1xuICAgIHRoaXMuX3BhZ2UgPSBwYWdlO1xuICB9XG5cbiAgZ2V0IF9jb250ZW50KCkge1xuICAgIHJldHVybiB0aGlzLmNoaWxkcmVuWzBdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBwYWdlTG9hZGVyXG4gICAqIEB0eXBlIHtGdW5jdGlvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVBhZ2UgZWxlbWVudCBsb2FkZWQgaW4gdGhlIHNwbGl0dGVyIGNvbnRlbnQuWy9lbl1cbiAgICogICBbamFd44GT44Gu6KaB57Sg5YaF44Gr6KGo56S644GZ44KL44Oa44O844K444KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGdldCBwYWdlTG9hZGVyKCkge1xuICAgIHJldHVybiB0aGlzLl9wYWdlTG9hZGVyO1xuICB9XG5cbiAgc2V0IHBhZ2VMb2FkZXIobG9hZGVyKSB7XG4gICAgaWYgKCEobG9hZGVyIGluc3RhbmNlb2YgUGFnZUxvYWRlcikpIHtcbiAgICAgIHV0aWwudGhyb3dQYWdlTG9hZGVyKCk7XG4gICAgfVxuICAgIHRoaXMuX3BhZ2VMb2FkZXIgPSBsb2FkZXI7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBsb2FkXG4gICAqIEBzaWduYXR1cmUgbG9hZChwYWdlLCBbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwYWdlLCBbb3B0aW9uc11cbiAgICogICBbZW5dUGFnZSBVUkwuIENhbiBiZSBlaXRoZXIgYW4gSFRNTCBkb2N1bWVudCBvciBhbiBgPHRlbXBsYXRlPmAgaWQuWy9lbl1cbiAgICogICBbamFdcGFnZeOBrlVSTOOBi+OAgWA8dGVtcGxhdGU+YOOBp+Wuo+iogOOBl+OBn+ODhuODs+ODl+ODrOODvOODiOOBrmlk5bGe5oCn44Gu5YCk44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNob3cgdGhlIHBhZ2Ugc3BlY2lmaWVkIGluIGBwYWdlYCBpbiB0aGUgY29udGVudC5bL2VuXVxuICAgKiAgIFtqYV3mjIflrprjgZfjgZ9VUkzjgpLjg6HjgqTjg7Pjg5rjg7zjgrjjgpLoqq3jgb/ovrzjgb/jgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgbmV3IGA8b25zLXBhZ2U+YCBlbGVtZW50Wy9lbl1cbiAgICogICBbamFdYDxvbnMtcGFnZT5g6KaB57Sg44KS6Kej5rG644GZ44KLUHJvbWlzZeOCquODluOCuOOCp+OCr+ODiOOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBsb2FkKHBhZ2UsIG9wdGlvbnMgPSB7fSkge1xuICAgIHRoaXMuX3BhZ2UgPSBwYWdlO1xuICAgIGNvbnN0IGNhbGxiYWNrID0gb3B0aW9ucy5jYWxsYmFjayB8fCBmdW5jdGlvbigpIHt9O1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgbGV0IG9sZENvbnRlbnQgPSB0aGlzLl9jb250ZW50IHx8IG51bGw7XG5cbiAgICAgIHRoaXMuX3BhZ2VMb2FkZXIubG9hZCh7cGFnZSwgcGFyZW50OiB0aGlzfSwgcGFnZUVsZW1lbnQgPT4ge1xuICAgICAgICBpZiAob2xkQ29udGVudCkge1xuICAgICAgICAgIHRoaXMuX3BhZ2VMb2FkZXIudW5sb2FkKG9sZENvbnRlbnQpO1xuICAgICAgICAgIG9sZENvbnRlbnQgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHRoaXMuX3Nob3coKSk7XG5cbiAgICAgICAgY2FsbGJhY2socGFnZUVsZW1lbnQpO1xuICAgICAgICByZXNvbHZlKHBhZ2VFbGVtZW50KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgX3Nob3coKSB7XG4gICAgaWYgKHRoaXMuX2NvbnRlbnQpIHtcbiAgICAgIHRoaXMuX2NvbnRlbnQuX3Nob3coKTtcbiAgICB9XG4gIH1cblxuICBfaGlkZSgpIHtcbiAgICBpZiAodGhpcy5fY29udGVudCkge1xuICAgICAgdGhpcy5fY29udGVudC5faGlkZSgpO1xuICAgIH1cbiAgfVxuXG4gIF9kZXN0cm95KCkge1xuICAgIGlmICh0aGlzLl9jb250ZW50KSB7XG4gICAgICB0aGlzLl9wYWdlTG9hZGVyLnVubG9hZCh0aGlzLl9jb250ZW50KTtcbiAgICB9XG4gICAgdGhpcy5yZW1vdmUoKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgcmV3cml0YWJsZXMoKSB7XG4gICAgcmV0dXJuIHJld3JpdGFibGVzO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLlNwbGl0dGVyQ29udGVudCA9IFNwbGl0dGVyQ29udGVudEVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1zcGxpdHRlci1jb250ZW50JywgU3BsaXR0ZXJDb250ZW50RWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTcGxpdHRlck1hc2tFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9ib3VuZE9uQ2xpY2sgPSB0aGlzLl9vbkNsaWNrLmJpbmQodGhpcyk7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIGlmICh0aGlzLnBhcmVudE5vZGUuX3NpZGVzLmV2ZXJ5KHNpZGUgPT4gc2lkZS5tb2RlID09PSAnc3BsaXQnKSkge1xuICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZSgnc3R5bGUnLCAnZGlzcGxheTogbm9uZSAhaW1wb3J0YW50Jyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBfb25DbGljayhldmVudCkge1xuICAgIGlmICh0aGlzLm9uQ2xpY2sgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgdGhpcy5vbkNsaWNrKCk7XG4gICAgfSBlbHNlIGlmICh1dGlsLm1hdGNoKHRoaXMucGFyZW50Tm9kZSwgJ29ucy1zcGxpdHRlcicpKSB7XG4gICAgICB0aGlzLnBhcmVudE5vZGUuX3NpZGVzLmZvckVhY2goc2lkZSA9PiBzaWRlLmNsb3NlKCdsZWZ0JykuY2F0Y2goKCkgPT4ge30pKTtcbiAgICB9XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kT25DbGljayk7XG4gICAgdXRpbC5pb3NNYXNrU2Nyb2xsRml4KHRoaXMsIHRydWUpO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kT25DbGljayk7XG4gICAgdXRpbC5pb3NNYXNrU2Nyb2xsRml4KHRoaXMsIGZhbHNlKTtcbiAgfVxufVxuXG5vbnNFbGVtZW50cy5TcGxpdHRlck1hc2sgPSBTcGxpdHRlck1hc2tFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtc3BsaXR0ZXItbWFzaycsIFNwbGl0dGVyTWFza0VsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IHN0eWxlciBmcm9tICcuLi8uLi9vbnMvc3R5bGVyJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuaW1wb3J0IEJhc2VBbmltYXRvciBmcm9tICcuLi8uLi9vbnMvYmFzZS1hbmltYXRvcic7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNwbGl0dGVyQW5pbWF0b3IgZXh0ZW5kcyBCYXNlQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnY3ViaWMtYmV6aWVyKC4xLCAuNywgLjEsIDEpJywgZHVyYXRpb24gPSAwLjMsIGRlbGF5ID0gMH0gPSB7fSkge1xuICAgIHN1cGVyKHsgdGltaW5nLCBkdXJhdGlvbiwgZGVsYXkgfSk7XG4gIH1cblxuICB1cGRhdGVPcHRpb25zKG9wdGlvbnMgPSB7fSkge1xuICAgIHV0aWwuZXh0ZW5kKHRoaXMsIHtcbiAgICAgIHRpbWluZzogdGhpcy50aW1pbmcsIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLCBkZWxheTogdGhpcy5kZWxheVxuICAgIH0sIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gc2lkZUVsZW1lbnRcbiAgICovXG4gIGFjdGl2YXRlKHNpZGVFbGVtZW50KSB7XG4gICAgY29uc3Qgc3BsaXR0ZXIgPSBzaWRlRWxlbWVudC5wYXJlbnROb2RlO1xuXG4gICAgY29udGVudFJlYWR5KHNwbGl0dGVyLCAoKSA9PiB7XG4gICAgICB0aGlzLl9zaWRlID0gc2lkZUVsZW1lbnQ7XG4gICAgICB0aGlzLl9vcHBvc2l0ZVNpZGUgPSBzcGxpdHRlci5yaWdodCAhPT0gc2lkZUVsZW1lbnQgJiYgc3BsaXR0ZXIucmlnaHQgfHwgc3BsaXR0ZXIubGVmdCAhPT0gc2lkZUVsZW1lbnQgJiYgc3BsaXR0ZXIubGVmdDtcbiAgICAgIHRoaXMuX2NvbnRlbnQgPSBzcGxpdHRlci5jb250ZW50O1xuICAgICAgdGhpcy5fbWFzayA9IHNwbGl0dGVyLm1hc2s7XG4gICAgfSk7XG4gIH1cblxuICBkZWFjdGl2YXRlKCkge1xuICAgIHRoaXMuY2xlYXJUcmFuc2l0aW9uKCk7XG4gICAgdGhpcy5fbWFzayAmJiB0aGlzLmNsZWFyTWFzaygpO1xuICAgIHRoaXMuX2NvbnRlbnQgPSB0aGlzLl9zaWRlID0gdGhpcy5fb3Bwb3NpdGVTaWRlID0gdGhpcy5fbWFzayA9IG51bGw7XG4gIH1cblxuICBnZXQgbWludXMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3NpZGUuc2lkZSA9PT0gJ3JpZ2h0JyA/ICctJyA6ICcnO1xuICB9XG5cbiAgY2xlYXJUcmFuc2l0aW9uKCkge1xuICAgICdzaWRlIG1hc2sgY29udGVudCcuc3BsaXQoL1xccysvKVxuICAgICAgLmZvckVhY2goZSA9PiB0aGlzWydfJyArIGVdICYmIHN0eWxlci5jbGVhcih0aGlzWydfJyArIGVdLCAndHJhbnNmb3JtIHRyYW5zaXRpb24nKSlcbiAgfVxuXG4gIGNsZWFyTWFzaygpIHtcbiAgICAvLyBDaGVjayBpZiB0aGUgb3RoZXIgc2lkZSBuZWVkcyB0aGUgbWFzayBiZWZvcmUgY2xlYXJpbmdcbiAgICBpZiAoIXRoaXMuX29wcG9zaXRlU2lkZSB8fCB0aGlzLl9vcHBvc2l0ZVNpZGUubW9kZSA9PT0gJ3NwbGl0JyB8fCAhdGhpcy5fb3Bwb3NpdGVTaWRlLmlzT3Blbikge1xuICAgICAgdGhpcy5fbWFzay5zdHlsZS5vcGFjaXR5ID0gJyc7XG4gICAgICB0aGlzLl9tYXNrLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBkaXN0YW5jZVxuICAgKi9cbiAgdHJhbnNsYXRlKGRpc3RhbmNlKSB7XG5cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBvcGVuKGRvbmUpIHtcbiAgICBkb25lKCk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZG9uZVxuICAgKi9cbiAgY2xvc2UoZG9uZSkge1xuICAgIGRvbmUoKTtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi8uLi9vbnMvYW5pbWl0JztcbmltcG9ydCBTcGxpdHRlckFuaW1hdG9yIGZyb20gJy4vYW5pbWF0b3IuanMnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBPdmVybGF5U3BsaXR0ZXJBbmltYXRvciBleHRlbmRzIFNwbGl0dGVyQW5pbWF0b3Ige1xuXG4gIHRyYW5zbGF0ZShkaXN0YW5jZSkge1xuICAgIHRoaXMuX21hc2suc3R5bGUuZGlzcGxheSA9ICdibG9jayc7IC8vIEF2b2lkIGNvbnRlbnQgY2xpY2tzXG5cbiAgICBhbmltaXQodGhpcy5fc2lkZSlcbiAgICAgIC5xdWV1ZSh7XG4gICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKCR7dGhpcy5taW51cyArIGRpc3RhbmNlfXB4LCAwLCAwKWBcbiAgICAgIH0pXG4gICAgICAucGxheSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGRvbmVcbiAgICovXG4gIG9wZW4oZG9uZSkge1xuICAgIGFuaW1pdC5ydW5BbGwoXG4gICAgICBhbmltaXQodGhpcy5fc2lkZSlcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgke3RoaXMubWludXN9MTAwJSwgMCwgMClgXG4gICAgICAgIH0sIHRoaXMuZGVmKVxuICAgICAgICAucXVldWUoY2FsbGJhY2sgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSAmJiBkb25lKCk7XG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQodGhpcy5fbWFzaylcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBkaXNwbGF5OiAnYmxvY2snXG4gICAgICAgIH0pXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgb3BhY2l0eTogJzEnXG4gICAgICAgIH0sIHtcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6ICdsaW5lYXInLFxuICAgICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZG9uZVxuICAgKi9cbiAgY2xvc2UoZG9uZSkge1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcbiAgICAgIGFuaW1pdCh0aGlzLl9zaWRlKVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDAsIDApJ1xuICAgICAgICB9LCB0aGlzLmRlZilcbiAgICAgICAgLnF1ZXVlKGNhbGxiYWNrID0+IHtcbiAgICAgICAgICBkb25lICYmIGRvbmUoKTtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KHRoaXMuX21hc2spXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgb3BhY2l0eTogJzAnXG4gICAgICAgIH0sIHtcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6ICdsaW5lYXInLFxuICAgICAgICB9KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGRpc3BsYXk6ICdub25lJ1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBhbmltaXQgZnJvbSAnLi4vLi4vb25zL2FuaW1pdCc7XG5pbXBvcnQgU3BsaXR0ZXJBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yLmpzJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUHVzaFNwbGl0dGVyQW5pbWF0b3IgZXh0ZW5kcyBTcGxpdHRlckFuaW1hdG9yIHtcblxuICBfZ2V0U2xpZGluZ0VsZW1lbnRzKCkge1xuICAgIGNvbnN0IHNsaWRpbmdFbGVtZW50cyA9IFt0aGlzLl9zaWRlLCB0aGlzLl9jb250ZW50XTtcbiAgICBpZiAodGhpcy5fb3Bwb3NpdGVTaWRlICYmIHRoaXMuX29wcG9zaXRlU2lkZS5tb2RlID09PSAnc3BsaXQnKSB7XG4gICAgICBzbGlkaW5nRWxlbWVudHMucHVzaCh0aGlzLl9vcHBvc2l0ZVNpZGUpO1xuICAgIH1cblxuICAgIHJldHVybiBzbGlkaW5nRWxlbWVudHM7XG4gIH1cblxuICB0cmFuc2xhdGUoZGlzdGFuY2UpIHtcbiAgICBpZiAoIXRoaXMuX3NsaWRpbmdFbGVtZW50cykge1xuICAgICAgdGhpcy5fc2xpZGluZ0VsZW1lbnRzID0gdGhpcy5fZ2V0U2xpZGluZ0VsZW1lbnRzKCk7XG4gICAgfVxuXG4gICAgdGhpcy5fbWFzay5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJzsgLy8gQXZvaWQgY29udGVudCBjbGlja3NcblxuICAgIGFuaW1pdCh0aGlzLl9zbGlkaW5nRWxlbWVudHMpXG4gICAgICAucXVldWUoe1xuICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgke3RoaXMubWludXMgKyBkaXN0YW5jZX1weCwgMCwgMClgXG4gICAgICB9KVxuICAgICAgLnBsYXkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBvcGVuKGRvbmUpIHtcbiAgICBjb25zdCBtYXggPSB0aGlzLl9zaWRlLm9mZnNldFdpZHRoO1xuICAgIHRoaXMuX3NsaWRpbmdFbGVtZW50cyA9IHRoaXMuX2dldFNsaWRpbmdFbGVtZW50cygpO1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcbiAgICAgIGFuaW1pdCh0aGlzLl9zbGlkaW5nRWxlbWVudHMpXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoJHt0aGlzLm1pbnVzICsgbWF4fXB4LCAwLCAwKWBcbiAgICAgICAgfSwgdGhpcy5kZWYpXG4gICAgICAgIC5xdWV1ZShjYWxsYmFjayA9PiB7XG4gICAgICAgICAgdGhpcy5fc2xpZGluZ0VsZW1lbnRzID0gbnVsbDtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUgJiYgZG9uZSgpO1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KHRoaXMuX21hc2spXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgZGlzcGxheTogJ2Jsb2NrJ1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZG9uZVxuICAgKi9cbiAgY2xvc2UoZG9uZSkge1xuICAgIHRoaXMuX3NsaWRpbmdFbGVtZW50cyA9IHRoaXMuX2dldFNsaWRpbmdFbGVtZW50cygpO1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcbiAgICAgIGFuaW1pdCh0aGlzLl9zbGlkaW5nRWxlbWVudHMpXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknXG4gICAgICAgIH0sIHRoaXMuZGVmKVxuICAgICAgICAucXVldWUoY2FsbGJhY2sgPT4ge1xuICAgICAgICAgIHRoaXMuX3NsaWRpbmdFbGVtZW50cyA9IG51bGw7XG4gICAgICAgICAgc3VwZXIuY2xlYXJUcmFuc2l0aW9uKCk7XG4gICAgICAgICAgZG9uZSAmJiBkb25lKCk7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfSksXG5cbiAgICAgIGFuaW1pdCh0aGlzLl9tYXNrKVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGRpc3BsYXk6ICdub25lJ1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuaW1wb3J0IHN0eWxlciBmcm9tICcuLi8uLi9vbnMvc3R5bGVyJztcbmltcG9ydCBhbmltaXQgZnJvbSAnLi4vLi4vb25zL2FuaW1pdCc7XG5pbXBvcnQgU3BsaXR0ZXJBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yLmpzJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmV2ZWFsU3BsaXR0ZXJBbmltYXRvciBleHRlbmRzIFNwbGl0dGVyQW5pbWF0b3Ige1xuXG4gIF9nZXRTbGlkaW5nRWxlbWVudHMoKSB7XG4gICAgY29uc3Qgc2xpZGluZ0VsZW1lbnRzID0gW3RoaXMuX2NvbnRlbnQsIHRoaXMuX21hc2tdO1xuICAgIGlmICh0aGlzLl9vcHBvc2l0ZVNpZGUgJiYgdGhpcy5fb3Bwb3NpdGVTaWRlLm1vZGUgPT09ICdzcGxpdCcpIHtcbiAgICAgIHNsaWRpbmdFbGVtZW50cy5wdXNoKHRoaXMuX29wcG9zaXRlU2lkZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNsaWRpbmdFbGVtZW50cztcbiAgfVxuXG4gIGFjdGl2YXRlKHNpZGVFbGVtZW50KSB7XG4gICAgc3VwZXIuYWN0aXZhdGUoc2lkZUVsZW1lbnQpO1xuICAgIGlmIChzaWRlRWxlbWVudC5tb2RlID09PSAnY29sbGFwc2UnKSB7XG4gICAgICB0aGlzLl9zZXRTdHlsZXMoc2lkZUVsZW1lbnQpO1xuICAgIH1cbiAgfVxuXG4gIGRlYWN0aXZhdGUoKSB7XG4gICAgdGhpcy5fc2lkZSAmJiB0aGlzLl91bnNldFN0eWxlcyh0aGlzLl9zaWRlKTtcbiAgICBzdXBlci5kZWFjdGl2YXRlKCk7XG4gIH1cblxuICBfc2V0U3R5bGVzKHNpZGVFbGVtZW50KSB7XG4gICAgc3R5bGVyKHNpZGVFbGVtZW50LCB7XG4gICAgICBsZWZ0OiBzaWRlRWxlbWVudC5zaWRlID09PSAncmlnaHQnID8gJ2F1dG8nIDogMCxcbiAgICAgIHJpZ2h0OiBzaWRlRWxlbWVudC5zaWRlID09PSAncmlnaHQnICA/IDAgOiAnYXV0bycsXG4gICAgICB6SW5kZXg6IDAsXG4gICAgICBiYWNrZ3JvdW5kQ29sb3I6ICdibGFjaycsXG4gICAgICB0cmFuc2Zvcm06IHRoaXMuX2dlbmVyYXRlQmVoaW5kUGFnZVN0eWxlKDApLmNvbnRhaW5lci50cmFuc2Zvcm0sXG4gICAgICBkaXNwbGF5OiAnbm9uZSdcbiAgICB9KTtcblxuICAgIGNvbnN0IHNwbGl0dGVyID0gc2lkZUVsZW1lbnQucGFyZW50RWxlbWVudDtcbiAgICBjb250ZW50UmVhZHkoc3BsaXR0ZXIsICgpID0+IHNwbGl0dGVyLmNvbnRlbnQgJiYgc3R5bGVyKHNwbGl0dGVyLmNvbnRlbnQsIHsgYm94U2hhZG93OiAnMCAwIDEycHggMCByZ2JhKDAsIDAsIDAsIDAuMiknIH0pKTtcbiAgfVxuXG4gIF91bnNldFN0eWxlcyhzaWRlRWxlbWVudCkge1xuICAgIHN0eWxlci5jbGVhcihzaWRlRWxlbWVudCwgJ2xlZnQgcmlnaHQgekluZGV4IGJhY2tncm91bmRDb2xvciBkaXNwbGF5Jyk7XG4gICAgaWYgKHNpZGVFbGVtZW50Ll9jb250ZW50KSB7XG4gICAgICBzaWRlRWxlbWVudC5fY29udGVudC5zdHlsZS5vcGFjaXR5ID0gJyc7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgdGhlIG90aGVyIHNpZGUgbmVlZHMgdGhlIGNvbW1vbiBzdHlsZXNcbiAgICBpZiAoIXRoaXMuX29wcG9zaXRlU2lkZSB8fCB0aGlzLl9vcHBvc2l0ZVNpZGUubW9kZSA9PT0gJ3NwbGl0Jykge1xuICAgICAgc2lkZUVsZW1lbnQucGFyZW50RWxlbWVudC5jb250ZW50ICYmIHN0eWxlci5jbGVhcihzaWRlRWxlbWVudC5wYXJlbnRFbGVtZW50LmNvbnRlbnQsICdib3hTaGFkb3cnKTtcbiAgICB9XG4gIH1cblxuICBfZ2VuZXJhdGVCZWhpbmRQYWdlU3R5bGUoZGlzdGFuY2UpIHtcbiAgICBjb25zdCBtYXggPSB0aGlzLm1heFdpZHRoO1xuXG4gICAgbGV0IGJlaGluZERpc3RhbmNlID0gKGRpc3RhbmNlIC0gbWF4KSAvIG1heCAqIDEwO1xuICAgIGJlaGluZERpc3RhbmNlID0gaXNOYU4oYmVoaW5kRGlzdGFuY2UpID8gMCA6IE1hdGgubWF4KE1hdGgubWluKGJlaGluZERpc3RhbmNlLCAwKSwgLTEwKTtcblxuICAgIGNvbnN0IGJlaGluZFRyYW5zZm9ybSA9IGB0cmFuc2xhdGUzZCgkeyh0aGlzLm1pbnVzID8gLTEgOiAxKSAqIGJlaGluZERpc3RhbmNlfSUsIDAsIDApYDtcbiAgICBjb25zdCBvcGFjaXR5ID0gMSArIGJlaGluZERpc3RhbmNlIC8gMTAwO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRlbnQ6IHtcbiAgICAgICAgb3BhY2l0eVxuICAgICAgfSxcbiAgICAgIGNvbnRhaW5lcjoge1xuICAgICAgICB0cmFuc2Zvcm06IGJlaGluZFRyYW5zZm9ybVxuICAgICAgfVxuICAgIH07XG4gIH1cblxuICB0cmFuc2xhdGUoZGlzdGFuY2UpIHtcbiAgICB0aGlzLl9zaWRlLnN0eWxlLmRpc3BsYXkgPSAnJztcbiAgICB0aGlzLl9zaWRlLnN0eWxlLnpJbmRleCA9IDE7XG4gICAgdGhpcy5tYXhXaWR0aCA9IHRoaXMubWF4V2lkdGggfHwgdGhpcy5fZ2V0TWF4V2lkdGgoKTtcbiAgICBjb25zdCBtZW51U3R5bGUgPSB0aGlzLl9nZW5lcmF0ZUJlaGluZFBhZ2VTdHlsZShNYXRoLm1pbihkaXN0YW5jZSwgdGhpcy5tYXhXaWR0aCkpO1xuXG4gICAgaWYgKCF0aGlzLl9zbGlkaW5nRWxlbWVudHMpIHtcbiAgICAgIHRoaXMuX3NsaWRpbmdFbGVtZW50cyA9IHRoaXMuX2dldFNsaWRpbmdFbGVtZW50cygpO1xuICAgIH1cblxuICAgIHRoaXMuX21hc2suc3R5bGUuZGlzcGxheSA9ICdibG9jayc7IC8vIEF2b2lkIGNvbnRlbnQgY2xpY2tzXG5cbiAgICBhbmltaXQucnVuQWxsKFxuICAgICAgYW5pbWl0KHRoaXMuX3NsaWRpbmdFbGVtZW50cylcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgke3RoaXMubWludXMgKyBkaXN0YW5jZX1weCwgMCwgMClgXG4gICAgICAgIH0pLFxuICAgICAgYW5pbWl0KHRoaXMuX3NpZGUuX2NvbnRlbnQpXG4gICAgICAgIC5xdWV1ZShtZW51U3R5bGUuY29udGVudCksXG4gICAgICBhbmltaXQodGhpcy5fc2lkZSlcbiAgICAgICAgLnF1ZXVlKG1lbnVTdHlsZS5jb250YWluZXIpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBvcGVuKGRvbmUpIHtcbiAgICB0aGlzLl9zaWRlLnN0eWxlLmRpc3BsYXkgPSAnJztcbiAgICB0aGlzLl9zaWRlLnN0eWxlLnpJbmRleCA9IDE7XG4gICAgdGhpcy5tYXhXaWR0aCA9IHRoaXMubWF4V2lkdGggfHwgdGhpcy5fZ2V0TWF4V2lkdGgoKTtcbiAgICBjb25zdCBtZW51U3R5bGUgPSB0aGlzLl9nZW5lcmF0ZUJlaGluZFBhZ2VTdHlsZSh0aGlzLm1heFdpZHRoKTtcbiAgICB0aGlzLl9zbGlkaW5nRWxlbWVudHMgPSB0aGlzLl9nZXRTbGlkaW5nRWxlbWVudHMoKTtcblxuICAgIHNldFRpbWVvdXQoKCkgPT4geyAvLyBGaXg6IFRpbWUgdG8gdXBkYXRlIHByZXZpb3VzIHRyYW5zbGF0ZTNkIGFmdGVyIGNoYW5naW5nIHN0eWxlLmRpc3BsYXlcbiAgICAgIGFuaW1pdC5ydW5BbGwoXG4gICAgICAgIGFuaW1pdCh0aGlzLl9zbGlkaW5nRWxlbWVudHMpXG4gICAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoJHt0aGlzLm1pbnVzICsgdGhpcy5tYXhXaWR0aH1weCwgMCwgMClgXG4gICAgICAgICAgfSwgdGhpcy5kZWYpLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLl9tYXNrKVxuICAgICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIGRpc3BsYXk6ICdibG9jaydcbiAgICAgICAgICB9KSxcblxuICAgICAgICBhbmltaXQodGhpcy5fc2lkZS5fY29udGVudClcbiAgICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAgIC5xdWV1ZShtZW51U3R5bGUuY29udGVudCwgdGhpcy5kZWYpLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLl9zaWRlKVxuICAgICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgICAgLnF1ZXVlKG1lbnVTdHlsZS5jb250YWluZXIsIHRoaXMuZGVmKVxuICAgICAgICAgIC5xdWV1ZShjYWxsYmFjayA9PiB7XG4gICAgICAgICAgICB0aGlzLl9zbGlkaW5nRWxlbWVudHMgPSBudWxsO1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIGRvbmUgJiYgZG9uZSgpO1xuICAgICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9LCAxMDAwLzYwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBjbG9zZShkb25lKSB7XG4gICAgY29uc3QgbWVudVN0eWxlID0gdGhpcy5fZ2VuZXJhdGVCZWhpbmRQYWdlU3R5bGUoMCk7XG4gICAgdGhpcy5fc2xpZGluZ0VsZW1lbnRzID0gdGhpcy5fZ2V0U2xpZGluZ0VsZW1lbnRzKCk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuICAgICAgYW5pbWl0KHRoaXMuX3NsaWRpbmdFbGVtZW50cylcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKSdcbiAgICAgICAgfSwgdGhpcy5kZWYpLFxuXG4gICAgICBhbmltaXQodGhpcy5fbWFzaylcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBkaXNwbGF5OiAnbm9uZSdcbiAgICAgICAgfSksXG5cbiAgICAgIGFuaW1pdCh0aGlzLl9zaWRlLl9jb250ZW50KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUobWVudVN0eWxlLmNvbnRlbnQsIHRoaXMuZGVmKSxcblxuICAgICAgYW5pbWl0KHRoaXMuX3NpZGUpXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZShtZW51U3R5bGUuY29udGFpbmVyLCB0aGlzLmRlZilcbiAgICAgICAgLnF1ZXVlKGNhbGxiYWNrID0+IHtcbiAgICAgICAgICB0aGlzLl9zbGlkaW5nRWxlbWVudHMgPSBudWxsO1xuICAgICAgICAgIHRoaXMuX3NpZGUuc3R5bGUuekluZGV4ID0gMDtcbiAgICAgICAgICB0aGlzLl9zaWRlLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgdGhpcy5fc2lkZS5fY29udGVudC5zdHlsZS5vcGFjaXR5ID0gJyc7XG4gICAgICAgICAgZG9uZSAmJiBkb25lKCk7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIF9nZXRNYXhXaWR0aCgpIHtcbiAgICByZXR1cm4gdGhpcy5fc2lkZS5vZmZzZXRXaWR0aDtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uLy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBBbmltYXRvckZhY3RvcnkgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL2FuaW1hdG9yLWZhY3RvcnknO1xuaW1wb3J0IE92ZXJsYXlTcGxpdHRlckFuaW1hdG9yIGZyb20gJy4vb3ZlcmxheS1hbmltYXRvcic7XG5pbXBvcnQgUHVzaFNwbGl0dGVyQW5pbWF0b3IgZnJvbSAnLi9wdXNoLWFuaW1hdG9yJztcbmltcG9ydCBSZXZlYWxTcGxpdHRlckFuaW1hdG9yIGZyb20gJy4vcmV2ZWFsLWFuaW1hdG9yJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL2RldmljZS1iYWNrLWJ1dHRvbi1kaXNwYXRjaGVyJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBfYW5pbWF0b3JEaWN0ID0ge1xuICBkZWZhdWx0OiBPdmVybGF5U3BsaXR0ZXJBbmltYXRvcixcbiAgb3ZlcmxheTogT3ZlcmxheVNwbGl0dGVyQW5pbWF0b3IsXG4gIHB1c2g6IFB1c2hTcGxpdHRlckFuaW1hdG9yLFxuICByZXZlYWw6IFJldmVhbFNwbGl0dGVyQW5pbWF0b3Jcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXNwbGl0dGVyXG4gKiBAY2F0ZWdvcnkgbWVudVxuICogQGRlc2NyaXB0aW9uXG4gKiAgW2VuXVxuICogICAgQSBjb21wb25lbnQgdGhhdCBlbmFibGVzIHJlc3BvbnNpdmUgbGF5b3V0IGJ5IGltcGxlbWVudGluZyBib3RoIGEgdHdvLWNvbHVtbiBsYXlvdXQgYW5kIGEgc2xpZGluZyBtZW51IGxheW91dC5cbiAqXG4gKiAgICBJdCBjYW4gYmUgY29uZmlndXJlZCB0byBhdXRvbWF0aWNhbGx5IGV4cGFuZCBpbnRvIGEgY29sdW1uIGxheW91dCBvbiBsYXJnZSBzY3JlZW5zIGFuZCBjb2xsYXBzZSB0aGUgbWVudSBvbiBzbWFsbGVyIHNjcmVlbnMuIFdoZW4gdGhlIG1lbnUgaXMgY29sbGFwc2VkIHRoZSB1c2VyIGNhbiBvcGVuIGl0IGJ5IHN3aXBpbmcuXG4gKiAgWy9lbl1cbiAqICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIHJPUU9NTFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3NwbGl0dGVyXG4gKiBAZ3VpZGUgZnVuZGFtZW50YWxzLmh0bWwjbWFuYWdpbmctcGFnZXNcbiAqICBbZW5dTWFuYWdpbmcgbXVsdGlwbGUgcGFnZXMuWy9lbl1cbiAqICBbamFd6KSH5pWw44Gu44Oa44O844K444KS566h55CG44GZ44KLWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zcGxpdHRlci1jb250ZW50XG4gKiAgW2VuXVRoZSBgPG9ucy1zcGxpdHRlci1jb250ZW50PmAgY29tcG9uZW50IGNvbnRhaW5zIHRoZSBtYWluIGNvbnRlbnQgb2YgdGhlIHBhZ2UuWy9lbl1cbiAqICBbamFdb25zLXNwbGl0dGVyLWNvbnRlbnTjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLXNwbGl0dGVyLXNpZGVcbiAqICBbZW5dVGhlIGA8b25zLXNwbGl0dGVyLXNpZGU+YCBjb21wb25lbnQgY29udGFpbnMgdGhlIG1lbnUuWy9lbl1cbiAqICBbamFdb25zLXNwbGl0dGVyLXNpZGXjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtc3BsaXR0ZXIgaWQ9XCJzcGxpdHRlclwiPlxuICogICA8b25zLXNwbGl0dGVyLWNvbnRlbnQ+XG4gKiAgICAgLi4uXG4gKiAgIDwvb25zLXNwbGl0dGVyLWNvbnRlbnQ+XG4gKlxuICogICA8b25zLXNwbGl0dGVyLXNpZGUgc2lkZT1cImxlZnRcIiB3aWR0aD1cIjgwJVwiIGNvbGxhcHNlIHN3aXBlYWJsZT5cbiAqICAgICAuLi5cbiAqICAgPC9vbnMtc3BsaXR0ZXItc2lkZT5cbiAqIDwvb25zLXNwbGl0dGVyPlxuICpcbiAqIDxzY3JpcHQ+XG4gKiAgIHZhciBzcGxpdHRlciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzcGxpdHRlcicpO1xuICogICBzcGxpdHRlci5sZWZ0Lm9wZW4oKTtcbiAqIDwvc2NyaXB0PlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTcGxpdHRlckVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgX2dldFNpZGUoc2lkZSkge1xuICAgIGNvbnN0IGVsZW1lbnQgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCBlID0+IHtcbiAgICAgIHJldHVybiB1dGlsLm1hdGNoKGUsICdvbnMtc3BsaXR0ZXItc2lkZScpICYmIGUuZ2V0QXR0cmlidXRlKCdzaWRlJykgPT09IHNpZGU7XG4gICAgfSk7XG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGxlZnRcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtIVE1MRWxlbWVudH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUxlZnQgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGdldCBsZWZ0KCkge1xuICAgIHJldHVybiB0aGlzLl9nZXRTaWRlKCdsZWZ0Jyk7XG4gIH1cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSByaWdodFxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0hUTUxFbGVtZW50fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmlnaHQgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGdldCByaWdodCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0U2lkZSgncmlnaHQnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgc2lkZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0hUTUxFbGVtZW50fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyc3QgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGVsZW1lbnQgcmVnYXJkbGVzcyB0aGUgYWN0dWFsIHNpZGUuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGdldCBzaWRlKCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnb25zLXNwbGl0dGVyLXNpZGUnKTtcbiAgfVxuXG4gIGdldCBfc2lkZXMoKSB7XG4gICAgcmV0dXJuIFt0aGlzLmxlZnQsIHRoaXMucmlnaHRdLmZpbHRlcihlID0+IGUpO1xuICB9XG4gIC8qKlxuICAgKiBAcHJvcGVydHkgY29udGVudFxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0hUTUxFbGVtZW50fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGA8b25zLXNwbGl0dGVyLWNvbnRlbnQ+YCBlbGVtZW50LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgY29udGVudCgpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJ29ucy1zcGxpdHRlci1jb250ZW50Jyk7XG4gIH1cblxuICBnZXQgdG9wUGFnZSgpIHtcbiAgICByZXR1cm4gdGhpcy5jb250ZW50Ll9jb250ZW50O1xuICB9XG5cbiAgZ2V0IG1hc2soKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICdvbnMtc3BsaXR0ZXItbWFzaycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvbkRldmljZUJhY2tCdXR0b25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUJhY2stYnV0dG9uIGhhbmRsZXIuWy9lbl1cbiAgICogICBbamFd44OQ44OD44Kv44Oc44K/44Oz44OP44Oz44OJ44Op44CCWy9qYV1cbiAgICovXG4gIGdldCBvbkRldmljZUJhY2tCdXR0b24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyO1xuICB9XG5cbiAgc2V0IG9uRGV2aWNlQmFja0J1dHRvbihjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLl9iYWNrQnV0dG9uSGFuZGxlcikge1xuICAgICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIuZGVzdHJveSgpO1xuICAgIH1cblxuICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyID0gZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIuY3JlYXRlSGFuZGxlcih0aGlzLCBjYWxsYmFjayk7XG4gIH1cblxuICBfb25EZXZpY2VCYWNrQnV0dG9uKGV2ZW50KSB7XG4gICAgdGhpcy5fc2lkZXMuc29tZShzID0+IHMuaXNPcGVuID8gcy5jbG9zZSgpIDogZmFsc2UpIHx8IGV2ZW50LmNhbGxQYXJlbnRIYW5kbGVyKCk7XG4gIH1cblxuICBfb25Nb2RlQ2hhbmdlKGUpIHtcbiAgICBpZiAoZS50YXJnZXQucGFyZW50Tm9kZSkge1xuICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgICAgdGhpcy5fbGF5b3V0KCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBfbGF5b3V0KCkge1xuICAgIHRoaXMuX3NpZGVzLmZvckVhY2goc2lkZSA9PiB7XG4gICAgICBpZiAodGhpcy5jb250ZW50KSB7XG4gICAgICAgIHRoaXMuY29udGVudC5zdHlsZVtzaWRlLnNpZGVdID0gc2lkZS5tb2RlID09PSAnc3BsaXQnID8gc2lkZS5zdHlsZS53aWR0aCA6IDA7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fb25Nb2RlQ2hhbmdlID0gdGhpcy5fb25Nb2RlQ2hhbmdlLmJpbmQodGhpcyk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgIXRoaXMubWFzayAmJiB0aGlzLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ29ucy1zcGxpdHRlci1tYXNrJykpO1xuICAgICAgdGhpcy5fbGF5b3V0KCk7XG4gICAgfSk7XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLm9uRGV2aWNlQmFja0J1dHRvbiA9IHRoaXMuX29uRGV2aWNlQmFja0J1dHRvbi5iaW5kKHRoaXMpO1xuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignbW9kZWNoYW5nZScsIHRoaXMuX29uTW9kZUNoYW5nZSwgZmFsc2UpO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIuZGVzdHJveSgpO1xuICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyID0gbnVsbDtcbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vZGVjaGFuZ2UnLCB0aGlzLl9vbk1vZGVDaGFuZ2UsIGZhbHNlKTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7fVxuXG4gIF9zaG93KCkge1xuICAgIHV0aWwucHJvcGFnYXRlQWN0aW9uKHRoaXMsICdfc2hvdycpO1xuICB9XG5cbiAgX2hpZGUoKSB7XG4gICAgdXRpbC5wcm9wYWdhdGVBY3Rpb24odGhpcywgJ19oaWRlJyk7XG4gIH1cblxuICBfZGVzdHJveSgpIHtcbiAgICB1dGlsLnByb3BhZ2F0ZUFjdGlvbih0aGlzLCAnX2Rlc3Ryb3knKTtcbiAgICB0aGlzLnJlbW92ZSgpO1xuICB9XG5cbiAgc3RhdGljIHJlZ2lzdGVyQW5pbWF0b3IobmFtZSwgQW5pbWF0b3IpIHtcbiAgICBpZiAoIShBbmltYXRvciBpbnN0YW5jZW9mIFNwbGl0dGVyQW5pbWF0b3IpKSB7XG4gICAgICB1dGlsLnRocm93QW5pbWF0b3IoJ1NwbGl0dGVyJyk7XG4gICAgfVxuICAgIF9hbmltYXRvckRpY3RbbmFtZV0gPSBBbmltYXRvcjtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgU3BsaXR0ZXJBbmltYXRvcigpIHtcbiAgICByZXR1cm4gU3BsaXR0ZXJBbmltYXRvcjtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgYW5pbWF0b3JzKCkge1xuICAgIHJldHVybiBfYW5pbWF0b3JEaWN0O1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLlNwbGl0dGVyID0gU3BsaXR0ZXJFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtc3BsaXR0ZXInLCBTcGxpdHRlckVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgQW5pbWF0b3JGYWN0b3J5IGZyb20gJy4uL29ucy9pbnRlcm5hbC9hbmltYXRvci1mYWN0b3J5JztcbmltcG9ydCBvcmllbnRhdGlvbiBmcm9tICcuLi9vbnMvb3JpZW50YXRpb24nO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uL29ucy9pbnRlcm5hbCc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBTcGxpdHRlckFuaW1hdG9yIGZyb20gJy4vb25zLXNwbGl0dGVyL2FuaW1hdG9yJztcbmltcG9ydCBTd2lwZVJldmVhbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvc3dpcGUtcmV2ZWFsJztcbmltcG9ydCBEb29yTG9jayBmcm9tICcuLi9vbnMvZG9vcmxvY2snO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5pbXBvcnQgeyBQYWdlTG9hZGVyLCBkZWZhdWx0UGFnZUxvYWRlcn0gZnJvbSAnLi4vb25zL3BhZ2UtbG9hZGVyJztcbmltcG9ydCBTcGxpdHRlckVsZW1lbnQgZnJvbSAnLi9vbnMtc3BsaXR0ZXInO1xuXG5jb25zdCBTUExJVF9NT0RFID0gJ3NwbGl0JztcbmNvbnN0IENPTExBUFNFX01PREUgPSAnY29sbGFwc2UnO1xuY29uc3QgQ0xPU0VEX1NUQVRFID0gJ2Nsb3NlZCc7XG5jb25zdCBPUEVOX1NUQVRFID0gJ29wZW4nO1xuY29uc3QgQ0hBTkdJTkdfU1RBVEUgPSAnY2hhbmdpbmcnO1xuXG5jb25zdCByZXdyaXRhYmxlcyA9IHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gc3BsaXR0ZXJTaWRlRWxlbWVudFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcmVhZHkoc3BsaXR0ZXJTaWRlRWxlbWVudCwgY2FsbGJhY2spIHtcbiAgICBzZXRJbW1lZGlhdGUoY2FsbGJhY2spO1xuICB9XG59O1xuXG5jbGFzcyBDb2xsYXBzZURldGVjdGlvbiB7XG4gIGNvbnN0cnVjdG9yKGVsZW1lbnQsIHRhcmdldCkge1xuICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgIHRoaXMuX29uQ2hhbmdlID0gdGhpcy5fb25DaGFuZ2UuYmluZCh0aGlzKTtcbiAgICB0YXJnZXQgJiYgdGhpcy5jaGFuZ2VUYXJnZXQodGFyZ2V0KTtcbiAgfVxuXG4gIGNoYW5nZVRhcmdldCh0YXJnZXQpIHtcbiAgICB0aGlzLmRpc2FibGUoKTtcbiAgICB0aGlzLl90YXJnZXQgPSB0YXJnZXQ7XG4gICAgaWYgKHRhcmdldCkge1xuICAgICAgdGhpcy5fb3JpZW50YXRpb24gPSBbJ3BvcnRyYWl0JywgJ2xhbmRzY2FwZSddLmluZGV4T2YodGFyZ2V0KSAhPT0gLTE7XG4gICAgICB0aGlzLmFjdGl2YXRlKCk7XG4gICAgfVxuICB9XG5cbiAgX21hdGNoKHZhbHVlKSB7XG4gICAgaWYgKHRoaXMuX29yaWVudGF0aW9uKSB7XG4gICAgICByZXR1cm4gdGhpcy5fdGFyZ2V0ID09PSAodmFsdWUuaXNQb3J0cmFpdCA/ICdwb3J0cmFpdCcgOiAnbGFuZHNjYXBlJyk7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZS5tYXRjaGVzO1xuICB9XG5cbiAgX29uQ2hhbmdlKHZhbHVlKSB7XG4gICAgdGhpcy5fZWxlbWVudC5fdXBkYXRlTW9kZSh0aGlzLl9tYXRjaCh2YWx1ZSkgPyBDT0xMQVBTRV9NT0RFIDogU1BMSVRfTU9ERSk7XG4gIH1cblxuICBhY3RpdmF0ZSgpIHtcbiAgICBpZiAodGhpcy5fb3JpZW50YXRpb24pIHtcbiAgICAgIG9yaWVudGF0aW9uLm9uKCdjaGFuZ2UnLCB0aGlzLl9vbkNoYW5nZSk7XG4gICAgICB0aGlzLl9vbkNoYW5nZSh7aXNQb3J0cmFpdDogb3JpZW50YXRpb24uaXNQb3J0cmFpdCgpfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX3F1ZXJ5UmVzdWx0ID0gd2luZG93Lm1hdGNoTWVkaWEodGhpcy5fdGFyZ2V0KTtcbiAgICAgIHRoaXMuX3F1ZXJ5UmVzdWx0LmFkZExpc3RlbmVyKHRoaXMuX29uQ2hhbmdlKTtcbiAgICAgIHRoaXMuX29uQ2hhbmdlKHRoaXMuX3F1ZXJ5UmVzdWx0KTtcbiAgICB9XG4gIH1cblxuICBkaXNhYmxlKCkge1xuICAgIGlmICh0aGlzLl9vcmllbnRhdGlvbikge1xuICAgICAgb3JpZW50YXRpb24ub2ZmKCdjaGFuZ2UnLCB0aGlzLl9vbkNoYW5nZSk7XG4gICAgfSBlbHNlIGlmICh0aGlzLl9xdWVyeVJlc3VsdCkge1xuICAgICAgdGhpcy5fcXVlcnlSZXN1bHQucmVtb3ZlTGlzdGVuZXIodGhpcy5fb25DaGFuZ2UpO1xuICAgICAgdGhpcy5fcXVlcnlSZXN1bHQgPSBudWxsO1xuICAgIH1cbiAgfVxufVxuXG5jb25zdCB3aWR0aFRvUHggPSAod2lkdGgsIHBhcmVudCkgPT4ge1xuICBjb25zdCBbdmFsdWUsIHB4XSA9IFtwYXJzZUludCh3aWR0aCwgMTApLCAvcHgvLnRlc3Qod2lkdGgpXTtcbiAgcmV0dXJuIHB4ID8gdmFsdWUgOiBNYXRoLnJvdW5kKHBhcmVudC5vZmZzZXRXaWR0aCAqIHZhbHVlIC8gMTAwKTtcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXNwbGl0dGVyLXNpZGVcbiAqIEBjYXRlZ29yeSBtZW51XG4gKiBAZGVzY3JpcHRpb25cbiAqICBbZW5dXG4gKiAgICBUaGUgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGVsZW1lbnQgaXMgdXNlZCBhcyBhIGNoaWxkIGVsZW1lbnQgb2YgYDxvbnMtc3BsaXR0ZXI+YC5cbiAqXG4gKiAgICBJdCB3aWxsIGJlIGRpc3BsYXllZCBvbiBlaXRoZXIgdGhlIGxlZnQgb3IgcmlnaHQgc2lkZSBvZiB0aGUgYDxvbnMtc3BsaXR0ZXItY29udGVudD5gIGVsZW1lbnQuXG4gKlxuICogICAgSXQgc3VwcG9ydHMgdHdvIG1vZGVzOiBjb2xsYXBzZWQgYW5kIHNwbGl0LiBXaGVuIGl0J3MgaW4gY29sbGFwc2VkIG1vZGUgaXQgd2lsbCBiZSBoaWRkZW4gZnJvbSB2aWV3IGFuZCBjYW4gYmUgZGlzcGxheWVkIHdoZW4gdGhlIHVzZXIgc3dpcGVzIHRoZSBzY3JlZW4gb3IgdGFwcyBhIGJ1dHRvbi4gSW4gc3BsaXQgbW9kZSB0aGUgZWxlbWVudCBpcyBhbHdheXMgc2hvd24uIEl0IGNhbiBiZSBjb25maWd1cmVkIHRvIGF1dG9tYXRpY2FsbHkgc3dpdGNoIGJldHdlZW4gdGhlIHR3byBtb2RlcyBkZXBlbmRpbmcgb24gdGhlIHNjcmVlbiBzaXplLlxuICogIFsvZW5dXG4gKiAgW2phXW9ucy1zcGxpdHRlci1zaWRl6KaB57Sg44Gv44CBb25zLXNwbGl0dGVy6KaB57Sg44Gu5a2Q6KaB57Sg44Go44GX44Gm5Yip55So44GX44G+44GZ44CCWy9qYV1cbiAqIEBjb2RlcGVuIHJPUU9NTFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3NwbGl0dGVyXG4gKiBAZ3VpZGUgZnVuZGFtZW50YWxzLmh0bWwjbWFuYWdpbmctcGFnZXNcbiAqICBbZW5dTWFuYWdpbmcgbXVsdGlwbGUgcGFnZXMuWy9lbl1cbiAqICBbamFd6KSH5pWw44Gu44Oa44O844K444KS566h55CG44GZ44KLWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zcGxpdHRlclxuICogIFtlbl1UaGUgYDxvbnMtc3BsaXR0ZXI+YCBpcyB0aGUgcGFyZW50IGNvbXBvbmVudC5bL2VuXVxuICogIFtqYV1vbnMtc3BsaXR0ZXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLXNwbGl0dGVyLWNvbnRlbnRcbiAqICBbZW5dVGhlIGA8b25zLXNwbGl0dGVyLWNvbnRlbnQ+YCBjb21wb25lbnQgY29udGFpbnMgdGhlIG1haW4gY29udGVudCBvZiB0aGUgcGFnZS5bL2VuXVxuICogIFtqYV1vbnMtc3BsaXR0ZXItY29udGVudOOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1zcGxpdHRlcj5cbiAqICAgPG9ucy1zcGxpdHRlci1jb250ZW50PlxuICogICAgIC4uLlxuICogICA8L29ucy1zcGxpdHRlci1jb250ZW50PlxuICpcbiAqICAgPG9ucy1zcGxpdHRlci1zaWRlIHNpZGU9XCJsZWZ0XCIgd2lkdGg9XCI4MCVcIiBjb2xsYXBzZT5cbiAqICAgICAuLi5cbiAqICAgPC9vbnMtc3BsaXR0ZXItc2lkZT5cbiAqIDwvb25zLXNwbGl0dGVyPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTcGxpdHRlclNpZGVFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgbW9kZWNoYW5nZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQganVzdCBhZnRlciB0aGUgY29tcG9uZW50J3MgbW9kZSBjaGFuZ2VzLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruimgee0oOOBruODouODvOODieOBjOWkieWMluOBl+OBn+mam+OBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnNpZGVcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gZXZlbnQubW9kZVxuICAgKiAgIFtlbl1SZXR1cm5zIHRoZSBjdXJyZW50IG1vZGUuIENhbiBiZSBlaXRoZXIgYFwiY29sbGFwc2VcImAgb3IgYFwic3BsaXRcImAuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Gu44Oi44O844OJ44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBwcmVvcGVuXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGJlZm9yZSB0aGUgc2xpZGluZyBtZW51IGlzIG9wZW5lZC5bL2VuXVxuICAgKiAgIFtqYV3jgrnjg6njgqTjg4fjgqPjg7PjgrDjg6Hjg4vjg6Xjg7zjgYzplovjgY/liY3jgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnRcbiAgICogICBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCpOODmeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGV2ZW50LmNhbmNlbFxuICAgKiAgIFtlbl1DYWxsIHRvIGNhbmNlbCBvcGVuaW5nIHNsaWRpbmcgbWVudS5bL2VuXVxuICAgKiAgIFtqYV3jgrnjg6njgqTjg4fjgqPjg7PjgrDjg6Hjg4vjg6Xjg7zjgYzplovjgY/jga7jgpLjgq3jg6Pjg7Pjgrvjg6vjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuc2lkZVxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdG9wZW5cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIHNsaWRpbmcgbWVudSBpcyBvcGVuZWQuWy9lbl1cbiAgICogICBbamFd44K544Op44Kk44OH44Kj44Oz44Kw44Oh44OL44Ol44O844GM6ZaL44GE44Gf5b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50XG4gICAqICAgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgqrjg5bjgrjjgqfjgq/jg4jjgafjgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuc2lkZVxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlY2xvc2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYmVmb3JlIHRoZSBzbGlkaW5nIG1lbnUgaXMgY2xvc2VkLlsvZW5dXG4gICAqICAgW2phXeOCueODqeOCpOODh+OCo+ODs+OCsOODoeODi+ODpeODvOOBjOmWieOBmOOCi+WJjeOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnNpZGVcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC5jYW5jZWxcbiAgICogICBbZW5dQ2FsbCB0byBjYW5jZWwgb3BlbmluZyBzbGlkaW5nLW1lbnUuWy9lbl1cbiAgICogICBbamFd44K544Op44Kk44OH44Kj44Oz44Kw44Oh44OL44Ol44O844GM6ZaJ44GY44KL44Gu44KS44Kt44Oj44Oz44K744Or44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBwb3N0Y2xvc2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIHNsaWRpbmcgbWVudSBpcyBjbG9zZWQuWy9lbl1cbiAgICogICBbamFd44K544Op44Kk44OH44Kj44Oz44Kw44Oh44OL44Ol44O844GM6ZaJ44GY44Gf5b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50XG4gICAqICAgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgqrjg5bjgrjjgqfjgq/jg4jjgafjgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuc2lkZVxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGFuaW1hdGlvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCAgZGVmYXVsdFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24uIFVzZSBvbmUgb2YgYG92ZXJsYXlgLCBgcHVzaGAsIGByZXZlYWxgIG9yICBgZGVmYXVsdGAuWy9lbl1cbiAgICogIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PjgpLmjIflrprjgZfjgb7jgZnjgIJcIm92ZXJsYXlcIiwgXCJwdXNoXCIsIFwicmV2ZWFsXCIsIFwiZGVmYXVsdFwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uLW9wdGlvbnNcbiAgICogQHR5cGUge0V4cHJlc3Npb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCB0aW1pbmcgYW5kIGRlbGF5IHdpdGggYW4gb2JqZWN0IGxpdGVyYWwuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCB0aW1pbmcsIGRlbGF544KS44Kq44OW44K444Kn44Kv44OI44Oq44OG44Op44Or44Gn5oyH5a6a44GX44G+44GZ44CCZS5nLiB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG9wZW4tdGhyZXNob2xkXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0ICAwLjNcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU3BlY2lmeSBob3cgbXVjaCB0aGUgbWVudSBuZWVkcyB0byBiZSBzd2lwZWQgYmVmb3JlIG9wZW5pbmcuIEEgdmFsdWUgYmV0d2VlbiBgMGAgYW5kIGAxYC5bL2VuXVxuICAgKiAgW2phXeOBqeOBruOBj+OCieOBhOOCueODr+OCpOODl+OBmeOCjOOBsOOCueODqeOCpOODh+OCo+ODs+OCsOODoeODi+ODpeODvOOCkumWi+OBj+OBi+OBqeOBhuOBi+OBruWJsuWQiOOCkuaMh+WumuOBl+OBvuOBmeOAgjDjgYvjgokx44Gu6ZaT44Gu5pWw5YCk44KS5oyH5a6a44GX44G+44GZ44CC44K544Ov44Kk44OX44Gu6Led6Zui44GM44GT44GT44Gn5oyH5a6a44GX44Gf5pWw5YCk5o6b44GR44KL44GT44Gu6KaB57Sg44Gu5bmF44KI44KK44KC5aSn44GN44GR44KM44Gw44CB44K544Ov44Kk44OX44GM57WC44KP44Gj44Gf5pmC44Gr44GT44Gu6KaB57Sg44KS6ZaL44GN44G+44GZ44CC44OH44OV44Kp44Or44OI44GvMC4z44Gn44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgY29sbGFwc2VcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgU3BlY2lmeSB0aGUgY29sbGFwc2UgYmVoYXZpb3IuIFZhbGlkIHZhbHVlcyBhcmUgYFwicG9ydHJhaXRcImAsIGBcImxhbmRzY2FwZVwiYCBvciBhIG1lZGlhIHF1ZXJ5LlxuICAgKiAgICAgVGhlIHN0cmluZ3MgYFwicG9ydHJhaXRcImAgYW5kIGBcImxhbmRzY2FwZVwiYCBtZWFucyB0aGUgdmlldyB3aWxsIGNvbGxhcHNlIHdoZW4gZGV2aWNlIGlzIGluIGxhbmRzY2FwZSBvciBwb3J0cmFpdCBvcmllbnRhdGlvbi5cbiAgICogICAgIElmIHRoZSB2YWx1ZSBpcyBhIG1lZGlhIHF1ZXJ5LCB0aGUgdmlldyB3aWxsIGNvbGxhcHNlIHdoZW4gdGhlIG1lZGlhIHF1ZXJ5IHJlc29sdmVzIHRvIGB0cnVlYC5cbiAgICogICAgIElmIHRoZSB2YWx1ZSBpcyBub3QgZGVmaW5lZCwgdGhlIHZpZXcgYWx3YXlzIGJlIGluIGBcImNvbGxhcHNlXCJgIG1vZGUuXG4gICAqICAgWy9lbl1cbiAgICogICBbamFdXG4gICAqICAgICDlt6blgbTjga7jg5rjg7zjgrjjgpLpnZ7ooajnpLrjgavjgZnjgovmnaHku7bjgpLmjIflrprjgZfjgb7jgZnjgIJwb3J0cmFpdCwgbGFuZHNjYXBl44CBd2lkdGggI3B444KC44GX44GP44Gv44Oh44OH44Kj44Ki44Kv44Ko44Oq44Gu5oyH5a6a44GM5Y+v6IO944Gn44GZ44CCXG4gICAqICAgICBwb3J0cmFpdOOCguOBl+OBj+OBr2xhbmRzY2FwZeOCkuaMh+WumuOBmeOCi+OBqOOAgeODh+ODkOOCpOOCueOBrueUu+mdouOBjOe4puWQkeOBjeOCguOBl+OBj+OBr+aoquWQkeOBjeOBq+OBquOBo+OBn+aZguOBq+mBqeeUqOOBleOCjOOBvuOBmeOAglxuICAgKiAgICAg44Oh44OH44Kj44Ki44Kv44Ko44Oq44KS5oyH5a6a44GZ44KL44Go44CB5oyH5a6a44GX44Gf44Kv44Ko44Oq44Gr6YGp5ZCI44GX44Gm44GE44KL5aC05ZCI44Gr6YGp55So44GV44KM44G+44GZ44CCXG4gICAqICAgICDlgKTjgavkvZXjgoLmjIflrprjgZfjgarjgYTloLTlkIjjgavjga/jgIHluLjjgatjb2xsYXBzZeODouODvOODieOBq+OBquOCiuOBvuOBmeOAglxuICAgKiAgIFsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHN3aXBlLXRhcmdldC13aWR0aFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIHdpZHRoIG9mIHN3aXBlYWJsZSBhcmVhIGNhbGN1bGF0ZWQgZnJvbSB0aGUgZWRnZSAoaW4gcGl4ZWxzKS4gVXNlIHRoaXMgdG8gZW5hYmxlIHN3aXBlIG9ubHkgd2hlbiB0aGUgZmluZ2VyIHRvdWNoIG9uIHRoZSBzY3JlZW4gZWRnZS5bL2VuXVxuICAgKiAgIFtqYV3jgrnjg6/jgqTjg5fjga7liKTlrprpoJjln5/jgpLjg5Tjgq/jgrvjg6vljZjkvY3jgafmjIflrprjgZfjgb7jgZnjgILnlLvpnaLjga7nq6/jgYvjgonmjIflrprjgZfjgZ/ot53pm6LjgavpgZTjgZnjgovjgajjg5rjg7zjgrjjgYzooajnpLrjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSB3aWR0aFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ2FuIGJlIHNwZWNpZmllZCBpbiBlaXRoZXIgcGl4ZWxzIG9yIGFzIGEgcGVyY2VudGFnZSwgZS5nLiBgOTAlYCBvciBgMjAwcHhgLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruimgee0oOOBruaoquW5heOCkuaMh+WumuOBl+OBvuOBmeOAgnB444GoJeOBp+OBruaMh+WumuOBjOWPr+iDveOBp+OBmeOAgmVnLiA5MCUsIDIwMHB4Wy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc2lkZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBsZWZ0XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IHdoaWNoIHNpZGUgb2YgdGhlIHNjcmVlbiB0aGUgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGVsZW1lbnQgaXMgbG9jYXRlZC4gUG9zc2libGUgdmFsdWVzIGFyZSBgXCJsZWZ0XCJgIGFuZCBgXCJyaWdodFwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7opoHntKDjgYzlt6bjgYvlj7PjgYvjgpLmjIflrprjgZfjgb7jgZnjgILmjIflrprjgafjgY3jgovlgKTjga9cImxlZnRcIuOBi1wicmlnaHRcIuOBruOBv+OBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGVcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUN1cnJlbnQgbW9kZS4gUG9zc2libGUgdmFsdWVzIGFyZSBgXCJjb2xsYXBzZVwiYCBvciBgXCJzcGxpdFwiYC4gVGhpcyBhdHRyaWJ1dGUgaXMgcmVhZCBvbmx5LlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBruODouODvOODieOBjOioreWumuOBleOCjOOBvuOBmeOAglwiY29sbGFwc2VcIuOCguOBl+OBj+OBr1wic3BsaXRcIuOBjOaMh+WumuOBleOCjOOBvuOBmeOAguOBk+OBruWxnuaAp+OBr+iqreOBv+i+vOOBv+WwgueUqOOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHBhZ2VcbiAgICogQGluaXRvbmx5XG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgVVJMIG9mIHRoZSBtZW51IHBhZ2UuWy9lbl1cbiAgICogICBbamFdb25zLXNwbGl0dGVyLXNpZGXopoHntKDjgavooajnpLrjgZnjgovjg5rjg7zjgrjjga5VUkzjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBzd2lwZWFibGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRvIGVuYWJsZSBzd2lwZSBpbnRlcmFjdGlvbiBvbiBjb2xsYXBzZSBtb2RlLlsvZW5dXG4gICAqICAgW2phXWNvbGxhcHNl44Oi44O844OJ5pmC44Gr44K544Ov44Kk44OX5pON5L2c44KS5pyJ5Yq544Gr44GZ44KL5aC05ZCI44Gr5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX3BhZ2UgPSBudWxsO1xuICAgIHRoaXMuX3N0YXRlID0gQ0xPU0VEX1NUQVRFO1xuICAgIHRoaXMuX2xvY2sgPSBuZXcgRG9vckxvY2soKTtcbiAgICB0aGlzLl9wYWdlTG9hZGVyID0gZGVmYXVsdFBhZ2VMb2FkZXI7XG4gICAgdGhpcy5fY29sbGFwc2VEZXRlY3Rpb24gPSBuZXcgQ29sbGFwc2VEZXRlY3Rpb24odGhpcyk7XG5cbiAgICB0aGlzLl9hbmltYXRvckZhY3RvcnkgPSBuZXcgQW5pbWF0b3JGYWN0b3J5KHtcbiAgICAgIGFuaW1hdG9yczogU3BsaXR0ZXJFbGVtZW50LmFuaW1hdG9ycyxcbiAgICAgIGJhc2VDbGFzczogU3BsaXR0ZXJBbmltYXRvcixcbiAgICAgIGJhc2VDbGFzc05hbWU6ICdTcGxpdHRlckFuaW1hdG9yJyxcbiAgICAgIGRlZmF1bHRBbmltYXRpb246IHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24nKVxuICAgIH0pO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIC8vIFRoZXNlIGF0dHJpYnV0ZXMgYXJlIHVzZWQgZWFybHkgYnkgdGhlIHBhcmVudCBlbGVtZW50XG4gICAgICB0aGlzLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaygnd2lkdGgnKTtcbiAgICAgIGlmICghdGhpcy5oYXNBdHRyaWJ1dGUoJ3NpZGUnKSkge1xuICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZSgnc2lkZScsICdsZWZ0Jyk7XG4gICAgICB9XG5cbiAgICAgIHJld3JpdGFibGVzLnJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgICAgY29uc3QgcGFnZSA9IHRoaXMuX3BhZ2UgfHwgdGhpcy5nZXRBdHRyaWJ1dGUoJ3BhZ2UnKTtcbiAgICAgICAgcGFnZSAmJiB0aGlzLmxvYWQocGFnZSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGlmICghdXRpbC5tYXRjaCh0aGlzLnBhcmVudE5vZGUsICdvbnMtc3BsaXR0ZXInKSkge1xuICAgICAgdXRpbC50aHJvdygnUGFyZW50IG11c3QgYmUgYW4gb25zLXNwbGl0dGVyIGVsZW1lbnQnKTtcbiAgICB9XG5cbiAgICB0aGlzLl9zd2lwZSA9IG5ldyBTd2lwZVJldmVhbCh7XG4gICAgICBlbGVtZW50OiB0aGlzLFxuICAgICAgZWxlbWVudEhhbmRsZXI6IHRoaXMucGFyZW50RWxlbWVudCxcbiAgICAgIHN3aXBlTWF4OiAoKSA9PiB7XG4gICAgICAgIHRoaXMuX29uU3dpcGUgJiYgdGhpcy5fb25Td2lwZSgxLCB0aGlzLl9hbmltYXRpb25PcHQpO1xuICAgICAgICB0aGlzLm9wZW4oKTtcbiAgICAgIH0sXG4gICAgICBzd2lwZU1pZDogKGRpc3RhbmNlLCB3aWR0aCkgPT4ge1xuICAgICAgICB0aGlzLl9vblN3aXBlICYmIHRoaXMuX29uU3dpcGUoZGlzdGFuY2Uvd2lkdGgpO1xuICAgICAgICB0aGlzLl9hbmltYXRvci50cmFuc2xhdGUoZGlzdGFuY2UpO1xuICAgICAgfSxcbiAgICAgIHN3aXBlTWluOiAoKSA9PiB7XG4gICAgICAgIHRoaXMuX29uU3dpcGUgJiYgdGhpcy5fb25Td2lwZSgwLCB0aGlzLl9hbmltYXRpb25PcHQpO1xuICAgICAgICB0aGlzLmNsb3NlKCk7XG4gICAgICB9LFxuICAgICAgZ2V0VGhyZXNob2xkOiAoKSA9PiBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBwYXJzZUZsb2F0KHRoaXMuZ2V0QXR0cmlidXRlKCdvcGVuLXRocmVzaG9sZCcpKSB8fCAwLjMpKSxcbiAgICAgIGdldFNpZGU6ICgpID0+IHRoaXMuc2lkZSxcbiAgICAgIGlzSW5pdGlhbFN0YXRlOiAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGNsb3NlZCA9IHRoaXMuX3N0YXRlID09PSBDTE9TRURfU1RBVEU7XG4gICAgICAgIHRoaXMuX3N0YXRlID0gQ0hBTkdJTkdfU1RBVEU7XG4gICAgICAgIHJldHVybiBjbG9zZWQ7XG4gICAgICB9LFxuICAgICAgaWdub3JlU3dpcGU6IChldmVudCwgZGlzdGFuY2UpID0+IHtcbiAgICAgICAgY29uc3QgaXNPcGVuID0gdGhpcy5pc09wZW47XG4gICAgICAgIGNvbnN0IHZhbGlkRHJhZyA9IGQgPT4gdGhpcy5zaWRlID09PSAnbGVmdCdcbiAgICAgICAgICA/ICgoZCA9PT0gJ2xlZnQnICYmIGlzT3BlbikgfHwgKGQgPT09ICdyaWdodCcgJiYgIWlzT3BlbikpXG4gICAgICAgICAgOiAoKGQgPT09ICdsZWZ0JyAmJiAhaXNPcGVuKSB8fCAoZCA9PT0gJ3JpZ2h0JyAmJiBpc09wZW4pKTtcblxuICAgICAgICBjb25zdCBhcmVhID0gTWF0aC5tYXgoMCwgcGFyc2VJbnQodGhpcy5nZXRBdHRyaWJ1dGUoJ3N3aXBlLXRhcmdldC13aWR0aCcpLCAxMCkgfHwgMCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX21vZGUgPT09IFNQTElUX01PREUgfHwgdGhpcy5fbG9jay5pc0xvY2tlZCgpIHx8IHRoaXMuX2lzT3RoZXJTaWRlT3BlbigpXG4gICAgICAgICAgfHwgIXZhbGlkRHJhZyhldmVudC5nZXN0dXJlLmRpcmVjdGlvbilcbiAgICAgICAgICB8fCAoIWlzT3BlbiAmJiBhcmVhICE9PSAwICYmIGRpc3RhbmNlID4gYXJlYSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaygnc3dpcGVhYmxlJyk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5vYnNlcnZlZEF0dHJpYnV0ZXMuZm9yRWFjaChhdHRyID0+IHRoaXMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKGF0dHIsIG51bGwsIHRoaXMuZ2V0QXR0cmlidXRlKGF0dHIpKSk7XG4gICAgfSk7XG4gIH1cblxuICBnZXQgc2lkZSgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRBdHRyaWJ1dGUoJ3NpZGUnKSA9PT0gJ3JpZ2h0JyA/ICdyaWdodCcgOiAnbGVmdCc7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLl9zd2lwZSAmJiB0aGlzLl9zd2lwZS5kaXNwb3NlKCk7XG4gICAgdGhpcy5fYW5pbWF0b3IgPSB0aGlzLl9hbmltYXRpb25PcHQgPSB0aGlzLl9zd2lwZSA9IG51bGw7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydhbmltYXRpb24nLCAnd2lkdGgnLCAnY29sbGFwc2UnLCAnc3dpcGVhYmxlJywgJ2FuaW1hdGlvbi1vcHRpb25zJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnc3dpcGVhYmxlJzpcbiAgICAgICAgdGhpcy5fc3dpcGUgJiYgdGhpcy5fc3dpcGUudXBkYXRlKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnd2lkdGgnOlxuICAgICAgICBjdXJyZW50ID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3dpZHRoJyk7IC8vIFNvbWV0aW1lcyB1bmRlZmluZWQuIENFIGJ1Zz9cbiAgICAgICAgdGhpcy5zdHlsZS53aWR0aCA9IC9eXFxkKyhweHwlKSQvLnRlc3QoY3VycmVudCkgPyBjdXJyZW50IDogJzgwJSc7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhpc1t1dGlsLmNhbWVsaXplKGBfdXBkYXRlLSR7bmFtZX1gKV0oY3VycmVudCk7XG4gICAgfVxuICB9XG5cbiAgX2VtaXRFdmVudChuYW1lKSB7XG4gICAgaWYgKG5hbWUuc2xpY2UoMCwgMykgIT09ICdwcmUnKSB7XG4gICAgICByZXR1cm4gdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsIG5hbWUsIHtzaWRlOiB0aGlzfSk7XG4gICAgfVxuICAgIGxldCBpc0NhbmNlbGVkID0gZmFsc2U7XG5cbiAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgbmFtZSwge1xuICAgICAgc2lkZTogdGhpcyxcbiAgICAgIGNhbmNlbDogKCkgPT4gaXNDYW5jZWxlZCA9IHRydWVcbiAgICB9KTtcblxuICAgIHJldHVybiBpc0NhbmNlbGVkO1xuICB9XG5cbiAgX2lzT3RoZXJTaWRlT3BlbigpIHtcbiAgICByZXR1cm4gISF1dGlsLmZpbmRDaGlsZCh0aGlzLnBhcmVudEVsZW1lbnQsXG4gICAgICBlbCA9PiBlbCBpbnN0YW5jZW9mIHRoaXMuY29uc3RydWN0b3IgJiYgZWwgIT09IHRoaXMgJiYgZWwuX21vZGUgPT09IENPTExBUFNFX01PREUgJiYgZWwuaXNPcGVuXG4gICAgKTtcbiAgfVxuXG4gIF91cGRhdGVDb2xsYXBzZSh2YWx1ZSA9IHRoaXMuZ2V0QXR0cmlidXRlKCdjb2xsYXBzZScpKSB7XG4gICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSAnc3BsaXQnKSB7XG4gICAgICB0aGlzLl9jb2xsYXBzZURldGVjdGlvbi5kaXNhYmxlKCk7XG4gICAgICByZXR1cm4gdGhpcy5fdXBkYXRlTW9kZShTUExJVF9NT0RFKTtcbiAgICB9XG4gICAgaWYgKHZhbHVlID09PSAnJyB8fCB2YWx1ZSA9PT0gJ2NvbGxhcHNlJykge1xuICAgICAgdGhpcy5fY29sbGFwc2VEZXRlY3Rpb24uZGlzYWJsZSgpO1xuICAgICAgcmV0dXJuIHRoaXMuX3VwZGF0ZU1vZGUoQ09MTEFQU0VfTU9ERSk7XG4gICAgfVxuXG4gICAgdGhpcy5fY29sbGFwc2VEZXRlY3Rpb24uY2hhbmdlVGFyZ2V0KHZhbHVlKTtcbiAgfVxuXG4gIF91cGRhdGVNb2RlKG1vZGUpIHtcbiAgICBpZiAobW9kZSAhPT0gdGhpcy5fbW9kZSkge1xuICAgICAgdGhpcy5fbW9kZSA9IG1vZGU7XG4gICAgICB0aGlzLnNldEF0dHJpYnV0ZSgnbW9kZScsIG1vZGUpOyAvLyByZWFkb25seSBhdHRyaWJ1dGUgZm9yIHRoZSB1c2Vyc1xuXG4gICAgICBpZiAobW9kZSA9PT0gU1BMSVRfTU9ERSkge1xuICAgICAgICB0aGlzLl9hbmltYXRvciAmJiB0aGlzLl9hbmltYXRvci5kZWFjdGl2YXRlKCk7XG4gICAgICAgIHRoaXMuX3N0YXRlID0gQ0xPU0VEX1NUQVRFO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fYW5pbWF0b3IgJiYgdGhpcy5fYW5pbWF0b3IuYWN0aXZhdGUodGhpcyk7XG4gICAgICAgIHRoaXMuX3N0YXRlID09PSBPUEVOX1NUQVRFICYmIHRoaXMuX2FuaW1hdG9yLm9wZW4oKTtcbiAgICAgIH1cblxuICAgICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdtb2RlY2hhbmdlJywgeyBzaWRlOiB0aGlzLCBtb2RlIH0pO1xuICAgIH1cbiAgfVxuXG4gIF91cGRhdGVBbmltYXRpb24oYW5pbWF0aW9uID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpKSB7XG4gICAgaWYgKHRoaXMucGFyZW50Tm9kZSkge1xuICAgICAgdGhpcy5fYW5pbWF0b3IgJiYgdGhpcy5fYW5pbWF0b3IuZGVhY3RpdmF0ZSgpO1xuICAgICAgdGhpcy5fYW5pbWF0b3IgPSB0aGlzLl9hbmltYXRvckZhY3RvcnkubmV3QW5pbWF0b3Ioe2FuaW1hdGlvbn0pO1xuICAgICAgdGhpcy5fYW5pbWF0b3IuYWN0aXZhdGUodGhpcyk7XG4gICAgICB0aGlzLl9hbmltYXRpb25PcHQgPSB7XG4gICAgICAgIHRpbWluZzogdGhpcy5fYW5pbWF0b3IuZHVyYXRpb24sXG4gICAgICAgIGR1cmF0aW9uOiB0aGlzLl9hbmltYXRvci5kdXJhdGlvblxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBfdXBkYXRlQW5pbWF0aW9uT3B0aW9ucyh2YWx1ZSA9IHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24tb3B0aW9ucycpKSB7XG4gICAgdGhpcy5fYW5pbWF0b3IudXBkYXRlT3B0aW9ucyhBbmltYXRvckZhY3RvcnkucGFyc2VBbmltYXRpb25PcHRpb25zU3RyaW5nKHZhbHVlKSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHBhZ2VcbiAgICogQHR5cGUgeyp9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1QYWdlIGxvY2F0aW9uIHRvIGxvYWQgaW4gdGhlIHNwbGl0dGVyIHNpZGUuWy9lbl1cbiAgICogICBbamFd44GT44Gu6KaB57Sg5YaF44Gr6KGo56S644GZ44KL44Oa44O844K444KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGdldCBwYWdlKCkge1xuICAgIHJldHVybiB0aGlzLl9wYWdlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7Kn0gcGFnZVxuICAgKi9cbiAgc2V0IHBhZ2UocGFnZSkge1xuICAgIHRoaXMuX3BhZ2UgPSBwYWdlO1xuICB9XG5cbiAgZ2V0IF9jb250ZW50KCkge1xuICAgIHJldHVybiB0aGlzLmNoaWxkcmVuWzBdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBwYWdlTG9hZGVyXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgZ2V0IHBhZ2VMb2FkZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BhZ2VMb2FkZXI7XG4gIH1cblxuICBzZXQgcGFnZUxvYWRlcihsb2FkZXIpIHtcbiAgICBpZiAoIShsb2FkZXIgaW5zdGFuY2VvZiBQYWdlTG9hZGVyKSkge1xuICAgICAgdXRpbC50aHJvd1BhZ2VMb2FkZXIoKTtcbiAgICB9XG4gICAgdGhpcy5fcGFnZUxvYWRlciA9IGxvYWRlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgbW9kZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUN1cnJlbnQgbW9kZS4gUG9zc2libGUgdmFsdWVzIGFyZSBcInNwbGl0XCIsIFwiY29sbGFwc2VcIiwgXCJjbG9zZWRcIiwgXCJvcGVuXCIgb3IgXCJjaGFuZ2luZ1wiLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgbW9kZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fbW9kZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb25Td2lwZVxuICAgKiBAdHlwZSB7RnVuY3Rpb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Ib29rIGNhbGxlZCB3aGVuZXZlciB0aGUgdXNlciBzbGlkZXMgdGhlIHNwbGl0dGVyLiBJdCBnZXRzIGEgZGVjaW1hbCByYXRpbyAoMC0xKSBhbmQgYW4gYW5pbWF0aW9uT3B0aW9ucyBvYmplY3QgYXMgYXJndW1lbnRzLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgb25Td2lwZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fb25Td2lwZTtcbiAgfVxuXG4gIHNldCBvblN3aXBlKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICYmICEodmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHV0aWwudGhyb3coJ1wib25Td2lwZVwiIG11c3QgYmUgYSBmdW5jdGlvbicpXG4gICAgfVxuICAgIHRoaXMuX29uU3dpcGUgPSB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgaXNPcGVuXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAcmVhZG9ubHlcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoaXMgdmFsdWUgaXMgYHRydWVgIHdoZW4gdGhlIG1lbnUgaXMgb3Blbi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgZ2V0IGlzT3BlbigpIHtcbiAgICByZXR1cm4gdGhpcy5fbW9kZSA9PT0gQ09MTEFQU0VfTU9ERSAmJiB0aGlzLl9zdGF0ZSAhPT0gQ0xPU0VEX1NUQVRFO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2Qgb3BlblxuICAgKiBAc2lnbmF0dXJlIG9wZW4oW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXVRoaXMgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgYWZ0ZXIgdGhlIG1lbnUgaGFzIGJlZW4gb3BlbmVkLlsvZW5dXG4gICAqICAgW2phXeODoeODi+ODpeODvOOBjOmWi+OBhOOBn+W+jOOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1PcGVuIG1lbnUgaW4gY29sbGFwc2UgbW9kZS5bL2VuXVxuICAgKiAgIFtqYV1jb2xsYXBzZeODouODvOODieOBq+OBquOBo+OBpuOBhOOCi29ucy1zcGxpdHRlci1zaWRl6KaB57Sg44KS6ZaL44GN44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIHNwbGl0dGVyIHNpZGUgZWxlbWVudCBvciBmYWxzZSBpZiBub3QgaW4gY29sbGFwc2UgbW9kZVsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBvcGVuKG9wdGlvbnMpIHtcbiAgICByZXR1cm4gdGhpcy50b2dnbGUob3B0aW9ucywgdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBjbG9zZVxuICAgKiBAc2lnbmF0dXJlIGNsb3NlKFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1UaGlzIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIGFmdGVyIHRoZSBtZW51IGhhcyBiZWVuIGNsb3NlZC5bL2VuXVxuICAgKiAgIFtqYV3jg6Hjg4vjg6Xjg7zjgYzplonjgZjjgZ/lvozjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ2xvc2UgbWVudSBpbiBjb2xsYXBzZSBtb2RlLlsvZW5dXG4gICAqICAgW2phXWNvbGxhcHNl44Oi44O844OJ44Gr44Gq44Gj44Gm44GE44KLb25zLXNwbGl0dGVyLXNpZGXopoHntKDjgpLplonjgZjjgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgc3BsaXR0ZXIgc2lkZSBlbGVtZW50IG9yIGZhbHNlIGlmIG5vdCBpbiBjb2xsYXBzZSBtb2RlWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGNsb3NlKG9wdGlvbnMpIHtcbiAgICByZXR1cm4gdGhpcy50b2dnbGUob3B0aW9ucywgZmFsc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgdG9nZ2xlXG4gICAqIEBzaWduYXR1cmUgdG9nZ2xlKFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dT3BlbnMgaWYgaXQncyBjbG9zZWQuIENsb3NlcyBpZiBpdCdzIG9wZW4uWy9lbl1cbiAgICogICBbamFd6ZaL44GR44Gm44GE44KL5aC05ZCI44Gv6KaB57Sg44KS6ZaJ44GY44G+44GZ44Gd44GX44Gm6ZaL44GR44Gm44GE44KL5aC05ZCI44Gv6KaB57Sg44KS6ZaL44GN44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIHNwbGl0dGVyIHNpZGUgZWxlbWVudCBvciBmYWxzZSBpZiBub3QgaW4gY29sbGFwc2UgbW9kZVsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICB0b2dnbGUob3B0aW9ucyA9IHt9LCBmb3JjZSkge1xuICAgIGNvbnN0IHNob3VsZE9wZW4gPSB0eXBlb2YgZm9yY2UgPT09ICdib29sZWFuJyA/IGZvcmNlIDogIXRoaXMuaXNPcGVuO1xuICAgIGNvbnN0IGFjdGlvbiA9IHNob3VsZE9wZW4gPyAnb3BlbicgOiAnY2xvc2UnO1xuICAgIGNvbnN0IEZJTkFMX1NUQVRFID0gc2hvdWxkT3BlbiA/IE9QRU5fU1RBVEUgOiBDTE9TRURfU1RBVEU7XG5cbiAgICBpZiAodGhpcy5fbW9kZSA9PT0gU1BMSVRfTU9ERSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmYWxzZSk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9zdGF0ZSA9PT0gRklOQUxfU1RBVEUpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcyk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9sb2NrLmlzTG9ja2VkKCkpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnQW5vdGhlciBzcGxpdHRlci1zaWRlIGFjdGlvbiBpcyBhbHJlYWR5IHJ1bm5pbmcuJyk7XG4gICAgfVxuICAgIGlmIChzaG91bGRPcGVuICYmIHRoaXMuX2lzT3RoZXJTaWRlT3BlbigpKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ0Fub3RoZXIgbWVudSBpcyBhbHJlYWR5IG9wZW4uJyk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9lbWl0RXZlbnQoYHByZSR7YWN0aW9ufWApKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoYENhbmNlbGVkIGluIHByZSR7YWN0aW9ufSBldmVudC5gKTtcbiAgICB9XG5cbiAgICBjb25zdCB1bmxvY2sgPSB0aGlzLl9sb2NrLmxvY2soKTtcbiAgICB0aGlzLl9zdGF0ZSA9IENIQU5HSU5HX1NUQVRFO1xuXG4gICAgaWYgKG9wdGlvbnMuYW5pbWF0aW9uKSB7XG4gICAgICB0aGlzLl91cGRhdGVBbmltYXRpb24ob3B0aW9ucy5hbmltYXRpb24pO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIHRoaXMuX2FuaW1hdG9yW2FjdGlvbl0oKCkgPT4ge1xuICAgICAgICB1dGlsLmlvc1BhZ2VTY3JvbGxGaXgoc2hvdWxkT3Blbik7XG4gICAgICAgIHRoaXMuX3N0YXRlID0gRklOQUxfU1RBVEU7XG4gICAgICAgIHVubG9jaygpO1xuICAgICAgICB0aGlzLl9lbWl0RXZlbnQoYHBvc3Qke2FjdGlvbn1gKTtcbiAgICAgICAgb3B0aW9ucy5jYWxsYmFjayBpbnN0YW5jZW9mIEZ1bmN0aW9uICYmIG9wdGlvbnMuY2FsbGJhY2sodGhpcyk7XG4gICAgICAgIHJlc29sdmUodGhpcyk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGxvYWRcbiAgICogQHNpZ25hdHVyZSBsb2FkKHBhZ2UsIFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtTdHJpbmd9IHBhZ2VcbiAgICogICBbZW5dUGFnZSBVUkwuIENhbiBiZSBlaXRoZXIgYW4gSFRNTCBkb2N1bWVudCBvciBhIGA8dGVtcGxhdGU+YC5bL2VuXVxuICAgKiAgIFtqYV1wYWdl44GuVVJM44GL44CBYDx0ZW1wbGF0ZT5g44Gn5a6j6KiA44GX44Gf44OG44Oz44OX44Os44O844OI44GuaWTlsZ7mgKfjga7lgKTjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyB0aGUgcGFnZSBzcGVjaWZpZWQgaW4gcGFnZVVybCBpbiB0aGUgcmlnaHQgc2VjdGlvblsvZW5dXG4gICAqICAgW2phXeaMh+WumuOBl+OBn1VSTOOCkuODoeOCpOODs+ODmuODvOOCuOOCkuiqreOBv+i+vOOBv+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVJlc29sdmVzIHRvIHRoZSBuZXcgcGFnZSBlbGVtZW50Wy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGxvYWQocGFnZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5fcGFnZSA9IHBhZ2U7XG4gICAgY29uc3QgY2FsbGJhY2sgPSBvcHRpb25zLmNhbGxiYWNrIHx8ICgoKSA9PiB7fSk7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICBsZXQgb2xkQ29udGVudCA9IHRoaXMuX2NvbnRlbnQgfHwgbnVsbDtcblxuICAgICAgdGhpcy5fcGFnZUxvYWRlci5sb2FkKHtwYWdlLCBwYXJlbnQ6IHRoaXN9LCBwYWdlRWxlbWVudCA9PiB7XG4gICAgICAgIGlmIChvbGRDb250ZW50KSB7XG4gICAgICAgICAgdGhpcy5fcGFnZUxvYWRlci51bmxvYWQob2xkQ29udGVudCk7XG4gICAgICAgICAgb2xkQ29udGVudCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBzZXRJbW1lZGlhdGUoKCkgPT4gdGhpcy5fc2hvdygpKTtcblxuICAgICAgICBjYWxsYmFjayhwYWdlRWxlbWVudCk7XG4gICAgICAgIHJlc29sdmUocGFnZUVsZW1lbnQpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBfc2hvdygpIHtcbiAgICBpZiAodGhpcy5fY29udGVudCkge1xuICAgICAgdGhpcy5fY29udGVudC5fc2hvdygpO1xuICAgIH1cbiAgfVxuXG4gIF9oaWRlKCkge1xuICAgIGlmICh0aGlzLl9jb250ZW50KSB7XG4gICAgICB0aGlzLl9jb250ZW50Ll9oaWRlKCk7XG4gICAgfVxuICB9XG5cbiAgX2Rlc3Ryb3koKSB7XG4gICAgaWYgKHRoaXMuX2NvbnRlbnQpIHtcbiAgICAgIHRoaXMuX3BhZ2VMb2FkZXIudW5sb2FkKHRoaXMuX2NvbnRlbnQpO1xuICAgIH1cbiAgICB0aGlzLnJlbW92ZSgpO1xuICB9XG5cbiAgc3RhdGljIGdldCBldmVudHMoKSB7XG4gICAgcmV0dXJuIFsncHJlb3BlbicsICdwb3N0b3BlbicsICdwcmVjbG9zZScsICdwb3N0Y2xvc2UnLCAnbW9kZWNoYW5nZSddO1xuICB9XG5cbiAgc3RhdGljIGdldCByZXdyaXRhYmxlcygpIHtcbiAgICByZXR1cm4gcmV3cml0YWJsZXM7XG4gIH1cbn1cblxub25zRWxlbWVudHMuU3BsaXR0ZXJTaWRlID0gU3BsaXR0ZXJTaWRlRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXNwbGl0dGVyLXNpZGUnLCBTcGxpdHRlclNpZGVFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VDaGVja2JveEVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtY2hlY2tib3gnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5pbXBvcnQgR2VzdHVyZURldGVjdG9yIGZyb20gJy4uL29ucy9nZXN0dXJlLWRldGVjdG9yJztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ3N3aXRjaC0tKicsXG4gICcuc3dpdGNoX19pbnB1dCc6ICdzd2l0Y2gtLSpfX2lucHV0JyxcbiAgJy5zd2l0Y2hfX2hhbmRsZSc6ICdzd2l0Y2gtLSpfX2hhbmRsZScsXG4gICcuc3dpdGNoX190b2dnbGUnOiAnc3dpdGNoLS0qX190b2dnbGUnXG59O1xuXG5jb25zdCBsb2NhdGlvbnMgPSB7XG4gIGlvczogWzEsIDIxXSxcbiAgbWF0ZXJpYWw6IFswLCAxNl1cbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXN3aXRjaFxuICogQGNhdGVnb3J5IGZvcm1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgU3dpdGNoIGNvbXBvbmVudC4gVGhlIHN3aXRjaCBjYW4gYmUgdG9nZ2xlZCBib3RoIGJ5IGRyYWdnaW5nIGFuZCB0YXBwaW5nLlxuICpcbiAqICAgICBXaWxsIGF1dG9tYXRpY2FsbHkgZGlzcGxheXMgYSBNYXRlcmlhbCBEZXNpZ24gc3dpdGNoIG9uIEFuZHJvaWQgZGV2aWNlcy5cbiAqICAgWy9lbl1cbiAqICAgW2phXeOCueOCpOODg+ODgeOCkuihqOekuuOBmeOCi+OCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAglsvamFdXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXU1hdGVyaWFsIERlc2lnbiBzd2l0Y2hbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIExwWFpRUVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3N3aXRjaFxuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNtb2RpZmllcnMgW2VuXU1vcmUgZGV0YWlscyBhYm91dCB0aGUgYG1vZGlmaWVyYCBhdHRyaWJ1dGVbL2VuXVtqYV1tb2RpZmllcuWxnuaAp+OBruS9v+OBhOaWuVsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1zd2l0Y2ggY2hlY2tlZD48L29ucy1zd2l0Y2g+XG4gKiA8b25zLXN3aXRjaCBkaXNhYmxlZD48L29ucy1zd2l0Y2g+XG4gKiA8b25zLXN3aXRjaCBtb2RpZmllcj1cIm1hdGVyaWFsXCI+PC9vbnMtc3dpdGNoPlxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN3aXRjaEVsZW1lbnQgZXh0ZW5kcyBCYXNlQ2hlY2tib3hFbGVtZW50IHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKCdtb2RpZmllcicsIG51bGwsIHRoaXMuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpKTtcbiAgICB9KTtcblxuICAgIHRoaXMuX29uQ2hhbmdlID0gdGhpcy5fb25DaGFuZ2UuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vblJlbGVhc2UgPSB0aGlzLl9vblJlbGVhc2UuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9sYXN0VGltZVN0YW1wID0gMDtcbiAgfVxuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHJldHVybiBzY2hlbWU7XG4gIH1cblxuICBnZXQgX2RlZmF1bHRDbGFzc05hbWUoKSB7XG4gICAgcmV0dXJuICdzd2l0Y2gnO1xuICB9XG5cbiAgZ2V0IF90ZW1wbGF0ZSgpIHtcbiAgICByZXR1cm4gYFxuICAgICAgPGlucHV0IHR5cGU9XCIke3RoaXMudHlwZX1cIiBjbGFzcz1cIiR7dGhpcy5fZGVmYXVsdENsYXNzTmFtZX1fX2lucHV0XCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiJHt0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lfV9fdG9nZ2xlXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCIke3RoaXMuX2RlZmF1bHRDbGFzc05hbWV9X19oYW5kbGVcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiJHt0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lfV9fdG91Y2hcIj48L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICBgO1xuICB9XG5cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuICdjaGVja2JveCc7XG4gIH1cblxuICAvKiBPd24gcHJvcHMgKi9cblxuICBfZ2V0UG9zaXRpb24oZSkge1xuICAgIGNvbnN0IGwgPSB0aGlzLl9sb2NhdGlvbnM7XG4gICAgcmV0dXJuIE1hdGgubWluKGxbMV0sIE1hdGgubWF4KGxbMF0sIHRoaXMuX3N0YXJ0WCArIGUuZ2VzdHVyZS5kZWx0YVgpKTtcbiAgfVxuXG4gIF9lbWl0Q2hhbmdlRXZlbnQoKSB7XG4gICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdjaGFuZ2UnLCB7XG4gICAgICB2YWx1ZTogdGhpcy5jaGVja2VkLFxuICAgICAgc3dpdGNoOiB0aGlzLFxuICAgICAgaXNJbnRlcmFjdGl2ZTogdHJ1ZVxuICAgIH0pO1xuICB9XG5cbiAgX29uQ2hhbmdlKGV2ZW50KSB7XG4gICAgaWYgKGV2ZW50ICYmIGV2ZW50LnN0b3BQcm9wYWdhdGlvbikge1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfVxuXG4gICAgdGhpcy5fZW1pdENoYW5nZUV2ZW50KCk7XG4gIH1cblxuICBfb25DbGljayhldikge1xuICAgIGlmIChldi50YXJnZXQuY2xhc3NMaXN0LmNvbnRhaW5zKGAke3RoaXMuZGVmYXVsdEVsZW1lbnRDbGFzc31fX3RvdWNoYClcbiAgICAgIHx8IChldi50aW1lU3RhbXAgLSB0aGlzLl9sYXN0VGltZVN0YW1wIDwgNTApIC8vIFByZXZlbnQgc2Vjb25kIGNsaWNrIHRyaWdnZXJlZCBieSA8bGFiZWw+XG4gICAgKSB7XG4gICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbiAgICB0aGlzLl9sYXN0VGltZVN0YW1wID0gZXYudGltZVN0YW1wO1xuICB9XG5cbiAgX29uSG9sZChlKSB7XG4gICAgaWYgKCF0aGlzLmRpc2FibGVkKSB7XG4gICAgICBNb2RpZmllclV0aWwuYWRkTW9kaWZpZXIodGhpcywgJ2FjdGl2ZScpO1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncmVsZWFzZScsIHRoaXMuX29uUmVsZWFzZSk7XG4gICAgfVxuICB9XG5cbiAgX29uRHJhZ1N0YXJ0KGUpIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCB8fCBbJ2xlZnQnLCAncmlnaHQnXS5pbmRleE9mKGUuZ2VzdHVyZS5kaXJlY3Rpb24pID09PSAtMSkge1xuICAgICAgTW9kaWZpZXJVdGlsLnJlbW92ZU1vZGlmaWVyKHRoaXMsICdhY3RpdmUnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBlLmNvbnN1bWVkID0gdHJ1ZTtcblxuICAgIE1vZGlmaWVyVXRpbC5hZGRNb2RpZmllcih0aGlzLCAnYWN0aXZlJyk7XG4gICAgdGhpcy5fc3RhcnRYID0gdGhpcy5fbG9jYXRpb25zW3RoaXMuY2hlY2tlZCA/IDEgOiAwXTsvLyAtIGUuZ2VzdHVyZS5kZWx0YVg7XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWcnLCB0aGlzLl9vbkRyYWcpO1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3JlbGVhc2UnLCB0aGlzLl9vblJlbGVhc2UpO1xuICB9XG5cbiAgX29uRHJhZyhlKSB7XG4gICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB0aGlzLl9oYW5kbGUuc3R5bGUubGVmdCA9IHRoaXMuX2dldFBvc2l0aW9uKGUpICsgJ3B4JztcbiAgfVxuXG4gIF9vblJlbGVhc2UoZSkge1xuICAgIGNvbnN0IGwgPSB0aGlzLl9sb2NhdGlvbnM7XG4gICAgY29uc3QgcG9zaXRpb24gPSB0aGlzLl9nZXRQb3NpdGlvbihlKTtcbiAgICBjb25zdCBwcmV2aW91c1ZhbHVlID0gdGhpcy5jaGVja2VkO1xuXG4gICAgdGhpcy5jaGVja2VkID0gcG9zaXRpb24gPj0gKGxbMF0gKyBsWzFdKSAvIDI7XG5cbiAgICBpZiAodGhpcy5jaGVja2VkICE9PSBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICB0aGlzLl9lbWl0Q2hhbmdlRXZlbnQoKTtcbiAgICB9XG5cbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2RyYWcnLCB0aGlzLl9vbkRyYWcpO1xuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3JlbGVhc2UnLCB0aGlzLl9vblJlbGVhc2UpO1xuXG4gICAgdGhpcy5faGFuZGxlLnN0eWxlLmxlZnQgPSAnJztcbiAgICBNb2RpZmllclV0aWwucmVtb3ZlTW9kaWZpZXIodGhpcywgJ2FjdGl2ZScpO1xuICB9XG5cbiAgY2xpY2soZXYgPSB7fSkge1xuICAgIGlmICghdGhpcy5kaXNhYmxlZCkge1xuICAgICAgdGhpcy5jaGVja2VkID0gIXRoaXMuY2hlY2tlZDtcbiAgICAgIHRoaXMuX2VtaXRDaGFuZ2VFdmVudCgpO1xuICAgICAgdGhpcy5fbGFzdFRpbWVTdGFtcCA9IGV2LnRpbWVTdGFtcCB8fCAwO1xuICAgIH1cbiAgfVxuXG4gIGdldCBfaGFuZGxlKCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3IoYC4ke3RoaXMuX2RlZmF1bHRDbGFzc05hbWV9X19oYW5kbGVgKTtcbiAgfVxuXG4gIGdldCBjaGVja2JveCgpIHtcbiAgICByZXR1cm4gdGhpcy5faW5wdXQ7XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5faW5wdXQuYWRkRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgdGhpcy5fb25DaGFuZ2UpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdkcmFnc3RhcnQnLCB0aGlzLl9vbkRyYWdTdGFydCk7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdob2xkJywgdGhpcy5fb25Ib2xkKTtcbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ3RhcCcsIHRoaXMuY2xpY2spO1xuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9vbkNsaWNrKTtcbiAgICB0aGlzLl9nZXN0dXJlRGV0ZWN0b3IgPSBuZXcgR2VzdHVyZURldGVjdG9yKHRoaXMsIHsgZHJhZ01pbkRpc3RhbmNlOiAxLCBob2xkVGltZW91dDogMjUxLCBwYXNzaXZlOiB0cnVlIH0pO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2lucHV0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIHRoaXMuX29uQ2hhbmdlKTtcbiAgICB9KTtcblxuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignZHJhZ3N0YXJ0JywgdGhpcy5fb25EcmFnU3RhcnQpO1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignaG9sZCcsIHRoaXMuX29uSG9sZCk7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCd0YXAnLCB0aGlzLmNsaWNrKTtcbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5fb25DbGljayk7XG4gICAgaWYgKHRoaXMuX2dlc3R1cmVEZXRlY3Rvcikge1xuICAgICAgdGhpcy5fZ2VzdHVyZURldGVjdG9yLmRpc3Bvc2UoKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWy4uLnN1cGVyLm9ic2VydmVkQXR0cmlidXRlcywgJ21vZGlmaWVyJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIGlmIChuYW1lID09PSAnbW9kaWZpZXInKSB7XG4gICAgICBjb25zdCBtZCA9IChjdXJyZW50IHx8ICcnKS5pbmRleE9mKCdtYXRlcmlhbCcpICE9PSAtMTtcbiAgICAgIHRoaXMuX2xvY2F0aW9ucyA9IGxvY2F0aW9uc1ttZCA/ICdtYXRlcmlhbCcgOiAnaW9zJ107XG4gICAgfVxuXG4gICAgc3VwZXIuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBldmVudCBjaGFuZ2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIHN3aXRjaCBpcyB0b2dnbGVkLlsvZW5dXG4gICAqICAgW2phXU9OL09GRuOBjOWkieOCj+OBo+OBn+aZguOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnN3aXRjaFxuICAgKiAgIFtlbl1Td2l0Y2ggb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCpOODmeODs+ODiOOBjOeZuueBq+OBl+OBn1N3aXRjaOOCquODluOCuOOCp+OCr+ODiOOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gZXZlbnQudmFsdWVcbiAgICogICBbZW5dQ3VycmVudCB2YWx1ZS5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjga7lgKTjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IGV2ZW50LmlzSW50ZXJhY3RpdmVcbiAgICogICBbZW5dVHJ1ZSBpZiB0aGUgY2hhbmdlIHdhcyB0cmlnZ2VyZWQgYnkgdGhlIHVzZXIgY2xpY2tpbmcgb24gdGhlIHN3aXRjaC5bL2VuXVxuICAgKiAgIFtqYV3jgr/jg4Pjg5fjgoTjgq/jg6rjg4Pjgq/jgarjganjga7jg6bjg7zjgrbjga7mk43kvZzjgavjgojjgaPjgablpInjgo/jgaPjgZ/loLTlkIjjgavjga90cnVl44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIHN3aXRjaC5bL2VuXVxuICAgKiAgW2phXeOCueOCpOODg+ODgeOBruihqOePvuOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpc2FibGVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBzd2l0Y2ggaXMgYmUgZGlzYWJsZWQuWy9lbl1cbiAgICogICBbamFd44K544Kk44OD44OB44KS54Sh5Yq544Gu54q25oWL44Gr44GZ44KL5aC05ZCI44Gr5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgY2hlY2tlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgc3dpdGNoIGlzIGNoZWNrZWQuWy9lbl1cbiAgICogICBbamFd44K544Kk44OD44OB44GMT07jga7nirbmhYvjgavjgZnjgovjgajjgY3jgavmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBpbnB1dC1pZFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYGlkYCBhdHRyaWJ1dGUgb2YgdGhlIGlubmVyIGA8aW5wdXQ+YCBlbGVtZW50LiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHVzaW5nIGA8bGFiZWwgZm9yPVwiLi4uXCI+YCBlbGVtZW50cy5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGNoZWNrZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGlzIHZhbHVlIGlzIGB0cnVlYCBpZiB0aGUgc3dpdGNoIGlzIGNoZWNrZWQuWy9lbl1cbiAgICogICBbamFd44K544Kk44OD44OB44GMT07jga7loLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZhbHVlXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgaW5wdXQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgZGlzYWJsZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeeEoeWKueWMluOBleOCjOOBpuOBhOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgY2hlY2tib3hcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtIVE1MRWxlbWVudH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSB1bmRlcmx5aW5nIGNoZWNrYm94IGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI5YaF6YOo44GuY2hlY2tib3jopoHntKDjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxufVxuXG5vbnNFbGVtZW50cy5Td2l0Y2ggPSBTd2l0Y2hFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtc3dpdGNoJywgU3dpdGNoRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBpbnRlcm5hbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi8uLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBTd2lwZXIgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL3N3aXBlcic7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnLnRhYmJhcl9fY29udGVudCc6ICd0YWJiYXItLSpfX2NvbnRlbnQnLFxuICAnLnRhYmJhcl9fYm9yZGVyJzogJ3RhYmJhci0tKl9fYm9yZGVyJyxcbiAgJy50YWJiYXInOiAndGFiYmFyLS0qJ1xufTtcblxuY29uc3QgcmV3cml0YWJsZXMgPSB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IHRhYmJhckVsZW1lbnRcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHJlYWR5KHRhYmJhckVsZW1lbnQsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxufTtcblxuY29uc3QgbnVsbFBhZ2UgPSBpbnRlcm5hbC5udWxsRWxlbWVudDtcbmNvbnN0IGxlcnAgPSAoeDAsIHgxLCB0KSA9PiAoMSAtIHQpICogeDAgKyB0ICogeDE7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXRhYmJhclxuICogQGNhdGVnb3J5IHRhYmJhclxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1BIGNvbXBvbmVudCB0byBkaXNwbGF5IGEgdGFiIGJhciBvbiB0aGUgYm90dG9tIG9mIGEgcGFnZS4gVXNlZCB3aXRoIGA8b25zLXRhYj5gIHRvIG1hbmFnZSBwYWdlcyB1c2luZyB0YWJzLlsvZW5dXG4gKiAgIFtqYV3jgr/jg5bjg5Djg7zjgpLjg5rjg7zjgrjkuIvpg6jjgavooajnpLrjgZnjgovjgZ/jgoHjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjgafjgZnjgIJvbnMtdGFi44Go57WE44G/5ZCI44KP44Gb44Gm5L2/44GG44GT44Go44Gn44CB44Oa44O844K444KS566h55CG44Gn44GN44G+44GZ44CCWy9qYV1cbiAqIEBjb2RlcGVuIHBHdURMXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvdGFiYmFyXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXUEgdGFiYmFyIGluIE1hdGVyaWFsIERlc2lnbi5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBtb2RpZmllciBhdXRvZ3Jvd1xuICogICBbZW5dVGFicyBhdXRvbWF0aWNhbGx5IGdyb3cgZGVwZW5kaW5nIG9uIHRoZWlyIGNvbnRlbnQgaW5zdGVhZCBvZiBoYXZpbmcgYSBmaXhlZCB3aWR0aC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBtb2RpZmllciB0b3AtYm9yZGVyXG4gKiAgIFtlbl1TaG93cyBhIHN0YXRpYyBib3JkZXItYm90dG9tIGluIHRhYnMgZm9yIGlPUyB0b3AgdGFiYmFycy5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBndWlkZSBmdW5kYW1lbnRhbHMuaHRtbCNtYW5hZ2luZy1wYWdlc1xuICogIFtlbl1NYW5hZ2luZyBtdWx0aXBsZSBwYWdlcy5bL2VuXVxuICogIFtqYV3opIfmlbDjga7jg5rjg7zjgrjjgpLnrqHnkIbjgZnjgotbL2phXVxuICogQHNlZWFsc28gb25zLXRhYlxuICogICBbZW5dVGhlIGA8b25zLXRhYj5gIGNvbXBvbmVudC5bL2VuXVxuICogICBbamFdb25zLXRhYuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtcGFnZVxuICogICBbZW5dVGhlIGA8b25zLXBhZ2U+YCBjb21wb25lbnQuWy9lbl1cbiAqICAgW2phXW9ucy1wYWdl44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXRhYmJhcj5cbiAqICAgPG9ucy10YWJcbiAqICAgICBwYWdlPVwiaG9tZS5odG1sXCJcbiAqICAgICBsYWJlbD1cIkhvbWVcIlxuICogICAgIGFjdGl2ZT5cbiAqICAgPC9vbnMtdGFiPlxuICogICA8b25zLXRhYlxuICogICAgIHBhZ2U9XCJzZXR0aW5ncy5odG1sXCJcbiAqICAgICBsYWJlbD1cIlNldHRpbmdzXCJcbiAqICAgICBhY3RpdmU+XG4gKiAgIDwvb25zLXRhYj5cbiAqIDwvb25zLXRhYmJhcj5cbiAqXG4gKiA8dGVtcGxhdGUgaWQ9XCJob21lLmh0bWxcIj5cbiAqICAgLi4uXG4gKiA8L3RlbXBsYXRlPlxuICpcbiAqIDx0ZW1wbGF0ZSBpZD1cInNldHRpbmdzLmh0bWxcIj5cbiAqICAgLi4uXG4gKiA8L3RlbXBsYXRlPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUYWJiYXJFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlY2hhbmdlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlcyBqdXN0IGJlZm9yZSB0aGUgdGFiIGlzIGNoYW5nZWQuWy9lbl1cbiAgICogICBbamFd44Ki44Kv44OG44Kj44OW44Gq44K/44OW44GM5aSJ44KP44KL5YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50XG4gICAqICAgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge051bWJlcn0gZXZlbnQuaW5kZXhcbiAgICogICBbZW5dQ3VycmVudCBpbmRleC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjgqLjgq/jg4bjgqPjg5bjgavjgarjgaPjgabjgYTjgotvbnMtdGFi44Gu44Kk44Oz44OH44OD44Kv44K544KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnRhYkl0ZW1cbiAgICogICBbZW5dVGFiIGl0ZW0gb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXXRhYkl0ZW3jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC5jYW5jZWxcbiAgICogICBbZW5dQ2FsbCB0aGlzIGZ1bmN0aW9uIHRvIGNhbmNlbCB0aGUgY2hhbmdlIGV2ZW50LlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWRvOOBs+WHuuOBmeOBqOOAgeOCouOCr+ODhuOCo+ODluOBquOCv+ODluOBruWkieabtOOBjOOCreODo+ODs+OCu+ODq+OBleOCjOOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdGNoYW5nZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZXMganVzdCBhZnRlciB0aGUgdGFiIGlzIGNoYW5nZWQuWy9lbl1cbiAgICogICBbamFd44Ki44Kv44OG44Kj44OW44Gq44K/44OW44GM5aSJ44KP44Gj44Gf5b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50XG4gICAqICAgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge051bWJlcn0gZXZlbnQuaW5kZXhcbiAgICogICBbZW5dQ3VycmVudCBpbmRleC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjgqLjgq/jg4bjgqPjg5bjgavjgarjgaPjgabjgYTjgotvbnMtdGFi44Gu44Kk44Oz44OH44OD44Kv44K544KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnRhYkl0ZW1cbiAgICogICBbZW5dVGFiIGl0ZW0gb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXXRhYkl0ZW3jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHJlYWN0aXZlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlcyBpZiB0aGUgYWxyZWFkeSBvcGVuIHRhYiBpcyB0YXBwZWQgYWdhaW4uWy9lbl1cbiAgICogICBbamFd44GZ44Gn44Gr44Ki44Kv44OG44Kj44OW44Gr44Gq44Gj44Gm44GE44KL44K/44OW44GM44KC44GG5LiA5bqm44K/44OD44OX44KE44Kv44Oq44OD44Kv44GV44KM44Gf5aC05ZCI44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50XG4gICAqICAgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge051bWJlcn0gZXZlbnQuaW5kZXhcbiAgICogICBbZW5dQ3VycmVudCBpbmRleC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjgqLjgq/jg4bjgqPjg5bjgavjgarjgaPjgabjgYTjgotvbnMtdGFi44Gu44Kk44Oz44OH44OD44Kv44K544KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnRhYkl0ZW1cbiAgICogICBbZW5dVGFiIGl0ZW0gb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXXRhYkl0ZW3jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhbmltYXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgbm9uZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRvIGBcIm5vbmVcImAgdGhlIHRyYW5zaXRpb25zIHdpbGwgbm90IGJlIGFuaW1hdGVkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGFuaW1hdGlvbi1vcHRpb25zXG4gICAqIEB0eXBlIHtFeHByZXNzaW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgdGltaW5nIGFuZCBkZWxheSB3aXRoIGFuIG9iamVjdCBsaXRlcmFsLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgdGltaW5nLCBkZWxheeOCkuOCquODluOCuOOCp+OCr+ODiOODquODhuODqeODq+OBp+aMh+WumuOBl+OBvuOBmeOAgmUuZy4ge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAxLCB0aW1pbmc6ICdlYXNlLWluJ31bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBwb3NpdGlvblxuICAgKiBAaW5pdG9ubHlcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgYm90dG9tXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UYWJiYXIncyBwb3NpdGlvbi4gQXZhaWxhYmxlIHZhbHVlcyBhcmUgYFwiYm90dG9tXCJgIGFuZCBgXCJ0b3BcImAuIFVzZSBgXCJhdXRvXCJgIHRvIGNob29zZSBwb3NpdGlvbiBkZXBlbmRpbmcgb24gcGxhdGZvcm0gKGJvdHRvbSBmb3IgaU9TIGZsYXQgZGVzaWduLCB0b3AgZm9yIE1hdGVyaWFsIERlc2lnbikuWy9lbl1cbiAgICogICBbamFd44K/44OW44OQ44O844Gu5L2N572u44KS5oyH5a6a44GX44G+44GZ44CCXCJib3R0b21cIuOCguOBl+OBj+OBr1widG9wXCLjgpLpgbjmip7jgafjgY3jgb7jgZnjgILjg4fjg5Xjgqnjg6vjg4jjga9cImJvdHRvbVwi44Gn44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc3dpcGVhYmxlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIHRhYiBiYXIgY2FuIGJlIHNjcm9sbGVkIGJ5IGRyYWcgb3Igc3dpcGUuWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM44GC44KL5pmC44CB44K/44OW44OQ44O844KS44K544Ov44Kk44OX44KE44OJ44Op44OD44Kw44Gn56e75YuV44Gn44GN44KL44KI44GG44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgaWdub3JlLWVkZ2Utd2lkdGhcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgMjBcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXURpc3RhbmNlIGluIHBpeGVscyBmcm9tIGJvdGggZWRnZXMuIFN3aXBpbmcgb24gdGhlc2UgYXJlYXMgd2lsbCBwcmlvcml0aXplIHBhcmVudCBjb21wb25lbnRzIHN1Y2ggYXMgYG9ucy1zcGxpdHRlcmAgb3IgYG9ucy1uYXZpZ2F0b3JgLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGhpZGUtdGFic1xuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0byBoaWRlIHRoZSB0YWJzLlsvZW5dXG4gICAqICAgW2phXeOCv+ODluOCkumdnuihqOekuuOBq+OBmeOCi+WgtOWQiOOBq+aMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHRhYi1ib3JkZXJcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHNldCB0aGUgdGFicyBzaG93IGEgZHluYW1pYyBib3R0b20gYm9yZGVyLiBPbmx5IHdvcmtzIGZvciBpT1MgZmxhdCBkZXNpZ24gc2luY2UgdGhlIGJvcmRlciBpcyBhbHdheXMgdmlzaWJsZSBpbiBNYXRlcmlhbCBEZXNpZ24uWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSB0YWJiYXIuWy9lbl1cbiAgICogICBbamFd44K/44OW44OQ44O844Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLl9sb2FkSW5hY3RpdmUgPSB1dGlsLmRlZmVyKCk7IC8vIEltcHJvdmVzICMyMzI0XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX2NvbXBpbGUoKSk7XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBpZiAoIXRoaXMuX3N3aXBlcikge1xuICAgICAgdGhpcy5fc3dpcGVyID0gbmV3IFN3aXBlcih7XG4gICAgICAgIGdldEVsZW1lbnQ6ICgpID0+IHRoaXMuX2NvbnRlbnRFbGVtZW50LFxuICAgICAgICBnZXRJbml0aWFsSW5kZXg6ICgpID0+IHRoaXMuZ2V0QXR0cmlidXRlKCdhY3RpdmVJbmRleCcpIHx8IHRoaXMuZ2V0QXR0cmlidXRlKCdhY3RpdmUtaW5kZXgnKSxcbiAgICAgICAgZ2V0QXV0b1Njcm9sbFJhdGlvOiB0aGlzLl9nZXRBdXRvU2Nyb2xsUmF0aW8uYmluZCh0aGlzKSxcbiAgICAgICAgZ2V0QnViYmxlV2lkdGg6ICgpID0+IHBhcnNlSW50KHRoaXMuZ2V0QXR0cmlidXRlKCdpZ25vcmUtZWRnZS13aWR0aCcpIHx8IDI1LCAxMCksXG4gICAgICAgIGlzQXV0b1Njcm9sbGFibGU6ICgpID0+IHRydWUsXG4gICAgICAgIHByZUNoYW5nZUhvb2s6IHRoaXMuX29uUHJlQ2hhbmdlLmJpbmQodGhpcyksXG4gICAgICAgIHBvc3RDaGFuZ2VIb29rOiB0aGlzLl9vblBvc3RDaGFuZ2UuYmluZCh0aGlzKSxcbiAgICAgICAgcmVmcmVzaEhvb2s6IHRoaXMuX29uUmVmcmVzaC5iaW5kKHRoaXMpLFxuICAgICAgICBzY3JvbGxIb29rOiB0aGlzLl9vblNjcm9sbC5iaW5kKHRoaXMpXG4gICAgICB9KTtcblxuICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgICAgdGhpcy5fdGFiYmFyQm9yZGVyID0gdXRpbC5maW5kQ2hpbGQodGhpcy5fdGFiYmFyRWxlbWVudCwgJy50YWJiYXJfX2JvcmRlcicpO1xuICAgICAgICB0aGlzLl9zd2lwZXIuaW5pdCh7IHN3aXBlYWJsZTogdGhpcy5oYXNBdHRyaWJ1dGUoJ3N3aXBlYWJsZScpIH0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX3VwZGF0ZVBvc2l0aW9uKCk7XG5cbiAgICAgIGlmICghdXRpbC5maW5kUGFyZW50KHRoaXMsICdvbnMtcGFnZScsIHAgPT4gcCA9PT0gZG9jdW1lbnQuYm9keSkpIHtcbiAgICAgICAgdGhpcy5fc2hvdygpOyAvLyBUaGlzIHRhYmJhciBpcyB0aGUgdG9wIGNvbXBvbmVudFxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgaWYgKHRoaXMuX3N3aXBlciAmJiB0aGlzLl9zd2lwZXIuaW5pdGlhbGl6ZWQpIHtcbiAgICAgIHRoaXMuX3N3aXBlci5kaXNwb3NlKCk7XG4gICAgICB0aGlzLl9zd2lwZXIgPSBudWxsO1xuICAgICAgdGhpcy5fdGFiYmFyQm9yZGVyID0gbnVsbDtcbiAgICAgIHRoaXMuX3RhYnNSZWN0ID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBfbm9ybWFsaXplRXZlbnQoZXZlbnQpIHtcbiAgICByZXR1cm4geyAuLi5ldmVudCwgaW5kZXg6IGV2ZW50LmFjdGl2ZUluZGV4LCB0YWJJdGVtOiB0aGlzLnRhYnNbZXZlbnQuYWN0aXZlSW5kZXhdIH07XG4gIH1cblxuICBfb25Qb3N0Q2hhbmdlKGV2ZW50KSB7XG4gICAgZXZlbnQgPSB0aGlzLl9ub3JtYWxpemVFdmVudChldmVudCk7XG4gICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdwb3N0Y2hhbmdlJywgZXZlbnQpO1xuICAgIGNvbnN0IHBhZ2UgPSBldmVudC50YWJJdGVtLnBhZ2VFbGVtZW50O1xuICAgIHBhZ2UgJiYgcGFnZS5fc2hvdygpO1xuICB9XG5cbiAgX29uUHJlQ2hhbmdlKGV2ZW50KSB7XG4gICAgZXZlbnQgPSB0aGlzLl9ub3JtYWxpemVFdmVudChldmVudCk7XG4gICAgZXZlbnQuY2FuY2VsID0gKCkgPT4gZXZlbnQuY2FuY2VsZWQgPSB0cnVlO1xuXG4gICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdwcmVjaGFuZ2UnLCBldmVudCk7XG5cbiAgICBpZiAoIWV2ZW50LmNhbmNlbGVkKSB7XG4gICAgICBjb25zdCB7IGFjdGl2ZUluZGV4LCBsYXN0QWN0aXZlSW5kZXggfSA9IGV2ZW50O1xuICAgICAgY29uc3QgdGFicyA9IHRoaXMudGFicztcblxuICAgICAgdGFic1thY3RpdmVJbmRleF0uc2V0QWN0aXZlKHRydWUpO1xuICAgICAgaWYgKGxhc3RBY3RpdmVJbmRleCA+PSAwKSB7XG4gICAgICAgIGNvbnN0IHByZXZUYWIgPSB0YWJzW2xhc3RBY3RpdmVJbmRleF07XG4gICAgICAgIHByZXZUYWIuc2V0QWN0aXZlKGZhbHNlKTtcbiAgICAgICAgcHJldlRhYi5wYWdlRWxlbWVudCAmJiBwcmV2VGFiLnBhZ2VFbGVtZW50Ll9oaWRlKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGV2ZW50LmNhbmNlbGVkXG4gIH1cblxuICBfb25TY3JvbGwoaW5kZXgsIG9wdGlvbnMgPSB7fSkge1xuICAgIGlmICh0aGlzLl90YWJiYXJCb3JkZXIpIHtcbiAgICAgIHRoaXMuX3RhYmJhckJvcmRlci5zdHlsZS50cmFuc2l0aW9uID0gYGFsbCAke29wdGlvbnMuZHVyYXRpb24gfHwgMH1zICR7b3B0aW9ucy50aW1pbmcgfHwgJyd9YDtcblxuICAgICAgaWYgKHRoaXMuX2F1dG9ncm93ICYmIHRoaXMuX3RhYnNSZWN0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc3QgYSA9IE1hdGguZmxvb3IoaW5kZXgpLCBiID0gTWF0aC5jZWlsKGluZGV4KSwgciA9IGluZGV4ICUgMTtcbiAgICAgICAgdGhpcy5fdGFiYmFyQm9yZGVyLnN0eWxlLndpZHRoID0gbGVycCh0aGlzLl90YWJzUmVjdFthXS53aWR0aCwgdGhpcy5fdGFic1JlY3RbYl0ud2lkdGgsIHIpICsgJ3B4JztcbiAgICAgICAgdGhpcy5fdGFiYmFyQm9yZGVyLnN0eWxlLnRyYW5zZm9ybSA9IGB0cmFuc2xhdGUzZCgke2xlcnAodGhpcy5fdGFic1JlY3RbYV0ubGVmdCwgdGhpcy5fdGFic1JlY3RbYl0ubGVmdCwgcil9cHgsIDAsIDApYDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX3RhYmJhckJvcmRlci5zdHlsZS50cmFuc2Zvcm0gPSBgdHJhbnNsYXRlM2QoJHtpbmRleCAqIDEwMH0lLCAwLCAwKWA7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5fb25Td2lwZSAmJiB0aGlzLl9vblN3aXBlKGluZGV4LCBvcHRpb25zKTtcbiAgfVxuXG4gIF9vblJlZnJlc2goKSB7XG4gICAgdGhpcy5fYXV0b2dyb3cgPSB1dGlsLmhhc01vZGlmaWVyKHRoaXMsICdhdXRvZ3JvdycpO1xuICAgIHRoaXMuX3RhYnNSZWN0ID0gdGhpcy50YWJzLm1hcCh0YWIgPT4gdGFiLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpKTtcbiAgICBpZiAodGhpcy5fdGFiYmFyQm9yZGVyKSB7XG4gICAgICB0aGlzLl90YWJiYXJCb3JkZXIuc3R5bGUuZGlzcGxheSA9IHRoaXMuaGFzQXR0cmlidXRlKCd0YWItYm9yZGVyJykgfHwgdXRpbC5oYXNNb2RpZmllcih0aGlzLCAnbWF0ZXJpYWwnKSA/ICdibG9jaycgOiAnbm9uZSc7XG4gICAgICBjb25zdCBpbmRleCA9IHRoaXMuZ2V0QWN0aXZlVGFiSW5kZXgoKTtcbiAgICAgIGlmICh0aGlzLl90YWJzUmVjdC5sZW5ndGggPiAwICYmIGluZGV4ID49IDApIHtcbiAgICAgICAgdGhpcy5fdGFiYmFyQm9yZGVyLnN0eWxlLndpZHRoID0gdGhpcy5fdGFic1JlY3RbaW5kZXhdLndpZHRoICsgJ3B4JztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBfZ2V0QXV0b1Njcm9sbFJhdGlvKG1hdGNoZXMsIHZlbG9jaXR5LCBzaXplKSB7XG4gICAgY29uc3QgcmF0aW8gPSAuNjsgLy8gQmFzZSByYXRpb1xuICAgIGNvbnN0IG1vZGlmaWVyID0gc2l6ZSAvIDMwMCAqIChtYXRjaGVzID8gLTEgOiAxKTsgLy8gQmFzZWQgb24gc2NyZWVuIHNpemVcbiAgICByZXR1cm4gTWF0aC5taW4oMSwgTWF0aC5tYXgoMCwgcmF0aW8gKyB2ZWxvY2l0eSAqIG1vZGlmaWVyKSk7XG4gIH1cblxuICBnZXQgX3RhYmJhckVsZW1lbnQoKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICcudGFiYmFyJyk7XG4gIH1cblxuICBnZXQgX2NvbnRlbnRFbGVtZW50KCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnRhYmJhcl9fY29udGVudCcpO1xuICB9XG5cbiAgZ2V0IF90YXJnZXRFbGVtZW50KCkge1xuICAgIGNvbnN0IGNvbnRlbnQgPSB0aGlzLl9jb250ZW50RWxlbWVudDtcbiAgICByZXR1cm4gY29udGVudCAmJiBjb250ZW50LmNoaWxkcmVuWzBdIHx8IG51bGw7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIGNvbnN0IGNvbnRlbnQgPSB0aGlzLl9jb250ZW50RWxlbWVudCB8fCB1dGlsLmNyZWF0ZSgnLnRhYmJhcl9fY29udGVudCcpO1xuICAgIGNvbnRlbnQuY2xhc3NMaXN0LmFkZCgnb25zLXRhYmJhcl9fY29udGVudCcpO1xuICAgIGNvbnN0IHRhYmJhciA9IHRoaXMuX3RhYmJhckVsZW1lbnQgfHwgdXRpbC5jcmVhdGUoJy50YWJiYXInKTtcbiAgICB0YWJiYXIuY2xhc3NMaXN0LmFkZCgnb25zLXRhYmJhcl9fZm9vdGVyJyk7XG5cbiAgICBpZiAoIXRhYmJhci5wYXJlbnROb2RlKSB7XG4gICAgICB3aGlsZSAodGhpcy5maXJzdENoaWxkKSB7XG4gICAgICAgIHRhYmJhci5hcHBlbmRDaGlsZCh0aGlzLmZpcnN0Q2hpbGQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGFjdGl2ZUluZGV4ID0gTnVtYmVyKHRoaXMuZ2V0QXR0cmlidXRlKCdhY3RpdmVJbmRleCcpKTsgLy8gMCBieSBkZWZhdWx0XG4gICAgaWYgKHRhYmJhci5jaGlsZHJlbi5sZW5ndGggPiBhY3RpdmVJbmRleCAmJiAhdXRpbC5maW5kQ2hpbGQodGFiYmFyLCAnW2FjdGl2ZV0nKSkge1xuICAgICAgdGFiYmFyLmNoaWxkcmVuW2FjdGl2ZUluZGV4XS5zZXRBdHRyaWJ1dGUoJ2FjdGl2ZScsICcnKTtcbiAgICB9XG5cbiAgICB0aGlzLl90YWJiYXJCb3JkZXIgPSB1dGlsLmZpbmRDaGlsZCh0YWJiYXIsICcudGFiYmFyX19ib3JkZXInKSB8fCB1dGlsLmNyZWF0ZSgnLnRhYmJhcl9fYm9yZGVyJyk7XG4gICAgdGFiYmFyLmFwcGVuZENoaWxkKHRoaXMuX3RhYmJhckJvcmRlcik7XG4gICAgdGFiYmFyLmNsYXNzTGlzdC5hZGQoJ29ucy1zd2lwZXItdGFiYmFyJyk7IC8vIEhpZGVzIG1hdGVyaWFsIGJvcmRlclxuXG4gICAgIWNvbnRlbnQuY2hpbGRyZW5bMF0gJiYgY29udGVudC5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSk7XG4gICAgIWNvbnRlbnQuY2hpbGRyZW5bMV0gJiYgY29udGVudC5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSk7XG4gICAgY29udGVudC5hcHBlbmRDaGlsZCA9IGNvbnRlbnQuYXBwZW5kQ2hpbGQuYmluZChjb250ZW50LmNoaWxkcmVuWzBdKTtcbiAgICBjb250ZW50Lmluc2VydEJlZm9yZSA9IGNvbnRlbnQuaW5zZXJ0QmVmb3JlLmJpbmQoY29udGVudC5jaGlsZHJlblswXSk7XG5cbiAgICB0aGlzLmFwcGVuZENoaWxkKGNvbnRlbnQpO1xuICAgIHRoaXMuYXBwZW5kQ2hpbGQodGFiYmFyKTsgLy8gVHJpZ2dlcnMgb25zLXRhYiBjb25uZWN0ZWRDYWxsYmFja1xuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgX3VwZGF0ZVBvc2l0aW9uKHBvc2l0aW9uID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3Bvc2l0aW9uJykpIHtcbiAgICBjb25zdCB0b3AgPSB0aGlzLl90b3AgPSBwb3NpdGlvbiA9PT0gJ3RvcCcgfHwgKHBvc2l0aW9uID09PSAnYXV0bycgJiYgdXRpbC5oYXNNb2RpZmllcih0aGlzLCAnbWF0ZXJpYWwnKSk7XG4gICAgY29uc3QgYWN0aW9uID0gdG9wID8gdXRpbC5hZGRNb2RpZmllciA6IHV0aWwucmVtb3ZlTW9kaWZpZXI7XG5cbiAgICBhY3Rpb24odGhpcywgJ3RvcCcpO1xuXG4gICAgY29uc3QgcGFnZSA9IHV0aWwuZmluZFBhcmVudCh0aGlzLCAnb25zLXBhZ2UnKTtcbiAgICBpZiAocGFnZSkge1xuICAgICAgY29udGVudFJlYWR5KHBhZ2UsICgpID0+IHtcbiAgICAgICAgbGV0IHAgPSAwO1xuICAgICAgICBpZiAocGFnZS5jaGlsZHJlblswXSAmJiB1dGlsLm1hdGNoKHBhZ2UuY2hpbGRyZW5bMF0sICdvbnMtdG9vbGJhcicpKSB7XG4gICAgICAgICAgYWN0aW9uKHBhZ2UuY2hpbGRyZW5bMF0sICdub3NoYWRvdycpO1xuICAgICAgICAgIHAgPSAxOyAvLyBWaXN1YWwgZml4IGZvciBzb21lIGRldmljZXNcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNvbnRlbnQgPSBwYWdlLl9nZXRDb250ZW50RWxlbWVudCgpO1xuICAgICAgICBjb25zdCBjcyA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHBhZ2UuX2dldENvbnRlbnRFbGVtZW50KCksIG51bGwpXG5cbiAgICAgICAgdGhpcy5zdHlsZS50b3AgPSB0b3AgPyBwYXJzZUludChjcy5nZXRQcm9wZXJ0eVZhbHVlKCdwYWRkaW5nLXRvcCcpLCAxMCkgLSBwICsgJ3B4JyA6ICcnO1xuXG4gICAgICAgIC8vIFJlZnJlc2ggY29udGVudCB0b3AgLSBGaXggZm9yIGlPUyA4XG4gICAgICAgIGNvbnRlbnQuc3R5bGUudG9wID0gY3MudG9wO1xuICAgICAgICBjb250ZW50LnN0eWxlLnRvcCA9ICcnO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaW50ZXJuYWwuYXV0b1N0YXR1c0JhckZpbGwoKCkgPT4ge1xuICAgICAgY29uc3QgZmlsbGVkID0gdXRpbC5maW5kUGFyZW50KHRoaXMsIGUgPT4gZS5oYXNBdHRyaWJ1dGUoJ3N0YXR1cy1iYXItZmlsbCcpKTtcbiAgICAgIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdzdGF0dXMtYmFyLWZpbGwnLCB0b3AgJiYgIWZpbGxlZCk7XG4gICAgfSk7XG4gIH1cblxuICBnZXQgdG9wUGFnZSgpIHtcbiAgICBjb25zdCB0YWJzID0gdGhpcy50YWJzLFxuICAgICAgaW5kZXggPSB0aGlzLmdldEFjdGl2ZVRhYkluZGV4KCk7XG4gICAgcmV0dXJuIHRhYnNbaW5kZXhdXG4gICAgICA/IHRhYnNbaW5kZXhdLnBhZ2VFbGVtZW50IHx8IHRoaXMucGFnZXNbMF0gfHwgbnVsbFxuICAgICAgOiBudWxsO1xuICB9XG5cbiAgZ2V0IHBhZ2VzKCkge1xuICAgIHJldHVybiB1dGlsLmFycmF5RnJvbSh0aGlzLl90YXJnZXRFbGVtZW50LmNoaWxkcmVuKTtcbiAgfVxuXG4gIGdldCB0YWJzKCkge1xuICAgIHJldHVybiBBcnJheS5wcm90b3R5cGUuZmlsdGVyLmNhbGwodGhpcy5fdGFiYmFyRWxlbWVudC5jaGlsZHJlbiwgZSA9PiBlLnRhZ05hbWUgPT09ICdPTlMtVEFCJyk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBzZXRBY3RpdmVUYWJcbiAgICogQHNpZ25hdHVyZSBzZXRBY3RpdmVUYWIoaW5kZXgsIFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGluZGV4XG4gICAqICAgW2VuXVRhYiBpbmRleC5bL2VuXVxuICAgKiAgIFtqYV3jgr/jg5bjga7jgqTjg7Pjg4fjg4Pjgq/jgrnjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXUZ1bmN0aW9uIHRoYXQgcnVucyB3aGVuIHRoZSBuZXcgcGFnZSBoYXMgbG9hZGVkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUlmIHRoaXMgb3B0aW9uIGlzIFwibm9uZVwiLCB0aGUgdHJhbnNpdGlvbiB3b24ndCBzbGlkZS5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9Wy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNob3cgc3BlY2lmaWVkIHRhYiBwYWdlLiBBbmltYXRpb25zIGFuZCB0aGVpciBvcHRpb25zIGNhbiBiZSBzcGVjaWZpZWQgYnkgdGhlIHNlY29uZCBwYXJhbWV0ZXIuWy9lbl1cbiAgICogICBbamFd5oyH5a6a44GX44Gf44Kk44Oz44OH44OD44Kv44K544Gu44K/44OW44KS6KGo56S644GX44G+44GZ44CC44Ki44OL44Oh44O844K344On44Oz44Gq44Gp44Gu44Kq44OX44K344On44Oz44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIG5ldyBwYWdlIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIHNldEFjdGl2ZVRhYihuZXh0SW5kZXgsIG9wdGlvbnMgPSB7fSkge1xuICAgIGNvbnN0IHByZXZJbmRleCA9IHRoaXMuZ2V0QWN0aXZlVGFiSW5kZXgoKTtcbiAgICBjb25zdCBwcmV2VGFiID0gdGhpcy50YWJzW3ByZXZJbmRleF0sXG4gICAgICBuZXh0VGFiID0gdGhpcy50YWJzW25leHRJbmRleF07XG5cbiAgICBpZiAoIW5leHRUYWIpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnU3BlY2lmaWVkIGluZGV4IGRvZXMgbm90IG1hdGNoIGFueSB0YWIuJyk7XG4gICAgfVxuXG4gICAgaWYgKG5leHRJbmRleCA9PT0gcHJldkluZGV4KSB7XG4gICAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ3JlYWN0aXZlJywgeyBpbmRleDogbmV4dEluZGV4LCBhY3RpdmVJbmRleDogbmV4dEluZGV4LCB0YWJJdGVtOiBuZXh0VGFiIH0pO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShuZXh0VGFiLnBhZ2VFbGVtZW50KTtcbiAgICB9XG5cbiAgICAvLyBGSVhNRTogbmV4dFRhYi5sb2FkZWQgaXMgYnJva2VuIGluIFpvbmUuanMgcHJvbWlzZXMgKEFuZ3VsYXIyKVxuICAgIGNvbnN0IG5leHRQYWdlID0gbmV4dFRhYi5wYWdlRWxlbWVudDtcbiAgICByZXR1cm4gKG5leHRQYWdlID8gUHJvbWlzZS5yZXNvbHZlKG5leHRQYWdlKSA6IG5leHRUYWIubG9hZGVkKVxuICAgICAgLnRoZW4obmV4dFBhZ2UgPT4gdGhpcy5fc3dpcGVyLnNldEFjdGl2ZUluZGV4KG5leHRJbmRleCwge1xuICAgICAgICByZWplY3Q6IHRydWUsXG4gICAgICAgIC4uLm9wdGlvbnMsXG4gICAgICAgIGFuaW1hdGlvbjogcHJldlRhYiAmJiBuZXh0UGFnZSA/IG9wdGlvbnMuYW5pbWF0aW9uIHx8IHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24nKSA6ICdub25lJyxcbiAgICAgICAgYW5pbWF0aW9uT3B0aW9uczogdXRpbC5leHRlbmQoXG4gICAgICAgICAgeyBkdXJhdGlvbjogLjMsIHRpbWluZzogJ2N1YmljLWJlemllciguNCwgLjcsIC41LCAxKScgfSxcbiAgICAgICAgICB0aGlzLmhhc0F0dHJpYnV0ZSgnYW5pbWF0aW9uLW9wdGlvbnMnKSA/IHV0aWwuYW5pbWF0aW9uT3B0aW9uc1BhcnNlKHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24tb3B0aW9ucycpKSA6IHt9LFxuICAgICAgICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyB8fCB7fVxuICAgICAgICApXG4gICAgICB9KS50aGVuKCgpID0+IHtcbiAgICAgICAgb3B0aW9ucy5jYWxsYmFjayBpbnN0YW5jZW9mIEZ1bmN0aW9uICYmIG9wdGlvbnMuY2FsbGJhY2sobmV4dFBhZ2UpO1xuICAgICAgICByZXR1cm4gbmV4dFBhZ2U7XG4gICAgICB9KSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBzZXRUYWJiYXJWaXNpYmlsaXR5XG4gICAqIEBzaWduYXR1cmUgc2V0VGFiYmFyVmlzaWJpbGl0eSh2aXNpYmxlKVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IHZpc2libGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVVzZWQgdG8gaGlkZSBvciBzaG93IHRoZSB0YWIgYmFyLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBzZXRUYWJiYXJWaXNpYmlsaXR5KHZpc2libGUpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fY29udGVudEVsZW1lbnQuc3R5bGVbdGhpcy5fdG9wID8gJ3RvcCcgOiAnYm90dG9tJ10gPSB2aXNpYmxlID8gJycgOiAnMHB4JztcbiAgICAgIHRoaXMuX3RhYmJhckVsZW1lbnQuc3R5bGUuZGlzcGxheSA9IHZpc2libGUgPyAnJyA6ICdub25lJztcbiAgICAgIHZpc2libGUgJiYgdGhpcy5fb25SZWZyZXNoKCk7XG4gICAgfSk7XG4gIH1cblxuICBzaG93KCkge1xuICAgIHRoaXMuc2V0VGFiYmFyVmlzaWJpbGl0eSh0cnVlKTtcbiAgfVxuXG4gIGhpZGUoKSB7XG4gICAgdGhpcy5zZXRUYWJiYXJWaXNpYmlsaXR5KGZhbHNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdmlzaWJsZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSB0YWJiYXIgaXMgdmlzaWJsZSBvciBub3QuWy9lbl1cbiAgICogICBbamFd44K/44OW44OQ44O844GM6KaL44GI44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG4gIGdldCB2aXNpYmxlKCkge1xuICAgIHJldHVybiB0aGlzLl90YWJiYXJFbGVtZW50LnN0eWxlLmRpc3BsYXkgIT09ICdub25lJztcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgc3dpcGVhYmxlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRW5hYmxlIHN3aXBlIGludGVyYWN0aW9uLlsvZW5dXG4gICAqICAgW2phXXN3aXBlYWJsZeOBp+OBguOCjOOBsHRydWXjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZ2V0IHN3aXBlYWJsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ3N3aXBlYWJsZScpO1xuICB9XG5cbiAgc2V0IHN3aXBlYWJsZSh2YWx1ZSkge1xuICAgIHJldHVybiB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnc3dpcGVhYmxlJywgdmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvblN3aXBlXG4gICAqIEB0eXBlIHtGdW5jdGlvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUhvb2sgY2FsbGVkIHdoZW5ldmVyIHRoZSB1c2VyIHNsaWRlcyB0aGUgdGFiYmFyLiBJdCBnZXRzIGEgZGVjaW1hbCBpbmRleCBhbmQgYW4gYW5pbWF0aW9uT3B0aW9ucyBvYmplY3QgYXMgYXJndW1lbnRzLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgb25Td2lwZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fb25Td2lwZTtcbiAgfVxuXG4gIHNldCBvblN3aXBlKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICYmICEodmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHV0aWwudGhyb3coYFwib25Td2lwZVwiIG11c3QgYmUgYSBmdW5jdGlvbmApXG4gICAgfVxuICAgIHRoaXMuX29uU3dpcGUgPSB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGdldEFjdGl2ZVRhYkluZGV4XG4gICAqIEBzaWduYXR1cmUgZ2V0QWN0aXZlVGFiSW5kZXgoKVxuICAgKiBAcmV0dXJuIHtOdW1iZXJ9XG4gICAqICAgW2VuXVRoZSBpbmRleCBvZiB0aGUgY3VycmVudGx5IGFjdGl2ZSB0YWIuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Ki44Kv44OG44Kj44OW44Gr44Gq44Gj44Gm44GE44KL44K/44OW44Gu44Kk44Oz44OH44OD44Kv44K544KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgdGFiIGluZGV4IG9uIGN1cnJlbnQgYWN0aXZlIHRhYi4gSWYgYWN0aXZlIHRhYiBpcyBub3QgZm91bmQsIHJldHVybnMgLTEuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Ki44Kv44OG44Kj44OW44Gr44Gq44Gj44Gm44GE44KL44K/44OW44Gu44Kk44Oz44OH44OD44Kv44K544KS6L+U44GX44G+44GZ44CC54++5Zyo44Ki44Kv44OG44Kj44OW44Gq44K/44OW44GM44Gq44GE5aC05ZCI44Gr44GvLTHjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZ2V0QWN0aXZlVGFiSW5kZXgodGFicyA9IHRoaXMudGFicykge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGFicy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHRhYnNbaV0gJiYgdGFic1tpXS50YWdOYW1lID09PSAnT05TLVRBQicgJiYgdGFic1tpXS5pc0FjdGl2ZSgpKSB7XG4gICAgICAgIHJldHVybiBpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gLTE7XG4gIH1cblxuICBfc2hvdygpIHtcbiAgICB0aGlzLl9zd2lwZXIuc2hvdygpO1xuXG4gICAgc2V0SW1tZWRpYXRlKCgpID0+IHtcbiAgICAgIGNvbnN0IHRhYnMgPSB0aGlzLnRhYnM7XG4gICAgICBjb25zdCBhY3RpdmVJbmRleCA9IHRoaXMuZ2V0QWN0aXZlVGFiSW5kZXgodGFicyk7XG4gICAgICB0aGlzLl9sb2FkSW5hY3RpdmUucmVzb2x2ZSgpO1xuICAgICAgaWYgKHRhYnMubGVuZ3RoID4gMCAmJiBhY3RpdmVJbmRleCA+PSAwKSB7XG4gICAgICAgIHRhYnNbYWN0aXZlSW5kZXhdLmxvYWRlZC50aGVuKGVsID0+IGVsICYmIHNldEltbWVkaWF0ZSgoKSA9PiBlbC5fc2hvdygpKSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBfaGlkZSgpIHtcbiAgICB0aGlzLl9zd2lwZXIuaGlkZSgpO1xuICAgIGNvbnN0IHRvcFBhZ2UgPSB0aGlzLnRvcFBhZ2U7XG4gICAgdG9wUGFnZSAmJiB0b3BQYWdlLl9oaWRlKCk7XG4gIH1cblxuICBfZGVzdHJveSgpIHtcbiAgICB0aGlzLnRhYnMuZm9yRWFjaCh0YWIgPT4gdGFiLnJlbW92ZSgpKTtcbiAgICB0aGlzLnJlbW92ZSgpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAncG9zaXRpb24nLCAnc3dpcGVhYmxlJywgJ3RhYi1ib3JkZXInLCAnaGlkZS10YWJzJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIGlmIChuYW1lID09PSAnbW9kaWZpZXInKSB7XG4gICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgIGNvbnN0IGlzVG9wID0gbSA9PiAvKF58XFxzKyl0b3AoJHxcXHMrKS9pLnRlc3QobSk7XG4gICAgICBpc1RvcChsYXN0KSAhPT0gaXNUb3AoY3VycmVudCkgJiYgdGhpcy5fdXBkYXRlUG9zaXRpb24oKTtcbiAgICB9IGVsc2UgaWYgKG5hbWUgPT09ICdwb3NpdGlvbicpIHtcbiAgICAgIHV0aWwuaXNBdHRhY2hlZCh0aGlzKSAmJiB0aGlzLl91cGRhdGVQb3NpdGlvbigpO1xuICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gJ3N3aXBlYWJsZScpIHtcbiAgICAgIHRoaXMuX3N3aXBlciAmJiB0aGlzLl9zd2lwZXIudXBkYXRlU3dpcGVhYmxlKHRoaXMuaGFzQXR0cmlidXRlKCdzd2lwZWFibGUnKSk7XG4gICAgfSBlbHNlIGlmIChuYW1lID09PSAnaGlkZS10YWJzJykge1xuICAgICAgdGhpcy5zZXRUYWJiYXJWaXNpYmlsaXR5KCF0aGlzLmhhc0F0dHJpYnV0ZSgnaGlkZS10YWJzJykgfHwgY3VycmVudCA9PT0gJ2ZhbHNlJyk7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGdldCByZXdyaXRhYmxlcygpIHtcbiAgICByZXR1cm4gcmV3cml0YWJsZXM7XG4gIH1cblxuICBzdGF0aWMgZ2V0IGV2ZW50cygpIHtcbiAgICByZXR1cm4gWydwcmVjaGFuZ2UnLCAncG9zdGNoYW5nZScsICdyZWFjdGl2ZSddO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLlRhYmJhciA9IFRhYmJhckVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy10YWJiYXInLCBUYWJiYXJFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IFRhYmJhckVsZW1lbnQgZnJvbSAnLi9vbnMtdGFiYmFyJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuaW1wb3J0IHsgUGFnZUxvYWRlciwgZGVmYXVsdFBhZ2VMb2FkZXIgfSBmcm9tICcuLi9vbnMvcGFnZS1sb2FkZXInO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ3RhYmJhcl9faXRlbSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJyc6ICd0YWJiYXItLSpfX2l0ZW0nLFxuICAnLnRhYmJhcl9fYnV0dG9uJzogJ3RhYmJhci0tKl9fYnV0dG9uJ1xufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtdGFiXG4gKiBAY2F0ZWdvcnkgdGFiYmFyXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVJlcHJlc2VudHMgYSB0YWIgaW5zaWRlIHRhYiBiYXIuIEVhY2ggYDxvbnMtdGFiPmAgcmVwcmVzZW50cyBhIHBhZ2UuWy9lbl1cbiAqICAgW2phXVxuICogICAgIOOCv+ODluODkOODvOOBq+mFjee9ruOBleOCjOOCi+WQhOOCouOCpOODhuODoOOBruOCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAguOBneOCjOOBnuOCjOOBrm9ucy10YWLjga/jg5rjg7zjgrjjgpLooajjgZfjgb7jgZnjgIJcbiAqICAgICBvbnMtdGFi6KaB57Sg44Gu5Lit44Gr44Gv44CB44K/44OW44Gr6KGo56S644GV44KM44KL44Kz44Oz44OG44Oz44OE44KS55u05o6l6KiY6L+w44GZ44KL44GT44Go44GM5Ye65p2l44G+44GZ44CCXG4gKiAgIFsvamFdXG4gKiBAY29kZXBlbiBwR3VETFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3RhYmJhclxuICogQGd1aWRlIGZ1bmRhbWVudGFscy5odG1sI21hbmFnaW5nLXBhZ2VzXG4gKiAgIFtlbl1NYW5hZ2luZyBtdWx0aXBsZSBwYWdlcy5bL2VuXVxuICogICBbamFd6KSH5pWw44Gu44Oa44O844K444KS566h55CG44GZ44KLWy9qYV1dXG4gKiBAZ3VpZGUgYXBwc2l6ZS5odG1sI3JlbW92aW5nLWljb24tcGFja3MgW2VuXVJlbW92aW5nIGljb24gcGFja3MuWy9lbl1bamFdWy9qYV1cbiAqIEBndWlkZSBmYXEuaHRtbCNob3ctY2FuLWktdXNlLWN1c3RvbS1pY29uLXBhY2tzIFtlbl1BZGRpbmcgY3VzdG9tIGljb24gcGFja3MuWy9lbl1bamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy10YWJiYXJcbiAqICAgW2VuXW9ucy10YWJiYXIgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy10YWJiYXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLXBhZ2VcbiAqICAgW2VuXW9ucy1wYWdlIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtcGFnZeOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtaWNvblxuICogICBbZW5db25zLWljb24gY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1pY29u44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXRhYmJhcj5cbiAqICAgPG9ucy10YWJcbiAqICAgICBwYWdlPVwiaG9tZS5odG1sXCJcbiAqICAgICBsYWJlbD1cIkhvbWVcIlxuICogICAgIGFjdGl2ZT5cbiAqICAgPC9vbnMtdGFiPlxuICogICA8b25zLXRhYlxuICogICAgIHBhZ2U9XCJzZXR0aW5ncy5odG1sXCJcbiAqICAgICBsYWJlbD1cIlNldHRpbmdzXCJcbiAqICAgICBhY3RpdmU+XG4gKiAgIDwvb25zLXRhYj5cbiAqIDwvb25zLXRhYmJhcj5cbiAqXG4gKiA8dGVtcGxhdGUgaWQ9XCJob21lLmh0bWxcIj5cbiAqICAgLi4uXG4gKiA8L3RlbXBsYXRlPlxuICpcbiAqIDx0ZW1wbGF0ZSBpZD1cInNldHRpbmdzLmh0bWxcIj5cbiAqICAgLi4uXG4gKiA8L3RlbXBsYXRlPlxuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRhYkVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgcGFnZVxuICAgKiBAaW5pdG9ubHlcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBwYWdlIHRoYXQgaXMgZGlzcGxheWVkIHdoZW4gdGhlIHRhYiBpcyB0YXBwZWQuWy9lbl1cbiAgICogICBbamFdb25zLXRhYuOBjOWPgueFp+OBmeOCi+ODmuODvOOCuOOBuOOBrlVSTOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGljb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgVGhlIGljb24gbmFtZSBmb3IgdGhlIHRhYi4gQ2FuIHNwZWNpZnkgdGhlIHNhbWUgaWNvbiBuYW1lIGFzIGA8b25zLWljb24+YC4gQ2hlY2sgW1NlZSBhbHNvXSgjc2VlYWxzbykgc2VjdGlvbiBmb3IgbW9yZSBpbmZvcm1hdGlvbi5cbiAgICogICBbL2VuXVxuICAgKiAgIFtqYV1cbiAgICogICAgIOOCouOCpOOCs+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAgm9ucy1pY29u44Go5ZCM44GY44Ki44Kk44Kz44Oz5ZCN44KS5oyH5a6a44Gn44GN44G+44GZ44CCXG4gICAqICAgICDlgIvliKXjgavjgqLjgqTjgrPjg7PjgpLjgqvjgrnjgr/jg57jgqTjgrrjgZnjgovloLTlkIjjga/jgIFiYWNrZ3JvdW5kLWltYWdl44Gq44Gp44GuQ1NT44K544K/44Kk44Or44KS55So44GE44Gm5oyH5a6a44Gn44GN44G+44GZ44CCXG4gICAqICAgWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYWN0aXZlLWljb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBuYW1lIG9mIHRoZSBpY29uIHdoZW4gdGhlIHRhYiBpcyBhY3RpdmUuWy9lbl1cbiAgICogICBbamFd44Ki44Kv44OG44Kj44OW44Gu6Zqb44Gu44Ki44Kk44Kz44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbGFiZWxcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBsYWJlbCBvZiB0aGUgdGFiIGl0ZW0uWy9lbl1cbiAgICogICBbamFd44Ki44Kk44Kz44Oz5LiL44Gr6KGo56S644GV44KM44KL44Op44OZ44Or44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYmFkZ2VcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXURpc3BsYXkgYSBub3RpZmljYXRpb24gYmFkZ2Ugb24gdG9wIG9mIHRoZSB0YWIuWy9lbl1cbiAgICogICBbamFd44OQ44OD44K444Gr6KGo56S644GZ44KL5YaF5a6544KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYWN0aXZlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGlzIGF0dHJpYnV0ZSBzaG91bGQgYmUgc2V0IHRvIHRoZSB0YWIgdGhhdCBpcyBhY3RpdmUgYnkgZGVmYXVsdC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKFsnbGFiZWwnLCAnaWNvbicsICdiYWRnZSddLnNvbWUodGhpcy5oYXNBdHRyaWJ1dGUuYmluZCh0aGlzKSkpIHtcbiAgICAgIHRoaXMuX2NvbXBpbGUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX2NvbXBpbGUoKSk7XG4gICAgfVxuXG4gICAgdGhpcy5fcGFnZUxvYWRlciA9IGRlZmF1bHRQYWdlTG9hZGVyO1xuICAgIHRoaXMuX29uQ2xpY2sgPSB0aGlzLl9vbkNsaWNrLmJpbmQodGhpcyk7XG4gIH1cblxuICBzZXQgcGFnZUxvYWRlcihsb2FkZXIpIHtcbiAgICBpZiAoIShsb2FkZXIgaW5zdGFuY2VvZiBQYWdlTG9hZGVyKSkge1xuICAgICAgdXRpbC50aHJvd1BhZ2VMb2FkZXIoKTtcbiAgICB9XG4gICAgdGhpcy5fcGFnZUxvYWRlciA9IGxvYWRlcjtcbiAgfVxuXG4gIGdldCBwYWdlTG9hZGVyKCkge1xuICAgIHJldHVybiB0aGlzLl9wYWdlTG9hZGVyO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKGRlZmF1bHRDbGFzc05hbWUpO1xuXG4gICAgaWYgKHRoaXMuX2J1dHRvbikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGJ1dHRvbiA9IHV0aWwuY3JlYXRlKCdidXR0b24udGFiYmFyX19idXR0b24nKTtcbiAgICB3aGlsZSAodGhpcy5jaGlsZE5vZGVzWzBdKSB7XG4gICAgICBidXR0b24uYXBwZW5kQ2hpbGQodGhpcy5jaGlsZE5vZGVzWzBdKTtcbiAgICB9XG5cbiAgICBjb25zdCBpbnB1dCA9IHV0aWwuY3JlYXRlKCdpbnB1dCcsIHsgZGlzcGxheTogJ25vbmUnIH0pO1xuICAgIGlucHV0LnR5cGUgPSAncmFkaW8nO1xuXG4gICAgdGhpcy5hcHBlbmRDaGlsZChpbnB1dCk7XG4gICAgdGhpcy5hcHBlbmRDaGlsZChidXR0b24pO1xuXG4gICAgdGhpcy5fdXBkYXRlQnV0dG9uQ29udGVudCgpO1xuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgICB0aGlzLl91cGRhdGVSaXBwbGUoKTtcbiAgfVxuXG4gIF91cGRhdGVSaXBwbGUoKSB7XG4gICAgdGhpcy5fYnV0dG9uICYmIHV0aWwudXBkYXRlUmlwcGxlKHRoaXMuX2J1dHRvbiwgdGhpcy5oYXNBdHRyaWJ1dGUoJ3JpcHBsZScpKTtcbiAgfVxuXG4gIF91cGRhdGVCdXR0b25Db250ZW50KCkge1xuICAgIGNvbnN0IGJ1dHRvbiA9IHRoaXMuX2J1dHRvbjtcblxuICAgIGxldCBpY29uV3JhcHBlciA9IHRoaXMuX2ljb247XG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdpY29uJykpIHtcbiAgICAgIGljb25XcmFwcGVyID0gaWNvbldyYXBwZXIgfHwgdXRpbC5jcmVhdGVFbGVtZW50KCc8ZGl2IGNsYXNzPVwidGFiYmFyX19pY29uXCI+PG9ucy1pY29uPjwvb25zLWljb24+PC9kaXY+Jyk7XG4gICAgICBjb25zdCBpY29uID0gaWNvbldyYXBwZXIuY2hpbGRyZW5bMF07XG4gICAgICBjb25zdCBmaXggPSAobGFzdCA9PiAoKSA9PiBpY29uLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaygnaWNvbicsIGxhc3QsIHRoaXMuZ2V0QXR0cmlidXRlKCdpY29uJykpKShpY29uLmdldEF0dHJpYnV0ZSgnaWNvbicpKTtcbiAgICAgIGljb24uc2V0QXR0cmlidXRlKCdpY29uJywgdGhpcy5nZXRBdHRyaWJ1dGUodGhpcy5pc0FjdGl2ZSgpID8gJ2FjdGl2ZS1pY29uJyA6ICdpY29uJykpO1xuICAgICAgaWNvbldyYXBwZXIucGFyZW50RWxlbWVudCAhPT0gYnV0dG9uICYmIGJ1dHRvbi5pbnNlcnRCZWZvcmUoaWNvbldyYXBwZXIsIGJ1dHRvbi5maXJzdENoaWxkKTtcblxuICAgICAgLy8gZGlydHkgZml4IGZvciBodHRwczovL2dpdGh1Yi5jb20vT25zZW5VSS9PbnNlblVJL2lzc3Vlcy8xNjU0XG4gICAgICBpY29uLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayBpbnN0YW5jZW9mIEZ1bmN0aW9uXG4gICAgICAgID8gZml4KClcbiAgICAgICAgOiBzZXRJbW1lZGlhdGUoKCkgPT4gaWNvbi5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sgaW5zdGFuY2VvZiBGdW5jdGlvbiAmJiBmaXgoKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGljb25XcmFwcGVyICYmIGljb25XcmFwcGVyLnJlbW92ZSgpO1xuICAgIH1cblxuICAgIFsnbGFiZWwnLCAnYmFkZ2UnXS5mb3JFYWNoKChhdHRyLCBpbmRleCkgPT4ge1xuICAgICAgbGV0IHByb3AgPSB0aGlzLnF1ZXJ5U2VsZWN0b3IoYC50YWJiYXJfXyR7YXR0cn1gKTtcbiAgICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZShhdHRyKSkge1xuICAgICAgICBwcm9wID0gcHJvcCB8fCB1dGlsLmNyZWF0ZShgLnRhYmJhcl9fJHthdHRyfWAgKyAoYXR0ciA9PT0gJ2JhZGdlJyA/ICcgbm90aWZpY2F0aW9uJyA6ICcnKSk7XG4gICAgICAgIHByb3AudGV4dENvbnRlbnQgPSB0aGlzLmdldEF0dHJpYnV0ZShhdHRyKTtcbiAgICAgICAgcHJvcC5wYXJlbnRFbGVtZW50ICE9PSBidXR0b24gJiYgYnV0dG9uLmFwcGVuZENoaWxkKHByb3ApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcHJvcCAmJiBwcm9wLnJlbW92ZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgZ2V0IF9pbnB1dCgpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJ2lucHV0Jyk7XG4gIH1cblxuICBnZXQgX2J1dHRvbigpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJy50YWJiYXJfX2J1dHRvbicpO1xuICB9XG5cbiAgZ2V0IF9pY29uKCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3IoJy50YWJiYXJfX2ljb24nKTtcbiAgfVxuXG4gIGdldCBfdGFiYmFyKCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRQYXJlbnQodGhpcywgJ29ucy10YWJiYXInKTtcbiAgfVxuXG4gIGdldCBpbmRleCgpIHtcbiAgICByZXR1cm4gQXJyYXkucHJvdG90eXBlLmluZGV4T2YuY2FsbCh0aGlzLnBhcmVudEVsZW1lbnQuY2hpbGRyZW4sIHRoaXMpO1xuICB9XG5cbiAgX29uQ2xpY2soKSB7XG4gICAgaWYgKHRoaXMub25DbGljayBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICB0aGlzLm9uQ2xpY2soKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fdGFiYmFyLnNldEFjdGl2ZVRhYih0aGlzLmluZGV4LCB7IHJlamVjdDogZmFsc2UgfSk7XG4gICAgfVxuICB9XG5cbiAgc2V0QWN0aXZlKGFjdGl2ZSA9IHRydWUpIHtcbiAgICB0aGlzLl9pbnB1dC5jaGVja2VkID0gYWN0aXZlO1xuICAgIHRoaXMuY2xhc3NMaXN0LnRvZ2dsZSgnYWN0aXZlJywgYWN0aXZlKTtcbiAgICB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnYWN0aXZlJywgYWN0aXZlKVxuXG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdpY29uJykgJiYgdGhpcy5oYXNBdHRyaWJ1dGUoJ2FjdGl2ZS1pY29uJykpIHtcbiAgICAgIHRoaXMuX2ljb24uY2hpbGRyZW5bMF0uc2V0QXR0cmlidXRlKCdpY29uJywgdGhpcy5nZXRBdHRyaWJ1dGUoYWN0aXZlID8gJ2FjdGl2ZS1pY29uJyA6ICdpY29uJykpO1xuICAgIH1cbiAgfVxuXG4gIF9sb2FkUGFnZUVsZW1lbnQocGFyZW50LCBwYWdlKSB7XG4gICAgdGhpcy5faGFzTG9hZGVkID0gdHJ1ZTtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIHRoaXMuX3BhZ2VMb2FkZXIubG9hZCh7IHBhcmVudCwgcGFnZSB9LCBwYWdlRWxlbWVudCA9PiB7XG4gICAgICAgIHBhcmVudC5yZXBsYWNlQ2hpbGQocGFnZUVsZW1lbnQsIHBhcmVudC5jaGlsZHJlblt0aGlzLmluZGV4XSk7IC8vIEVuc3VyZSBwb3NpdGlvblxuICAgICAgICB0aGlzLl9sb2FkZWRQYWdlID0gcGFnZUVsZW1lbnQ7XG4gICAgICAgIHJlc29sdmUocGFnZUVsZW1lbnQpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBnZXQgcGFnZUVsZW1lbnQoKSB7XG4gICAgLy8gSXQgaGFzIGJlZW4gbG9hZGVkIGJ5IG9ucy10YWJcbiAgICBpZiAodGhpcy5fbG9hZGVkUGFnZSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2xvYWRlZFBhZ2U7XG4gICAgfVxuICAgIC8vIE1hbnVhbGx5IGF0dGFjaGVkIHRvIERPTSwgMSBwZXIgdGFiXG4gICAgY29uc3QgdGFiYmFyID0gdGhpcy5fdGFiYmFyO1xuICAgIGlmICh0YWJiYXIucGFnZXMubGVuZ3RoID09PSB0YWJiYXIudGFicy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiB0YWJiYXIucGFnZXNbdGhpcy5pbmRleF07XG4gICAgfVxuICAgIC8vIExvYWRlZCBpbiBhbm90aGVyIHdheVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0FjdGl2ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5jbGFzc0xpc3QuY29udGFpbnMoJ2FjdGl2ZScpO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX29uQ2xpY2ssIGZhbHNlKTtcbiAgICBpZiAodGhpcy5fbG9hZGVkUGFnZSkge1xuICAgICAgdGhpcy5faGFzTG9hZGVkID0gZmFsc2U7XG4gICAgICB0aGlzLmxvYWRlZCA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX29uQ2xpY2ssIGZhbHNlKTtcblxuICAgIGlmICghdXRpbC5pc0F0dGFjaGVkKHRoaXMpIHx8IHRoaXMubG9hZGVkKSB7XG4gICAgICByZXR1cm47IC8vIG9ucy10YWJiYXIgY29tcGlsYXRpb24gbWF5IHRyaWdnZXIgdGhpc1xuICAgIH1cblxuICAgIGNvbnN0IGRlZmVycmVkID0gdXRpbC5kZWZlcigpO1xuICAgIHRoaXMubG9hZGVkID0gZGVmZXJyZWQucHJvbWlzZTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICBjb25zdCBpbmRleCA9IHRoaXMuaW5kZXg7XG4gICAgICBjb25zdCB0YWJiYXIgPSB0aGlzLl90YWJiYXI7XG4gICAgICBpZiAoIXRhYmJhcikge1xuICAgICAgICB1dGlsLnRocm93KCdUYWIgZWxlbWVudHMgbXVzdCBiZSBjaGlsZHJlbiBvZiBUYWJiYXInKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRhYmJhci5oYXNBdHRyaWJ1dGUoJ21vZGlmaWVyJykpIHtcbiAgICAgICAgdXRpbC5hZGRNb2RpZmllcih0aGlzLCB0YWJiYXIuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCF0aGlzLl9oYXNMb2FkZWQpIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdhY3RpdmUnKSkge1xuICAgICAgICAgIHRoaXMuc2V0QWN0aXZlKHRydWUpO1xuICAgICAgICAgIHRhYmJhci5zZXRBdHRyaWJ1dGUoJ2FjdGl2ZUluZGV4JywgaW5kZXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGluZGV4ID09PSB0YWJiYXIudGFicy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgdGFiYmFyLl9vblJlZnJlc2goKTtcbiAgICAgICAgICBzZXRJbW1lZGlhdGUoKCkgPT4gdGFiYmFyLl9vblJlZnJlc2goKSk7XG4gICAgICAgIH1cblxuICAgICAgICBUYWJiYXJFbGVtZW50LnJld3JpdGFibGVzLnJlYWR5KHRhYmJhciwgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHBhZ2VUYXJnZXQgPSB0aGlzLnBhZ2UgfHwgdGhpcy5nZXRBdHRyaWJ1dGUoJ3BhZ2UnKTtcbiAgICAgICAgICBpZiAoIXRoaXMucGFnZUVsZW1lbnQgJiYgcGFnZVRhcmdldCkge1xuICAgICAgICAgICAgY29uc3QgcGFyZW50VGFyZ2V0ID0gdGFiYmFyLl90YXJnZXRFbGVtZW50O1xuICAgICAgICAgICAgY29uc3QgZHVtbXlQYWdlID0gdXRpbC5jcmVhdGUoJ2RpdicsIHsgaGVpZ2h0OiAnMTAwJScsIHdpZHRoOiAnMTAwJScsIHZpc2liaWxpdHk6ICdoaWRkZW4nIH0pO1xuICAgICAgICAgICAgcGFyZW50VGFyZ2V0Lmluc2VydEJlZm9yZShkdW1teVBhZ2UsIHBhcmVudFRhcmdldC5jaGlsZHJlbltpbmRleF0pOyAvLyBFbnN1cmUgcG9zaXRpb25cblxuICAgICAgICAgICAgY29uc3QgbG9hZCA9ICgpID0+IHRoaXMuX2xvYWRQYWdlRWxlbWVudChwYXJlbnRUYXJnZXQsIHBhZ2VUYXJnZXQpLnRoZW4oZGVmZXJyZWQucmVzb2x2ZSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpID8gbG9hZCgpIDogdGFiYmFyLl9sb2FkSW5hY3RpdmUucHJvbWlzZS50aGVuKGxvYWQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBkZWZlcnJlZC5yZXNvbHZlKHRoaXMucGFnZUVsZW1lbnQpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJywgJ3JpcHBsZScsICdpY29uJywgJ2xhYmVsJywgJ3BhZ2UnLCAnYmFkZ2UnLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3JpcHBsZSc6XG4gICAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl91cGRhdGVSaXBwbGUoKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaWNvbic6XG4gICAgICBjYXNlICdsYWJlbCc6XG4gICAgICBjYXNlICdiYWRnZSc6XG4gICAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl91cGRhdGVCdXR0b25Db250ZW50KCkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3BhZ2UnOlxuICAgICAgICB0aGlzLnBhZ2UgPSBjdXJyZW50IHx8ICcnO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cbn1cblxub25zRWxlbWVudHMuVGFiID0gVGFiRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXRhYicsIFRhYkVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IEJhc2VBbmltYXRvciBmcm9tICcuLi8uLi9vbnMvYmFzZS1hbmltYXRvcic7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRvYXN0QW5pbWF0b3IgZXh0ZW5kcyBCYXNlQW5pbWF0b3Ige1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICAgKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy50aW1pbmdcbiAgICogQHBhcmFtIHtOdW1iZXJ9IG9wdGlvbnMuZHVyYXRpb25cbiAgICogQHBhcmFtIHtOdW1iZXJ9IG9wdGlvbnMuZGVsYXlcbiAgICovXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnbGluZWFyJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuMn0gPSB7fSkge1xuICAgIHN1cGVyKHsgdGltaW5nLCBkZWxheSwgZHVyYXRpb24gfSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gbW9kYWxcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHNob3cobW9kYWwsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBtb2RhbFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgaGlkZShtb2RhbCwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjaygpO1xuICB9XG59XG4iLCJcbi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBhbmltaXQgZnJvbSAnLi4vLi4vb25zL2FuaW1pdCc7XG5pbXBvcnQgVG9hc3RBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcblxuLyoqXG4gKiBpT1Mgc3R5bGUgYW5pbWF0b3IgZm9yIGRpYWxvZy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRmFkZVRvYXN0QW5pbWF0b3IgZXh0ZW5kcyBUb2FzdEFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7dGltaW5nID0gJ2xpbmVhcicsIGRlbGF5ID0gMCwgZHVyYXRpb24gPSAwLjN9ID0ge30pIHtcbiAgICBzdXBlcih7IHRpbWluZywgZGVsYXksIGR1cmF0aW9uIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHRvYXN0XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBzaG93KHRvYXN0LCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQodG9hc3QsIHRoaXMuZGVmKVxuICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAwIH0sIHsgb3BhY2l0eTogMSB9KVxuICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICBkb25lKCk7XG4gICAgICB9KVxuICAgICAgLnBsYXkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSB0b2FzdFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgaGlkZSh0b2FzdCwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrID8gY2FsbGJhY2sgOiBmdW5jdGlvbigpIHt9O1xuXG4gICAgYW5pbWl0KHRvYXN0LCB0aGlzLmRlZilcbiAgICAgIC5kZWZhdWx0KHsgb3BhY2l0eTogMSB9LCB7IG9wYWNpdHk6IDAgfSlcbiAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgZG9uZSgpO1xuICAgICAgfSlcbiAgICAgIC5wbGF5KCk7XG4gIH1cbn1cbiIsIlxuLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi8uLi9vbnMvYW5pbWl0JztcbmltcG9ydCBwbGF0Zm9ybSBmcm9tICcuLi8uLi9vbnMvcGxhdGZvcm0nO1xuaW1wb3J0IGlQaG9uZVhQYXRjaCBmcm9tICcuLi8uLi9vbnMvaXBob25leC1wYXRjaCc7XG5pbXBvcnQgVG9hc3RBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcblxuLyoqXG4gKiBBc2NlbmQgVG9hc3QgQW5pbWF0b3IuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEFzY2VuZFRvYXN0QW5pbWF0b3IgZXh0ZW5kcyBUb2FzdEFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7IHRpbWluZyA9ICdlYXNlJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuMjUgfSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcblxuICAgIHRoaXMubWVzc2FnZURlbGF5ID0gdGhpcy5kdXJhdGlvbiAqIDAuNCArIHRoaXMuZGVsYXk7IC8vIERlbGF5IG1lc3NhZ2Ugb3BhY2l0eSBjaGFuZ2VcbiAgICBpZiAocGxhdGZvcm0uaXNBbmRyb2lkKCkpIHtcbiAgICAgIHRoaXMuYXNjZW5zaW9uID0gNDg7IC8vIFRvYXN0cyBhcmUgYWx3YXlzIDEgbGluZVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoaVBob25lWFBhdGNoLmlzSVBob25lWFBvcnRyYWl0UGF0Y2hBY3RpdmUoKSkge1xuICAgICAgICB0aGlzLmFzY2Vuc2lvbiA9IDk4OyAvLyA2NCArIDM0XG4gICAgICB9IGVsc2UgaWYgKGlQaG9uZVhQYXRjaC5pc0lQaG9uZVhMYW5kc2NhcGVQYXRjaEFjdGl2ZSgpKSB7XG4gICAgICAgIHRoaXMuYXNjZW5zaW9uID0gODU7IC8vIDY0ICsgMjFcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuYXNjZW5zaW9uID0gNjQ7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHRvYXN0XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBzaG93KHRvYXN0LCBjYWxsYmFjaykge1xuICAgIHRvYXN0ID0gdG9hc3QuX3RvYXN0O1xuICAgIHV0aWwuZ2xvYmFscy5mYWJPZmZzZXQgPSB0aGlzLmFzY2Vuc2lvbjtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG4gICAgICBhbmltaXQodG9hc3QsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDAsICR7dGhpcy5hc2NlbnNpb259cHgsIDApYCB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknIH1cbiAgICAgICAgKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQodGhpcy5fZ2V0RmFicygpKVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCAtJHt0aGlzLmFzY2Vuc2lvbn1weCwgMCkgc2NhbGUoMSlgIH0sIHRoaXMuZGVmKSxcblxuICAgICAgYW5pbWl0KHV0aWwuYXJyYXlGcm9tKHRvYXN0LmNoaWxkcmVuKSwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KHsgb3BhY2l0eTogMCB9LCB7IG9wYWNpdHk6IDEgfSlcbiAgICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gdG9hc3RcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUodG9hc3QsIGNhbGxiYWNrKSB7XG4gICAgdG9hc3QgPSB0b2FzdC5fdG9hc3Q7XG4gICAgdXRpbC5nbG9iYWxzLmZhYk9mZnNldCA9IDA7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuICAgICAgYW5pbWl0KHRvYXN0LCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKScgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDAsICR7dGhpcy5hc2NlbnNpb259cHgsIDApYCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KHRoaXMuX2dldEZhYnMoKSwgdGhpcy5kZWYpXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7IHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDAsIDAsIDApIHNjYWxlKDEpYCB9LCB0aGlzLmRlZiksXG5cbiAgICAgIGFuaW1pdCh1dGlsLmFycmF5RnJvbSh0b2FzdC5jaGlsZHJlbiksIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdCh7IG9wYWNpdHk6IDEgfSwgeyBvcGFjaXR5OiAwIH0pXG4gICAgKTtcbiAgfVxuXG4gIF9nZXRGYWJzKCkge1xuICAgIHJldHVybiB1dGlsLmFycmF5RnJvbShkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdvbnMtZmFiW3Bvc2l0aW9ufj1ib3R0b21dLCBvbnMtc3BlZWQtZGlhbFtwb3NpdGlvbn49Ym90dG9tXScpKS5maWx0ZXIoZmFiID0+IGZhYi52aXNpYmxlKTtcbiAgfVxufVxuIiwiXG4vKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuaW1wb3J0IGlQaG9uZVhQYXRjaCBmcm9tICcuLi8uLi9vbnMvaXBob25leC1wYXRjaCc7XG5pbXBvcnQgVG9hc3RBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcblxuLyoqXG4gKiBMaWZ0LWZhZGUgVG9hc3QgQW5pbWF0b3JcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTGlmdFRvYXN0QW5pbWF0b3IgZXh0ZW5kcyBUb2FzdEFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7IHRpbWluZyA9ICdlYXNlJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuMzUgfSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcbiAgICB0aGlzLmJvZHlIZWlnaHQgPSBkb2N1bWVudC5ib2R5LmNsaWVudEhlaWdodDsgLy8gYXZvaWQgRm9yY2VkIFN5bmNocm9ub3VzIExheW91dFxuICAgIGlmIChpUGhvbmVYUGF0Y2guaXNJUGhvbmVYUG9ydHJhaXRQYXRjaEFjdGl2ZSgpKSB7XG4gICAgICB0aGlzLmxpZnRBbW91bnQgPSAnY2FsYygxMDAlICsgMzRweCknO1xuICAgIH0gZWxzZSBpZiAoaVBob25lWFBhdGNoLmlzSVBob25lWExhbmRzY2FwZVBhdGNoQWN0aXZlKCkpIHtcbiAgICAgIHRoaXMubGlmdEFtb3VudCA9ICdjYWxjKDEwMCUgKyAyMXB4KSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubGlmdEFtb3VudCA9ICcxMDAlJztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gdG9hc3RcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHNob3codG9hc3QsIGNhbGxiYWNrKSB7XG4gICAgdG9hc3QgPSB0b2FzdC5fdG9hc3Q7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuICAgICAgYW5pbWl0KHRvYXN0LCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCAke3RoaXMubGlmdEFtb3VudH0sIDApYCwgb3BhY2l0eTogMCB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknLCBvcGFjaXR5OiAxIH1cbiAgICAgICAgKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHRvYXN0XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBoaWRlKHRvYXN0LCBjYWxsYmFjaykge1xuICAgIHRvYXN0ID0gdG9hc3QuX3RvYXN0O1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcbiAgICAgIGFuaW1pdCh0b2FzdCwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknLCBvcGFjaXR5OiAxIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCAke3RoaXMubGlmdEFtb3VudH0sIDApYCwgb3BhY2l0eTogMCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cblxuICBfdXBkYXRlUG9zaXRpb24odG9hc3QpIHtcbiAgICBpZiAocGFyc2VJbnQodG9hc3Quc3R5bGUudG9wLCAxMCkgPT09IDApIHtcbiAgICAgIHRvYXN0LnN0eWxlLnRvcCA9IHRvYXN0LnN0eWxlLmJvdHRvbSA9ICcnO1xuICAgIH1cbiAgfVxufVxuIiwiXG4vKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuaW1wb3J0IGlQaG9uZVhQYXRjaCBmcm9tICcuLi8uLi9vbnMvaXBob25leC1wYXRjaCc7XG5pbXBvcnQgVG9hc3RBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcblxuLyoqXG4gKiBGYWxsLWZhZGUgVG9hc3QgQW5pbWF0b3JcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRmFsbFRvYXN0QW5pbWF0b3IgZXh0ZW5kcyBUb2FzdEFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7IHRpbWluZyA9ICdlYXNlJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuMzUgfSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcbiAgICBpZiAoaVBob25lWFBhdGNoLmlzSVBob25lWFBvcnRyYWl0UGF0Y2hBY3RpdmUoKSkge1xuICAgICAgdGhpcy5mYWxsQW1vdW50ID0gJ2NhbGMoLTEwMCUgLSA0NHB4KSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZmFsbEFtb3VudCA9ICctMTAwJSc7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHRvYXN0XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBzaG93KHRvYXN0LCBjYWxsYmFjaykge1xuICAgIHRvYXN0ID0gdG9hc3QuX3RvYXN0O1xuICAgIHRoaXMuX3VwZGF0ZVBvc2l0aW9uKHRvYXN0KTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG4gICAgICBhbmltaXQodG9hc3QsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDAsICR7dGhpcy5mYWxsQW1vdW50fSwgMClgLCBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKScsIG9wYWNpdHk6IDEgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICBjYWxsYmFjayAmJiBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gdG9hc3RcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUodG9hc3QsIGNhbGxiYWNrKSB7XG4gICAgdG9hc3QgPSB0b2FzdC5fdG9hc3Q7XG4gICAgdGhpcy5fdXBkYXRlUG9zaXRpb24odG9hc3QpO1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcbiAgICAgIGFuaW1pdCh0b2FzdCwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknLCBvcGFjaXR5OiAxIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCAke3RoaXMuZmFsbEFtb3VudH0sIDApYCwgb3BhY2l0eTogMCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHRoaXMuX3VwZGF0ZVBvc2l0aW9uKHRvYXN0LCB0cnVlKTtcbiAgICAgICAgICBjYWxsYmFjayAmJiBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgX3VwZGF0ZVBvc2l0aW9uKHRvYXN0LCBjbGVhblVwKSB7XG4gICAgbGV0IGNvcnJlY3RUb3A7XG4gICAgaWYgKGlQaG9uZVhQYXRjaC5pc0lQaG9uZVhQb3J0cmFpdFBhdGNoQWN0aXZlKCkpIHtcbiAgICAgIGNvcnJlY3RUb3AgPSAnNDRweCc7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvcnJlY3RUb3AgPSAnMCc7XG4gICAgfVxuXG4gICAgaWYgKHRvYXN0LnN0eWxlLnRvcCAhPT0gY29ycmVjdFRvcCkge1xuICAgICAgdG9hc3Quc3R5bGUudG9wID0gY29ycmVjdFRvcDtcbiAgICAgIHRvYXN0LnN0eWxlLmJvdHRvbSA9ICdpbml0aWFsJztcbiAgICB9XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi8uLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi8uLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEFuaW1hdG9yRmFjdG9yeSBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvYW5pbWF0b3ItZmFjdG9yeSc7XG5pbXBvcnQgVG9hc3RBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcbmltcG9ydCBGYWRlVG9hc3RBbmltYXRvciBmcm9tICcuL2ZhZGUtYW5pbWF0b3InO1xuaW1wb3J0IEFzY2VuZFRvYXN0QW5pbWF0b3IgZnJvbSAnLi9hc2NlbmQtYW5pbWF0b3InO1xuaW1wb3J0IExpZnRUb2FzdEFuaW1hdG9yIGZyb20gJy4vbGlmdC1hbmltYXRvcic7XG5pbXBvcnQgRmFsbFRvYXN0QW5pbWF0b3IgZnJvbSAnLi9mYWxsLWFuaW1hdG9yJztcbmltcG9ydCBwbGF0Zm9ybSBmcm9tICcuLi8uLi9vbnMvcGxhdGZvcm0nO1xuaW1wb3J0IEJhc2VEaWFsb2dFbGVtZW50IGZyb20gJy4uL2Jhc2UvYmFzZS1kaWFsb2cnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi8uLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy50b2FzdCc6ICd0b2FzdC0tKicsXG4gICcudG9hc3RfX21lc3NhZ2UnOiAndG9hc3QtLSpfX21lc3NhZ2UnLFxuICAnLnRvYXN0X19idXR0b24nOiAndG9hc3QtLSpfX2J1dHRvbidcbn07XG5cbmNvbnN0IGRlZmF1bHRDbGFzc05hbWUgPSAndG9hc3QnO1xuXG5jb25zdCBfYW5pbWF0b3JEaWN0ID0ge1xuICAnZGVmYXVsdCc6IHBsYXRmb3JtLmlzQW5kcm9pZCgpID8gQXNjZW5kVG9hc3RBbmltYXRvciA6IExpZnRUb2FzdEFuaW1hdG9yLFxuICAnZmFkZSc6IEZhZGVUb2FzdEFuaW1hdG9yLFxuICAnYXNjZW5kJzogQXNjZW5kVG9hc3RBbmltYXRvcixcbiAgJ2xpZnQnOiBMaWZ0VG9hc3RBbmltYXRvcixcbiAgJ2ZhbGwnOiBGYWxsVG9hc3RBbmltYXRvcixcbiAgJ25vbmUnOiBUb2FzdEFuaW1hdG9yXG59O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy10b2FzdFxuICogQGNhdGVnb3J5IGRpYWxvZ1xuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBUaGUgVG9hc3Qgb3IgU25hY2tiYXIgY29tcG9uZW50IGlzIHVzZWZ1bCBmb3IgZGlzcGxheWluZyBkaXNtaXNzYWJsZSBpbmZvcm1hdGlvbiBvciBzaW1wbGUgYWN0aW9ucyBhdCAobm9ybWFsbHkpIHRoZSBib3R0b20gb2YgdGhlIHBhZ2UuXG4gKlxuICogICAgIFRoaXMgY29tcG9uZW50IGRvZXMgbm90IGJsb2NrIHVzZXIgaW5wdXQsIGFsbG93aW5nIHRoZSBhcHAgdG8gY29udGludWUgaXRzIGZsb3cuIEZvciBzaW1wbGUgdG9hc3RzLCBjb25zaWRlciBgb25zLm5vdGlmaWNhdGlvbi50b2FzdGAgaW5zdGVhZC5cbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvdG9hc3RcbiAqIEBzZWVhbHNvIG9ucy1hbGVydC1kaWFsb2dcbiAqICAgW2VuXVRoZSBgPG9ucy1hbGVydC1kaWFsb2c+YCBjb21wb25lbnQgaXMgcHJlZmVycmVkIGZvciBkaXNwbGF5aW5nIHVuZGlzbWlzc2FibGUgaW5mb3JtYXRpb24uWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRvYXN0RWxlbWVudCBleHRlbmRzIEJhc2VEaWFsb2dFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhbmltYXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgZGVmYXVsdFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgYW5pbWF0aW9uIHVzZWQgd2hlbiBzaG93aW5nIGFuZCBoaWRpbmcgdGhlIHRvYXN0LiBDYW4gYmUgZWl0aGVyIGBcImRlZmF1bHRcImAsIGBcImFzY2VuZFwiYCAoQW5kcm9pZCksIGBcImxpZnRcImAgKGlPUyksIGBcImZhbGxcImAsIGBcImZhZGVcImAgb3IgYFwibm9uZVwiYC5bL2VuXVxuICAgKiAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGFuaW1hdGlvbi1vcHRpb25zXG4gICAqIEB0eXBlIHtFeHByZXNzaW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgdGltaW5nIGFuZCBkZWxheSB3aXRoIGFuIG9iamVjdCBsaXRlcmFsLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgdGltaW5nLCBkZWxheeOCkuOCquODluOCuOOCp+OCr+ODiOODquODhuODqeODq+OBp+aMh+WumuOBl+OBvuOBmeOAgmUuZy4gPGNvZGU+e2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAxLCB0aW1pbmc6ICdlYXNlLWluJ308L2NvZGU+Wy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX2RlZmF1bHREQkIgPSBudWxsO1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl9jb21waWxlKCkpO1xuICB9XG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgcmV0dXJuIHNjaGVtZTtcbiAgfVxuXG4gIGdldCBfdG9hc3QoKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsIGAuJHtkZWZhdWx0Q2xhc3NOYW1lfWApO1xuICB9XG5cbiAgX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSgpIHtcbiAgICAvLyBSZXNldCBwb3NpdGlvbiBzdHlsZVxuICAgIHRoaXMuX3RvYXN0ICYmICh0aGlzLl90b2FzdC5zdHlsZS50b3AgPSB0aGlzLl90b2FzdC5zdHlsZS5ib3R0b20gPSAnJyk7XG5cbiAgICByZXR1cm4gbmV3IEFuaW1hdG9yRmFjdG9yeSh7XG4gICAgICBhbmltYXRvcnM6IF9hbmltYXRvckRpY3QsXG4gICAgICBiYXNlQ2xhc3M6IFRvYXN0QW5pbWF0b3IsXG4gICAgICBiYXNlQ2xhc3NOYW1lOiAnVG9hc3RBbmltYXRvcicsXG4gICAgICBkZWZhdWx0QW5pbWF0aW9uOiB0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uJylcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb25EZXZpY2VCYWNrQnV0dG9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1CYWNrLWJ1dHRvbiBoYW5kbGVyLlsvZW5dXG4gICAqICAgW2phXeODkOODg+OCr+ODnOOCv+ODs+ODj+ODs+ODieODqeOAglsvamFdXG4gICAqL1xuXG4gIF9jb21waWxlKCkge1xuICAgIGF1dG9TdHlsZS5wcmVwYXJlKHRoaXMpO1xuXG4gICAgdGhpcy5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIHRoaXMuc3R5bGUuekluZGV4ID0gMTAwMDA7IC8vIExvd2VyIHRoYW4gZGlhbG9nc1xuXG4gICAgY29uc3QgbWVzc2FnZUNsYXNzTmFtZSA9ICd0b2FzdF9fbWVzc2FnZSc7XG4gICAgY29uc3QgYnV0dG9uQ2xhc3NOYW1lID0gJ3RvYXN0X19idXR0b24nO1xuXG4gICAgbGV0IHRvYXN0ID0gdXRpbC5maW5kQ2hpbGQodGhpcywgYC4ke2RlZmF1bHRDbGFzc05hbWV9YCk7XG4gICAgaWYgKCF0b2FzdCkge1xuICAgICAgdG9hc3QgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIHRvYXN0LmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG4gICAgICB3aGlsZSAodGhpcy5jaGlsZE5vZGVzWzBdKSB7XG4gICAgICAgIHRvYXN0LmFwcGVuZENoaWxkKHRoaXMuY2hpbGROb2Rlc1swXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbGV0IGJ1dHRvbiA9IHV0aWwuZmluZENoaWxkKHRvYXN0LCBgLiR7YnV0dG9uQ2xhc3NOYW1lfWApO1xuICAgIGlmICghYnV0dG9uKSB7XG4gICAgICBidXR0b24gPSB1dGlsLmZpbmRDaGlsZCh0b2FzdCwgZSA9PiB1dGlsLm1hdGNoKGUsICcuYnV0dG9uJykgfHwgdXRpbC5tYXRjaChlLCAnYnV0dG9uJykpO1xuICAgICAgaWYgKGJ1dHRvbikge1xuICAgICAgICBidXR0b24uY2xhc3NMaXN0LnJlbW92ZSgnYnV0dG9uJyk7XG4gICAgICAgIGJ1dHRvbi5jbGFzc0xpc3QuYWRkKGJ1dHRvbkNsYXNzTmFtZSk7XG4gICAgICAgIHRvYXN0LmFwcGVuZENoaWxkKGJ1dHRvbik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZCh0b2FzdCwgYC4ke21lc3NhZ2VDbGFzc05hbWV9YCkpIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXRpbC5maW5kQ2hpbGQodG9hc3QsICcubWVzc2FnZScpO1xuICAgICAgaWYgKCFtZXNzYWdlKSB7XG4gICAgICAgIG1lc3NhZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IHRvYXN0LmNoaWxkTm9kZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAodG9hc3QuY2hpbGROb2Rlc1tpXSAhPT0gYnV0dG9uKSB7XG4gICAgICAgICAgICBtZXNzYWdlLmluc2VydEJlZm9yZSh0b2FzdC5jaGlsZE5vZGVzW2ldLCBtZXNzYWdlLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbWVzc2FnZS5jbGFzc0xpc3QuYWRkKG1lc3NhZ2VDbGFzc05hbWUpO1xuXG4gICAgICB0b2FzdC5pbnNlcnRCZWZvcmUobWVzc2FnZSwgdG9hc3QuZmlyc3RDaGlsZCk7XG4gICAgfVxuXG4gICAgaWYgKHRvYXN0LnBhcmVudE5vZGUgIT09IHRoaXMpIHtcbiAgICAgIHRoaXMuYXBwZW5kQ2hpbGQodG9hc3QpO1xuICAgIH1cblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgdGhpcy5fc2NoZW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdmlzaWJsZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIHZpc2libGUgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeimgee0oOOBjOimi+OBiOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHNob3dcbiAgICogQHNpZ25hdHVyZSBzaG93KFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUFuaW1hdGlvbiBuYW1lLiBBdmFpbGFibGUgYW5pbWF0aW9ucyBhcmUgYFwiZGVmYXVsdFwiYCwgYFwiYXNjZW5kXCJgIChBbmRyb2lkKSwgYFwibGlmdFwiYCAoaU9TKSwgYFwiZmFsbFwiYCwgYFwiZmFkZVwiYCBvciBgXCJub25lXCJgLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25PcHRpb25zXVxuICAgKiAgIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgZGVsYXkgYW5kIHRpbWluZy4gRS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIGRlbGF5LCB0aW1pbmfjgpLmjIflrprjgZfjgb7jgZnjgIJlLmcuIHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyB0aGUgZWxlbWVudC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgZGlzcGxheWVkIGVsZW1lbnRbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQG1ldGhvZCB0b2dnbGVcbiAgICogQHNpZ25hdHVyZSB0b2dnbGUoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJkZWZhdWx0XCJgLCBgXCJhc2NlbmRcImAgKEFuZHJvaWQpLCBgXCJsaWZ0XCJgIChpT1MpLCBgXCJmYWxsXCJgLCBgXCJmYWRlXCJgIG9yIGBcIm5vbmVcImAuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4ge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Ub2dnbGUgdG9hc3QgdmlzaWJpbGl0eS5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQG1ldGhvZCBoaWRlXG4gICAqIEBzaWduYXR1cmUgaGlkZShbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcImRlZmF1bHRcImAsIGBcImFzY2VuZFwiYCAoQW5kcm9pZCksIGBcImxpZnRcImAgKGlPUyksIGBcImZhbGxcImAsIGBcImZhZGVcImAgb3IgYFwibm9uZVwiYC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9Wy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUhpZGUgdG9hc3QuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGhpZGRlbiBlbGVtZW50Wy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IEFuaW1hdG9yXG4gICAqL1xuICBzdGF0aWMgcmVnaXN0ZXJBbmltYXRvcihuYW1lLCBBbmltYXRvcikge1xuICAgIGlmICghKEFuaW1hdG9yLnByb3RvdHlwZSBpbnN0YW5jZW9mIFRvYXN0QW5pbWF0b3IpKSB7XG4gICAgICB1dGlsLnRocm93KCdcIkFuaW1hdG9yXCIgcGFyYW0gbXVzdCBpbmhlcml0IE9uc1RvYXN0RWxlbWVudC5Ub2FzdEFuaW1hdG9yJyk7XG4gICAgfVxuICAgIF9hbmltYXRvckRpY3RbbmFtZV0gPSBBbmltYXRvcjtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgYW5pbWF0b3JzKCkge1xuICAgIHJldHVybiBfYW5pbWF0b3JEaWN0O1xuICB9XG5cbiAgc3RhdGljIGdldCBUb2FzdEFuaW1hdG9yKCkge1xuICAgIHJldHVybiBUb2FzdEFuaW1hdG9yO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLlRvYXN0ID0gVG9hc3RFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtdG9hc3QnLCBUb2FzdEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgQmFzZUJ1dHRvbkVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtYnV0dG9uJztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtdG9vbGJhci1idXR0b25cbiAqIEBjYXRlZ29yeSBwYWdlXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXU1hdGVyaWFsIERlc2lnbiB0b29sYmFyIGJ1dHRvbi5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBtb2RpZmllciBvdXRsaW5lXG4gKiAgIFtlbl1BIGJ1dHRvbiB3aXRoIGFuIG91dGxpbmUuWy9lbl1cbiAqICAgW2phXeOCouOCpuODiOODqeOCpOODs+OCkuOCguOBo+OBn+ODnOOCv+ODs+OCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXUJ1dHRvbiBjb21wb25lbnQgZm9yIG9ucy10b29sYmFyIGFuZCBvbnMtYm90dG9tLXRvb2xiYXIuWy9lbl1cbiAqICAgW2phXW9ucy10b29sYmFy44GC44KL44GE44Gvb25zLWJvdHRvbS10b29sYmFy44Gr6Kit572u44Gn44GN44KL44Oc44K/44Oz55So44Kz44Oz44Od44O844ON44Oz44OI44Gn44GZ44CCWy9qYV1cbiAqIEBjb2RlcGVuIGFIbUdMXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvcGFnZVxuICogQGd1aWRlIGNvbXBpbGF0aW9uLmh0bWwjdG9vbGJhci1jb21waWxhdGlvblxuICogICBbZW5dQWRkaW5nIGEgdG9vbGJhclsvZW5dXG4gKiAgIFtqYV3jg4Tjg7zjg6vjg5Djg7zjga7ov73liqBbL2phXVxuICogQHNlZWFsc28gb25zLXRvb2xiYXJcbiAqICAgW2VuXVRoZSBgPG9ucy10b29sYmFyPmAgY29tcG9uZW50IGRpc3BsYXlzIGEgbmF2aWdhdGlvbiBiYXIgYXQgdGhlIHRvcCBvZiBhIHBhZ2UuWy9lbl1cbiAqICAgW2phXW9ucy10b29sYmFy44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1iYWNrLWJ1dHRvblxuICogICBbZW5dVGhlIGA8b25zLWJhY2stYnV0dG9uPmAgZGlzcGxheXMgYSBiYWNrIGJ1dHRvbiBpbiB0aGUgbmF2aWdhdGlvbiBiYXIuWy9lbl1cbiAqICAgW2phXW9ucy1iYWNrLWJ1dHRvbuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy10b29sYmFyPlxuICogICA8ZGl2IGNsYXNzPVwibGVmdFwiPlxuICogICAgIDxvbnMtdG9vbGJhci1idXR0b24+XG4gKiAgICAgICBCdXR0b25cbiAqICAgICA8L29ucy10b29sYmFyLWJ1dHRvbj5cbiAqICAgPC9kaXY+XG4gKiAgIDxkaXYgY2xhc3M9XCJjZW50ZXJcIj5cbiAqICAgICBUaXRsZVxuICogICA8L2Rpdj5cbiAqICAgPGRpdiBjbGFzcz1cInJpZ2h0XCI+XG4gKiAgICAgPG9ucy10b29sYmFyLWJ1dHRvbj5cbiAqICAgICAgIDxvbnMtaWNvbiBpY29uPVwiaW9uLW5hdmljb25cIiBzaXplPVwiMjhweFwiPjwvb25zLWljb24+XG4gKiAgICAgPC9vbnMtdG9vbGJhci1idXR0b24+XG4gKiAgIDwvZGl2PlxuICogPC9vbnMtdG9vbGJhcj5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVG9vbGJhckJ1dHRvbkVsZW1lbnQgZXh0ZW5kcyBCYXNlQnV0dG9uRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBidXR0b24uWy9lbl1cbiAgICogICBbamFd44Oc44K/44Oz44Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgaWNvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1DcmVhdGVzIGFuIGBvbnMtaWNvbmAgY29tcG9uZW50IHdpdGggdGhpcyBzdHJpbmcuWy9lbl1cbiAgICogIFtqYV1gb25zLWljb25g44Kz44Oz44Od44O844ON44Oz44OI44KS5oKq5oCn44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZGlzYWJsZWRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgaWYgYnV0dG9uIHNob3VsZCBiZSBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3jg5zjgr/jg7PjgpLnhKHlirnljJbjgZnjgovloLTlkIjjga/mjIflrprjgZfjgabjgY/jgaDjgZXjgYTjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZWxlbWVudCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgcmV0dXJuIHsgJyc6ICd0b29sYmFyLWJ1dHRvbi0tKicgfTtcbiAgfVxuXG4gIGdldCBfZGVmYXVsdENsYXNzTmFtZSgpIHtcbiAgICByZXR1cm4gJ3Rvb2xiYXItYnV0dG9uJztcbiAgfVxuXG4gIGdldCBfcmlwcGxlT3B0KCkge1xuICAgIHJldHVybiBbdGhpcywgdW5kZWZpbmVkLCB7IGNlbnRlcjogJycsICdzaXplJzogJ2NvbnRhaW4nLCAnYmFja2dyb3VuZCc6ICd0cmFuc3BhcmVudCcgfV07XG4gIH1cbn1cblxub25zRWxlbWVudHMuVG9vbGJhckJ1dHRvbiA9IFRvb2xiYXJCdXR0b25FbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtdG9vbGJhci1idXR0b24nLCBUb29sYmFyQnV0dG9uRWxlbWVudCk7XG4iLCJpbXBvcnQgb25zIGZyb20gJy4vb25zJzsgLy8gQWRkIG9ucyBpbnRlcm5hbHNcbmltcG9ydCBzZXR1cCBmcm9tICcuL3NldHVwJzsgLy8gQWRkIHBvbHlmaWxsc1xuXG4vLyBBZGQgYW5kIHJlZ2lzdGVyIEN1c3RvbSBFbGVtZW50c1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy10ZW1wbGF0ZSc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWlmJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtYWN0aW9uLXNoZWV0JztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtYWN0aW9uLXNoZWV0LWJ1dHRvbic7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWFsZXJ0LWRpYWxvZyc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWFsZXJ0LWRpYWxvZy1idXR0b24nO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1iYWNrLWJ1dHRvbic7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWJvdHRvbS10b29sYmFyJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtYnV0dG9uJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtY2FyZCc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWNhcm91c2VsLWl0ZW0nO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1jYXJvdXNlbCc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWNvbCc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWRpYWxvZyc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWZhYic7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWdlc3R1cmUtZGV0ZWN0b3InO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1pY29uJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtbGF6eS1yZXBlYXQnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1saXN0LWhlYWRlcic7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWxpc3QtdGl0bGUnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1saXN0LWl0ZW0nO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1saXN0JztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtaW5wdXQnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1jaGVja2JveCc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLXJhZGlvJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtc2VhcmNoLWlucHV0JztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtbW9kYWwnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1uYXZpZ2F0b3InO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1wYWdlJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtcG9wb3Zlcic7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLXByb2dyZXNzLWJhcic7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLXByb2dyZXNzLWNpcmN1bGFyJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtcHVsbC1ob29rJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtcmFuZ2UnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1yaXBwbGUnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1yb3cnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1zZWdtZW50JztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtc2VsZWN0JztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtc3BlZWQtZGlhbC1pdGVtJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtc3BlZWQtZGlhbCc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLXNwbGl0dGVyLWNvbnRlbnQnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1zcGxpdHRlci1tYXNrJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtc3BsaXR0ZXItc2lkZSc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLXNwbGl0dGVyJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtc3dpdGNoJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtdGFiJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtdGFiYmFyJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtdG9hc3QnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy10b29sYmFyLWJ1dHRvbic7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLXRvb2xiYXInO1xuXG5zZXR1cChvbnMpOyAvLyBTZXR1cCBpbml0aWFsIGxpc3RlbmVyc1xud2luZG93Ll9zdXBlclNlY3JldE9ucyA9IG9ucztcblxuZXhwb3J0IGRlZmF1bHQgb25zO1xuIl0sIm5hbWVzIjpbInByZWZpeCIsInN0eWxlcyIsIndpbmRvdyIsImdldENvbXB1dGVkU3R5bGUiLCJkb2N1bWVudCIsImRvY3VtZW50RWxlbWVudCIsIkFycmF5IiwicHJvdG90eXBlIiwic2xpY2UiLCJjYWxsIiwiam9pbiIsIm1hdGNoIiwiT0xpbmsiLCJuYW1lIiwidXRpbCIsImh5cGhlbmF0ZSIsInN0eWxlciIsImVsZW1lbnQiLCJzdHlsZSIsImtleXMiLCJmb3JFYWNoIiwia2V5Iiwid2FybiIsImNsZWFyIiwiY2xlYXJsaXN0Iiwic3BsaXQiLCJyZWR1Y2UiLCJyIiwicyIsImNvbmNhdCIsImkiLCJsZW5ndGgiLCJzb21lIiwiaW5kZXhPZiIsInB1c2giLCJnZXRBdHRyaWJ1dGUiLCJyZW1vdmVBdHRyaWJ1dGUiLCJOYXRpdmVIVE1MRWxlbWVudCIsIkhUTUxFbGVtZW50IiwiUGxhdGZvcm0iLCJfc2VsZWN0ZWRQbGF0Zm9ybSIsIl9pZ25vcmVQbGF0Zm9ybVNlbGVjdCIsInBsYXRmb3JtIiwidHJpbSIsInRvTG93ZXJDYXNlIiwiZm4iLCJyZXN1bHQiLCJyZWFkeVN0YXRlIiwiRXJyb3IiLCJjb3Jkb3ZhIiwicGhvbmVnYXAiLCJQaG9uZUdhcCIsInRlc3QiLCJuYXZpZ2F0b3IiLCJ1c2VyQWdlbnQiLCJpc0lQaG9uZSIsInNjcmVlbiIsIndpZHRoIiwiaGVpZ2h0IiwiZm9yY2VBY3R1YWxQbGF0Zm9ybSIsIl9nZXRTZWxlY3RlZFBsYXRmb3JtIiwiZGV2aWNlIiwicGFyc2VJbnQiLCJ2ZXJzaW9uIiwidmVyIiwicmVwbGFjZSIsInVhIiwiaXNJT1MiLCJzdGFuZGFsb25lIiwibHRlOSIsIndlYmtpdCIsIm1lc3NhZ2VIYW5kbGVycyIsImluZGV4ZWREQiIsImlzSU9TU2FmYXJpIiwiaXNXS1dlYlZpZXciLCJvcGVyYSIsIkluc3RhbGxUcmlnZ2VyIiwiT2JqZWN0IiwidG9TdHJpbmciLCJwIiwic2FmYXJpIiwicHVzaE5vdGlmaWNhdGlvbiIsImNocm9tZSIsImRvY3VtZW50TW9kZSIsImlzQW5kcm9pZCIsImlzV1AiLCJpc0lQYWQiLCJpc0lQb2QiLCJlcnJvciIsInRocm93IiwibWVzc2FnZSIsInBhZ2VBdHRyaWJ1dGVFeHByZXNzaW9uIiwidmFsdWUiLCJvdmVyd3JpdGUiLCJfdmFyaWFibGVzIiwiaGFzT3duUHJvcGVydHkiLCJwYXJ0IiwiYyIsImluSW50ZXJwb2xhdGlvbiIsImN1cnJlbnRJbmRleCIsInRva2VucyIsImNoYXJBdCIsInRva2VuIiwic3Vic3RyaW5nIiwicmUiLCJ2YXJpYWJsZSIsImdldFZhcmlhYmxlIiwicnYiLCJtYXAiLCJfcmVwbGFjZVRva2VuIiwiYmluZCIsImV4cHJlc3Npb24iLCJfcGFyc2VQYXJ0IiwiX3JlcGxhY2VUb2tlbnMiLCJfcGFyc2VFeHByZXNzaW9uIiwiZGVmaW5lVmFyaWFibGUiLCJnZXRNb2JpbGVPUyIsImdldElPU0RldmljZSIsImlzV2ViVmlldyIsImludGVybmFsIiwiY29uZmlnIiwibnVsbEVsZW1lbnQiLCJjcmVhdGVFbGVtZW50IiwiaXNFbmFibGVkQXV0b1N0YXR1c0JhckZpbGwiLCJhdXRvU3RhdHVzQmFyRmlsbCIsIm5vcm1hbGl6ZVBhZ2VIVE1MIiwiaHRtbCIsIndhaXRET01Db250ZW50TG9hZGVkIiwid3JhcHBlZENhbGxiYWNrIiwicmVtb3ZlRXZlbnRMaXN0ZW5lciIsImFkZEV2ZW50TGlzdGVuZXIiLCJjYWxsYmFjayIsIm9uUmVhZHkiLCJzaG91bGRGaWxsU3RhdHVzQmFyIiwiaXNJT1M3YWJvdmUiLCJpc0lQaG9uZVgiLCJib2R5IiwicXVlcnlTZWxlY3RvciIsInRlbXBsYXRlU3RvcmUiLCJfc3RvcmFnZSIsInRlbXBsYXRlIiwiZSIsInRhcmdldCIsIm5vZGVOYW1lIiwic2V0IiwidGVtcGxhdGVJZCIsInJlZ2lzdGVyIiwicXVlcnkiLCJ0ZW1wbGF0ZXMiLCJxdWVyeVNlbGVjdG9yQWxsIiwidGV4dENvbnRlbnQiLCJjb250ZW50IiwiZ2V0VGVtcGxhdGVIVE1MQXN5bmMiLCJwYWdlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZWplY3QiLCJjYWNoZSIsImdldCIsIkRvY3VtZW50RnJhZ21lbnQiLCJsb2NhbCIsImdldEVsZW1lbnRCeUlkIiwieGhyIiwiWE1MSHR0cFJlcXVlc3QiLCJvcGVuIiwib25sb2FkIiwicmVzcG9uc2VUZXh0Iiwic3RhdHVzIiwiZnJhZ21lbnQiLCJjcmVhdGVGcmFnbWVudCIsImFycmF5RnJvbSIsInNjcmlwdCIsInR5cGUiLCJlbCIsImFwcGVuZENoaWxkIiwiY3JlYXRlVGV4dE5vZGUiLCJ0ZXh0IiwiaW5uZXJIVE1MIiwicGFyZW50Tm9kZSIsInJlcGxhY2VDaGlsZCIsIm9uZXJyb3IiLCJzZW5kIiwiZ2V0UGFnZUhUTUxBc3luYyIsInBhZ2VzIiwiZXZhbHVhdGUiLCJnZXRQYWdlIiwiY2F0Y2giLCJzaGlmdCIsIkFuaW1hdG9yRmFjdG9yeSIsIm9wdHMiLCJfYW5pbWF0b3JzIiwiYW5pbWF0b3JzIiwiX2Jhc2VDbGFzcyIsImJhc2VDbGFzcyIsIl9iYXNlQ2xhc3NOYW1lIiwiYmFzZUNsYXNzTmFtZSIsIl9hbmltYXRpb24iLCJkZWZhdWx0QW5pbWF0aW9uIiwiX2FuaW1hdGlvbk9wdGlvbnMiLCJkZWZhdWx0QW5pbWF0aW9uT3B0aW9ucyIsIm9wdGlvbnMiLCJkZWZhdWx0QW5pbWF0b3IiLCJhbmltYXRvciIsImFuaW1hdGlvbiIsIkFuaW1hdG9yIiwiYW5pbWF0aW9uT3B0cyIsImV4dGVuZCIsImFuaW1hdGlvbk9wdGlvbnMiLCJhbmltYXRpb25zRGlzYWJsZWQiLCJkdXJhdGlvbiIsImRlbGF5IiwianNvblN0cmluZyIsImFuaW1hdGlvbk9wdGlvbnNQYXJzZSIsImF1dG9TdHlsZUVuYWJsZWQiLCJtb2RpZmllcnNNYXAiLCJwbGF0Zm9ybXMiLCJhbmRyb2lkIiwiZWxlbWVudE5hbWUiLCJ0YWdOYW1lIiwiaGFzTW9kaWZpZXIiLCJvbGRNb2RpZmllciIsIm5ld01vZGlmaWVyIiwidW5zaGlmdCIsInNldEF0dHJpYnV0ZSIsImVsZW1lbnRzIiwiaGFzQXR0cmlidXRlIiwiaW9zIiwicmVtb3ZlTW9kaWZpZXIiLCJhZGRNb2RpZmllciIsInVubG9ja2VkIiwiZ2V0UGxhdGZvcm0iLCJmb3JjZSIsIm1vYmlsZU9TIiwib25zUGxhdGZvcm0iLCJwcmVwYXJlIiwibWFwTW9kaWZpZXIiLCJtb2RpZmllciIsIm0iLCJyZXN0b3JlTW9kaWZpZXIiLCJNb2RpZmllclV0aWwiLCJsYXN0IiwiY3VycmVudCIsIm1ha2VEaWN0IiwicmVtb3ZlZCIsImFkZGVkIiwiZGljdCIsImRpZmYiLCJjbGFzc0xpc3QiLCJrbGFzcyIsImFkZCIsImsiLCJyZW1vdmUiLCJzY2hlbWUiLCJ0YXJnZXRFbGVtZW50cyIsInNlbGVjdG9yIiwiZmlsdGVyIiwiZmluZFBhcmVudCIsInRhcmdldEVsZW1lbnQiLCJwYXJlbnQiLCJhcHBseURpZmZUb0NsYXNzTGlzdCIsImFwcGx5RGlmZlRvRWxlbWVudCIsIm1vZGlmaWVyVG9rZW4iLCJpbmRleCIsInNwbGljZSIsIl9kb21Db250ZW50TG9hZGVkIiwiX3JlYWR5IiwiX29uRE9NQ29udGVudExvYWRlZCIsIkhhbmRsZXJSZXBvc2l0b3J5IiwiaGFuZGxlciIsImRhdGFzZXQiLCJkZXZpY2VCYWNrQnV0dG9uSGFuZGxlcklkIiwiaWQiLCJfZ2VuSWQiLCJfc3RvcmUiLCJ1bmRlZmluZWQiLCJEZXZpY2VCYWNrQnV0dG9uRGlzcGF0Y2hlciIsIl9pc0VuYWJsZWQiLCJfYm91bmRDYWxsYmFjayIsIl9jYWxsYmFjayIsImFkZEJhY2tCdXR0b25MaXN0ZW5lciIsInJlbW92ZUJhY2tCdXR0b25MaXN0ZW5lciIsImV2ZW50IiwiY3JlYXRlRXZlbnQiLCJpbml0RXZlbnQiLCJkaXNwYXRjaEV2ZW50IiwiX2Rpc3BhdGNoRGV2aWNlQmFja0J1dHRvbkV2ZW50IiwiRnVuY3Rpb24iLCJfZWxlbWVudCIsImVuYWJsZSIsInRyZWUiLCJfY2FwdHVyZVRyZWUiLCJfZmluZEhhbmRsZXJMZWFmRWxlbWVudCIsImNyZWF0ZVRyZWUiLCJhcHBseSIsImFycmF5T2YiLCJjaGlsZHJlbiIsImNoaWxkRWxlbWVudCIsImRpc3BsYXkiLCJfaXNTaG93biIsImhhcyIsInN1YlRyZWUiLCJmaW5kIiwibm9kZSIsImNoaWxkTm9kZSIsImxlZnQiLCJyaWdodCIsImxlZnRaIiwiekluZGV4IiwicmlnaHRaIiwiaXNOYU4iLCJkYmJEaXNwYXRjaGVyIiwiZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIiLCJzdGFydHNXaXRoIiwic3Vic3RyIiwiZW5kc1dpdGgiLCJ1bndyYXAiLCJpc09iamVjdFN0cmluZyIsImlzQXJyYXlTdHJpbmciLCJpc1F1b3RlZFN0cmluZyIsInN0cmluZyIsIm9yaWdpbmFsU3RyaW5nIiwicHJvY2Vzc1Rva2VuIiwicGFyc2VPYmplY3QiLCJwYXJzZUFycmF5IiwibmV4dFRva2VuIiwibGltaXQiLCJjaGFyQ29kZUF0IiwibmVzdGVkT2JqZWN0IiwiaXNWYWxpZEtleSIsIm9iamVjdCIsInJlYWRpbmdLZXkiLCJwcmV2aW91c1Rva2VuIiwiYXJyYXkiLCJwYXJzZSIsImVycm9yUHJlZml4IiwiZ2xvYmFscyIsIl9ydW5PbkFjdHVhbFBsYXRmb3JtIiwiYWN0dWFsTW9iaWxlT1MiLCJpc1VJV2ViVmlldyIsImRlZmluZVByb3BlcnR5Iiwic3VwcG9ydHNQYXNzaXZlIiwib3B0IiwiaXNHRCIsImNhcHR1cmUiLCJwcmVwYXJlUXVlcnkiLCJtYXRjaGVzIiwid2Via2l0TWF0Y2hlc1NlbGVjdG9yIiwibW96TWF0Y2hlc1NlbGVjdG9yIiwibXNNYXRjaGVzU2VsZWN0b3IiLCJmaW5kQ2hpbGQiLCJjaGlsZE5vZGVzIiwibm9kZVR5cGUiLCJOb2RlIiwiRUxFTUVOVF9OT0RFIiwidW50aWwiLCJpc0F0dGFjaGVkIiwiY29udGFpbnMiLCJoYXNBbnlDb21wb25lbnRBc1BhcmVudCIsImdldEFsbENoaWxkTm9kZXMiLCJmcm9tIiwiY2hpbGRFbCIsImlzUGFnZUNvbnRyb2wiLCJwcm9wYWdhdGVBY3Rpb24iLCJhY3Rpb24iLCJjaGlsZCIsImNhbWVsaXplIiwibCIsInRvVXBwZXJDYXNlIiwiY3JlYXRlIiwiY2xhc3NOYW1lIiwid3JhcHBlciIsImltcG9ydE5vZGUiLCJkc3QiLCJhcmdzIiwiaiIsImFycmF5TGlrZSIsInBhcnNlSlNPTk9iamVjdFNhZmVseSIsImZhaWxTYWZlIiwiSlNPTiIsImZpbmRGcm9tUGF0aCIsInBhdGgiLCJnZXRUb3BQYWdlIiwiY29udGFpbmVyIiwidG9wUGFnZSIsImZpbmRUb29sYmFyUGFnZSIsIl9jYW5BbmltYXRlVG9vbGJhciIsIl9jb250ZW50RWxlbWVudCIsIm5leHRQYWdlIiwidHJpZ2dlckVsZW1lbnRFdmVudCIsImV2ZW50TmFtZSIsImRldGFpbCIsIkN1c3RvbUV2ZW50IiwibW9kaWZpZXJOYW1lIiwiUmVnRXhwIiwiYXV0b1N0eWxlIiwiZm9yY2VBdXRvU3R5bGUiLCJuZXdNb2RpZmllcnMiLCJ0b2dnbGVNb2RpZmllciIsInRvZ2dsZSIsInJlc3RvcmVDbGFzcyIsImRlZmF1bHRDbGFzcyIsInJlZnJlc2giLCJ1cGRhdGVQYXJlbnRQb3NpdGlvbiIsIl9wYXJlbnRVcGRhdGVkIiwicGFyZW50RWxlbWVudCIsImdldFByb3BlcnR5VmFsdWUiLCJwb3NpdGlvbiIsInRvZ2dsZUF0dHJpYnV0ZSIsImJpbmRMaXN0ZW5lcnMiLCJsaXN0ZW5lck5hbWVzIiwiYm91bmROYW1lIiwiZWFjaCIsIm9iaiIsImYiLCJ1cGRhdGVSaXBwbGUiLCJoYXNSaXBwbGUiLCJhdHRycyIsInJpcHBsZUVsZW1lbnQiLCJpbnNlcnRCZWZvcmUiLCJmaXJzdENoaWxkIiwiaXNJbnRlZ2VyIiwiaXNGaW5pdGUiLCJNYXRoIiwiZmxvb3IiLCJkZWZlciIsImRlZmVycmVkIiwicHJvbWlzZSIsIndhcm5pbmdzRGlzYWJsZWQiLCJ0aHJvd0Fic3RyYWN0IiwidGhyb3dNZW1iZXIiLCJ0aHJvd1BhZ2VMb2FkZXIiLCJ0aHJvd0FuaW1hdG9yIiwicHJldmVudCIsImNhbmNlbGFibGUiLCJwcmV2ZW50RGVmYXVsdCIsImlvc1ByZXZlbnRTY3JvbGwiLCJjbGVhbiIsIm9mZiIsIm9uIiwiaW9zUGFnZVNjcm9sbEZpeCIsImZvcmNlVUlXZWJWaWV3U2Nyb2xsRml4IiwiaW9zTWFza1Njcm9sbEZpeCIsImlzVmFsaWRHZXN0dXJlIiwiZ2VzdHVyZSIsImRpc3RhbmNlIiwiZGVsdGFUaW1lIiwiY2hlY2tNaXNzaW5nSW1wb3J0IiwiZWxlbWVudE5hbWVzIiwib25zRWxlbWVudHMiLCJUSU1FT1VUX1JBVElPIiwiY2FwaXRhbGl6ZSIsInN0ciIsImJ1aWxkVHJhbnNpdGlvblZhbHVlIiwicGFyYW1zIiwicHJvcGVydHkiLCJ0aW1pbmciLCJwcm9wcyIsInByb3AiLCJvbmNlT25UcmFuc2l0aW9uRW5kIiwic3RvcFByb3BhZ2F0aW9uIiwicmVtb3ZlTGlzdGVuZXJzIiwiX3RyYW5zaXRpb25FbmRFdmVudHMiLCJ2ZW5kb3JQcmVmaXgiLCJfY3NzUHJvcGVydHlEaWN0IiwiYSIsInoiLCJ1cHBlciIsImhhc0Nzc1Byb3BlcnR5IiwicHJlIiwiZm9yY2VMYXlvdXRBdE9uY2UiLCJiYXRjaEltbWVkaWF0ZSIsIm9mZnNldEhlaWdodCIsImNhbGxiYWNrcyIsImNvbmNyZWF0ZUNhbGxiYWNrcyIsImJhdGNoQW5pbWF0aW9uRnJhbWUiLCJyYWYiLCJyZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJ3ZWJraXRSZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJtb3pSZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJvUmVxdWVzdEFuaW1hdGlvbkZyYW1lIiwibXNSZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJ0cmFuc2l0aW9uUHJvcGVydHlOYW1lIiwiQW5pbWl0IiwiZGVmYXVsdHMiLCJ0cmFuc2l0aW9uUXVldWUiLCJsYXN0U3R5bGVBdHRyaWJ1dGVEaWN0IiwiZG9uZSIsInN0YXJ0QW5pbWF0aW9uIiwidG8iLCJzdGVwIiwiY3NzIiwic2F2ZVN0eWxlIiwicXVldWUiLCJ3YWl0IiwicmVzdG9yZVN0eWxlIiwidHJhbnNpdGlvbiIsIlRyYW5zaXRpb24iLCJidWlsZCIsInNlY29uZHMiLCJzZWxmIiwidHJhbnNpdGlvbk5hbWUiLCJ0cmFuc2l0aW9uVmFsdWUiLCJ0aW1lb3V0SWQiLCJjbGVhclRyYW5zaXRpb24iLCJzZXRUaW1lb3V0IiwibGVuIiwicmVzZXQiLCJfZGVxdWV1ZVRyYW5zaXRpb24iLCJfY3VycmVudFRyYW5zaXRpb24iLCJjYWxsZWQiLCJydW5BbGwiLCJhcmd1bWVudHMiLCJwbGF5IiwiY3JlYXRlQWN0dWFsQ3NzUHJvcHMiLCJ0aW1lb3V0IiwicHJlZml4ZWQiLCJFdmVudCIsIlV0aWxzIiwiRGV0ZWN0aW9uIiwiUG9pbnRlckV2ZW50IiwiR2VzdHVyZURldGVjdG9yIiwiSW5zdGFuY2UiLCJET0NVTUVOVCIsIkhBU19QT0lOVEVSRVZFTlRTIiwicG9pbnRlckVuYWJsZWQiLCJtc1BvaW50ZXJFbmFibGVkIiwiSEFTX1RPVUNIRVZFTlRTIiwiSVNfTU9CSUxFIiwiTk9fTU9VU0VFVkVOVFMiLCJDQUxDVUxBVEVfSU5URVJWQUwiLCJFVkVOVF9UWVBFUyIsIkRJUkVDVElPTl9ET1dOIiwiRElSRUNUSU9OX0xFRlQiLCJESVJFQ1RJT05fVVAiLCJESVJFQ1RJT05fUklHSFQiLCJQT0lOVEVSX01PVVNFIiwiUE9JTlRFUl9UT1VDSCIsIlBPSU5URVJfUEVOIiwiRVZFTlRfU1RBUlQiLCJFVkVOVF9NT1ZFIiwiRVZFTlRfRU5EIiwiRVZFTlRfUkVMRUFTRSIsIkVWRU5UX1RPVUNIIiwiUkVBRFkiLCJwbHVnaW5zIiwiZ2VzdHVyZXMiLCJzZXR1cCIsImRldGVybWluZUV2ZW50VHlwZXMiLCJvblRvdWNoIiwiZGV0ZWN0IiwidXRpbHMiLCJkZXN0Iiwic3JjIiwibWVyZ2UiLCJpdGVyYXRvciIsImNvbnRleHQiLCJpblN0ciIsImluQXJyYXkiLCJkZWVwIiwiZXZlcnkiLCJ0b0FycmF5IiwiaGFzUGFyZW50IiwiZ2V0Q2VudGVyIiwidG91Y2hlcyIsInBhZ2VYIiwicGFnZVkiLCJjbGllbnRYIiwiY2xpZW50WSIsIm1pbiIsIm1heCIsInRvdWNoIiwiZ2V0VmVsb2NpdHkiLCJkZWx0YVgiLCJkZWx0YVkiLCJhYnMiLCJnZXRBbmdsZSIsInRvdWNoMSIsInRvdWNoMiIsIngiLCJ5IiwiYXRhbjIiLCJQSSIsImdldERpcmVjdGlvbiIsImdldERpc3RhbmNlIiwic3FydCIsImdldFNjYWxlIiwic3RhcnQiLCJlbmQiLCJnZXRSb3RhdGlvbiIsImlzVmVydGljYWwiLCJkaXJlY3Rpb24iLCJzZXRQcmVmaXhlZENzcyIsInByZWZpeGVzIiwidG9DYW1lbENhc2UiLCJ0b2dnbGVCZWhhdmlvciIsImZhbHNlRm4iLCJ1c2VyU2VsZWN0Iiwib25zZWxlY3RzdGFydCIsInVzZXJEcmFnIiwib25kcmFnc3RhcnQiLCJob29rIiwidHlwZXMiLCJldmVudFR5cGUiLCJvblRvdWNoSGFuZGxlciIsImV2Iiwic3JjVHlwZSIsImlzUG9pbnRlciIsImlzTW91c2UiLCJ0cmlnZ2VyVHlwZSIsInByZXZlbnRNb3VzZUV2ZW50cyIsImJ1dHRvbiIsInNob3VsZERldGVjdCIsImJ1dHRvbnMiLCJtYXRjaFR5cGUiLCJ1cGRhdGVQb2ludGVyIiwiZG9EZXRlY3QiLCJ0b3VjaExpc3QiLCJnZXRUb3VjaExpc3QiLCJ0b3VjaExpc3RMZW5ndGgiLCJ0cmlnZ2VyQ2hhbmdlIiwidHJpZ2dlciIsImNoYW5nZWRMZW5ndGgiLCJjaGFuZ2VkVG91Y2hlcyIsInN0YXJ0ZWQiLCJldkRhdGEiLCJjb2xsZWN0RXZlbnREYXRhIiwiaWRlbnRpZmllcnMiLCJpZGVudGlmaWVyIiwicG9pbnRlclR5cGUiLCJEYXRlIiwibm93Iiwic3JjRXZlbnQiLCJwcmV2ZW50TWFuaXB1bGF0aW9uIiwic3RvcERldGVjdCIsInRvdWNobGlzdCIsInBvaW50ZXJzIiwicG9pbnRlciIsInBvaW50ZXJFdmVudCIsInBvaW50ZXJJZCIsInB0IiwiTVNQT0lOVEVSX1RZUEVfTU9VU0UiLCJNU1BPSU5URVJfVFlQRV9UT1VDSCIsIk1TUE9JTlRFUl9UWVBFX1BFTiIsInJlc2V0TGlzdCIsImRldGVjdGlvbiIsInN0YXJ0RGV0ZWN0IiwiaW5zdCIsImV2ZW50RGF0YSIsInN0b3BwZWQiLCJleHRlbmRFdmVudERhdGEiLCJpbnN0T3B0aW9ucyIsInRyaWdnZXJHZXN0dXJlIiwiZW5hYmxlZCIsImxhc3RFdmVudCIsInByZXZpb3VzIiwiZ2V0Q2FsY3VsYXRlZERhdGEiLCJjZW50ZXIiLCJjdXIiLCJyZWNhbGMiLCJjYWxjRXYiLCJsYXN0Q2FsY0V2ZW50IiwiY2FsY0RhdGEiLCJsYXN0Q2FsY0RhdGEiLCJ0aW1lU3RhbXAiLCJmdXR1cmVDYWxjRXZlbnQiLCJ2ZWxvY2l0eSIsImFuZ2xlIiwidmVsb2NpdHlYIiwidmVsb2NpdHlZIiwiaW50ZXJpbUFuZ2xlIiwiaW50ZXJpbURpcmVjdGlvbiIsInN0YXJ0RXYiLCJzdGFydEV2ZW50IiwibGFzdEV2Iiwic29ydCIsImIiLCJsaXN0ZW5lck9wdGlvbnMiLCJwYXNzaXZlIiwiYmVoYXZpb3IiLCJldmVudFN0YXJ0SGFuZGxlciIsImV2ZW50SGFuZGxlcnMiLCJvbkV2ZW50Iiwib2ZmRXZlbnQiLCJ0cmlnZ2VyRXZlbnQiLCJzdGF0ZSIsImRpc3Bvc2UiLCJlaCIsInRyaWdnZXJlZCIsImRyYWdHZXN0dXJlIiwiZHJhZ01heFRvdWNoZXMiLCJkcmFnTWluRGlzdGFuY2UiLCJzdGFydENlbnRlciIsImRyYWdEaXN0YW5jZUNvcnJlY3Rpb24iLCJmYWN0b3IiLCJkcmFnTG9ja1RvQXhpcyIsImRyYWdMb2NrTWluRGlzdGFuY2UiLCJsYXN0RGlyZWN0aW9uIiwiZHJhZ0Jsb2NrVmVydGljYWwiLCJkcmFnQmxvY2tIb3Jpem9udGFsIiwiRHJhZyIsIkdlc3R1cmUiLCJyZWxlYXNlR2VzdHVyZSIsInRpbWVyIiwiaG9sZEdlc3R1cmUiLCJob2xkVGltZW91dCIsImhvbGRUaHJlc2hvbGQiLCJIb2xkIiwiUmVsZWFzZSIsIkluZmluaXR5IiwiU3dpcGUiLCJzd2lwZUdlc3R1cmUiLCJzd2lwZU1pblRvdWNoZXMiLCJzd2lwZU1heFRvdWNoZXMiLCJzd2lwZVZlbG9jaXR5WCIsInN3aXBlVmVsb2NpdHlZIiwiaGFzTW92ZWQiLCJ0YXBHZXN0dXJlIiwicHJldiIsInNpbmNlUHJldiIsImRpZERvdWJsZVRhcCIsInRhcE1heERpc3RhbmNlIiwidGFwTWF4VGltZSIsImRvdWJsZVRhcEludGVydmFsIiwiZG91YmxlVGFwRGlzdGFuY2UiLCJ0YXBBbHdheXMiLCJUYXAiLCJUb3VjaCIsInRvdWNoR2VzdHVyZSIsInByZXZlbnRNb3VzZSIsInRyYW5zZm9ybUdlc3R1cmUiLCJzY2FsZVRocmVzaG9sZCIsInNjYWxlIiwicm90YXRpb25UaHJlc2hvbGQiLCJyb3RhdGlvbiIsInRyYW5zZm9ybU1pblNjYWxlIiwidHJhbnNmb3JtTWluUm90YXRpb24iLCJUcmFuc2Zvcm0iLCJyZWFkeU1hcCIsInF1ZXVlTWFwIiwiaXNDb250ZW50UmVhZHkiLCJzZXRDb250ZW50UmVhZHkiLCJhZGRDYWxsYmFjayIsImNvbnN1bWVRdWV1ZSIsImRlbGV0ZSIsImNvbnRlbnRSZWFkeSIsIldlYWtNYXAiLCJvYnNlcnZlciIsIk11dGF0aW9uT2JzZXJ2ZXIiLCJvYnNlcnZlIiwiY2hpbGRMaXN0IiwiY2hhcmFjdGVyRGF0YSIsIlRvYXN0UXVldWUiLCJ0aGVuIiwiX3NldEF0dHJpYnV0ZXMiLCJfbm9ybWFsaXplQXJndW1lbnRzIiwibWVzc2FnZUhUTUwiLCJidXR0b25MYWJlbHMiLCJidXR0b25MYWJlbCIsImlzQXJyYXkiLCJwYXJhbSIsIm5vdGlmaWNhdGlvbiIsIl9jcmVhdGVBbGVydERpYWxvZyIsImlucHV0U3RyaW5nIiwiaXNQcm9tcHQiLCJpbnB1dFR5cGUiLCJwbGFjZWhvbGRlciIsImRlZmF1bHRWYWx1ZSIsImxhYmVsIiwicHJpbWFyeUJ1dHRvbkluZGV4IiwiX2Rlc3Ryb3lEaWFsb2ciLCJkaWFsb2ciLCJvbkRpYWxvZ0NhbmNlbCIsImRlc3Ryb3kiLCJtYXNrQ29sb3IiLCJ0aXRsZSIsInN1Ym1pdE9uRW50ZXIiLCJpbnB1dCIsIm9ua2V5cHJlc3MiLCJrZXlDb2RlIiwiaGlkZSIsInJlc29sdmVWYWx1ZSIsImZvb3RlciIsImJ1dHRvbkVsZW1lbnQiLCJvbmNsaWNrIiwiY29tcGlsZSIsInNob3ciLCJhdXRvZm9jdXMiLCJzdHJMZW5ndGgiLCJmb2N1cyIsInNldFNlbGVjdGlvblJhbmdlIiwiYWxlcnQiLCJjb25maXJtIiwicHJvbXB0IiwidG9hc3QiLCJmaW5pc2giLCJfdG9hc3QiLCJjaGVja09wdGlvbnMiLCJlcnIiLCJpbnN0YW5jZU9mIiwiY2IiLCJkIiwiYWN0aW9uU2hlZXQiLCJjbGFzcyIsImNyZWF0ZURvY3VtZW50RnJhZ21lbnQiLCJpdGVtIiwiYnV0dG9uT3B0aW9ucyIsImRlc3RydWN0aXZlIiwiaWNvbiIsIk1pY3JvRXZlbnQiLCJmY3QiLCJfZXZlbnRzIiwiX2ZjdCIsIm1peGluIiwiZGVzdE9iamVjdCIsIl9pc1BvcnRyYWl0IiwiaXNQb3J0cmFpdCIsIl9vbk9yaWVudGF0aW9uQ2hhbmdlIiwiX29uUmVzaXplIiwiaW5uZXJIZWlnaHQiLCJpbm5lcldpZHRoIiwiX2luc3RhbGxJc1BvcnRyYWl0SW1wbGVtZW50YXRpb24iLCJlbWl0Iiwib3JpZW50YXRpb24iLCJuSXRlciIsImludGVydmFsIiwic2V0SW50ZXJ2YWwiLCJ3IiwiaCIsIl9pbml0IiwibW9kaWZpZXJzIiwic29mdHdhcmVLZXlib2FyZCIsIl92aXNpYmxlIiwib25TaG93Iiwib25IaWRlIiwiYmluZEV2ZW50cyIsIktleWJvYXJkIiwib25zaG93Iiwib25oaWRlIiwidmlzaWJsZSIsImlzVmlzaWJsZSIsIm5vUGx1Z2luRXJyb3IiLCJnZW5lcmF0ZUlkIiwiRG9vckxvY2siLCJfbG9ja0xpc3QiLCJfd2FpdExpc3QiLCJfbG9nIiwibG9nIiwidW5sb2NrIiwiX3VubG9jayIsIl90cnlUb0ZyZWVXYWl0TGlzdCIsImlzTG9ja2VkIiwibG9hZFBhZ2UiLCJwYWdlRWxlbWVudCIsInVubG9hZFBhZ2UiLCJfZGVzdHJveSIsIlBhZ2VMb2FkZXIiLCJsb2FkZXIiLCJ1bmxvYWRlciIsIl9sb2FkZXIiLCJfdW5sb2FkZXIiLCJFbGVtZW50IiwiZGVmYXVsdFBhZ2VMb2FkZXIiLCJpbnN0YW50UGFnZUxvYWRlciIsIm9ucyIsInNlbGVjdCIsImxvY2F0aW9uIiwic2VhcmNoIiwid2FpdERldmljZVJlYWR5IiwicmVhZHlFcnJvciIsImFmdGVyIiwiaXNSZWFkeSIsIl9yZWFkeUxvY2siLCJyZWFkeSIsIndhaXRVbmxvY2siLCJzZXREZWZhdWx0RGV2aWNlQmFja0J1dHRvbkxpc3RlbmVyIiwibGlzdGVuZXIiLCJfZGVmYXVsdERldmljZUJhY2tCdXR0b25IYW5kbGVyIiwic2V0TGlzdGVuZXIiLCJkaXNhYmxlRGV2aWNlQmFja0J1dHRvbkhhbmRsZXIiLCJkaXNhYmxlIiwiZW5hYmxlRGV2aWNlQmFja0J1dHRvbkhhbmRsZXIiLCJmaXJlRGV2aWNlQmFja0J1dHRvbkV2ZW50IiwiZW5hYmxlQXV0b1N0YXR1c0JhckZpbGwiLCJkaXNhYmxlQXV0b1N0YXR1c0JhckZpbGwiLCJtb2NrU3RhdHVzQmFyIiwibW9jayIsImRpc2FibGVBbmltYXRpb25zIiwiZW5hYmxlQW5pbWF0aW9ucyIsIl9kaXNhYmxlV2FybmluZ3MiLCJfZW5hYmxlV2FybmluZ3MiLCJkaXNhYmxlQXV0b1N0eWxpbmciLCJlbmFibGVBdXRvU3R5bGluZyIsImRpc2FibGVJY29uQXV0b1ByZWZpeCIsIkljb24iLCJzZXRBdXRvUHJlZml4IiwiZm9yY2VQbGF0Zm9ybVN0eWxpbmciLCJuZXdQbGF0Zm9ybSIsIl91dGlsIiwiX3BsYXRmb3JtVXBkYXRlIiwiX3VwZGF0ZVBvc2l0aW9uIiwicHJlbG9hZCIsImFsbCIsImFwcGVuZCIsImxpbmsiLCJjcmVhdGVQb3BvdmVyIiwiY3JlYXRlRGlhbG9nIiwiY3JlYXRlQWxlcnREaWFsb2ciLCJvcGVuQWN0aW9uU2hlZXQiLCJyZXNvbHZlTG9hZGluZ1BsYWNlaG9sZGVyIiwiX3Jlc29sdmVMb2FkaW5nUGxhY2Vob2xkZXIiLCJfc2V0dXBMb2FkaW5nUGxhY2VIb2xkZXJzIiwicmVtb3ZlQ2hpbGQiLCJ1bmxvY2tEZXZpY2VSZWFkeSIsImxvY2siLCJnZXRDUyIsImN1cnJlbnRTY3JpcHQiLCJzY3JpcHRzIiwiZ2V0U2NyaXB0UGFnZSIsIkZhc3RDbGljayIsImxheWVyIiwib2xkT25DbGljayIsInRyYWNraW5nQ2xpY2siLCJ0cmFja2luZ0NsaWNrU3RhcnQiLCJ0b3VjaFN0YXJ0WCIsInRvdWNoU3RhcnRZIiwibGFzdFRvdWNoSWRlbnRpZmllciIsInRvdWNoQm91bmRhcnkiLCJ0YXBEZWxheSIsInRhcFRpbWVvdXQiLCJub3ROZWVkZWQiLCJtZXRob2QiLCJtZXRob2RzIiwiZGV2aWNlSXNBbmRyb2lkIiwib25Nb3VzZSIsIm9uQ2xpY2siLCJvblRvdWNoU3RhcnQiLCJvblRvdWNoTW92ZSIsIm9uVG91Y2hFbmQiLCJvblRvdWNoQ2FuY2VsIiwic3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uIiwicm12IiwiaGlqYWNrZWQiLCJhZHYiLCJwcm9wYWdhdGlvblN0b3BwZWQiLCJkZXZpY2VJc1dpbmRvd3NQaG9uZSIsImRldmljZUlzSU9TIiwiZGV2aWNlSXNJT1M0IiwiZGV2aWNlSXNJT1NXaXRoQmFkVGFyZ2V0IiwiZGV2aWNlSXNCbGFja0JlcnJ5MTAiLCJ0ZXh0RmllbGRzIiwibmVlZHNDbGljayIsImRpc2FibGVkIiwibmVlZHNGb2N1cyIsInJlYWRPbmx5Iiwic2VuZENsaWNrIiwiY2xpY2tFdmVudCIsImFjdGl2ZUVsZW1lbnQiLCJibHVyIiwiaW5pdE1vdXNlRXZlbnQiLCJkZXRlcm1pbmVFdmVudFR5cGUiLCJzY3JlZW5YIiwic2NyZWVuWSIsImZvcndhcmRlZFRvdWNoRXZlbnQiLCJ1cGRhdGVTY3JvbGxQYXJlbnQiLCJzY3JvbGxQYXJlbnQiLCJmYXN0Q2xpY2tTY3JvbGxQYXJlbnQiLCJzY3JvbGxIZWlnaHQiLCJmYXN0Q2xpY2tMYXN0U2Nyb2xsVG9wIiwic2Nyb2xsVG9wIiwiZ2V0VGFyZ2V0RWxlbWVudEZyb21FdmVudFRhcmdldCIsImV2ZW50VGFyZ2V0IiwiVEVYVF9OT0RFIiwiaXNUZXh0RmllbGQiLCJ0YXJnZXRUb3VjaGVzIiwiaXNDb250ZW50RWRpdGFibGUiLCJsYXN0Q2xpY2tUaW1lIiwidG91Y2hIYXNNb3ZlZCIsImJvdW5kYXJ5IiwiZmluZENvbnRyb2wiLCJsYWJlbEVsZW1lbnQiLCJjb250cm9sIiwiaHRtbEZvciIsImZvckVsZW1lbnQiLCJ0YXJnZXRUYWdOYW1lIiwiY2FuY2VsTmV4dENsaWNrIiwiZWxlbWVudEZyb21Qb2ludCIsInBhZ2VYT2Zmc2V0IiwicGFnZVlPZmZzZXQiLCJ0b3AiLCJwZXJtaXR0ZWQiLCJtZXRhVmlld3BvcnQiLCJjaHJvbWVWZXJzaW9uIiwiYmxhY2tiZXJyeVZlcnNpb24iLCJmaXJlZm94VmVyc2lvbiIsIm9udG91Y2hzdGFydCIsImV4ZWMiLCJzY3JvbGxXaWR0aCIsIm91dGVyV2lkdGgiLCJtc1RvdWNoQWN0aW9uIiwidG91Y2hBY3Rpb24iLCJhdHRhY2giLCJkZWZpbmUiLCJiYWJlbEhlbHBlcnMudHlwZW9mIiwiYW1kIiwibW9kdWxlIiwiZXhwb3J0cyIsImN1c3RvbUVsZW1lbnRzIiwiZm9yY2VQb2x5ZmlsbCIsImdsb2JhbCIsIl9fZyIsImNvcmUiLCJfX2UiLCJpdCIsImlzT2JqZWN0IiwiVHlwZUVycm9yIiwicmVxdWlyZSQkMCIsImlzIiwicmVxdWlyZSQkMSIsInJlcXVpcmUkJDIiLCJTIiwidmFsIiwidmFsdWVPZiIsImRQIiwiTyIsIlAiLCJBdHRyaWJ1dGVzIiwidG9QcmltaXRpdmUiLCJJRThfRE9NX0RFRklORSIsImJpdG1hcCIsImNyZWF0ZURlc2MiLCJweCIsInJhbmRvbSIsIlNSQyIsIlRPX1NUUklORyIsIiR0b1N0cmluZyIsIlRQTCIsImluc3BlY3RTb3VyY2UiLCJzYWZlIiwiaXNGdW5jdGlvbiIsIlN0cmluZyIsInRoYXQiLCJQUk9UT1RZUEUiLCIkZXhwb3J0Iiwic291cmNlIiwiSVNfRk9SQ0VEIiwiRiIsIklTX0dMT0JBTCIsIkciLCJJU19TVEFUSUMiLCJJU19QUk9UTyIsIklTX0JJTkQiLCJCIiwiZXhwUHJvdG8iLCJvd24iLCJvdXQiLCJleHAiLCJjdHgiLCJyZWRlZmluZSIsIlUiLCJXIiwiUiIsInByb3BlcnR5SXNFbnVtZXJhYmxlIiwiY29mIiwiSU9iamVjdCIsImRlZmluZWQiLCJnT1BEIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwidG9JT2JqZWN0IiwicElFIiwiY2hlY2siLCJwcm90byIsInNldFByb3RvdHlwZU9mIiwiYnVnZ3kiLCJfX3Byb3RvX18iLCJTSEFSRUQiLCJzdG9yZSIsIlN5bWJvbCIsIlVTRV9TWU1CT0wiLCIkZXhwb3J0cyIsInVpZCIsIlRBRyIsIkFSRyIsInRyeUdldCIsIlQiLCJjYWxsZWUiLCJjbGFzc29mIiwiY2VpbCIsInBvcyIsInRvSW50ZWdlciIsIklTX0lOQ0xVREVTIiwiJHRoaXMiLCJmcm9tSW5kZXgiLCJ0b0xlbmd0aCIsInRvQWJzb2x1dGVJbmRleCIsInNoYXJlZCIsImFycmF5SW5kZXhPZiIsIklFX1BST1RPIiwibmFtZXMiLCIka2V5cyIsImVudW1CdWdLZXlzIiwiZGVmaW5lUHJvcGVydGllcyIsIlByb3BlcnRpZXMiLCJnZXRLZXlzIiwiRW1wdHkiLCJjcmVhdGVEaWN0IiwiaWZyYW1lIiwibHQiLCJndCIsImlmcmFtZURvY3VtZW50IiwiY29udGVudFdpbmRvdyIsIndyaXRlIiwiY2xvc2UiLCJhbk9iamVjdCIsImRQcyIsImRlZiIsInRhZyIsInN0YXQiLCJjb25maWd1cmFibGUiLCJJdGVyYXRvclByb3RvdHlwZSIsIkNvbnN0cnVjdG9yIiwiTkFNRSIsIm5leHQiLCJkZXNjcmlwdG9yIiwiT2JqZWN0UHJvdG8iLCJnZXRQcm90b3R5cGVPZiIsInRvT2JqZWN0IiwiY29uc3RydWN0b3IiLCJJVEVSQVRPUiIsIkJVR0dZIiwiRkZfSVRFUkFUT1IiLCJLRVlTIiwiVkFMVUVTIiwicmV0dXJuVGhpcyIsIkJhc2UiLCJERUZBVUxUIiwiSVNfU0VUIiwiRk9SQ0VEIiwiZ2V0TWV0aG9kIiwia2luZCIsInZhbHVlcyIsImVudHJpZXMiLCJERUZfVkFMVUVTIiwiVkFMVUVTX0JVRyIsIiRuYXRpdmUiLCIkZGVmYXVsdCIsIiRlbnRyaWVzIiwiJGFueU5hdGl2ZSIsIkxJQlJBUlkiLCIkYXQiLCJpdGVyYXRlZCIsIl90IiwiX2kiLCJwb2ludCIsIlVOU0NPUEFCTEVTIiwiQXJyYXlQcm90byIsIl9rIiwiSXRlcmF0b3JzIiwiQXJndW1lbnRzIiwiYWRkVG9VbnNjb3BhYmxlcyIsIndrcyIsIlRPX1NUUklOR19UQUciLCJBcnJheVZhbHVlcyIsIkRPTUl0ZXJhYmxlcyIsImNvbGxlY3Rpb25zIiwiZXhwbGljaXQiLCJDb2xsZWN0aW9uIiwiJGl0ZXJhdG9ycyIsImZvcmJpZGRlbkZpZWxkIiwicmV0IiwiZ2V0SXRlcmF0b3JNZXRob2QiLCJCUkVBSyIsIlJFVFVSTiIsIml0ZXJhYmxlIiwiaXRlckZuIiwiZ2V0SXRlckZuIiwiaXNBcnJheUl0ZXIiLCJTUEVDSUVTIiwiS0VZIiwiQyIsIkRFU0NSSVBUT1JTIiwiTUVUQSIsInNldERlc2MiLCJpc0V4dGVuc2libGUiLCJGUkVFWkUiLCJwcmV2ZW50RXh0ZW5zaW9ucyIsInNldE1ldGEiLCJmYXN0S2V5IiwiZ2V0V2VhayIsIm9uRnJlZXplIiwibWV0YSIsIk5FRUQiLCJUWVBFIiwiU0laRSIsImdldEVudHJ5IiwiZW50cnkiLCJfZiIsIm4iLCJJU19NQVAiLCJBRERFUiIsIl9sIiwiZm9yT2YiLCJ2YWxpZGF0ZSIsImRhdGEiLCJjYWxsYmFja2ZuIiwidiIsIlNBRkVfQ0xPU0lORyIsInJpdGVyIiwic2tpcENsb3NpbmciLCJhcnIiLCJpdGVyIiwiY29tbW9uIiwiSVNfV0VBSyIsImZpeE1ldGhvZCIsImZhaWxzIiwiZ2V0Q29uc3RydWN0b3IiLCJpbnN0YW5jZSIsIkhBU05UX0NIQUlOSU5HIiwiVEhST1dTX09OX1BSSU1JVElWRVMiLCJBQ0NFUFRfSVRFUkFCTEVTIiwiJGl0ZXJEZXRlY3QiLCJCVUdHWV9aRVJPIiwiJGluc3RhbmNlIiwiaW5oZXJpdElmUmVxdWlyZWQiLCJzZXRTdHJvbmciLCJTRVQiLCJTZXQiLCJzdHJvbmciLCJ0b0pTT04iLCJDT0xMRUNUSU9OIiwib2YiLCJBIiwibWFwRm4iLCJtYXBwaW5nIiwiYUZ1bmN0aW9uIiwibmV4dEl0ZW0iLCJyZXF1aXJlJCQ3IiwiTUFQIiwiTWFwIiwiYXJnIiwib3JpZ2luYWwiLCJzcGVjaWVzQ29uc3RydWN0b3IiLCIkY3JlYXRlIiwiSVNfRklMVEVSIiwiSVNfU09NRSIsIklTX0VWRVJZIiwiSVNfRklORF9JTkRFWCIsIk5PX0hPTEVTIiwiYXNjIiwicmVzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwiJGFzc2lnbiIsImFzc2lnbiIsIksiLCJhTGVuIiwiZ2V0U3ltYm9scyIsImdPUFMiLCJpc0VudW0iLCJhcnJheUZpbmQiLCJjcmVhdGVBcnJheU1ldGhvZCIsImFycmF5RmluZEluZGV4IiwidW5jYXVnaHRGcm96ZW5TdG9yZSIsIlVuY2F1Z2h0RnJvemVuU3RvcmUiLCJmaW5kVW5jYXVnaHRGcm96ZW4iLCIkaGFzIiwiV0VBS19NQVAiLCJ3ZWFrIiwidWZzdG9yZSIsInRtcCIsIkludGVybmFsTWFwIiwiJFdlYWtNYXAiLCJmcmVlemUiLCJyZXF1aXJlJCQ1IiwiJGRlZmluZVByb3BlcnR5IiwibWFwZm4iLCJyZXNlcnZlZFRhZ0xpc3QiLCJpc1ZhbGlkQ3VzdG9tRWxlbWVudE5hbWUiLCJsb2NhbE5hbWUiLCJyZXNlcnZlZCIsInZhbGlkRm9ybSIsImlzQ29ubmVjdGVkIiwibmF0aXZlVmFsdWUiLCJfX0NFX2lzSW1wb3J0RG9jdW1lbnQiLCJEb2N1bWVudCIsIlNoYWRvd1Jvb3QiLCJob3N0IiwibmV4dFNpYmxpbmdPckFuY2VzdG9yU2libGluZyIsInJvb3QiLCJuZXh0U2libGluZyIsIm5leHROb2RlIiwid2Fsa0RlZXBEZXNjZW5kYW50RWxlbWVudHMiLCJ2aXNpdGVkSW1wb3J0cyIsImltcG9ydCIsInNoYWRvd1Jvb3QiLCJfX0NFX3NoYWRvd1Jvb3QiLCJzZXRQcm9wZXJ0eVVuY2hlY2tlZCIsImRlc3RpbmF0aW9uIiwiQ3VzdG9tRWxlbWVudFN0YXRlIiwiQ3VzdG9tRWxlbWVudEludGVybmFscyIsIl9sb2NhbE5hbWVUb0RlZmluaXRpb24iLCJfY29uc3RydWN0b3JUb0RlZmluaXRpb24iLCJfcGF0Y2hlcyIsIl9oYXNQYXRjaGVzIiwiZGVmaW5pdGlvbiIsInBhdGNoIiwiX19DRV9wYXRjaGVkIiwiX19DRV9zdGF0ZSIsIkNFU3RhdGUiLCJjdXN0b20iLCJVdGlsaXRpZXMiLCJjb25uZWN0ZWRDYWxsYmFjayIsInVwZ3JhZGVFbGVtZW50IiwiZGlzY29ubmVjdGVkQ2FsbGJhY2siLCJnYXRoZXJFbGVtZW50cyIsIl9fQ0VfaGFzUmVnaXN0cnkiLCJfX0NFX2RvY3VtZW50TG9hZEhhbmRsZWQiLCJwYXRjaEFuZFVwZ3JhZGVUcmVlIiwiY3VycmVudFN0YXRlIiwibG9jYWxOYW1lVG9EZWZpbml0aW9uIiwiY29uc3RydWN0aW9uU3RhY2siLCJwb3AiLCJmYWlsZWQiLCJfX0NFX2RlZmluaXRpb24iLCJhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2siLCJvYnNlcnZlZEF0dHJpYnV0ZXMiLCJfX0NFX2lzQ29ubmVjdGVkQ2FsbGJhY2tDYWxsZWQiLCJvbGRWYWx1ZSIsIm5ld1ZhbHVlIiwibmFtZXNwYWNlIiwiRG9jdW1lbnRDb25zdHJ1Y3Rpb25PYnNlcnZlciIsImludGVybmFscyIsImRvYyIsIl9pbnRlcm5hbHMiLCJfZG9jdW1lbnQiLCJfb2JzZXJ2ZXIiLCJfaGFuZGxlTXV0YXRpb25zIiwiZGlzY29ubmVjdCIsIm11dGF0aW9ucyIsImFkZGVkTm9kZXMiLCJEZWZlcnJlZCIsIl92YWx1ZSIsIl9yZXNvbHZlIiwiX3Byb21pc2UiLCJDdXN0b21FbGVtZW50UmVnaXN0cnkiLCJfZWxlbWVudERlZmluaXRpb25Jc1J1bm5pbmciLCJfd2hlbkRlZmluZWREZWZlcnJlZCIsIl9mbHVzaENhbGxiYWNrIiwiX2ZsdXNoUGVuZGluZyIsIl91bmZsdXNoZWRMb2NhbE5hbWVzIiwiX2RvY3VtZW50Q29uc3RydWN0aW9uT2JzZXJ2ZXIiLCJTeW50YXhFcnJvciIsImFkb3B0ZWRDYWxsYmFjayIsImdldENhbGxiYWNrIiwiY2FsbGJhY2tWYWx1ZSIsInNldERlZmluaXRpb24iLCJfZmx1c2giLCJwcmlvciIsInRvUHJvbWlzZSIsIm91dGVyIiwiaW5uZXIiLCJmbHVzaCIsIndoZW5EZWZpbmVkIiwicG9seWZpbGxXcmFwRmx1c2hDYWxsYmFjayIsImNyZWF0ZUVsZW1lbnROUyIsImNsb25lTm9kZSIsImdldEF0dHJpYnV0ZU5TIiwic2V0QXR0cmlidXRlTlMiLCJyZW1vdmVBdHRyaWJ1dGVOUyIsIkFscmVhZHlDb25zdHJ1Y3RlZE1hcmtlciIsImNvbnN0cnVjdG9yVG9EZWZpbml0aW9uIiwiTmF0aXZlIiwiRG9jdW1lbnRfY3JlYXRlRWxlbWVudCIsImxhc3RJbmRleCIsImJ1aWx0SW4iLCJub2RlcyIsImNvbm5lY3RlZEJlZm9yZSIsInByZXBlbmQiLCJkaXNjb25uZWN0VHJlZSIsImNvbm5lY3RUcmVlIiwiY2xvbmUiLCJEb2N1bWVudF9pbXBvcnROb2RlIiwicGF0Y2hUcmVlIiwiTlNfSFRNTCIsIkRvY3VtZW50X2NyZWF0ZUVsZW1lbnROUyIsIkRvY3VtZW50X3ByZXBlbmQiLCJEb2N1bWVudF9hcHBlbmQiLCJyZWZOb2RlIiwiaW5zZXJ0ZWROb2RlcyIsIm5hdGl2ZVJlc3VsdCIsIk5vZGVfaW5zZXJ0QmVmb3JlIiwibm9kZVdhc0Nvbm5lY3RlZCIsIk5vZGVfYXBwZW5kQ2hpbGQiLCJOb2RlX2Nsb25lTm9kZSIsIm93bmVyRG9jdW1lbnQiLCJOb2RlX3JlbW92ZUNoaWxkIiwibm9kZVRvSW5zZXJ0Iiwibm9kZVRvUmVtb3ZlIiwiTm9kZV9yZXBsYWNlQ2hpbGQiLCJub2RlVG9JbnNlcnRXYXNDb25uZWN0ZWQiLCJ0aGlzSXNDb25uZWN0ZWQiLCJwYXRjaF90ZXh0Q29udGVudCIsImJhc2VEZXNjcmlwdG9yIiwiZW51bWVyYWJsZSIsImFzc2lnbmVkVmFsdWUiLCJyZW1vdmVkTm9kZXMiLCJjaGlsZE5vZGVzTGVuZ3RoIiwiTm9kZV90ZXh0Q29udGVudCIsImFkZFBhdGNoIiwicGFydHMiLCJiZWZvcmUiLCJ3YXNDb25uZWN0ZWQiLCJyZXBsYWNlV2l0aCIsIkVsZW1lbnRfYXR0YWNoU2hhZG93IiwiaW5pdCIsInBhdGNoX2lubmVySFRNTCIsImh0bWxTdHJpbmciLCJyZW1vdmVkRWxlbWVudHMiLCJFbGVtZW50X2lubmVySFRNTCIsIkhUTUxFbGVtZW50X2lubmVySFRNTCIsInJhd0RpdiIsIkVsZW1lbnRfc2V0QXR0cmlidXRlIiwiRWxlbWVudF9nZXRBdHRyaWJ1dGUiLCJFbGVtZW50X3NldEF0dHJpYnV0ZU5TIiwiRWxlbWVudF9nZXRBdHRyaWJ1dGVOUyIsIkVsZW1lbnRfcmVtb3ZlQXR0cmlidXRlIiwiRWxlbWVudF9yZW1vdmVBdHRyaWJ1dGVOUyIsInBhdGNoX2luc2VydEFkamFjZW50RWxlbWVudCIsImJhc2VNZXRob2QiLCJ3aGVyZSIsImluc2VydGVkRWxlbWVudCIsIkhUTUxFbGVtZW50X2luc2VydEFkamFjZW50RWxlbWVudCIsIkVsZW1lbnRfaW5zZXJ0QWRqYWNlbnRFbGVtZW50IiwiRWxlbWVudF9wcmVwZW5kIiwiRWxlbWVudF9hcHBlbmQiLCJFbGVtZW50X2JlZm9yZSIsIkVsZW1lbnRfYWZ0ZXIiLCJFbGVtZW50X3JlcGxhY2VXaXRoIiwiRWxlbWVudF9yZW1vdmUiLCJwcmlvckN1c3RvbUVsZW1lbnRzIiwiSnNNdXRhdGlvbk9ic2VydmVyIiwicmVnaXN0cmF0aW9uc1RhYmxlIiwic2V0SW1tZWRpYXRlIiwic2V0SW1tZWRpYXRlUXVldWUiLCJzZW50aW5lbCIsImZ1bmMiLCJwb3N0TWVzc2FnZSIsImlzU2NoZWR1bGVkIiwic2NoZWR1bGVkT2JzZXJ2ZXJzIiwic2NoZWR1bGVDYWxsYmFjayIsImRpc3BhdGNoQ2FsbGJhY2tzIiwid3JhcElmTmVlZGVkIiwiU2hhZG93RE9NUG9seWZpbGwiLCJvYnNlcnZlcnMiLCJvMSIsIm8yIiwidWlkXyIsImFueU5vbkVtcHR5IiwidGFrZVJlY29yZHMiLCJjYWxsYmFja18iLCJyZW1vdmVUcmFuc2llbnRPYnNlcnZlcnNGb3IiLCJub2Rlc18iLCJyZWdpc3RyYXRpb25zIiwicmVnaXN0cmF0aW9uIiwicmVtb3ZlVHJhbnNpZW50T2JzZXJ2ZXJzIiwiZm9yRWFjaEFuY2VzdG9yQW5kT2JzZXJ2ZXJFbnF1ZXVlUmVjb3JkIiwic3VidHJlZSIsInJlY29yZCIsImVucXVldWUiLCJ1aWRDb3VudGVyIiwicmVjb3Jkc18iLCJhdHRyaWJ1dGVzIiwiYXR0cmlidXRlT2xkVmFsdWUiLCJhdHRyaWJ1dGVGaWx0ZXIiLCJjaGFyYWN0ZXJEYXRhT2xkVmFsdWUiLCJSZWdpc3RyYXRpb24iLCJhZGRMaXN0ZW5lcnMiLCJjb3B5T2ZSZWNvcmRzIiwiTXV0YXRpb25SZWNvcmQiLCJwcmV2aW91c1NpYmxpbmciLCJhdHRyaWJ1dGVOYW1lIiwiYXR0cmlidXRlTmFtZXNwYWNlIiwiY29weU11dGF0aW9uUmVjb3JkIiwiY3VycmVudFJlY29yZCIsInJlY29yZFdpdGhPbGRWYWx1ZSIsImdldFJlY29yZCIsImdldFJlY29yZFdpdGhPbGRWYWx1ZSIsImNsZWFyUmVjb3JkcyIsInJlY29yZFJlcHJlc2VudHNDdXJyZW50TXV0YXRpb24iLCJzZWxlY3RSZWNvcmQiLCJsYXN0UmVjb3JkIiwibmV3UmVjb3JkIiwidHJhbnNpZW50T2JzZXJ2ZWROb2RlcyIsInJlY29yZHMiLCJyZWNvcmRUb1JlcGxhY2VMYXN0IiwiYWRkTGlzdGVuZXJzXyIsInJlbW92ZUxpc3RlbmVyc18iLCJhdHRyTmFtZSIsInJlbGF0ZWROb2RlIiwibmFtZXNwYWNlVVJJIiwiYXR0ckNoYW5nZSIsIk11dGF0aW9uRXZlbnQiLCJBRERJVElPTiIsInByZXZWYWx1ZSIsImFkZFRyYW5zaWVudE9ic2VydmVyIiwiY2hhbmdlZE5vZGUiLCJfaXNQb2x5ZmlsbGVkIiwibmV4dEhhbmRsZSIsInRhc2tzQnlIYW5kbGUiLCJjdXJyZW50bHlSdW5uaW5nQVRhc2siLCJhZGRGcm9tU2V0SW1tZWRpYXRlQXJndW1lbnRzIiwicGFydGlhbGx5QXBwbGllZCIsInJ1bklmUHJlc2VudCIsImhhbmRsZSIsInRhc2siLCJjbGVhckltbWVkaWF0ZSIsImluc3RhbGxOZXh0VGlja0ltcGxlbWVudGF0aW9uIiwibmV4dFRpY2siLCJjYW5Vc2VQb3N0TWVzc2FnZSIsImltcG9ydFNjcmlwdHMiLCJwb3N0TWVzc2FnZUlzQXN5bmNocm9ub3VzIiwib2xkT25NZXNzYWdlIiwib25tZXNzYWdlIiwiaW5zdGFsbFBvc3RNZXNzYWdlSW1wbGVtZW50YXRpb24iLCJtZXNzYWdlUHJlZml4Iiwib25HbG9iYWxNZXNzYWdlIiwiYXR0YWNoRXZlbnQiLCJpbnN0YWxsTWVzc2FnZUNoYW5uZWxJbXBsZW1lbnRhdGlvbiIsImNoYW5uZWwiLCJNZXNzYWdlQ2hhbm5lbCIsInBvcnQxIiwicG9ydDIiLCJpbnN0YWxsUmVhZHlTdGF0ZUNoYW5nZUltcGxlbWVudGF0aW9uIiwib25yZWFkeXN0YXRlY2hhbmdlIiwiaW5zdGFsbFNldFRpbWVvdXRJbXBsZW1lbnRhdGlvbiIsImF0dGFjaFRvIiwicHJvY2VzcyIsIkRFRkFVTFRfVklFV1BPUlQiLCJWaWV3cG9ydCIsInZpZXdwb3J0RWxlbWVudCIsImhlYWQiLCJlbnN1cmVWaWV3cG9ydEVsZW1lbnQiLCJfb25zTG9hZGVkIiwiZmFzdENsaWNrIiwic3VwcG9ydFRvdWNoQWN0aW9uIiwiX2ludGVybmFsIiwiY3JlYXRlSGFuZGxlciIsImFwcCIsImV4aXRBcHAiLCJfZ2VzdHVyZURldGVjdG9yIiwiZ2V0RWxlbWVudENsYXNzIiwiQmFzZUVsZW1lbnQiLCJUZW1wbGF0ZUVsZW1lbnQiLCJvdXRlckhUTUwiLCJidWJibGVzIiwiVGVtcGxhdGUiLCJJZkVsZW1lbnQiLCJfaXNBbGxvd2VkUGxhdGZvcm0iLCJjb25kaXRpb25hbE9yaWVudGF0aW9uIiwiY3VycmVudE9yaWVudGF0aW9uIiwiSWYiLCJCYXNlQW5pbWF0b3IiLCJwcm9wZXJ0aWVzIiwiZXh0ZW5kZWRBbmltYXRvciIsIm5ld0FuaW1hdG9yIiwiaVBob25lWFBhdGNoIiwiaXNJUGhvbmVYUG9ydHJhaXRQYXRjaEFjdGl2ZSIsImlzSVBob25lWExhbmRzY2FwZVBhdGNoQWN0aXZlIiwiZ2V0U2FmZUFyZWFMZW5ndGhzIiwic2FmZUFyZWFMZW5ndGhzIiwiZ2V0U2FmZUFyZWFET01SZWN0Iiwic2FmZUFyZWFSZWN0IiwiQWN0aW9uU2hlZXRBbmltYXRvciIsIk1EQWN0aW9uU2hlZXRBbmltYXRvciIsIm1hc2tUaW1pbmciLCJtYXNrRHVyYXRpb24iLCJhbmltaXQiLCJfbWFzayIsIm9wYWNpdHkiLCJfc2hlZXQiLCJkZWZhdWx0IiwidHJhbnNmb3JtIiwiSU9TQWN0aW9uU2hlZXRBbmltYXRvciIsImxpZnRBbW91bnQiLCJjbGllbnRIZWlnaHQiLCJCYXNlRGlhbG9nRWxlbWVudCIsInNob3VsZFNob3ciLCJfZG9vckxvY2siLCJfY2FuY2VsIiwiX3NlbGZDYW1lbE5hbWUiLCJfZGVmYXVsdERCQiIsImNhbGxQYXJlbnRIYW5kbGVyIiwiX2FuaW1hdG9yRmFjdG9yeSIsIl91cGRhdGVBbmltYXRvckZhY3RvcnkiLCJfcnVubmluZyIsIl9zZXRWaXNpYmxlIiwicGFyc2VBbmltYXRpb25PcHRpb25zU3RyaW5nIiwiY2FuY2VsZWQiLCJfdG9nZ2xlU3R5bGUiLCJiYWNrZ3JvdW5kQ29sb3IiLCJvbkRldmljZUJhY2tCdXR0b24iLCJfYmFja0J1dHRvbkhhbmRsZXIiLCJvbk1vZGlmaWVyQ2hhbmdlZCIsIl9zY2hlbWUiLCJfdXBkYXRlTWFzayIsIl9hbmltYXRvckRpY3QiLCJBY3Rpb25TaGVldEVsZW1lbnQiLCJfY29tcGlsZSIsInNoZWV0IiwiX3RpdGxlIiwibWFzayIsImluaXRNb2RpZmllciIsIl91cGRhdGVUaXRsZSIsIkFjdGlvblNoZWV0IiwiQmFzZUJ1dHRvbkVsZW1lbnQiLCJfZGVmYXVsdENsYXNzTmFtZSIsIl9pY29uIiwiX3VwZGF0ZVJpcHBsZSIsIl9yaXBwbGVPcHQiLCJfdXBkYXRlSWNvbiIsIkFjdGlvblNoZWV0QnV0dG9uRWxlbWVudCIsIkFjdGlvblNoZWV0QnV0dG9uIiwiQWxlcnREaWFsb2dBbmltYXRvciIsIkFuZHJvaWRBbGVydERpYWxvZ0FuaW1hdG9yIiwiX2RpYWxvZyIsIklPU0FsZXJ0RGlhbG9nQW5pbWF0b3IiLCJBbGVydERpYWxvZ0VsZW1lbnQiLCJBbGVydERpYWxvZyIsIkFsZXJ0RGlhbG9nQnV0dG9uRWxlbWVudCIsIkFsZXJ0RGlhbG9nQnV0dG9uIiwiZGVmYXVsdENsYXNzTmFtZSIsIkJhY2tCdXR0b25FbGVtZW50IiwiX29wdGlvbnMiLCJfYm91bmRPbkNsaWNrIiwiX29uQ2xpY2siLCJtZEJhY2tCdXR0b25JY29uIiwiaW9zQmFja0J1dHRvbkljb24iLCJwb3BQYWdlIiwiQmFja0J1dHRvbiIsIkJvdHRvbVRvb2xiYXJFbGVtZW50IiwiQm90dG9tVG9vbGJhciIsIkJ1dHRvbkVsZW1lbnQiLCJCdXR0b24iLCJDYXJkRWxlbWVudCIsIkNhcmQiLCJDYXJvdXNlbEl0ZW1FbGVtZW50IiwiQ2Fyb3VzZWxJdGVtIiwiZGlyZWN0aW9uTWFwIiwiU3dpcGVyIiwiRkFMU0UiLCJnZXRFbGVtZW50Iiwic2Nyb2xsSG9vayIsIml0ZW1TaXplIiwiZ2V0QXV0b1Njcm9sbFJhdGlvIiwicmF0aW8iLCJzaG91bGRCbG9jayIsIm9uRHJhZ1N0YXJ0Iiwib25EcmFnIiwib25EcmFnRW5kIiwib25SZXNpemUiLCJfc2hvdWxkRml4U2Nyb2xsIiwic3dpcGVhYmxlIiwiYXV0b1JlZnJlc2giLCJpbml0aWFsaXplZCIsImJsb2NrZXIiLCJfbXV0YXRpb25PYnNlcnZlciIsInVwZGF0ZVN3aXBlYWJsZSIsInVwZGF0ZUF1dG9SZWZyZXNoIiwiX3Njcm9sbCIsIl9vZmZzZXQiLCJfbGFzdEFjdGl2ZUluZGV4IiwiX3VwZGF0ZUxheW91dCIsIl9zZXR1cEluaXRpYWxJbmRleCIsInNldHVwUmVzaXplIiwidGFyZ2V0U2l6ZSIsIl9yZXNldCIsInNldEFjdGl2ZUluZGV4Iiwicm91bmQiLCJOdW1iZXIiLCJnZXRJbml0aWFsSW5kZXgiLCJpdGVtQ291bnQiLCJpdGVtTnVtU2l6ZSIsIl9zY3JvbGxUbyIsIl9zZXRTd2lwaW5nIiwic2Nyb2xsIiwibWF4U2Nyb2xsIiwiYXJyYXlPZkFycmF5IiwiY29udGVudHMiLCJfY2hhbmdlVG8iLCJjb3VudCIsInNpemUiLCJzaG91bGRVcGRhdGUiLCJzaG91bGRXYXRjaCIsIm5ld1NpemUiLCJibG9jayIsInBvaW50ZXJFdmVudHMiLCJpc0ZpcnN0IiwiaXNPdmVyU2Nyb2xsYWJsZSIsImlzTGFzdCIsIl9pZ25vcmVEcmFnIiwiY29uc3VtZWQiLCJjb25zdW1lIiwiX2NhbkNvbnN1bWVHZXN0dXJlIiwic3RhcnRYIiwiZGlzdEZyb21FZGdlIiwiZ2V0QnViYmxlV2lkdGgiLCJfc3RhcnRlZCIsInRvZ2dsZUJsb2NrZXIiLCJfY29udGludWVkIiwiX2dldERlbHRhIiwidGhyb3R0bGUiLCJub3JtYWxpemVkU2Nyb2xsIiwiX25vcm1hbGl6ZVNjcm9sbCIsIl9zdGFydE1vbWVudHVtU2Nyb2xsIiwiX2tpbGxPdmVyU2Nyb2xsIiwiX2dldFZlbG9jaXR5IiwibWF0Y2hlc0RpcmVjdGlvbiIsImRNIiwiZGlyIiwibmV4dFNjcm9sbCIsIl9nZXRBdXRvU2Nyb2xsIiwic3dpcGUiLCJraWxsT3ZlclNjcm9sbCIsIm92ZXJTY3JvbGxIb29rIiwiYWN0aXZlSW5kZXgiLCJnZXRBY3RpdmVJbmRleCIsImxhc3RBY3RpdmVJbmRleCIsImNoYW5nZSIsInByZUNoYW5nZUhvb2siLCJwb3N0Q2hhbmdlSG9vayIsInRvRml4ZWQiLCJfZ2V0VHJhbnNmb3JtIiwib2Zmc2V0IiwiaXNBdXRvU2Nyb2xsYWJsZSIsImxhc3RTY3JvbGwiLCJzY3JvbGxSYXRpbyIsIl90YXJnZXRTaXplIiwiX2l0ZW1OdW1TaXplIiwicmVmcmVzaEhvb2siLCJheGlzIiwidDNkIiwibmV4dEVsZW1lbnRTaWJsaW5nIiwiaXNDZW50ZXJlZCIsIl9jYWxjdWxhdGVJdGVtU2l6ZSIsIkNhcm91c2VsRWxlbWVudCIsIl9zd2lwZXIiLCJhdXRvU2Nyb2xsUmF0aW8iLCJ2ZXJ0aWNhbCIsIm92ZXJzY3JvbGxhYmxlIiwiY2VudGVyZWQiLCJhdXRvU2Nyb2xsIiwiX29uT3ZlclNjcm9sbCIsIl9vbkNoYW5nZSIsIl9vblJlZnJlc2giLCJfb25Td2lwZSIsInVwZGF0ZUl0ZW1TaXplIiwid2FpdEZvckFjdGlvbiIsImNhcm91c2VsIiwiaXRlbVNpemVBdHRyIiwicGFyc2VGbG9hdCIsIkNhcm91c2VsIiwiQ29sRWxlbWVudCIsIl91cGRhdGVXaWR0aCIsIkNvbCIsIkRpYWxvZ0FuaW1hdG9yIiwiQW5kcm9pZERpYWxvZ0FuaW1hdG9yIiwiSU9TRGlhbG9nQW5pbWF0b3IiLCJib2R5SGVpZ2h0IiwiU2xpZGVEaWFsb2dBbmltYXRvciIsIkRpYWxvZ0VsZW1lbnQiLCJEaWFsb2ciLCJGYWJFbGVtZW50IiwiX2hpZGUiLCJfc2hvdyIsIl9tYW51YWxseUhpZGRlbiIsIl90b2dnbGUiLCJpc0JvdHRvbSIsInRyYW5zbGF0ZSIsImZhYk9mZnNldCIsIkZhYiIsIkdlc3R1cmVEZXRlY3RvckVsZW1lbnQiLCJhdXRvUHJlZml4IiwiSWNvbkVsZW1lbnQiLCJfY2xlYW5DbGFzc0F0dHJpYnV0ZSIsIl91cGRhdGUiLCJfYnVpbGRDbGFzc0FuZFN0eWxlIiwiX3BhcnNlQXR0ciIsImF0dHIiLCJtZCIsImxhc3RJY29uIiwibGFzdE1vZGlmaWVyIiwiX3ByZWZpeEljb24iLCJjdXN0b21QcmVmaXhSRSIsImljb25OYW1lIiwicmVtb3ZlUHJvcGVydHkiLCJmb250U2l6ZSIsIkxhenlSZXBlYXREZWxlZ2F0ZSIsInVzZXJEZWxlZ2F0ZSIsInRlbXBsYXRlRWxlbWVudCIsIl91c2VyRGVsZWdhdGUiLCJfdGVtcGxhdGVFbGVtZW50IiwiX3JlbmRlciIsImxvYWRJdGVtRWxlbWVudCIsImNyZWF0ZUl0ZW1Db250ZW50IiwiY291bnRJdGVtcyIsInVwZGF0ZUl0ZW1Db250ZW50IiwiY2FsY3VsYXRlSXRlbUhlaWdodCIsImRlc3Ryb3lJdGVtIiwiaXRlbUhlaWdodCIsIkxhenlSZXBlYXRQcm92aWRlciIsIndyYXBwZXJFbGVtZW50IiwiZGVsZWdhdGUiLCJfd3JhcHBlckVsZW1lbnQiLCJfZGVsZWdhdGUiLCJfaW5zZXJ0SW5kZXgiLCJfcGFnZUNvbnRlbnQiLCJfZmluZFBhZ2VDb250ZW50RWxlbWVudCIsImxhc3RTY3JvbGxUb3AiLCJwYWRkaW5nIiwiX3RvcFBvc2l0aW9ucyIsIl9yZW5kZXJlZEl0ZW1zIiwiX3Vua25vd25JdGVtSGVpZ2h0IiwiX2FkZEV2ZW50TGlzdGVuZXJzIiwicGFnZUNvbnRlbnQiLCJfaXRlbUhlaWdodCIsInZpc2liaWxpdHkiLCJzdGF0aWNJdGVtSGVpZ2h0IiwiX2dldEl0ZW1IZWlnaHQiLCJmb3JjZVJlbmRlciIsImZvcmNlU2Nyb2xsRG93biIsImZpcnN0SXRlbUluZGV4IiwiX2ZpcnN0SXRlbVJlbmRlcmVkIiwiX2NhbGN1bGF0ZVJlbmRlcmVkSGVpZ2h0IiwiZm9yY2VGaXJzdEluZGV4IiwiX3JlbW92ZUFsbEVsZW1lbnRzIiwiZm9yY2VMYXN0SW5kZXgiLCJfY2hlY2tJdGVtSGVpZ2h0IiwiaXNTY3JvbGxVcCIsImtlZXAiLCJnZXRCb3VuZGluZ0NsaWVudFJlY3QiLCJfY291bnRJdGVtcyIsIl9jYWxjdWxhdGVTdGFydEluZGV4IiwiaGFzUmVuZGVyRnVuY3Rpb24iLCJfcmVuZGVyRWxlbWVudCIsIl9yZW1vdmVFbGVtZW50IiwidXBkYXRlSXRlbSIsImxhc3RJdGVtSW5kZXgiLCJfbGFzdEl0ZW1SZW5kZXJlZCIsIl9yZWNhbGN1bGF0ZVRvcFBvc2l0aW9ucyIsIm1pZGRsZSIsImltbWVkaWF0ZSIsImNhbGxOb3ciLCJfZGVib3VuY2UiLCJfYm91bmRPbkNoYW5nZSIsIl9ib3VuZERvdWJsZUZpcmVPblRvdWNoZW5kIiwiX3BhcmVudEVsZW1lbnQiLCJfcmVtb3ZlRXZlbnRMaXN0ZW5lcnMiLCJwYWRkaW5nVG9wIiwiTGF6eVJlcGVhdEVsZW1lbnQiLCJfbGF6eVJlcGVhdFByb3ZpZGVyIiwiTGF6eVJlcGVhdCIsIkxpc3RIZWFkZXJFbGVtZW50IiwiTGlzdEhlYWRlciIsIkxpc3RUaXRsZUVsZW1lbnQiLCJMaXN0VGl0bGUiLCJMaXN0SXRlbUFuaW1hdG9yIiwibGlzdEl0ZW0iLCJTbGlkZUxpc3RJdGVtQW5pbWF0b3IiLCJfYW5pbWF0ZUV4cGFuc2lvbiIsInNob3VsZE9wZW4iLCJvbGRIZWlnaHQiLCJleHBhbmRhYmxlQ29udGVudCIsIm9sZERpc3BsYXkiLCJjb21wdXRlZFN0eWxlIiwiZXhwYW5zaW9uT3BlblRyYW5zaXRpb24iLCJwYWRkaW5nQm90dG9tIiwiaWNvbk9wZW5UcmFuc2l0aW9uIiwicmV2ZXJzZSIsImV4cGFuZENoZXZyb24iLCJMaXN0SXRlbUVsZW1lbnQiLCJ0b2dnbGVFeHBhbnNpb24iLCJfc2hvdWxkSWdub3JlVGFwIiwic2hvd0V4cGFuc2lvbiIsImhpZGVFeHBhbnNpb24iLCJ0b3BDb250ZW50IiwiY2VudGVyQ29udGVudCIsIl90b3AiLCJjaGV2cm9uIiwiX2V4cGFuZGluZyIsImV4cGFuZGVkIiwiX3NldHVwTGlzdGVuZXJzIiwiX29yaWdpbmFsQmFja2dyb3VuZENvbG9yIiwidGFwcGVkIiwiX29uVG91Y2giLCJfb25SZWxlYXNlIiwiX29uRHJhZyIsInRvdWNoU3R5bGUiLCJib3hTaGFkb3ciLCJMaXN0SXRlbSIsIkxpc3RFbGVtZW50IiwiTGlzdCIsIklOUFVUX0FUVFJJQlVURVMiLCJCYXNlSW5wdXRFbGVtZW50IiwiX2JvdW5kRGVsZWdhdGVFdmVudCIsIl9kZWxlZ2F0ZUV2ZW50IiwiX3RlbXBsYXRlIiwiX3NldElucHV0SWQiLCJfdXBkYXRlQm91bmRBdHRyaWJ1dGVzIiwiX2lucHV0IiwidG9JU09TdHJpbmciLCJJbnB1dEVsZW1lbnQiLCJfYm91bmRPbklucHV0IiwiX2JvdW5kT25Gb2N1c2luIiwiX3VwZGF0ZUxhYmVsIiwiX3VwZGF0ZUxhYmVsQ2xhc3MiLCJfaGVscGVyIiwiaW5uZXJUZXh0IiwiSW5wdXQiLCJCYXNlQ2hlY2tib3hFbGVtZW50IiwiY2hlY2tlZCIsIkNoZWNrYm94RWxlbWVudCIsIkNoZWNrYm94IiwiUmFkaW9FbGVtZW50IiwiUmFkaW8iLCJTZWFyY2hJbnB1dEVsZW1lbnQiLCJTZWFyY2hJbnB1dCIsIk1vZGFsQW5pbWF0b3IiLCJtb2RhbCIsIkZhZGVNb2RhbEFuaW1hdG9yIiwiTGlmdE1vZGFsQW5pbWF0b3IiLCJNb2RhbEVsZW1lbnQiLCJNb2RhbCIsIndpZHRoVG9QeCIsIm9mZnNldFdpZHRoIiwiU3dpcGVSZXZlYWwiLCJlbGVtZW50SGFuZGxlciIsImdldFRocmVzaG9sZCIsImdldFNpZGUiLCJoYW5kbGVHZXN0dXJlIiwiZ2VzdHVyZURldGVjdG9yIiwiaWdub3JlU3dpcGUiLCJfd2lkdGgiLCJfc3RhcnREaXN0YW5jZSIsIl9kaXN0YW5jZSIsImlzSW5pdGlhbFN0YXRlIiwiZGVsdGEiLCJzd2lwZU1pZCIsImlzU3dpcGVNYXgiLCJzd2lwZU1heCIsInN3aXBlTWluIiwiTmF2aWdhdG9yQW5pbWF0b3IiLCJlbnRlclBhZ2UiLCJsZWF2ZVBhZ2UiLCJJT1NTd2lwZU5hdmlnYXRvckFuaW1hdG9yIiwiZHVyYXRpb25SZXN0b3JlIiwiZHVyYXRpb25Td2lwZSIsInRpbWluZ1N3aXBlIiwicmVzdCIsIm9wdFN3aXBlIiwib3B0UmVzdG9yZSIsInN3aXBlU2hhZG93IiwiaXNEcmFnU3RhcnQiLCJ1bmJsb2NrIiwiYmFja2dyb3VuZE1hc2siLCJkZWNvbXAiLCJfZGVjb21wb3NlIiwiZW50ZXIiLCJsZWF2ZSIsIl9jYWxjdWxhdGVEZWx0YSIsInNob3VsZEFuaW1hdGVUb29sYmFyIiwiX3Nob3VsZEFuaW1hdGVUb29sYmFyIiwidG9vbGJhciIsIl9zYXZlU3R5bGUiLCJvdmVyZmxvd0VsZW1lbnQiLCJtYXhXaWR0aCIsImlzU3dpcGluZyIsIl9kcmFnU3RhcnRTZXR1cCIsInN3aXBlUmF0aW8iLCJib3R0b21Ub29sYmFyIiwiYmFja2dyb3VuZCIsInRvb2xiYXJDZW50ZXIiLCJiYWNrQnV0dG9uTGFiZWwiLCJvdGhlciIsIl9zYXZlZFN0eWxlIiwic2F2ZSIsInJlc3RvcmUiLCJfcmVzdG9yZVN0eWxlIiwidHJhbnNsYXRlM2QiLCJJT1NTbGlkZU5hdmlnYXRvckFuaW1hdG9yIiwiX2dldFRvb2xiYXJFbGVtZW50IiwiX2dldFRvb2xiYXJMZWZ0SXRlbXNFbGVtZW50IiwiX2dldFRvb2xiYXJSaWdodEl0ZW1zRWxlbWVudCIsImV4Y2x1ZGVCYWNrQnV0dG9uIiwiX2dldFRvb2xiYXJDZW50ZXJJdGVtc0VsZW1lbnQiLCJfZ2V0VG9vbGJhckJhY2tCdXR0b25JY29uRWxlbWVudCIsIl9nZXRUb29sYmFyQmFja0J1dHRvbkxhYmVsRWxlbWVudCIsIl9nZXRDb250ZW50RWxlbWVudCIsIl9nZXRCYWNrZ3JvdW5kRWxlbWVudCIsIl9nZXRCb3R0b21Ub29sYmFyRWxlbWVudCIsInRvb2xiYXJzIiwiZW50ZXJUb29sYmFyIiwibGVhdmVUb29sYmFyIiwiaXNTdGF0aWMiLCJpc01hdGVyaWFsIiwiaXNUcmFuc3BhcmVudCIsImRlY29tcG9zaXRpb24iLCJwYWdlUmVjdCIsImxhYmVsUmVjdCIsImJhY2tCdXR0b25JY29uIiwiZW50ZXJQYWdlVGFyZ2V0IiwibGVhdmVQYWdlVGFyZ2V0IiwiZW50ZXJQYWdlRGVjb21wb3NpdGlvbiIsImxlYXZlUGFnZURlY29tcG9zaXRpb24iLCJwb3BTd2lwZSIsIklPU0xpZnROYXZpZ2F0b3JBbmltYXRvciIsIklPU0ZhZGVOYXZpZ2F0b3JBbmltYXRvciIsIk1EU2xpZGVOYXZpZ2F0b3JBbmltYXRvciIsImJsYWNrTWFza09wYWNpdHkiLCJNRExpZnROYXZpZ2F0b3JBbmltYXRvciIsIm1hc2tDbGVhciIsIk1ERmFkZU5hdmlnYXRvckFuaW1hdG9yIiwidGltaW5nUG9wIiwiTm9uZU5hdmlnYXRvckFuaW1hdG9yIiwicmV3cml0YWJsZXMiLCJuYXZpZ2F0b3JFbGVtZW50IiwidmVyaWZ5UGFnZUVsZW1lbnQiLCJOYXZpZ2F0b3JFbGVtZW50IiwiX2lzUnVubmluZyIsIl9pbml0aWFsaXplZCIsIl9wYWdlTG9hZGVyIiwiX3BhZ2VNYXAiLCJfcGFnZSIsIl9vbkRldmljZUJhY2tCdXR0b24iLCJzd2lwZUFuaW1hdG9yIiwiX3N3aXBlIiwicHJldmlvdXNFbGVtZW50U2libGluZyIsImFyZWEiLCJpc0JCIiwicHVzaGVkT3B0aW9ucyIsImFuaW1hdG9yRmFjdG9yeSIsImxvYWRlZCIsIl9nZXRQYWdlVGFyZ2V0IiwicHVzaFBhZ2UiLCJfdXBkYXRlTGFzdFBhZ2VCYWNrQnV0dG9uIiwidXBkYXRlIiwiX3ByZXBhcmVQYWdlQW5kT3B0aW9ucyIsInRpbWVzIiwiX3JlbW92ZVBhZ2VzIiwicG9wVXBkYXRlIiwidW5sb2FkIiwiX3BvcFBhZ2UiLCJfZW1pdFByZVBvcEV2ZW50IiwidXBkYXRlQmFja0J1dHRvbiIsInBhZ2VIVE1MIiwiX3B1c2hQYWdlIiwibG9hZCIsIl9lbWl0UHJlUHVzaEV2ZW50IiwicGFnZUxlbmd0aCIsIl9yZXBsYWNlUGFnZSIsInJlc29sdmVkVmFsdWUiLCJfbm9ybWFsaXplSW5kZXgiLCJpbnNlcnRQYWdlIiwibmV3UGFnZSIsIl9sYXN0SW5kZXhPZlBhZ2UiLCJwYWdlTmFtZSIsImlzQ2FuY2VsZWQiLCJfZW1pdFByZUV2ZW50IiwidGVtcGxhdGVIVE1MIiwicGFnZUxvYWRlciIsImxhc3RFbGVtZW50Q2hpbGQiLCJOYXZpZ2F0b3IiLCJUb29sYmFyRWxlbWVudCIsInNpYmxpbmdCYWNrZ3JvdW5kIiwic2libGluZ0NvbnRlbnQiLCJzZXRWaXNpYmlsaXR5IiwiX2Vuc3VyZVRvb2xiYXJJdGVtRWxlbWVudHMiLCJfZW5zdXJlVG9vbGJhckVsZW1lbnQiLCJUb29sYmFyIiwiUGFnZUVsZW1lbnQiLCJfZGVyaXZlSG9va3MiLCJfYmFja2dyb3VuZEVsZW1lbnQiLCJfZWxlbWVudFNob3VsZEJlTW92ZWQiLCJfdHJ5VG9GaWxsU3RhdHVzQmFyIiwiZml4ZWRFbGVtZW50cyIsIm9uSW5pdCIsImJhY2tCdXR0b24iLCJvdmVyTGltaXQiLCJfaW5maW5pdGVTY3JvbGxMaW1pdCIsIl9vbkluZmluaXRlU2Nyb2xsIiwiX2xvYWRpbmdDb250ZW50Iiwib25JbmZpbml0ZVNjcm9sbCIsIm9uRGVzdHJveSIsImV2ZW50cyIsIl9ib3VuZE9uU2Nyb2xsIiwiX29uU2Nyb2xsIiwiUGFnZSIsIlBvcG92ZXJBbmltYXRvciIsInBvcG92ZXIiLCJhbmltYXRpb25zIiwiX2FuaW1hdGUiLCJmYWRlIiwiTURGYWRlUG9wb3ZlckFuaW1hdG9yIiwiX2FuaW1hdGVBbGwiLCJpbiIsIklPU0ZhZGVQb3BvdmVyQW5pbWF0b3IiLCJwb3NpdGlvbnMiLCJQb3BvdmVyRWxlbWVudCIsIl9jdXJyZW50VGFyZ2V0IiwiX3Bvc2l0aW9uUG9wb3ZlciIsIl9jbGVhclN0eWxlcyIsInJhZGl1cyIsIl9yYWRpdXMiLCJjb250ZW50RWxlbWVudCIsIl9jb250ZW50IiwibWFyZ2luIiwiX21hcmdpbiIsInRhcmdldFJlY3QiLCJpc01EIiwiY292ZXIiLCJwYXJlbnREaW1lbnNpb25zIiwibWF4UG9zaXRpb25zIiwiYm90dG9tIiwidGFyZ2V0RGlzdGFuY2UiLCJ0YXJnZXRDZW50ZXJEaXN0YW5jZUZyb20iLCJfY2FsY3VsYXRlRGlyZWN0aW9ucyIsInByaW1hcnlEaXJlY3Rpb24iLCJwcmltYXJ5Iiwic2Vjb25kYXJ5RGlyZWN0aW9uIiwic2Vjb25kYXJ5IiwiX2N1cnJlbnREaXJlY3Rpb24iLCJzaXplTmFtZSIsImNvbnRlbnRTaXplIiwidGFyZ2V0QW5kQXJyb3dMZW5ndGgiLCJwcmltYXJ5T2Zmc2V0Iiwic2Vjb25kYXJ5T2Zmc2V0IiwiX3BvcG92ZXIiLCJfYXJyb3ciLCJoYXNEZWZhdWx0Q29udGFpbmVyIiwiYXJyb3ciLCJQb3BvdmVyIiwiSU5ERVQiLCJQcm9ncmVzc0JhckVsZW1lbnQiLCJfaXNDb21waWxlZCIsIl9wcmltYXJ5IiwiX3NlY29uZGFyeSIsIl91cGRhdGVEZXRlcm1pbmF0ZSIsIl91cGRhdGVWYWx1ZSIsImJhckVsZW1lbnQiLCJQcm9ncmVzc0JhciIsIlByb2dyZXNzQ2lyY3VsYXJFbGVtZW50IiwicGVyIiwic3ZnIiwiUHJvZ3Jlc3NDaXJjdWxhciIsIlNUQVRFX0lOSVRJQUwiLCJTVEFURV9QUkVBQ1RJT04iLCJTVEFURV9BQ1RJT04iLCJ0aHJvd1R5cGUiLCJQdWxsSG9va0VsZW1lbnQiLCJfb25EcmFnU3RhcnQiLCJfb25EcmFnRW5kIiwiX3NldFN0YXRlIiwibGluZUhlaWdodCIsIl9wYWdlRWxlbWVudCIsInRhcFkiLCJtYXhZIiwiZHJhZ2dhYmxlQXJlYVJhdGlvIiwiX3N0YXJ0U2Nyb2xsIiwiX2N1cnJlbnRUcmFuc2xhdGlvbiIsInRoIiwidGhyZXNob2xkSGVpZ2h0IiwiX2ZpbmlzaCIsIl90cmFuc2xhdGVUbyIsImFuaW1hdGUiLCJvbkFjdGlvbiIsIm5vRXZlbnQiLCJsYXN0U3RhdGUiLCJtYXJnaW5Ub3AiLCJfb25QdWxsIiwic2Nyb2xsRWxlbWVudCIsIl9kcmFnTG9ja0Rpc2FibGVkIiwic2Nyb2xsVG9nZ2xlIiwiZ2RUb2dnbGUiLCJfc2V0U3R5bGUiLCJfb25BY3Rpb24iLCJQdWxsSG9vayIsImFjdGl2ZUNsYXNzVG9rZW4iLCJSYW5nZUVsZW1lbnQiLCJfb25Nb3VzZURvd24iLCJfb25Nb3VzZVVwIiwiX29uVG91Y2hTdGFydCIsIl9vblRvdWNoRW5kIiwiX29uSW5wdXQiLCJfb25EcmFnc3RhcnQiLCJfb25EcmFnZW5kIiwiX3VwZGF0ZURpc2FibGVkIiwiZm9jdXNSaW5nIiwiX2ZvY3VzUmluZyIsImJhY2tncm91bmRTaXplIiwiX3JhdGlvIiwiUmFuZ2UiLCJBbmltYXRvckNTUyIsImZpbmFsIiwiZ2V0VGltZSIsImluaXRpYWwiLCJ1cGRhdGVTdHlsZXMiLCJjbGVhclRpbWVvdXQiLCJ0cmFuc2l0aW9uRHVyYXRpb24iLCJzdG9wTmV4dCIsIm5ld0R1cmF0aW9uIiwicGFzc2VkIiwicmVtYWluaW5nIiwic3BlZWRVcFRpbWUiLCJzdG9wIiwibWlsbGlzZWNvbmRzIiwic3BlZWQiLCJ0cmFuc2l0aW9uUHJvcGVydHkiLCJfb25TdG9wQW5pbWF0aW9ucyIsIl9xdWV1ZSIsIl9pbmRleCIsInN0b3BBbmltYXRpb25zIiwiUmlwcGxlRWxlbWVudCIsIl9vblRhcCIsIl9vbkhvbGQiLCJfYW5pbWF0b3IiLCJfd2F2ZSIsImdldEVsZW1lbnRzQnlDbGFzc05hbWUiLCJfYmFja2dyb3VuZCIsInNpemVzIiwiX2dldEVmZmVjdFNpemUiLCJfY2VudGVyIiwiX21pblIiLCJfY2FsY3VsYXRlQ29vcmRzIiwic3RvcEFsbCIsInJpcHBsZSIsIl91cGRhdGVQYXJlbnQiLCJfcmlwcGxlQW5pbWF0aW9uIiwiX2hvbGRpbmciLCJfcGFyZW50Tm9kZSIsInBuIiwiUmlwcGxlIiwiUm93RWxlbWVudCIsIlJvdyIsIlNlZ21lbnRFbGVtZW50IiwiX3NlZ21lbnRJZCIsIl90YWJiYXIiLCJfb25UYWJiYXJQcmVDaGFuZ2UiLCJnZXRBY3RpdmVUYWJJbmRleCIsImdldEFjdGl2ZUJ1dHRvbkluZGV4IiwiX3NldENoZWNrZWQiLCJmaXJzdEVsZW1lbnRDaGlsZCIsInNldEFjdGl2ZVRhYiIsIl9wb3N0Q2hhbmdlIiwiU2VnbWVudCIsIlNlbGVjdEVsZW1lbnQiLCJfZGVyaXZlR2V0dGVycyIsIl9zZWxlY3QiLCJzZWwiLCJvcHRpb24iLCJTZWxlY3QiLCJTcGVlZERpYWxJdGVtRWxlbWVudCIsIlNwZWVkRGlhbEl0ZW0iLCJTcGVlZERpYWxFbGVtZW50IiwiX2l0ZW1TaG93biIsIl91cGRhdGVEaXJlY3Rpb24iLCJ0b2dnbGVJdGVtcyIsImlubGluZSIsIl9mYWIiLCJpdGVtcyIsIl9nZXRUcmFuc2xhdGUiLCJoaWRlSXRlbXMiLCJ0b3RhbERlbGF5IiwiaXNPcGVuIiwic2hvd0l0ZW1zIiwiU3BlZWREaWFsIiwiU3BsaXR0ZXJDb250ZW50RWxlbWVudCIsIm9sZENvbnRlbnQiLCJTcGxpdHRlckNvbnRlbnQiLCJTcGxpdHRlck1hc2tFbGVtZW50IiwiX3NpZGVzIiwic2lkZSIsIm1vZGUiLCJTcGxpdHRlck1hc2siLCJTcGxpdHRlckFuaW1hdG9yIiwic2lkZUVsZW1lbnQiLCJzcGxpdHRlciIsIl9zaWRlIiwiX29wcG9zaXRlU2lkZSIsImNsZWFyTWFzayIsIk92ZXJsYXlTcGxpdHRlckFuaW1hdG9yIiwibWludXMiLCJQdXNoU3BsaXR0ZXJBbmltYXRvciIsInNsaWRpbmdFbGVtZW50cyIsIl9zbGlkaW5nRWxlbWVudHMiLCJfZ2V0U2xpZGluZ0VsZW1lbnRzIiwiUmV2ZWFsU3BsaXR0ZXJBbmltYXRvciIsIl9zZXRTdHlsZXMiLCJfdW5zZXRTdHlsZXMiLCJfZ2VuZXJhdGVCZWhpbmRQYWdlU3R5bGUiLCJiZWhpbmREaXN0YW5jZSIsImJlaGluZFRyYW5zZm9ybSIsIl9nZXRNYXhXaWR0aCIsIm1lbnVTdHlsZSIsIlNwbGl0dGVyRWxlbWVudCIsIl9sYXlvdXQiLCJfZ2V0U2lkZSIsIl9vbk1vZGVDaGFuZ2UiLCJTcGxpdHRlciIsIlNQTElUX01PREUiLCJDT0xMQVBTRV9NT0RFIiwiQ0xPU0VEX1NUQVRFIiwiT1BFTl9TVEFURSIsIkNIQU5HSU5HX1NUQVRFIiwic3BsaXR0ZXJTaWRlRWxlbWVudCIsIkNvbGxhcHNlRGV0ZWN0aW9uIiwiY2hhbmdlVGFyZ2V0IiwiX3RhcmdldCIsIl9vcmllbnRhdGlvbiIsImFjdGl2YXRlIiwiX3VwZGF0ZU1vZGUiLCJfbWF0Y2giLCJfcXVlcnlSZXN1bHQiLCJtYXRjaE1lZGlhIiwiYWRkTGlzdGVuZXIiLCJyZW1vdmVMaXN0ZW5lciIsIlNwbGl0dGVyU2lkZUVsZW1lbnQiLCJfc3RhdGUiLCJfbG9jayIsIl9jb2xsYXBzZURldGVjdGlvbiIsIl9hbmltYXRpb25PcHQiLCJjbG9zZWQiLCJ2YWxpZERyYWciLCJfbW9kZSIsIl9pc090aGVyU2lkZU9wZW4iLCJkZWFjdGl2YXRlIiwidXBkYXRlT3B0aW9ucyIsIkZJTkFMX1NUQVRFIiwiX2VtaXRFdmVudCIsIl91cGRhdGVBbmltYXRpb24iLCJTcGxpdHRlclNpZGUiLCJsb2NhdGlvbnMiLCJTd2l0Y2hFbGVtZW50IiwiX2xhc3RUaW1lU3RhbXAiLCJfbG9jYXRpb25zIiwiX3N0YXJ0WCIsIl9lbWl0Q2hhbmdlRXZlbnQiLCJkZWZhdWx0RWxlbWVudENsYXNzIiwiX2hhbmRsZSIsIl9nZXRQb3NpdGlvbiIsInByZXZpb3VzVmFsdWUiLCJjbGljayIsIlN3aXRjaCIsInRhYmJhckVsZW1lbnQiLCJsZXJwIiwieDAiLCJ4MSIsInQiLCJUYWJiYXJFbGVtZW50IiwiX2xvYWRJbmFjdGl2ZSIsIl9nZXRBdXRvU2Nyb2xsUmF0aW8iLCJfb25QcmVDaGFuZ2UiLCJfb25Qb3N0Q2hhbmdlIiwiX3RhYmJhckJvcmRlciIsIl90YWJiYXJFbGVtZW50IiwiX3RhYnNSZWN0IiwidGFiSXRlbSIsInRhYnMiLCJfbm9ybWFsaXplRXZlbnQiLCJjYW5jZWwiLCJzZXRBY3RpdmUiLCJwcmV2VGFiIiwiX2F1dG9ncm93IiwidGFiIiwidGFiYmFyIiwiY3MiLCJmaWxsZWQiLCJuZXh0SW5kZXgiLCJwcmV2SW5kZXgiLCJuZXh0VGFiIiwic2V0VGFiYmFyVmlzaWJpbGl0eSIsImlzQWN0aXZlIiwiaXNUb3AiLCJfdGFyZ2V0RWxlbWVudCIsIlRhYmJhciIsIlRhYkVsZW1lbnQiLCJfYnV0dG9uIiwiX3VwZGF0ZUJ1dHRvbkNvbnRlbnQiLCJpY29uV3JhcHBlciIsImZpeCIsImFjdGl2ZSIsIl9oYXNMb2FkZWQiLCJfbG9hZGVkUGFnZSIsInBhZ2VUYXJnZXQiLCJwYXJlbnRUYXJnZXQiLCJkdW1teVBhZ2UiLCJfbG9hZFBhZ2VFbGVtZW50IiwiVGFiIiwiVG9hc3RBbmltYXRvciIsIkZhZGVUb2FzdEFuaW1hdG9yIiwiQXNjZW5kVG9hc3RBbmltYXRvciIsIm1lc3NhZ2VEZWxheSIsImFzY2Vuc2lvbiIsIl9nZXRGYWJzIiwiZmFiIiwiTGlmdFRvYXN0QW5pbWF0b3IiLCJGYWxsVG9hc3RBbmltYXRvciIsImZhbGxBbW91bnQiLCJjbGVhblVwIiwiY29ycmVjdFRvcCIsIlRvYXN0RWxlbWVudCIsIm1lc3NhZ2VDbGFzc05hbWUiLCJidXR0b25DbGFzc05hbWUiLCJUb2FzdCIsIlRvb2xiYXJCdXR0b25FbGVtZW50IiwiVG9vbGJhckJ1dHRvbiIsIl9zdXBlclNlY3JldE9ucyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFBQSxrQkFBZSxFQUFmOztBQ0FBOzs7Ozs7Ozs7Ozs7Ozs7OztBQWlCQSxBQUVBOzs7Ozs7QUFNQSxJQUFNQSxTQUFVLFlBQVc7TUFDbkJDLFNBQVNDLE9BQU9DLGdCQUFQLENBQXdCQyxTQUFTQyxlQUFqQyxFQUFrRCxFQUFsRCxDQUFmO01BQ01MLFNBQVMsQ0FBQ00sTUFBTUMsU0FBTixDQUFnQkMsS0FBaEIsQ0FDYkMsSUFEYSxDQUNSUixNQURRLEVBRWJTLElBRmEsQ0FFUixFQUZRLEVBR2JDLEtBSGEsQ0FHUCxtQkFITyxLQUdrQlYsT0FBT1csS0FBUCxLQUFpQixFQUFqQixJQUF1QixDQUFDLEVBQUQsRUFBSyxHQUFMLENBSDFDLEVBSWIsQ0FKYSxDQUFmOztTQU1PLFVBQVNDLElBQVQsRUFBZTtXQUNiLE1BQU1iLE1BQU4sR0FBZSxHQUFmLEdBQXFCYyxPQUFLQyxTQUFMLENBQWVGLElBQWYsQ0FBNUI7R0FERjtDQVJhLEVBQWY7Ozs7Ozs7Ozs7QUFzQkEsSUFBTUcsU0FBUyxTQUFUQSxNQUFTLENBQVNDLE9BQVQsRUFBa0JDLEtBQWxCLEVBQXlCO1NBQy9CQyxJQUFQLENBQVlELEtBQVosRUFBbUJFLE9BQW5CLENBQTJCLFVBQVNDLEdBQVQsRUFBYztRQUNuQ0EsT0FBT0os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
|