{"version":3,"file":"deloitte.vca.blazor.js.flows.bundle.js","mappings":";2BACA,IAAIA,EAAsB,CCA1BA,EAAwB,CAACC,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXF,EAAoBI,EAAEF,EAAYC,KAASH,EAAoBI,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDH,EAAwB,CAACS,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFV,EAAyBC,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,6hGCD9D,MAAMC,EAAU,qBACVC,EAAW,iBACXC,EAAU,mBACVC,EAAU,gBACVC,EAAW,iBACXC,EAAU,oBACVC,EAAS,eACTC,EAAY,kBAEZC,EAAY,kBACZC,EAAY,kBACZC,EAAS,eACTC,EAAY,kBACZC,EAAY,kBAEZC,EAAa,mBACbC,EAAiB,uBACjBC,EAAc,oBACdC,EAAa,wBACbC,EAAa,wBACbC,EAAU,qBACVC,EAAW,sBACXC,EAAW,sBACXC,EAAW,sBACXC,EAAkB,6BAClBC,EAAY,uBACZC,EAAY,uBAEZC,EAAiB,CACnB,CAACzB,IAAU,EACX,CAACC,IAAW,EACZ,CAACa,IAAiB,EAClB,CAACC,IAAc,EACf,CAACb,IAAU,EACX,CAACC,IAAU,EACX,CAACa,IAAa,EACd,CAACC,IAAa,EACd,CAACC,IAAU,EACX,CAACC,IAAW,EACZ,CAACC,IAAW,EACZ,CAACd,IAAS,EACV,CAACC,IAAY,EACb,CAACC,IAAY,EACb,CAACC,IAAY,EACb,CAACC,IAAS,EACV,CAACC,IAAY,EACb,CAACC,IAAY,EACb,CAACS,IAAW,EACZ,CAACC,IAAkB,EACnB,CAACC,IAAY,EACb,CAACC,IAAY,EACb,CAACpB,IAAW,EACZ,CAACC,IAAU,EACX,CAACQ,IAAa,GAIZa,EAAgB,kBAOhBC,EAAiB,kBACjBC,EAAe,4BAKfC,EAAe,4BAEfC,EAAeC,8OAGfC,EAAS,OACTC,EAAU,IAAIH,KACdI,EAAU,gFAEVC,EAAY,IAAIR,KAChBS,EAAU,IAAIR,KACdS,EAAS,KAAKX,IAAgBI,EAHpB,MAG6CH,EAAiBC,EAAeC,KACvFS,EAAS,2BAETC,GAAc,KAAKb,KACnBc,GAAa,kCACbC,GAAa,qCACbC,GAAU,IAAIb,KAIdc,GAAc,MAAMP,KAAWC,KAC/BO,GAAc,MAAMF,MAAWL,KAC/BQ,GAAkB,MAAMb,0BACxBc,GAAkB,MAAMd,0BACxBe,GAAW,MAZQb,KAAWI,MAa9BU,GAAW,oBAIXC,GAAQD,GAAWD,GAHP,gBAAiB,CAACR,GAAaC,GAAYC,IAAYS,KAAK,QAAQF,GAAWD,OAI3FI,GAAU,MAAM,CAAChB,EAAWK,GAAYC,IAAYS,KAAK,QAAQD,KAEjEG,GAAiBC,OAAO,CAC1B,GAAGX,MAAWN,KAAWS,QAAqB,CAACZ,EAASS,GAAS,KAAKQ,KAAK,QAC3E,GAAGN,MAAeE,QAAqB,CAACb,EAASS,GAAUC,GAAa,KAAKO,KAAK,QAClF,GAAGR,MAAWC,MAAeE,KAC7B,GAAGH,MAAWI,KARC,mDADA,mDAYf,OACAK,IACFD,KAAK,KAAM,KAGPI,GAAiB,qBAGjBC,GAAa,4EAObC,GAAW,MAAM,CADE,GAAGjB,KAAcL,KACAA,EAASM,GAAYC,GAJ9C,IAAIf,MAIgEwB,KAAK,QAGpFO,GAAYJ,OAAO,GAAGf,OAAYA,MAAWkB,GAAWP,KAAS,KAEjES,GAAe,mDACfC,GAAgB,QAEhBC,GAAgB,IAAIC,WAAW,GAC/BC,GAAe,WACfC,GAAaV,OAEf,8GAUE,KACAW,GAAW,mBAEXC,GAAiBZ,OAAO3D,UAAUwE,KAAKC,KACzC,sEAOEC,GAAc,4CAKdC,GAAcC,GACTb,GAAUS,KAAKI,GAWpBC,GAAiBD,GACZD,GAAWC,GATC,CAACA,GACbA,EAAOE,MAAMf,KAAc,GAQNgB,CAAeH,GAL1B,CAACA,GACXA,EAAOI,MAAM,IAIiCC,CAAaL,GAGhEM,GAAUC,GACE,MAAVA,EACO,GAGJC,GAAKD,GAAQE,KAAK7F,GAAQ2F,EAAO3F,KAGtC4F,GAAQD,GACHG,GAAYH,GAAUI,GAAcJ,GAAUzF,OAAO0F,KAAK1F,OAAOyF,IAiBtEI,GAAgB,CAAClF,EAAOmF,KAC1B,MAAMC,EAAQC,MAAMC,QAAQtF,GACtBuF,GAASH,GAASI,GAAaxF,IAAUyF,GAAOzF,KAAWC,EAC3DyF,GAAUN,IAAUG,GAASI,GAAa3F,GAC1C4F,EAAcR,GAASG,GAASG,EAChCG,EAAS7F,EAAM6F,OACfC,EAAS,IAAIT,MAAMO,EAAcC,EAAS,GAChD,IAAIE,EAAQH,GAAe,EAAIC,EAC/B,OAASE,EAAQF,GACbC,EAAOC,GAAS,GAAGA,IAEvB,IAAK,MAAM5G,KAAOa,GACTmF,IAAavF,eAAeC,KAAKG,EAAOb,IACvCyG,IAEU,WAARzG,GAEA6G,GAAQ7G,EAAK0G,KAGjBC,EAAOG,KAAK9G,GAGpB,OAAO2G,CAAM,EAGXI,GAAe,CAACC,EAAOhH,KACzB,IAAI,OAAE0G,GAAWM,EACjB,KAAON,KACH,GAAIO,GAAGD,EAAMN,GAAQ,GAAI1G,GACrB,OAAO0G,EAGf,OAAQ,CAAC,EAGPO,GAAK,CAACpG,EAAOqG,IACRrG,IAAUqG,GAAUrG,GAAUA,GAASqG,GAAUA,EAGtDb,GAAgBxF,GACF,MAATA,GAAiC,iBAATA,EAG7BsG,GAAiB,CAACtG,EAAO+F,EAAOjB,KAClC,IAAKyB,GAASzB,GACV,OAAO,EAEX,MAAM0B,SAAcT,EAMpB,SAJmC,UAARS,EACtBvB,GAAYH,IAAWiB,GAAS,GAAKA,EAAQjB,EAAOe,OAC5C,UAARW,GAAoBT,KAASjB,IAGvBsB,GAAGtB,EAAOiB,GAAQ/F,EAEjB,EAWVyG,GAAezG,IACjB,MAAM0G,EAAO1G,GAASA,EAAM2G,YAG5B,OAAO3G,KAFwB,mBAAT0G,GAAuBA,EAAK/G,WAAcN,OAAOM,UAEjD,EAGpBiH,GAAc,CAAC9B,EAAQ3F,EAAKa,KAC9B,MAAM6G,EAAW/B,EAAO3F,GAClBS,eAAeC,KAAKiF,EAAQ3F,IAAQiH,GAAGS,EAAU7G,UACxC8G,IAAV9G,GAAyBb,KAAO2F,KACjCA,EAAO3F,GAAOa,EAClB,EAGE+G,GAAa,CAACC,EAAQC,EAAOnC,KAC/B,IAAIiB,GAAS,EACb,MAAMF,EAASoB,EAAMpB,OAErB,OAASE,EAAQF,GAAQ,CACrB,MAAM1G,EAAM8H,EAAMlB,GAClBa,GAAY9B,EAAQ3F,EAAK6H,EAAO7H,GACpC,CACA,OAAO2F,CAAM,EAGXG,GAAejF,GACD,MAATA,GAAkC,mBAAVA,GAAgD,iBAAjBA,EAAM6F,QAChE7F,EAAM6F,QAAU,GAAK7F,EAAM6F,OAAS,GAAM,EAG5CqB,GAAYlH,GACS,iBAATA,GACTwF,GAAaxF,IAAUyF,GAAOzF,KAAWa,EAe5CsG,GAAY,CAACH,EAAQb,KACvB,IAAIJ,GAAS,EACb,MAAMF,EAASmB,EAAOnB,OAGtB,IADAM,IAAUA,EAAQ,IAAId,MAAMQ,MACnBE,EAAQF,GACbM,EAAMJ,GAASiB,EAAOjB,GAE1B,OAAOI,CAAK,EAGVV,GAAUzF,GACC,MAATA,OACiB8G,IAAV9G,EAhUM,qBANL,gBAyULX,OAAOM,UAAUyH,SAASvH,KAAKG,GAGpCqH,GAAoBC,IACtB,MAAMxB,EAAS,IAAIwB,EAAYX,YAAYW,EAAYC,YAEvD,OADA,IAAIC,WAAW1B,GAAQ2B,IAAI,IAAID,WAAWF,IACnCxB,CAAM,EAGX4B,GAAkB,CAACC,EAAYC,KACjC,MAAMC,EAASD,EAASP,GAAiBM,EAAWE,QAAUF,EAAWE,OACzE,OAAO,IAAIF,EAAWhB,YAAYkB,EAAQF,EAAWG,WAAYH,EAAW9B,OAAO,EASjFkC,GAAmBjD,GACgB,mBAAtBA,EAAO6B,aAA8BF,GAAY3B,GAE1D,CAAC,EADDzF,OAAO2I,OAAO3I,OAAO4I,eAAenD,IAIxCoD,GAAcpD,GACF,MAAVA,EACO,IAGXA,EAASzF,OAAOyF,GACAzF,OAAO8I,sBAAsBrD,GAE9BsD,QAAQC,GAAWC,qBAAqBzI,KAAKiF,EAAQuD,MA8ClE1C,GAAgB3F,GACXwF,GAAaxF,IAAUwD,GAAWW,KAAKsB,GAAOzF,IAGnDuI,GAAczD,IAChB,MAAMgB,EAASzG,OAAO0F,KAAKD,GAK3B,OAJIO,MAAMC,QAAQR,IAAqB,MAAVA,GACzBgB,EAAOG,QAAQiC,GAAW7I,OAAOyF,KAG9BgB,CAAM,EAGX0C,GAAgB1D,IAClB,MAAMgB,EAAS,GACf,KAAOhB,GACHgB,EAAOG,QAAQiC,GAAWpD,IAC1BA,EAASzF,OAAO4I,eAAe5I,OAAOyF,IAG1C,OAAOgB,CAAM,EAGX2C,GAAgB3D,IAClB,MAAMgB,EAAS,GAEf,IAAK,MAAM3G,KAAO2F,EACdgB,EAAOG,KAAK9G,GAOhB,OAJKkG,MAAMC,QAAQR,IACfgB,EAAOG,QAAQuC,GAAa1D,IAGzBgB,CAAM,EAGX4C,GAAa,EAAGC,YAAYxJ,KAC9B,MAAMyJ,EAAOD,EACb,OAAOE,GAAU1J,GACXyJ,EAAoB,iBAARzJ,EAAmB,SAAW,QAC1CyJ,EAAK5D,GAAG,EAgEZ8D,GAAc,CAAC9I,EAAOqG,EAAO0C,IAC3B/I,IAAUqG,IAGD,MAATrG,GAA0B,MAATqG,IAAmBb,GAAaxF,KAAWwF,GAAaa,GAClErG,GAAUA,GAASqG,GAAUA,EAGjC2C,GAAgBhJ,EAAOqG,EAAOyC,GAAaC,IAGhDC,GAAkB,CAAClE,EAAQuB,EAAO4C,EAAWF,KAC/C,IAAIG,EAAW7D,MAAMC,QAAQR,GAC7B,MAAMqE,EAAW9D,MAAMC,QAAQe,GAC/B,IAAI+C,EAASF,EAAWhJ,EAAWuF,GAAOX,GACtCuE,EAASF,EAAWjJ,EAAWuF,GAAOY,GAE1C+C,EAASA,GAAUnJ,EAAUQ,EAAY2I,EACzCC,EAASA,GAAUpJ,EAAUQ,EAAY4I,EAEzC,IAAIC,EAAWF,GAAU3I,EACzB,MAAM8I,EAAWF,GAAU5I,EACrB+I,EAAYJ,GAAUC,EAE5B,GAAIG,IAAcF,EAEd,OADAP,IAAUA,EAAQ,IAAIU,IACdP,GAAYvD,GAAab,GAC3B4E,GAAY5E,EAAQuB,GAAO,EAAO4C,EAAWF,GAC7CY,GAAW7E,EAAQuB,EAAO+C,EAAQH,EAAWF,GAGvD,MAAMa,EAAeN,GAAY1J,eAAeC,KAAKiF,EAAQ,eACvD+E,EAAeN,GAAY3J,eAAeC,KAAKwG,EAAO,eAE5D,GAAIuD,GAAgBC,EAAc,CAC9B,MAAMC,EAAeF,EAAe9E,EAAO9E,QAAU8E,EAC/CiF,EAAeF,EAAexD,EAAMrG,QAAUqG,EAGpD,OADA0C,IAAUA,EAAQ,IAAIU,IACfR,EAAUa,EAAcC,EAAchB,EACjD,CAEA,QAAKS,IAILT,IAAUA,EAAQ,IAAIU,IA3GL,EAAC3E,EAAQuB,EAAO4C,EAAWF,KAC5C,MAAMiB,EAAWzB,GAAWzD,GACtBmF,EAAYD,EAASnE,OAI3B,GAAIoE,GAHa1B,GAAWlC,GACDR,OAGvB,OAAO,EAEX,IAAI1G,EACA4G,EAAQkE,EACZ,KAAOlE,KAEH,GADA5G,EAAM6K,EAASjE,IACTnG,eAAeC,KAAKwG,EAAOlH,GAC7B,OAAO,EAIf,MAAM+K,EAAanB,EAAMvJ,IAAIsF,GACvBqF,EAAapB,EAAMvJ,IAAI6G,GAC7B,GAAI6D,GAAcC,EACd,OAAOD,GAAc7D,GAAS8D,GAAcrF,EAEhD,IAKIsF,EALAtE,GAAS,EAOb,IANAiD,EAAMtB,IAAI3C,EAAQuB,GAClB0C,EAAMtB,IAAIpB,EAAOvB,KAKRiB,EAAQkE,GAAW,CACxB9K,EAAM6K,EAASjE,GACf,MAAMc,EAAW/B,EAAO3F,GAClBkL,EAAWhE,EAAMlH,GAEvB,GACO0H,IAAawD,IAAYpB,EAAUpC,EAAUwD,EAAUtB,GAE3D,CACCjD,GAAS,EACT,KACJ,CACAsE,IAAaA,EAAkB,eAAPjL,EAC5B,CAEA,GAAI2G,IAAWsE,EAAU,CACrB,MAAME,EAAUxF,EAAO6B,YACjB4D,EAAUlE,EAAMM,YAElB2D,GAAWC,KACd,gBAAiBzF,MAAU,gBAAiBuB,IACxB,mBAAZiE,GAA0BA,aAAmBA,GAC/B,mBAAZC,GAA0BA,aAAmBA,IACpDzE,GAAS,EAEjB,CAGA,OAFAiD,EAAc,OAAEjE,GAChBiE,EAAc,OAAE1C,GACTP,CAAM,EAkDN0E,CAAa1F,EAAQuB,EAAO4C,EAAWF,GAAM,EAGlDW,GAAc,CAACvD,EAAOE,EAAOoE,EAAkBxB,EAAWF,KAC5D,MACM2B,EAAYvE,EAAMN,OAGxB,GAAI6E,GAFcrE,EAAMR,OAGpB,OAAO,EAGX,MAAM8E,EAAa5B,EAAMvJ,IAAI2G,GACvBgE,EAAapB,EAAMvJ,IAAI6G,GAC7B,GAAIsE,GAAcR,EACd,OAAOQ,GAActE,GAAS8D,GAAchE,EAEhD,IAAIJ,GAAS,EACTD,GAAS,EACb,MAAM8E,EAAOH,EAAmB,IAAII,QAAW/D,EAK/C,IAHAiC,EAAMtB,IAAItB,EAAOE,GACjB0C,EAAMtB,IAAIpB,EAAOF,KAERJ,EAAQ2E,GAAW,CACxB,IAAII,EACJ,MAAMC,EAAW5E,EAAMJ,GACjBsE,EAAWhE,EAAMN,GAEvB,QAAiBe,IAAbgE,EAAwB,CACxB,GAAIA,EACA,SAEJhF,GAAS,EACT,KACJ,CAEA,GAAI8E,GACA,IAAKI,GAAK3E,GAAO,CAACgE,EAAUY,KACxB,IAAKC,GAASN,EAAMK,KACvBF,IAAaV,GAAYpB,EAAU8B,EAAUV,EAAUtB,IAChD,OAAO6B,EAAK3E,KAAKgF,EACrB,IACA,CACAnF,GAAS,EACT,KACJ,OACG,GACHiF,IAAaV,IACbpB,EAAU8B,EAAUV,EAAUtB,GAC/B,CACCjD,GAAS,EACT,KACJ,CACJ,CAGA,OAFAiD,EAAc,OAAE5C,GAChB4C,EAAc,OAAE1C,GACTP,CAAM,EAGXkF,GAAO,CAAC7E,EAAOgF,KACjB,IAAIpF,GAAS,EACb,MAAMF,EAAkB,MAATM,EAAgB,EAAIA,EAAMN,OAEzC,OAASE,EAAQF,GACb,GAAIsF,EAAUhF,EAAMJ,GAAQA,EAAOI,GAC/B,OAAO,EAGf,OAAO,CAAK,EAGV+E,GAAW,CAACE,EAAOjM,IACdiM,EAAMC,IAAIlM,GAGfmM,GAAwB,CAACxG,EAAQuB,EAAO4C,EAAWF,MAChDjE,EAAOyC,YAAclB,EAAMkB,aACnB0B,EAAU,IAAIzB,WAAW1C,GAAS,IAAI0C,WAAWnB,GAAQ0C,IAMpEY,GAAa,CAAC7E,EAAQuB,EAAOkF,EAAKtC,EAAWF,KAE/C,OAAQwC,GACJ,KAAKvK,EACD,OAAK8D,EAAOyC,YAAclB,EAAMkB,YAC3BzC,EAAOgD,YAAczB,EAAMyB,aAGhChD,EAASA,EAAO+C,OAChBxB,EAAQA,EAAMwB,OACPyD,GAAsBxG,EAAQuB,EAAO4C,EAAWF,IAC3D,KAAKhI,EACD,OAAOuK,GAAsBxG,EAAQuB,EAAO4C,EAAWF,GAC3D,KAAK5I,EACL,KAAKC,EACL,KAAKI,EACD,OAAO4F,IAAItB,GAASuB,GACxB,KAAKhG,EACD,OAAOyE,EAAO0G,MAAQnF,EAAMmF,MAAQ1G,EAAO2G,SAAWpF,EAAMoF,QAChE,KAAK/K,EACL,KAAKE,EACD,OAAOkE,GAAU,GAAGuB,IACxB,KAAK9F,EAED,IAAImL,EAAUC,GAGlB,KAAKhL,EAGD,GAFA+K,IAAYA,EAAUE,IAElB9G,EAAO+G,MAAQxF,EAAMwF,KACrB,OAAO,EAGX,MAAMC,EAAU/C,EAAMvJ,IAAIsF,GAC1B,GAAIgH,EACA,OAAOA,GAAWzF,EAItB0C,EAAMtB,IAAI3C,EAAQuB,GAClB,MAAMP,EAAS4D,GAAYgC,EAAQ5G,GAAS4G,EAAQrF,IAAQ,EAAM4C,EAAWF,GAE7E,OADAA,EAAc,OAAEjE,GACTgB,EACX,KAAKjF,EACD,OAAOf,OAAOH,UAAUoM,QAAQlM,KAAKiF,IAAWhF,OAAOH,UAAUoM,QAAQlM,KAAKwG,GAGtF,OAAO,CAAK,EAGVsF,GAAc3G,IAChB,IAAIe,GAAS,EACTD,EAAST,MAAML,EAAI6G,MAKvB,OAHA7G,EAAIgH,SAAQ,CAAChM,EAAOb,KAChB2G,IAASC,GAAS,CAAC5G,EAAKa,EAAM,IAE3B8F,CAAM,EAGX8F,GAAcnE,IAChB,IAAI1B,GAAS,EACb,MAAMD,EAAS,IAAIT,MAAMoC,EAAIoE,MAK7B,OAHApE,EAAIuE,SAAShM,IACT8F,IAASC,GAAS/F,CAAK,IAEpB8F,CAAM,EAGXmG,GAAQ,CAACjM,EAAO8E,KAClB,GAAIO,MAAMC,QAAQtF,GACd,OAAO,EAEX,MAAMwG,SAAcxG,EACpB,QAAa,WAATwG,GAA8B,YAATA,GAA+B,MAATxG,IAAiBkH,GAASlH,KAGlE4D,GAAcO,KAAKnE,KAAW2D,GAAaQ,KAAKnE,IAC5C,MAAV8E,GAAkB9E,KAASX,OAAOyF,EAAQ,EAqBzCoH,GAAW,CAACC,EAAMrH,IAChBO,MAAMC,QAAQ6G,GACPA,EAGJF,GAAME,EAAMrH,GAAU,CAACqH,GAvBb,CAAC5H,IAClB,MAAMuB,EAAS,GAcf,OAbIvB,EAAOT,WAAW,KAAOD,IACzBiC,EAAOG,KAAK,IAEhB1B,EAAO6H,QAAQpI,IAAY,CAACS,EAAO4H,EAAYC,EAAOC,KAClD,IAAIpN,EAAMsF,EACN6H,EACAnN,EAAMoN,EAAUH,QAAQrI,GAAc,MAEjCsI,IACLlN,EAAMkN,EAAWG,QAErB1G,EAAOG,KAAK9G,EAAI,IAEb2G,CAAM,EAQyB2G,CAAa,GAAGN,KAGpD3M,GAAM,CAACsF,EAAQqH,KAGjB,IAAIpG,EAAQ,EACZ,MAAMF,GAHNsG,EAAOD,GAASC,EAAMrH,IAGFe,OAEpB,KAAiB,MAAVf,GAAkBiB,EAAQF,GAC7Bf,EAASA,EAAO4H,GAAMP,EAAKpG,KAC3BA,IAGJ,OAAQA,GAASA,GAASF,EAAUf,OAASgC,CAAS,EAG1D,SAAS6F,GAAiB3M,EAAOqG,GAC7B,GAAIrG,IAAUqG,EAAO,CACjB,MAAMuG,OAAyB9F,IAAV9G,EACf6M,EAAsB,OAAV7M,EACZ8M,EAAiB9M,GAAUA,EAC3B+M,EAAc7F,GAASlH,GAEvBgN,OAAyBlG,IAAVT,EACf4G,EAAsB,OAAV5G,EACZ6G,EAAiB7G,GAAUA,EAC3B8G,EAAcjG,GAASb,GAE7B,IAAM4G,IAAcE,IAAgBJ,GAAe/M,EAAQqG,GACtD0G,GAAeC,GAAgBE,IAAmBD,IAAcE,GAChEN,GAAaG,GAAgBE,IAC5BN,GAAgBM,IACjBJ,EACD,OAAO,EAEX,IAAMD,IAAcE,IAAgBI,GAAenN,EAAQqG,GACtD8G,GAAeP,GAAgBE,IAAmBD,IAAcE,GAChEE,GAAaL,GAAgBE,IAC5BE,GAAgBF,IACjBI,EACD,OAAQ,CAEhB,CACA,OAAO,CACX,CAwBA,MAAME,GAAO,CAACjH,EAAOtB,KACjB,IAAIwI,EAAW,CAAClH,EAAOnG,MACK,MAATmG,IAAoBA,EAAMN,SACtBM,EAAMmH,QAAQtN,IAAU,EAE3CuN,GAAW,EACf,MAAMzH,EAAS,GACT0H,EAAe3I,EAAOgB,OAE5B,IAAKM,EAAMN,OACP,OAAOC,EAGPjB,EAAOgB,QAvtBU,MAwtBjBwH,EAAW,CAACjC,EAAOjM,IAAQiM,EAAMC,IAAIlM,GACrCoO,GAAW,EACX1I,EAAS,IAAIgG,GAAShG,IAG1B4I,EACA,IAAK,IAAItO,KAAOgH,EAAO,CACnB,IAAInG,EAAQmG,EAAMhH,GAClB,MAAMuO,EAAW1N,EAGjB,GADAA,EAAmB,IAAVA,EAAeA,EAAQ,EAC5BuN,GAAYG,GAAaA,EAAU,CACnC,IAAIC,EAAcH,EAClB,KAAOG,KACH,GAAI9I,EAAO8I,KAAiBD,EACxB,SAASD,EAGjB3H,EAAOG,KAAKjG,EAChB,MACUqN,EAASxI,EAAQ6I,IACvB5H,EAAOG,KAAKjG,EAEpB,CAEA,OAAO8F,CAAM,EA4DX4G,GAAS1M,IACX,GAAqB,iBAAVA,GAAsBkH,GAASlH,GACtC,OAAOA,EAEX,MAAM8F,EAAS,GAAG9F,IAClB,MAAkB,KAAV8F,GAAkB,EAAI9F,IAAU,IAAa,KAAO8F,CAAM,EAGhE8H,GAAY,CAAC5N,EAAO4H,GAAS,EAAOiG,GAAS,EAAOC,GAAS,EAAMC,EAAY5O,EAAK2F,EAAQiE,KAC9F,IAAIjD,EAMJ,GAJIiI,IACAjI,EAAShB,EAASiJ,EAAW/N,EAAOb,EAAK2F,EAAQiE,GAASgF,EAAW/N,SAG1D8G,IAAXhB,EACA,OAAOA,EAGX,IAAKS,GAASvG,GACV,OAAOA,EAGX,MAAMoF,EAAQC,MAAMC,QAAQtF,GACtBuL,EAAM9F,GAAOzF,GAEnB,GAAIoF,GAGA,GAFAU,EAroBe,CAACK,IACpB,MAAMN,EAASM,EAAMN,OACrB,IAAIC,EAAS,IAAIK,EAAMQ,YAAYd,GAOnC,OALIA,GAA6B,iBAAZM,EAAM,IAAkBvG,eAAeC,KAAKsG,EAAO,WACpEL,EAAOC,MAAQI,EAAMJ,MACrBD,EAAOkI,MAAQ7H,EAAM6H,OAGlBlI,CAAM,EA4nBAmI,CAAejO,IAEnB4H,EACD,OAAOT,GAAUnH,EAAO8F,OAEzB,CACH,MAAMoI,EAA0B,mBAAVlO,EAEtB,GAAIuL,IAAQ9K,GAAa8K,IAAQtL,GAAYiO,IAAWpJ,GAEpD,GADAgB,EAAU+H,GAAUK,EAAU,CAAC,EAAInG,GAAgB/H,IAC9C4H,EACD,OAAOiG,EACHM,GAAcnO,EAAO+G,GAAW/G,EAAOX,OAAO0F,KAAK/E,GAAQ8F,IAhlB3D,EAACkB,EAAQlC,IAClBiC,GAAWC,EAAQkB,GAAWlB,GAASlC,GAglB9BsJ,CAAYpO,EAAOX,OAAOgP,OAAOvI,EAAQ9F,QAE9C,CACH,GAAIkO,IAAWxM,EAAe6J,GAC1B,OAAOzG,EAAS9E,EAAQ,CAAC,EAE7B8F,EA9kBW,EAAChB,EAAQyG,EAAK3D,KACjC,MAAM0G,EAAcxJ,EAAO6B,YAC3B,OAAO4E,GACH,KAAKxK,EACD,OAAOsG,GAAiBvC,GAC5B,KAAK3E,EACL,KAAKC,EACD,OAAO,IAAIkO,GAAaxJ,GAC5B,KAAK9D,EACD,OAdZ,SAAuBuN,EAAU3G,GAC7B,MAAMC,EAASD,EAASP,GAAiBkH,EAAS1G,QAAU0G,EAAS1G,OACrE,OAAO,IAAI0G,EAAS5H,YAAYkB,EAAQ0G,EAASzG,WAAYyG,EAAShH,WAC1E,CAWmBiH,CAAc1J,EAAQ8C,GACjC,KAAK3G,EACL,KAAKC,EACL,KAAKC,EACL,KAAKC,EACL,KAAKC,EACL,KAAKC,EACL,KAAKC,EACL,KAAKC,EACL,KAAKC,EACD,OAAOiG,GAAgB5C,EAAQ8C,GACnC,KAAKrH,EAEL,KAAKC,EACL,KAAKI,EACD,OAAO,IAAI0N,EAAYxJ,GAC3B,KAAKpE,EACD,MA1DQ,CAAC+N,IACjB,MAAM3I,EAAS,IAAI2I,EAAO9H,YAAY8H,EAAOzH,OAAQ,OAAO0H,KAAKD,IAEjE,OADA3I,EAAO6I,UAAYF,EAAOE,UACnB7I,CAAM,EAuDE8I,CAAY9J,GACvB,KAAKnE,EACD,OAAO,IAAI2N,EACf,KAAKzN,EACD,OAAOf,OAAOH,UAAUoM,QAAU1M,OAAOS,OAAOH,UAAUoM,QAAQlM,KAAKiF,IAAW,CAAC,EAC3F,EA+iBiB+J,CAAe7O,EAAOuL,EAAK3D,EACxC,CACJ,CAEAmB,IAAUA,EAAQ,IAAIU,IACtB,MAAMqC,EAAU/C,EAAMvJ,IAAIQ,GAE1B,GAAI8L,EACA,OAAOA,EAKX,GAFA/C,EAAMtB,IAAIzH,EAAO8F,GA3sBP,CAAC9F,GACJwF,GAAaxF,IAAUyF,GAAOzF,IAAUO,EA4sB3CuO,CAAM9O,GAKN,OAJAA,EAAMgM,SAAQ,CAAC+C,EAAU5P,KACrB2G,EAAO2B,IAAItI,EAAKyO,GAAUmB,EAAUnH,EAAQiG,EAAQC,EAAQC,EAAY5O,EAAKa,EAAO+I,GAAO,IAGxFjD,EAGX,GAztBU,CAAC9F,GACJwF,GAAaxF,IAAUyF,GAAOzF,IAAUW,EAwtB3CqO,CAAMhP,GAKN,OAJAA,EAAMgM,SAAQ+C,IACVjJ,EAAOmJ,IAAIrB,GAAUmB,EAAUnH,EAAQiG,EAAQC,EAAQC,EAAYgB,EAAU/O,EAAO+I,GAAO,IAGxFjD,EAGX,GAAGH,GAAa3F,GACZ,OAAO8F,EAGX,MAIMmB,EAAS7B,OAAQ0B,GAJNgH,EACVD,EAASpF,GAAeF,GACxBsF,EAASqB,GAASnK,IAEmB/E,GAW5C,OATCiH,GAASjH,GAAOgM,SAAQ,CAAC+C,EAAU5P,KAC5B8H,IAEA8H,EAAW/O,EADXb,EAAM4P,IAIVnI,GAAYd,EAAQ3G,EAAKyO,GAAUmB,EAAUnH,EAAQiG,EAAQC,EAAQC,EAAY5O,EAAKa,EAAO+I,GAAO,IAGjGjD,CAAM,EAGXqI,GAAgB,CAACnH,EAAQlC,IACpBiC,GAAWC,EAAQwB,GAAaxB,GAASlC,GAG9C,GAAS,CAACA,EAAQqH,IACbA,EAAKtG,OAAS,EAAIf,EAAStF,GAAIsF,EAAQqH,EAAKgD,MAAM,GAAI,IAG3D1H,GAAM,CAAC3C,EAAQqH,EAAMnM,KACvB,IAAKuG,GAASzB,GACV,OAAOA,EAIX,MAAMe,GAFNsG,EAAOD,GAASC,EAAMrH,IAEFe,OACd8I,EAAY9I,EAAS,EAE3B,IAAIE,GAAS,EACTqJ,EAAStK,EAEb,KAAiB,MAAVsK,KAAoBrJ,EAAQF,GAAQ,CACvC,MAAM1G,EAAMuN,GAAMP,EAAKpG,IACvB,IAAIsJ,EAAWrP,EAEf,GAAI+F,GAAS4I,EAAW,CACpB,MAAM9H,EAAWuI,EAAOjQ,GACxBkQ,OAAWvI,OACMA,IAAbuI,IACAA,EAAW9I,GAASM,GACdA,EACCb,GAAQmG,EAAKpG,EAAQ,IAAM,GAAK,CAAC,EAEhD,CACAa,GAAYwI,EAAQjQ,EAAKkQ,GACzBD,EAASA,EAAOjQ,EACpB,CACA,OAAO2F,CAAM,EAGXkB,GAAU,CAAChG,EAAO6F,KACpB,MAAMW,SAAcxG,EAGpB,SAFA6F,EAAmB,MAAVA,EAAiByJ,OAAOC,iBAAmB1J,KAG1C,WAATW,GACa,WAATA,GAAqBvC,GAASE,KAAKnE,KACnCA,GAAS,GAAKA,EAAQ,GAAK,GAAKA,EAAQ6F,CAAO,EAGlD2J,GAAQ,CAAC1K,EAAQqH,KACnBA,EAAOD,GAASC,EAAMrH,GACtBA,EAAS,GAAOA,EAAQqH,GACxB,MAAMsD,EAActD,EAAKA,EAAKtG,OAAS,GACvC,OAAiB,MAAVf,UAAyBA,EAAO4H,GAAM+C,GAAa,EAGxD5G,GAAa7I,IACf,MAAMwG,SAAcxG,EACpB,MAAiB,WAATwG,GAA8B,WAATA,GAA8B,WAATA,GAA8B,YAATA,EACtD,cAAVxG,EACU,OAAVA,CAAe,EAGpBkP,GAAUpK,IACZ,MAAMgB,EAAS,GACf,IAAK,MAAM3G,KAAO2F,EACdgB,EAAOG,KAAK9G,GAEhB,OAAO2G,CAAM,EAYX4J,GAAU,CAAC5K,EAAQ3F,KACrB,IAAY,gBAARA,GAAgD,mBAAhB2F,EAAO3F,KAIhC,aAAPA,EAIJ,OAAO2F,EAAO3F,EAAI,EAGtB,SAASwQ,GAAeC,EAAUC,GAAU,GACxC,MAAO,CAAC/K,KAAWgL,KACf,IAAI/J,GAAS,EACTF,EAASiK,EAAQjK,OACjBkI,EAAalI,EAAS,EAAIiK,EAAQjK,EAAS,QAAKiB,EACpD,MAAMiJ,EAAQlK,EAAS,EAAIiK,EAAQ,QAAKhJ,EAexC,IAbAiH,EAAc6B,EAAS/J,OAAS,GAA2B,mBAAfkI,GACrClI,IAAUkI,GACX8B,EAAU,CAACG,EAAGC,KACZ,GAAI5K,MAAMC,QAAQ0K,KAAO3K,MAAMC,QAAQ2K,GACnC,OAAOA,CACX,OACAnJ,EAEJiJ,GAASzJ,GAAewJ,EAAQ,GAAIA,EAAQ,GAAIC,KAChDhC,EAAalI,EAAS,OAAIiB,EAAYiH,EACtClI,EAAS,GAEbf,EAASzF,OAAOyF,KACPiB,EAAQF,GAAQ,CACrB,MAAMmB,EAAS8I,EAAQ/J,GACnBiB,GACA4I,EAAS9K,EAAQkC,EAAQjB,EAAOgI,EAExC,CACA,OAAOjJ,CAAM,CAErB,CAEA,MAAMoL,GAAY,CAACpL,EAAQkC,EAAQmJ,EAAUpC,EAAYhF,KACjDjE,IAAWkC,GAIf,GAAMA,GAAQ,CAACoJ,EAAUjR,KACrB,GAAIoH,GAAS6J,GACTrH,IAAUA,EAAQ,IAAIU,IACtB4G,GAAcvL,EAAQkC,EAAQ7H,EAAKgR,EAAUD,GAAWnC,EAAYhF,OACjE,CACH,IAAIsG,EAAWtB,EACTA,EAAWjJ,EAAO3F,GAAMiR,EAAU,GAAGjR,IAAO2F,EAAQkC,EAAQ+B,QAC5DjC,OAEWA,IAAbuI,IACAA,EAAWe,GAGfE,GAAiBxL,EAAQ3F,EAAKkQ,EAClC,IACDH,GAAO,EAGRmB,GAAgB,CAACvL,EAAQkC,EAAQ7H,EAAKgR,EAAUI,EAAWxC,EAAYhF,KACzE,MAAMlC,EAAW6I,GAAQ5K,EAAQ3F,GAC3BiR,EAAWV,GAAQ1I,EAAQ7H,GAC3B2M,EAAU/C,EAAMvJ,IAAI4Q,GAE1B,GAAItE,EAEA,YADAwE,GAAiBxL,EAAQ3F,EAAK2M,GAIlC,IAAIuD,EAAWtB,EACTA,EAAWlH,EAAUuJ,EAAU,GAAGjR,IAAO2F,EAAQkC,EAAQ+B,QACzDjC,EAEFyG,OAAwBzG,IAAbuI,EAEf,GAAI9B,EAAU,CACV,MAAMnI,EAAQC,MAAMC,QAAQ8K,GACtBI,GAAWpL,GAASO,GAAayK,GAEvCf,EAAWe,EACPhL,GAASoL,EACLnL,MAAMC,QAAQuB,GACdwI,EAAWxI,EAENrB,GAAaqB,IAAa5B,GAAY4B,GAC3CwI,EAAWlI,GAAUN,GAEhB2J,GACLjD,GAAW,EACX8B,EAAW3H,GAAgB0I,GAAU,IAGrCf,EAAW,GAGVoB,GAAcL,IAAaM,GAAYN,IAC5Cf,EAAWxI,EACP6J,GAAY7J,GACZwI,EAjHM,CAACrP,IACnBA,EAAQX,OAAOW,GACf,MAAM8F,EAAS,CAAC,EAChB,IAAK,MAAM3G,KAAOa,EACd8F,EAAO3G,GAAOa,EAAMb,GAExB,OAAO2G,CAAM,EA2GU6K,CAAc9J,GAEA,mBAAbA,GAA4BN,GAASM,KACjDwI,EAAWtH,GAAgBqI,KAI/B7C,GAAW,CAEnB,CACIA,IAEAxE,EAAMtB,IAAI2I,EAAUf,GACpBkB,EAAUlB,EAAUe,EAAUD,EAAUpC,EAAYhF,GACpDA,EAAc,OAAEqH,IAEpBE,GAAiBxL,EAAQ3F,EAAKkQ,EAAS,EAGrCiB,GAAmB,CAACxL,EAAQ3F,EAAKa,WACpB8G,IAAV9G,IAAwBoG,GAAGtB,EAAO3F,GAAMa,SAC9B8G,IAAV9G,KAAyBb,KAAO2F,KACjC8B,GAAY9B,EAAQ3F,EAAKa,EAC7B,EAsBE4Q,GAAW,CAACC,EAAYC,KAC1B,GAAkB,MAAdD,EACA,OAAOA,EAEX,IAAK5L,GAAY4L,GACb,MATW,EAAC/L,EAAQgM,IACjBhM,GAhBX,SAAiBA,EAAQgM,EAAUC,GAC/B,MAAMC,EAAW3R,OAAOyF,GAClBmC,EAAQ8J,EAASjM,GACvB,IAAI,OAAEe,GAAWoB,EACblB,GAAS,EAEb,KAAOF,KAAU,CACb,MAAM1G,EAAM8H,IAAQlB,GACpB,IAA+C,IAA3C+K,EAASE,EAAS7R,GAAMA,EAAK6R,GAC7B,KAER,CACA,OAAOlM,CACX,CAGqBmM,CAAQnM,EAAQgM,EAAU/L,IAQhCmM,CAAWL,EAAYC,GAElC,MAAMjL,EAASgL,EAAWhL,OACpBmL,EAAW3R,OAAOwR,GACxB,IAAI9K,GAAS,EAEb,OAASA,EAAQF,IACsC,IAA/CiL,EAASE,EAASjL,GAAQA,EAAOiL,KAIzC,OAAOH,CAAU,EAQfM,GAAaC,KAAQ,EAAIxF,GAAW,IAAIwF,IAAI,MAACtK,GAAW,KAAK,IAAO,IACnEjC,GAAW,IAAIuM,IAAIvM,GACpB,OAEN,SAASwM,GAAoBxK,EAAUuJ,EAAUjR,EAAK2F,EAAQkC,EAAQ+B,GAOlE,OANIxC,GAASM,IAAaN,GAAS6J,KAE/BrH,EAAMtB,IAAI2I,EAAUvJ,GACpBqJ,GAAUrJ,EAAUuJ,OAAUtJ,EAAWuK,GAAqBtI,GAC9DA,EAAc,OAAEqH,IAEbvJ,CACX,CAEA,SAASyK,GAAYT,EAAYU,EAAWC,GAEpCD,EADAA,EAAU1L,OACE0L,EAAUvM,KAAK8L,GACnBzL,MAAMC,QAAQwL,GACN9Q,GAAUR,GAAIQ,EAA2B,IAApB8Q,EAASjL,OAAeiL,EAAS,GAAKA,GAGhEA,IAGC,CAAE9Q,GAAUA,GAG5B,IAAIyR,GAAiB,EACjBC,GAAa,EAEjB,MAAM5L,EAASb,GAAY4L,GAAc,IAAIxL,MAAMwL,EAAWhL,QAAU,GAYxE,OAVA+K,GAASC,GAAa7Q,IAClB,MAAM2R,EAAWJ,EAAUvM,KAAK8L,GAAaA,EAAS9Q,KAEtD8F,IAAS4L,GAAa,CAClBC,WACA5L,QAAS0L,EACTzR,QACH,IAMT,SAAoBmG,GAChB,IAAI,OAAEN,GAAWM,EAGjB,IADAA,EAAMyL,MANoB,CAAC9M,EAAQuB,IAjgBvC,SAAyBvB,EAAQuB,EAAOmL,GACpC,IAAIzL,GAAS,EACb,MAAM8L,EAAc/M,EAAO6M,SACrBG,EAAczL,EAAMsL,SACpB9L,EAASgM,EAAYhM,OACrBkM,EAAeP,EAAO3L,OAE5B,OAASE,EAAQF,GAAQ,CACrB,MAAMmM,EAAQjM,EAAQgM,EAAeP,EAAOzL,GAAS,KAE/CD,GADSkM,GAA0B,mBAAVA,EAAwBA,EAAQrF,IAC1CkF,EAAY9L,GAAQ+L,EAAY/L,IACrD,GAAID,EACA,OAAIkM,GAA0B,mBAAVA,EACTlM,GAAmB,QAATkM,GAAmB,EAAI,GAErClM,CAEf,CAEA,OAAOhB,EAAOiB,MAAQM,EAAMN,KAChC,CA6eiDkM,CAAgBnN,EAAQuB,EAAOmL,KAOrE3L,KACHM,EAAMN,GAAUM,EAAMN,GAAQ7F,MAElC,OAAOmG,CACX,CAXW+L,CAAWpM,EACtB,CAYA,SAASqM,GAAmBnS,GACxB,OAAOA,GAAUA,IAAUuG,GAASvG,EACxC,CAEA,SAASoS,GAAwBjT,EAAKiR,GAClC,OAAQtL,GACU,MAAVA,GAGGA,EAAO3F,KAASiR,SACLtJ,IAAbsJ,GAA2BjR,KAAOE,OAAOyF,GAEtD,CAEA,SAASuN,GAAMvN,EAAQqH,GACnB,OAAiB,MAAVrH,GAAkBwN,GAAQxN,EAAQqH,EAAMoG,GACnD,CAcA,SAASC,GAAYxL,GACjB,MAAMyL,EAOV,SAAsB3N,GAClB,MAAMgB,EAASf,GAAKD,GACpB,IAAIe,EAASC,EAAOD,OAEpB,KAAOA,KAAU,CACb,MAAM1G,EAAM2G,EAAOD,GACb7F,EAAQ8E,EAAO3F,GACrB2G,EAAOD,GAAU,CAAC1G,EAAKa,EAAOmS,GAAmBnS,GACrD,CACA,OAAO8F,CACX,CAjBsB4M,CAAa1L,GAC/B,OAAyB,IAArByL,EAAU5M,QAAgB4M,EAAU,GAAG,GAChCL,GAAwBK,EAAU,GAAG,GAAIA,EAAU,GAAG,IAEzD3N,GAAWA,IAAWkC,GAelC,SAAqBlC,EAAQkC,EAAQyL,GACjC,IAAI1M,EAAQ0M,EAAU5M,OACtB,MAAMA,EAASE,EAGf,GAAc,MAAVjB,EACA,OAAQe,EAEZ,IAAI+C,EACA9C,EAEJ,IADAhB,EAASzF,OAAOyF,GACTiB,KAEH,GADA6C,EAAO6J,EAAU1M,GACI6C,EAAK,GACpBA,EAAK,KAAO9D,EAAO8D,EAAK,MACtBA,EAAK,KAAM9D,GAEf,OAAO,EAGf,OAASiB,EAAQF,GAAQ,CACrB+C,EAAO6J,EAAU1M,GACjB,MAAM5G,EAAMyJ,EAAK,GACX/B,EAAW/B,EAAO3F,GAClBiR,EAAWxH,EAAK,GAEtB,GAAoBA,EAAK,IACrB,QAAiB9B,IAAbD,KAA4B1H,KAAO2F,GACnC,OAAO,MAER,CACH,MAAMiE,EAAQ,IAAIU,GAIlB,UAAiB3C,IAAXhB,EACAgD,GAAYsH,EAAUvJ,EAAUkC,GAChCjD,GAEF,OAAO,CAEf,CACJ,CACA,OAAO,CACX,CA3D4C6M,CAAY7N,EAAQkC,EAAQyL,EACxE,CAwEA,SAASG,GAAa5S,GAClB,MAAoB,mBAATA,EACAA,EAEE,MAATA,EACQ6S,GAAQA,EAEA,iBAAT7S,EACAqF,MAAMC,QAAQtF,IAlGAmM,EAmGKnM,EAAM,GAnGLoQ,EAmGSpQ,EAAM,GAlG1CiM,GAAME,IAASgG,GAAmB/B,GAC3BgC,GAAwB1F,GAAMP,GAAOiE,GAExCtL,IACJ,MAAM+B,EAAWrH,GAAIsF,EAAQqH,GAC7B,YAAqBrF,IAAbD,GAA0BA,IAAauJ,EACzCiC,GAAMvN,EAAQqH,GACdrD,GAAYsH,EAAUvJ,EAAS,GA4F/B2L,GAAYxS,GAtB1B,SAAkBmM,GACd,OAAOF,GAAME,IAGKhN,EAHgBuN,GAAMP,GAIhCrH,GAAqB,MAAVA,OAAiBgC,EAAYhC,EAAO3F,IAG3D,SAA0BgN,GACtB,OAAQrH,GAAWtF,GAAIsF,EAAQqH,EACnC,CATqD2G,CAAiB3G,GAGtE,IAAsBhN,CAFtB,CAsBW4T,CAAS/S,GAtGpB,IAA6BmM,EAAMiE,CAuGnC,CAEA,SAAS4C,KACL,MAAMlN,EAAS8M,GACf,OAAOK,UAAUpN,OAASC,EAAOmN,UAAU,GAAIA,UAAU,IAAMnN,CACnE,CAEA,MAAMoN,GAAc,CAAC/M,EAAO2K,EAAUqC,EAAaC,KAC/C,IAAIrN,GAAS,EACb,MAAMF,EAAkB,MAATM,EAAgB,EAAIA,EAAMN,OAKzC,IAHIuN,GAAavN,IACbsN,EAAchN,IAAQJ,MAEjBA,EAAQF,GACbsN,EAAcrC,EAASqC,EAAahN,EAAMJ,GAAQA,EAAOI,GAE7D,OAAOgN,CAAW,EAGhBE,GAAa,CAACxC,EAAYC,EAAUqC,EAAaC,EAAWE,KAC9DA,EAASzC,GAAY,CAAC7Q,EAAO+F,EAAO8K,KAChCsC,EAAcC,GACPA,GAAY,EAAOpT,GACpB8Q,EAASqC,EAAanT,EAAO+F,EAAO8K,EAAW,IAElDsC,GASLI,GAAiBvT,GACZqF,MAAMC,QAAQtF,IAAU0Q,GAAY1Q,OACxCA,IAASA,EAAMF,OAAO0T,qBAG7B,SAASC,GAAYtN,EAAOuN,EAAOvI,EAAWwI,EAAU7N,GACpD,IAAIC,GAAS,EACb,MAAMF,EAASM,EAAMN,OAKrB,IAHAsF,IAAcA,EAAYoI,IAC1BzN,IAAWA,EAAS,MAEXC,EAAQF,GAAQ,CACrB,IAAI7F,EAAQmG,EAAMJ,GACd2N,EAAQ,GAAKvI,EAAUnL,GACnB0T,EAAQ,EAERD,GAAYzT,EAAO0T,EAAQ,EAAGvI,EAAWwI,EAAU7N,GAEnDA,EAAOG,QAAQjG,GAEX2T,IACR7N,EAAOA,EAAOD,QAAU7F,EAEhC,CACA,OAAO8F,CACX,CAEA,MAAM4K,GAAe1Q,GACVwF,GAAaxF,IAA2B,sBAAjByF,GAAOzF,GA2BnCuS,GAAY,CAACzN,EAAQ3F,IACN,MAAV2F,GAAkB3F,KAAOE,OAAOyF,GAGrCwN,GAAU,CAACxN,EAAQqH,EAAMyH,KAO3B,IAJA,IAZc5T,EAYV+F,GAAS,EACTF,GAHJsG,EAAOD,GAASC,EAAMrH,IAGJe,OACdC,GAAS,IAEJC,EAAQF,GAAQ,CACrB,IAAI1G,EAAMuN,GAAMP,EAAKpG,IACrB,KAAMD,EAAmB,MAAVhB,GAAkB8O,EAAQ9O,EAAQ3F,IAC7C,MAEJ2F,EAASA,EAAO3F,EACpB,CACA,OAAI2G,KAAYC,GAASF,EACdC,KAEXD,EAAmB,MAAVf,EAAiB,EAAIA,EAAOe,SAzBd,iBADT7F,EA2Bc6F,IAzBxB7F,GAAS,GAAKA,EAAQ,GAAK,GAAKA,GAASsP,OAAOC,kBAyBbvJ,GAAQ7G,EAAK0G,KAC/CR,MAAMC,QAAQR,IAAW4L,GAAY5L,GAAQ,EAyBhD+O,GAGMtP,IACJ,IAAKA,EACD,MAAO,GAGX,MAAMuP,EAAaxP,GAAWC,GACxBC,GAAcD,QACduC,EAEAiN,EAAMD,EACNA,EAAW,GACXvP,EAAO,GAEPyP,EAAWF,EAtBP,EAAC3N,EAAO8N,EAAOC,KAC7B,MAAM,OAAErO,GAAWM,EAEnB,OADA+N,OAAcpN,IAARoN,EAAoBrO,EAASqO,EACQ/N,EAAMgJ,MAoBjB,EApB8B+E,EAAI,EAoBxDC,CAAUL,GAAe3Q,KAAK,IAC9BoB,EAAO4K,MAAM,GAEnB,OAAO4E,EAAc,cAAMC,CAAQ,EAS3C,MAAMvK,GACF,WAAA9C,CAAYyN,GACR,MAAMxL,EAAOyL,KAAK1L,SAAW,IAAI2L,GAAUF,GAC3CC,KAAKxI,KAAOjD,EAAKiD,IACrB,CAEA,KAAA0I,GACIF,KAAK1L,SAAW,IAAI2L,GACpBD,KAAKxI,KAAO,CAChB,CAEA,OAAO1M,GACH,MAAMyJ,EAAOyL,KAAK1L,SACZ7C,EAAS8C,EAAa,OAAEzJ,GAG9B,OADAkV,KAAKxI,KAAOjD,EAAKiD,KACV/F,CACX,CAEA,GAAAtG,CAAIL,GACA,OAAOkV,KAAK1L,SAASnJ,IAAIL,EAC7B,CAEA,GAAAkM,CAAIlM,GACA,OAAOkV,KAAK1L,SAAS0C,IAAIlM,EAC7B,CAEA,GAAAsI,CAAItI,EAAKa,GACL,IAAI4I,EAAOyL,KAAK1L,SAChB,GAAIC,aAAgB0L,GAAW,CAC3B,MAAME,EAAQ5L,EAAKD,SACnB,GAAI6L,EAAM3O,OAAS4O,IAGf,OAFAD,EAAMvO,KAAK,CAAC9G,EAAKa,IACjBqU,KAAKxI,OAASjD,EAAKiD,KACZwI,KAEXzL,EAAOyL,KAAK1L,SAAW,IAAI+L,GAASF,EACxC,CAGA,OAFA5L,EAAKnB,IAAItI,EAAKa,GACdqU,KAAKxI,KAAOjD,EAAKiD,KACVwI,IACX,EAGJ,MAAMC,GACF,WAAA3N,CAAYyN,GACR,IAAIrO,GAAS,EACb,MAAMF,EAAoB,MAAXuO,EAAkB,EAAIA,EAAQvO,OAG7C,IADAwO,KAAKE,UACIxO,EAAQF,GAAQ,CACrB,MAAM8O,EAAQP,EAAQrO,GACtBsO,KAAK5M,IAAIkN,EAAM,GAAIA,EAAM,GAC7B,CACJ,CAEA,KAAAJ,GACIF,KAAK1L,SAAW,GAChB0L,KAAKxI,KAAO,CAChB,CAEA,OAAO1M,GACH,MAAMyJ,EAAOyL,KAAK1L,SACZ5C,EAAQG,GAAa0C,EAAMzJ,GAEjC,QAAI4G,EAAQ,KAIRA,GADc6C,EAAK/C,OAAS,EAE5B+C,EAAKgM,MAELhM,EAAKiM,OAAO9O,EAAO,KAErBsO,KAAKxI,MACA,EACX,CAEA,GAAArM,CAAIL,GACA,MAAMyJ,EAAOyL,KAAK1L,SACZ5C,EAAQG,GAAa0C,EAAMzJ,GACjC,OAAO4G,EAAQ,OAAIe,EAAY8B,EAAK7C,GAAO,EAC/C,CAEA,GAAAsF,CAAIlM,GACA,OAAO+G,GAAamO,KAAK1L,SAAUxJ,IAAQ,CAC/C,CAEA,GAAAsI,CAAItI,EAAKa,GACL,MAAM4I,EAAOyL,KAAK1L,SACZ5C,EAAQG,GAAa0C,EAAMzJ,GAQjC,OANI4G,EAAQ,KACNsO,KAAKxI,KACPjD,EAAK3C,KAAK,CAAC9G,EAAKa,KAEhB4I,EAAK7C,GAAO,GAAK/F,EAEdqU,IACX,EAGJ,MAAMK,GACF,WAAA/N,CAAYyN,GACR,IAAIrO,GAAS,EACb,MAAMF,EAAoB,MAAXuO,EAAkB,EAAIA,EAAQvO,OAG7C,IADAwO,KAAKE,UACIxO,EAAQF,GAAQ,CACrB,MAAM8O,EAAQP,EAAQrO,GACtBsO,KAAK5M,IAAIkN,EAAM,GAAIA,EAAM,GAC7B,CACJ,CAEA,KAAAJ,GACIF,KAAKxI,KAAO,EACZwI,KAAK1L,SAAW,CACZ,KAAQ,IAAImM,GACZ,IAAO,IAAIC,IACX,OAAU,IAAID,GAEtB,CAEA,OAAO3V,GACH,MAAM2G,EAAS4C,GAAW2L,KAAMlV,GAAa,OAAEA,GAE/C,OADAkV,KAAKxI,MAAQ/F,EAAS,EAAI,EACnBA,CACX,CAEA,GAAAtG,CAAIL,GACA,OAAOuJ,GAAW2L,KAAMlV,GAAKK,IAAIL,EACrC,CAEA,GAAAkM,CAAIlM,GACA,OAAOuJ,GAAW2L,KAAMlV,GAAKkM,IAAIlM,EACrC,CAEA,GAAAsI,CAAItI,EAAKa,GACL,MAAM4I,EAAOF,GAAW2L,KAAMlV,GACxB0M,EAAOjD,EAAKiD,KAIlB,OAFAjD,EAAKnB,IAAItI,EAAKa,GACdqU,KAAKxI,MAAQjD,EAAKiD,MAAQA,EAAO,EAAI,EAC9BwI,IACX,EAGJ,MAAMS,GACF,WAAAnO,CAAYyN,GACR,IAAIrO,GAAS,EACb,MAAMF,EAAoB,MAAXuO,EAAkB,EAAIA,EAAQvO,OAG7C,IADAwO,KAAKE,UACIxO,EAAQF,GAAQ,CACrB,MAAM8O,EAAQP,EAAQrO,GACtBsO,KAAK5M,IAAIkN,EAAM,GAAIA,EAAM,GAC7B,CACJ,CAEA,KAAAJ,GACIF,KAAK1L,SAAWtJ,OAAO2I,OAAO,MAC9BqM,KAAKxI,KAAO,CAChB,CAEA,OAAO1M,GACH,MAAM2G,EAASuO,KAAKhJ,IAAIlM,WAAekV,KAAK1L,SAASxJ,GAErD,OADAkV,KAAKxI,MAAQ/F,EAAS,EAAI,EACnBA,CACX,CAEA,GAAAtG,CAAIL,GACA,MACM2G,EADOuO,KAAK1L,SACExJ,GACpB,OAAO2G,IAAWvC,QAAiBuD,EAAYhB,CACnD,CAEA,GAAAuF,CAAIlM,GAEA,YAAqB2H,IADRuN,KAAK1L,SACNxJ,EAChB,CAEA,GAAAsI,CAAItI,EAAKa,GACL,MAAM4I,EAAOyL,KAAK1L,SAGlB,OAFA0L,KAAKxI,MAAQwI,KAAKhJ,IAAIlM,GAAO,EAAI,EACjCyJ,EAAKzJ,QAAiB2H,IAAV9G,EAAsBuD,GAAiBvD,EAC5CqU,IACX,EAGJ,MAAMxJ,GACF,WAAAlE,CAAY9B,GACR,IAAIkB,GAAS,EACb,MAAMF,EAAmB,MAAVhB,EAAiB,EAAIA,EAAOgB,OAG3C,IADAwO,KAAK1L,SAAW,IAAI+L,KACX3O,EAAQF,GACbwO,KAAKpF,IAAIpK,EAAOkB,GAExB,CAEA,GAAAkJ,CAAIjP,GAEA,OADAqU,KAAK1L,SAASlB,IAAIzH,EAAOuD,IAClB8Q,IACX,CAEA,GAAAhJ,CAAIrL,GACA,OAAOqU,KAAK1L,SAAS0C,IAAIrL,EAC7B,EAGJ6K,GAASlL,UAAUsG,KAAO4E,GAASlL,UAAUsP,IAItC,MAKM1I,GAAW,SAASvG,GAC7B,QAASA,IAA2B,iBAAVA,GAAuC,mBAAVA,EAC3D,EAEagV,GAAW,SAAShV,GAC7B,IAAIoH,EAAW/H,OAAOM,UAAUyH,SAChC,MAAwB,iBAAVpH,KAAyBA,GAA0B,iBAAVA,GAAsBoH,EAASvH,KAAKG,KAAWQ,CAC1G,EAEayU,GAAW,SAASjV,GAC7B,IAAIoH,EAAW/H,OAAOM,UAAUyH,SAChC,MAAwB,iBAAVpH,KAAyBA,GAA0B,iBAAVA,GAAsBoH,EAASvH,KAAKG,KAAWY,CAC1G,EAEa,GAAS+O,IAAe,CAAC7K,EAAQkC,KAC1C,GAAIP,GAAYO,IAAW/B,GAAY+B,GACnCD,GAAWC,EAAQjC,GAAKiC,GAASlC,QAGrC,IAAK,IAAI3F,KAAO6H,EACRpH,eAAeC,KAAKmH,EAAQ7H,IAC5ByH,GAAY9B,EAAQ3F,EAAK6H,EAAO7H,GAExC,IAyCS+V,GAlCa,CAACpQ,KAAWgL,KAClC,IAAI/J,GAAS,EACTF,EAASiK,EAAQjK,OACrB,MAAMkK,EAAQlK,EAAS,EAAIiK,EAAQ,QAAKhJ,EAMxC,IAJIiJ,GAASzJ,GAAewJ,EAAQ,GAAIA,EAAQ,GAAIC,KAChDlK,EAAS,KAGJE,EAAQF,GAAQ,CACrB,MAAMmB,EAAS8I,EAAQ/J,GAEvB,GAAc,MAAViB,EACA,SAGJ,MAAMC,EAAQ5H,OAAO0F,KAAKiC,GACpBmO,EAAclO,EAAMpB,OAC1B,IAAIuP,GAAc,EAElB,OAASA,EAAaD,GAAa,CAC/B,MAAMhW,EAAM8H,EAAMmO,GACZpV,EAAQ8E,EAAO3F,SAEP2H,IAAV9G,GACCoG,GAAGpG,EAAOX,OAAOM,UAAUR,MAAUS,eAAeC,KAAKiF,EAAQ3F,MAClE2F,EAAO3F,GAAO6H,EAAO7H,GAE7B,CACJ,CAEA,OAAO2F,CAAM,EAUJuQ,GALiB,YAAyBC,GAEnD,OADAA,EAAKrP,UAAKa,EAAWuK,IACdkE,GAAMC,WAAM1O,EAAWwO,EAClC,EAKaG,GAAS,CAAC5E,EAAY1E,KAASmJ,KACxC,IAAIvP,GAAS,EACb,MAAMmI,EAAyB,mBAAT/B,EAChBrG,EAASb,GAAY4L,GAAc,IAAIxL,MAAMwL,EAAWhL,QAAU,GAMxE,OAJA+K,GAASC,GAAa7Q,IAClB8F,IAASC,GAASmI,EAAS/B,EAAKqJ,MAAMxV,EAAOsV,GAAQI,GAAe1V,EAAOmM,KAASmJ,EAAK,IAGtFxP,CAAM,EAIJ4P,GAAiB,CAAC5Q,EAAQqH,KAASmJ,KAC5CnJ,EAAOD,GAASC,EAAMrH,GAEtB,MAAM6Q,EAAiB,OADvB7Q,EAAS,GAAOA,EAAQqH,IACMrH,EAASA,EAAO4H,GAlpBlD,SAAcvG,GACV,MAAMN,EAAkB,MAATM,EAAgB,EAAIA,EAAMN,OACzC,OAAOA,EAASM,EAAMN,EAAS,QAAKiB,CACxC,CA+oBwD8O,CAAKzJ,KACzD,OAAe,MAARwJ,OAAe7O,EAAY6O,EAAKH,MAAM1Q,EAAQwQ,EAAK,EAGjDO,GAAc,CAAC1P,EAAOnG,EAAO8Q,KACtC,IAAIgF,EAAM,EACNC,EAAgB,MAAT5P,EAAgB,EAAIA,EAAMN,OACrC,GAAY,GAARkQ,EACA,OAAO,EAMX,MAAMC,GAFNhW,GADA8Q,EAAWkC,GAAYlC,EAAU,IAChB9Q,KAEUA,EACrB6M,EAAsB,OAAV7M,EACZ+M,EAAc7F,GAASlH,GACvBiW,OAA2BnP,IAAV9G,EAEvB,KAAO8V,EAAMC,GAAM,CACf,IAAIG,EACJ,MAAMC,EAAMC,KAAKC,OAAOP,EAAMC,GAAQ,GAChCrI,EAAWoD,EAAS3K,EAAMgQ,IAC1BnJ,OAA4BlG,IAAb4G,EACfT,EAAyB,OAAbS,EACZR,EAAiBQ,GAAaA,EAC9BP,EAAcjG,GAASwG,GAGzBwI,EADAF,EACS9I,EACF+I,EACE/I,GAAiBF,EACnBH,EACEK,GAAkBF,IAAiBC,EACrCF,EACEG,GAAkBF,IAAiBC,IAAcE,GACnDF,IAAaE,GAGXO,EAAW1N,EAEpBkW,EACAJ,EAAMK,EAAM,EAEZJ,EAAOI,CAEf,CACA,OAAOC,KAAKE,IAAIP,EA/xDI,WA+xDkB,EAG7BQ,GAAO,CAACpQ,EAAO2K,KACxB,IAAI/K,GAAS,EACTsH,EAAW,CAAClH,EAAOnG,MACK,MAATmG,IAAoBA,EAAMN,SACtBM,EAAMmH,QAAQtN,IAAU,EAE/C8Q,EAAWkC,GAAYlC,EAAU,GACjC,IAAIvD,GAAW,EAEf,MAAM,OAAE1H,GAAWM,EACbL,EAAS,GACf,IAAI8E,EAAO9E,EAEX,GAAID,GAv1DiB,IAu1DW,CAC5B,MAAM4B,EAAMqJ,EAAW,KAAOK,GAAUhL,GACxC,GAAIsB,EACA,OAAOmE,GAAWnE,GAEtB8F,GAAW,EACXF,EAAW,CAACjC,EAAOjM,IAAQiM,EAAMC,IAAIlM,GACrCyL,EAAO,IAAIC,EACf,MACID,EAAOkG,EAAW,GAAKhL,EAE3B2H,EACA,OAAS1H,EAAQF,GAAQ,CACrB,IAAI7F,EAAQmG,EAAMJ,GAClB,MAAM2H,EAAWoD,EAAWA,EAAS9Q,GAASA,EAG9C,GADAA,EAAmB,IAAVA,EAAeA,EAAQ,EAC5BuN,GAAYG,GAAaA,EAAU,CACnC,IAAI8I,EAAY5L,EAAK/E,OACrB,KAAO2Q,KACH,GAAI5L,EAAK4L,KAAe9I,EACpB,SAASD,EAGbqD,GACAlG,EAAK3E,KAAKyH,GAEd5H,EAAOG,KAAKjG,EAChB,MACUqN,EAASzC,EAAM8C,KACjB9C,IAAS9E,GACT8E,EAAK3E,KAAKyH,GAEd5H,EAAOG,KAAKjG,GAEpB,CACA,OAAO8F,CAAM,EAGJ2Q,GAASzW,GAAU4N,GAAU5N,GAE7B0W,GAAa1W,GAAU4N,GAAU5N,GAAO,GAExC2W,GAAW3W,IACpB,GAAa,MAATA,EACA,OAAO,EAEX,GAAIiF,GAAYjF,KACXqF,MAAMC,QAAQtF,IAA2B,iBAAVA,GAA8C,mBAAjBA,EAAM6U,QAC/DlP,GAAa3F,IAAU0Q,GAAY1Q,IACvC,OAAQA,EAAM6F,OAElB,MAAM0F,EAAM9F,GAAOzF,GACnB,GAAW,gBAAPuL,GAAgC,gBAAPA,EACzB,OAAQvL,EAAM6L,KAElB,GAAIpF,GAAYzG,GACZ,OAn0DS,CAAC8E,IACd,IAAK2B,GAAY3B,GACb,OAAOzF,OAAO0F,KAAKD,GAEvB,IAAIgB,EAAS,GACb,IAAK,IAAI3G,KAAOE,OAAOyF,GACflF,eAAeC,KAAKiF,EAAQ3F,IAAe,eAAPA,GACpC2G,EAAOG,KAAK9G,GAIpB,OAAO2G,CAAM,EAwzDD8Q,CAAS5W,GAAO6F,OAE5B,IAAK,MAAM1G,KAAOa,EACd,GAAIJ,eAAeC,KAAKG,EAAOb,GAC3B,OAAO,EAGf,OAAO,CAAI,EAEF0X,GAAU,CAAC/R,EAAQuB,IAAUyC,GAAYhE,EAAQuB,GAEjD,GAAcrG,GAA2B,mBAAVA,EAE/ByQ,GAAiBzQ,IAC1B,IAAKwF,GAAaxF,IAA2B,mBAAjByF,GAAOzF,GAC/B,OAAO,EAEX,GAAqC,OAAjCX,OAAO4I,eAAejI,GACtB,OAAO,EAEX,IAAI8W,EAAQ9W,EACZ,KAAwC,OAAjCX,OAAO4I,eAAe6O,IACzBA,EAAQzX,OAAO4I,eAAe6O,GAElC,OAAOzX,OAAO4I,eAAejI,KAAW8W,CAAK,EAGpCC,GAAW/W,IACpB,IAAKA,EACD,MAAO,GAGX,GAAIiF,GAAYjF,GACZ,OAAOiV,GAASjV,GAASwE,GAAcxE,GAASmH,GAAUnH,GAG9D,GAAIF,OAAOkX,UAAYlX,OAAOkX,YAAY3X,OAAOW,GAAQ,CACrD,MAAMgX,EAAWhX,EAAMF,OAAOkX,YAC9B,IAAIpO,EACJ,MAAM9C,EAAS,GAEf,OAAS8C,EAAOoO,EAASC,QAAQC,MAC7BpR,EAAOG,KAAK2C,EAAK5I,OAErB,OAAO8F,CACX,CAEA,MAAMyF,EAAM9F,GAAOzF,GAGnB,OAFauL,GAAOhL,EAASoL,GAAcJ,GAAO5K,EAASiL,GAAa/G,IAE5D7E,EAAM,EAiJTmX,GAAS,CAACtG,EAAYU,EAAY,MAC3C,GAAkB,MAAdV,EACA,MAAO,GAGX,MAAMhL,EAAS0L,EAAU1L,OAWzB,OAVIA,EAAS,GAAKS,GAAeuK,EAAYU,EAAU,GAAIA,EAAU,IACjEA,EAAY,GACL1L,EAAS,GAAKS,GAAeiL,EAAU,GAAIA,EAAU,GAAIA,EAAU,MAC1EA,EAAY,CAACA,EAAU,KAGtBlM,MAAMC,QAAQiM,KACfA,EAAY,CAACyB,GAAYzB,EAAW,KAGjCD,GAAYT,EAAYU,EAAU6F,KAAK,GAAI,GAAG,EAG5CC,GAAelR,GACA,MAATA,GAAoBA,EAAMN,OACzB4N,GAAYtN,EAAOmR,KAAY,GAGtCC,GAAU,CAACpR,KAAUtB,IAAWI,GAAYkB,GAASiH,GAAKjH,EAAOtB,GAAU,GAE3E2S,GAAa,CAACrR,KAAUtB,IACjCW,GAAaW,IAAUlB,GAAYkB,GAC/BiH,GAAKjH,EAAOtB,EAAOuS,KAAK,IAAM,GAYzBK,GAAQ,IAAIC,KACrB,MAAMvR,EAAQuR,EAAON,KAAK,GAC1B,OAAOb,GAAKpQ,EAAM,EAGT,GAAM,CAACrB,EAAQ3F,KACxB,GAAc,MAAV2F,EACA,OAAO,EAGQ,iBAAR3F,IACPA,EAAMA,EAAIwF,MAAM,MAGpB,IAAIoB,GAAS,EACT/F,EAAQ8E,EAEZ,OAASiB,EAAQ5G,EAAI0G,QAAQ,CACzB,IAAK7F,IAAUJ,eAAeC,KAAKG,EAAOb,EAAI4G,IAC1C,OAAO,EAEX/F,EAAQA,EAAMb,EAAI4G,GACtB,CAEA,OAAO,CAAI,EAGFD,GAAS,CAAChB,EAAQqH,EAAMwL,KAGjC,IAAI5R,GAAS,EACTF,GAHJsG,EAAOD,GAASC,EAAMrH,IAGJe,OAMlB,IAJKA,IACDA,EAAS,EACTf,OAASgC,KAEJf,EAAQF,GAAQ,CACrB,IAAI7F,EAAkB,MAAV8E,OAAiBgC,EAAYhC,EAAO4H,GAAMP,EAAKpG,UAC7Ce,IAAV9G,IACA+F,EAAQF,EACR7F,EAAQ2X,GAEZ7S,EAA0B,mBAAV9E,EAAuBA,EAAMH,KAAKiF,GAAU9E,CAChE,CACA,OAAO8E,CAAM,EAGJ,GAAO,CAACA,KAAW8S,KAC5B,IAAI9R,EAAS,CAAC,EACd,GAAc,MAAVhB,EACA,OAAOgB,EAEX,IAAI8B,GAAS,EACbgQ,EAAQA,EAAMR,KAAK,GAAGpS,KAAKmH,IACvBA,EAAOD,GAASC,EAAMrH,GACtB8C,IAAWA,EAASuE,EAAKtG,OAAS,GAC3BsG,KAEXpF,GAAWjC,EAAQ2D,GAAa3D,GAASgB,GACrC8B,IACA9B,EAAS8H,GAAU9H,GAAQ,GAAM,GAAM,GAAO9F,GAAUyQ,GAAczQ,QAAS8G,EAAY9G,KAE/F,IAAI6F,EAAS+R,EAAM/R,OACnB,KAAOA,KACH2J,GAAM1J,EAAQ8R,EAAM/R,IAExB,OAAOC,CAAM,EAGJ+R,GAAO,CAAC/S,KAAW8S,IACX,MAAV9S,EAAiB,CAAC,EAp0BZ,EAACA,EAAQ8S,IAIP,EAAC9S,EAAQ8S,EAAOzM,KAC/B,IAAIpF,GAAS,EACb,MAAMF,EAAS+R,EAAM/R,OACfC,EAAS,CAAC,EAEhB,OAASC,EAAQF,GAAQ,CACrB,MAAMsG,EAAOyL,EAAM7R,GACb/F,EAAQR,GAAIsF,EAAQqH,GACtBhB,EAAUnL,EAAOmM,IACjB1E,GAAI3B,EAAQoG,GAASC,EAAMrH,GAAS9E,EAE5C,CACA,OAAO8F,CAAM,EAfNgS,CAAWhT,EAAQ8S,GAAO,CAAC5X,EAAOmM,IAASkG,GAAMvN,EAAQqH,KAm0BnC4L,CAASjT,EAAQ8S,EAAMR,KAAKE,MAWhD,GAAQ,CAACxS,EAAQgM,EAAY9Q,GAAUA,KAChD,IAAI+F,GAAS,EACb,MAAMiL,EAAW3R,OAAOyF,GAClBmC,EAAQhC,GAAYH,GAAUI,GAAcJ,GAAQ,GAAQoK,GAAOpK,GACzE,IAAIe,EAASoB,EAAMpB,OAEnB,KAAMA,KAAU,CACZ,MAAM1G,EAAM8H,IAAQlB,GACpB,IAA+C,IAA3C+K,EAASE,EAAS7R,GAAMA,EAAK6R,GAC7B,KAER,GAGSgH,GAAY,CAACzT,EAAS,KAnyBrB,EAACA,EAAQ0T,KACnB,QAAgBnR,IAAZmR,EAAuB,CACvB,MAAMnS,EAAS5B,GAAeK,GANjB,CAACA,GACXA,EAAOE,MAAMpB,IAKwB6U,CAAa3T,GAV1C,CAACA,GACTA,EAAOE,MAAMJ,IAS+C8T,CAAW5T,GAC1E,OAAOuB,GAAU,EACrB,CACA,OAAOvB,EAAOE,MAAMwT,IAAY,EAAE,EA+xBlCG,CAAM,GAAG7T,IAAS6H,QAAQ,aAAc,KACnCiM,QAAO,CAACvS,EAAQwS,EAAMvS,KACnBuS,EAAOA,EAAKC,cACLzS,GAAUC,EAAQ8N,GAAWyE,GAAQA,KAC7C,IAGX,IAAIE,GAAY,EAET,MAAMC,GAAW,CAACC,EAAS,KAEvB,GAAGA,OADGF,GAIJjD,GAAQ5F,IAAe,CAAC7K,EAAQkC,EAAQmJ,EAAUpC,KAC3DmC,GAAUpL,EAAQkC,EAAQmJ,EAAUpC,EAAW,IAChD,GCtzEH,GA5CA,MAEI,WAAApH,GACI0N,KAAKrP,IAAM,IAAI2T,OACnB,CAEA,GAAAtN,CAAI5L,EAAKN,GACL,YAAY2H,IAAR3H,EAA0BkV,KAAKrP,IAAIqG,IAAI5L,GACpCN,KAAOkV,KAAKrP,IAAIxF,IAAIC,EAC/B,CAEA,MAAAuI,CAAOvI,GAEH,OADK4U,KAAKhJ,IAAI5L,IAAM4U,KAAKrP,IAAIyC,IAAIhI,EAAKJ,OAAO2I,OAAO,OAC7CqM,KAAK7U,IAAIC,EACpB,CAEA,GAAAD,CAAIC,EAAKN,GACL,IAAKkV,KAAKhJ,IAAI5L,GAAM,OACpB,MAAMmJ,EAAOyL,KAAKrP,IAAIxF,IAAIC,GAC1B,YAAYqH,IAAR3H,EAA0ByJ,EACvBA,EAAKzJ,EAChB,CAEA,GAAAsI,CAAIhI,EAAKN,EAAKa,GACV,QAAY8G,IAAR3H,EAAmB,OACvB,MAAMyJ,EAAOyL,KAAKrM,OAAOvI,GACN,iBAARN,EACPyJ,EAAKzJ,GAAOa,EAEZX,OAAOgP,OAAOzF,EAAMzJ,EAE5B,CAEA,MAAAyZ,CAAOnZ,EAAKN,GACHkV,KAAKhJ,IAAI5L,UACFqH,IAAR3H,EACAkV,KAAKrP,IAAI6T,OAAOpZ,UAEH4U,KAAKrP,IAAIxF,IAAIC,GACdN,GAEpB,GCvCS2Z,GAAW,IAAI,GAEfC,GAAW,IAAI,GCJfC,GAAQ,SAASC,EAAKhS,GAE/B,KAAMoN,gBAAgB2E,IAClB,OAAO,IAAIA,GAAMC,EAAKhS,GAItBgS,GAAOA,EAAIzS,MACX6N,KAAK6E,cAAgBD,EACrB5E,KAAK7N,KAAOyS,EAAIzS,KAIhB6N,KAAK8E,mBAAqBF,EAAIG,iBACxBC,GACAC,GAGNjF,KAAKkF,OAASN,EAAIM,OAClBlF,KAAKmF,cAAgBP,EAAIO,cACzBnF,KAAKoF,cAAgBR,EAAIQ,eAIzBpF,KAAK7N,KAAOyS,EAIZhS,GACA5H,OAAOgP,OAAOgG,KAAMpN,GAIxBoN,KAAKqF,UAAaT,GAAOA,EAAIS,WAAcC,KAAKC,MAGhDvF,KAAKwF,UAAW,CACpB,EAsFA,SAASR,KACL,OAAO,CACX,CAEA,SAASC,KACL,OAAO,CACX,CAxFAN,GAAMrZ,UAAY,CACdgH,YAAaqS,GACbG,mBAAoBG,GACpBQ,qBAAsBR,GACtBS,8BAA+BT,GAC/BU,eAAgB,WACZ,MAAMC,EAAM5F,KAAK6E,cACjB7E,KAAK8E,mBAAqBE,GACtBY,GACAA,EAAID,gBAEZ,EACAE,gBAAiB,WACb,MAAMD,EAAM5F,KAAK6E,cACjB7E,KAAKyF,qBAAuBT,GACxBY,GACAA,EAAIC,iBAEZ,EACAC,yBAA0B,WACtB,MAAMF,EAAM5F,KAAK6E,cACjB7E,KAAK0F,8BAAgCV,GACjCY,GACAA,EAAIE,2BAER9F,KAAK6F,iBACT,GAIJ,CACI,SACA,UACA,aACA,iBACA,UACA,SACA,aACA,UACA,QACA,QACA,WACA,OACA,OACA,OACA,WACA,MACA,UACA,SACA,UACA,UACA,UACA,UACA,UACA,YACA,cACA,UACA,UACA,gBACA,YACA,UACA,SACFlO,SAASR,GAEX,SAAiBA,GACbnM,OAAOC,eAAe0Z,GAAMrZ,UAAW6L,EAAM,CACzCjM,YAAY,EACZ6a,cAAc,EACd5a,IAAK,WACD,OAAO6U,KAAK6E,cAAgB7E,KAAK6E,cAAc1N,QAAQ1E,CAC3D,EACAW,IAAK,SAASzH,GACVX,OAAOC,eAAe+U,KAAM7I,EAAM,CAC9BjM,YAAY,EACZ6a,cAAc,EACdC,UAAU,EACVra,MAAOA,GAEf,GAER,CAlBoBsa,CAAQ9O,KCvF5B,MAAM,GAA8B,oBAAX+O,OAA0BA,OAAOC,SAAW,KAC/DC,GAAkB,IAAY,GAASA,gBAEvCC,GAAiB,sBAKjBC,GAAgB,oBAGhB,GAAI,SAASC,GAGf,OAAO,IAAI,GAAEC,IAAID,EACrB,EAEA,GAAEE,GAAK,GAAEnb,UAAY,CACjBgH,YAAa,GAEbd,OAAQ,GAIZ,GAAEkV,KAAO,EAGT,GAAEnS,KAAOmQ,GAET,GAAExD,MAAQ,SAASyF,EAAOC,GACtB,IAAIC,GAAOD,EAAOpV,OACdsV,EAAIH,EAAMnV,OACd,IAAK,IAAIuV,EAAI,EAAGA,EAAIF,EAAKE,IACrBJ,EAAMG,KAAOF,EAAOG,GAGxB,OADAJ,EAAMnV,OAASsV,EACRH,CACX,EAEA,GAAEK,UAAY,SAAS9W,GAEnB,MAAM+W,EAAU,GAASC,eAAeC,qBAGlCC,EAAOH,EAAQI,cAAc,QACnCD,EAAKE,KAAO,GAASC,SAASD,KAC9BL,EAAQO,KAAKC,YAAYL,GAEzBH,EAAQS,KAAKC,UAAYzX,EAEzB,MAAM0X,EAAUX,EAAQY,qBAAqB,UAC7C,IAAK,IAAIf,EAAI,EAAGA,EAAIc,EAAQpW,OAAQsV,IAChCc,EAAQd,GAAGvC,SAEf,OAAOvT,MAAM8W,KAAKb,EAAQS,KAAKK,WACnC,EAEsB,mBAAXtc,SACP,GAAEgb,GAAGhb,OAAOkX,UAAY3R,MAAM1F,UAAUG,OAAOkX,WAGnD,GAAE8D,GAAG/D,QAAU,WACX,OAAO1R,MAAM8W,KAAK9H,KACtB,EAIA,GAAEyG,GAAGuB,UAAY,SAASC,GAEtB,MAAMC,EAAM,GAAEhH,MAAMlB,KAAK1N,cAAe2V,GAIxC,OAFAC,EAAIC,WAAanI,KAEVkI,CACX,EAEA,GAAEzB,GAAG2B,KAAO,SAAS7B,GACjB,MAAO8B,GAAMrI,KACPkI,EAAMlI,KAAKgI,UAAU,IAC3B,IAAKK,EAAI,OAAOH,EAEhB,MAAM,SAAEI,GAAaD,EACrB,OAAiB,IAAbC,GAA+B,IAAbA,GAA+B,KAAbA,IAGhB,iBAAb/B,EACH8B,IAAO9B,GAAY8B,EAAGE,SAAShC,IAC/B,GAAErF,MAAMgH,EAAK,CAAC3B,IAGlB,GAAErF,MAAMgH,EAAKG,EAAGG,iBAAiBjC,KAP1B2B,CAUf,EAEA,GAAEzB,GAAG7L,IAAM,SAAS2L,EAAUU,GAC1B,MAAMwB,EAAc,GAAElC,EAAUU,GAASvE,UACnCgG,EAAe1I,KAAK0C,UACpBwF,EAAMlI,KAAKgI,UAAU,IAE3B,OADA,GAAE9G,MAAMgH,EAAKhG,GAAKwG,EAAaC,OAAOF,KAC/BP,CACX,EAEA,GAAEzB,GAAGmC,QAAU,WACX,OAAO5I,KAAKpF,IAAIoF,KAAKmI,WACzB,EAEA,GAAE1B,GAAG1S,OAAS,SAASwS,GACnB,MAAMsC,EAAU,GAChB,IAAK,IAAI/B,EAAI,EAAGA,EAAI9G,KAAKxO,OAAQsV,IAAK,CAClC,MAAMgC,EAAO9I,KAAK8G,GACbgC,EAAKD,QAAQtC,IAClBsC,EAAQjX,KAAKkX,EACjB,CACA,OAAO9I,KAAKgI,UAAUa,EAC1B,EAMA,MAAME,GAAa,sCAQbvC,GAAM,SAASD,GACjB,IAAKA,EAED,OAAOvG,KAEX,GAAwB,mBAAbuG,EAGP,MAAM,IAAIyC,MAAM,0BAEpB,GAAIpK,UAAUpN,OAAS,EACnB,MAAM,IAAIwX,MAAM,uCAEpB,GAAIzC,EAAS+B,SAIT,OAFAtI,KAAK,GAAKuG,EACVvG,KAAKxO,OAAS,EACPwO,KAEX,IAAI5P,EACJ,GAxBiB,OAFEuJ,EA0BD4M,EAAW,IAxBnB,IAA0C,MAA5B5M,EAAMA,EAAMnI,OAAS,IAAcmI,EAAMnI,QAAU,EA6BvEpB,EAAQ,CAAC,KAAMmW,EAAU,UACtB,IAAwB,iBAAbA,EAKd,OAAO,GAAErF,MAAMlB,KAAMuG,GAHrBnW,EAAQ2Y,GAAW1O,KAAKkM,EAI5B,CAtCJ,IAAuB5M,EAuCnB,IAAKvJ,IAAUA,EAAM,GAEjB,OAAO6Y,GAAMb,KAAK7B,GAItB,GAAInW,EAAM,GAGN,OADA,GAAE8Q,MAAMlB,KAAM,GAAEgH,UAAU5W,EAAM,KACzB4P,KAGX,MAAMqI,EAAK,GAASa,eAAe9Y,EAAM,IAMzC,OALIiY,IAEArI,KAAK,GAAKqI,EACVrI,KAAKxO,OAAS,GAEXwO,IACX,EAEA,GAAEwG,IAAMA,GAGRA,GAAIlb,UAAY,GAAEmb,GAIlB,GAAE9B,MAAQA,GAEV,GAAEwE,MAAQ,CACNC,QAASpe,OAAO2I,OAAO,OAG3B,GAAEwV,MAAMnS,IAAM,SAASqS,EAAMC,GACzB,MAAMC,EAAS9E,GAAStZ,IAAIke,EAAM,UAClC,QAAKE,KACAD,GACEtY,MAAMC,QAAQsY,EAAOD,KAAeC,EAAOD,GAAW9X,OAAS,EAC1E,EAEA,GAAE2X,MAAMK,GAAK,SAASH,EAAMI,EAAOlD,EAAUhS,EAAMkS,EAAIiD,GAGnD,GAAqB,iBAAVD,EAAoB,CAEH,iBAAblD,IAEPhS,EAAOA,GAAQgS,EACfA,OAAW9T,GAEf,IAAK,IAAIN,KAAQsX,EACb,GAAEN,MAAMK,GAAGH,EAAMlX,EAAMoU,EAAUhS,EAAMkV,EAAMtX,GAAOuX,GAExD,OAAOL,CACX,CAkBA,GAhBY,MAAR9U,GAAsB,MAANkS,GAEhBA,EAAKF,EACLhS,EAAOgS,OAAW9T,GACL,MAANgU,IACiB,iBAAbF,GAEPE,EAAKlS,EACLA,OAAO9B,IAGPgU,EAAKlS,EACLA,EAAOgS,EACPA,OAAW9T,KAGdgU,EACD,OAAO4C,EAEX,GAAY,IAARK,EAAW,CACX,MAAMC,EAASlD,EACfA,EAAK,SAAS0C,GAGV,OADA,KAAIS,IAAIT,GACDQ,EAAOxI,MAAMnB,KAAMpB,UAC9B,EAGA6H,EAAGC,KAAOiD,EAAOjD,OAASiD,EAAOjD,KAAO,GAAEA,OAC9C,CACA,IAAK,IAAII,EAAI,EAAGA,EAAIuC,EAAK7X,OAAQsV,IAC7B,GAAEqC,MAAMvO,IAAIyO,EAAKvC,GAAI2C,EAAOhD,EAAIlS,EAAMgS,EAE9C,EAEA,GAAE4C,MAAMvO,IAAM,SAASyO,EAAMI,EAAOI,EAAStV,EAAMgS,GAE/C,GAAmB,iBAAR8C,EACP,OAGJ,MAAMS,EAAWrF,GAAS9Q,OAAO0V,GAGjC,IAAIU,EAmBAR,EAIAS,EAtBAH,EAAQA,UACRE,EAAcF,EACdA,EAAUE,EAAYF,QACtBtD,EAAWwD,EAAYxD,UAKvBA,GACAH,GAAgByC,QAAQtC,GAIvBsD,EAAQnD,OACTmD,EAAQnD,KAAO,GAAEA,SAKf6C,EAASO,EAASP,UACpBA,EAASO,EAASP,OAASve,OAAO2I,OAAO,QAGvCqW,EAAcF,EAASG,UACzBD,EAAcF,EAASG,OAAS,SAASC,GAGrC,YAAqB,IAAN,GACT,GAAEf,MAAMgB,SAAShJ,MAAMkI,EAAMzK,gBAC7BnM,CACV,GAIJ,MAAM2X,GAAYX,GAAS,IAAIrZ,MAAMkW,KAAkB,CAAC,IACxD,IAAIQ,EAAIsD,EAAS5Y,OACjB,KAAOsV,KAAK,CACR,MAAO,CAAEuD,EAAUC,EAAK,IAAMjE,GAAehM,KAAK+P,EAAStD,IAE3D,IAAKuD,EACD,SAGJ,MAAME,EAAaD,EAAGha,MAAM,KAAKiN,OAEjC,IAAI6L,EAAU,GAAED,MAAMC,QAAQiB,GAE9B,MAAMlY,EAAQiX,IAAY7C,EAAW6C,EAAQoB,aAAepB,EAAQqB,WAAcJ,EAElFjB,EAAU,GAAED,MAAMC,QAAQjX,GAE1B,MAAMuY,EAAY1f,OAAOgP,OACrB,CACI7H,KAAMA,EACNkY,SAAUA,EACV9V,KAAMA,EACNsV,QAASA,EACTnD,KAAMmD,EAAQnD,KACdH,SAAUA,EACVoE,UAAWJ,EAAWzb,KAAK,MAE/Bib,GAGJ,IAAIa,GAEEA,EAAWrB,EAAOpX,MACpByY,EAAWrB,EAAOpX,GAAQ,GAC1ByY,EAASC,cAAgB,EAIpBzB,GAAYA,EAAQ0B,QAC2C,IAA5D1B,EAAQ0B,MAAMtf,KAAK6d,EAAM9U,EAAMgW,EAAYP,IAE3CX,EAAK0B,kBACL1B,EAAK0B,iBAAiB5Y,EAAM6X,IAKpCZ,GAAWA,EAAQxO,MACnBwO,EAAQxO,IAAIpP,KAAK6d,EAAMqB,GAClBA,EAAUb,QAAQnD,OACnBgE,EAAUb,QAAQnD,KAAOmD,EAAQnD,OAKrCH,EACAqE,EAASpK,OAAOoK,EAASC,gBAAiB,EAAGH,GAE7CE,EAAShZ,KAAK8Y,EAEtB,CACJ,EAGA,GAAEvB,MAAM5E,OAAS,SAAS8E,EAAMI,EAAOI,EAAStD,EAAUyE,GAEtD,MAAMlB,EAAWrF,GAAStZ,IAAIke,GAC9B,IAAKS,IAAaA,EAASP,OAAQ,OACnC,MAAMA,EAASO,EAASP,OAGlBa,GAAYX,GAAS,IAAIrZ,MAAMkW,KAAkB,CAAC,IACxD,IAAIQ,EAAIsD,EAAS5Y,OACjB,KAAOsV,KAAK,CACR,MAAO,CAAEuD,EAAUC,EAAK,IAAMjE,GAAehM,KAAK+P,EAAStD,IAE3D,IAAKuD,EAAU,CACX,IAAK,MAAMlY,KAAQoX,EACf,GAAEJ,MAAM5E,OACJ8E,EACAlX,EAAOiY,EAAStD,GAChB+C,EACAtD,GACA,GAGR,QACJ,CAEA,MAAM6C,EAAU,GAAED,MAAMC,QAAQiB,GAC1BlY,EAAQiX,IAAY7C,EAAW6C,EAAQoB,aAAepB,EAAQqB,WAAcJ,EAC5EO,EAAWrB,EAAOpX,GACxB,IAAKyY,GAAgC,IAApBA,EAASpZ,OAAc,SAExC,MAAM+Y,EAAaD,EAAGha,MAAM,KAAKiN,OAC3B0N,EAAaX,EACb,IAAIrb,OAAO,UAAYsb,EAAWzb,KAAK,iBAAmB,WAC1D,KAGAoc,EAAYN,EAASpZ,OAC3B,IAAIuV,EAAImE,EACR,KAAOnE,KAAK,CACR,MAAM2D,EAAYE,EAAS7D,IAGtBiE,GAAeX,IAAaK,EAAUL,UACjCR,GAAWA,EAAQnD,OAASgE,EAAUhE,MACtCuE,IAAcA,EAAWnb,KAAK4a,EAAUC,YACxCpE,GACEA,IAAamE,EAAUnE,WACT,OAAbA,IAAqBmE,EAAUnE,YAExCqE,EAASpK,OAAOuG,EAAG,GACf2D,EAAUnE,UACVqE,EAASC,gBAETzB,GAAWA,EAAQ7E,QACnB6E,EAAQ7E,OAAO/Y,KAAK6d,EAAMqB,GAGtC,CAIIQ,GAAiC,IAApBN,EAASpZ,SAEjB4X,GAAYA,EAAQ+B,WAC4C,IAA7D/B,EAAQ+B,SAAS3f,KAAK6d,EAAMkB,EAAYT,EAASG,SAGjDZ,EAAK+B,qBACL/B,EAAK+B,oBAAoBjZ,EAAM2X,EAASG,eAGzCV,EAAOpX,GAEtB,CAGImQ,GAAQiH,KACR9E,GAASF,OAAO8E,EAAM,UACtB5E,GAASF,OAAO8E,EAAM,UAE9B,EAEA,GAAEF,MAAMgB,SAAW,SAASkB,GAExB,MAAMhC,EAAOrJ,KAEPmJ,EAAQ,GAAEA,MAAMmC,IAAID,GAC1BlC,EAAMoC,eAAiBlC,EAEvB,MAAMpI,EAAOjQ,MAAM8W,KAAKlJ,WACxBqC,EAAK,GAAKkI,EAEV,MAAMqC,EAAa/G,GAAStZ,IAAIke,EAAM,UAChCuB,EAAYY,GAAcA,EAAWrC,EAAMhX,OAAU,GACrDiX,EAAU,GAAED,MAAMC,QAAQD,EAAMhX,MAGtC,GAAIiX,GAAWA,EAAQqC,cAC2B,IAA1CrC,EAAQqC,YAAYjgB,KAAK6d,EAAMF,GAAkB,OAIzD,MAAMuC,EAAe,GAAEvC,MAAMyB,SAASpf,KAAK6d,EAAMF,EAAOyB,GAGxD,IACIe,EADA7E,EAAI,EAER,MAAQ6E,EAAUD,EAAa5E,QAAUqC,EAAM1D,wBAAwB,CACnE0D,EAAMhE,cAAgBwG,EAAQtC,KAC9B,IACIqB,EADA3D,EAAI,EAER,MACK2D,EAAYiB,EAAQf,SAAS7D,QACzBoC,EAAMzD,iCACb,CAEEyD,EAAMuB,UAAYA,EAClBvB,EAAM5U,KAAOmW,EAAUnW,KAEvB,MAAMqX,EAAc,GAAEzC,MAAMC,QAAQsB,EAAUL,UAC9C,IAAIR,EAEAA,EADA+B,GAAeA,EAAY3B,OACjB2B,EAAY3B,OAEZS,EAAUb,QAGxB,MAAM3B,EAAM2B,EAAQ1I,MAAMwK,EAAQtC,KAAMpI,QAC5BxO,IAARyV,IAC6B,KAAxBiB,EAAM1X,OAASyW,KAChBiB,EAAMxD,iBACNwD,EAAMtD,kBAGlB,CACJ,CAOA,OAJIuD,GAAWA,EAAQyC,cACnBzC,EAAQyC,aAAargB,KAAK6d,EAAMF,GAG7BA,EAAM1X,MACjB,EAEA,GAAE0X,MAAMyB,SAAW,SAASzB,EAAOyB,GAE/B,MAAMC,EAAgBD,EAASC,cACzBa,EAAe,GAGrB,GACIb,KAMqB,UAAf1B,EAAMhX,MAAoBgX,EAAM2C,QAAU,GAEhD,IAAK,IAAIC,EAAM5C,EAAMjE,OAAQ6G,IAAQ/L,KAAM+L,EAAMA,EAAIC,YAAchM,KAG/D,GACqB,IAAjB+L,EAAIzD,WACiB,UAAfa,EAAMhX,OAAqC,IAAjB4Z,EAAIE,UACtC,CACE,MAAMC,EAAkB,GAClBC,EAAmB,CAAC,EAC1B,IAAK,IAAIrF,EAAI,EAAGA,EAAI+D,EAAe/D,IAAK,CACpC,MAAM4D,EAAYE,EAAS9D,GAErBsF,EAAM1B,EAAUnE,SAAW,SACH9T,IAA1B0Z,EAAiBC,KACjBD,EAAiBC,GAAOL,EAAIlD,QAAQuD,IAEpCD,EAAiBC,IACjBF,EAAgBta,KAAK8Y,EAE7B,CACIwB,EAAgB1a,QAChBka,EAAa9Z,KAAK,CACdyX,KAAM0C,EACNnB,SAAUsB,GAGtB,CAYR,OAPIrB,EAAgBD,EAASpZ,QACzBka,EAAa9Z,KAAK,CACdyX,KAAMrJ,KACN4K,SAAUA,EAAS9P,MAAM+P,KAI1Ba,CACX,EAEA,GAAEvC,MAAMmC,IAAM,SAASzG,GACnB,OAAOA,EAAcW,SAAWX,EAAgB,IAAIF,GAAME,EAC9D,EAGA,MAAMoE,GAAQ,GAAE,KCvkBV,MACFoD,GAAK,MACLrK,GAAK,GACLsK,IACAvK,KAESwK,GAAQ,CAGjBC,OAAQ,SAASC,EAAQC,EAAO/gB,GAE5B,IAAIghB,EAAaF,EAAO,GAAKA,EAAO,GAChCG,EAAYF,EAAM,GAAKA,EAAM,GACjC,OAAU/gB,EAAQ8gB,EAAO,IAAME,EAAcC,EAAYF,EAAM,IAAO,CAC1E,GAGSG,GAAiB,SAASC,GAEnC,OAAQA,EAAQ,KAAQA,EAAQ,EAAI,IAAM,EAC9C,EAEaC,GAAa,SAASphB,EAAOqhB,GAEtC,OAAOA,EAAWX,GAAM1gB,EAAQqhB,EACpC,EAEaC,GAAQ,SAASC,GAE1B,OAAQ,IAAMA,EAAMZ,GAAM,GAC9B,EAEaa,GAAQ,SAASC,EAAKC,GAI/B,OADAD,GADAC,EAAUA,IAAW,GACLD,EAAOA,EAAM,KAChBd,GAAK,GACtB,EAGagB,GAAS,SAASrL,EAAKsL,GAEhC,QAAY9a,IAAR8a,EAEAA,OAAe9a,IAARwP,EAAqB,EAAIA,EAChCA,EAAM,OAEH,GAAIsL,EAAMtL,EAAK,CAElB,MAAMuL,EAAOvL,EACbA,EAAMsL,EACNA,EAAMC,CACV,CAEA,OAAOxL,GAAOD,KAAKuL,UAAYC,EAAMtL,EAAM,GAAMA,EACrD,GCpDM,IACFwL,GAAG,IACHC,GAAG,MACHC,IACA5L,KAES6L,GAAU,SAASC,EAAGC,GAE/B,IAAIC,EAAOZ,GAAMU,EAAEG,GACfC,EAAOd,GAAMW,EAAEE,GACfE,EAAOL,EAAEM,EACTC,EAAON,EAAEK,EACTE,EAAOlB,GAAMiB,EAAOF,GACpBF,EAAIN,GAAIW,GAAQZ,GAAIQ,GACpBE,EAAIV,GAAIM,GAAQL,GAAIO,GAAQP,GAAIK,GAAQN,GAAIQ,GAAQR,GAAIY,GAKxD3c,EAJOub,GAAMU,GAAMK,EAAGG,IAIP,KAKnB,OAJIzc,EAAQ,IACRA,GAAS,KAJE,CAAC,KAAM,IAAK,KAAM,IAAK,KAAM,IAAK,KAAM,KAKvDA,EAAQ4c,SAAS5c,EAAQ,IAG7B,EC3Ba6c,GAAgB,SAAS3O,EAAOC,GAEzC,IAAI2O,EAAK5O,EAAMuO,EACXM,EAAK7O,EAAMoO,EAGf,OAAQQ,GAFC3O,EAAIsO,GAEOK,GAAMC,GADjB5O,EAAImO,GACyBS,CAC1C,ECPa,GAAS,SAAS7O,EAAOC,GAClC,OAAOkC,KAAK2M,KAAKH,GAAc3O,EAAOC,GAC1C,ECJa4J,GAAQ,CACjBkF,MAAO,EACPC,KAAM,EACNC,QAAS,EACTC,KAAM,EACNC,SAAU,EACVC,QAAS,EACTC,MAAO,EACPC,KAAM,ICOJ,IACFC,GACA1B,IAAG,GACHC,IAAG,QACHgB,GAAI,IACJzM,GAAG,IACHsL,GACAI,MAAK,GACLtB,MAAK,OACL+C,GACA9C,GAAE,IACFvK,KAES4M,GAAQ,SAASR,EAAGH,GAE7B,KAAMhO,gBAAgB2O,IAClB,OAAO,IAAIA,GAAMR,EAAGH,GAGxB,GAAiB,iBAANG,EAAgB,CACvB,IAAIkB,EAAKlB,EAAE7d,OAA0B,IAApB6d,EAAElV,QAAQ,KAAc,IAAM,KAC/CkV,EAAImB,WAAWD,EAAG,IAClBrB,EAAIsB,WAAWD,EAAG,GAEtB,MAAWrkB,OAAOmjB,KAAOA,IACrBH,EAAIG,EAAEH,EACNG,EAAIA,EAAEA,GAGVnO,KAAKmO,OAAU1b,IAAN0b,EAAkB,EAAIA,EAC/BnO,KAAKgO,OAAUvb,IAANub,EAAkB,EAAIA,CACnC,EAMAW,GAAMY,UAAY,SAASC,EAAU1C,EAAO2C,GAExCA,EAAS,IAAId,GAAMc,GACnB,IAAItB,EAAIgB,GAAIK,EAAW,GAAI1C,IACvBkB,EAAImB,GAAIK,EAAW,GAAI1C,IACvBM,EAAMP,GAAeI,GAAMH,IAa/B,OAXIM,EAAM,GACNY,GAAKA,EAEEZ,EAAM,KACbe,GAAKA,EACLH,GAAKA,GAEEZ,EAAM,MACbe,GAAKA,GAGF,IAAIQ,GAAMc,EAAOtB,EAAIA,EAAGsB,EAAOzB,EAAIA,EAC9C,EAGAW,GAAMrB,OAAS,SAASoC,EAAIC,EAAIC,EAAIC,GAEhC,OAAO,IAAIlB,GAAMrB,GAAOoC,EAAIC,GAAKrC,GAAOsC,EAAIC,GAChD,EAEAlB,GAAMrjB,UAAY,CAEd6G,KAAMsX,GAAMkF,MAEZmB,cAAe,SAASC,GAEpB,IAAIC,EAAID,EAAOve,OACf,GAAU,IAANwe,EAAS,OAAO,IAAIrB,GAAMoB,EAAO,IAGrC,IAFA,IAAIE,EAAU,KACVC,EAAiBjN,IACZ6D,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CACxB,IAAI+G,EAAI,IAAIc,GAAMoB,EAAOjJ,IACrBqJ,EAAcnQ,KAAKoQ,gBAAgBvC,GACnCsC,EAAcD,IACdD,EAAUpC,EACVqC,EAAiBC,EAEzB,CACA,OAAOF,CACX,EAKAI,aAAc,SAASC,GAEnB,OAAIA,EAAEC,cAAcvQ,QAIpBA,KAAKmO,EAAIlM,GAAIsL,GAAIvN,KAAKmO,EAAGmC,EAAEnC,GAAImC,EAAEnC,EAAImC,EAAEE,OACvCxQ,KAAKgO,EAAI/L,GAAIsL,GAAIvN,KAAKgO,EAAGsC,EAAEtC,GAAIsC,EAAEtC,EAAIsC,EAAEG,SAJ5BzQ,IAMf,EAQA0Q,aAAc,SAASC,EAAIC,GAEvB,IAAIF,EAAgB1Q,KAAK6Q,OAAOF,IAAO3Q,KAAK6Q,OAAOD,GAAOE,IAAO9Q,KAAK+Q,MAAMH,GAAM5Q,KAAK+Q,MAAMJ,GAM7F,OAJID,EAAe,IACfA,GAAgB,KAGbA,CACX,EAGA9C,QAAS,SAASoD,GACd,OAAOpD,GAAQ5N,KAAMgR,EACzB,EAIAC,cAAe,SAASC,EAAIC,EAAIC,GAG5B,OAAOpR,KAAKoC,QAAQiP,QAAQH,GAAKC,GAAIJ,MAAMK,GAAOpR,KAAK+Q,MAAMK,EACjE,EAEAhP,MAAO,WAEH,OAAO,IAAIuM,GAAM3O,KACrB,EAWAsR,MAAO,SAASX,EAAIC,GAEhB,OAAQD,GAAMC,GAASA,EAAGzC,EAAInO,KAAKmO,IAAMwC,EAAG3C,EAAIhO,KAAKgO,IAAQ4C,EAAG5C,EAAIhO,KAAKgO,IAAM2C,EAAGxC,EAAInO,KAAKmO,GAAO2C,GACtG,EAEA3N,WAAY,SAAS+N,EAAIC,GAOrB,OALKnmB,OAAOkmB,KAAQA,IAChBC,EAAKD,EAAGlD,EACRkD,EAAKA,EAAG/C,GAGL,IAAIQ,GAAM3O,KAAKmO,GAAK+C,GAAM,GAAIlR,KAAKgO,GAAKmD,GAAM,GACzD,EAGA3B,SAAU,SAAS3B,GACf,OAAO,GAAO7N,KAAM6N,EACxB,EAGA0D,IAAK,SAAS1D,GAEV,OAAOA,EAAK7N,KAAKmO,EAAIN,EAAEM,EAAInO,KAAKgO,EAAIH,EAAEG,EAAK8C,GAC/C,EAEAD,OAAQ,SAAShD,GAEb,QAASA,GACL7N,KAAKmO,IAAMN,EAAEM,GACbnO,KAAKgO,IAAMH,EAAEG,CACrB,EAGAwD,KAAM,SAAS3D,EAAG4D,GAEd,IAAItD,EAAInO,KAAKmO,EACTH,EAAIhO,KAAKgO,EACb,OAAO,IAAIW,IAAO,EAAI8C,GAAKtD,EAAIsD,EAAI5D,EAAEM,GAAI,EAAIsD,GAAKzD,EAAIyD,EAAI5D,EAAEG,EAChE,EAEA0D,UAAW,WAEP,OAAOhD,GAAM1O,KAAKmO,EAAInO,KAAKmO,EAAMnO,KAAKgO,EAAIhO,KAAKgO,IAAO,GAC1D,EAGA2D,kBAAmB,SAAS9D,GAExB,OAAOsB,GAAItB,EAAEM,EAAInO,KAAKmO,GAAKgB,GAAItB,EAAEG,EAAIhO,KAAKgO,EAC9C,EAIA4D,KAAM,SAASR,EAAK5B,GAEhB,IAAIuB,EAAQ5D,GAAM,IAAKwB,GAAMyC,GAAML,MAAM/Q,OAEzC,OADaA,KAAKqR,OAAO,GAAIN,GAASvB,GAAW,GAAIuB,GAASvB,EAElE,EAGAqC,UAAW,SAASrgB,GAEhB,IAAI+a,GAAS/a,GAAU,GAAKwO,KAAK0R,YACjC,OAAO1R,KAAKuM,MAAMA,EAAOA,EAC7B,EAGA8E,OAAQ,SAASH,EAAIC,GASjB,OAPKnmB,OAAOkmB,KAAQA,IAChBC,EAAKD,EAAGlD,EACRkD,EAAKA,EAAG/C,GAGZnO,KAAKmO,GAAK+C,GAAM,EAChBlR,KAAKgO,GAAKmD,GAAM,EACTnR,IACX,EAIA8R,WAAY,SAASV,GAEjB,OAAO,IAAKzC,GAAMyC,GAAMQ,KAAK5R,KAAMA,KAAKwP,SAAS4B,GACrD,EAIAW,OAAQ,SAAStC,EAAQ3C,GAErB,GAAc,IAAVA,EAAa,OAAO9M,KAExByP,EAASA,GAAU,IAAId,GAAM,EAAG,GAEhC7B,EAAQK,GAAMN,IAAgBC,IAC9B,IAAIkF,EAAW,GAAIlF,GACfmF,EAAW,GAAInF,GAEfqB,EAAK6D,GAAYhS,KAAKmO,EAAIsB,EAAOtB,GAAO8D,GAAYjS,KAAKgO,EAAIyB,EAAOzB,GAAMyB,EAAOtB,EACjFH,EAAKiE,GAAYjS,KAAKmO,EAAIsB,EAAOtB,GAAO6D,GAAYhS,KAAKgO,EAAIyB,EAAOzB,GAAMyB,EAAOzB,EAIrF,OAFAhO,KAAKmO,EAAIA,EACTnO,KAAKgO,EAAIA,EACFhO,IACX,EAEAqM,MAAO,SAAS6F,GAEZ,IAAIC,EAAI,EACR,GAAID,EACA,OAAQA,GACJ,KAAK,EAAGC,EAAI,GAAI,MAChB,KAAK,EAAGA,EAAI,IAAK,MACjB,KAAK,EAAGA,EAAI,IAAM,MAClB,QAASA,EAAI/C,GAAI,GAAI8C,GAM7B,OAFAlS,KAAKmO,EAAI,GAAMnO,KAAKmO,EAAIgE,GAAKA,EAC7BnS,KAAKgO,EAAI,GAAMhO,KAAKgO,EAAImE,GAAKA,EACtBnS,IACX,EAGAuM,MAAO,SAAS6F,EAAIC,EAAI5C,GAKpB,OAHAA,EAAUA,GAAU,IAAId,GAAMc,IAAY,IAAId,GAAM,EAAG,GACvD3O,KAAKmO,EAAIsB,EAAOtB,EAAIiE,GAAMpS,KAAKmO,EAAIsB,EAAOtB,GAC1CnO,KAAKgO,EAAIyB,EAAOzB,EAAIqE,GAAMrS,KAAKgO,EAAIyB,EAAOzB,GACnChO,IACX,EAEA+M,WAAY,SAASuF,EAAIC,GAIrB,OAFAvS,KAAKmO,EAAIpB,GAAW/M,KAAKmO,EAAGmE,GAC5BtS,KAAKgO,EAAIjB,GAAW/M,KAAKgO,EAAGuE,GAAMD,GAC3BtS,IACX,EAEAoQ,gBAAiB,SAASvC,GACtB,OAAOU,GAAcvO,KAAM6N,EAC/B,EAKAkD,MAAO,SAASlD,GAKZ,IAAIG,KAHJH,EAAI,IAAIc,GAAMd,IAGFG,EAAIhO,KAAKgO,GACjBG,EAAIN,EAAEM,EAAInO,KAAKmO,EACfjB,EAAM,GAAMc,EAAGG,GAOnB,OAJIjB,EAAM,IACNA,EAAM,EAAI,GAAKA,GAGZ,IAAMA,EAAM,EACvB,EAEAsF,OAAQ,WAEJ,MAAO,CAAErE,EAAGnO,KAAKmO,EAAGH,EAAGhO,KAAKgO,EAChC,EAIAyE,QAAS,SAAS1nB,GAEdA,EAAKA,GAAK,IAAI4jB,GAAM5jB,IAAO,IAAI4jB,GAAM,EAAG,GACxC,IAAIR,EAAInO,KAAKmO,EACTH,EAAIhO,KAAKgO,EAGb,OAFAhO,KAAKmO,EAAIO,IAAMP,EAAIpjB,EAAEojB,IAAMA,EAAIpjB,EAAEojB,IAAMH,EAAIjjB,EAAEijB,IAAMA,EAAIjjB,EAAEijB,IACzDhO,KAAKgO,EAAIb,GAAMpiB,EAAEgmB,MAAM,IAAIpC,GAAMR,EAAGH,KAC7BhO,IACX,EAEAjN,SAAU,WAEN,OAAOiN,KAAKmO,EAAI,IAAMnO,KAAKgO,CAC/B,EAEA0E,UAAW,WAEP,OAAO1S,KAAKmO,EAAI,IAAMnO,KAAKgO,CAC/B,EAEA2E,OAAQ,SAASxE,EAAGH,GAShB,OAPKhjB,OAAOmjB,KAAOA,IACfH,EAAIG,EAAEH,EACNG,EAAIA,EAAEA,GAGVnO,KAAKmO,EAAIA,GAAK,EACdnO,KAAKgO,EAAIA,GAAK,EACPhO,IACX,EAIA4S,YAAa,SAAS/E,GAGlB,OADW,IAAIc,GAAM,EAAG,GACZ+B,aAAa1Q,KAAM6N,EACnC,GAGJc,GAAMrjB,UAAUunB,UAAYlE,GAAMrjB,UAAU+lB,OAGrC,MAAM,GAAQ1C,IC9WjBpB,IAAG,GACHtL,IAAG,IACHF,KAES6M,GAAO,SAAS+B,EAAIC,GAE7B,OAAM5Q,gBAAgB4O,GAIlB+B,aAAc/B,GACP,IAAIA,GAAK+B,EAAG/Q,MAAO+Q,EAAG9Q,MAGjCG,KAAKJ,MAAQ,IAAI+O,GAAMgC,QACvB3Q,KAAKH,IAAM,IAAI8O,GAAMiC,KARV,IAAIhC,GAAK+B,EAAIC,EAS5B,EAEAhC,GAAKtjB,UAAY,CAEb6G,KAAMsX,GAAMmF,KAGZ9B,MAAO,WAEH,IAAIgG,EAAkB,IAAInE,GAAM3O,KAAKJ,MAAMuO,EAAI,EAAGnO,KAAKJ,MAAMoO,GAC7D,OAAOhO,KAAKJ,MAAM8Q,aAAa1Q,KAAKH,IAAKiT,EAC7C,EAEAC,KAAM,WAEF,IAAIC,EAAO,GAAIhT,KAAKJ,MAAMuO,EAAGnO,KAAKH,IAAIsO,GAClC8E,EAAM,GAAIjT,KAAKJ,MAAMoO,EAAGhO,KAAKH,IAAImO,GACjCkF,EAAQ,GAAIlT,KAAKJ,MAAMuO,EAAGnO,KAAKH,IAAIsO,GACnCgF,EAAS,GAAInT,KAAKJ,MAAMoO,EAAGhO,KAAKH,IAAImO,GAExC,OAAO,IAAIc,GAAKkE,EAAMC,EAAMC,EAAQF,EAAQG,EAASF,EACzD,EAIArF,QAAS,WACL,OAAOA,GAAQ5N,KAAKJ,MAAOI,KAAKH,IACpC,EAEAuC,MAAO,WAEH,OAAO,IAAIwM,GAAK5O,KAAKJ,MAAOI,KAAKH,IACrC,EAGAuT,aAAc,SAASvF,GAEnB,OAAO7N,KAAKqT,QAAQrT,KAAKsT,6BAA6BzF,GAC1D,EAEA0F,mBAAoB,SAAS1F,GAEzB,OAAO7N,KAAKsT,6BAA6BzF,GAAK7N,KAAKxO,QACvD,EAGA8hB,6BAA8B,SAASzF,GAEnC,IAAI2F,EAAUxT,KAAKyT,SAASlC,IAAI,IAAK3C,GAAK5O,KAAKJ,MAAOiO,GAAI4F,UACtDC,EAAqB,GAAI,EAAG,GAAI,EAAGF,EAAUxT,KAAKuO,kBAItD,OAAImF,GAAuBA,EAA2B,EAG/CA,CACX,EAEAC,oBAAqB,SAAS9F,GAE1B,OAAO7N,KAAK4T,UAAU5T,KAAKsT,6BAA6BzF,GAC5D,EAGA0C,cAAe,SAAS1C,GAEpB,IAAIjO,EAAQI,KAAKJ,MACbC,EAAMG,KAAKH,IAEf,GAA4B,IAAxBD,EAAM0R,MAAMzD,EAAGhO,GAAY,OAAO,EAGtC,IAAIrO,EAASwO,KAAKxO,SAClB,QAAI,IAAKod,GAAKhP,EAAOiO,GAAIrc,SAAWA,GAChC,IAAKod,GAAKf,EAAGhO,GAAMrO,SAAWA,EAItC,EAGAqiB,SAAU,SAASC,GAEf,IAAIC,EAAe/T,KAAKqT,QAAQS,GAGhC,MAAO,CACH,IAAIlF,GAAK5O,KAAKJ,MAAOmU,GACrB,IAAInF,GAAKmF,EAAc/T,KAAKH,KAEpC,EAGAmU,eAAgB,SAASxiB,GAErB,IAAIuiB,EAAe/T,KAAKiU,cAAcziB,GAGtC,MAAO,CACH,IAAIod,GAAK5O,KAAKJ,MAAOmU,GACrB,IAAInF,GAAKmF,EAAc/T,KAAKH,KAEpC,EAEAgR,OAAQ,SAASqD,GAEb,QAASA,GACLlU,KAAKJ,MAAMuO,IAAM+F,EAAEtU,MAAMuO,GACzBnO,KAAKJ,MAAMoO,IAAMkG,EAAEtU,MAAMoO,GACzBhO,KAAKH,IAAIsO,IAAM+F,EAAErU,IAAIsO,GACrBnO,KAAKH,IAAImO,IAAMkG,EAAErU,IAAImO,CAC7B,EAKAmG,UAAW,SAASC,EAAOC,GAEvB,GAAID,GAASA,EAAME,qBAAsB,CACrC,IAAIC,EAAeH,EAAME,qBAAqBtU,KAAMqU,GAOpD,OAJIE,GAAiBH,aAAiBxF,KAClC2F,EAAeA,EAAa,IAGzBA,CACX,CAEA,OAAO,IACX,EAEAD,qBAAsB,SAASE,GAE3B,IAAIC,EAAS,IAAI9F,GAAM3O,KAAKH,IAAIsO,EAAInO,KAAKJ,MAAMuO,EAAGnO,KAAKH,IAAImO,EAAIhO,KAAKJ,MAAMoO,GACtE0G,EAAS,IAAI/F,GAAM6F,EAAK3U,IAAIsO,EAAIqG,EAAK5U,MAAMuO,EAAGqG,EAAK3U,IAAImO,EAAIwG,EAAK5U,MAAMoO,GACtE2G,EAAOF,EAAOtG,EAAIuG,EAAO1G,EAAMyG,EAAOzG,EAAI0G,EAAOvG,EACjDyG,EAAU,IAAIjG,GAAM6F,EAAK5U,MAAMuO,EAAInO,KAAKJ,MAAMuO,EAAGqG,EAAK5U,MAAMoO,EAAIhO,KAAKJ,MAAMoO,GAC3E6G,EAASD,EAAQzG,EAAIuG,EAAO1G,EAAM4G,EAAQ5G,EAAI0G,EAAOvG,EACrD2G,EAAQF,EAAQzG,EAAIsG,EAAOzG,EAAM4G,EAAQ5G,EAAIyG,EAAOtG,EAExD,GAAY,IAARwG,GAAaE,EAAQF,EAAM,GAAKG,EAAOH,EAAM,EAE7C,OAAO,KAGX,GAAIA,EAAM,GACN,GAAIE,EAAQF,GAAOG,EAAOH,EACtB,OAAO,UAIX,GAAIE,EAAQF,GAAOG,EAAOH,EACtB,OAAO,KAIf,MAAO,CAAC,IAAIhG,GACR3O,KAAKJ,MAAMuO,EAAK0G,EAAQJ,EAAOtG,EAAIwG,EACnC3U,KAAKJ,MAAMoO,EAAK6G,EAAQJ,EAAOzG,EAAI2G,GAE3C,EAEAI,iBAAkB,WAEd,OAAQ/U,KAAKJ,MAAMiR,OAAO7Q,KAAKH,IACnC,EAGArO,OAAQ,WACJ,OAAO,GAAOwO,KAAKJ,MAAOI,KAAKH,IACnC,EAGAmV,SAAU,WAEN,OAAO,IAAIrG,IACN3O,KAAKJ,MAAMuO,EAAInO,KAAKH,IAAIsO,GAAK,GAC7BnO,KAAKJ,MAAMoO,EAAIhO,KAAKH,IAAImO,GAAK,EAEtC,EAEAiH,SAAU,SAASzF,GACf,MAAM0E,EAAIlU,KAAKoC,QACf,IAAKpC,KAAK+U,mBAAoB,OAAOb,EACrC,MAAM,MAAEtU,EAAK,IAAEC,GAAQqU,EACjBgB,EAAOtV,EAAMwC,QAAQ2P,OAAOlS,EAAK,KACjCsV,EAAOtV,EAAIuC,QAAQ2P,OAAOnS,EAAO,IAGvC,OAFAA,EAAMgS,KAAKuD,EAAM3F,GACjB3P,EAAI+R,KAAKsD,EAAM1F,GACR0E,CACX,EAGAb,QAAS,SAAS5B,GAEd,IAAI7R,EAAQI,KAAKJ,MACbC,EAAMG,KAAKH,IAEf,OAAI4R,GAAK,EAAU7R,EAAMwC,QACrBqP,GAAK,EAAU5R,EAAIuC,QAEhBxC,EAAM4R,KAAK3R,EAAK4R,EAC3B,EAEAwC,cAAe,SAASziB,GAEpB,IAAIoO,EAAQI,KAAKJ,MACbC,EAAMG,KAAKH,IAEXuV,GAAY,EACZ5jB,EAAS,IACT4jB,GAAY,EACZ5jB,GAAUA,GAGd,IAAI6jB,EAAarV,KAAKxO,SACtB,OAAIA,GAAU6jB,EAAoBD,EAAYvV,EAAIuC,QAAUxC,EAAMwC,QAE3DpC,KAAKqT,SAAS+B,EAAY,EAAYC,EAAa7jB,GAAW6jB,EACzE,EAGAC,YAAa,SAASzH,GAGlBA,EAAI,IAAIc,GAAMd,GACd,IAAIjO,EAAQI,KAAKJ,MACbC,EAAMG,KAAKH,IAGf,QAFoBA,EAAIsO,EAAIvO,EAAMuO,IAAMN,EAAEG,EAAIpO,EAAMoO,IAAMnO,EAAImO,EAAIpO,EAAMoO,IAAMH,EAAEM,EAAIvO,EAAMuO,IAErEnO,KAAKxO,QAC9B,EAEAugB,OAAQ,SAAStC,EAAQ3C,GAIrB,OAFA9M,KAAKJ,MAAMmS,OAAOtC,EAAQ3C,GAC1B9M,KAAKH,IAAIkS,OAAOtC,EAAQ3C,GACjB9M,IACX,EAEAqM,MAAO,SAAS6F,GAIZ,OAFAlS,KAAKJ,MAAMyM,MAAM6F,GACjBlS,KAAKH,IAAIwM,MAAM6F,GACRlS,IACX,EAEAuM,MAAO,SAAS6F,EAAIC,EAAI5C,GAIpB,OAFAzP,KAAKJ,MAAM2M,MAAM6F,EAAIC,EAAI5C,GACzBzP,KAAKH,IAAI0M,MAAM6F,EAAIC,EAAI5C,GAChBzP,IACX,EAGAuV,UAAW,SAAS/jB,GAEhB,IAAIgkB,EAAgBxV,KAAKxO,SACzB,IAAKgkB,EAAe,OAAOxV,KAE3B,IAAIyV,EAAcjkB,EAASgkB,EAC3B,OAAOxV,KAAKuM,MAAMkJ,EAAaA,EAAazV,KAAKJ,MACrD,EAIA2O,cAAe,WACX,OAAOA,GAAcvO,KAAKJ,MAAOI,KAAKH,IAC1C,EAEA+T,UAAW,SAASnC,GAEhB,IAAKzR,KAAK+U,mBAAoB,OAAO,KAErC,IAAInV,EAAQI,KAAKJ,MACbC,EAAMG,KAAKH,IAEX6V,EAAe1V,KAAKqT,QAAQ5B,GAE5BkE,EAAc,IAAI/G,GAAKhP,EAAOC,GAGlC,OAFA8V,EAAY9C,UAAU6C,EAAavH,EAAIvO,EAAMuO,EAAGuH,EAAa1H,EAAIpO,EAAMoO,GAEhE2H,CACX,EAEAC,gBAAiB,SAASpkB,GAEtB,IAAKwO,KAAK+U,mBAAoB,OAAO,KAErC,IAAInV,EAAQI,KAAKJ,MACbC,EAAMG,KAAKH,IAEX6V,EAAe1V,KAAKiU,cAAcziB,GAElCmkB,EAAc,IAAI/G,GAAKhP,EAAOC,GAGlC,OAFA8V,EAAY9C,UAAU6C,EAAavH,EAAIvO,EAAMuO,EAAGuH,EAAa1H,EAAIpO,EAAMoO,GAEhE2H,CACX,EAEA5iB,SAAU,WAEN,OAAOiN,KAAKJ,MAAM7M,WAAa,IAAMiN,KAAKH,IAAI9M,UAClD,EAEA2f,UAAW,WAEP,OAAO1S,KAAKJ,MAAM8S,YAAc,IAAM1S,KAAKH,IAAI6S,WACnD,EAEAG,UAAW,SAASgD,EAAIC,GAIpB,OAFA9V,KAAKJ,MAAMiT,UAAUgD,EAAIC,GACzB9V,KAAKH,IAAIgT,UAAUgD,EAAIC,GAChB9V,IACX,EAGAyT,OAAQ,WAEJ,OAAO,IAAI9E,GAAM3O,KAAKH,IAAIsO,EAAInO,KAAKJ,MAAMuO,EAAGnO,KAAKH,IAAImO,EAAIhO,KAAKJ,MAAMoO,EACxE,GAIJY,GAAKtjB,UAAUipB,aAAe3F,GAAKtjB,UAAU6oB,UAItC,MAAM,GAAOvF,IC9VhBF,KAAI,GACJrC,MAAK,GACL+C,IAAG,IACHrN,KAES8M,GAAU,SAASkH,EAAGpa,EAAGC,GAElC,OAAMoE,gBAAgB6O,GAIlBkH,aAAalH,GACN,IAAIA,GAAQ,IAAIF,GAAMoH,EAAE5H,EAAG4H,EAAE/H,GAAI+H,EAAEpa,EAAGoa,EAAEna,IAGnDma,EAAI,IAAIpH,GAAMoH,GACd/V,KAAKmO,EAAI4H,EAAE5H,EACXnO,KAAKgO,EAAI+H,EAAE/H,EACXhO,KAAKrE,EAAIA,OACTqE,KAAKpE,EAAIA,IAXE,IAAIiT,GAAQkH,EAAGpa,EAAGC,EAYjC,EAEAiT,GAAQmH,SAAW,SAASC,GAGxB,OADAA,EAAO,IAAInH,GAAKmH,GACT,IAAIpH,GAAQoH,EAAKC,SAAUD,EAAKzF,MAAQ,EAAGyF,EAAKxF,OAAS,EACpE,EAEA5B,GAAQvjB,UAAY,CAEhB6G,KAAMsX,GAAMoF,QAEZkE,KAAM,WAEF,OAAO,IAAIjE,GAAK9O,KAAKmO,EAAInO,KAAKrE,EAAGqE,KAAKgO,EAAIhO,KAAKpE,EAAG,EAAIoE,KAAKrE,EAAG,EAAIqE,KAAKpE,EAC3E,EAKAsa,OAAQ,WAEJ,OAAO,IAAIvH,GAAM3O,KAAKmO,EAAGnO,KAAKgO,EAClC,EAEA5L,MAAO,WAEH,OAAO,IAAIyM,GAAQ7O,KACvB,EAMAuQ,cAAe,SAAS1C,GAEpB,OAAO7N,KAAKmW,mBAAmBtI,IAAM,CACzC,EAEAgD,OAAQ,SAASuF,GAEb,QAASA,GACLA,EAAQjI,IAAMnO,KAAKmO,GACnBiI,EAAQpI,IAAMhO,KAAKgO,GACnBoI,EAAQza,IAAMqE,KAAKrE,GACnBya,EAAQxa,IAAMoE,KAAKpE,CAC3B,EAMAya,QAAS,SAASnF,EAAIC,GAYlB,YAXW1e,IAAPye,IACAA,EAAK,QAGEze,IAAP0e,IACAA,EAAKD,GAGTlR,KAAKrE,GAAK,EAAIuV,EACdlR,KAAKpE,GAAK,EAAIuV,EAEPnR,IACX,EAEAsU,qBAAsB,SAASE,GAE3B,IAAI8B,EAAgB,GAChBC,EAAK/B,EAAK5U,MACV4W,EAAKhC,EAAK3U,IACV4W,EAAKzW,KAAKrE,EACV+a,EAAK1W,KAAKpE,EACV+a,EAAMnC,EAAKf,SACX1a,EAAOwd,EAAGpT,WAAW,IAAIwL,GAAM3O,OAC/B4W,EAAO,IAAIjI,GAAMgI,EAAIxI,GAAKsI,EAAKA,GAAKE,EAAI3I,GAAK0I,EAAKA,IAClDG,EAAQ,IAAIlI,GAAM5V,EAAKoV,GAAKsI,EAAKA,GAAK1d,EAAKiV,GAAK0I,EAAKA,IAErD/a,EAAIgb,EAAIpF,IAAIqF,GACZhb,EAAI+a,EAAIpF,IAAIsF,GAEZC,EAAIlb,EAAIA,EAAID,GADR5C,EAAKwY,IAAIsF,GAAS,GAG1B,GAAIC,EAAI,EACJ,OAAO,KACJ,GAAIA,EAAI,EAAG,CACd,IAAIC,EAAO,GAAKD,GACZE,IAAOpb,EAAImb,GAAQpb,EACnBsb,IAAOrb,EAAImb,GAAQpb,EAEvB,IAAKqb,EAAK,GAAK,EAAIA,KAAQC,EAAK,GAAK,EAAIA,GAErC,OAAO,KAEH,GAAKD,GAAMA,GAAM,GAAGV,EAAc1kB,KAAK2kB,EAAG/E,KAAKgF,EAAIQ,IACnD,GAAKC,GAAMA,GAAM,GAAGX,EAAc1kB,KAAK2kB,EAAG/E,KAAKgF,EAAIS,GAE/D,KAAO,CACH,IAAIxF,GAAK7V,EAAID,EACb,KAAI,GAAK8V,GAAKA,GAAK,GAIf,OAAO,KAHP6E,EAAc1kB,KAAK2kB,EAAG/E,KAAKgF,EAAI/E,GAKvC,CAEA,OAAO6E,CACX,EAKAY,sCAAuC,SAASrJ,EAAGf,GAE/Ce,EAAI,IAAIc,GAAMd,GAEVf,GAAOe,EAAEkE,OAAO,IAAIpD,GAAM3O,KAAKmO,EAAGnO,KAAKgO,GAAIlB,GAE/C,IAEIrb,EAFAyf,EAAKrD,EAAEM,EAAInO,KAAKmO,EAChBgD,EAAKtD,EAAEG,EAAIhO,KAAKgO,EAGpB,GAAW,IAAPkD,EAEA,OADAzf,EAASuO,KAAK+S,OAAOoE,oBAAoBtJ,GACrCf,EAAcrb,EAAOsgB,OAAO,IAAIpD,GAAM3O,KAAKmO,EAAGnO,KAAKgO,IAAKlB,GACrDrb,EAGX,IAAI2lB,EAAIjG,EAAKD,EACTmG,EAAWD,EAAIA,EACfE,EAAWtX,KAAKrE,EAAIqE,KAAKrE,EACzB4b,EAAWvX,KAAKpE,EAAIoE,KAAKpE,EAEzBuS,EAAI,GAAK,GAAM,EAAImJ,EAAaD,EAAWE,IAG3CvJ,EAAIoJ,GAFRjJ,EAAI+C,EAAK,GAAK/C,EAAIA,GAKlB,OAFA1c,EAAS,IAAIkd,GAAM3O,KAAKmO,EAAIA,EAAGnO,KAAKgO,EAAIA,GAEpClB,EAAcrb,EAAOsgB,OAAO,IAAIpD,GAAM3O,KAAKmO,EAAGnO,KAAKgO,IAAKlB,GACrDrb,CACX,EAMA0kB,mBAAoB,SAASnF,GAEzB,IAAIxC,EAAKwC,EAAM7C,EACXM,EAAKuC,EAAMhD,EACXrS,EAAIqE,KAAKrE,EACTC,EAAIoE,KAAKpE,EACTuS,EAAInO,KAAKmO,EACTH,EAAIhO,KAAKgO,EAEb,OAASQ,EAAKL,IAAMK,EAAKL,IAAOxS,EAAIA,IAAO8S,EAAKT,IAAMS,EAAKT,IAAOpS,EAAIA,EAC1E,EAEAyQ,MAAO,SAAS6F,GAEZ,IAAIC,EAAI,EACR,GAAID,EACA,OAAQA,GACJ,KAAK,EAAGC,EAAI,GAAI,MAChB,KAAK,EAAGA,EAAI,IAAK,MACjB,KAAK,EAAGA,EAAI,IAAM,MAClB,QAASA,EAAI,GAAI,GAAID,GAQ7B,OAJAlS,KAAKmO,EAAI,GAAMnO,KAAKmO,EAAIgE,GAAKA,EAC7BnS,KAAKgO,EAAI,GAAMhO,KAAKgO,EAAImE,GAAKA,EAC7BnS,KAAKrE,EAAI,GAAMqE,KAAKrE,EAAIwW,GAAKA,EAC7BnS,KAAKpE,EAAI,GAAMoE,KAAKpE,EAAIuW,GAAKA,EACtBnS,IACX,EAMAwX,aAAc,SAAS3J,GAEnB,IAYIG,EAAGG,EAXHK,EAAKX,EAAEM,EACPM,EAAKZ,EAAEG,EACPrS,EAAIqE,KAAKrE,EACTC,EAAIoE,KAAKpE,EACTsa,EAASlW,KAAK+S,OAAOmD,SACrBkB,EAAIlB,EAAO/H,EACX6B,EAAIkG,EAAOlI,EAEXyJ,EAAKjJ,EAAK0H,EAAO/H,EAAIxS,EAAI,EACzB+b,EAAKlJ,EAAK0H,EAAO/H,EAAIxS,EAAI,EAY7B,OATI8b,GAAMC,EAENvJ,EAAKxS,EAAIA,GAAK6S,EAAK4I,GAAOzb,EAAIA,GAAK8S,EAAKuB,KADxChC,EAAIQ,EAAK0H,EAAO/H,EAAIM,EAdJ,GAcyBA,EAdzB,IAekCuB,IAAOpU,EAAIA,GAAK4S,EAAK4I,IAAMA,EAI7EpJ,EAAKpS,EAAIA,GAAK6S,EAAKuB,GAAOpU,EAAIA,GAAK4S,EAAK4I,KADxCjJ,EAAIM,EAAKyH,EAAOlI,EAAIQ,EAlBJ,GAkByBA,EAlBzB,IAmBkC4I,IAAOzb,EAAIA,GAAK8S,EAAKuB,IAAMA,EAG1E,IAAKrB,GAAMR,EAAGH,GAAI+C,MAAMlD,EAEnC,EAEA9a,SAAU,WAEN,OAAO,IAAK4b,GAAM3O,KAAKmO,EAAGnO,KAAKgO,GAAIjb,WAAa,IAAMiN,KAAKrE,EAAI,IAAMqE,KAAKpE,CAC9E,GAIG,MAAMwa,GAAUvH,IC7OnBM,IAAG,GACH1B,IAAG,GACHC,IAAG,GACHzL,IAAG,GACHsL,IAAG,GACHlB,MAAK,GACL+C,IAAG,IACHrN,KAES+M,GAAO,SAASX,EAAGH,EAAG2J,EAAGC,GAElC,KAAM5X,gBAAgB8O,IAClB,OAAO,IAAIA,GAAKX,EAAGH,EAAG2J,EAAGC,GAGxB5sB,OAAOmjB,KAAOA,IACfH,EAAIG,EAAEH,EACN2J,EAAIxJ,EAAEqC,MACNoH,EAAIzJ,EAAEsC,OACNtC,EAAIA,EAAEA,GAGVnO,KAAKmO,OAAU1b,IAAN0b,EAAkB,EAAIA,EAC/BnO,KAAKgO,OAAUvb,IAANub,EAAkB,EAAIA,EAC/BhO,KAAKwQ,WAAc/d,IAANklB,EAAkB,EAAIA,EACnC3X,KAAKyQ,YAAehe,IAANmlB,EAAkB,EAAIA,CACxC,EAEA9I,GAAK+I,YAAc,SAAS3N,GAGxB,OADAA,EAAI,IAAI2E,GAAQ3E,GACT,IAAI4E,GAAK5E,EAAEiE,EAAIjE,EAAEvO,EAAGuO,EAAE8D,EAAI9D,EAAEtO,EAAG,EAAIsO,EAAEvO,EAAG,EAAIuO,EAAEtO,EACzD,EAEAkT,GAAKgJ,eAAiB,YAAY/H,GAE9B,GAAsB,IAAlBA,EAAOve,OAAc,OAAO,KAEhC,MAAMqc,EAAI,IAAIc,GACd,IAAIoJ,EAAMC,EAAMC,EAAMC,EACtBH,EAAOC,EAAO/U,IACdgV,EAAOC,GAAO,IAEd,IAAK,IAAIpR,EAAI,EAAGA,EAAIiJ,EAAOve,OAAQsV,IAAK,CACpC+G,EAAE8E,OAAO5C,EAAOjJ,IAChB,MAAMqH,EAAIN,EAAEM,EACNH,EAAIH,EAAEG,EAERG,EAAI4J,IAAMA,EAAO5J,GACjBA,EAAI8J,IAAMA,EAAO9J,GACjBH,EAAIgK,IAAMA,EAAOhK,GACjBA,EAAIkK,IAAMA,EAAOlK,EACzB,CAEA,OAAO,IAAIc,GAAKiJ,EAAMC,EAAMC,EAAOF,EAAMG,EAAOF,EACpD,EAEAlJ,GAAKqJ,cAAgB,YAAYC,GAE7B,GAAqB,IAAjBA,EAAM5mB,OAAc,OAAO,KAE/B,MAAM8e,EAAI,IAAIxB,GACd,IAAIiJ,EAAMC,EAAMC,EAAMC,EACtBH,EAAOC,EAAO/U,IACdgV,EAAOC,GAAO,IAEd,IAAK,IAAIpR,EAAI,EAAGA,EAAIsR,EAAM5mB,OAAQsV,IAAK,CACnCwJ,EAAEqC,OAAOyF,EAAMtR,IACf,MAAMqH,EAAImC,EAAEnC,EACNH,EAAIsC,EAAEtC,EACNqK,EAAKlK,EAAImC,EAAEE,MACX8H,EAAKtK,EAAIsC,EAAEG,OAEbtC,EAAI4J,IAAMA,EAAO5J,GACjBkK,EAAKJ,IAAMA,EAAOI,GAClBrK,EAAIgK,IAAMA,EAAOhK,GACjBsK,EAAKJ,IAAMA,EAAOI,EAC1B,CAEA,OAAO,IAAIxJ,GAAKiJ,EAAMC,EAAMC,EAAOF,EAAMG,EAAOF,EACpD,EAEAlJ,GAAKxjB,UAAY,CAEb6G,KAAMsX,GAAMqF,KAIZiE,KAAM,SAASjG,GACX,OAAO9M,KAAKoC,QAAQmW,mBAAmBzL,EAC3C,EAEAyL,mBAAoB,SAASzL,GACzB,IAAKA,EAAO,OAAO9M,KACnB,MAAM,MAAEwQ,EAAK,OAAEC,GAAWzQ,KACpB+Q,EAAQ5D,GAAML,GACd0L,EAAK,GAAI,GAAIzH,IACb0H,EAAK,GAAI,GAAI1H,IACb4G,EAAInH,EAAQiI,EAAKhI,EAAS+H,EAC1BZ,EAAIpH,EAAQgI,EAAK/H,EAASgI,EAKhC,OAJAzY,KAAKmO,IAAMqC,EAAQmH,GAAK,EACxB3X,KAAKgO,IAAMyC,EAASmH,GAAK,EACzB5X,KAAKwQ,MAAQmH,EACb3X,KAAKyQ,OAASmH,EACP5X,IACX,EAEA0Y,WAAY,WAER,OAAO,IAAI/J,GAAM3O,KAAKmO,EAAGnO,KAAKgO,EAAIhO,KAAKyQ,OAC3C,EAEAkI,WAAY,WAER,OAAO,IAAI/J,GAAK5O,KAAK0Y,aAAc1Y,KAAK4Y,cAC5C,EAEAC,aAAc,WAEV,OAAO,IAAIlK,GAAM3O,KAAKmO,EAAInO,KAAKwQ,MAAQ,EAAGxQ,KAAKgO,EAAIhO,KAAKyQ,OAC5D,EAEAyF,OAAQ,WAEJ,OAAO,IAAIvH,GAAM3O,KAAKmO,EAAInO,KAAKwQ,MAAQ,EAAGxQ,KAAKgO,EAAIhO,KAAKyQ,OAAS,EACrE,EAEArO,MAAO,WAEH,OAAO,IAAI0M,GAAK9O,KACpB,EAIAuQ,cAAe,SAAS1C,EAAGwG,GACvB,IAAIlG,EAAGH,EASP,OARKH,GAAmB,iBAANA,IAMXM,IAAI,EAAGH,IAAI,GAAMH,KAHjBM,IAAGH,KAAM,IAAIW,GAAMd,IAKnBwG,GAAOA,EAAIyE,OACX3K,EAAInO,KAAKmO,GAAKA,EAAInO,KAAKmO,EAAInO,KAAKwQ,OAASxC,EAAIhO,KAAKgO,GAAKA,EAAIhO,KAAKgO,EAAIhO,KAAKyQ,OAC1EtC,GAAKnO,KAAKmO,GAAKA,GAAKnO,KAAKmO,EAAInO,KAAKwQ,OAASxC,GAAKhO,KAAKgO,GAAKA,GAAKhO,KAAKgO,EAAIhO,KAAKyQ,MACvF,EAGAsI,aAAc,SAASzI,GAEnB,IAAI0I,EAAK,IAAIlK,GAAK9O,MAAM6R,YACpBoH,EAAK,IAAInK,GAAKwB,GAAGuB,YACjBqH,EAAKF,EAAGxI,MACR2I,EAAKH,EAAGvI,OACR2I,EAAKH,EAAGzI,MACR6I,EAAKJ,EAAGxI,OAEZ,KAAKyI,GAAOC,GAAOC,GAAOC,GAEtB,OAAO,EAGX,IAAI7K,EAAKwK,EAAG7K,EACRM,EAAKuK,EAAGhL,EACR0B,EAAKuJ,EAAG9K,EACRyB,EAAKqJ,EAAGjL,EAOZ,OALAoL,GAAM1J,EACNwJ,GAAM1K,EACN6K,GAAMzJ,EACNuJ,GAAM1K,EAECD,GAAMkB,GAAM0J,GAAMF,GAAMzK,GAAMmB,GAAMyJ,GAAMF,CACrD,EAEAG,OAAQ,WAEJ,OAAO,IAAI3K,GAAM3O,KAAKmO,EAAInO,KAAKwQ,MAAOxQ,KAAKgO,EAAIhO,KAAKyQ,OACxD,EAGAI,OAAQ,SAASP,GAEb,IAAIiJ,EAAK,IAAKzK,GAAK9O,MAAO6R,YACtB2H,EAAK,IAAK1K,GAAKwB,GAAIuB,YACvB,OAAO0H,EAAGpL,IAAMqL,EAAGrL,GAAKoL,EAAGvL,IAAMwL,EAAGxL,GAAKuL,EAAG/I,QAAUgJ,EAAGhJ,OAAS+I,EAAG9I,SAAW+I,EAAG/I,MACvF,EAMA4F,QAAS,SAASnF,EAAIC,GAelB,YAbW1e,IAAPye,IACAA,EAAK,QAGEze,IAAP0e,IACAA,EAAKD,GAGTlR,KAAKmO,GAAK+C,EACVlR,KAAKgO,GAAKmD,EACVnR,KAAKwQ,OAAS,EAAIU,EAClBlR,KAAKyQ,QAAU,EAAIU,EAEZnR,IACX,EAGAmU,UAAW,SAAS7D,GAEhB,IAAImJ,EAAWzZ,KAAKyP,SAChBiK,EAAW1Z,KAAKsZ,SAChBK,EAAUrJ,EAAEb,SACZmK,EAAUtJ,EAAEgJ,SAGhB,GAAIM,EAAQzL,GAAKsL,EAAStL,GACtByL,EAAQ5L,GAAKyL,EAASzL,GACtB2L,EAAQxL,GAAKuL,EAASvL,GACtBwL,EAAQ3L,GAAK0L,EAAS1L,EAAG,OAAO,KAEpC,IAAIG,EAAI,GAAIsL,EAAStL,EAAGwL,EAAQxL,GAC5BH,EAAI,GAAIyL,EAASzL,EAAG2L,EAAQ3L,GAEhC,OAAO,IAAIc,GAAKX,EAAGH,EAAG,GAAI0L,EAASvL,EAAGyL,EAAQzL,GAAKA,EAAG,GAAIuL,EAAS1L,EAAG4L,EAAQ5L,GAAKA,EACvF,EAEAsG,qBAAsB,SAASE,GAE3B,IAIIqF,EAAI/S,EAJJwJ,EAAItQ,KACJ8Z,EAAY,CAACxJ,EAAEyJ,UAAWzJ,EAAE0J,YAAa1J,EAAEqI,aAAcrI,EAAE2J,YAC3DlK,EAAS,GACTmK,EAAY,GAGZlK,EAAI8J,EAAUtoB,OAClB,IAAKsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAGJ,QADX+S,EAAKrF,EAAKL,UAAU2F,EAAUhT,MACXoT,EAAUjhB,QAAQ4gB,EAAG9mB,YAAc,IAClDgd,EAAOne,KAAKioB,GACZK,EAAUtoB,KAAKioB,EAAG9mB,aAI1B,OAAOgd,EAAOve,OAAS,EAAIue,EAAS,IACxC,EAKAmH,sCAAuC,SAASrJ,EAAGf,GAE/Ce,EAAI,IAAIc,GAAMd,GACd,IACIpc,EADAykB,EAAS,IAAIvH,GAAM3O,KAAKmO,EAAInO,KAAKwQ,MAAQ,EAAGxQ,KAAKgO,EAAIhO,KAAKyQ,OAAS,GAGnE3D,GAAOe,EAAEkE,OAAOmE,EAAQpJ,GAW5B,IARA,IAAIqN,EAAQ,CACRna,KAAK+Z,UACL/Z,KAAKga,YACLha,KAAK2Y,aACL3Y,KAAKia,YAELG,EAAY,IAAIxL,GAAKsH,EAAQrI,GAExB/G,EAAIqT,EAAM3oB,OAAS,EAAGsV,GAAK,IAAKA,EAAG,CACxC,IAAIyN,EAAe4F,EAAMrT,GAAGyN,aAAa6F,GACzC,GAAqB,OAAjB7F,EAAuB,CACvB9iB,EAAS8iB,EACT,KACJ,CACJ,CAEA,OADI9iB,GAAUqb,GAAOrb,EAAOsgB,OAAOmE,GAASpJ,GACrCrb,CACX,EAEAwoB,SAAU,WAEN,OAAO,IAAIrL,GAAK5O,KAAKqa,UAAWra,KAAK0Y,aACzC,EAEA4B,WAAY,WAER,OAAO,IAAI3L,GAAM3O,KAAKmO,EAAGnO,KAAKgO,EAAIhO,KAAKyQ,OAAS,EACpD,EAEA8J,kBAAmB,SAAStE,EAAMxG,GAK9B,IAAI+K,EAAKC,EAAKC,EAAKC,EAAKC,EAAKC,EAAKC,EAAKC,EAHvC9E,EAAO,IAAInH,GAAKmH,GAChBxG,IAAWA,EAASwG,EAAKC,UAGzB,IAAI8E,EAAKvL,EAAOtB,EACZ8M,EAAKxL,EAAOzB,EAKhBwM,EAAMC,EAAMC,EAAMC,EAAMC,EAAMC,EAAMC,EAAMC,EAAM9X,IAGhD,IAAI0N,EAAKsF,EAAKoE,UACV1J,EAAGxC,EAAI6M,IACPR,GAAOxa,KAAKmO,EAAI6M,IAAOrK,EAAGxC,EAAI6M,IAE9BrK,EAAG3C,EAAIiN,IACPL,GAAO5a,KAAKgO,EAAIiN,IAAOtK,EAAG3C,EAAIiN,IAGlC,IAAIrK,EAAKqF,EAAK2C,cACVhI,EAAGzC,EAAI6M,IACPP,GAAOza,KAAKmO,EAAInO,KAAKwQ,MAAQwK,IAAOpK,EAAGzC,EAAI6M,IAE3CpK,EAAG5C,EAAIiN,IACPJ,GAAO7a,KAAKgO,EAAIhO,KAAKyQ,OAASwK,IAAOrK,EAAG5C,EAAIiN,IAGhD,IAAIC,EAAKjF,EAAKkF,WACVD,EAAG/M,EAAI6M,IACPN,GAAO1a,KAAKmO,EAAInO,KAAKwQ,MAAQwK,IAAOE,EAAG/M,EAAI6M,IAE3CE,EAAGlN,EAAIiN,IACPH,GAAO9a,KAAKgO,EAAIiN,IAAOC,EAAGlN,EAAIiN,IAGlC,IAAIG,EAAKnF,EAAKyC,aAQd,OAPI0C,EAAGjN,EAAI6M,IACPL,GAAO3a,KAAKmO,EAAI6M,IAAOI,EAAGjN,EAAI6M,IAE9BI,EAAGpN,EAAIiN,IACPF,GAAO/a,KAAKgO,EAAIhO,KAAKyQ,OAASwK,IAAOG,EAAGpN,EAAIiN,IAGzC,CACH7I,GAAI,GAAIoI,EAAKC,EAAKC,EAAKC,GACvBtI,GAAI,GAAIuI,EAAKC,EAAKC,EAAKC,GAE/B,EAEAM,yBAA0B,SAASpF,EAAMxG,GAErC,IAAIlD,EAAQvM,KAAKua,kBAAkBtE,EAAMxG,GACzC,OAAO,GAAIlD,EAAM6F,GAAI7F,EAAM8F,GAC/B,EAIAiJ,cAAe,SAAShL,GAMpB,OAJAtQ,KAAKmO,GAAKmC,EAAEnC,GAAK,EACjBnO,KAAKgO,GAAKsC,EAAEtC,GAAK,EACjBhO,KAAKwQ,OAASF,EAAEE,OAAS,EACzBxQ,KAAKyQ,QAAUH,EAAEG,QAAU,EACpBzQ,IACX,EAMA6R,UAAW,WAEP,IAAI0J,EAAOvb,KAAKmO,EACZqN,EAAOxb,KAAKgO,EACZyN,EAAWzb,KAAKwQ,MAChBkL,EAAY1b,KAAKyQ,OAarB,OAZIzQ,KAAKwQ,MAAQ,IACb+K,EAAOvb,KAAKmO,EAAInO,KAAKwQ,MACrBiL,GAAYzb,KAAKwQ,OAEjBxQ,KAAKyQ,OAAS,IACd+K,EAAOxb,KAAKgO,EAAIhO,KAAKyQ,OACrBiL,GAAa1b,KAAKyQ,QAEtBzQ,KAAKmO,EAAIoN,EACTvb,KAAKgO,EAAIwN,EACTxb,KAAKwQ,MAAQiL,EACbzb,KAAKyQ,OAASiL,EACP1b,IACX,EAGAqR,OAAQ,SAASH,EAAIC,GAIjB,OAAOxC,GAAMrjB,UAAU+lB,OAAO7lB,KAAKwU,KAAMkR,EAAIC,EACjD,EAEA1B,OAAQ,WAEJ,OAAO,IAAId,GAAM3O,KAAKmO,EAAGnO,KAAKgO,EAClC,EAIAmJ,oBAAqB,SAASnG,GAG1B,GADAA,EAAQ,IAAIrC,GAAMqC,GACdhR,KAAKuQ,cAAcS,GAEnB,OADWhR,KAAK2b,mBAAmB3K,IAE/B,IAAK,QACD,OAAO,IAAIrC,GAAM3O,KAAKmO,EAAInO,KAAKwQ,MAAOQ,EAAMhD,GAChD,IAAK,OACD,OAAO,IAAIW,GAAM3O,KAAKmO,EAAG6C,EAAMhD,GACnC,IAAK,SACD,OAAO,IAAIW,GAAMqC,EAAM7C,EAAGnO,KAAKgO,EAAIhO,KAAKyQ,QAC5C,IAAK,MACD,OAAO,IAAI9B,GAAMqC,EAAM7C,EAAGnO,KAAKgO,GAG3C,OAAOgD,EAAMX,aAAarQ,KAC9B,EAEAga,UAAW,WAEP,OAAO,IAAIpL,GAAK5O,KAAKmb,WAAYnb,KAAK4Y,cAC1C,EAEAgD,YAAa,WAET,OAAO,IAAIjN,GAAM3O,KAAKmO,EAAInO,KAAKwQ,MAAOxQ,KAAKgO,EAAIhO,KAAKyQ,OAAS,EACjE,EAEApE,MAAO,SAAS6F,GAEZ,IAAIC,EAAI,EACR,GAAID,EACA,OAAQA,GACJ,KAAK,EAAGC,EAAI,GAAI,MAChB,KAAK,EAAGA,EAAI,IAAK,MACjB,KAAK,EAAGA,EAAI,IAAM,MAClB,QAASA,EAAI,GAAI,GAAID,GAQ7B,OAJAlS,KAAKmO,EAAI,GAAMnO,KAAKmO,EAAIgE,GAAKA,EAC7BnS,KAAKgO,EAAI,GAAMhO,KAAKgO,EAAImE,GAAKA,EAC7BnS,KAAKwQ,MAAQ,GAAMxQ,KAAKwQ,MAAQ2B,GAAKA,EACrCnS,KAAKyQ,OAAS,GAAMzQ,KAAKyQ,OAAS0B,GAAKA,EAChCnS,IACX,EAGAuM,MAAO,SAAS6F,EAAIC,EAAI5C,GAOpB,OALAA,EAASzP,KAAKyP,SAASlD,MAAM6F,EAAIC,EAAI5C,GACrCzP,KAAKmO,EAAIsB,EAAOtB,EAChBnO,KAAKgO,EAAIyB,EAAOzB,EAChBhO,KAAKwQ,OAAS4B,EACdpS,KAAKyQ,QAAU4B,EACRrS,IACX,EAIA2b,mBAAoB,SAAS3K,GAGzB,IAAI6K,GADJ7K,EAAQ,IAAIrC,GAAMqC,IACK7C,EAAInO,KAAKmO,EAC5B2N,EAAe9b,KAAKmO,EAAInO,KAAKwQ,MAASQ,EAAM7C,EAC5C4N,EAAY/K,EAAMhD,EAAIhO,KAAKgO,EAE3BiC,EAAU4L,EACVG,EAAO,OAcX,OAZIF,EAAc7L,IACdA,EAAU6L,EACVE,EAAO,SAEPD,EAAY9L,IACZA,EAAU8L,EACVC,EAAO,OAVShc,KAAKgO,EAAIhO,KAAKyQ,OAAUO,EAAMhD,EAY/BiC,IAEf+L,EAAO,UAEJA,CACX,EAEAjP,WAAY,SAASuF,EAAIC,GAErB,IAAI9C,EAASzP,KAAKyP,SAAS1C,WAAWuF,EAAIC,GACtC+G,EAAStZ,KAAKsZ,SAASvM,WAAWuF,EAAIC,GAK1C,OAJAvS,KAAKmO,EAAIsB,EAAOtB,EAChBnO,KAAKgO,EAAIyB,EAAOzB,EAChBhO,KAAKwQ,MAAQ8I,EAAOnL,EAAIsB,EAAOtB,EAC/BnO,KAAKyQ,OAAS6I,EAAOtL,EAAIyB,EAAOzB,EACzBhO,IACX,EAEAwS,OAAQ,WAEJ,MAAO,CAAErE,EAAGnO,KAAKmO,EAAGH,EAAGhO,KAAKgO,EAAGwC,MAAOxQ,KAAKwQ,MAAOC,OAAQzQ,KAAKyQ,OACnE,EAEAsJ,QAAS,WAEL,OAAO,IAAInL,GAAK5O,KAAKqa,UAAWra,KAAKmb,WACzC,EAEAc,UAAW,WAEP,OAAO,IAAItN,GAAM3O,KAAKmO,EAAInO,KAAKwQ,MAAQ,EAAGxQ,KAAKgO,EACnD,EAEAmN,SAAU,WAEN,OAAO,IAAIxM,GAAM3O,KAAKmO,EAAInO,KAAKwQ,MAAOxQ,KAAKgO,EAC/C,EAEAjb,SAAU,WAEN,OAAOiN,KAAKyP,SAAS1c,WAAa,IAAMiN,KAAKsZ,SAASvmB,UAC1D,EAGAqQ,MAAO,SAAS6S,GAEZ,OAAOnH,GAAKqJ,cAAcnY,KAAMiW,EACpC,EAEAtD,OAAQ,SAASxE,EAAGH,EAAG2J,EAAGC,GAatB,OAXK5sB,OAAOmjB,KAAOA,IACfH,EAAIG,EAAEH,EACN2J,EAAIxJ,EAAEqC,MACNoH,EAAIzJ,EAAEsC,OACNtC,EAAIA,EAAEA,GAGVnO,KAAKmO,EAAIA,GAAK,EACdnO,KAAKgO,EAAIA,GAAK,EACdhO,KAAKwQ,MAAQmH,GAAK,EAClB3X,KAAKyQ,OAASmH,GAAK,EACZ5X,IACX,GAGJ8O,GAAKxjB,UAAUstB,YAAc9J,GAAKxjB,UAAUguB,OAE5CxK,GAAKxjB,UAAU+uB,QAAUvL,GAAKxjB,UAAUmkB,OAExCX,GAAKxjB,UAAUunB,UAAY/D,GAAKxjB,UAAU+lB,OAGnC,MAAM4E,GAAOnH,GCnjBb,SAASoN,GAAYC,GAGxB,MAAMC,EAAgBD,EAAUhkB,OAChC,GAAsB,KAAlBikB,EAAsB,MAAO,GAEjC,MAAMrM,EAAS,GAMTsM,EAASD,EAAc9rB,MAAM,sBAE7BgsB,EAAYD,EAAO7qB,OACzB,IAAK,IAAIsV,EAAI,EAAGA,EAAIwV,EAAWxV,GAAK,EAKhCiJ,EAAOne,KAAK,CAAEuc,GAAIkO,EAAOvV,GAAIkH,GAAIqO,EAAOvV,EAAI,KAEhD,OAAOiJ,CACX,CAEO,SAASwM,GAAYxM,GACxB,MAAMyM,EAAYzM,EAAOve,OACzB,GAAkB,IAAdgrB,EAAiB,MAAO,GAC5B,MAAMC,EAAY,GAClB,IAAK,IAAI3V,EAAI,EAAGA,EAAI0V,EAAW1V,IAAK,CAChC,MAAMkK,EAAQjB,EAAOjJ,GAAG1E,QACxBqa,EAAU7qB,KAAKof,EACnB,CACA,OAAOyL,CACX,CAMO,SAASC,GAAW3M,GAEvB,MAAM,IAAEZ,GAAQpN,KAEhB,IAAI+E,EACAkJ,EAMA2M,EAJAH,EAAYzM,EAAOve,OACvB,GAAkB,IAAdgrB,EAAiB,MAAO,GAI5B,IAAK1V,EAAI,EAAGA,EAAI0V,EAAW1V,UACJrU,IAAfkqB,GAIO5M,EAAOjJ,GAAGkH,EAAI2O,EAAW3O,GAIxB+B,EAAOjJ,GAAGkH,IAAM2O,EAAW3O,GAAO+B,EAAOjJ,GAAGqH,EAAIwO,EAAWxO,KANnEwO,EAAa5M,EAAOjJ,IAkB5B,IAAI8V,EAAqB,GACzB,IAAK9V,EAAI,EAAGA,EAAI0V,EAAW1V,IAAK,CAE5B,IAAIgG,EAAQ6P,EAAW5L,MAAMhB,EAAOjJ,IACtB,IAAVgG,IACAA,EAAQ,KAKZ,IAAIxM,EAAQ,CAACyP,EAAOjJ,GAAIA,EAAGgG,GAC3B8P,EAAmBhrB,KAAK0O,EAC5B,CAmBA,GAhBAsc,EAAmBrf,MAAK,SAASsf,EAASC,GAItC,IAAIC,EAAaF,EAAQ,GAAKC,EAAQ,GAQtC,OAPmB,IAAfC,IAEAA,EAAaD,EAAQ,GAAKD,EAAQ,IAK/BE,CACX,IAGIH,EAAmBprB,OAAS,EAAG,CAC/B,IAAIwrB,EAAmBJ,EAAmBA,EAAmBprB,OAAS,GACtEorB,EAAmBK,QAAQD,EAC/B,CAaA,IATA,IAGIE,EACAC,EACAC,EACAC,EACAC,EACAC,EAiGAC,EAzGAC,EAAe,CAAC,EAChBC,EAAmB,GAQc,IAA9Bd,EAAmBprB,QAOtB,GAJA2rB,GADAD,EAAqBN,EAAmBrc,OACN,IAI9Bkd,EAAalyB,eAAe2xB,EAAmB,GAAK,KAAOA,EAAmB,IAOlF,IADA,IAAIS,GAAmB,GACfA,GAEJ,GAAID,EAAiBlsB,OAAS,EAE1BksB,EAAiB9rB,KAAKsrB,GACtBS,GAAmB,MAEhB,CAEHN,GADAD,EAAsBM,EAAiBnd,OACH,GAIpC,IAAIqd,GAFJL,GADAD,EAA4BI,EAAiBnd,OACG,IAET+Q,MAAM+L,EAAeF,GAE5D,GAAIS,EAAe,EAEfF,EAAiB9rB,KAAK0rB,GACtBI,EAAiB9rB,KAAKwrB,GACtBM,EAAiB9rB,KAAKsrB,GACtBS,GAAmB,OAEhB,GAAqB,IAAjBC,EAAoB,CAK3B,IACIlN,EAAe2M,EAAc3M,aAAa6M,EAAqBJ,GAC/DhO,EAAIuB,EAAe,KAFP,OAYL2M,EAAcxM,OAAOsM,IAAiBI,EAAoB1M,OAAOwM,IANxEI,EAAaL,EAAoB,GAAK,KAAOA,EAAoB,IAAMC,EAEvEK,EAAiB9rB,KAAK0rB,IAcfnO,GAAMuB,EAAe,GAAK,IAAO,GAtB5B,QA0BZgN,EAAiB9rB,KAAK0rB,GAEtBV,EAAmBhrB,KAAKwrB,GAKhC,MAIIK,EAAaL,EAAoB,GAAK,KAAOA,EAAoB,IAAMC,EAEvEK,EAAiB9rB,KAAK0rB,EAI9B,CAOJI,EAAiBlsB,OAAS,GAC1BksB,EAAiBnd,MAKrB,IAAIsd,GAAgC,EAEpC,IADA7N,EAAI0N,EAAiBlsB,OAChBsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CAEpB,IAAIgX,EAAmBJ,EAAiB5W,GAAG,SAEnBrU,IAApB+qB,GAAiCM,EAAmBN,KACpDA,EAAkBM,EAClBD,EAA+B/W,EAEvC,CAEA,IAAIiX,EAA4B,GAChC,GAAIF,EAA+B,EAAG,CAClC,IAAIG,EAAgBN,EAAiB5iB,MAAM+iB,GACvCI,EAAiBP,EAAiB5iB,MAAM,EAAG+iB,GAC/CE,EAA4BC,EAAcrV,OAAOsV,EAErD,MACIF,EAA4BL,EAGhC,IAAIQ,EAAa,GAEjB,IADAlO,EAAI+N,EAA0BvsB,OACzBsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IACfoX,EAAWtsB,KAAKmsB,EAA0BjX,GAAG,IAGjD,OAAOoX,CACX,CC/OO,MAAMnP,GAAW,SAASgB,GAE7B,OAAM/P,gBAAgB+O,GAIA,iBAAXgB,EACA,IAAIhB,GAASoP,MAAMpO,QAG9B/P,KAAK+P,OAAU/e,MAAMC,QAAQ8e,GAAUA,EAAOpf,IAAIge,IAAS,IAPhD,IAAII,GAASgB,EAQ5B,EAEAhB,GAASoP,MAAQ,SAAShC,GACtB,OAAO,IAAIpN,GAASmN,GAAYC,GACpC,EAEApN,GAASiH,SAAW,SAASC,GACzB,OAAO,IAAIlH,GAAS,CAChBkH,EAAKoE,UACLpE,EAAKkF,WACLlF,EAAK2C,cACL3C,EAAKyC,aACLzC,EAAKoE,WAEb,EAEAtL,GAASzjB,UAAY,CAEjB6G,KAAMsX,GAAMsF,SAEZgE,KAAM,WAEF,IAAIrD,EAAKzM,IACL0M,GAAK,IACLC,EAAK3M,IACL4M,GAAK,IAELE,EAAS/P,KAAK+P,OACdyM,EAAYzM,EAAOve,OACvB,GAAkB,IAAdgrB,EAAiB,OAAO,KAE5B,IAAK,IAAI1V,EAAI,EAAGA,EAAI0V,EAAW1V,IAAK,CAEhC,IAAIkK,EAAQjB,EAAOjJ,GACfqH,EAAI6C,EAAM7C,EACVH,EAAIgD,EAAMhD,EAEVG,EAAIuB,IAAIA,EAAKvB,GACbA,EAAIwB,IAAIA,EAAKxB,GACbH,EAAI4B,IAAIA,EAAK5B,GACbA,EAAI6B,IAAIA,EAAK7B,EACrB,CAEA,OAAO,IAAIc,GAAKY,EAAIE,EAAID,EAAKD,EAAIG,EAAKD,EAC1C,EAEAxN,MAAO,WACH,OAAO,IAAI2M,GAASwN,GAAYvc,KAAK+P,QACzC,EAEAqD,aAAc,SAASvF,GAEnB,IAAIuQ,EAAWpe,KAAKuT,mBAAmB1F,GAEvC,OAAO7N,KAAKiU,cAAcmK,EAC9B,EAEA7K,mBAAoB,SAAS1F,GAEzB,IAKIuQ,EALArO,EAAS/P,KAAKqe,eACd7B,EAAYzM,EAAOve,OACvB,GAAkB,IAAdgrB,EAAiB,OAAO,EAC5B,GAAkB,IAAdA,EAAiB,OAAO,EAM5B,IAHA,IAAItM,EAAiBjN,IACjBzR,EAAS,EACTwe,EAAIwM,EAAY,EACX1V,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CAExB,IAAI0N,EAAO,IAAI5F,GAAKmB,EAAOjJ,GAAIiJ,EAAOjJ,EAAI,IACtCuO,EAAab,EAAKhjB,SAElBkiB,EAAqBc,EAAKlB,6BAA6BzF,GAGvDsC,EAFKqE,EAAKnB,QAAQK,GAEDtD,gBAAgBvC,GACjCsC,EAAcD,IACdA,EAAiBC,EACjBiO,EAAW5sB,EAAUkiB,EAAqB2B,GAG9C7jB,GAAU6jB,CACd,CAEA,OAAO+I,CACX,EAEA9K,6BAA8B,SAASzF,GAEnC,IAAIuQ,EAAWpe,KAAKuT,mBAAmB1F,GACvC,GAAiB,IAAbuQ,EAAgB,OAAO,EAE3B,IAAI5sB,EAASwO,KAAKxO,SAClB,OAAe,IAAXA,EAAqB,EAElB4sB,EAAW5sB,CACtB,EAEAmiB,oBAAqB,SAAS9F,GAE1B,IAAIuQ,EAAWpe,KAAKuT,mBAAmB1F,GAEvC,OAAO7N,KAAK4V,gBAAgBwI,EAChC,EAMA7N,cAAe,SAAS1C,GAEpB,IAAIkC,EAAS/P,KAAK+P,OACdyM,EAAYzM,EAAOve,OACvB,GAAkB,IAAdgrB,EAAiB,OAAO,EAY5B,IAVA,IAAIrO,EAAIN,EAAEM,EACNH,EAAIH,EAAEG,EAGNsQ,EAAa9B,EAAY,EACzB+B,EAAW,EACXC,EAAmB,EACnBC,EAAU,IAAI7P,GACd8P,EAAM,IAAI9P,GACV+P,EAAS,IAAIhQ,GACV4P,EAAW/B,EAAW+B,IAAY,CACrC,IAAI3e,EAAQmQ,EAAOuO,GACfze,EAAMkQ,EAAOwO,GACjB,GAAI1Q,EAAEgD,OAAOjR,GAAQ,OAAO,EAI5B,GAFA6e,EAAQ7e,MAAQA,EAChB6e,EAAQ5e,IAAMA,EACV4e,EAAQlO,cAAc1C,GAAI,OAAO,EAGrC,GAAMG,GAAKpO,EAAMoO,GAAOA,EAAInO,EAAImO,GAASA,EAAIpO,EAAMoO,GAAOA,GAAKnO,EAAImO,EAAK,CAOpE,IAAI4Q,EAAiBhf,EAAMuO,EAAIA,EAAMtO,EAAIsO,EAAIA,EAAOvO,EAAMuO,EAAIA,EAAMtO,EAAIsO,EAAIA,EACxEyQ,GAAe,IAEfD,EAAOxQ,EAAIA,EAAIyQ,EACfD,EAAO3Q,EAAIA,EACX0Q,EAAI9e,MAAQiO,EACZ6Q,EAAI7e,IAAM8e,EACNF,EAAQtK,UAAUuK,IAElBF,IAGZ,CAGAF,EAAaC,CACjB,CAGA,OAASC,EAAmB,GAAO,CACvC,EAEAK,MAAO,WACH,MAAM,MAAEjf,EAAK,IAAEC,EAAG,OAAEkQ,GAAW/P,KAI/B,OAHIJ,GAASC,IAAQD,EAAMiR,OAAOhR,IAC9BkQ,EAAOne,KAAKgO,EAAMwC,SAEfpC,IACX,EAEAqe,aAAc,WACV,OAAOre,KAAK+P,MAChB,EAEA2M,WAAY,WACR,OAAO,IAAI3N,GAAS2N,GAAW1c,KAAK+P,QACxC,EAIAc,OAAQ,SAAShD,GAEb,IAAKA,EAAG,OAAO,EAEf,IAAIkC,EAAS/P,KAAK+P,OACd+O,EAAcjR,EAAEkC,OAEhByM,EAAYzM,EAAOve,OACvB,GAAIstB,EAAYttB,SAAWgrB,EAAW,OAAO,EAE7C,IAAK,IAAI1V,EAAI,EAAGA,EAAI0V,EAAW1V,IAAK,CAEhC,IAAIkK,EAAQjB,EAAOjJ,GACfiY,EAAalR,EAAEkC,OAAOjJ,GAG1B,IAAKkK,EAAMH,OAAOkO,GAAa,OAAO,CAC1C,CAGA,OAAO,CACX,EAEAzK,qBAAsB,SAASJ,GAK3B,IAJA,IAAIM,EAAO,IAAI5F,GAAKsF,GAChBoC,EAAgB,GAChBvG,EAAS/P,KAAKqe,eACdW,EAAK,IAAIpQ,GACJ9H,EAAI,EAAGkJ,EAAID,EAAOve,OAAS,EAAGsV,EAAIkJ,EAAGlJ,IAAK,CAC/CkY,EAAGpf,MAAQmQ,EAAOjJ,GAClBkY,EAAGnf,IAAMkQ,EAAOjJ,EAAI,GACpB,IAAImY,EAAMzK,EAAKF,qBAAqB0K,GAChCC,GAAK3I,EAAc1kB,KAAKqtB,EAAI,GACpC,CACA,OAAQ3I,EAAc9kB,OAAS,EAAK8kB,EAAgB,IACxD,EAEAvB,iBAAkB,WAEd,IAAIhF,EAAS/P,KAAK+P,OACdyM,EAAYzM,EAAOve,OACvB,GAAkB,IAAdgrB,EAAiB,OAAO,EAI5B,IAFA,IAAIhI,EAAO,IAAI5F,GACXoB,EAAIwM,EAAY,EACX1V,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAInB,GAHA0N,EAAK5U,MAAQmQ,EAAOjJ,GACpB0N,EAAK3U,IAAMkQ,EAAOjJ,EAAI,GAElB0N,EAAKO,mBAAoB,OAAO,EAIxC,OAAO,CACX,EAEAvjB,OAAQ,WAEJ,IAAIue,EAAS/P,KAAKqe,eACd7B,EAAYzM,EAAOve,OACvB,GAAkB,IAAdgrB,EAAiB,OAAO,EAI5B,IAFA,IAAIhrB,EAAS,EACTwe,EAAIwM,EAAY,EACX1V,EAAI,EAAGA,EAAIkJ,EAAGlJ,IACnBtV,GAAUue,EAAOjJ,GAAG0I,SAASO,EAAOjJ,EAAI,IAG5C,OAAOtV,CACX,EAEA6hB,QAAS,SAASS,GAEd,IAAI/D,EAAS/P,KAAKqe,eACd7B,EAAYzM,EAAOve,OACvB,GAAkB,IAAdgrB,EAAiB,OAAO,KAC5B,GAAkB,IAAdA,EAAiB,OAAOzM,EAAO,GAAG3N,QAEtC,GAAI0R,GAAS,EAAG,OAAO/D,EAAO,GAAG3N,QACjC,GAAI0R,GAAS,EAAG,OAAO/D,EAAOyM,EAAY,GAAGpa,QAE7C,IACI5Q,EADiBwO,KAAKxO,SACIsiB,EAE9B,OAAO9T,KAAKiU,cAAcziB,EAC9B,EAEAyiB,cAAe,SAASziB,GAEpB,IAAIue,EAAS/P,KAAKqe,eACd7B,EAAYzM,EAAOve,OACvB,GAAkB,IAAdgrB,EAAiB,OAAO,KAC5B,GAAkB,IAAdA,EAAiB,OAAOzM,EAAO,GAAG3N,QAEtC,IAAIgT,GAAY,EACZ5jB,EAAS,IACT4jB,GAAY,EACZ5jB,GAAUA,GAKd,IAFA,IAAI0iB,EAAI,EACJlE,EAAIwM,EAAY,EACX1V,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CACxB,IAAIpV,EAAS0jB,EAAYtO,EAAKkJ,EAAI,EAAIlJ,EAElCnL,EAAIoU,EAAOre,GACXkK,EAAImU,EAAOre,EAAQ,GACnB8iB,EAAO,IAAI5F,GAAKjT,EAAGC,GACnBkb,EAAInb,EAAE6T,SAAS5T,GAEnB,GAAIpK,GAAW0iB,EAAI4C,EACf,OAAOtC,EAAKP,eAAemB,EAAY,GAAK,IAAM5jB,EAAS0iB,IAG/DA,GAAK4C,CACT,CAIA,OADiB1B,EAAYrF,EAAOyM,EAAY,GAAKzM,EAAO,IAC3C3N,OACrB,EAEAiK,MAAO,SAAS6F,GAKZ,IAHA,IAAInC,EAAS/P,KAAK+P,OACdyM,EAAYzM,EAAOve,OAEdsV,EAAI,EAAGA,EAAI0V,EAAW1V,IAC3BiJ,EAAOjJ,GAAGuF,MAAM6F,GAGpB,OAAOlS,IACX,EAEAuM,MAAO,SAAS6F,EAAIC,EAAI5C,GAKpB,IAHA,IAAIM,EAAS/P,KAAK+P,OACdyM,EAAYzM,EAAOve,OAEdsV,EAAI,EAAGA,EAAI0V,EAAW1V,IAC3BiJ,EAAOjJ,GAAGyF,MAAM6F,EAAIC,EAAI5C,GAG5B,OAAOzP,IACX,EAEAkf,SAAU,SAAS7K,EAAM,CAAC,GAEtB,MAAMtE,EAAS/P,KAAK+P,OACpB,GAAIA,EAAOve,OAAS,EAAG,OAAOwO,KAM9B,MAAMmf,EAAY9K,EAAI8K,WAAa,MAGnC,IAAIC,EAAe,EAGnB,KAAOrP,EAAOqP,EAAe,IAAI,CAC7B,MACMC,EAAeD,EAAe,EAC9B9kB,EAAa8kB,EAAe,EAE5BE,EAAavP,EAJAqP,GAKbG,EAAcxP,EAAOsP,GACrBG,EAAYzP,EAAOzV,GAEX,IAAIsU,GAAK0Q,EAAYE,GACRpM,aAAamM,GACE/P,SAAS+P,IACvBJ,EAGxBpP,EAAOvP,OAAO6e,EAAa,GAQ3BD,GAAgB,CAGxB,CAGA,OAAOpf,IACX,EAEA4T,UAAW,SAASE,GAEhB,IACI0I,EADSxc,KAAKqe,eACK7sB,OACvB,GAAkB,IAAdgrB,EAAiB,OAAO,KAC5B,GAAkB,IAAdA,EAAiB,OAAO,KAExB1I,EAAQ,IAAGA,EAAQ,GACnBA,EAAQ,IAAGA,EAAQ,GAEvB,IACItiB,EADiBwO,KAAKxO,SACIsiB,EAE9B,OAAO9T,KAAK4V,gBAAgBpkB,EAChC,EAEAokB,gBAAiB,SAASpkB,GAEtB,IAAIue,EAAS/P,KAAKqe,eACd7B,EAAYzM,EAAOve,OACvB,GAAkB,IAAdgrB,EAAiB,OAAO,KAC5B,GAAkB,IAAdA,EAAiB,OAAO,KAE5B,IAMIiD,EANArK,GAAY,EACZ5jB,EAAS,IACT4jB,GAAY,EACZ5jB,GAAUA,GAMd,IAFA,IAAI0iB,EAAI,EACJlE,EAAIwM,EAAY,EACX1V,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CACxB,IAAIpV,EAAS0jB,EAAYtO,EAAKkJ,EAAI,EAAIlJ,EAElCnL,EAAIoU,EAAOre,GACXkK,EAAImU,EAAOre,EAAQ,GACnB8iB,EAAO,IAAI5F,GAAKjT,EAAGC,GACnBkb,EAAInb,EAAE6T,SAAS5T,GAEnB,GAAI4Y,EAAKO,mBAAoB,CACzB,GAAIvjB,GAAW0iB,EAAI4C,EACf,OAAOtC,EAAKoB,iBAAiBR,EAAY,GAAK,IAAM5jB,EAAS0iB,IAGjEuL,EAAgBjL,CACpB,CAEAN,GAAK4C,CACT,CAGA,GAAI2I,EAAe,CACf,IAAI3L,EAASsB,EAAY,EAAI,EAC7B,OAAOqK,EAAc7L,UAAUE,EACnC,CAGA,OAAO,IACX,EAEA/gB,SAAU,WAEN,OAAOiN,KAAK+P,OAAS,EACzB,EAEA8C,UAAW,SAASgD,EAAIC,GAKpB,IAHA,IAAI/F,EAAS/P,KAAK+P,OACdyM,EAAYzM,EAAOve,OAEdsV,EAAI,EAAGA,EAAI0V,EAAW1V,IAC3BiJ,EAAOjJ,GAAG+L,UAAUgD,EAAIC,GAG5B,OAAO9V,IACX,EAGA0S,UAAW,WAEP,IAAI3C,EAAS/P,KAAK+P,OACdyM,EAAYzM,EAAOve,OACvB,GAAkB,IAAdgrB,EAAiB,MAAO,GAG5B,IADA,IAAIkD,EAAS,GACJ5Y,EAAI,EAAGA,EAAI0V,EAAW1V,IAAK,CAEhC,IAAIkK,EAAQjB,EAAOjJ,GACnB4Y,GAAU1O,EAAM7C,EAAI,IAAM6C,EAAMhD,EAAI,GACxC,CAEA,OAAO0R,EAAOvnB,MAClB,GAGJnN,OAAOC,eAAe8jB,GAASzjB,UAAW,QAAS,CAG/Cya,cAAc,EAEd7a,YAAY,EAEZC,IAAK,WAID,OAAkB,IAFL6U,KAAK+P,OACKve,OACK,KAErBwO,KAAK+P,OAAO,EACvB,IAGJ/kB,OAAOC,eAAe8jB,GAASzjB,UAAW,MAAO,CAG7Cya,cAAc,EAEd7a,YAAY,EAEZC,IAAK,WAED,IACIqxB,EADSxc,KAAK+P,OACKve,OACvB,OAAkB,IAAdgrB,EAAwB,KAErBxc,KAAK+P,OAAOyM,EAAY,EACnC,ICngBJ,MACIrN,IAAG,GACHT,KAAI,GACJzM,IAAG,GACHsL,IAAG,GACH6B,IAAG,IACHrN,KAESkN,GAAQ,SAAS0B,EAAIC,EAAIsK,EAAIE,GAEtC,OAAMpb,gBAAgBiP,GAIlB0B,aAAc1B,GACP,IAAIA,GAAM0B,EAAG/Q,MAAO+Q,EAAGgP,cAAehP,EAAGiP,cAAejP,EAAG9Q,MAGtEG,KAAKJ,MAAQ,IAAI+O,GAAMgC,GACvB3Q,KAAK2f,cAAgB,IAAIhR,GAAMiC,GAC/B5Q,KAAK4f,cAAgB,IAAIjR,GAAMuM,QAC/Blb,KAAKH,IAAM,IAAI8O,GAAMyM,KAVV,IAAInM,GAAM0B,EAAIC,EAAIsK,EAAIE,EAWrC,ECtBO,SAASyE,GAAOz0B,GA2BnB,IAAI0b,EACAkJ,EAEA/O,EAAO,GAEX,IADA+O,EAAIpR,UAAUpN,OACTsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IACf7F,EAAKrP,KAAKgN,UAAUkI,IAGxB,IAAK1b,EAAK,MAAM,IAAI4d,MAAM,4BAC1B,IAAI8W,EAAQ90B,OAAO2I,OAAOvI,GAG1B,IADA4kB,EAAI/O,EAAKzP,OACJsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CAEpB,IAEIiZ,EACAj1B,EAHA8Z,EAAM3D,EAAK6F,GAIf,IAAKhc,KAAO8Z,EAEJA,EAAIrZ,eAAeT,YACZg1B,EAAMh1B,GACbi1B,EAAoB/0B,OAAOg1B,yBAAyBpb,EAAK9Z,GACzDE,OAAOC,eAAe60B,EAAOh1B,EAAKi1B,GAG9C,CAEA,OAAOD,CACX,CD7BA7Q,GAAMgR,cAAgB,WAkFlB,SAASC,EAAsBC,GAE3B,IAAInQ,EAAImQ,EAAI3uB,OAER2c,EAAI,GACJiS,EAAM,GACNxkB,EAAI,EAERuS,EAAE,GAAKgS,EAAI,GAAKvkB,EAGhB,IAAK,IAAIkL,EAAI,EAAGA,EAAIkJ,EAAGlJ,IACnBsZ,EAAItZ,GAAK,EAAIlL,EACbA,GAAKkL,EAAIkJ,EAAI,EAAI,EAAM,KAAOoQ,EAAItZ,GAClCqH,EAAErH,IAAMqZ,EAAIrZ,GAAKqH,EAAErH,EAAI,IAAMlL,EAGjC,IAAKkL,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAEfqH,EAAE6B,EAAIlJ,EAAI,IAAMsZ,EAAIpQ,EAAIlJ,GAAKqH,EAAE6B,EAAIlJ,GAGvC,OAAOqH,CACX,CAEA,OAAO,SAAS4B,GAEZ,IAAKA,GAAW/e,MAAMC,QAAQ8e,IAAWA,EAAOve,OAAS,EACrD,MAAM,IAAIwX,MAAM,kCAOpB,IAJA,IAAIqX,EA3GR,SAA+BC,GAE3B,IAGIxZ,EAHAyZ,EAAqB,GACrBC,EAAsB,GACtBxQ,EAAIsQ,EAAM9uB,OAAS,EAIvB,GAAS,GAALwe,EAaA,OAXAuQ,EAAmB,GAAK,IAAI5R,IACvB,EAAI2R,EAAM,GAAGnS,EAAImS,EAAM,GAAGnS,GAAK,GAC/B,EAAImS,EAAM,GAAGtS,EAAIsS,EAAM,GAAGtS,GAAK,GAIpCwS,EAAoB,GAAK,IAAI7R,GACzB,EAAI4R,EAAmB,GAAGpS,EAAImS,EAAM,GAAGnS,EACvC,EAAIoS,EAAmB,GAAGvS,EAAIsS,EAAM,GAAGtS,GAGpC,CAACuS,EAAoBC,GAKhC,IAAIL,EAAM,GAGV,IAAKrZ,EAAI,EAAGA,EAAIkJ,EAAI,EAAGlJ,IACnBqZ,EAAIrZ,GAAK,EAAIwZ,EAAMxZ,GAAGqH,EAAI,EAAImS,EAAMxZ,EAAI,GAAGqH,EAG/CgS,EAAI,GAAKG,EAAM,GAAGnS,EAAI,EAAImS,EAAM,GAAGnS,EACnCgS,EAAInQ,EAAI,IAAM,EAAIsQ,EAAMtQ,EAAI,GAAG7B,EAAImS,EAAMtQ,GAAG7B,GAAK,EAGjD,IAAIA,EAAI+R,EAAsBC,GAG9B,IAAKrZ,EAAI,EAAGA,EAAIkJ,EAAI,IAAKlJ,EACrBqZ,EAAIrZ,GAAK,EAAIwZ,EAAMxZ,GAAGkH,EAAI,EAAIsS,EAAMxZ,EAAI,GAAGkH,EAG/CmS,EAAI,GAAKG,EAAM,GAAGtS,EAAI,EAAIsS,EAAM,GAAGtS,EACnCmS,EAAInQ,EAAI,IAAM,EAAIsQ,EAAMtQ,EAAI,GAAGhC,EAAIsS,EAAMtQ,GAAGhC,GAAK,EAGjD,IAAIA,EAAIkS,EAAsBC,GAG9B,IAAKrZ,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAEfyZ,EAAmB3uB,KAAK,IAAI+c,GAAMR,EAAErH,GAAIkH,EAAElH,KAGtCA,EAAIkJ,EAAI,EACRwQ,EAAoB5uB,KAAK,IAAI+c,GACzB,EAAI2R,EAAOxZ,EAAI,GAAGqH,EAAIA,EAAErH,EAAI,GAC5B,EAAIwZ,EAAMxZ,EAAI,GAAGkH,EAAIA,EAAElH,EAAI,KAI/B0Z,EAAoB5uB,KAAK,IAAI+c,IACxB2R,EAAMtQ,GAAG7B,EAAIA,EAAE6B,EAAI,IAAM,GACzBsQ,EAAMtQ,GAAGhC,EAAIA,EAAEgC,EAAI,IAAM,IAKtC,MAAO,CAACuQ,EAAoBC,EAChC,CAoCwBC,CAAsB1Q,GAEtC2Q,EAAS,GACT1Q,EAAIqQ,EAAc,GAAG7uB,OAChBsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CAExB,IAAI6Y,EAAgB,IAAIhR,GAAM0R,EAAc,GAAGvZ,GAAGqH,EAAGkS,EAAc,GAAGvZ,GAAGkH,GACrE4R,EAAgB,IAAIjR,GAAM0R,EAAc,GAAGvZ,GAAGqH,EAAGkS,EAAc,GAAGvZ,GAAGkH,GAEzE0S,EAAO9uB,KAAK,IAAIqd,GAAMc,EAAOjJ,GAAI6Y,EAAeC,EAAe7P,EAAOjJ,EAAI,IAC9E,CAEA,OAAO4Z,CACX,CACH,CA/HqB,GAiItBzR,GAAM3jB,UAAY,CAEd6G,KAAMsX,GAAMwF,MAGZ8D,KAAM,WAwBF,IAtBA,IAkBIpX,EAAGC,EAAGma,EAAGtE,EACTkP,EAAIC,EACJC,EAAMC,EApBNlhB,EAAQI,KAAKJ,MACb+f,EAAgB3f,KAAK2f,cACrBC,EAAgB5f,KAAK4f,cACrB/f,EAAMG,KAAKH,IAEX2O,EAAK5O,EAAMuO,EACXM,EAAK7O,EAAMoO,EACX0B,EAAKiQ,EAAcxR,EACnByB,EAAK+P,EAAc3R,EACnB2B,EAAKiQ,EAAczR,EACnB0B,EAAK+P,EAAc5R,EACnB+S,EAAKlhB,EAAIsO,EACT6S,EAAKnhB,EAAImO,EAET+B,EAAS,IAAI/e,MACbiwB,EAAU,IAAIjwB,MACdkwB,EAAS,CAAC,IAAIlwB,MAAS,IAAIA,OAMtB8V,EAAI,EAAGA,EAAI,IAAKA,EAarB,GAXU,IAANA,GACAlL,EAAI,EAAI4S,EAAK,GAAKkB,EAAK,EAAIC,EAC3BhU,GAAK,EAAI6S,EAAK,EAAIkB,EAAK,EAAIC,EAAK,EAAIoR,EACpChL,EAAI,EAAIrG,EAAK,EAAIlB,IAGjB5S,EAAI,EAAI6S,EAAK,GAAKmB,EAAK,EAAIC,EAC3BlU,GAAK,EAAI8S,EAAK,EAAImB,EAAK,EAAIC,EAAK,EAAImR,EACpCjL,EAAI,EAAInG,EAAK,EAAInB,GAGjB,GAAI9S,GAAK,MAAb,CACI,GAAI,GAAIC,GAAK,MACT,SAIC,GADL6V,GAAKsE,EAAIna,IACO6V,EAAI,GAAIwP,EAAQrvB,KAAK6f,EAGzC,MAGAqP,EAAW,GADXD,EAAOjlB,EAAIA,EAAI,EAAIma,EAAIpa,GAGnBklB,EAAO,IAGN,GADLF,IAAO/kB,EAAIklB,IAAa,EAAInlB,KACXglB,EAAK,GAAIM,EAAQrvB,KAAK+uB,GAGlC,GADLC,IAAOhlB,EAAIklB,IAAa,EAAInlB,KACXilB,EAAK,GAAIK,EAAQrvB,KAAKgvB,IAQ3C,IALA,IAEIO,EACAhT,EAAGH,EAHHjH,EAAIka,EAAQzvB,OACZ4vB,EAAOra,EAIJA,KAIHoH,GAFAgT,EAAK,GADL1P,EAAIwP,EAAQla,KAGFoa,EAAKA,EAAK3S,EAAO,EAAI2S,EAAKA,EAAK1P,EAAI/B,EAAO,EAAIyR,EAAK1P,EAAIA,EAAI9B,EAAO8B,EAAIA,EAAIA,EAAIsP,EACxFG,EAAO,GAAGna,GAAKoH,EAEfH,EAAKmT,EAAKA,EAAKA,EAAK1S,EAAO,EAAI0S,EAAKA,EAAK1P,EAAI7B,EAAO,EAAIuR,EAAK1P,EAAIA,EAAI5B,EAAO4B,EAAIA,EAAIA,EAAIuP,EACxFE,EAAO,GAAGna,GAAKiH,EAEf+B,EAAOhJ,GAAK,CAAEsa,EAAGlT,EAAGmT,EAAGtT,GAG3BiT,EAAQG,GAAQ,EAChBH,EAAQG,EAAO,GAAK,EAEpBrR,EAAOqR,GAAQ,CAAEC,EAAG7S,EAAI8S,EAAG7S,GAC3BsB,EAAOqR,EAAO,GAAK,CAAEC,EAAGN,EAAIO,EAAGN,GAE/BE,EAAO,GAAGE,GAAQ5S,EAClB0S,EAAO,GAAGE,GAAQ3S,EAElByS,EAAO,GAAGE,EAAO,GAAKL,EACtBG,EAAO,GAAGE,EAAO,GAAKJ,EAEtBC,EAAQzvB,OAAS4vB,EAAO,EACxBF,EAAO,GAAG1vB,OAAS4vB,EAAO,EAC1BF,EAAO,GAAG1vB,OAAS4vB,EAAO,EAC1BrR,EAAOve,OAAS4vB,EAAO,EAEvB,IAAIpO,EAAO,GAAI7R,MAAM,KAAM+f,EAAO,IAC9BjO,EAAM,GAAI9R,MAAM,KAAM+f,EAAO,IAC7BhO,EAAQ,GAAI/R,MAAM,KAAM+f,EAAO,IAC/B/N,EAAS,GAAIhS,MAAM,KAAM+f,EAAO,IAEpC,OAAO,IAAIpS,GAAKkE,EAAMC,EAAMC,EAAQF,EAAQG,EAASF,EACzD,EAEA7Q,MAAO,WAEH,OAAO,IAAI6M,GAAMjP,KAAKJ,MAAOI,KAAK2f,cAAe3f,KAAK4f,cAAe5f,KAAKH,IAC9E,EAGAuT,aAAc,SAASvF,EAAGwG,GAEtB,OAAOrU,KAAKuhB,SAASvhB,KAAKwhB,cAAc3T,EAAGwG,GAC/C,EAEAd,mBAAoB,SAAS1F,EAAGwG,GAG5B,IAAInC,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UAEjEwP,EAAW,CAAExP,UAAWA,EAAWyP,kBADElvB,IAArB4hB,EAAIsN,aAA8B3hB,KAAK4hB,gBAAgB,CAAE1P,UAAWA,IAAemC,EAAIsN,cAG3G,OAAO3hB,KAAK6hB,UAAU7hB,KAAKwhB,cAAc3T,EAAG6T,GAAWA,EAC3D,EAEApO,6BAA8B,SAASzF,EAAGwG,GAGtC,IAAInC,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UAEjEwP,EAAW,CAAExP,UAAWA,EAAWyP,kBADElvB,IAArB4hB,EAAIsN,aAA8B3hB,KAAK4hB,gBAAgB,CAAE1P,UAAWA,IAAemC,EAAIsN,cAGvGvD,EAAWpe,KAAKuT,mBAAmB1F,EAAG6T,GAC1C,IAAKtD,EAAU,OAAO,EAEtB,IAAI5sB,EAASwO,KAAKxO,OAAOkwB,GACzB,OAAe,IAAXlwB,EAAqB,EAElB4sB,EAAW5sB,CACtB,EAGAgwB,cAAe,SAAS3T,EAAGwG,GAiBvB,IAdA,IAKIyN,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EAXAlQ,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UACjEyP,OAAqClvB,IAArB4hB,EAAIsN,aAA8B3hB,KAAK4hB,gBAAgB,CAAE1P,UAAWA,IAAemC,EAAIsN,aAWvG3R,EAAI2R,EAAanwB,OACjB6wB,EAAmBrS,EAAK,EAAIA,EAAK,EAC5BlJ,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CAExB,IAAIwb,EAAqBX,EAAa7a,GAElCyb,EAAYD,EAAmB1iB,MAAM4P,SAAS3B,GAC9C2U,EAAUF,EAAmBziB,IAAI2P,SAAS3B,GAC1C4U,EAAUF,EAAYC,IAGrBJ,GAAeK,EAAUL,KAC1BN,EAA0BQ,EAE1BP,EAAgCjb,EAAIub,EACpCL,GAA+Blb,EAAI,GAAKub,EAExCJ,EAAgBM,EAChBL,EAAcM,EAEdL,EAAcG,EAAmB1iB,MAAM4P,SAAS8S,EAAmBziB,KAEnEuiB,EAAaK,EAErB,CAOA,IALA,IAAIC,EAAiB,GAAI,IAAKxQ,KAKjB,CAOT,IAAIyQ,EAAuBV,EAAiB,GAAIA,EAAgBC,GAAeD,EAAiB,EAC5FW,EAAqBV,EAAe,GAAID,EAAgBC,GAAeA,EAAe,EAY1F,GAX6BS,EAAsBD,GAAoBE,EAAoBF,IAM5DT,GAAiBA,EAAiBE,EAAcO,IAClDR,GAAeA,EAAeC,EAAcO,EAKrE,OAAST,GAAiBC,EAAeH,EAAgCC,EAI7E,IAAIa,EAAUf,EAAwBgB,OAAO,IAC7CT,GAAmB,EAEnB,IAAIU,EAAaF,EAAQ,GAAGjjB,MAAM4P,SAAS3B,GACvCmV,EAAWH,EAAQ,GAAGhjB,IAAI2P,SAAS3B,GACnCoV,EAAWF,EAAaC,EAExBE,EAAaL,EAAQ,GAAGjjB,MAAM4P,SAAS3B,GACvCsV,EAAWN,EAAQ,GAAGhjB,IAAI2P,SAAS3B,GAGnCoV,GAFWC,EAAaC,GAGxBrB,EAA0Be,EAAQ,GAElCb,GAA+BK,EAE/BJ,EAAgBc,EAChBb,EAAcc,IAGdlB,EAA0Be,EAAQ,GAElCd,GAAiCM,EAEjCJ,EAAgBiB,EAChBhB,EAAciB,EAEtB,CACJ,EAEAxP,oBAAqB,SAAS9F,EAAGwG,GAE7B,OAAOrU,KAAKojB,WAAWpjB,KAAKwhB,cAAc3T,EAAGwG,GACjD,EAMA9D,cAAe,SAAS1C,EAAGwG,GAGvB,OADerU,KAAKqjB,WAAWhP,GACf9D,cAAc1C,EAClC,EAIAgG,SAAU,SAASC,EAAOO,GAEtB,GAAIP,GAAS,EAAG,OAAO9T,KAAKsjB,UAAU,GACtC,GAAIxP,GAAS,EAAG,OAAO9T,KAAKsjB,UAAU,GAEtC,IAAI7R,EAAIzR,KAAKujB,IAAIzP,EAAOO,GAExB,OAAOrU,KAAKsjB,UAAU7R,EAC1B,EAGAuC,eAAgB,SAASxiB,EAAQ6iB,GAE7B,IAAI5C,EAAIzR,KAAKwjB,UAAUhyB,EAAQ6iB,GAE/B,OAAOrU,KAAKsjB,UAAU7R,EAC1B,EAKA6R,UAAW,SAAS7R,GAEhB,IAAI7R,EAAQI,KAAKJ,MACb+f,EAAgB3f,KAAK2f,cACrBC,EAAgB5f,KAAK4f,cACrB/f,EAAMG,KAAKH,IAGf,GAAI4R,GAAK,EACL,MAAO,CACH,IAAIxC,GAAMrP,EAAOA,EAAOA,EAAOA,GAC/B,IAAIqP,GAAMrP,EAAO+f,EAAeC,EAAe/f,IAIvD,GAAI4R,GAAK,EACL,MAAO,CACH,IAAIxC,GAAMrP,EAAO+f,EAAeC,EAAe/f,GAC/C,IAAIoP,GAAMpP,EAAKA,EAAKA,EAAKA,IAIjC,IAAI4jB,EAAgBzjB,KAAK0jB,kBAAkBjS,GAEvCkS,EAAgBF,EAAcG,mBAC9BC,EAAgBJ,EAAcK,mBAC9BC,EAAUN,EAAcM,QACxBC,EAAkBP,EAAcQ,qBAChCC,EAAkBT,EAAcU,qBAGpC,MAAO,CACH,IAAIlV,GAAMrP,EAAO+jB,EAAeE,EAAeE,GAC/C,IAAI9U,GAAM8U,EAASC,EAAiBE,EAAiBrkB,GAE7D,EAGAukB,iBAAkB,WAEd,OAAOpkB,KAAKJ,MAAM4P,SAASxP,KAAKH,IACpC,EAGAgR,OAAQ,SAASkF,GAEb,QAASA,GACL/V,KAAKJ,MAAMuO,IAAM4H,EAAEnW,MAAMuO,GACzBnO,KAAKJ,MAAMoO,IAAM+H,EAAEnW,MAAMoO,GACzBhO,KAAK2f,cAAcxR,IAAM4H,EAAE4J,cAAcxR,GACzCnO,KAAK2f,cAAc3R,IAAM+H,EAAE4J,cAAc3R,GACzChO,KAAK4f,cAAczR,IAAM4H,EAAE6J,cAAczR,GACzCnO,KAAK4f,cAAc5R,IAAM+H,EAAE6J,cAAc5R,GACzChO,KAAKH,IAAIsO,IAAM4H,EAAElW,IAAIsO,GACrBnO,KAAKH,IAAImO,IAAM+H,EAAElW,IAAImO,CAC7B,EAGA0V,kBAAmB,SAASjS,GAExB,IAAI7R,EAAQI,KAAKJ,MACbykB,EAAWrkB,KAAK2f,cAChB2E,EAAWtkB,KAAK4f,cAChB/f,EAAMG,KAAKH,IAGf,GAAI4R,GAAK,EACL,MAAO,CACHmS,mBAAoBhkB,EAAMwC,QAC1B0hB,mBAAoBlkB,EAAMwC,QAC1B2hB,QAASnkB,EAAMwC,QACf6hB,qBAAsBI,EAASjiB,QAC/B+hB,qBAAsBG,EAASliB,SAIvC,GAAIqP,GAAK,EACL,MAAO,CACHmS,mBAAoBS,EAASjiB,QAC7B0hB,mBAAoBQ,EAASliB,QAC7B2hB,QAASlkB,EAAIuC,QACb6hB,qBAAsBpkB,EAAIuC,QAC1B+hB,qBAAsBtkB,EAAIuC,SAIlC,IAAImiB,EAAY,IAAK3V,GAAKhP,EAAOykB,GAAWhR,QAAQ5B,GAChD+S,EAAY,IAAK5V,GAAKyV,EAAUC,GAAWjR,QAAQ5B,GACnDgT,EAAY,IAAK7V,GAAK0V,EAAUzkB,GAAMwT,QAAQ5B,GAE9CiT,EAAc,IAAK9V,GAAK2V,EAAWC,GAAYnR,QAAQ5B,GACvDkT,EAAc,IAAK/V,GAAK4V,EAAWC,GAAYpR,QAAQ5B,GAY3D,MARa,CACTmS,mBAAoBW,EACpBT,mBAAoBY,EACpBX,QALU,IAAKnV,GAAK8V,EAAaC,GAActR,QAAQ5B,GAMvDwS,qBAAsBU,EACtBR,qBAAsBM,EAI9B,EAYA7C,gBAAiB,SAASvN,GAGtB,IAAInC,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UAIjEtS,EAAQI,KAAKJ,MACbykB,EAAWrkB,KAAK2f,cAChB2E,EAAWtkB,KAAK4f,cAChB/f,EAAMG,KAAKH,IAEX8hB,EAAe,CAAC,IAAI1S,GAAMrP,EAAOykB,EAAUC,EAAUzkB,IACzD,GAAkB,IAAdqS,EAAiB,OAAOyP,EAK5B,IADe3hB,KAAK+U,mBACP,OAAO4M,EAEpB,IAAIiD,EAAiB5kB,KAAKokB,mBAEtB1B,EAAiB,GAAI,IAAKxQ,GAO1B2S,EAAgB,EAK0B,IAA/BR,EAAS/S,MAAM1R,EAAOC,IAA+C,IAA/BykB,EAAShT,MAAM1R,EAAOC,KAEvEglB,EAAiB,EAAI3S,GAOzB,IADA,IAAI4S,EAAY,IACH,CACTA,GAAa,EAKb,IAFA,IAAIC,EAAkB,GAClBC,EAAkBrD,EAAanwB,OAC1BsV,EAAI,EAAGA,EAAIke,EAAiBle,IAAK,CAEtC,IACI+b,EADqBlB,EAAa7a,GACLgc,OAAO,IACxCiC,EAAgBnzB,KAAKixB,EAAQ,GAAIA,EAAQ,GAC7C,CAKA,IAFA,IAAIrxB,EAAS,EACTyzB,EAAqBF,EAAgBvzB,OAChCuV,EAAI,EAAGA,EAAIke,EAAoBle,IAGpCvV,GAD4BuzB,EAAgBhe,GACZqd,mBAIpC,GAAIU,GAAaD,IAG6B,IAAXrzB,GAAkBA,EAASozB,GAAkBpzB,EAAU,GACzDkxB,EACzB,OAAOqC,EAKfpD,EAAeoD,EACfH,EAAiBpzB,CACrB,CACJ,EAEAujB,iBAAkB,WAEd,IAAInV,EAAQI,KAAKJ,MACbykB,EAAWrkB,KAAK2f,cAChB2E,EAAWtkB,KAAK4f,cAChB/f,EAAMG,KAAKH,IAEf,QAASD,EAAMiR,OAAOwT,IAAaA,EAASxT,OAAOyT,IAAaA,EAASzT,OAAOhR,GACpF,EAGArO,OAAQ,SAAS6iB,GASb,IANA,IAAInC,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UACjEyP,OAAqClvB,IAArB4hB,EAAIsN,aAA8B3hB,KAAK4hB,gBAAgB,CAAE1P,UAAWA,IAAemC,EAAIsN,aAGvGnwB,EAAS,EACTwe,EAAI2R,EAAanwB,OACZsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAGnBtV,GADyBmwB,EAAa7a,GACTsd,mBAGjC,OAAO5yB,CACX,EAGAqwB,UAAW,SAASpQ,EAAG4C,GAEnB,GAAI5C,GAAK,EAAG,OAAO,EAGnB,IAAIS,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UAOrE,OAHelS,KAAK8iB,OAAOrR,GAAG,GACAjgB,OAAO,CAAE0gB,UAAWA,GAGtD,EAKAmB,QAAS,SAASS,EAAOO,GAErB,GAAIP,GAAS,EAAG,OAAO9T,KAAKJ,MAAMwC,QAClC,GAAI0R,GAAS,EAAG,OAAO9T,KAAKH,IAAIuC,QAEhC,IAAIqP,EAAIzR,KAAKujB,IAAIzP,EAAOO,GAExB,OAAOrU,KAAKuhB,SAAS9P,EACzB,EAGAwC,cAAe,SAASziB,EAAQ6iB,GAE5B,IAAI5C,EAAIzR,KAAKwjB,UAAUhyB,EAAQ6iB,GAE/B,OAAOrU,KAAKuhB,SAAS9P,EACzB,EAMA8P,SAAU,SAAS9P,GAEf,OAAIA,GAAK,EAAUzR,KAAKJ,MAAMwC,QAC1BqP,GAAK,EAAUzR,KAAKH,IAAIuC,QAErBpC,KAAK0jB,kBAAkBjS,GAAGsS,OACrC,EAGAtC,UAAW,EAEXpV,MAAO,SAAS6F,GAMZ,OAJAlS,KAAKJ,MAAMyM,MAAM6F,GACjBlS,KAAK2f,cAActT,MAAM6F,GACzBlS,KAAK4f,cAAcvT,MAAM6F,GACzBlS,KAAKH,IAAIwM,MAAM6F,GACRlS,IACX,EAEAuM,MAAO,SAAS6F,EAAIC,EAAI5C,GAMpB,OAJAzP,KAAKJ,MAAM2M,MAAM6F,EAAIC,EAAI5C,GACzBzP,KAAK2f,cAAcpT,MAAM6F,EAAIC,EAAI5C,GACjCzP,KAAK4f,cAAcrT,MAAM6F,EAAIC,EAAI5C,GACjCzP,KAAKH,IAAI0M,MAAM6F,EAAIC,EAAI5C,GAChBzP,IACX,EAGA4T,UAAW,SAASE,EAAOO,GAEvB,IAAKrU,KAAK+U,mBAAoB,OAAO,KAEjCjB,EAAQ,EAAGA,EAAQ,EACdA,EAAQ,IAAGA,EAAQ,GAE5B,IAAIrC,EAAIzR,KAAKujB,IAAIzP,EAAOO,GAExB,OAAOrU,KAAKojB,WAAW3R,EAC3B,EAGAmE,gBAAiB,SAASpkB,EAAQ6iB,GAE9B,IAAKrU,KAAK+U,mBAAoB,OAAO,KAErC,IAAItD,EAAIzR,KAAKwjB,UAAUhyB,EAAQ6iB,GAE/B,OAAOrU,KAAKojB,WAAW3R,EAC3B,EAGA2R,WAAY,SAAS3R,GAEjB,IAAKzR,KAAK+U,mBAAoB,OAAO,KAEjCtD,EAAI,EAAGA,EAAI,EACNA,EAAI,IAAGA,EAAI,GAEpB,IAAIyT,EAAiBllB,KAAK0jB,kBAAkBjS,GAExCd,EAAKuU,EAAepB,mBACpBlT,EAAKsU,EAAejB,qBAEpBvO,EAAewP,EAAenB,QAE9BpO,EAAc,IAAI/G,GAAK+B,EAAIC,GAG/B,OAFA+E,EAAY9C,UAAU6C,EAAavH,EAAIwC,EAAGxC,EAAGuH,EAAa1H,EAAI2C,EAAG3C,GAE1D2H,CACX,EAGA4N,IAAK,SAASzP,EAAOO,GAEjB,GAAIP,GAAS,EAAG,OAAO,EACvB,GAAIA,GAAS,EAAG,OAAO,EAGvB,IAAI5B,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UAEjEwP,EAAW,CAAExP,UAAWA,EAAWyP,kBADElvB,IAArB4hB,EAAIsN,aAA8B3hB,KAAK4hB,gBAAgB,CAAE1P,UAAWA,IAAemC,EAAIsN,cAIvGnwB,EADcwO,KAAKxO,OAAOkwB,GACH5N,EAE3B,OAAO9T,KAAKwjB,UAAUhyB,EAAQkwB,EAClC,EAWA8B,UAAW,SAAShyB,EAAQ6iB,GAExB,IAAIe,GAAY,EACZ5jB,EAAS,IACT4jB,GAAY,EACZ5jB,GAAUA,GAmBd,IAfA,IAKIswB,EACAC,EACAC,EAGAmD,EACAC,EAXAlT,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UACjEyP,OAAqClvB,IAArB4hB,EAAIsN,aAA8B3hB,KAAK4hB,gBAAgB,CAAE1P,UAAWA,IAAemC,EAAIsN,aACvGD,EAAW,CAAExP,UAAWA,EAAWyP,aAAcA,GAUjDzN,EAAI,EACJlE,EAAI2R,EAAanwB,OACjB6wB,EAAkB,EAAIrS,EACjBlJ,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CACxB,IAAIpV,EAAS0jB,EAAYtO,EAAKkJ,EAAI,EAAIlJ,EAElCwb,EAAqBX,EAAa7a,GAClCgQ,EAAIwL,EAAmB8B,mBAE3B,GAAI5yB,GAAW0iB,EAAI4C,EAAI,CACnBgL,EAA0BQ,EAE1BP,EAAgCrwB,EAAQ2wB,EACxCL,GAA+BtwB,EAAQ,GAAK2wB,EAE5C8C,EAA8B/P,EAAa5jB,EAAS0iB,EAAO4C,EAAI5C,EAAK1iB,EACpE4zB,EAA4BhQ,EAAc0B,EAAI5C,EAAK1iB,EAAWA,EAAS0iB,EAEvE,KACJ,CAEAA,GAAK4C,CACT,CAEA,IAAKgL,EAAyB,OAAQ1M,EAAY,EAAI,EAYtD,IAPA,IAAIiQ,EAAcrlB,KAAKxO,OAAOkwB,GAE1BgB,EAAiB,GAAI,IAAKxQ,KAKjB,CAGT,IAQIoT,EACAC,EANJ,IAD2C,IAAhBF,EAAsBF,EAA6BE,EAAe,GAChE3C,EAAgB,OAAOX,EAEpD,IAD2C,IAAhBsD,EAAsBD,EAA2BC,EAAe,GAC9D3C,EAAgB,OAAOV,EAMpD,IAAIa,EAAUf,EAAwBgB,OAAO,IAC7CT,GAAmB,EAEnB,IAAImD,EAAkB3C,EAAQ,GAAGuB,mBAC7BqB,EAAkB5C,EAAQ,GAAGuB,mBAE7Be,GAA8BK,GAC9B1D,EAA0Be,EAAQ,GAElCb,GAA+BK,EAG/BkD,EAA8BC,GAD9BF,EAAgCH,KAIhCrD,EAA0Be,EAAQ,GAElCd,GAAiCM,EAGjCkD,EAA8BE,GAD9BH,EAAgCH,EAA6BK,IAIjEL,EAA6BG,EAC7BF,EAA2BG,CAC/B,CACJ,EAIAG,SAAU,SAASrR,GASf,IANA,IAAInC,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UACjEyP,OAAqClvB,IAArB4hB,EAAIsN,aAA8B3hB,KAAK4hB,gBAAgB,CAAE1P,UAAWA,IAAemC,EAAIsN,aAGvG5R,EAAS,CAAC4R,EAAa,GAAG/hB,MAAMwC,SAChC4N,EAAI2R,EAAanwB,OACZsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CAExB,IAAIwb,EAAqBX,EAAa7a,GACtCiJ,EAAOne,KAAK0wB,EAAmBziB,IAAIuC,QACvC,CAEA,OAAO2N,CACX,EAIAsT,WAAY,SAAShP,GAEjB,OAAO,IAAItF,GAAS/O,KAAK0lB,SAASrR,GACtC,EAEAthB,SAAU,WAEN,OAAOiN,KAAKJ,MAAQ,IAAMI,KAAK2f,cAAgB,IAAM3f,KAAK4f,cAAgB,IAAM5f,KAAKH,GACzF,EAEAgT,UAAW,SAASgD,EAAIC,GAMpB,OAJA9V,KAAKJ,MAAMiT,UAAUgD,EAAIC,GACzB9V,KAAK2f,cAAc9M,UAAUgD,EAAIC,GACjC9V,KAAK4f,cAAc/M,UAAUgD,EAAIC,GACjC9V,KAAKH,IAAIgT,UAAUgD,EAAIC,GAChB9V,IACX,GAGJiP,GAAM3jB,UAAUw3B,OAAS7T,GAAM3jB,UAAUg4B,UEl7BlC,MAAMpU,GAAO,SAASyW,GAEzB,KAAM3lB,gBAAgBkP,IAClB,OAAO,IAAIA,GAAKyW,GAGpB,GAAmB,iBAARA,EACP,OAAO,IAAIzW,GAAKiP,MAAMwH,GAK1B,IAAI7e,EACAkJ,EAEJ,GALAhQ,KAAK4lB,SAAW,GAKXD,EAGE,GAAI30B,MAAMC,QAAQ00B,IAAuB,IAAfA,EAAIn0B,OAQjC,GADAwe,GAJA2V,EAAMA,EAAI3hB,QAAO,SAAS6hB,EAAKrnB,GAC3B,OAAOqnB,EAAIld,OAAOnK,EACtB,GAAG,KAEKhN,OACJm0B,EAAI,GAAGG,UACP,IAAKhf,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CAEpB,IAAI2X,EAAUkH,EAAI7e,GAElB9G,KAAK+lB,cAActH,EACvB,KAEG,CACH,IAAIuH,EAAc,KAClB,IAAKlf,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CAEpB,IAAI1b,EAAMu6B,EAAI7e,GAEd,KAAO1b,aAAewjB,IAAUxjB,aAAe6jB,IAC3C,MAAM,IAAIjG,MAAM,6DAGV,IAANlC,GAAS9G,KAAK+lB,cAAc7W,GAAK+W,cAAc,IAAK76B,EAAIwU,QAGxDomB,IAAgBA,EAAYnmB,IAAIgR,OAAOzlB,EAAIwU,QAAQI,KAAK+lB,cAAc7W,GAAK+W,cAAc,IAAK76B,EAAIwU,QAElGxU,aAAewjB,GACf5O,KAAK+lB,cAAc7W,GAAK+W,cAAc,IAAK76B,EAAIyU,MAExCzU,aAAe6jB,IACtBjP,KAAK+lB,cAAc7W,GAAK+W,cAAc,IAAK76B,EAAIu0B,cAAev0B,EAAIw0B,cAAex0B,EAAIyU,MAGzFmmB,EAAc56B,CAClB,CACJ,MAEG,GAAIu6B,EAAIG,UACX9lB,KAAK+lB,cAAcJ,QAEhB,GAAIA,aAAe/W,GACtB5O,KAAK+lB,cAAc7W,GAAK+W,cAAc,IAAKN,EAAI/lB,QAC/CI,KAAK+lB,cAAc7W,GAAK+W,cAAc,IAAKN,EAAI9lB,WAE5C,GAAI8lB,aAAe1W,GACtBjP,KAAK+lB,cAAc7W,GAAK+W,cAAc,IAAKN,EAAI/lB,QAC/CI,KAAK+lB,cAAc7W,GAAK+W,cAAc,IAAKN,EAAIhG,cAAegG,EAAI/F,cAAe+F,EAAI9lB,UAElF,MAAI8lB,aAAe5W,IAatB,MAAM,IAAI/F,MAAM,qDAZhB,IAAM2c,EAAI5V,QAAiC,IAAtB4V,EAAI5V,OAAOve,OAAgB,OAGhD,IADAwe,EAAI2V,EAAI5V,OAAOve,OACVsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CAEpB,IAAIkK,EAAQ2U,EAAI5V,OAAOjJ,GAEb,IAANA,EAAS9G,KAAK+lB,cAAc7W,GAAK+W,cAAc,IAAKjV,IACnDhR,KAAK+lB,cAAc7W,GAAK+W,cAAc,IAAKjV,GACpD,CAIJ,CACJ,EAitCA,SAASkV,GAAW5zB,EAAa6zB,GAmB7B,OAFAA,EAAUlJ,QAAQ,MAEX,IAAKmJ,SAAS96B,UAAUyE,KAAKoR,MAAM7O,EAAa6zB,GAC3D,CA7tCAjX,GAAKiP,MAAQ,SAASkI,GAElB,IAAKA,EAAU,OAAO,IAAInX,GAQ1B,IANA,IAAIpX,EAAO,IAAIoX,GAGXoX,EAAWD,EAASj2B,MADR,6GAGZm2B,EAAcD,EAAS90B,OAClBsV,EAAI,EAAGA,EAAIyf,EAAazf,IAAK,CAElC,IAEI7F,EAFUqlB,EAASxf,GAEJ1W,MADP,uEAGRquB,EAAUvP,GAAK+W,cAAc9kB,MAAMnB,KAAMiB,GAC7CnJ,EAAKiuB,cAActH,EACvB,CAEA,OAAO3mB,CACX,EAIAoX,GAAK+W,cAAgB,SAAS9zB,GAE1B,IAAKA,EAAM,MAAM,IAAI6W,MAAM,0BAE3B,IAAIwd,EAAqBtX,GAAKuX,aAAat0B,GAC3C,IAAKq0B,EAAoB,MAAM,IAAIxd,MAAM7W,EAAO,2CAIhD,IAFA,IAAI8O,EAAO,GACP+O,EAAIpR,UAAUpN,OACTsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IACnB7F,EAAKrP,KAAKgN,UAAUkI,IAGxB,OAAOof,GAAWM,EAAoBvlB,EAC1C,EAEAiO,GAAK5jB,UAAY,CAEb6G,KAAMsX,GAAMyF,KAIZ6W,cAAe,SAASJ,GAEpB,IAIIe,EAJAd,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAKvBo1B,EAAoC,IAAhBD,EAAqBf,EAASe,EAAc,GAAK,KAGzE,GAAK31B,MAAMC,QAAQ00B,GAMZ,CAOH,KAJAA,EAAMA,EAAI3hB,QAAO,SAAS6hB,EAAKrnB,GAC3B,OAAOqnB,EAAIld,OAAOnK,EACtB,GAAG,KAEM,GAAGsnB,UAAW,MAAM,IAAI9c,MAAM,sBAGvC,IADA,IAAIgH,EAAI2V,EAAIn0B,OACHsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CAExB,IAAI+f,EAAalB,EAAI7e,GACrB4f,EAAiB1mB,KAAK8mB,eAAeD,EAAYD,EArBvC,MAsBVhB,EAASh0B,KAAK80B,GACdE,EAAkBF,CACtB,CACJ,KAvByB,CACrB,IAAKf,IAAQA,EAAIG,UAAW,MAAM,IAAI9c,MAAM,qBAE5C0d,EAAiB1mB,KAAK8mB,eAAenB,EAAKiB,EAL5B,MAMdhB,EAASh0B,KAAK80B,EAElB,CAkBJ,EAKA3T,KAAM,WAEF,IAIIA,EAJA6S,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,OAAO,KAG9B,IAAK,IAAI7f,EAAI,EAAGA,EAAI6f,EAAa7f,IAAK,CAElC,IAAI2X,EAAUmH,EAAS9e,GACvB,GAAI2X,EAAQsI,UAAW,CACnB,IAAIC,EAAcvI,EAAQ1L,OAC1BA,EAAOA,EAAOA,EAAK3P,MAAM4jB,GAAeA,CAC5C,CACJ,CAEA,GAAIjU,EAAM,OAAOA,EAGjB,IAAI3X,EAAcwqB,EAASe,EAAc,GACzC,OAAO,IAAI7X,GAAK1T,EAAYyE,IAAIsO,EAAG/S,EAAYyE,IAAImO,EAAG,EAAG,EAC7D,EAGA5L,MAAO,WAOH,IALA,IAAIwjB,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAGvBsG,EAAO,IAAIoX,GACNpI,EAAI,EAAGA,EAAI6f,EAAa7f,IAAK,CAElC,IAAI2X,EAAUmH,EAAS9e,GAAG1E,QAC1BtK,EAAKiuB,cAActH,EACvB,CAEA,OAAO3mB,CACX,EAEAsb,aAAc,SAASvF,EAAGwG,GAEtB,IAAI5C,EAAIzR,KAAKwhB,cAAc3T,EAAGwG,GAC9B,OAAK5C,EAEEzR,KAAKuhB,SAAS9P,GAFN,IAGnB,EAEA8B,mBAAoB,SAAS1F,EAAGwG,GAG5B,IAAInC,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UAEjEwP,EAAW,CAAExP,UAAWA,EAAW+U,yBADgBx0B,IAA5B4hB,EAAI4S,oBAAqCjnB,KAAKknB,uBAAuB,CAAEhV,UAAWA,IAAemC,EAAI4S,qBAG5HxV,EAAIzR,KAAKwhB,cAAc3T,EAAG6T,GAC9B,OAAKjQ,EAEEzR,KAAK6hB,UAAUpQ,EAAGiQ,GAFV,CAGnB,EAEApO,6BAA8B,SAASzF,EAAGwG,GAGtC,IAAInC,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UAEjEwP,EAAW,CAAExP,UAAWA,EAAW+U,yBADgBx0B,IAA5B4hB,EAAI4S,oBAAqCjnB,KAAKknB,uBAAuB,CAAEhV,UAAWA,IAAemC,EAAI4S,qBAG5H7I,EAAWpe,KAAKuT,mBAAmB1F,EAAG6T,GAC1C,GAAiB,IAAbtD,EAAgB,OAAO,EAE3B,IAAI5sB,EAASwO,KAAKxO,OAAOkwB,GACzB,OAAe,IAAXlwB,EAAqB,EAElB4sB,EAAW5sB,CACtB,EAGAgwB,cAAe,SAAS3T,EAAGwG,GAEvB,IAAIuR,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,OAAO,KAS9B,IANA,IAIInF,EAJAtP,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UACjE+U,OAAmDx0B,IAA5B4hB,EAAI4S,oBAAqCjnB,KAAKknB,uBAAuB,CAAEhV,UAAWA,IAAemC,EAAI4S,oBAI5HE,EAAqBlkB,IAChB6D,EAAI,EAAGA,EAAI6f,EAAa7f,IAAK,CAElC,IAAI2X,EAAUmH,EAAS9e,GACnB6a,EAAesF,EAAoBngB,GAEvC,GAAI2X,EAAQsI,UAAW,CACnB,IAAIK,EAAuB3I,EAAQ+C,cAAc3T,EAAG,CAChDqE,UAAWA,EACXyP,aAAcA,IAEd0F,EAAsB5I,EAAQ8C,SAAS6F,GACvChX,EAAkB,IAAKxB,GAAKyY,EAAqBxZ,GAAIU,gBAErD6B,EAAkB+W,IAClB3F,EAAgB,CAAE8F,aAAcxgB,EAAGnb,MAAOy7B,GAC1CD,EAAqB/W,EAE7B,CACJ,CAEA,OAAIoR,GAGG,CAAE8F,aAAcX,EAAc,EAAGh7B,MAAO,EACnD,EAEAgoB,oBAAqB,SAAS9F,EAAGwG,GAE7B,IAAIuR,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,OAAO,KAS9B,IANA,IAIIhT,EAJAzB,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UACjE+U,OAAmDx0B,IAA5B4hB,EAAI4S,oBAAqCjnB,KAAKknB,uBAAuB,CAAEhV,UAAWA,IAAemC,EAAI4S,oBAI5HE,EAAqBlkB,IAChB6D,EAAI,EAAGA,EAAI6f,EAAa7f,IAAK,CAElC,IAAI2X,EAAUmH,EAAS9e,GACnB6a,EAAesF,EAAoBngB,GAEvC,GAAI2X,EAAQ1J,mBAAoB,CAC5B,IAAIqS,EAAuB3I,EAAQ+C,cAAc3T,EAAG,CAChDqE,UAAWA,EACXyP,aAAcA,IAEd0F,EAAsB5I,EAAQ8C,SAAS6F,GACvChX,EAAkB,IAAKxB,GAAKyY,EAAqBxZ,GAAIU,gBAErD6B,EAAkB+W,IAClBxT,EAAsB8K,EAAQ2E,WAAWgE,GACzCD,EAAqB/W,EAE7B,CACJ,CAEA,OAAIuD,GAGG,IACX,EAMApD,cAAe,SAAS1C,EAAGwG,GAEvB,IAAIkT,EAAYvnB,KAAKwnB,YAAYnT,GACjC,IAAKkT,EAAW,OAAO,EAMvB,IAJA,IAAIE,EAAeF,EAAU/1B,OAGzBgtB,EAAmB,EACd1X,EAAI,EAAGA,EAAI2gB,EAAc3gB,IACfygB,EAAUzgB,GACZyJ,cAAc1C,IAEvB2Q,IAKR,OAASA,EAAmB,GAAO,CACvC,EAGA3K,SAAU,SAASC,EAAOO,GAItB,GAAoB,IAFLrU,KAAK4lB,SACOp0B,OACJ,OAAO,KAE1BsiB,EAAQ,IAAGA,EAAQ,GACnBA,EAAQ,IAAGA,EAAQ,GAGvB,IAAI5B,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UAEjEwP,EAAW,CAAExP,UAAWA,EAAW+U,yBADgBx0B,IAA5B4hB,EAAI4S,oBAAqCjnB,KAAKknB,uBAAuB,CAAEhV,UAAWA,IAAemC,EAAI4S,qBAI5Hz1B,EADawO,KAAKxO,OAAOkwB,GACH5N,EAE1B,OAAO9T,KAAKgU,eAAexiB,EAAQkwB,EACvC,EAGA1N,eAAgB,SAASxiB,EAAQ6iB,GAE7B,IAAIsS,EAAc3mB,KAAK4lB,SAASp0B,OAChC,GAAoB,IAAhBm1B,EAAmB,OAAO,KAE9B,IAAIvR,GAAY,EACZ5jB,EAAS,IACT4jB,GAAY,EACZ5jB,GAAUA,GAId,IAIIsV,EACA2X,EAKAoE,EACA6E,EACAC,EACAC,EACAnW,EAdAS,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UACjE+U,OAAmDx0B,IAA5B4hB,EAAI4S,oBAAqCjnB,KAAKknB,uBAAuB,CAAEhV,UAAWA,IAAemC,EAAI4S,oBAQ5H/S,EAAI,EAMR,IAAKpN,EAAI,EAAGA,EAAI6f,EAAa7f,IAAK,CAC9B,IAAIpV,EAAS0jB,EAAYtO,EAAK6f,EAAc,EAAI7f,EAEhD2X,EAAUze,KAAK6nB,WAAWn2B,GAC1B,IAAIiwB,EAAesF,EAAoBv1B,GACnColB,EAAI2H,EAAQjtB,OAAO,CAAE0gB,UAAWA,EAAWyP,aAAcA,IAE7D,GAAIlD,EAAQ1J,qBACR4S,EAAmBlJ,EACnBmJ,EAAwBl2B,EAEpBF,GAAW0iB,EAAI4C,GAAI,CACnB4Q,EAAsBh2B,EACtBmxB,EAAUpE,EAAQzK,gBAAiBoB,EAAY,GAAK,IAAM5jB,EAAS0iB,GAAK,CACpEhC,UAAWA,EACXyP,aAAcA,IAElB,KACJ,CAGJzN,GAAK4C,CACT,CAEA,IAAK6Q,EACD,OAAO,KAKN9E,IACD6E,EAAsBE,EACtBnW,EAAK2D,EAAY,EAAI,EACrByN,EAAU8E,EAAiBrE,UAAU7R,IAKzC,IAAIqW,EAAW9nB,KAAKoC,QACpB0lB,EAASC,eAAeL,EAAqB7E,GAE7C,IAAImF,EAAqBN,EACrBO,EAAmBP,EAAsB,EACzCQ,EAAmBR,EAAsB,EAGxC7E,EAAQ,GAAG9N,qBACZ+S,EAASK,cAAcH,GACvBC,GAAoB,EACpBC,GAAoB,GAIxB,IAAIE,EAAYN,EAASD,WAAWI,GAAkBroB,MACtDkoB,EAASO,cAAcJ,EAAkB/Y,GAAK+W,cAAc,IAAKmC,IACjEF,GAAoB,EAGfrF,EAAQ,GAAG9N,qBACZ+S,EAASK,cAAcD,EAAmB,GAC1CA,GAAoB,GAKxB,IAAII,EAAmCJ,EAAmBF,EAAqB,EAC/E,IAAKlhB,EAAIohB,EAAkBphB,EAAIghB,EAASlC,SAASp0B,OAAQsV,IAAK,CAE1D,IAAIyhB,EAAkBvoB,KAAK6nB,WAAW/gB,EAAIwhB,GAG1C,GAAsB,OAFtB7J,EAAUqJ,EAASD,WAAW/gB,IAEjB3U,OAAkBo2B,EAAgBC,oBAAoB3oB,IAAIgR,OAAO4N,EAAQ+J,oBAAoB3oB,KAAM,CAG5G,IAAI4oB,EAAmBvZ,GAAK+W,cAAc,IAAKsC,EAAgB1oB,KAC/DioB,EAASC,eAAejhB,EAAG2hB,EAC/B,CACJ,CAOA,MAAO,CAHS,IAAIvZ,GAAK4Y,EAASlC,SAAS9qB,MAAM,EAAGmtB,IACnC,IAAI/Y,GAAK4Y,EAASlC,SAAS9qB,MAAMmtB,IAGtD,EAIApX,OAAQ,SAAShD,GAEb,IAAKA,EAAG,OAAO,EAEf,IAAI+X,EAAW5lB,KAAK4lB,SAChB8C,EAAgB7a,EAAE+X,SAElBe,EAAcf,EAASp0B,OAC3B,GAAIk3B,EAAcl3B,SAAWm1B,EAAa,OAAO,EAEjD,IAAK,IAAI7f,EAAI,EAAGA,EAAI6f,EAAa7f,IAAK,CAElC,IAAI2X,EAAUmH,EAAS9e,GACnB6hB,EAAeD,EAAc5hB,GAGjC,GAAK2X,EAAQtsB,OAASw2B,EAAax2B,OAAWssB,EAAQ5N,OAAO8X,GAAgB,OAAO,CACxF,CAGA,OAAO,CACX,EAKAd,WAAY,SAASn2B,GAEjB,IAAIk0B,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,MAAM,IAAI3d,MAAM,yBAGvC,GADItX,EAAQ,IAAGA,EAAQi1B,EAAcj1B,GACjCA,GAASi1B,GAAej1B,EAAQ,EAAG,MAAM,IAAIsX,MAAM,uBAEvD,OAAO4c,EAASl0B,EACpB,EAGAw1B,uBAAwB,SAAS7S,GAY7B,IAVA,IAAIuR,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAIvB0gB,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UAIjE+U,EAAsB,GACjBngB,EAAI,EAAGA,EAAI6f,EAAa7f,IAAK,CAElC,IACI6a,EADUiE,EAAS9e,GACI8a,gBAAgB,CAAE1P,UAAWA,IACxD+U,EAAoBr1B,KAAK+vB,EAC7B,CAEA,OAAOsF,CACX,EAKA2B,YAAa,WAET,MAEMhD,EAFgB5lB,KAAKoC,QAAQymB,WAEJjD,SACzBe,EAAcf,EAASp0B,OAEvBs3B,EAAW,GACjB,IAAK,IAAIhiB,EAAI,EAAGA,EAAI6f,EAAa7f,IAAK,CAElC,MAAM2X,EAAUmH,EAAS9e,GACrB2X,EAAQsK,eAGRD,EAASl3B,KAAK,IAAIsd,GAAKuP,IAIvBqK,EAASA,EAASt3B,OAAS,GAAGu0B,cAActH,EAEpD,CAEA,OAAOqK,CACX,EASAT,cAAe,SAAS32B,EAAOi0B,GAE3B,IASIe,EATAd,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAM3B,GADIE,EAAQ,IAAGA,EAAQi1B,EAAcj1B,EAAQ,GACzCA,EAAQi1B,GAAej1B,EAAQ,EAAG,MAAM,IAAIsX,MAAM,uBAItD,IAAI4d,EAAkB,KAClBoC,EAAc,KAalB,GAXoB,IAAhBrC,IAGIqC,EAFAt3B,GAAS,GACTk1B,EAAkBhB,EAASl0B,EAAQ,IACLs3B,YAIhBpD,EAAS,IAI1B50B,MAAMC,QAAQ00B,GAMZ,CAOH,KAJAA,EAAMA,EAAI3hB,QAAO,SAAS6hB,EAAKrnB,GAC3B,OAAOqnB,EAAIld,OAAOnK,EACtB,GAAG,KAEM,GAAGsnB,UAAW,MAAM,IAAI9c,MAAM,sBAGvC,IADA,IAAIgH,EAAI2V,EAAIn0B,OACHsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CAExB,IAAI+f,EAAalB,EAAI7e,GACrB4f,EAAiB1mB,KAAK8mB,eAAeD,EAAYD,EAAiBoC,GAClEpD,EAASplB,OAAQ9O,EAAQoV,EAAI,EAAG4f,GAChCE,EAAkBF,CACtB,CACJ,KAvByB,CACrB,IAAKf,IAAQA,EAAIG,UAAW,MAAM,IAAI9c,MAAM,qBAE5C0d,EAAiB1mB,KAAK8mB,eAAenB,EAAKiB,EAAiBoC,GAC3DpD,EAASplB,OAAO9O,EAAO,EAAGg1B,EAE9B,CAkBJ,EAEApS,qBAAsB,SAASE,EAAMH,GAEjC,IAAIE,EAAe,KACfgT,EAAYvnB,KAAKwnB,YAAYnT,GACjC,IAAKkT,EAAW,OAAO,KACvB,IAAK,IAAIzgB,EAAI,EAAGkJ,EAAIuX,EAAU/1B,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAC9C,IAAImiB,EAAW1B,EAAUzgB,GACrBoiB,EAAuB1U,EAAKL,UAAU8U,GACtCC,IACA3U,IAAiBA,EAAe,IAC5BvjB,MAAMC,QAAQi4B,GACdl4B,MAAM1F,UAAUsG,KAAKuP,MAAMoT,EAAc2U,GAEzC3U,EAAa3iB,KAAKs3B,GAG9B,CAEA,OAAO3U,CACX,EAEAQ,iBAAkB,WAKd,IAHA,IAAI6Q,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAElBsV,EAAI,EAAGA,EAAI6f,EAAa7f,IAI7B,GAFc8e,EAAS9e,GAEXiO,mBAAoB,OAAO,EAI3C,OAAO,CACX,EAIAoU,QAAS,WAEL,IAAIvD,EAAW5lB,KAAK4lB,SAEpB,OADmC,IAApBA,EAASp0B,QAAuC,MAArBo0B,EAAS,GAAGzzB,IAE1D,EAIAX,OAAQ,SAAS6iB,GAEb,IAAIuR,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,OAAO,EAQ9B,IALA,IAAIzU,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UACjE+U,OAAmDx0B,IAA5B4hB,EAAI4S,oBAAqCjnB,KAAKknB,uBAAuB,CAAEhV,UAAWA,IAAemC,EAAI4S,oBAG5Hz1B,EAAS,EACJsV,EAAI,EAAGA,EAAI6f,EAAa7f,IAAK,CAElC,IAAI2X,EAAUmH,EAAS9e,GACnB6a,EAAesF,EAAoBngB,GACvCtV,GAAUitB,EAAQjtB,OAAO,CAAEmwB,aAAcA,GAC7C,CAEA,OAAOnwB,CACX,EAGAqwB,UAAW,SAASpQ,EAAG4C,GAEnB,IAAIuR,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,OAAO,EAE9B,IAAIW,EAAe7V,EAAE6V,aACrB,GAAIA,EAAe,EAAG,OAAO,EAE7B,IAAI8B,EAAS3X,EAAE9lB,MACX27B,GAAgBX,GAChBW,EAAeX,EAAc,EAC7ByC,EAAS,GACFA,EAAS,EAAGA,EAAS,EACvBA,EAAS,IAAGA,EAAS,GAS9B,IANA,IAIIzH,EAJAzP,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UACjE+U,OAAmDx0B,IAA5B4hB,EAAI4S,oBAAqCjnB,KAAKknB,uBAAuB,CAAEhV,UAAWA,IAAemC,EAAI4S,oBAI5Hz1B,EAAS,EACJsV,EAAI,EAAGA,EAAIwgB,EAAcxgB,IAAK,CAEnC,IAAI2X,EAAUmH,EAAS9e,GACvB6a,EAAesF,EAAoBngB,GACnCtV,GAAUitB,EAAQjtB,OAAO,CAAE63B,WAAYnX,EAAWyP,aAAcA,GACpE,CAMA,OAJAlD,EAAUmH,EAAS0B,GACnB3F,EAAesF,EAAoBK,GACnC91B,EAAUitB,EAAQoD,UAAUuH,EAAQ,CAAEC,WAAYnX,EAAWyP,aAAcA,GAG/E,EAGAtO,QAAS,SAASS,EAAOO,GAIrB,GAAoB,IAFLrU,KAAK4lB,SACOp0B,OACJ,OAAO,KAE9B,GAAIsiB,GAAS,EAAG,OAAO9T,KAAKJ,MAAMwC,QAClC,GAAI0R,GAAS,EAAG,OAAO9T,KAAKH,IAAIuC,QAGhC,IAAI8P,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UAEjEwP,EAAW,CAAExP,UAAWA,EAAW+U,yBADgBx0B,IAA5B4hB,EAAI4S,oBAAqCjnB,KAAKknB,uBAAuB,CAAEhV,UAAWA,IAAemC,EAAI4S,qBAI5Hz1B,EADawO,KAAKxO,OAAOkwB,GACH5N,EAE1B,OAAO9T,KAAKiU,cAAcziB,EAAQkwB,EACtC,EAIAzN,cAAe,SAASziB,EAAQ6iB,GAE5B,IAAIuR,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,OAAO,KAE9B,GAAe,IAAXn1B,EAAc,OAAOwO,KAAKJ,MAAMwC,QAEpC,IAAIgT,GAAY,EACZ5jB,EAAS,IACT4jB,GAAY,EACZ5jB,GAAUA,GAUd,IANA,IAII83B,EAJApX,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UACjE+U,OAAmDx0B,IAA5B4hB,EAAI4S,oBAAqCjnB,KAAKknB,uBAAuB,CAAEhV,UAAWA,IAAemC,EAAI4S,oBAI5H/S,EAAI,EACCpN,EAAI,EAAGA,EAAI6f,EAAa7f,IAAK,CAClC,IAAIpV,EAAS0jB,EAAYtO,EAAK6f,EAAc,EAAI7f,EAE5C2X,EAAUmH,EAASl0B,GACnBiwB,EAAesF,EAAoBv1B,GACnColB,EAAI2H,EAAQjtB,OAAO,CAAE0gB,UAAWA,EAAWyP,aAAcA,IAE7D,GAAIlD,EAAQsI,UAAW,CACnB,GAAIv1B,GAAW0iB,EAAI4C,EACf,OAAO2H,EAAQxK,eAAgBmB,EAAY,GAAK,IAAM5jB,EAAS0iB,GAAK,CAChEhC,UAAWA,EACXyP,aAAcA,IAItB2H,EAAqB7K,CACzB,CAEAvK,GAAK4C,CACT,CAGA,OAAIwS,EAA4BlU,EAAYkU,EAAmBzpB,IAAMypB,EAAmB1pB,MAGtEgmB,EAASe,EAAc,GACtB9mB,IAAIuC,OAC3B,EAGAmf,SAAU,SAAS9P,GAEf,IAAImU,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,OAAO,KAE9B,IAAIW,EAAe7V,EAAE6V,aACrB,GAAIA,EAAe,EAAG,OAAO1B,EAAS,GAAGrE,SAAS,GAClD,GAAI+F,GAAgBX,EAAa,OAAOf,EAASe,EAAc,GAAGpF,SAAS,GAE3E,IAAI6H,EAAS3X,EAAE9lB,MAIf,OAHIy9B,EAAS,EAAGA,EAAS,EAChBA,EAAS,IAAGA,EAAS,GAEvBxD,EAAS0B,GAAc/F,SAAS6H,EAC3C,EAGA3H,UAAW,EAGXqF,eAAgB,SAASrI,EAASmI,EAAiBoC,GAG/CvK,EAAQmI,gBAAkBA,EAC1BnI,EAAQuK,YAAcA,EAClBpC,IAAiBA,EAAgBoC,YAAcvK,GAC/CuK,IAAaA,EAAYpC,gBAAkBnI,GAE/C,IAAI8K,EAAqB9K,EASzB,OARIA,EAAQsK,iBACRtK,EAAQ+J,oBAAsB/J,EAC9B8K,EAAqBP,GAIrBO,GAAoBvpB,KAAKwpB,0BAA0BD,GAEhD9K,CACX,EAMA0J,cAAe,SAASz2B,GAEpB,IAAIk0B,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,MAAM,IAAI3d,MAAM,yBAGvC,GADItX,EAAQ,IAAGA,EAAQi1B,EAAcj1B,GACjCA,GAASi1B,GAAej1B,EAAQ,EAAG,MAAM,IAAIsX,MAAM,uBAEvD,IAAIygB,EAAiB7D,EAASplB,OAAO9O,EAAO,GAAG,GAC3Ck1B,EAAkB6C,EAAe7C,gBACjCoC,EAAcS,EAAeT,YAG7BpC,IAAiBA,EAAgBoC,YAAcA,GAC/CA,IAAaA,EAAYpC,gBAAkBA,GAG3C6C,EAAeV,gBAAkBC,GAAahpB,KAAKwpB,0BAA0BR,EACrF,EAQAjB,eAAgB,SAASr2B,EAAOi0B,GAE5B,IAOIe,EAPAd,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,MAAM,IAAI3d,MAAM,yBAGvC,GADItX,EAAQ,IAAGA,EAAQi1B,EAAcj1B,GACjCA,GAASi1B,GAAej1B,EAAQ,EAAG,MAAM,IAAIsX,MAAM,uBAIvD,IAAI0gB,EAAkB9D,EAASl0B,GAC3Bk1B,EAAkB8C,EAAgB9C,gBAClCoC,EAAcU,EAAgBV,YAE9BO,EAAqBG,EAAgBX,eAEzC,GAAK/3B,MAAMC,QAAQ00B,GAQZ,CAOH,KAJAA,EAAMA,EAAI3hB,QAAO,SAAS6hB,EAAKrnB,GAC3B,OAAOqnB,EAAIld,OAAOnK,EACtB,GAAG,KAEM,GAAGsnB,UAAW,MAAM,IAAI9c,MAAM,sBAEvC4c,EAASplB,OAAO9O,EAAO,GAGvB,IADA,IAAIse,EAAI2V,EAAIn0B,OACHsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CAExB,IAAI+f,EAAalB,EAAI7e,GACrB4f,EAAiB1mB,KAAK8mB,eAAeD,EAAYD,EAAiBoC,GAClEpD,EAASplB,OAAQ9O,EAAQoV,EAAI,EAAG4f,GAChCE,EAAkBF,EAEd6C,GAAsB7C,EAAeqC,iBAAgBQ,GAAqB,EAClF,CACJ,KA7ByB,CACrB,IAAK5D,IAAQA,EAAIG,UAAW,MAAM,IAAI9c,MAAM,qBAE5C0d,EAAiB1mB,KAAK8mB,eAAenB,EAAKiB,EAAiBoC,GAC3DpD,EAASplB,OAAO9O,EAAO,EAAGg1B,GAEtB6C,GAAsB7C,EAAeqC,iBAAgBQ,GAAqB,EAElF,CAwBIA,GAAsBP,GAAahpB,KAAKwpB,0BAA0BR,EAC1E,EAEA3c,MAAO,SAAS6F,GAKZ,IAHA,IAAI0T,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAElBsV,EAAI,EAAGA,EAAI6f,EAAa7f,IAEf8e,EAAS9e,GACfuF,MAAM6F,GAGlB,OAAOlS,IACX,EAEAuM,MAAO,SAAS6F,EAAIC,EAAI5C,GAKpB,IAHA,IAAImW,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAElBsV,EAAI,EAAGA,EAAI6f,EAAa7f,IAEf8e,EAAS9e,GACfyF,MAAM6F,EAAIC,EAAI5C,GAG1B,OAAOzP,IACX,EAEA2pB,UAAW,SAAS7V,EAAOO,GAEvB,IAAI3iB,EAAQsO,KAAK4pB,eAAe9V,EAAOO,GACvC,OAAK3iB,EAEEsO,KAAK6nB,WAAWn2B,GAFJ,IAGvB,EAGAm4B,gBAAiB,SAASr4B,EAAQ6iB,GAE9B,IAAI3iB,EAAQsO,KAAK8pB,qBAAqBt4B,EAAQ6iB,GAC9C,OAAK3iB,EAEEsO,KAAK6nB,WAAWn2B,GAFJ,IAGvB,EAEAk4B,eAAgB,SAAS9V,EAAOO,GAI5B,GAAoB,IAFLrU,KAAK4lB,SACOp0B,OACJ,OAAO,KAE1BsiB,EAAQ,IAAGA,EAAQ,GACnBA,EAAQ,IAAGA,EAAQ,GAGvB,IAAI5B,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UAEjEwP,EAAW,CAAExP,UAAWA,EAAW+U,yBADgBx0B,IAA5B4hB,EAAI4S,oBAAqCjnB,KAAKknB,uBAAuB,CAAEhV,UAAWA,IAAemC,EAAI4S,qBAI5Hz1B,EADawO,KAAKxO,OAAOkwB,GACH5N,EAE1B,OAAO9T,KAAK8pB,qBAAqBt4B,EAAQkwB,EAC7C,EAGAoI,qBAAsB,SAASt4B,EAAQ6iB,GAEnC,IAAIuR,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,OAAO,KAE9B,IAAIvR,GAAY,EACZ5jB,EAAS,IACT4jB,GAAY,EACZ5jB,GAAUA,GAUd,IANA,IAAI0gB,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UACjE+U,OAAmDx0B,IAA5B4hB,EAAI4S,oBAAqCjnB,KAAKknB,uBAAuB,CAAEhV,UAAWA,IAAemC,EAAI4S,oBAG5H8C,EAA0B,KAC1B7V,EAAI,EACCpN,EAAI,EAAGA,EAAI6f,EAAa7f,IAAK,CAClC,IAAIpV,EAAS0jB,EAAYtO,EAAK6f,EAAc,EAAI7f,EAE5C2X,EAAUmH,EAASl0B,GACnBiwB,EAAesF,EAAoBv1B,GACnColB,EAAI2H,EAAQjtB,OAAO,CAAE0gB,UAAWA,EAAWyP,aAAcA,IAE7D,GAAIlD,EAAQsI,UAAW,CACnB,GAAIv1B,GAAW0iB,EAAI4C,EAAI,OAAOplB,EAC9Bq4B,EAA0Br4B,CAC9B,CAEAwiB,GAAK4C,CACT,CAIA,OAAOiT,CACX,EAIArX,UAAW,WAEP,IAAK1S,KAAKmpB,UAAW,MAAM,IAAIngB,MAAM,0BAErC,OAAOhJ,KAAKjN,UAChB,EAGA6gB,UAAW,SAASE,EAAOO,GAIvB,GAAoB,IAFLrU,KAAK4lB,SACOp0B,OACJ,OAAO,KAE1BsiB,EAAQ,IAAGA,EAAQ,GACnBA,EAAQ,IAAGA,EAAQ,GAGvB,IAAI5B,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UAEjEwP,EAAW,CAAExP,UAAWA,EAAW+U,yBADgBx0B,IAA5B4hB,EAAI4S,oBAAqCjnB,KAAKknB,uBAAuB,CAAEhV,UAAWA,IAAemC,EAAI4S,qBAI5Hz1B,EADawO,KAAKxO,OAAOkwB,GACH5N,EAE1B,OAAO9T,KAAK4V,gBAAgBpkB,EAAQkwB,EACxC,EAIA9L,gBAAiB,SAASpkB,EAAQ6iB,GAE9B,IAAIuR,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,OAAO,KAE9B,IAAIvR,GAAY,EACZ5jB,EAAS,IACT4jB,GAAY,EACZ5jB,GAAUA,GAUd,IANA,IAIIm2B,EAJAzV,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UACjE+U,OAAmDx0B,IAA5B4hB,EAAI4S,oBAAqCjnB,KAAKknB,uBAAuB,CAAEhV,UAAWA,IAAemC,EAAI4S,oBAI5H/S,EAAI,EACCpN,EAAI,EAAGA,EAAI6f,EAAa7f,IAAK,CAClC,IAAIpV,EAAS0jB,EAAYtO,EAAK6f,EAAc,EAAI7f,EAE5C2X,EAAUmH,EAASl0B,GACnBiwB,EAAesF,EAAoBv1B,GACnColB,EAAI2H,EAAQjtB,OAAO,CAAE0gB,UAAWA,EAAWyP,aAAcA,IAE7D,GAAIlD,EAAQ1J,mBAAoB,CAC5B,GAAIvjB,GAAW0iB,EAAI4C,EACf,OAAO2H,EAAQ7I,iBAAkBR,EAAY,GAAK,IAAM5jB,EAAS0iB,GAAK,CAClEhC,UAAWA,EACXyP,aAAcA,IAItBgG,EAAmBlJ,CACvB,CAEAvK,GAAK4C,CACT,CAGA,GAAI6Q,EAAkB,CAClB,IAAIlW,EAAK2D,EAAY,EAAI,EACzB,OAAOuS,EAAiBvE,WAAW3R,EACvC,CAGA,OAAO,IACX,EAGA2R,WAAY,SAAS3R,GAEjB,IAAImU,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,OAAO,KAE9B,IAAIW,EAAe7V,EAAE6V,aACrB,GAAIA,EAAe,EAAG,OAAO1B,EAAS,GAAGxC,WAAW,GACpD,GAAIkE,GAAgBX,EAAa,OAAOf,EAASe,EAAc,GAAGvD,WAAW,GAE7E,IAAIgG,EAAS3X,EAAE9lB,MAIf,OAHIy9B,EAAS,EAAGA,EAAS,EAChBA,EAAS,IAAGA,EAAS,GAEvBxD,EAAS0B,GAAclE,WAAWgG,EAC7C,EAEA1D,SAAU,SAASrR,GAEf,IAAIuR,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,OAAO,KAQ9B,IALA,IAAIzU,OAA+Bzf,KADnC4hB,EAAMA,GAAO,CAAC,GACOnC,UAA2BlS,KAAKyhB,UAAYpN,EAAInC,UACjE+U,OAAmDx0B,IAA5B4hB,EAAI4S,oBAAqCjnB,KAAKknB,uBAAuB,CAAEhV,UAAWA,IAAemC,EAAI4S,oBAE5HlX,EAAS,GACTia,EAAgB,GACXljB,EAAI,EAAGA,EAAI6f,EAAa7f,IAAK,CAClC,IAAI2X,EAAUmH,EAAS9e,GACvB,GAAI2X,EAAQsI,UAAW,CACnB,IAAIkD,EAA6BhD,EAAoBngB,GACrD,GAAImjB,EAA2Bz4B,OAAS,EAAG,CACvC,IAAI04B,EAAoBD,EAA2Bt5B,KAAI,SAASw5B,GAC5D,OAAOA,EAAMvqB,KACjB,IACA5O,MAAM1F,UAAUsG,KAAKuP,MAAM6oB,EAAeE,EAC9C,MACIF,EAAcp4B,KAAK6sB,EAAQ7e,MAEnC,MAAWoqB,EAAcx4B,OAAS,IAC9Bw4B,EAAcp4B,KAAKg0B,EAAS9e,EAAI,GAAGjH,KACnCkQ,EAAOne,KAAKo4B,GACZA,EAAgB,GAExB,CAMA,OAJIA,EAAcx4B,OAAS,IACvBw4B,EAAcp4B,KAAKoO,KAAKH,KACxBkQ,EAAOne,KAAKo4B,IAETja,CACX,EAEAyX,YAAa,SAASnT,GAElB,IAAIkT,EAAY,GACZxX,EAAS/P,KAAK0lB,SAASrR,GAC3B,IAAKtE,EAAQ,OAAO,KACpB,IAAK,IAAIjJ,EAAI,EAAGkJ,EAAID,EAAOve,OAAQsV,EAAIkJ,EAAGlJ,IACtCygB,EAAU31B,KAAK,IAAImd,GAASgB,EAAOjJ,KAGvC,OAAOygB,CACX,EAEAx0B,SAAU,WAMN,IAJA,IAAI6yB,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAEvB60B,EAAW,GACNvf,EAAI,EAAGA,EAAI6f,EAAa7f,IAG7Buf,GADcT,EAAS9e,GACH4L,YAAc,IAGtC,OAAO2T,EAASluB,MACpB,EAEA0a,UAAW,SAASgD,EAAIC,GAKpB,IAHA,IAAI8P,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAElBsV,EAAI,EAAGA,EAAI6f,EAAa7f,IAEf8e,EAAS9e,GACf+L,UAAUgD,EAAIC,GAG1B,OAAO9V,IACX,EAGAwpB,0BAA2B,SAAS/K,GAGhC,IADA,IAAImI,EAAkBnI,EAAQmI,gBACvBnI,IAAYA,EAAQsK,gBAGFtK,EAAQ+J,oBAAzB5B,EAA+CA,EAAgB4B,oBAChC,KAEnC5B,EAAkBnI,EAClBA,EAAUA,EAAQuK,WAE1B,EAIAH,SAAU,WAGN,OADK7oB,KAAKmpB,WAAWnpB,KAAKqoB,cAAc,EAAGnZ,GAAK+W,cAAc,IAAK,EAAG,IAC/DjmB,IACX,GAGJhV,OAAOC,eAAeikB,GAAK5jB,UAAW,QAAS,CAG3Cya,cAAc,EAEd7a,YAAY,EAEZC,IAAK,WAED,IAAIy6B,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,OAAO,KAE9B,IAAK,IAAI7f,EAAI,EAAGA,EAAI6f,EAAa7f,IAAK,CAElC,IAAI2X,EAAUmH,EAAS9e,GACvB,GAAI2X,EAAQsI,UAAW,OAAOtI,EAAQ7e,KAC1C,CAGA,OAAOgmB,EAASe,EAAc,GAAG9mB,GACrC,IAGJ7U,OAAOC,eAAeikB,GAAK5jB,UAAW,MAAO,CAGzCya,cAAc,EAEd7a,YAAY,EAEZC,IAAK,WAED,IAAIy6B,EAAW5lB,KAAK4lB,SAChBe,EAAcf,EAASp0B,OAC3B,GAAoB,IAAhBm1B,EAAmB,OAAO,KAE9B,IAAK,IAAI7f,EAAI6f,EAAc,EAAG7f,GAAK,EAAGA,IAAK,CAEvC,IAAI2X,EAAUmH,EAAS9e,GACvB,GAAI2X,EAAQsI,UAAW,OAAOtI,EAAQ5e,GAC1C,CAGA,OAAO+lB,EAASe,EAAc,GAAG9mB,GACrC,IAkCJ,IAAIuqB,GAAmB,CAGnBrX,KAAM,WAEF,MAAM,IAAI/J,MAAM,4CACpB,EAGA5G,MAAO,WAEH,MAAM,IAAI4G,MAAM,4CACpB,EAGAoK,aAAc,WAEV,MAAM,IAAIpK,MAAM,4CACpB,EAGAuK,mBAAoB,WAEhB,MAAM,IAAIvK,MAAM,4CACpB,EAGAsK,6BAA8B,WAE1B,MAAM,IAAItK,MAAM,4CACpB,EAGAwY,cAAe,SAAS3T,GAEpB,GAAI7N,KAAKsT,6BAA8B,OAAOtT,KAAKsT,6BAA6BzF,GAEhF,MAAM,IAAI7E,MAAM,sFACpB,EAGA2K,oBAAqB,WAEjB,MAAM,IAAI3K,MAAM,4CACpB,EAGA6K,SAAU,WAEN,MAAM,IAAI7K,MAAM,4CACpB,EAGAgL,eAAgB,WAEZ,MAAM,IAAIhL,MAAM,4CACpB,EAGAsa,UAAW,SAAS7R,GAEhB,GAAIzR,KAAK6T,SAAU,OAAO7T,KAAK6T,SAASpC,GAExC,MAAM,IAAIzI,MAAM,8DACpB,EAGA6H,OAAQ,WAEJ,MAAM,IAAI7H,MAAM,4CACpB,EAGA4Y,gBAAiB,WAEb,MAAM,IAAI5Y,MAAM,4CACpB,EAGA+L,iBAAkB,WAEd,MAAM,IAAI/L,MAAM,4CACpB,EAEA8c,WAAW,EAEXiD,gBAAgB,EAEhBhC,WAAW,EAGXv1B,OAAQ,WAEJ,MAAM,IAAIwX,MAAM,4CACpB,EAGA6Y,UAAW,SAASpQ,GAEhB,GAAIA,GAAK,EAAG,OAAO,EAEnB,IAAIjgB,EAASwO,KAAKxO,SAElB,OAAIigB,GAAK,EAAUjgB,EAEZA,EAASigB,CACpB,EAEAuX,YAAa,KAGb3V,QAAS,WAEL,MAAM,IAAIrK,MAAM,4CACpB,EAGAiL,cAAe,WAEX,MAAM,IAAIjL,MAAM,4CACpB,EAGAuY,SAAU,SAAS9P,GAEf,GAAIzR,KAAKqT,QAAS,OAAOrT,KAAKqT,QAAQ5B,GAEtC,MAAM,IAAIzI,MAAM,4DACpB,EAEA4d,gBAAiB,KAGjBva,MAAO,WAEH,MAAM,IAAIrD,MAAM,4CACpB,EAEAwf,oBAAqB,KAGrBjc,MAAO,WAEH,MAAM,IAAIvD,MAAM,4CACpB,EAGA0J,UAAW,WAEP,MAAM,IAAI1J,MAAM,4CACpB,EAGA4K,UAAW,WAEP,MAAM,IAAI5K,MAAM,4CACpB,EAGA4M,gBAAiB,WAEb,MAAM,IAAI5M,MAAM,4CACpB,EAGAoa,WAAY,SAAS3R,GAEjB,GAAIzR,KAAK4T,UAAW,OAAO5T,KAAK4T,UAAUnC,GAE1C,MAAM,IAAIzI,MAAM,gEACpB,EAGAjW,SAAU,WAEN,MAAM,IAAIiW,MAAM,4CACpB,EAGA6J,UAAW,WAEP,MAAM,IAAI7J,MAAM,4CACpB,GAKJhe,OAAOC,eAAem/B,GAAkB,MAAO,CAE3CrkB,cAAc,EAEd7a,YAAY,EAEZ8a,UAAU,IAKdhb,OAAOC,eAAem/B,GAAkB,QAAS,CAG7CrkB,cAAc,EAEd7a,YAAY,EAEZC,IAAK,WAED,IAAK6U,KAAK4mB,gBAAiB,MAAM,IAAI5d,MAAM,gIAE3C,OAAOhJ,KAAK4mB,gBAAgB/mB,GAChC,IAIJ7U,OAAOC,eAAem/B,GAAkB,OAAQ,CAE5CrkB,cAAc,EAEd7a,YAAY,EAEZC,IAAK,WAED,MAAM,IAAI6d,MAAM,8CACpB,IAIJ,IAAIqhB,GAAS,WAIT,IAFA,IAcIC,EAoCQC,EAlDRtpB,EAAO,GACP+O,EAAIpR,UAAUpN,OACTsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IACnB7F,EAAKrP,KAAKgN,UAAUkI,IAGxB,KAAM9G,gBAAgBqqB,IAClB,OAAOnE,GAAWmE,GAAQppB,GAG9B,GAAU,IAAN+O,EACA,MAAM,IAAIhH,MAAM,iFAKpB,GAAI/H,EAAK,aAAc2N,GAAM,CACzB,GAAU,IAANoB,EAEA,OADAhQ,KAAKH,IAAMoB,EAAK,GAAGpB,IAAIuC,QAChBpC,KAGP,MAAM,IAAIgJ,MAAM,iEAAmEgH,EAAI,oBAG/F,CAAO,GAAuB,iBAAZ/O,EAAK,IAAsC,iBAAZA,EAAK,GAAiB,CACnE,GAAU,IAAN+O,EAEA,OADAhQ,KAAKH,IAAM,IAAI8O,IAAO1N,EAAK,IAAKA,EAAK,IAC9BjB,KAEJ,GAAIgQ,EAAI,EACX,MAAM,IAAIhH,MAAM,iEAAmEgH,EAAI,2BAGvF,IAAIwa,EAEJ,IADAF,EAAc,GACTxjB,EAAI,EAAGA,EAAIkJ,EAAGlJ,GAAK,EAEpB0jB,EAAgBvpB,EAAKnG,MAAMgM,EAAGA,EAAI,GAClCwjB,EAAY14B,KAAKs0B,GAAWmE,GAAQG,IAExC,OAAOF,CAGf,CACI,GAAU,IAANta,EAEA,OADAhQ,KAAKH,IAAM,IAAI8O,GAAM1N,EAAK,IACnBjB,KAKP,IADAsqB,EAAc,GACTxjB,EAAI,EAAGA,EAAIkJ,EAAGlJ,GAAK,EAEpByjB,EAAetpB,EAAK6F,GACpBwjB,EAAY14B,KAAK,IAAIy4B,GAAOE,IAEhC,OAAOD,CAGnB,EAEIG,GAAkB,CAElBroB,MAAO,WAEH,OAAO,IAAIioB,GAAOrqB,KAAKH,IAC3B,EAEAgU,SAAU,SAASC,GAEf,IACI+O,EADO,IAAIjU,GAAK5O,KAAKJ,MAAOI,KAAKH,KAClBgU,SAASC,GAC5B,MAAO,CACH,IAAIuW,GAAOxH,EAAQ,IACnB,IAAIwH,GAAOxH,EAAQ,IAE3B,EAEA7O,eAAgB,SAASxiB,GAErB,IACIqxB,EADO,IAAIjU,GAAK5O,KAAKJ,MAAOI,KAAKH,KAClBmU,eAAexiB,GAClC,MAAO,CACH,IAAI64B,GAAOxH,EAAQ,IACnB,IAAIwH,GAAOxH,EAAQ,IAE3B,EAEAjB,gBAAiB,WAEb,MAAO,EACX,EAEA7M,iBAAkB,WAEd,QAAK/U,KAAK4mB,kBAEF5mB,KAAKJ,MAAMiR,OAAO7Q,KAAKH,IACnC,EAEAwM,MAAO,SAAS6F,GAGZ,OADAlS,KAAKH,IAAIwM,MAAM6F,GACRlS,IACX,EAEAuM,MAAO,SAAS6F,EAAIC,EAAI5C,GAGpB,OADAzP,KAAKH,IAAI0M,MAAM6F,EAAIC,EAAI5C,GAChBzP,IACX,EAEA0S,UAAW,WAEP,IAAI7S,EAAMG,KAAKH,IACf,OAAOG,KAAK7N,KAAO,IAAM0N,EAAIsO,EAAI,IAAMtO,EAAImO,CAC/C,EAEAjb,SAAU,WAEN,OAAOiN,KAAK7N,KAAO,IAAM6N,KAAKJ,MAAQ,IAAMI,KAAKH,GACrD,EAEAgT,UAAW,SAASgD,EAAIC,GAGpB,OADA9V,KAAKH,IAAIgT,UAAUgD,EAAIC,GAChB9V,IACX,GAGJhV,OAAOC,eAAew/B,GAAiB,OAAQ,CAE3C1kB,cAAc,EAEd7a,YAAY,EAEZS,MAAO,MAGX0+B,GAAO/+B,UAAYu0B,GAAOuK,GAAkBxb,GAAKtjB,UAAWm/B,IAE5D,IAAIC,GAAU,WAIV,IAFA,IAcIJ,EA6CQK,EA3DR1pB,EAAO,GACP+O,EAAIpR,UAAUpN,OACTsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IACnB7F,EAAKrP,KAAKgN,UAAUkI,IAGxB,KAAM9G,gBAAgB0qB,IAClB,OAAOxE,GAAWwE,GAASzpB,GAG/B,GAAU,IAAN+O,EACA,MAAM,IAAIhH,MAAM,oFAKpB,GAAI/H,EAAK,aAAcgO,GAAO,CAC1B,GAAU,IAANe,EAIA,OAHAhQ,KAAK2f,cAAgB1e,EAAK,GAAG0e,cAAcvd,QAC3CpC,KAAK4f,cAAgB3e,EAAK,GAAG2e,cAAcxd,QAC3CpC,KAAKH,IAAMoB,EAAK,GAAGpB,IAAIuC,QAChBpC,KAGP,MAAM,IAAIgJ,MAAM,oEAAsEgH,EAAI,qBAGlG,CAAO,GAAuB,iBAAZ/O,EAAK,IAAsC,iBAAZA,EAAK,GAAiB,CACnE,GAAU,IAAN+O,EAIA,OAHAhQ,KAAK2f,cAAgB,IAAIhR,IAAO1N,EAAK,IAAKA,EAAK,IAC/CjB,KAAK4f,cAAgB,IAAIjR,IAAO1N,EAAK,IAAKA,EAAK,IAC/CjB,KAAKH,IAAM,IAAI8O,IAAO1N,EAAK,IAAKA,EAAK,IAC9BjB,KAEJ,GAAIgQ,EAAI,EACX,MAAM,IAAIhH,MAAM,oEAAsEgH,EAAI,2BAG1F,IAAIwa,EAEJ,IADAF,EAAc,GACTxjB,EAAI,EAAGA,EAAIkJ,EAAGlJ,GAAK,EAEpB0jB,EAAgBvpB,EAAKnG,MAAMgM,EAAGA,EAAI,GAClCwjB,EAAY14B,KAAKs0B,GAAWwE,GAASF,IAEzC,OAAOF,CAGf,CACI,GAAU,IAANta,EAIA,OAHAhQ,KAAK2f,cAAgB,IAAIhR,GAAM1N,EAAK,IACpCjB,KAAK4f,cAAgB,IAAIjR,GAAM1N,EAAK,IACpCjB,KAAKH,IAAM,IAAI8O,GAAM1N,EAAK,IACnBjB,KAEJ,GAAIgQ,EAAI,EACX,MAAM,IAAIhH,MAAM,oEAAsEgH,EAAI,sBAK1F,IADAsa,EAAc,GACTxjB,EAAI,EAAGA,EAAIkJ,EAAGlJ,GAAK,EAEpB6jB,EAAgB1pB,EAAKnG,MAAMgM,EAAGA,EAAI,GAClCwjB,EAAY14B,KAAKs0B,GAAWwE,GAASC,IAEzC,OAAOL,CAGnB,EAEIM,GAAmB,CAEnBxoB,MAAO,WAEH,OAAO,IAAIsoB,GAAQ1qB,KAAK2f,cAAe3f,KAAK4f,cAAe5f,KAAKH,IACpE,EAEAgU,SAAU,SAASC,EAAOO,GAEtB,IACIwO,EADQ,IAAI5T,GAAMjP,KAAKJ,MAAOI,KAAK2f,cAAe3f,KAAK4f,cAAe5f,KAAKH,KAC3DgU,SAASC,EAAOO,GACpC,MAAO,CACH,IAAIqW,GAAQ7H,EAAQ,IACpB,IAAI6H,GAAQ7H,EAAQ,IAE5B,EAEA7O,eAAgB,SAASxiB,EAAQ6iB,GAE7B,IACIwO,EADQ,IAAI5T,GAAMjP,KAAKJ,MAAOI,KAAK2f,cAAe3f,KAAK4f,cAAe5f,KAAKH,KAC3DmU,eAAexiB,EAAQ6iB,GAC3C,MAAO,CACH,IAAIqW,GAAQ7H,EAAQ,IACpB,IAAI6H,GAAQ7H,EAAQ,IAE5B,EAEAS,UAAW,SAAS7R,GAEhB,IACIoR,EADQ,IAAI5T,GAAMjP,KAAKJ,MAAOI,KAAK2f,cAAe3f,KAAK4f,cAAe5f,KAAKH,KAC3DyjB,UAAU7R,GAC9B,MAAO,CACH,IAAIiZ,GAAQ7H,EAAQ,IACpB,IAAI6H,GAAQ7H,EAAQ,IAE5B,EAEA9N,iBAAkB,WAEd,IAAK/U,KAAK4mB,gBAAiB,OAAO,EAElC,IAAIhnB,EAAQI,KAAKJ,MACbykB,EAAWrkB,KAAK2f,cAChB2E,EAAWtkB,KAAK4f,cAChB/f,EAAMG,KAAKH,IAEf,QAASD,EAAMiR,OAAOwT,IAAaA,EAASxT,OAAOyT,IAAaA,EAASzT,OAAOhR,GACpF,EAEAwM,MAAO,SAAS6F,GAKZ,OAHAlS,KAAK2f,cAActT,MAAM6F,GACzBlS,KAAK4f,cAAcvT,MAAM6F,GACzBlS,KAAKH,IAAIwM,MAAM6F,GACRlS,IACX,EAEAuM,MAAO,SAAS6F,EAAIC,EAAI5C,GAKpB,OAHAzP,KAAK2f,cAAcpT,MAAM6F,EAAIC,EAAI5C,GACjCzP,KAAK4f,cAAcrT,MAAM6F,EAAIC,EAAI5C,GACjCzP,KAAKH,IAAI0M,MAAM6F,EAAIC,EAAI5C,GAChBzP,IACX,EAEA0S,UAAW,WAEP,IAAImY,EAAK7qB,KAAK2f,cACVmL,EAAK9qB,KAAK4f,cACV/f,EAAMG,KAAKH,IACf,OAAOG,KAAK7N,KAAO,IAAM04B,EAAG1c,EAAI,IAAM0c,EAAG7c,EAAI,IAAM8c,EAAG3c,EAAI,IAAM2c,EAAG9c,EAAI,IAAMnO,EAAIsO,EAAI,IAAMtO,EAAImO,CACnG,EAEAjb,SAAU,WAEN,OAAOiN,KAAK7N,KAAO,IAAM6N,KAAKJ,MAAQ,IAAMI,KAAK2f,cAAgB,IAAM3f,KAAK4f,cAAgB,IAAM5f,KAAKH,GAC3G,EAEAgT,UAAW,SAASgD,EAAIC,GAKpB,OAHA9V,KAAK2f,cAAc9M,UAAUgD,EAAIC,GACjC9V,KAAK4f,cAAc/M,UAAUgD,EAAIC,GACjC9V,KAAKH,IAAIgT,UAAUgD,EAAIC,GAChB9V,IACX,GAGJhV,OAAOC,eAAe2/B,GAAkB,OAAQ,CAE5C7kB,cAAc,EAEd7a,YAAY,EAEZS,MAAO,MAGX++B,GAAQp/B,UAAYu0B,GAAOuK,GAAkBnb,GAAM3jB,UAAWs/B,IAE9D,IAAIG,GAAS,WAIT,IAFA,IAcIT,EA8CQC,EA5DRtpB,EAAO,GACP+O,EAAIpR,UAAUpN,OACTsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IACnB7F,EAAKrP,KAAKgN,UAAUkI,IAGxB,KAAM9G,gBAAgB+qB,IAClB,OAAO7E,GAAW6E,GAAQ9pB,GAG9B,GAAU,IAAN+O,EACA,MAAM,IAAIhH,MAAM,0FAKpB,GAAI/H,EAAK,aAAc2N,GAAM,CACzB,GAAU,IAANoB,EAEA,OADAhQ,KAAKH,IAAMoB,EAAK,GAAGpB,IAAIuC,QAChBpC,KAGP,MAAM,IAAIgJ,MAAM,0EAA4EgH,EAAI,oBAGxG,CAAO,GAAI/O,EAAK,aAAcgO,GAAO,CACjC,GAAU,IAANe,EAEA,OADAhQ,KAAKH,IAAMoB,EAAK,GAAGpB,IAAIuC,QAChBpC,KAGP,MAAM,IAAIgJ,MAAM,0EAA4EgH,EAAI,qBAGxG,CAAO,GAAuB,iBAAZ/O,EAAK,IAAsC,iBAAZA,EAAK,GAAiB,CACnE,GAAU,IAAN+O,EAEA,OADAhQ,KAAKH,IAAM,IAAI8O,IAAO1N,EAAK,IAAKA,EAAK,IAC9BjB,KAEJ,GAAIgQ,EAAI,EACX,MAAM,IAAIhH,MAAM,0EAA4EgH,EAAI,2BAGhG,IAAIwa,EAEJ,IADAF,EAAc,GACTxjB,EAAI,EAAGA,EAAIkJ,EAAGlJ,GAAK,EAEpB0jB,EAAgBvpB,EAAKnG,MAAMgM,EAAGA,EAAI,GACxB,IAANA,EAASwjB,EAAY14B,KAAKs0B,GAAW6E,GAAQP,IAC5CF,EAAY14B,KAAKs0B,GAAWmE,GAAQG,IAE7C,OAAOF,CAGf,CACI,GAAU,IAANta,EAEA,OADAhQ,KAAKH,IAAM,IAAI8O,GAAM1N,EAAK,IACnBjB,KAKP,IADAsqB,EAAc,GACTxjB,EAAI,EAAGA,EAAIkJ,EAAGlJ,GAAK,EAEpByjB,EAAetpB,EAAK6F,GACV,IAANA,EAASwjB,EAAY14B,KAAK,IAAIm5B,GAAOR,IACpCD,EAAY14B,KAAK,IAAIy4B,GAAOE,IAErC,OAAOD,CAGnB,EAEIU,GAAkB,CAElBjY,KAAM,WAEF,OAAO,IACX,EAEA3Q,MAAO,WAEH,OAAO,IAAI2oB,GAAO/qB,KAAKH,IAC3B,EAEAuT,aAAc,WAEV,OAAOpT,KAAKH,IAAIuC,OACpB,EAEAkR,6BAA8B,WAE1B,OAAO,CACX,EAEAC,mBAAoB,WAEhB,OAAO,CACX,EAEAiO,cAAe,WAEX,OAAO,CACX,EAEA7N,oBAAqB,WAEjB,OAAO,IACX,EAEAE,SAAU,WAEN,MAAO,CACH7T,KAAKoC,QACLpC,KAAKoC,QAEb,EAEA4R,eAAgB,WAEZ,MAAO,CACHhU,KAAKoC,QACLpC,KAAKoC,QAEb,EAEAyO,OAAQ,SAASuG,GAEb,OAAOpX,KAAKH,IAAIgR,OAAOuG,EAAEvX,IAC7B,EAEA+hB,gBAAiB,WAEb,MAAO,EACX,EAEA7M,iBAAkB,WAEd,OAAO,CACX,EAEAgU,gBAAgB,EAEhBhC,WAAW,EAEXv1B,OAAQ,WAEJ,OAAO,CACX,EAEAqwB,UAAW,WAEP,OAAO,CACX,EAEAxO,QAAS,WAEL,OAAOrT,KAAKH,IAAIuC,OACpB,EAEA6R,cAAe,WAEX,OAAOjU,KAAKH,IAAIuC,OACpB,EAEAmf,SAAU,WAEN,OAAOvhB,KAAKH,IAAIuC,OACpB,EAEAiK,MAAO,SAAS6F,GAGZ,OADAlS,KAAKH,IAAIwM,MAAM6F,GACRlS,IACX,EAEAuM,MAAO,SAAS6F,EAAIC,EAAI5C,GAGpB,OADAzP,KAAKH,IAAI0M,MAAM6F,EAAIC,EAAI5C,GAChBzP,IACX,EAEA0S,UAAW,WAEP,IAAI7S,EAAMG,KAAKH,IACf,OAAOG,KAAK7N,KAAO,IAAM0N,EAAIsO,EAAI,IAAMtO,EAAImO,CAC/C,EAEA4F,UAAW,WAEP,OAAO,IACX,EAEAgC,gBAAiB,WAEb,OAAO,IACX,EAEAwN,WAAY,WAER,OAAO,IACX,EAEArwB,SAAU,WAEN,OAAOiN,KAAK7N,KAAO,IAAM6N,KAAKH,GAClC,EAEAgT,UAAW,SAASgD,EAAIC,GAGpB,OADA9V,KAAKH,IAAIgT,UAAUgD,EAAIC,GAChB9V,IACX,GAGJhV,OAAOC,eAAe+/B,GAAiB,QAAS,CAE5CjlB,cAAc,EAEd7a,YAAY,EAEZC,IAAK,WAED,MAAM,IAAI6d,MAAM,oEACpB,IAGJhe,OAAOC,eAAe+/B,GAAiB,OAAQ,CAE3CjlB,cAAc,EAEd7a,YAAY,EAEZS,MAAO,MAGXo/B,GAAOz/B,UAAYu0B,GAAOuK,GAAkBY,IAE5C,IAAIC,GAAY,WAIZ,IAFA,IAAIhqB,EAAO,GACP+O,EAAIpR,UAAUpN,OACTsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IACnB7F,EAAKrP,KAAKgN,UAAUkI,IAGxB,KAAM9G,gBAAgBirB,IAClB,OAAO/E,GAAW+E,GAAWhqB,GAGjC,GAAI+O,EAAI,EACJ,MAAM,IAAIhH,MAAM,+CAGpB,OAAOhJ,IACX,EAEIkrB,GAAqB,CAErB9oB,MAAO,WAEH,OAAO,IAAI6oB,EACf,EAEApX,SAAU,SAASC,GAEf,IACI+O,EADO,IAAIjU,GAAK5O,KAAKJ,MAAOI,KAAKH,KAClBgU,SAASC,GAC5B,MAAO,CAEF+O,EAAQ,GAAG9N,mBAAqB,IAAIsV,GAAOxH,EAAQ,IAAM7iB,KAAKoC,QAC/D,IAAIioB,GAAOxH,EAAQ,IAE3B,EAEA7O,eAAgB,SAASxiB,GAErB,IACIqxB,EADO,IAAIjU,GAAK5O,KAAKJ,MAAOI,KAAKH,KAClBmU,eAAexiB,GAClC,MAAO,CAEFqxB,EAAQ,GAAG9N,mBAAqB,IAAIsV,GAAOxH,EAAQ,IAAM7iB,KAAKoC,QAC/D,IAAIioB,GAAOxH,EAAQ,IAE3B,EAEAjB,gBAAiB,WAEb,MAAO,EACX,EAEA7M,iBAAkB,WAEd,SAAK/U,KAAK4mB,kBAAoB5mB,KAAKwoB,qBAE3BxoB,KAAKJ,MAAMiR,OAAO7Q,KAAKH,KACnC,EAEAwM,MAAO,WAEH,OAAOrM,IACX,EAEAuM,MAAO,WAEH,OAAOvM,IACX,EAEA0S,UAAW,WAEP,OAAO1S,KAAK7N,IAChB,EAEAY,SAAU,WAEN,OAAOiN,KAAK7N,KAAO,IAAM6N,KAAKJ,MAAQ,IAAMI,KAAKH,GACrD,EAEAgT,UAAW,WAEP,OAAO7S,IACX,GAGJhV,OAAOC,eAAeigC,GAAoB,MAAO,CAG7CnlB,cAAc,EAEd7a,YAAY,EAEZC,IAAK,WAED,IAAK6U,KAAKwoB,oBAAqB,MAAM,IAAIxf,MAAM,2IAE/C,OAAOhJ,KAAKwoB,oBAAoB3oB,GACpC,IAGJ7U,OAAOC,eAAeigC,GAAoB,OAAQ,CAE9CnlB,cAAc,EAEd7a,YAAY,EAEZS,MAAO,MAGXs/B,GAAU3/B,UAAYu0B,GAAOuK,GAAkBxb,GAAKtjB,UAAW4/B,IAE/D,IAAIzE,GAAevX,GAAKuX,aAAe,CACnC0E,EAAGd,GACHe,EAAGV,GACHW,EAAGN,GACHO,EAAGL,GACHM,EAAGN,IAGP/b,GAAKsc,mBAAqB,IAAIv8B,OAAO,WAAajE,OAAO0F,KAAK+1B,IAAc33B,KAAK,IAAM,SAEvFogB,GAAKuc,gBAAkB,SAASl3B,GAE5B,MAAoB,iBAATA,GACJyL,KAAKwrB,mBAAmB17B,KAAKyE,EACxC,EC/sEO,MAAMm3B,GAAS,CAMlBC,mBAAoB,SAAS5b,GAIzB,OAFA6b,QAAQC,KAAK,cAEN,IAAI3c,GAAKD,GAAMgR,cAAclQ,IAAS2C,WACjD,EAOA+N,sBAAuB,SAASH,GAE5BsL,QAAQC,KAAK,cAEb,IAGI/kB,EAHAyZ,EAAqB,GACrBC,EAAsB,GACtBxQ,EAAIsQ,EAAM9uB,OAAS,EAIvB,GAAS,GAALwe,EAaA,OAXAuQ,EAAmB,GAAK,IAAI5R,IACvB,EAAI2R,EAAM,GAAGnS,EAAImS,EAAM,GAAGnS,GAAK,GAC/B,EAAImS,EAAM,GAAGtS,EAAIsS,EAAM,GAAGtS,GAAK,GAIpCwS,EAAoB,GAAK,IAAI7R,GACzB,EAAI4R,EAAmB,GAAGpS,EAAImS,EAAM,GAAGnS,EACvC,EAAIoS,EAAmB,GAAGvS,EAAIsS,EAAM,GAAGtS,GAGpC,CAACuS,EAAoBC,GAKhC,IAAIL,EAAM,GAGV,IAAKrZ,EAAI,EAAGA,EAAIkJ,EAAI,EAAGlJ,IACnBqZ,EAAIrZ,GAAK,EAAIwZ,EAAMxZ,GAAGqH,EAAI,EAAImS,EAAMxZ,EAAI,GAAGqH,EAG/CgS,EAAI,GAAKG,EAAM,GAAGnS,EAAI,EAAImS,EAAM,GAAGnS,EACnCgS,EAAInQ,EAAI,IAAM,EAAIsQ,EAAMtQ,EAAI,GAAG7B,EAAImS,EAAMtQ,GAAG7B,GAAK,EAGjD,IAAIA,EAAInO,KAAKkgB,sBAAsBC,GAGnC,IAAKrZ,EAAI,EAAGA,EAAIkJ,EAAI,IAAKlJ,EACrBqZ,EAAIrZ,GAAK,EAAIwZ,EAAMxZ,GAAGkH,EAAI,EAAIsS,EAAMxZ,EAAI,GAAGkH,EAG/CmS,EAAI,GAAKG,EAAM,GAAGtS,EAAI,EAAIsS,EAAM,GAAGtS,EACnCmS,EAAInQ,EAAI,IAAM,EAAIsQ,EAAMtQ,EAAI,GAAGhC,EAAIsS,EAAMtQ,GAAGhC,GAAK,EAGjD,IAAIA,EAAIhO,KAAKkgB,sBAAsBC,GAGnC,IAAKrZ,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAEfyZ,EAAmB3uB,KAAK,IAAI+c,GAAMR,EAAErH,GAAIkH,EAAElH,KAGtCA,EAAIkJ,EAAI,EACRwQ,EAAoB5uB,KAAK,IAAI+c,GACzB,EAAI2R,EAAOxZ,EAAI,GAAGqH,EAAIA,EAAErH,EAAI,GAC5B,EAAIwZ,EAAMxZ,EAAI,GAAGkH,EAAIA,EAAElH,EAAI,KAI/B0Z,EAAoB5uB,KAAK,IAAI+c,IACxB2R,EAAMtQ,GAAG7B,EAAIA,EAAE6B,EAAI,IAAM,GACzBsQ,EAAMtQ,GAAGhC,EAAIA,EAAEgC,EAAI,IAAM,IAKtC,MAAO,CAACuQ,EAAoBC,EAChC,EAOAsL,gBAAiB,SAASC,EAAIpb,EAAIC,EAAIsK,GAElC0Q,QAAQC,KAAK,cAEb,IAAI1B,EAAQ,IAAIlb,GAAM8c,EAAIpb,EAAIC,EAAIsK,GAElC,OAAO,SAAqBzJ,GAExB,IAAIoR,EAAUsH,EAAMrH,OAAOrR,GAE3B,MAAO,CAAC,CACJsa,GAAIlJ,EAAQ,GAAGjjB,MACf+Q,GAAIkS,EAAQ,GAAGlD,cACf/O,GAAIiS,EAAQ,GAAGjD,cACf1E,GAAI2H,EAAQ,GAAGhjB,KAChB,CACCksB,GAAIlJ,EAAQ,GAAGjjB,MACf+Q,GAAIkS,EAAQ,GAAGlD,cACf/O,GAAIiS,EAAQ,GAAGjD,cACf1E,GAAI2H,EAAQ,GAAGhjB,KAEvB,CACJ,EAMAqgB,sBAAuB,SAASC,GAE5ByL,QAAQC,KAAK,cAEb,IAAI7b,EAAImQ,EAAI3uB,OAER2c,EAAI,GACJiS,EAAM,GACNxkB,EAAI,EAERuS,EAAE,GAAKgS,EAAI,GAAKvkB,EAGhB,IAAK,IAAIkL,EAAI,EAAGA,EAAIkJ,EAAGlJ,IACnBsZ,EAAItZ,GAAK,EAAIlL,EACbA,GAAKkL,EAAIkJ,EAAI,EAAI,EAAM,KAAOoQ,EAAItZ,GAClCqH,EAAErH,IAAMqZ,EAAIrZ,GAAKqH,EAAErH,EAAI,IAAMlL,EAGjC,IAAKkL,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAEfqH,EAAE6B,EAAIlJ,EAAI,IAAMsZ,EAAIpQ,EAAIlJ,GAAKqH,EAAE6B,EAAIlJ,GAGvC,OAAOqH,CACX,EAQA6d,mBAAoB,SAASD,EAAIpb,EAAIC,EAAIsK,GAErC0Q,QAAQC,KAAK,cAEb,IAAI1B,EAAQ,IAAIlb,GAAM8c,EAAIpb,EAAIC,EAAIsK,GAElC,OAAO,SAAwBrN,GAE3B,OAAOsc,EAAM3I,cAAc3T,EAC/B,CACJ,GCvKSmB,GAAU,SAASe,GAE5B,OAAM/P,gBAAgBgP,GAIA,iBAAXe,EACA,IAAIf,GAAQmP,MAAMpO,QAG7B/P,KAAK+P,OAAU/e,MAAMC,QAAQ8e,GAAUA,EAAOpf,IAAIge,IAAS,IAPhD,IAAIK,GAAQe,EAQ3B,ECZO,SAASkc,GAAOC,EAAQC,EAAQC,EAAWC,GAC9C,OAAQH,EAAO/5B,MACX,KAAKsX,GAAMmF,KACP,GAAQud,EAAOh6B,OACNsX,GAAMmF,KACP,OAAO0d,GAAaJ,EAAQC,GAGpC,MAEJ,KAAK1iB,GAAMoF,QACP,OAAQsd,EAAOh6B,MACX,KAAKsX,GAAMmF,KACP,OAAO2d,GAAgBL,EAAQC,GAEnC,KAAK1iB,GAAMoF,QACP,OAAO2d,GAAmBN,EAAQC,GAG1C,MAEJ,KAAK1iB,GAAMqF,KACP,OAAQqd,EAAOh6B,MACX,KAAKsX,GAAMmF,KACP,OAAO6d,GAAaP,EAAQC,GAEhC,KAAK1iB,GAAMoF,QACP,OAAO6d,GAAgBR,EAAQC,GAEnC,KAAK1iB,GAAMqF,KACP,OAAO6d,GAAaT,EAAQC,GAGpC,MAEJ,KAAK1iB,GAAMsF,SACP,OAAQod,EAAOh6B,MACX,KAAKsX,GAAMmF,KACP,OAAOge,GAAiBV,EAAQC,GAEpC,KAAK1iB,GAAMoF,QACP,OAAOge,GAAoBX,EAAQC,GAEvC,KAAK1iB,GAAMqF,KACP,OAAOge,GAAiBZ,EAAQC,GAEpC,KAAK1iB,GAAMsF,SACP,OAAOge,GAAqBb,EAAQC,GAG5C,MAEJ,KAAK1iB,GAAMuF,QACP,OAAQmd,EAAOh6B,MACX,KAAKsX,GAAMmF,KACP,OAAOoe,GAAgBd,EAAQC,GAEnC,KAAK1iB,GAAMoF,QACP,OAAOoe,GAAmBf,EAAQC,GAEtC,KAAK1iB,GAAMqF,KACP,OAAOoe,GAAgBhB,EAAQC,GAEnC,KAAK1iB,GAAMsF,SACP,OAAOoe,GAAoBjB,EAAQC,GAEvC,KAAK1iB,GAAMuF,QACP,OAAOoe,GAAmBlB,EAAQC,GAG1C,MAEJ,KAAK1iB,GAAMyF,KACP,OAAQid,EAAOh6B,MACX,KAAKsX,GAAMmF,KACP,OAAOye,GAAanB,EAAQC,EAAQC,GAExC,KAAK3iB,GAAMoF,QACP,OAAOye,GAAgBpB,EAAQC,EAAQC,GAE3C,KAAK3iB,GAAMqF,KACP,OAAOye,GAAarB,EAAQC,EAAQC,GAExC,KAAK3iB,GAAMsF,SACP,OAAOye,GAAiBtB,EAAQC,EAAQC,GAE5C,KAAK3iB,GAAMuF,QACP,OAAOye,GAAgBvB,EAAQC,EAAQC,GAE3C,KAAK3iB,GAAMyF,KACP,OAAOwe,GAAaxB,EAAQC,EAAQC,EAAWC,IAO/D,OAAQF,EAAOh6B,MACX,KAAKsX,GAAMoF,QACX,KAAKpF,GAAMqF,KACX,KAAKrF,GAAMsF,SACX,KAAKtF,GAAMuF,QACX,KAAKvF,GAAMyF,KACP,OAAO+c,GAAOE,EAAQD,EAAQG,EAAWD,GAE7C,QACI,MAAMpjB,MAAM,wBAAwBkjB,SAAcC,yBAG9D,CAIO,SAASG,GAAaqB,EAAOC,GAChC,MAAMle,EAAKie,EAAM/tB,MAAMuO,EACjByB,EAAK+d,EAAM/tB,MAAMoO,EACjB2B,EAAKge,EAAM9tB,IAAIsO,EACf0B,EAAK8d,EAAM9tB,IAAImO,EACf+S,EAAK6M,EAAMhuB,MAAMuO,EACjB6S,EAAK4M,EAAMhuB,MAAMoO,EAGjB6f,EAAMle,EAAKD,EACXoe,EAAMje,EAAKD,EACXme,EAJKH,EAAM/tB,IAAIsO,EAIJ4S,EACXiN,EAJKJ,EAAM/tB,IAAImO,EAIJgT,EACXiN,EAAMve,EAAKqR,EACXmN,EAAMte,EAAKoR,EACXnT,EAAIggB,EAAMG,EAAMD,EAAMD,EACtBK,GAAKN,EAAMK,EAAMJ,EAAMG,GAAOpgB,EAC9B4D,GAAKsc,EAAMG,EAAMF,EAAMC,GAAOpgB,EACpC,OAAOsgB,GAAK,GAAKA,GAAK,GAAK1c,GAAK,GAAKA,GAAK,CAC9C,CAIO,SAAS8a,GAAgBnW,EAAS5B,GACrC,MAAM4Z,EAAMhY,EAAQza,EACd0yB,EAAMjY,EAAQxa,EACd0yB,EAAKlY,EAAQjI,EACbogB,EAAKnY,EAAQpI,EACb0B,EAAK8E,EAAK5U,MAAMuO,EAAImgB,EACpB3e,EAAK6E,EAAK3U,IAAIsO,EAAImgB,EAClB1e,EAAK4E,EAAK5U,MAAMoO,EAAIugB,EAEpBC,EAAQJ,EAAMA,EACdK,EAAQJ,EAAMA,EACdnd,EAAKvB,EAAKD,EACVyB,EAJKqD,EAAK3U,IAAImO,EAAIugB,EAIR3e,EACV8e,EAAIxd,EAAKA,EAAKsd,EAAQrd,EAAKA,EAAKsd,EAChCE,EAAI,EAAIjf,EAAKwB,EAAKsd,EAAQ,EAAI5e,EAAKuB,EAAKsd,EAExCG,EAAID,EAAIA,EAAI,EAAID,GADZhf,EAAKA,EAAK8e,EAAQ5e,EAAKA,EAAK6e,EAAQ,GAE9C,GAAU,IAANG,EAAS,CACT,MAAMnd,GAAKkd,EAAI,EAAID,EACnB,OAAOjd,GAAK,GAAKA,GAAK,CAC1B,CAAO,GAAImd,EAAI,EAAG,CACd,MAAMlgB,EAAO3M,KAAK2M,KAAKkgB,GACjBjO,IAAOgO,EAAIjgB,GAAQ,EAAIggB,EACvB9N,IAAO+N,EAAIjgB,GAAQ,EAAIggB,EAC7B,OAAQ/N,GAAM,GAAKA,GAAM,GAAOC,GAAM,GAAKA,GAAM,CACrD,CACA,OAAO,CACX,CAEO,SAAS4L,GAAmBqC,EAAUC,GACzC,OAuOJ,SAA+BC,EAAI3V,EAAI4V,GACnC,MAAM,IAAEvhB,EAAG,IAAEC,GAAQ3L,KACfktB,EAAQvhB,EAzOyB,GA0OjCwhB,EAAQzhB,EA1OyB,GA2OjC0hB,EAAQzhB,EA3OsC,GA4O9C0hB,EAAQ3hB,EA5OsC,GA6O9C4hB,EAASJ,EAAQA,EACjBK,EAASJ,EAAQA,EACjBK,EAAUN,EAAQC,EAClBM,EAASL,EAAQA,EACjBM,EAASL,EAAQA,EACjBM,EAAUP,EAAQC,EAClBO,EAAMZ,EAAGpzB,EAAIozB,EAAGpzB,EAChBi0B,EAAMb,EAAGnzB,EAAImzB,EAAGnzB,EAChBi0B,EAAMb,EAAGrzB,EAAIqzB,EAAGrzB,EAChBm0B,EAAMd,EAAGpzB,EAAIozB,EAAGpzB,EAChBm0B,EAAKJ,EAAMN,EAASO,EAAMN,EAC1BU,EAAKH,EAAML,EAASM,EAAML,EAC1BQ,EAAKN,EAAML,EAASM,EAAMP,EAC1Ba,EAAKL,EAAMJ,EAASK,EAAMN,EAChC,IAAIW,EAAK,GAAKP,EAAMD,GAAOJ,EACvBa,EAAK,GAAKN,EAAMD,GAAOH,EACvBW,GAAO,EAAIN,EAAKhB,EAAG5gB,EAAIgiB,EAAKpB,EAAG/gB,EAC/BsiB,GAAO,EAAIN,EAAKhB,EAAG7gB,EAAIiiB,EAAKpB,EAAGhhB,EAC/BuiB,GAAOJ,EAAKpB,EAAG5gB,EAAI,EAAI8hB,EAAKlB,EAAG/gB,EAC/BwiB,GAAOJ,EAAKpB,EAAG7gB,EAAI,EAAI+hB,EAAKlB,EAAGhhB,EACnC,MAAMyiB,EAAKV,EAAKhB,EAAG5gB,EAAI4gB,EAAG5gB,EAAI8hB,EAAKlB,EAAG/gB,EAAI+gB,EAAG/gB,EAAImiB,EAAKpB,EAAG5gB,EAAI4gB,EAAG/gB,EAAI2hB,EAAMC,EACpEc,EAAKV,EAAKhB,EAAG7gB,EAAI6gB,EAAG7gB,EAAI+hB,EAAKlB,EAAGhhB,EAAIghB,EAAGhhB,EAAIoiB,EAAKpB,EAAG7gB,EAAI6gB,EAAGhhB,EAAI6hB,EAAMC,EAE1EK,GAAU,EACVC,GAAU,EACVC,GAAU,EACVC,GAAU,EACVC,GAAU,EACVC,GAAU,EAEV,MAAMG,EAAKC,GAAK,CACZ,CAACb,EAAII,EAAIE,GACT,CAACF,EAAIF,EAAIM,GACT,CAACF,EAAIE,EAAIE,KAEPI,EAAKD,GAAK,CACZ,CAACZ,EAAII,EAAIE,GACT,CAACF,EAAIF,EAAIM,GACT,CAACF,EAAIE,EAAIE,KAEP1R,EAAK,WAAc4R,GAAK,CAC1B,CAACZ,EAAIG,EAAIE,GACT,CAACD,EAAIH,EAAIM,GACT,CAACD,EAAIC,EAAIE,KACRG,GAAK,CACN,CAACb,EAAIK,EAAIC,GACT,CAACF,EAAID,EAAIK,GACT,CAACF,EAAIG,EAAIC,KACRG,GAAK,CACN,CAACb,EAAII,EAAIG,GACT,CAACH,EAAIF,EAAIO,GACT,CAACH,EAAIE,EAAIG,MAEPI,EAAK,WAAcF,GAAK,CAC1B,CAACb,EAAIK,EAAIE,GACT,CAACH,EAAID,EAAIM,GACT,CAACH,EAAIG,EAAIE,KACRE,GAAK,CACN,CAACZ,EAAIG,EAAIG,GACT,CAACF,EAAIH,EAAIO,GACT,CAACF,EAAIC,EAAIG,KACRE,GAAK,CACN,CAACZ,EAAII,EAAIC,GACT,CAACD,EAAIF,EAAIK,GACT,CAACD,EAAIE,EAAIC,MAGPM,EAASC,GAAK,CAChB,CAACL,EAAI3R,GACL,CAACA,EAAI8R,KAEHG,EAASD,GAAK,CAChB,CAACL,EAAIG,GACL,CAAC9R,EAAI6R,KAEHK,EAASF,GAAK,CAChB,CAAChS,EAAI8R,GACL,CAACA,EAAID,KAQT,QALWG,GAAK,CACZ,CAAC,EAAID,EAAQE,GACb,CAACA,EAAQ,EAAIC,KAGR,IAAMJ,EAAK,GAAK9R,EAAK,GAIlC,CAtUWmS,CAAsBtC,EAAU,EAAGC,EAC9C,CAIO,SAASrC,GAAaxW,EAAMzB,GAC/B,MAAM,MAAE5U,EAAK,IAAEC,GAAQ2U,GACjB,EAAErG,EAAC,EAAEH,EAAC,MAAEwC,EAAK,OAAEC,GAAWwF,EAChC,QACKrW,EAAMuO,EAAIA,EAAIqC,GAAS3Q,EAAIsO,EAAIA,EAAIqC,GAChC5Q,EAAMuO,EAAIA,GAAKtO,EAAIsO,EAAIA,GACvBvO,EAAMoO,EAAIA,EAAIyC,GAAU5Q,EAAImO,EAAIA,EAAIyC,GACpC7Q,EAAMoO,EAAIA,GAAKnO,EAAImO,EAAIA,QAI3BiI,EAAK1F,cAAciE,EAAK5U,SAAUqW,EAAK1F,cAAciE,EAAK3U,OAGvDysB,GAAarW,EAAK8D,UAAWvF,IAC7B8X,GAAarW,EAAK+D,YAAaxF,IAC/B8X,GAAarW,EAAK0C,aAAcnE,IAChC8X,GAAarW,EAAKgE,WAAYzF,GACzC,CAEO,SAASkY,GAAgBzW,EAAMG,GAClC,QAAKuW,GAAa1W,EAAMnH,GAAK+I,YAAYzB,KAClC6W,GAAmBje,GAAQgH,SAASC,GAAOG,EACtD,CAEO,SAASuW,GAAayE,EAAOC,GAChC,OAAOD,EAAMjjB,EAAIkjB,EAAMljB,EAAIkjB,EAAM7gB,OAC1B4gB,EAAMjjB,EAAIijB,EAAM5gB,MAAQ6gB,EAAMljB,GAC9BijB,EAAMpjB,EAAIqjB,EAAMrjB,EAAIqjB,EAAM5gB,QAC1B2gB,EAAMpjB,EAAIojB,EAAM3gB,OAAS4gB,EAAMrjB,CAC1C,CAIO,SAAS4e,GAAiB3D,EAAUzU,GACvC,OAAO8c,GAAkBrI,EAAUzU,EAAM,CAAE+c,UAAU,GACzD,CAEO,SAAS1E,GAAoB5D,EAAU7S,GAC1C,OAAOob,GAAqBvI,EAAU7S,EAAS,CAAEmb,UAAU,GAC/D,CAEO,SAASzE,GAAiB7D,EAAUhT,GACvC,OAAOwb,GAAkBxI,EAAUhT,EAAM,CAAEsb,UAAU,GACzD,CAEO,SAASxE,GAAqB2E,EAAWC,GAC5C,OAAOC,GAAsBF,EAAWC,EAAW,CAAEJ,UAAU,GACnE,CAIO,SAASvE,GAAgB6E,EAASrd,GACrC,OAAO8c,GAAkBO,EAASrd,EAAM,CAAE+c,UAAU,GACxD,CAEO,SAAStE,GAAmB4E,EAASzb,GACxC,OAAOob,GAAqBK,EAASzb,EAAS,CAAEmb,UAAU,GAC9D,CAEO,SAASrE,GAAgB2E,EAAS5b,GACrC,OAAOwb,GAAkBI,EAAS5b,EAAM,CAAEsb,UAAU,GACxD,CAEO,SAASpE,GAAoB0E,EAAS5I,GACzC,OAAO2I,GAAsBC,EAAS5I,EAAU,CAAEsI,UAAU,GAChE,CAEO,SAASnE,GAAmB0E,EAAUC,GACzC,OAAOC,GAAqBF,EAAUC,EAAU,CAAER,UAAU,GAChE,CAIO,SAASlE,GAAav1B,EAAM0c,EAAMyd,GACrC,OAAOn6B,EAAK8wB,cAAcjyB,MAAKu7B,IAC3B,MAAOjJ,GAAYiJ,EAAQ1K,YAAYyK,IACjC,KAAE9/B,GAAS+/B,EAAQrK,YAAY,GACrC,MAAa,MAAT11B,EACO66B,GAAgB/D,EAAUzU,GAE1BoY,GAAiB3D,EAAUzU,EACtC,GAER,CAEO,SAAS8Y,GAAgBx1B,EAAMse,EAAS6b,GAC3C,OAAOn6B,EAAK8wB,cAAcjyB,MAAKu7B,IAC3B,MAAOjJ,GAAYiJ,EAAQ1K,YAAYyK,IACjC,KAAE9/B,GAAS+/B,EAAQrK,YAAY,GACrC,MAAa,MAAT11B,EACO86B,GAAmBhE,EAAU7S,GAE7ByW,GAAoB5D,EAAU7S,EACzC,GAER,CAEO,SAASmX,GAAaz1B,EAAMme,EAAMgc,GACrC,OAAOxE,GAAgB31B,EAAMkX,GAAQgH,SAASC,GAAOgc,EACzD,CAEO,SAASzE,GAAiB11B,EAAMmxB,EAAUgJ,GAC7C,OAAOE,GAAkBr6B,EAAMmxB,EAAUgJ,EAAS,CAAEV,UAAU,GAClE,CAEO,SAAS9D,GAAgB31B,EAAM+5B,EAASI,GAC3C,OAAOE,GAAkBr6B,EAAM+5B,EAASI,EAAS,CAAEV,UAAU,GACjE,CAEO,SAAS7D,GAAa0E,EAAOC,EAAOC,EAAUC,GACjD,OAAOH,EAAMxJ,cAAcjyB,MAAKu7B,IAC5B,MAAOR,GAAaQ,EAAQ1K,YAAY8K,IAClC,KAAEngC,GAAS+/B,EAAQrK,YAAY,GACrC,MAAa,MAAT11B,EACOs7B,GAAgB4E,EAAOX,EAAWa,GAElC/E,GAAiB6E,EAAOX,EAAWa,EAC9C,GAER,CAEA,SAASjB,GAAkBrI,EAAUzU,EAAMH,EAAM,CAAC,GAC9C,MAAM,SAAEkd,GAAW,GAAUld,EAC7B,IAAIme,EACJ,GAAIjB,EAAU,CACV,GAAItI,EAAS1Y,cAAciE,EAAK5U,OAG5B,OAAO,EAEX,MAAM,MAAEA,EAAK,IAAEC,EAAG,OAAEkQ,GAAWkZ,EAC/BuJ,EAAa3yB,EAAIgR,OAAOjR,GAASmQ,EAAS,IAAIA,EAAQnQ,EAC1D,MACI4yB,EAAavJ,EAASlZ,OAE1B,MAAM,OAAEve,GAAWghC,EACb/T,EAAU,IAAI7P,GACpB,IAAK,IAAI9H,EAAI,EAAGA,EAAItV,EAAS,EAAGsV,IAG5B,GAFA2X,EAAQ7e,MAAQ4yB,EAAW1rB,GAC3B2X,EAAQ5e,IAAM2yB,EAAW1rB,EAAI,GACzBwlB,GAAa9X,EAAMiK,GACnB,OAAO,EAGf,OAAO,CACX,CAEA,SAAS+S,GAAqBvI,EAAU7S,EAAS/B,EAAM,CAAC,GACpD,MAAM,MAAEzU,EAAK,IAAEC,EAAG,OAAEkQ,GAAWkZ,EAC/B,GAAI7S,EAAQ7F,cAAc3Q,GACtB,OAAO,EAEX,IAAI4yB,EACJ,MAAM,SAAEjB,GAAW,GAAUld,EAC7B,GAAIkd,EAAU,CACV,GAAItI,EAAS1Y,cAAc6F,EAAQF,UAG/B,OAAO,EAEXsc,EAAa3yB,EAAIgR,OAAOjR,GAASmQ,EAAS,IAAIA,EAAQnQ,EAC1D,MACI4yB,EAAaziB,EAGjB,MAAM,OAAEve,GAAWghC,EACb/T,EAAU,IAAI7P,GACpB,IAAK,IAAI9H,EAAI,EAAGA,EAAItV,EAAS,EAAGsV,IAG5B,GAFA2X,EAAQ7e,MAAQ4yB,EAAW1rB,GAC3B2X,EAAQ5e,IAAM2yB,EAAW1rB,EAAI,GACzBylB,GAAgBnW,EAASqI,GACzB,OAAO,EAGf,OAAO,CACX,CAEA,SAASgT,GAAkBxI,EAAUhT,EAAM5B,GAEvC,OAAO2d,GAAqB/I,EADZja,GAAQgH,SAASC,GACc5B,EACnD,CAEA,SAAS8d,GAAkBr6B,EAAM45B,EAAWO,EAAS5d,GACjD,OAAOvc,EAAK8wB,cAAcjyB,MAAKu7B,IAC3B,MAAOP,GAAaO,EAAQ1K,YAAYyK,IAClC,KAAE9/B,GAAS+/B,EAAQrK,YAAY,GACrC,MAAa,MAAT11B,EACO6/B,GAAqBN,EAAWC,EAAWtd,GAE3Cud,GAAsBF,EAAWC,EAAWtd,EACvD,GAER,CAEA,SAASud,GAAsBF,EAAWC,EAAWtd,EAAM,CAAC,GACxD,MAAM,SAAEkd,GAAW,GAAUld,EAC7B,IAAIoe,EACJ,GAAIlB,EAAU,CACV,MAAM,MAAE3xB,GAAU+xB,EAClB,GAAID,EAAUnhB,cAAc3Q,GAGxB,OAAO,EAEX6yB,EAAef,EAAUtvB,QAAQyc,OACrC,MACI4T,EAAef,EAEnB,MAAM5S,EAAc6S,EAAU5hB,QACxB,OAAEve,GAAWstB,EACbL,EAAU,IAAI7P,GACpB,IAAK,IAAI9H,EAAI,EAAGA,EAAItV,EAAS,EAAGsV,IAG5B,GAFA2X,EAAQ7e,MAAQkf,EAAYhY,GAC5B2X,EAAQ5e,IAAMif,EAAYhY,EAAI,GAC1B8lB,GAAiB6F,EAAchU,GAC/B,OAAO,EAGf,OAAO,CACX,CAEA,SAASuT,GAAqB/I,EAAU4I,EAASxd,GAC7C,OAAOwd,EAAQthB,cAAc0Y,EAASrpB,QAAUgyB,GAAsB3I,EAAU4I,EAAQzvB,QAAQyc,QAASxK,EAC7G,CAmGA,SAAS2c,GAAK5Z,GACV,OAAOA,EAAE,GAAG,GAAKA,EAAE,GAAG,GAAKA,EAAE,GAAG,GAAKA,EAAE,GAAG,EAC9C,CAEA,SAASwZ,GAAKxZ,GACV,OAAOA,EAAE,GAAG,GAAKA,EAAE,GAAG,GAAKA,EAAE,GAAG,GAC5BA,EAAE,GAAG,GAAKA,EAAE,GAAG,GAAKA,EAAE,GAAG,GACzBA,EAAE,GAAG,GAAKA,EAAE,GAAG,GAAKA,EAAE,GAAG,GACzBA,EAAE,GAAG,GAAKA,EAAE,GAAG,GAAKA,EAAE,GAAG,GACzBA,EAAE,GAAG,GAAKA,EAAE,GAAG,GAAKA,EAAE,GAAG,GACzBA,EAAE,GAAG,GAAKA,EAAE,GAAG,GAAKA,EAAE,GAAG,EACjC,CD3eApI,GAAQmP,MAAQ,SAAShC,GACrB,OAAO,IAAInN,GAAQkN,GAAYC,GACnC,EAEAnN,GAAQgH,SAAW,SAASC,GACxB,OAAO,IAAIjH,GAAQ,CACfiH,EAAKoE,UACLpE,EAAKkF,WACLlF,EAAK2C,cACL3C,EAAKyC,cAEb,EAEA1J,GAAQ1jB,UAAYu0B,GAAO9Q,GAASzjB,UAAW,CAE3C6G,KAAMsX,GAAMuF,QAEZ5M,MAAO,WACH,OAAO,IAAI4M,GAAQuN,GAAYvc,KAAK+P,QACxC,EAEA2M,WAAY,WACR,OAAO,IAAI1N,GAAQ0N,GAAW1c,KAAK+P,QACvC,EAEAsO,aAAc,WACV,MAAM,MAAEze,EAAK,IAAEC,EAAG,OAAEkQ,GAAW/P,KAC/B,OAAI+P,EAAOve,QAAU,GAAKoO,EAAMiR,OAAOhR,GAAakQ,EAC7C,IAAIA,EAAQnQ,EAAMwC,QAC7B,IEhCG,MAAM,GAAe,ECRtB,GAAI,WAKN,GAH+B,iBAAX8D,SAAyBA,OAAOwsB,SAMhD,OAAO,WACH,MAAM,IAAI1pB,MAAM,qCACpB,EAIJ,IAAIsB,EAAK,CACLqoB,IAAK,6BACLC,MAAO,gCACPC,IAAK,uCACLC,MAAO,+BACPC,MAAO,gCAMPC,EAAOjxB,KACPuK,EAAK0mB,EAAK1mB,GACVqB,EAAQqlB,EAAKrlB,MACbe,EAAOskB,EAAKtkB,KACZzM,EAAM+wB,EAAK/wB,IACXsL,EAAMylB,EAAKzlB,IACXE,EAAMulB,EAAKvlB,IACXC,EAAMslB,EAAKtlB,IAEXulB,EAAI,SAAS5qB,EAAI6qB,EAAOC,GAGxB,KAAMnzB,gBAAgBizB,GAClB,OAAOA,EAAE9xB,MAAMnW,OAAO2I,OAAOs/B,EAAE3nC,WAAYsT,WAG/C,GAAKyJ,EAAL,CAQA,GANI4qB,EAAEG,IAAI/qB,KACNA,EAAKA,EAAGS,MAGZoqB,EAAQA,GAAS,CAAC,EAEdD,EAAEryB,SAASyH,GAAK,CAIhB,GAAyB,SAFzBA,EAAKA,EAAGlQ,QAED+L,cAGHmE,EAAK4qB,EAAEI,yBAEJ,GAAc,MAAVhrB,EAAG,GAAY,CAKtB,IAAIirB,EAASL,EAAEI,kBAAkBhrB,GAIjC,GAAIirB,EAAOvrB,WAAWvW,OAAS,EAAG,CAG9B,IACIsV,EAAGD,EADH0sB,EAAc,GAGlB,IAAKzsB,EAAI,EAAGD,EAAMysB,EAAOvrB,WAAWvW,OAAQsV,EAAID,EAAKC,IAAK,CAEtD,IAAI0sB,EAAYF,EAAOvrB,WAAWjB,GAClCysB,EAAY3hC,KAAK,IAAIqhC,EAAE9sB,SAASstB,WAAWD,GAAW,IAC1D,CAEA,OAAOD,CACX,CAEAlrB,EAAKlC,SAASstB,WAAWH,EAAOI,YAAY,EAEhD,MAEIrrB,EAAKlC,SAASwtB,gBAAgBrpB,EAAGqoB,IAAKtqB,GAG1C4qB,EAAEW,SAASvrB,EACf,CAUA,OARArI,KAAK8I,KAAOT,EAEZrI,KAAK6zB,cAAcX,GAEfC,GACAnzB,KAAK8zB,OAAOX,GAGTnzB,IA3DQ,CA4DnB,EAEI+zB,EAAad,EAAE3nC,UA6RnB,SAAS0oC,EAAiBC,EAAUC,EAAiB7f,GACjDA,IAAQA,EAAM,CAAC,GAQf,IAPA,IAAI8f,EAA2B9f,EAAI8f,yBAC/BC,EAAM/f,EAAI+f,IACVC,EAAahgB,EAAIggB,WACjBC,EAAWjgB,EAAIigB,SACfC,EAAc,EACdC,EAAc,CAAC,EACfC,EAAQP,EAAgB1iC,OAAS,EAC5BuV,EAAI,EAAGA,GAAK0tB,EAAO1tB,IAAK,CAC7B,IAAI2tB,EAAaR,EAAgBntB,GAC7B4tB,EAAW,KACf,GAAI1B,EAAE/gC,SAASwiC,GAAa,CACxB,IAAIE,EAAkBF,EAAWxB,MAC7B2B,EAAS5B,EAAE,QAAS2B,GACpBE,EAAYD,EAAO/rB,KACnB2I,EAAIijB,EAAWjjB,EACf2iB,GAAOrtB,IAAM0tB,IAAOhjB,GAAK2iB,GAC7BU,EAAUC,YAActjB,EAExB,IAAIujB,EAAkBJ,EAAuB,MACzCI,GAAiBH,EAAOI,SAASD,GAKjCb,GAA0BU,EAAOK,KAAK,cAAeR,EAAWS,aAEpER,EAAWrlB,WAAWslB,EAAgB,cACjCQ,SAAST,KAAWA,EAAWL,GAChCK,GAAYA,EAAWJ,IAAaA,EAAcI,EAC1D,MACQP,GAAOrtB,IAAM0tB,IAAOC,GAAcN,GACtCU,EAAY3uB,SAASkvB,eAAeX,GAAc,KAC9CJ,GAAYA,EAAWC,IAAaA,EAAcD,GAE1DL,EAASxsB,YAAYqtB,EACzB,CAQA,OANIP,IAAaC,EAAYD,YAAcA,GACvCF,EACAG,EAAYH,WAAaA,EAClBE,IACPC,EAAYH,WAA4B,IAAdE,GAEvBC,CACX,CAzUAxpC,OAAOC,eAAe8oC,EAAY,KAAM,CACpC7oC,YAAY,EACZC,IAAK,WACD,OAAO6U,KAAK8I,KAAKwsB,EACrB,EACAliC,IAAK,SAASkiC,GACVt1B,KAAK8I,KAAKwsB,GAAKA,CACnB,IAOJvB,EAAWwB,sBAAwB,SAASrwB,GACxC,IAAI4D,EAAO9I,KAAK8I,KAChB,GAAImqB,EAAEuC,qBAAqBtwB,IAAW+tB,EAAEuC,qBAAqB1sB,GAAO,CAChE,IAAI2sB,EAAYxC,EAAEyC,OAAOxwB,GAAQywB,eAC7BC,EAAU9sB,EAAK6sB,eACnB,GAAIF,GAAaG,EACb,OAAOH,EAAUI,UAAUC,SAASF,EAE5C,CAEA,OAAO3C,EAAE8C,iBACb,EAOAhC,EAAWiC,UAAY,SAASC,EAAQ5hB,GAEpC,IAAIvL,EAAO9I,KAAK8I,KAChB,GAAImqB,EAAEiD,YAAYD,GACd,OAAOhD,EAAEkD,wBAAwBn2B,KAAKk1B,KAAK,cAG/C,GAAI7gB,GAAOA,EAAI+hB,SACX,OAAOp2B,KAAKk1B,KAAK,YAAajC,EAAEoD,wBAAwBJ,IAG5D,IAAIK,EAAerD,EAAEsD,mBAAmBN,GAExC,OADAntB,EAAKktB,UAAUQ,QAAQC,WAAWH,GAC3Bt2B,IACX,EAEA+zB,EAAWlhB,UAAY,SAASgD,EAAIC,EAAIzB,GAEpCA,EAAMA,GAAO,CAAC,EACdyB,EAAKA,GAAM,EAEX,IAAI4gB,EAAgB12B,KAAKk1B,KAAK,cAAgB,GAC1Cc,EAAY/C,EAAE0D,qBAAqBD,GAGvC,GAFAA,EAAgBV,EAAUrqC,MAEtBsnC,EAAEiD,YAAYrgB,GACd,OAAOmgB,EAAUnjB,UAGrB6jB,EAAgBA,EAAc3+B,QAAQ,sBAAuB,IAAII,OAEjE,IAEIy+B,EAAe,cAFPviB,EAAI+hB,SAAWvgB,EAAKmgB,EAAUnjB,UAAUgD,GAAKA,GAEf,KAD9BxB,EAAI+hB,SAAWtgB,EAAKkgB,EAAUnjB,UAAUiD,GAAKA,GACD,IAKxD,OADA9V,KAAKk1B,KAAK,aAAc0B,EAAe,IAAMF,GAAev+B,QACrD6H,IACX,EAEA+zB,EAAWhiB,OAAS,SAASjF,EAAO+pB,EAAIC,EAAIziB,GAExCA,EAAMA,GAAO,CAAC,EAEd,IAAIqiB,EAAgB12B,KAAKk1B,KAAK,cAAgB,GAC1Cc,EAAY/C,EAAE0D,qBAAqBD,GAIvC,GAHAA,EAAgBV,EAAUrqC,MAGtBsnC,EAAEiD,YAAYppB,GACd,OAAOkpB,EAAUjkB,OAGrB2kB,EAAgBA,EAAc3+B,QAAQ,mBAAoB,IAAII,OAE9D2U,GAAS,IAET,IAEIiqB,EAAY,WAFD1iB,EAAI+hB,SAAWtpB,EAAQkpB,EAAUjkB,OAAOjF,MAAQA,SACvCra,IAAPokC,QAA2BpkC,IAAPqkC,EAAoB,IAAMD,EAAK,IAAMC,EAAK,IAC5B,IAGnD,OADA92B,KAAKk1B,KAAK,aAAcwB,EAAgB,IAAMK,GAAW5+B,QAClD6H,IACX,EAGA+zB,EAAWxnB,MAAQ,SAAS6F,EAAIC,GAE5BA,EAAK4gB,EAAEiD,YAAY7jB,GAAMD,EAAKC,EAE9B,IAAIqkB,EAAgB12B,KAAKk1B,KAAK,cAAgB,GAC1Cc,EAAY/C,EAAE0D,qBAAqBD,GAIvC,GAHAA,EAAgBV,EAAUrqC,MAGtBsnC,EAAEiD,YAAY9jB,GACd,OAAO4jB,EAAUzpB,MAGrBmqB,EAAgBA,EAAc3+B,QAAQ,kBAAmB,IAAII,OAE7D,IAAI6+B,EAAW,SAAW5kB,EAAK,IAAMC,EAAK,IAG1C,OADArS,KAAKk1B,KAAK,aAAcwB,EAAgB,IAAMM,GAAU7+B,QACjD6H,IACX,EAKA+zB,EAAWhhB,KAAO,SAASkkB,EAAwB/xB,GAE/C,IAAIgyB,EACApuB,EAAO9I,KAAK8I,KACZquB,EAAkBruB,EAAKquB,gBAI3B,IAAKA,EACD,OAAO,IAAI,GAAO,EAAG,EAAG,EAAG,GAG/B,IAEID,EAAMpuB,EAAKsuB,SAEf,CAAE,MAAOltB,GAGLgtB,EAAM,CACF/oB,EAAGrF,EAAKuuB,WACRrpB,EAAGlF,EAAKwuB,UACR9mB,MAAO1H,EAAKyuB,YACZ9mB,OAAQ3H,EAAK0uB,aAErB,CAEA,GAAIP,EACA,OAAO,IAAI,GAAOC,GAGtB,IAAIjB,EAASj2B,KAAKu1B,sBAAsBrwB,GAAUiyB,GAElD,OAAOlE,EAAEwE,cAAcP,EAAKjB,EAChC,EAQAlC,EAAWqD,QAAU,SAAS/iB,GAE1B,IAEIqjB,EAFAC,EAAU,CAAC,EAGX7uB,EAAO9I,KAAK8I,KAMhB,IALsBA,EAAKquB,kBAKFlE,EAAEuC,qBAAqB1sB,GAC5C,OAAO,IAAI,GAAO,EAAG,EAAG,EAAG,GAY/B,GATIuL,IACIA,EAAInP,SACJyyB,EAAQzyB,OAAS+tB,EAAEyC,OAAOrhB,EAAInP,SAE9BmP,EAAIujB,YACJD,EAAQC,UAAYvjB,EAAIujB,YAI3BD,EAAQC,UAqBN,CAMH,IAAIzE,EAAWnzB,KAAKmzB,WAChBnjB,EAAImjB,EAAS3hC,OAEjB,GAAU,IAANwe,EACA,OAAOhQ,KAAKo3B,QAAQ,CAAElyB,OAAQyyB,EAAQzyB,OAAQ0yB,WAAW,IAKxDD,EAAQzyB,SAETyyB,EAAQzyB,OAASlF,MAGrB,IAAK,IAAI8G,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CACxB,IAEI+wB,EAFAC,EAAe3E,EAASrsB,GAMxB+wB,EADmC,IAAnCC,EAAa3E,WAAW3hC,OACZsmC,EAAaV,QAAQ,CAAElyB,OAAQyyB,EAAQzyB,OAAQ0yB,WAAW,IAG1DE,EAAaV,QAAQ,CAAElyB,OAAQyyB,EAAQzyB,OAAQ0yB,WAAW,IAQtEF,EALCA,EAKYA,EAAWt0B,MAAMy0B,GAHjBA,CAKrB,CAEA,OAAOH,CACX,CA/DI,IACIA,EAAa5uB,EAAKsuB,SACtB,CAAE,MAAOltB,GAELwtB,EAAa,CACTvpB,EAAGrF,EAAKuuB,WACRrpB,EAAGlF,EAAKwuB,UACR9mB,MAAO1H,EAAKyuB,YACZ9mB,OAAQ3H,EAAK0uB,aAErB,CAEA,GAAKG,EAAQzyB,OAGN,CAEH,IAAI+wB,EAASj2B,KAAKu1B,sBAAsBoC,EAAQzyB,QAChD,OAAO+tB,EAAEwE,cAAcC,EAAYzB,EACvC,CALI,OAAO,IAAI,GAAOyB,EAkD9B,EA6EA,IAAIK,EAAU,MAEd,SAASC,EAAcC,EAAItD,GACvB,IAAIuD,EAAY5oB,WAAW2oB,GAC3B,OAAIF,EAAQjoC,KAAKmoC,GAAYC,EAAYvD,EAClCuD,CACX,CAgCAnE,EAAWoE,KAAO,SAASC,EAAS/jB,GAEhC,GAAI+jB,GAA8B,iBAAZA,EAAsB,MAAM,IAAIpvB,MAAM,iEAI5DovB,EAAUnF,EAAEoF,aAAaD,GACzB/jB,IAAQA,EAAM,CAAC,GAEf,IAAIikB,EAAejkB,EAAIikB,aAEnBlE,EAAM/f,EAAI+f,IAEVmE,EAAWlkB,EAAIkkB,SAEfC,EAAiBnkB,EAAIokB,mBACrBC,EAA0C,WAAnBF,GAAkD,WAAnBA,GAAkD,QAAnBA,EAErFrqB,EAAIkG,EAAIlG,OACF1b,IAAN0b,IAAiBA,EAAInO,KAAKk1B,KAAK,MAAQ,GAE3C,IAAIyD,EAAMtkB,EAAI8f,yBACVgB,EAAc9gB,EAAI8gB,YAClBA,IAAgBlC,EAAEhiC,QAAQkkC,KAAcA,EAAc,CAACA,IAE3D,IAAIyD,EAAoBvkB,EAAIggB,WACxBwE,EAAwC,SAAtBD,EAClBvE,EAAa,EAAmB,QAAWuE,GAAqB,MAEpE54B,KAAK84B,QACL94B,KAAKk1B,KAAK,CAEN,YAAa,WAIb,QAAYkD,GAAWE,EAAgB,KAAO,SAIlD,IAAI3D,EAAWrlB,WAAWtP,KAAKk1B,KAAK,cAC/BP,IACDA,EAAW,IACP+D,GAAuBvD,IAAan1B,KAAKk1B,KAAK,YAAaP,IAGnE,IACIoE,EADAC,EAAM7yB,SAENoyB,GAEwB,iBAAbA,IAAuBA,EAAW,CAAEzhB,EAAGyhB,IAClDQ,EAlKR,SAA4B7F,EAAO+F,GAC/B/F,IAAUA,EAAQ,CAAC,GACnB,IAAIgG,EAAkBjG,EAAE,YACpBnc,EAAIoc,EAAMpc,EACd,GAAIA,QAA6BrkB,IAAxBygC,EAAM,cAA6B,CAMxC,IAAIiG,EAAalG,EAAE,QAAQiC,KAAK,IAAKpe,GAAGsiB,SAASH,EAAII,QACrDH,EAAgBhE,KAAK,aAAc,IAAMiE,EAAW7D,GACxD,CAUA,OATIrC,EAAE/gC,SAASghC,IAOXgG,EAAgBhE,KAAKhC,GAElBgG,EAAgBpwB,IAC3B,CA2IwBwwB,CAAmBf,EAAUv4B,OAE7C+4B,EAAgBC,EAAIO,yBAMxB,IAJA,IAGIC,EAHAnoB,EAAS,EACTooB,EAAQrB,EAAQ9nC,MAAM,MACtBopC,EAAe,GAEV5yB,EAAI,EAAG6yB,EAAQF,EAAMjoC,OAAS,EAAGsV,GAAK6yB,EAAO7yB,IAAK,CACvD,IAII8yB,EAJAzoB,EAAKkjB,EACLwF,EAAgB,SAChB5F,EAAW+E,EAAIrF,gBAAgBrpB,EAAGqoB,IAAK,SACvCne,EAAOilB,EAAM3yB,GAEjB,GAAI0N,EACA,GAAI2gB,EAAa,CAEb,IAAIjB,EAAkBjB,EAAE6G,eAAetlB,EAAM2gB,EAAa,CACtD9jB,QAASA,EACT8iB,yBAA0BwE,IAS1BoB,GAPJH,EAAc5F,EAAiBC,EAAUC,EAAiB,CACtDC,yBAA0BwE,EAC1BvE,IAAMttB,IAAM6yB,GAASvF,EACrBC,WAAY,EAAmB,KAAOA,EACtCC,SAAUK,KAGgBN,WAC1B0F,GAAelB,GAAwB,IAAN/xB,IAASqK,EAAK4oB,GACzC,IAANjzB,IAAS0yB,EAAuC,GAA1BI,EAAYrF,YAC1C,MACQH,GAAOttB,IAAM6yB,IAAOnlB,GAAQ4f,GAChCH,EAASc,YAAcvgB,MAExB,CAIHyf,EAASc,YAAc,IACvB8E,GAAiB,gBAGjB,IAAIG,EAAgB/F,EAASgG,MAG7B,GAFAD,EAAcE,YAAc,EAC5BF,EAAcG,cAAgB,EAC1BhF,EAAa,CAEbyE,EAAc,CAAC,EAEf,IAAIQ,EAAezF,EAEnB,IAAK,IAAI5tB,GAHTmtB,EAAkBjB,EAAEoH,uBAAuBlF,EAAa9jB,IAG3B7f,OAAQuV,EAAI,EAAGA,IAAK,CAC7C,MAAMmsB,EAAQgB,EAAgBntB,EAAI,GAAGmsB,MACrC,IAAKA,KAAW,cAAeA,GAAQ,SACvC,MAAMoH,EAAKhrB,WAAW4jB,EAAM,cAC5B,GAAIkC,SAASkF,GAAK,CACdF,EAAeE,EACf,KACJ,CACJ,CACIzB,IACI/xB,EAAI,EACJqK,EAAoB,IAAfipB,EAELZ,EAA4B,GAAfY,GAIrBnG,EAASsG,aAAa,YAAaH,GACnCR,EAAYrF,YAAc6F,CAC9B,CACJ,CACIR,GAAaF,EAAa9nC,KAAKgoC,GAC/B9yB,EAAI,GAAGmtB,EAASsG,aAAa,KAAMppB,IAEnCrK,EAAI,GAAKyxB,IAAUtE,EAASsG,aAAa,IAAKpsB,GAClD8lB,EAASuG,UAAUhE,QAAUqD,EAC7Bd,EAActxB,YAAYwsB,GAC1B5iB,GAAUmD,EAAKhjB,OAAS,CAC5B,CAEA,GAAIknC,EACA,GAAIvD,EACAhkB,EArKZ,SAAqBspB,EAAWf,EAAcgB,EAAYrG,GACtD,IAAKrjC,MAAMC,QAAQyoC,GAAe,OAAO,EACzC,IAAI1pB,EAAI0pB,EAAaloC,OACrB,IAAKwe,EAAG,OAAO,EAKf,IAJA,IAAI4pB,EAAcF,EAAa,GAC3BiB,EAAY3C,EAAc4B,EAAYrF,YAAamG,IAAeA,EAClEE,EAAe,EACfC,EAAe7C,EAAc3D,EAAYqG,GACpC5zB,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAGnB8zB,GADkB5C,GADlB4B,EAAcF,EAAa5yB,IACiButB,WAAYqG,IAAeG,EAG3E,IACI1pB,EADA2pB,EAAY9C,EAAc4B,EAAYrF,YAAamG,IAAeA,EAEtE,OAAQD,GACJ,IAAK,SACDtpB,EAAMwpB,EAAY,EAAM,IAAOG,EAAcF,EAAe,EAC5D,MACJ,IAAK,SACDzpB,GAAO,IAAO2pB,EAAaF,EAC3B,MACJ,QAEIzpB,EAAM,GAAMwpB,EAGpB,OAAOxpB,CACX,CAyIiB4pB,CAAYvC,EAAgBkB,EAAc/E,EAAUN,QACtD,GAAuB,QAAnBmE,EAEPrnB,EAAK,YACF,CACH,IAAI6pB,EASJ,OARIrB,EAAQ,GACRqB,EAAK1rB,WAAW+kB,IAAe,EAC/B2G,GAAMrB,EACD5B,EAAQjoC,KAAKukC,KAAa2G,GAAMrG,IAGrCqG,EAAK,EAEDxC,GACJ,IAAK,SACDrnB,EAAM,GAAO6pB,EAAK,EAAM,KACxB,MACJ,IAAK,SACD7pB,GAAO6pB,EAAK,GAAO,KAG/B,MAEuB,IAAnBxC,EACArnB,EAAK,MACEqnB,EACPrnB,EAAKqnB,GAGLrnB,EAAK,EAEkB,OAAnBnR,KAAKk1B,KAAK,MAAel1B,KAAKk1B,KAAK,IAAKsE,GAAc,UAMlE,OAHAT,EAAcrF,WAAW6G,aAAa,KAAMppB,GAE5CnR,KAAK8zB,OAAOiF,GACL/4B,IACX,EAOA+zB,EAAWkH,WAAa,SAAS9jC,GAE7B,MAAM+jC,EAAWC,EAAehkC,IAE1B,GAAEmT,EAAE,MAAE8wB,GAAUnI,EAAEoI,YAAYH,GAC9B7yB,EAAKrI,KAAK8I,KAShB,OAPIwB,EACIjC,EAAGizB,eAAehxB,EAAI8wB,IACtB/yB,EAAGkzB,kBAAkBjxB,EAAI8wB,GAEtB/yB,EAAGmzB,aAAaN,IACvB7yB,EAAGozB,gBAAgBP,GAEhBl7B,IACX,EAEA+zB,EAAWmB,KAAO,SAAS/9B,EAAMxL,GAE7B,GAAIsnC,EAAEiD,YAAY/+B,GAAO,CAMrB,IAHA,IAAIukC,EAAa17B,KAAK8I,KAAK4yB,WACvBxI,EAAQ,CAAC,EAEJpsB,EAAI,EAAGA,EAAI40B,EAAWlqC,OAAQsV,IACnCosB,EAAMwI,EAAW50B,GAAG3P,MAAQukC,EAAW50B,GAAGnb,MAG9C,OAAOunC,CACX,CAEA,GAAID,EAAEryB,SAASzJ,IAAS87B,EAAEiD,YAAYvqC,GAClC,OAAOqU,KAAK8I,KAAK6yB,aAAaR,EAAehkC,IAGjD,GAAoB,iBAATA,EAEP,IAAK,IAAIykC,KAAYzkC,EACbA,EAAK5L,eAAeqwC,IACpB57B,KAAKu6B,aAAaqB,EAAUzkC,EAAKykC,SAMzC57B,KAAKu6B,aAAapjC,EAAMxL,GAG5B,OAAOqU,IACX,EAEA+zB,EAAW8H,cAAgB,WAOvB,MAJgB,SADF77B,KAAK87B,WAEf97B,KAAKk1B,KAAK,IAAKjC,EAAE8I,kBAAkB/7B,KAAKk1B,KAAK,OAG1Cl1B,IACX,EAEA+zB,EAAWxvB,OAAS,WAMhB,OAJIvE,KAAK8I,KAAKkD,YACVhM,KAAK8I,KAAKkD,WAAWgwB,YAAYh8B,KAAK8I,MAGnC9I,IACX,EAEA+zB,EAAW+E,MAAQ,WAEf,KAAO94B,KAAK8I,KAAK4qB,YACb1zB,KAAK8I,KAAKkzB,YAAYh8B,KAAK8I,KAAK4qB,YAGpC,OAAO1zB,IACX,EAOA+zB,EAAWF,cAAgB,SAASX,GAEhC,IAAK,IAAIpoC,KAAOooC,EACRA,EAAM3nC,eAAeT,IACrBkV,KAAKu6B,aAAazvC,EAAKooC,EAAMpoC,IAIrC,OAAOkV,IACX,EAEA+zB,EAAWD,OAAS,SAASmI,GAEpBhJ,EAAEhiC,QAAQgrC,KACXA,EAAM,CAACA,IAGX,IAAK,IAAIn1B,EAAI,EAAGD,EAAMo1B,EAAIzqC,OAAQsV,EAAID,EAAKC,IACvC9G,KAAK8I,KAAKrB,YAAYwrB,EAAEyC,OAAOuG,EAAIn1B,KAGvC,OAAO9G,IACX,EAEA+zB,EAAWmI,QAAU,SAASD,GAE1B,IAAInc,EAAQ9f,KAAK8I,KAAK4qB,WACtB,OAAO5T,EAAQmT,EAAEnT,GAAOqc,OAAOF,GAAOj8B,KAAK8zB,OAAOmI,EACtD,EAEAlI,EAAWoI,OAAS,SAASF,GAEzB,IAAInzB,EAAO9I,KAAK8I,KACZszB,EAAStzB,EAAKkD,WAElB,GAAIowB,EAAQ,CAEHnJ,EAAEhiC,QAAQgrC,KACXA,EAAM,CAACA,IAGX,IAAK,IAAIn1B,EAAI,EAAGD,EAAMo1B,EAAIzqC,OAAQsV,EAAID,EAAKC,IACvCs1B,EAAOC,aAAapJ,EAAEyC,OAAOuG,EAAIn1B,IAAKgC,EAE9C,CAEA,OAAO9I,IACX,EAEA+zB,EAAWqF,SAAW,SAAStwB,GAE3B,OADAmqB,EAAEyC,OAAO5sB,GAAMrB,YAAYzH,KAAK8I,MACzB9I,IACX,EAEA+zB,EAAWpB,IAAM,WAEb,OAAO3yB,KAAK8I,gBAAgB5C,OAAOo2B,cAAgBt8B,KAAOizB,EAAEjzB,KAAK8I,KAAKquB,gBAC1E,EAEApD,EAAW+H,QAAU,WAEjB,OAAO97B,KAAK8I,KAAKgzB,QAAQS,aAC7B,EAEAxI,EAAWsF,KAAO,WACd,IAAIpyB,EAAUjH,KAAK2yB,OAAS3yB,KACxBw8B,EAAWv1B,EAAQ6B,KAAKjB,qBAAqB,QAAQ,GACzD,OAAI20B,EAAiBvJ,EAAEuJ,GAChBvJ,EAAE,QAAQmG,SAASnyB,EAC9B,EAEA8sB,EAAW3xB,MAAQ,WAEf,IAAIA,EAAQ6wB,EAAEjzB,KAAK8I,KAAK2zB,WAAU,IAGlC,OADAr6B,EAAM0G,KAAKwsB,GAAKrC,EAAE7uB,WACXhC,CACX,EAEA2xB,EAAW2I,QAAU,SAASn2B,GAE1B,IAAIo2B,EAAQ38B,KAAK8I,KAAK8zB,cAAcr2B,GACpC,OAAOo2B,EAAQ1J,EAAE0J,QAASlqC,CAC9B,EAEAshC,EAAW3rB,KAAO,SAAS7B,GAEvB,IAAIs2B,EAAO,GACPC,EAAQ98B,KAAK8I,KAAKN,iBAAiBjC,GAEvC,GAAIu2B,EAGA,IAAK,IAAIh2B,EAAI,EAAGA,EAAIg2B,EAAMtrC,OAAQsV,IAC9B+1B,EAAKjrC,KAAKqhC,EAAE6J,EAAMh2B,KAI1B,OAAO+1B,CACX,EAGA9I,EAAWZ,SAAW,WAKlB,IAHA,IAAIA,EAAWnzB,KAAK8I,KAAKf,WAErBuiB,EAAc,GACTxjB,EAAI,EAAGA,EAAIqsB,EAAS3hC,OAAQsV,IAEH,IADXqsB,EAASrsB,GACXwB,UACbgiB,EAAY14B,KAAKqhC,EAAEE,EAASrsB,KAGpC,OAAOwjB,CACX,EAGAyJ,EAAWqI,OAAS,WAChB,OAAOnJ,EAAEjzB,KAAK8I,KAAKkD,aAAe,IACtC,EAGA+nB,EAAWriC,MAAQ,WAKf,IAHA,IAAIA,EAAQ,EACRoX,EAAO9I,KAAK8I,KAAKi0B,gBAEdj0B,GAEmB,IAAlBA,EAAKR,UAAgB5W,IACzBoX,EAAOA,EAAKi0B,gBAGhB,OAAOrrC,CACX,EAEAqiC,EAAWiJ,kBAAoB,SAASxC,EAAWyC,GAK/C,IAHA,IAAI9F,EAAkBn3B,KAAK8I,KAAKquB,gBAC5BruB,EAAO9I,KAAK8I,KAAKkD,WAEdlD,GAAQA,IAASm0B,GAAcn0B,IAASquB,GAAiB,CAE5D,IAAI8B,EAAMhG,EAAEnqB,GACZ,GAAImwB,EAAIiE,SAAS1C,GACb,OAAOvB,EAGXnwB,EAAOA,EAAKkD,UAChB,CAEA,OAAO,IACX,EAGA+nB,EAAWxrB,SAAW,SAASF,GAE3B,IAAI1M,EAAIqE,KAAK8I,KACTlN,EAAIq3B,EAAEyC,OAAOrtB,GACb80B,EAAMvhC,GAAKA,EAAEoQ,WAEjB,OAAQrQ,IAAMwhC,MAAWA,GAAwB,IAAjBA,EAAI70B,UAAoD,GAAjC3M,EAAEyhC,wBAAwBD,GACrF,EAGApJ,EAAWsJ,aAAe,SAASlvB,EAAGH,GAElC,IAAI2kB,EAAM3yB,KAAK2yB,MAAM7pB,KAEjB+E,EAAI8kB,EAAI2K,iBACZzvB,EAAEM,EAAIA,EACNN,EAAEG,EAAIA,EAEN,IAEI,IAAIuvB,EAAc1vB,EAAE2vB,gBAAgB7K,EAAIgD,eAAeE,WACnD4H,EAAsBz9B,KAAKu1B,sBAAsB5C,GAAKkD,SAE9D,CAAE,MAAO3rB,GAGL,OAAO2D,CACX,CAEA,OAAO0vB,EAAYC,gBAAgBC,EACvC,EAEA1J,EAAW2J,uBAAyB,SAAS7vB,GAEzC,IACIqI,EADOlW,KAAKo3B,QAAQ,CAAElyB,OAAQlF,KAAK2yB,QACrBzc,SAGlB,OADAlW,KAAK6S,UAAUhF,EAAEM,EAAI+H,EAAO/H,EAAGN,EAAEG,EAAIkI,EAAOlI,GACrChO,IACX,EAOA+zB,EAAW4J,uBAAyB,SAASC,EAAUC,EAAW34B,GAE9D04B,EAAW,IAAI,GAAQA,GACvBC,EAAa,IAAI,GAAQA,GACzB34B,IAAWA,EAASlF,KAAK2yB,OAMzB,IAAIpmB,EAAQvM,KAAKuM,QACjBvM,KAAKk1B,KAAK,YAAa,IACvB,IAAIniB,EAAO/S,KAAKo3B,QAAQ,CAAElyB,OAAQA,IAAUqH,MAAMA,EAAM6F,GAAI7F,EAAM8F,IAG9DyrB,EAAoB7K,EAAEsD,qBAC1BuH,EAAkBC,cAAchrB,EAAK5E,EAAI4E,EAAKvC,MAAQ,GAAIuC,EAAK/E,EAAI+E,EAAKtC,OAAS,GAGjF,IAAIutB,EAAqB/K,EAAEsD,qBACvBzpB,EAAQ8wB,EAASltB,aAAamtB,EAAWD,EAASx7B,QAAQiP,OAAO,EAAG,IACpEvE,GAAOkxB,EAAmBC,UAAUnxB,EAAO,EAAG,GAGlD,IAAIoxB,EAAsBjL,EAAEsD,qBACxB4H,EAAgBP,EAASx7B,QAAQwP,KAAKisB,EAAW9qB,EAAKvC,MAAQ,GAClE0tB,EAAoBH,aAAa,EAAIH,EAASzvB,EAAIgwB,EAAchwB,EAAG,EAAIyvB,EAAS5vB,EAAImwB,EAAcnwB,GAGlG,IAAIowB,EAAMp+B,KAAKu1B,sBAAsBrwB,GAGjC8wB,EAAY/C,EAAEsD,qBASlB,OARAP,EAAUqI,UACNH,EAAoBjI,OAAOH,SACvBkI,EAAmB/H,OAAOH,SACtBgI,EAAkB7H,OAAOH,SACrBsI,EAAI7xB,MAAMA,EAAM6F,GAAI7F,EAAM8F,QAE1CrS,KAAKk1B,KAAK,YAAajC,EAAEoD,wBAAwBL,EAAUC,SAEpDj2B,IACX,EAEA+zB,EAAWuK,iBAAmB,SAASpL,EAAOp7B,GAE1CA,EAAOm7B,EAAEyC,OAAO59B,GAEhB,IAAIw9B,EAAKrC,EAAEW,SAAS97B,GAChBymC,EAAgBtL,EAAE,gBAAiBC,GACnCsL,EAAQvL,EAAE,QAAS,CAAE,aAAc,IAAMqC,IAE7CiJ,EAAczK,OAAO0K,GAErBx+B,KAAK8zB,OAAOyK,GACZ,IACIA,EAAcz1B,KAAK21B,cACvB,CAAE,MAAOv0B,GAGL,GAAyD,SAArD/D,SAASC,gBAAgBu1B,aAAa,WAAuB,CAG7D,IAAI+C,EAAYH,EAAcz1B,KAC9B41B,EAAUC,UAAY,GAEtB,IAAIC,EAAcF,EAAU/C,aAAa,MACrCiD,IAAaC,QAAQD,GAAeF,GAGxC,IADA,IAAII,EAAUC,WAAWL,GAChB53B,EAAI,EAAGD,EAAMi4B,EAAQttC,OAAQsV,EAAID,EAAKC,IAAK,CAChD,IAAI5B,EAAS45B,EAAQh4B,GACjBk4B,EAAW,IAAIC,SAASP,EAAWx5B,EAAQ4B,GAC/C63B,UAAU/sC,KAAKotC,GACfN,EAAUC,UAAU73B,GAAKk4B,EACzBA,EAASE,UACb,CACJ,CACJ,CACA,OAAOl/B,IACX,EAKA,MAAMm/B,EAAwB,oBAC9B,SAASC,EAAaC,GAClB,OAAKpM,EAAEryB,SAASy+B,IACTA,EAAIlnC,OAAO/H,MAAM+uC,IADK,EAEjC,CAEApL,EAAWmJ,SAAW,SAAS1C,GAC3B,QAAKvH,EAAEryB,SAAS45B,IACTx6B,KAAK8I,KAAKw2B,UAAU/2B,SAASiyB,EAAUriC,OAClD,EAEA47B,EAAWkB,SAAW,SAASuF,GAE3B,OADAx6B,KAAK8I,KAAKw2B,UAAU1kC,OAAOwkC,EAAa5E,IACjCx6B,IACX,EAEA+zB,EAAWwL,YAAc,SAAS/E,GAE9B,OADAx6B,KAAK8I,KAAKw2B,UAAU/6B,UAAU66B,EAAa5E,IACpCx6B,IACX,EAEA+zB,EAAWyL,YAAc,SAAShF,EAAWiF,GACzC,MAAMC,EAASN,EAAa5E,GAC5B,IAAK,IAAI1zB,EAAI,EAAGA,EAAI44B,EAAOluC,OAAQsV,IAC/B9G,KAAK8I,KAAKw2B,UAAUK,OAAOD,EAAO54B,GAAI24B,GAE1C,OAAOz/B,IACX,EAQA+zB,EAAW6L,OAAS,SAASC,GAEzBA,EAAWA,GAAY,EAMvB,IALA,IAIID,EAJA92B,EAAO9I,KAAK8I,KACZtX,EAASsX,EAAKg3B,iBACdC,EAAU,GACVvwB,EAAW,EAERA,EAAWhe,GACdouC,EAAS92B,EAAKk3B,iBAAiBxwB,GAC/BuwB,EAAQnuC,KAAK,CAAEuc,EAAGyxB,EAAOzxB,EAAGH,EAAG4xB,EAAO5xB,EAAGwB,SAAUA,IACnDA,GAAYqwB,EAEhB,OAAOE,CACX,EAEAhM,EAAWkM,cAAgB,WAEvB,IAAInoC,EAAOm7B,EAAE,QACbn7B,EAAKo9B,KAAKl1B,KAAKk1B,QACf,IAAIpe,EAAI9W,KAAKkgC,oBAIb,OAHIppB,GACAhf,EAAKo9B,KAAK,IAAKpe,GAEZhf,CACX,EAEAi8B,EAAWmM,kBAAoB,WAE3B,IAAIpE,EAAU97B,KAAK87B,UAEnB,OAAQA,GACJ,IAAK,OACD,OAAO97B,KAAKk1B,KAAK,KACrB,IAAK,OACD,OAAOjC,EAAEkN,sBAAsBngC,KAAK8I,MACxC,IAAK,UACD,OAAOmqB,EAAEmN,yBAAyBpgC,KAAK8I,MAC3C,IAAK,WACD,OAAOmqB,EAAEoN,0BAA0BrgC,KAAK8I,MAC5C,IAAK,UACD,OAAOmqB,EAAEqN,yBAAyBtgC,KAAK8I,MAC3C,IAAK,SACD,OAAOmqB,EAAEsN,wBAAwBvgC,KAAK8I,MAC1C,IAAK,OACD,OAAOmqB,EAAEuN,sBAAsBxgC,KAAK8I,MAG5C,MAAM,IAAIE,MAAM8yB,EAAU,gCAC9B,EAEA7I,EAAE3nC,UAAUm1C,gBAAkB,WAC1B,IAAItyB,EAAGH,EAAGwC,EAAOC,EAAQomB,EAAIC,EAAIxmB,EAAGmG,EAAIC,EAAI3G,EAAQ+G,EAAGpH,EAAIC,EAAIC,EAAIC,EACnE,OAAQ7P,KAAK87B,WAET,IAAK,OAKD,OAJA3tB,EAAImB,WAAWtP,KAAKk1B,KAAK,OAAS,EAClClnB,EAAIsB,WAAWtP,KAAKk1B,KAAK,OAAS,EAClC1kB,EAAQlB,WAAWtP,KAAKk1B,KAAK,WAAa,EAC1CzkB,EAASnB,WAAWtP,KAAKk1B,KAAK,YAAc,EACrC,IAAI,GAAO/mB,EAAGH,EAAGwC,EAAOC,GAEnC,IAAK,SAID,OAHAomB,EAAKvnB,WAAWtP,KAAKk1B,KAAK,QAAU,EACpC4B,EAAKxnB,WAAWtP,KAAKk1B,KAAK,QAAU,EACpC5kB,EAAIhB,WAAWtP,KAAKk1B,KAAK,OAAS,EAC3B,IAAI,GAAU,CAAE/mB,EAAG0oB,EAAI7oB,EAAG8oB,GAAMxmB,EAAGA,GAE9C,IAAK,UAKD,OAJAumB,EAAKvnB,WAAWtP,KAAKk1B,KAAK,QAAU,EACpC4B,EAAKxnB,WAAWtP,KAAKk1B,KAAK,QAAU,EACpCze,EAAKnH,WAAWtP,KAAKk1B,KAAK,QAAU,EACpCxe,EAAKpH,WAAWtP,KAAKk1B,KAAK,QAAU,EAC7B,IAAI,GAAU,CAAE/mB,EAAG0oB,EAAI7oB,EAAG8oB,GAAMrgB,EAAIC,GAE/C,IAAK,WAED,OADA3G,EAASkjB,EAAEyN,qBAAqB1gC,MACzB,IAAI,GAAW+P,GAE1B,IAAK,UAGD,OAFAA,EAASkjB,EAAEyN,qBAAqB1gC,OACrBxO,OAAS,GAAGue,EAAOne,KAAKme,EAAO,IACnC,IAAI,GAAWA,GAE1B,IAAK,OAGD,OAFA+G,EAAI9W,KAAKk1B,KAAK,KACT,GAAOzJ,gBAAgB3U,KAAIA,EAAImc,EAAE8I,kBAAkBjlB,IACjD,IAAI,GAAOA,GAEtB,IAAK,OAKD,OAJApH,EAAKJ,WAAWtP,KAAKk1B,KAAK,QAAU,EACpCtlB,EAAKN,WAAWtP,KAAKk1B,KAAK,QAAU,EACpCvlB,EAAKL,WAAWtP,KAAKk1B,KAAK,QAAU,EACpCrlB,EAAKP,WAAWtP,KAAKk1B,KAAK,QAAU,EAC7B,IAAI,GAAO,CAAE/mB,EAAGuB,EAAI1B,EAAG4B,GAAM,CAAEzB,EAAGwB,EAAI3B,EAAG6B,IAIxD,OAAO7P,KAAKo3B,SAChB,EAQArD,EAAW4M,iBAAmB,SAASvvB,EAAKlM,GAExC,IAAIytB,EAAM3yB,KAAK2yB,MAAM7pB,KACrB5D,EAASA,GAAUytB,EACnB,IAAI5f,EAAO/S,KAAKo3B,QAAQ,CAAElyB,OAAQA,IAC9BgR,EAASnD,EAAKmD,SAElB,GAAKnD,EAAKmE,sCAAsC9F,GAAhD,CAEA,IAAIwvB,EACA9E,EAAU97B,KAAK87B,UAKnB,GAAgB,SAAZA,EAAoB,CAEpB,IAAI+E,EAAQ,IAAI,GACZvxB,WAAWtP,KAAKk1B,KAAK,MAAQ,GAC7B5lB,WAAWtP,KAAKk1B,KAAK,MAAQ,GAC7B5lB,WAAWtP,KAAKk1B,KAAK,UACrB5lB,WAAWtP,KAAKk1B,KAAK,YAGrB4L,EAAa9gC,KAAKu1B,sBAAsBrwB,GAExC67B,EAAuB9N,EAAE+N,gBAAgBF,GAGzCG,EAAgBtO,EAAI4D,qBACxB0K,EAAchD,WAAW8C,EAAqBG,SAAUhrB,EAAO/H,EAAG+H,EAAOlI,GACzE,IAAIiI,EAAOgd,EAAEwE,cAAcoJ,EAAOI,EAAchL,OAAOH,SAASgL,IAChEF,EAAO,IAAK,GAAO3qB,GAAOiB,sCAAsC9F,EAAK2vB,EAAqBG,SAE9F,MAAO,GAAgB,SAAZpF,GAAkC,YAAZA,GAAqC,aAAZA,GAAsC,WAAZA,GAAoC,YAAZA,EAAuB,CAE/H,IAKIh1B,EAAG84B,EAAQuB,EAAoBC,EAAa5xB,EAJ5CuwB,GADwB,SAAZjE,EAAsB97B,KAAOA,KAAKigC,iBAC3BL,SACnByB,EAAcp+B,IACdq+B,EAAiB,GAIrB,IAAKx6B,EAAI,EAAGA,EAAIi5B,EAAQvuC,OAAQsV,IAE5B84B,EAASG,EAAQj5B,GAGjBq6B,GADAA,EAAKlO,EAAEqK,eAAesC,EAAOzxB,EAAGyxB,EAAO5xB,IAC/BwvB,gBAAgBx9B,KAAKu1B,sBAAsBrwB,KAOnDsK,GANAowB,EAAS,IAAI,GAAQuB,IACG3xB,SAAS0G,IAIjCkrB,EAAqC,IAAvBxB,EAAOpwB,SAAS4B,KAGfiwB,GACXA,EAAc7xB,EACd8xB,EAAiB,CAAC,CAAE1B,OAAQA,EAAQwB,YAAaA,KAC1C5xB,EAAW6xB,EAAc,GAChCC,EAAe1vC,KAAK,CAAEguC,OAAQA,EAAQwB,YAAaA,IAI3DE,EAAe/jC,MAAK,SAAS5B,EAAGC,GAC5B,OAAOD,EAAEylC,YAAcxlC,EAAEwlC,WAC7B,IAEIE,EAAe,KACfV,EAAOU,EAAe,GAAG1B,OAEjC,CAEA,OAAOgB,CAnE+D,CAoE1E,EAQA7M,EAAWwG,aAAe,SAASpjC,EAAMxL,GAErC,MAAM0c,EAAKrI,KAAK8I,KAEhB,GAAc,OAAVnd,EAEA,OADAqU,KAAKi7B,WAAW9jC,GACT6I,KAGX,MAAMk7B,EAAWC,EAAehkC,IAE1B,GAAEmT,GAAO2oB,EAAEoI,YAAYH,GAW7B,OAVI5wB,EAGAjC,EAAGk5B,eAAej3B,EAAI4wB,EAAUvvC,GACZ,OAAbuvC,EACP7yB,EAAGitB,GAAK3pC,EAER0c,EAAGkyB,aAAaW,EAAUvvC,GAGvBqU,IACX,EAIAizB,EAAEI,kBAAoB,SAAS+E,GAE3B,GAAIA,EAAS,CACT,MAAMoJ,EAAY,eAAel3B,EAAGqoB,qBAAqBroB,EAAGwoB,wBAAkCsF,WACxF,gBAAEhyB,GAAoB6sB,EAAEwO,SAASD,EAAW,CAAEE,OAAO,IAC3D,OAAOt7B,CACX,CAEA,MAAMusB,EAAMxsB,SAASwtB,gBAAgBrpB,EAAGqoB,IAAK,OAG7C,OAFAA,EAAI4O,eAAej3B,EAAGsoB,MAAO,cAAetoB,EAAGwoB,OAC/CH,EAAI4H,aAAa,UAlvCJ,OAmvCN5H,CACX,EAEAM,EAAE0O,eAAiB,SAASC,GACxB,MAAM,KAAE94B,GAASmqB,EAAE,QAAS,CAAE9gC,KAAM,YAAc,CAC9C8gC,EAAE4O,mBAAmBD,KAEzB,OAAO94B,CACX,EAEAmqB,EAAE4O,mBAAqB,SAASttC,EAAO,IAEnC,OADY4R,SAASe,eAAe46B,eAAe,KAAM,MAAO,MACrDD,mBAAmBttC,EAClC,EAEA0+B,EAAE9uB,UAAY,EAGd8uB,EAAE7uB,SAAW,WAET,MAAO,QAAU6uB,EAAE9uB,SACvB,EAEA8uB,EAAEyC,OAAS,SAASrtB,GAEhB,OAAO4qB,EAAEG,IAAI/qB,GAAMA,EAAGS,KAAQT,EAAG05B,UAAY15B,GAAMA,EAAG,EAC1D,EAEA4qB,EAAEW,SAAW,SAAS9qB,GAGlB,OADAA,EAAOmqB,EAAEyC,OAAO5sB,IACJwsB,KAAOxsB,EAAKwsB,GAAKrC,EAAE7uB,WACnC,EAOA6uB,EAAEoF,aAAe,SAASF,GAEtB,OAAQA,GAAQ,IAAIpgC,QAAQ,KAAM,IACtC,EAEAk7B,EAAEiD,YAAc,SAASvqC,GAErB,YAAwB,IAAVA,CAClB,EAEAsnC,EAAEryB,SAAW,SAASjV,GAElB,MAAwB,iBAAVA,CAClB,EAEAsnC,EAAE/gC,SAAW,SAASvG,GAElB,OAAOA,GAA2B,iBAAVA,CAC5B,EAEAsnC,EAAEhiC,QAAUD,MAAMC,QAElBgiC,EAAEwO,SAAW,SAASltC,EAAM8f,GAIxB,IAAIwe,EAFJxe,EAAMA,GAAO,CAAC,EAId,IACI,IAAI2tB,EAAS,IAAIC,UAEZhP,EAAEiD,YAAY7hB,EAAIqtB,SACnBM,EAAON,MAAQrtB,EAAIqtB,OAGvB7O,EAAMmP,EAAOE,gBAAgB3tC,EAAM,WACvC,CAAE,MAAO4tC,GACLtP,OAAMpgC,CACV,CAEA,IAAKogC,GAAOA,EAAIhrB,qBAAqB,eAAerW,OAChD,MAAM,IAAIwX,MAAM,gBAAkBzU,GAGtC,OAAOs+B,CACX,EAKA,MAAMuP,EAAkBp3C,OAAO2I,OAAO,MAItC,CACI,gBACA,cACA,gBACA,oBACA,mBACA,kBACA,WACA,4BACA,YACA,cACA,oBACA,gBACA,eACA,mBACA,YACA,eACA,oBACA,eACA,cACA,cACA,mBACA,YACA,aACA,aACA,sBACA,mBACA,eACA,YACA,YACA,YACA,gBACA,sBACA,iBACA,OACA,OACA,qBACA,mBACA,mBACA,mBACA,eACA,cACA,eACA,cACA,eACA,iBACA,cACA,UACA,UACA,aACA,UACA,aACA,mBACA,mBACA,cACFgE,SAASR,GAASirC,EAAgBjrC,GAAQA,IAE5CirC,EAA2B,UAAI,aAC/BA,EAA2B,UAAI,aAC/BA,EAA8B,aAAI,gBAClCA,EAA2B,UAAI,aAC/BA,EAA2B,UAAI,aAC/BA,EAA4B,WAAI,cAChCA,EAAyB,QAAI,WAC7BA,EAAyB,QAAI,WAC7BA,EAA0B,SAAI,YAE9B,MAAMjH,EAAiB,IAAIkH,MAAMD,EAAiB,CAC9Cj3C,IAAG,CAAC4L,EAAOI,IAKF87B,EAAEqP,2BACHnrC,KAAQJ,EACDA,EAAMI,GAGTJ,EAAMI,GAAQA,EAAKY,QAAQ,SAAU,OAAOmM,cALV/M,IAUlDnM,OAAOC,eAAegoC,EAAG,iBAAkB,CACvC/nC,YAAY,EACZS,MAAOwvC,EACPn1B,UAAU,IAIdhb,OAAOC,eAAegoC,EAAG,6BAA8B,CACnD/nC,YAAY,EACZS,OAAO,EACPqa,UAAU,IAOditB,EAAEoI,YAAc,SAASlkC,GAErB,IAA2B,IAAvBA,EAAK8B,QAAQ,KAAa,CAC1B,IAAIspC,EAAcprC,EAAK7G,MAAM,KAC7B,MAAO,CACHga,GAAIA,EAAGi4B,EAAY,IACnBnH,MAAOmH,EAAY,GAE3B,CAEA,MAAO,CACHj4B,GAAI,KACJ8wB,MAAOjkC,EAEf,EAIA87B,EAAEuP,wBAA0B,QAM5BvP,EAAEwP,eAAiB,mBAEnBxP,EAAEyP,uBAAyB,sBAC3BzP,EAAE0P,wBAA0B,0BAC5B1P,EAAE2P,qBAAuB,uBACzB3P,EAAE4P,oBAAsB,sBAExB5P,EAAEkD,wBAA0B,SAASH,GAGjC,IAAI8M,EAAuB7P,EAAE8C,kBAI7B,MAAMgN,EAAmB/M,GAAaA,EAAU5lC,MAAM6iC,EAAEwP,gBACxD,IAAKM,EAED,OAAOD,EAGX,MAAME,EAAaD,EAAiBvxC,OACpC,IAAK,IAAIsV,EAAI,EAAGA,EAAIk8B,EAAYl8B,IAAK,CAEjC,MAGMm8B,EAHiBF,EAAiBj8B,GAGM1W,MAAM6iC,EAAEyP,wBACtD,GAAIO,EAAwB,CAExB,IAAI7wB,EAAIC,EAAIwD,EAAIC,EAAIhJ,EAChBsxB,EAAMnL,EAAE8C,kBACZ,MAAMmN,EAAoBD,EAAuB,GAAG/+B,cAC9CjD,EAAOgiC,EAAuB,GAAG3yC,MAAM2iC,EAAEuP,yBAC/C,OAAQU,GAEJ,IAAK,QACD9wB,EAAK9C,WAAWrO,EAAK,IACrBoR,OAAkB5f,IAAZwO,EAAK,GAAoBmR,EAAK9C,WAAWrO,EAAK,IACpDm9B,EAAMA,EAAI+E,gBAAgB/wB,EAAIC,GAC9B,MAEJ,IAAK,YACDwD,EAAKvG,WAAWrO,EAAK,IACrB6U,EAAKxG,WAAWrO,EAAK,IACrBm9B,EAAMA,EAAIvrB,UAAUgD,EAAIC,GACxB,MAEJ,IAAK,SACDhJ,EAAQwC,WAAWrO,EAAK,IACxB4U,EAAKvG,WAAWrO,EAAK,KAAO,EAC5B6U,EAAKxG,WAAWrO,EAAK,KAAO,EAExBm9B,EADO,IAAPvoB,GAAmB,IAAPC,EACNsoB,EAAIvrB,UAAUgD,EAAIC,GAAI/D,OAAOjF,GAAO+F,WAAWgD,GAAKC,GAEpDsoB,EAAIrsB,OAAOjF,GAErB,MAEJ,IAAK,QACDA,EAAQwC,WAAWrO,EAAK,IACxBm9B,EAAMA,EAAIgF,MAAMt2B,GAChB,MAEJ,IAAK,QACDA,EAAQwC,WAAWrO,EAAK,IACxBm9B,EAAMA,EAAIiF,MAAMv2B,GAChB,MAEJ,IAAK,SACDsxB,EAAIziC,EAAI2T,WAAWrO,EAAK,IACxBm9B,EAAIxiC,EAAI0T,WAAWrO,EAAK,IACxBm9B,EAAIroB,EAAIzG,WAAWrO,EAAK,IACxBm9B,EAAItnB,EAAIxH,WAAWrO,EAAK,IACxBm9B,EAAIl0B,EAAIoF,WAAWrO,EAAK,IACxBm9B,EAAIjsB,EAAI7C,WAAWrO,EAAK,IACxB,MAEJ,QACI,SAIR6hC,EAAuBA,EAAqBhN,SAASsI,EACzD,CAEJ,CACA,OAAO0E,CACX,EAEA7P,EAAEoD,wBAA0B,SAASJ,GAGjC,OAFAA,IAAWA,GAAS,GAEb,gBACWxjC,IAAbwjC,EAAOt6B,EAAkBs6B,EAAOt6B,EAAI,GAAK,UAC5BlJ,IAAbwjC,EAAOr6B,EAAkBq6B,EAAOr6B,EAAI,GAAK,UAC5BnJ,IAAbwjC,EAAOlgB,EAAkBkgB,EAAOlgB,EAAI,GAAK,UAC5BtjB,IAAbwjC,EAAOnf,EAAkBmf,EAAOnf,EAAI,GAAK,UAC5BrkB,IAAbwjC,EAAO/rB,EAAkB+rB,EAAO/rB,EAAI,GAAK,UAC5BzX,IAAbwjC,EAAO9jB,EAAkB8jB,EAAO9jB,EAAI,GACrC,GACR,EAEA8gB,EAAE0D,qBAAuB,SAASX,GAE9B,IAAInjB,EAAWd,EAAQxF,EAEvB,GAAIypB,EAAW,CAEX,IAAIsN,EAAYrQ,EAAEuP,wBAGlB,GAAIxM,EAAU79B,OAAOc,QAAQ,WAAa,EAAG,CAKzC,IAAIg9B,EAAShD,EAAEkD,wBAAwBH,GACnCuN,EAAmBtQ,EAAE+N,gBAAgB/K,GAGzCpjB,EAAY,CAAC0wB,EAAiBC,WAAYD,EAAiBE,YAC3Dl3B,EAAQ,CAACg3B,EAAiBG,OAAQH,EAAiBI,QACnD5xB,EAAS,CAACwxB,EAAiBrC,UAG3B,IAAI0C,EAAkB,GACD,IAAjB/wB,EAAU,IAA6B,IAAjBA,EAAU,IAChC+wB,EAAgBhyC,KAAK,aAAeihB,EAAY,KAEnC,IAAbtG,EAAM,IAAyB,IAAbA,EAAM,IACxBq3B,EAAgBhyC,KAAK,SAAW2a,EAAQ,KAE1B,IAAdwF,EAAO,IACP6xB,EAAgBhyC,KAAK,UAAYmgB,EAAS,KAE9CikB,EAAY4N,EAAgB90C,KAAK,IAErC,KAAO,CAKH,MAAM+0C,EAAiB7N,EAAU5lC,MAAM6iC,EAAE0P,yBACrCkB,IACAhxB,EAAYgxB,EAAe,GAAGvzC,MAAMgzC,IAExC,MAAMQ,EAAc9N,EAAU5lC,MAAM6iC,EAAE2P,sBAClCkB,IACA/xB,EAAS+xB,EAAY,GAAGxzC,MAAMgzC,IAElC,MAAMS,EAAa/N,EAAU5lC,MAAM6iC,EAAE4P,qBACjCkB,IACAx3B,EAAQw3B,EAAW,GAAGzzC,MAAMgzC,GAEpC,CACJ,CAEA,IAAIlxB,EAAM7F,GAASA,EAAM,GAAM+C,WAAW/C,EAAM,IAAM,EAEtD,MAAO,CACH5gB,MAAOqqC,EACPnjB,UAAW,CACPgD,GAAKhD,GAAaA,EAAU,GAAMvE,SAASuE,EAAU,GAAI,IAAM,EAC/DiD,GAAKjD,GAAaA,EAAU,GAAMvE,SAASuE,EAAU,GAAI,IAAM,GAEnEd,OAAQ,CACJjF,MAAQiF,GAAUA,EAAO,GAAMzD,SAASyD,EAAO,GAAI,IAAM,EACzD8kB,GAAK9kB,GAAUA,EAAO,GAAMzD,SAASyD,EAAO,GAAI,SAAMtf,EACtDqkC,GAAK/kB,GAAUA,EAAO,GAAMzD,SAASyD,EAAO,GAAI,SAAMtf,GAE1D8Z,MAAO,CACH6F,GAAIA,EACJC,GAAK9F,GAASA,EAAM,GAAM+C,WAAW/C,EAAM,IAAM6F,GAG7D,EAEA6gB,EAAE+Q,oBAAsB,SAAS/N,EAAQjlB,GAIrC,MAAO,CAAE7C,EAFA6C,EAAM7C,EAAI8nB,EAAOt6B,EAAIqV,EAAMhD,EAAIioB,EAAOlgB,EAAI,EAEnC/H,EADPgD,EAAM7C,EAAI8nB,EAAOr6B,EAAIoV,EAAMhD,EAAIioB,EAAOnf,EAAI,EAEvD,EAEAmc,EAAE+N,gBAAkB,SAAS/K,GAKzB,IAAIgO,EAAKhR,EAAE+Q,oBAAoB/N,EAAQ,CAAE9nB,EAAG,EAAGH,EAAG,IAC9Ck2B,EAAKjR,EAAE+Q,oBAAoB/N,EAAQ,CAAE9nB,EAAG,EAAGH,EAAG,IAG9Co1B,EAAU,IAAM92B,EAAMqB,EAAMs2B,EAAGj2B,EAAGi2B,EAAG91B,GAAK,GAC1Ck1B,EAAU,IAAM/2B,EAAMqB,EAAMu2B,EAAGl2B,EAAGk2B,EAAG/1B,GAEzC,MAAO,CAEHq1B,WAAYvN,EAAO/rB,EACnBu5B,WAAYxN,EAAO9jB,EACnBuxB,OAAQh1B,EAAKunB,EAAOt6B,EAAIs6B,EAAOt6B,EAAIs6B,EAAOr6B,EAAIq6B,EAAOr6B,GACrD+nC,OAAQj1B,EAAKunB,EAAOlgB,EAAIkgB,EAAOlgB,EAAIkgB,EAAOnf,EAAImf,EAAOnf,GACrDssB,MAAOA,EACPC,MAAOA,EACPnC,SAAUkC,EAElB,EAIAnQ,EAAEkR,cAAgB,SAASlO,GAEvB,IAAIt6B,EAAGC,EAAGma,EAAGe,EASb,OARImf,GACAt6B,EAAIs3B,EAAEiD,YAAYD,EAAOt6B,GAAK,EAAIs6B,EAAOt6B,EACzCmb,EAAImc,EAAEiD,YAAYD,EAAOnf,GAAK,EAAImf,EAAOnf,EACzClb,EAAIq6B,EAAOr6B,EACXma,EAAIkgB,EAAOlgB,GAEXpa,EAAImb,EAAI,EAEL,CACH1E,GAAIxW,EAAI8S,EAAK/S,EAAIA,EAAIC,EAAIA,GAAKD,EAC9B0W,GAAI0D,EAAIrH,EAAKqH,EAAIA,EAAIe,EAAIA,GAAKA,EAEtC,EAIAmc,EAAEmR,eAAiB,SAASnO,GAExB,IAAIpoB,EAAI,CAAEM,EAAG,EAAGH,EAAG,GAKnB,OAJIioB,IACApoB,EAAIolB,EAAE+Q,oBAAoB/N,EAAQpoB,IAG/B,CACHf,MAAO,GAAiB,GAAQa,EAAME,EAAEG,EAAGH,EAAEM,IAAM,IAE3D,EAIA8kB,EAAEoR,kBAAoB,SAASpO,GAE3B,MAAO,CACHpgB,GAAKogB,GAAUA,EAAO/rB,GAAM,EAC5B4L,GAAKmgB,GAAUA,EAAO9jB,GAAM,EAEpC,EAEA8gB,EAAEG,IAAM,SAAS3iC,GAEb,OAAOA,aAAkBwiC,CAC7B,EAGAA,EAAEqR,WAAarR,EAAEG,IAIjBH,EAAEuC,qBAAuB,SAAS1sB,GAC9B,QAAKA,IACLA,EAAOmqB,EAAEyC,OAAO5sB,cAEOy7B,YAA2C,mBAAtBz7B,EAAK6sB,YACrD,EAEA,IAAI6O,EAAcvR,EAAE,OAAOnqB,KA21B3B,OAz1BAmqB,EAAE8C,gBAAkB,SAASE,GAEzB,IAAIwO,EAAYD,EAAYzO,kBAC5B,IAAK,IAAI2O,KAAazO,EAClBwO,EAAUC,GAAazO,EAAOyO,GAGlC,OAAOD,CACX,EAEAxR,EAAEsD,mBAAqB,SAASN,GAE5B,OAAKhD,EAAEiD,YAAYD,GASZuO,EAAYjO,sBAPTN,aAAkB0O,YACpB1O,EAAShD,EAAE8C,gBAAgBE,IAGxBuO,EAAYI,6BAA6B3O,GAIxD,EAEAhD,EAAEqK,eAAiB,SAASnvB,EAAGH,GAE3B,IAAIH,EAAI22B,EAAYlH,iBAGpB,OAFAzvB,EAAEM,EAAIA,EACNN,EAAEG,EAAIA,EACCH,CACX,EAEAolB,EAAEwE,cAAgB,SAASnnB,EAAG2lB,GAE1B,IAAIpoB,EAAI22B,EAAYlH,iBAEpBzvB,EAAEM,EAAImC,EAAEnC,EACRN,EAAEG,EAAIsC,EAAEtC,EACR,IAAI62B,EAAUh3B,EAAE2vB,gBAAgBvH,GAEhCpoB,EAAEM,EAAImC,EAAEnC,EAAImC,EAAEE,MACd3C,EAAEG,EAAIsC,EAAEtC,EACR,IAAI82B,EAAUj3B,EAAE2vB,gBAAgBvH,GAEhCpoB,EAAEM,EAAImC,EAAEnC,EAAImC,EAAEE,MACd3C,EAAEG,EAAIsC,EAAEtC,EAAIsC,EAAEG,OACd,IAAIs0B,EAAUl3B,EAAE2vB,gBAAgBvH,GAEhCpoB,EAAEM,EAAImC,EAAEnC,EACRN,EAAEG,EAAIsC,EAAEtC,EAAIsC,EAAEG,OACd,IAAIu0B,EAAUn3B,EAAE2vB,gBAAgBvH,GAE5Ble,EAAO9V,EAAI4iC,EAAQ12B,EAAG22B,EAAQ32B,EAAG42B,EAAQ52B,EAAG62B,EAAQ72B,GACpD8J,EAAO1K,EAAIs3B,EAAQ12B,EAAG22B,EAAQ32B,EAAG42B,EAAQ52B,EAAG62B,EAAQ72B,GACpD6J,EAAO/V,EAAI4iC,EAAQ72B,EAAG82B,EAAQ92B,EAAG+2B,EAAQ/2B,EAAGg3B,EAAQh3B,GACpDkK,EAAO3K,EAAIs3B,EAAQ72B,EAAG82B,EAAQ92B,EAAG+2B,EAAQ/2B,EAAGg3B,EAAQh3B,GAExD,OAAO,IAAI,GAAO+J,EAAMC,EAAMC,EAAOF,EAAMG,EAAOF,EACtD,EAEAib,EAAEgS,eAAiB,SAASp3B,EAAGooB,GAE3B,OAAO,IAAI,GAAQhD,EAAEqK,eAAezvB,EAAEM,EAAGN,EAAEG,GAAGwvB,gBAAgBvH,GAClE,EAEAhD,EAAEiS,cAAgB,SAAShxB,EAAG+hB,GAE1B,OAAO,IAAI,GACPhD,EAAEgS,eAAe/wB,EAAEtU,MAAOq2B,GAC1BhD,EAAEgS,eAAe/wB,EAAErU,IAAKo2B,GAEhC,EAEAhD,EAAEkS,kBAAoB,SAASt3B,EAAGooB,GAE9B,IAAImP,EAAYv3B,aAAa,GAAcA,EAAEkC,OAASlC,EACjDolB,EAAEhiC,QAAQm0C,KAAWA,EAAW,IAErC,IADA,IAAIC,EAAY,GACPv+B,EAAI,EAAGkJ,EAAIo1B,EAAS5zC,OAAQsV,EAAIkJ,EAAGlJ,IAAKu+B,EAAUv+B,GAAKmsB,EAAEgS,eAAeG,EAASt+B,GAAImvB,GAC9F,OAAO,IAAI,GAAWoP,EAC1B,EAIApS,EAAEqS,cAAgB,SAASC,GAGvB,IAFA,IAAIr9B,EAAM,CAAC,EACPs9B,EAASD,EAAYj1C,MAAM,KACtBwW,EAAI,EAAGA,EAAI0+B,EAAOh0C,OAAQsV,IAAK,CACpC,IACI2+B,EADQD,EAAO1+B,GACFxW,MAAM,KACvB4X,EAAIu9B,EAAK,GAAGttC,QAAUstC,EAAK,GAAGttC,MAClC,CACA,OAAO+P,CACX,EAGA+qB,EAAEyS,oBAAsB,SAASC,EAAaC,EAAaC,EAAYC,GAEnE,IAAIC,EAAY,EAAIz5B,EAAK,KACrB0M,EAAK2sB,EACL1sB,EAAK2sB,EACLI,EAAKH,EACLtvB,EAAKuvB,EACLG,GAAM1vB,EAAKyvB,IAAOC,EAAKD,EAAIA,EAAKzvB,EAAIA,EAAK0vB,GAAK1vB,EAAKyvB,GACnDE,EAAKD,EAAK35B,EAAK,IAAM,IACrB65B,EAAK14B,EAAIu4B,GACTI,EAAK14B,EAAIs4B,GACTnb,EAAKpd,EAAI8I,GACT8vB,EAAK34B,EAAI6I,GAEb,OAAQ0vB,GAAMF,EACP/sB,EACG,MAAQC,EACR,IAAMA,EAAK,IAAMA,EAAK,aAAgBA,EACtC,IAAMA,EAAK,IAAMA,EAAK,YAAcA,EACpC,MAAQD,EACR,IAAMA,EAAK,IAAMA,EAAK,aAAgBA,EACtC,IAAMA,EAAK,IAAMA,EAAK,YAAcA,EACpC,IACA,MAAQC,EACR,IAAMA,EAAK,IAAMA,EAAK,aAAgBA,EACtC,IAAMA,EAAK,IAAMA,EAAK,YAAcA,EACpC,IACHD,EACG,IAAMC,EAAKktB,EAAK,IAAMltB,EAAKmtB,EAC3B,IAAMntB,EAAK,IAAMA,EAAK,MAAQitB,EAAK,MAAQjtB,EAAK4R,EAAK,IAAM5R,EAAKotB,EAChE,IAAMrtB,EAAK6R,EAAK,IAAM7R,EAAKqtB,EAC3B,IAAMrtB,EAAK,IAAMA,EAAK,MAAQktB,EAAK,MAAQltB,EAAKmtB,EAAK,IAAMntB,EAAKotB,EAChE,IACA,IAAMntB,EAAKktB,EAAK,IAAMltB,EAAKmtB,EAC3B,IAAMntB,EAAK,IAAMA,EAAK,MAAQitB,EAAK,MAAQjtB,EAAK4R,EAAK,IAAM5R,EAAKotB,EADhE,OAId,EAKApT,EAAEqT,WAAa,SAAS3qC,EAAGC,GAEvB,IAAK,IAAIs5B,KAAQt5B,EAEA,UAATs5B,EAEAv5B,EAAEu5B,GAAQv5B,EAAEu5B,GAAQv5B,EAAEu5B,GAAQ,IAAMt5B,EAAEs5B,GAAQt5B,EAAEs5B,GAChC,UAATA,EAEHjC,EAAE/gC,SAASyJ,EAAEu5B,KAAUjC,EAAE/gC,SAAS0J,EAAEs5B,IAEpCv5B,EAAEu5B,GAAQjC,EAAEqT,WAAW3qC,EAAEu5B,GAAOt5B,EAAEs5B,IAC3BjC,EAAE/gC,SAASyJ,EAAEu5B,IAGpBv5B,EAAEu5B,GAAQjC,EAAEqT,WAAW3qC,EAAEu5B,GAAOjC,EAAEqS,cAAc1pC,EAAEs5B,KAC3CjC,EAAE/gC,SAAS0J,EAAEs5B,IAEpBv5B,EAAEu5B,GAAQjC,EAAEqT,WAAWrT,EAAEqS,cAAc3pC,EAAEu5B,IAAQt5B,EAAEs5B,IAGnDv5B,EAAEu5B,GAAQjC,EAAEqT,WAAWrT,EAAEqS,cAAc3pC,EAAEu5B,IAAQjC,EAAEqS,cAAc1pC,EAAEs5B,KAGvEv5B,EAAEu5B,GAAQt5B,EAAEs5B,GAIpB,OAAOv5B,CACX,EAEAs3B,EAAE6G,eAAiB,SAASroB,EAAG0jB,EAAa9gB,GAExC8gB,EAAcA,GAAe,GAU7B,IAPA,IAEIoR,EAEAC,EACAC,EALAp1B,GAFJgD,EAAMA,GAAO,CAAC,GAEGhD,QAAU,EACvBq1B,EAAY,GAEZx+B,EAAM,GAIDpB,EAAI,EAAGA,EAAI2K,EAAEjgB,OAAQsV,IAAK,CAE/B0/B,EAAOt+B,EAAIpB,GAAK2K,EAAE3K,GAElB,IAAK,IAAIC,EAAI,EAAGA,EAAIouB,EAAY3jC,OAAQuV,IAAK,CAEzC,IAAI2tB,EAAaS,EAAYpuB,GACzBnH,EAAQ80B,EAAW90B,MAAQyR,EAC3BxR,EAAM60B,EAAW70B,IAAMwR,EAEvBvK,GAAKlH,GAASkH,EAAIjH,IAEdozB,EAAE/gC,SAASs0C,GAEXA,EAAKtT,MAAQD,EAAEqT,WAAWrT,EAAEqT,WAAW,CAAC,EAAGE,EAAKtT,OAAQwB,EAAWxB,OAEnEsT,EAAOt+B,EAAIpB,GAAK,CAAE2K,EAAGA,EAAE3K,GAAIosB,MAAOwB,EAAWxB,OAE7C7e,EAAI8f,2BACHqS,EAAKrR,cAAgBqR,EAAKrR,YAAc,KAAKvjC,KAAKmV,GAG/D,EAEA0/B,EAAOv+B,EAAIpB,EAAI,IAMJmsB,EAAE/gC,SAASs0C,IAASvT,EAAE/gC,SAASu0C,GAGlCE,KAAKC,UAAUJ,EAAKtT,SAAWyT,KAAKC,UAAUH,EAAKvT,OACnDqT,EAAM90B,GAAK+0B,EAAK/0B,GAEhBi1B,EAAU90C,KAAK20C,GACfA,EAAQC,GAGLvT,EAAE/gC,SAASs0C,IAKXvT,EAAE/gC,SAASu0C,IAHlBC,EAAU90C,KAAK20C,GACfA,EAAQC,GASRD,GAASA,GAAS,IAAMC,EAxBxBD,EAAQC,CA0BhB,CAMA,OAJID,GACAG,EAAU90C,KAAK20C,GAGZG,CACX,EAEAzT,EAAEoH,uBAAyB,SAASlF,EAAazjC,GAE7C,IAAIirC,EAAQ,GAYZ,OAVIxH,GAEAA,EAAYx9B,SAAQ,SAAS+8B,GAErBA,EAAW90B,MAAQlO,GAASA,GAASgjC,EAAW70B,KAChD88B,EAAM/qC,KAAK8iC,EAEnB,IAGGiI,CACX,EAEA1J,EAAE4T,8BAAgC,SAAS1R,EAAav1B,EAAOC,GAE3D,IAAI88B,EAAQ,GAYZ,OAVIxH,GAEAA,EAAYx9B,SAAQ,SAAS+8B,IAEpB90B,GAAS80B,EAAW90B,OAASA,EAAQ80B,EAAW70B,KAASA,EAAM60B,EAAW90B,OAASC,GAAO60B,EAAW70B,KAAS60B,EAAW90B,OAASA,GAAS80B,EAAW70B,IAAMA,IAC7J88B,EAAM/qC,KAAK8iC,EAEnB,IAGGiI,CACX,EAGA1J,EAAE6T,iBAAmB,SAAS3R,EAAazjC,EAAO2f,GAe9C,OAbI8jB,GAEAA,EAAYx9B,SAAQ,SAAS+8B,GAErBA,EAAW90B,MAAQlO,GAASgjC,EAAW70B,KAAOnO,EAC9CgjC,EAAW70B,KAAOwR,EACXqjB,EAAW90B,OAASlO,IAC3BgjC,EAAW90B,OAASyR,EACpBqjB,EAAW70B,KAAOwR,EAE1B,IAGG8jB,CACX,EAEAlC,EAAEkN,sBAAwB,SAAS3rB,GAO/B,MAJQ,CACJ,KAFJA,EAAOye,EAAEze,IAEK0gB,KAAK,MAAO1gB,EAAK0gB,KAAK,MAChC,IAAK1gB,EAAK0gB,KAAK,MAAO1gB,EAAK0gB,KAAK,OAClCpmC,KAAK,IAEX,EAEAmkC,EAAEmN,yBAA2B,SAASvO,GAElC,IAAI9hB,EAASkjB,EAAEyN,qBAAqB7O,GACpC,OAAsB,IAAlB9hB,EAAOve,OAAqB,KAEzByhC,EAAE8T,gBAAgBh3B,GAAU,IACvC,EAEAkjB,EAAEoN,0BAA4B,SAASpX,GAEnC,IAAIlZ,EAASkjB,EAAEyN,qBAAqBzX,GACpC,OAAsB,IAAlBlZ,EAAOve,OAAqB,KAEzByhC,EAAE8T,gBAAgBh3B,EAC7B,EAEAkjB,EAAE8T,gBAAkB,SAASh3B,GAEzB,IAAK,IAAIjJ,EAAI,EAAGkJ,EAAID,EAAOve,OAAQsV,EAAIkJ,EAAGlJ,IACtCiJ,EAAOjJ,GAAKiJ,EAAOjJ,GAAGqH,EAAI,IAAM4B,EAAOjJ,GAAGkH,EAG9C,MAAO,KAAO+B,EAAOjhB,KAAK,KAC9B,EAEAmkC,EAAEyN,qBAAuB,SAAS53B,GAG9B,IAAIiH,EAAS,GACTi3B,GAFJl+B,EAAOmqB,EAAEyC,OAAO5sB,IAEMiH,OACtB,GAAIi3B,EACA,IAAK,IAAIlgC,EAAI,EAAGkJ,EAAIg3B,EAAWC,cAAengC,EAAIkJ,EAAGlJ,IACjDiJ,EAAOne,KAAKo1C,EAAWE,QAAQpgC,IAIvC,OAAOiJ,CACX,EAEAkjB,EAAEkU,MAAQ,QAEVlU,EAAEsN,wBAA0B,SAAS6G,GAEjCA,EAASnU,EAAEmU,GACX,IAAIvQ,EAAKvnB,WAAW83B,EAAOlS,KAAK,QAAU,EACtC4B,EAAKxnB,WAAW83B,EAAOlS,KAAK,QAAU,EACtC5kB,EAAIhB,WAAW83B,EAAOlS,KAAK,MAC3BmS,EAAK/2B,EAAI2iB,EAAEkU,MAUf,MARQ,CACJ,IAAKtQ,EAAIC,EAAKxmB,EACd,IAAKumB,EAAKwQ,EAAIvQ,EAAKxmB,EAAGumB,EAAKvmB,EAAGwmB,EAAKuQ,EAAIxQ,EAAKvmB,EAAGwmB,EAC/C,IAAKD,EAAKvmB,EAAGwmB,EAAKuQ,EAAIxQ,EAAKwQ,EAAIvQ,EAAKxmB,EAAGumB,EAAIC,EAAKxmB,EAChD,IAAKumB,EAAKwQ,EAAIvQ,EAAKxmB,EAAGumB,EAAKvmB,EAAGwmB,EAAKuQ,EAAIxQ,EAAKvmB,EAAGwmB,EAC/C,IAAKD,EAAKvmB,EAAGwmB,EAAKuQ,EAAIxQ,EAAKwQ,EAAIvQ,EAAKxmB,EAAGumB,EAAIC,EAAKxmB,EAChD,KACFxhB,KAAK,IAEX,EAEAmkC,EAAEqN,yBAA2B,SAASlqB,GAElCA,EAAU6c,EAAE7c,GACZ,IAAIygB,EAAKvnB,WAAW8G,EAAQ8e,KAAK,QAAU,EACvC4B,EAAKxnB,WAAW8G,EAAQ8e,KAAK,QAAU,EACvCze,EAAKnH,WAAW8G,EAAQ8e,KAAK,OAC7Bxe,EAAKpH,WAAW8G,EAAQ8e,KAAK,QAAUze,EACvC6wB,EAAM7wB,EAAKwc,EAAEkU,MACbI,EAAM7wB,EAAKuc,EAAEkU,MAUjB,MARQ,CACJ,IAAKtQ,EAAIC,EAAKpgB,EACd,IAAKmgB,EAAKyQ,EAAKxQ,EAAKpgB,EAAImgB,EAAKpgB,EAAIqgB,EAAKyQ,EAAK1Q,EAAKpgB,EAAIqgB,EACpD,IAAKD,EAAKpgB,EAAIqgB,EAAKyQ,EAAK1Q,EAAKyQ,EAAKxQ,EAAKpgB,EAAImgB,EAAIC,EAAKpgB,EACpD,IAAKmgB,EAAKyQ,EAAKxQ,EAAKpgB,EAAImgB,EAAKpgB,EAAIqgB,EAAKyQ,EAAK1Q,EAAKpgB,EAAIqgB,EACpD,IAAKD,EAAKpgB,EAAIqgB,EAAKyQ,EAAK1Q,EAAKyQ,EAAKxQ,EAAKpgB,EAAImgB,EAAIC,EAAKpgB,EACpD,KACF5nB,KAAK,IAEX,EAEAmkC,EAAEuN,sBAAwB,SAASvqB,GAI/B,OAFAA,EAAOgd,EAAEhd,GAEFgd,EAAEuU,WAAW,CAChBr5B,EAAGmB,WAAW2G,EAAKif,KAAK,OAAS,EACjClnB,EAAGsB,WAAW2G,EAAKif,KAAK,OAAS,EACjC1kB,MAAOlB,WAAW2G,EAAKif,KAAK,WAAa,EACzCzkB,OAAQnB,WAAW2G,EAAKif,KAAK,YAAc,EAC3Cze,GAAInH,WAAW2G,EAAKif,KAAK,QAAU,EACnCxe,GAAIpH,WAAW2G,EAAKif,KAAK,QAAU,GAE3C,EAOAjC,EAAEuU,WAAa,SAASl3B,GAEpB,IACInC,EAAImC,EAAEnC,EACNH,EAAIsC,EAAEtC,EACNwC,EAAQF,EAAEE,MACVC,EAASH,EAAEG,OACXg3B,EAAQxlC,EAAIqO,EAAEmG,IAAMnG,EAAE,WAAa,EAAGE,EAAQ,GAC9Ck3B,EAAWzlC,EAAIqO,EAAEmG,IAAMnG,EAAE,cAAgB,EAAGE,EAAQ,GACpDm3B,EAAQ1lC,EAAIqO,EAAEoG,IAAMpG,EAAE,WAAa,EAAGG,EAAS,GAC/Cm3B,EAAW3lC,EAAIqO,EAAEoG,IAAMpG,EAAE,cAAgB,EAAGG,EAAS,GA0BzD,OAxBIg3B,GAASC,GAAYC,GAASC,EAC1B,CACA,IAAKz5B,EAAGH,EAAI25B,EACZ,IAAKl3B,EAASk3B,EAAQC,EACtB,IAAKF,EAAUE,EAAU,EAAG,EAAG,EAAGF,EAAUE,EAC5C,IAAKp3B,EAAQ,EAAIk3B,EACjB,IAAKA,EAAUE,EAAU,EAAG,EAAG,EAAGF,GAAWE,EAC7C,MAAOn3B,EAASm3B,EAAWD,GAC3B,IAAKF,EAAOE,EAAO,EAAG,EAAG,GAAIF,GAAQE,EACrC,MAAOn3B,EAAQ,EAAIi3B,GACnB,IAAKA,EAAOE,EAAO,EAAG,EAAG,GAAIF,EAAOE,EACpC,KAGA,CACA,IAAKx5B,EAAGH,EACR,IAAKG,EAAIqC,EACT,IAAKxC,EAAIyC,EACT,IAAKtC,EACL,IAAKH,EACL,MAIClf,KAAK,IAClB,EAMAmkC,EAAE8I,kBAAoB,WAElB,IAAI8L,EAAS,2CACTC,EAAc,IAAI74C,OAAO,WAAa44C,EAAS,wCAA0CA,EAAS,QAAUA,EAAS,QAAS,MAC9HE,EAAa,IAAI94C,OAAO,qCAAuC44C,EAAS,QAAUA,EAAS,KAAM,MAEjG7U,EAAOjxB,KACPuK,EAAK0mB,EAAK1mB,GACVoB,EAAMslB,EAAKtlB,IACXD,EAAMulB,EAAKvlB,IACXu6B,EAAMhV,EAAKgV,IACXC,EAAOjV,EAAKiV,KACZv5B,EAAOskB,EAAKtkB,KACZS,EAAM6jB,EAAK7jB,IAEf,SAAS+4B,EAAIx4B,EAAIE,EAAIu4B,EAAIC,EAAIz4B,EAAIE,GAE7B,IAAIw4B,EAAM,EAAI,EACVC,EAAM,EAAI,EACd,MAAO,CAAED,EAAM34B,EAAO44B,EAAMH,EAAME,EAAMz4B,EAAO04B,EAAMF,EAAMC,EAAM14B,EAAO24B,EAAMH,EAAME,EAAMx4B,EAAOy4B,EAAMF,EAAKz4B,EAAIE,EACpH,CAEA,SAASkC,EAAO5D,EAAGH,EAAGd,GAIlB,MAAO,CAAEiB,EAFAA,EAAIV,EAAIP,GAASc,EAAIN,EAAIR,GAEnBc,EADNG,EAAIT,EAAIR,GAASc,EAAIP,EAAIP,GAEtC,CAEA,SAASq7B,EAAI74B,EAAIE,EAAI6G,EAAIC,EAAI5J,EAAO07B,EAAgBC,EAAY94B,EAAIE,EAAI+nB,GAGpE,IAGIvoB,EAHAq5B,EAAa,IAALp8B,EAAY,IACpBY,EAAOZ,EAAK,MAASQ,GAAS,GAC9B67B,EAAM,GAGV,GAAK/Q,EA4CDgR,EAAKhR,EAAU,GACfiR,EAAKjR,EAAU,GACff,EAAKe,EAAU,GACfd,EAAKc,EAAU,OA/CH,CAEZloB,GADAL,EAAK0C,EAAOrC,EAAIE,GAAK1C,IACbiB,EACRyB,EAAKP,EAAGrB,EAMR,IAAIG,GAAKuB,GAHTC,GADAN,EAAK0C,EAAOpC,EAAIE,GAAK3C,IACbiB,IAGY,EAChBH,GAAK4B,GAHTC,EAAKR,EAAGrB,IAGY,EAChB4J,EAAMzJ,EAAIA,GAAMsI,EAAKA,GAASzI,EAAIA,GAAM0I,EAAKA,GAE7CkB,EAAI,IAEJnB,GADAmB,EAAIlJ,EAAKkJ,GAETlB,GAAKkB,GAGT,IAAIkxB,EAAMryB,EAAKA,EACXsyB,EAAMryB,EAAKA,EAEXsyB,GAAMR,GAAkBC,GAAe,EAAI,GAAK/5B,EAAKS,GAAM25B,EAAMC,EAAQD,EAAM96B,EAAIA,EAAM+6B,EAAM56B,EAAIA,IAAQ26B,EAAM96B,EAAIA,EAAM+6B,EAAM56B,EAAIA,KACzI,IAAKlT,OAAOm6B,SAAS4T,GAEjB,MAAO,CAACt5B,EAAIE,EAAID,EAAIE,EAAIF,EAAIE,GAGhC,IAAIgnB,EAAOmS,EAAIvyB,EAAKzI,EAAK0I,GAAQhH,EAAKC,GAAM,EACxCmnB,EAAOkS,GAAKtyB,EAAKvI,EAAKsI,GAAQ7G,EAAKC,GAAM,EAEzC+4B,EAAKX,IAAOr4B,EAAKknB,GAAMpgB,GAAIuyB,QAAQ,IACnCJ,EAAKZ,IAAOp4B,EAAKinB,GAAMpgB,GAAIuyB,QAAQ,KAEvCL,EAAOl5B,EAAKmnB,EAAOvqB,EAAKs8B,EAAMA,GAGrB,IAAGA,EAAW,EAALt8B,EAAUs8B,IAF5BC,EAAOl5B,EAAKknB,EAAOvqB,EAAKu8B,EAAMA,GAGrB,IAAGA,EAAW,EAALv8B,EAAUu8B,GAExBJ,GAAeG,EAAKC,IAAKD,GAAgB,EAALt8B,IACnCm8B,GAAeI,EAAKD,IAAKC,GAAgB,EAALv8B,EAE7C,CAOA,IAAI45B,EAAK2C,EAAKD,EACd,GAAIz5B,EAAI+2B,GAAMwC,EAAM,CAChB,IAAIQ,EAAQL,EACRM,EAAQx5B,EACRy5B,EAAQv5B,EAIZ84B,EAAMJ,EAFN54B,EAAKknB,EAAMpgB,EAAKhJ,EADhBo7B,EAAKD,EAAMF,GAASD,GAAeI,EAAKD,EAAO,GAAK,IAEpD/4B,EAAKinB,EAAMpgB,EAAKhJ,EAAIm7B,GACFpyB,EAAIC,EAAI5J,EAAO,EAAG27B,EAAYU,EAAOC,EAAO,CAACP,EAAIK,EAAOrS,EAAIC,GAClF,CAEAoP,EAAK2C,EAAKD,EAEV,IAAI/d,EAAKpd,EAAIm7B,GACTvC,EAAK34B,EAAIk7B,GACT9d,EAAKrd,EAAIo7B,GACTQ,EAAK37B,EAAIm7B,GACTp3B,EAAIu2B,EAAI9B,EAAK,GACboD,EAAM,EAAI,GAAM7yB,EAAKhF,GACrB83B,EAAM,EAAI,GAAM7yB,EAAKjF,GACrB+3B,EAAK,CAAC95B,EAAIE,GACV65B,EAAK,CAAC/5B,EAAM45B,EAAKjD,EAAKz2B,EAAM25B,EAAK1e,GACjC6e,EAAK,CAAC/5B,EAAM25B,EAAKD,EAAKx5B,EAAM05B,EAAKze,GACjC6e,EAAK,CAACh6B,EAAIE,GAKd,GAHA45B,EAAG,GAAM,EAAID,EAAG,GAAMC,EAAG,GACzBA,EAAG,GAAM,EAAID,EAAG,GAAMC,EAAG,GAErB7R,EACA,MAAO,CAAC6R,EAAIC,EAAIC,GAAIhhC,OAAOggC,GAK3B,IAFA,IAAIiB,EAAS,GACTC,GAFJlB,EAAM,CAACc,EAAIC,EAAIC,GAAIhhC,OAAOggC,GAAK75C,OAAOwB,MAAM,MAE/BkB,OACJsV,EAAI,EAAGA,EAAI+iC,EAAI/iC,IACpB8iC,EAAO9iC,GAAMA,EAAI,EAAKiL,EAAO42B,EAAI7hC,EAAI,GAAI6hC,EAAI7hC,GAAIoG,GAAKc,EAAI+D,EAAO42B,EAAI7hC,GAAI6hC,EAAI7hC,EAAI,GAAIoG,GAAKiB,EAE9F,OAAOy7B,CAEf,CAyIA,SAAS/3B,EAAU/Z,GAEf,IAAI+V,EA3GR,SAAwBi8B,GAOpB,GALK94C,MAAMC,QAAQ64C,IAAe94C,MAAMC,QAAQ64C,GAAaA,EAAU,MACnEA,EAjCR,SAAyBC,GAErB,IAAKA,EAAY,OAAO,KAExB,IAAIC,EAAc,CAAEruC,EAAG,EAAGoa,EAAG,EAAG6B,EAAG,EAAG1D,EAAG,EAAGkD,EAAG,EAAGtJ,EAAG,EAAGqgB,EAAG,EAAG1c,EAAG,EAAGw4B,EAAG,EAAG1e,EAAG,GACzEh3B,EAAO,GAsBX,OApBA21C,OAAOH,GAAYhyC,QAAQ+vC,GAAa,SAASnsC,EAAGC,EAAGma,GAEnD,IAAIo0B,EAAS,GACThzC,EAAOyE,EAAEsI,cAWb,IAVA6R,EAAEhe,QAAQgwC,GAAY,SAASpsC,EAAGC,GAC1BA,GAAGuuC,EAAOv4C,MAAMgK,EACxB,IAEc,MAATzE,GAAkBgzC,EAAO34C,OAAS,IACnC+C,EAAK3C,KAAK,CAACgK,GAAG+M,OAAOwhC,EAAO3pC,OAAO,EAAG,KACtCrJ,EAAO,IACPyE,EAAY,MAANA,EAAa,IAAM,KAGtBuuC,EAAO34C,QAAUw4C,EAAY7yC,KAChC5C,EAAK3C,KAAK,CAACgK,GAAG+M,OAAOwhC,EAAO3pC,OAAO,EAAGwpC,EAAY7yC,MAC7C6yC,EAAY7yC,MAEzB,IAEO5C,CACX,CAKoB61C,CAAgBN,KAI3BA,IAAcA,EAAUt4C,OAAQ,MAAO,CAAC,CAAC,IAAK,EAAG,IAWtD,IATA,IAMI64C,EANA1B,EAAM,GACNx6B,EAAI,EACJH,EAAI,EACJs8B,EAAK,EACLC,EAAK,EAILV,EAAKC,EAAUt4C,OACVsV,EAJG,EAIQA,EAAI+iC,EAAI/iC,IAAK,CAE7B,IAAIwJ,EAAI,GACRq4B,EAAI/2C,KAAK0e,GAET,IAMQk6B,EACAzjC,EAPJ0jC,EAAKX,EAAUhjC,GAGnB,IAFAujC,EAAMI,EAAG,KAEEJ,EAAI9N,cAKX,OAJAjsB,EAAE,GAAK+5B,EAAI9N,cAIHjsB,EAAE,IACN,IAAK,IACDA,EAAE,GAAKm6B,EAAG,GACVn6B,EAAE,GAAKm6B,EAAG,GACVn6B,EAAE,GAAKm6B,EAAG,GACVn6B,EAAE,GAAKm6B,EAAG,GACVn6B,EAAE,GAAKm6B,EAAG,GACVn6B,EAAE,IAAMm6B,EAAG,GAAKt8B,EAChBmC,EAAE,IAAMm6B,EAAG,GAAKz8B,EAChB,MAEJ,IAAK,IACDsC,EAAE,IAAMm6B,EAAG,GAAKz8B,EAChB,MAEJ,IAAK,IACDsC,EAAE,IAAMm6B,EAAG,GAAKt8B,EAChB,MAEJ,IAAK,IAKD,IAJAm8B,GAAMG,EAAG,GAAKt8B,EACdo8B,GAAME,EAAG,GAAKz8B,EAEdw8B,EAAKC,EAAGj5C,OACHuV,EAAI,EAAGA,EAAIyjC,EAAIzjC,IAChBuJ,EAAEvJ,IAAM0jC,EAAG1jC,IAAOA,EAAI,EAAKoH,EAAIH,GAEnC,MAEJ,QAEI,IADAw8B,EAAKC,EAAGj5C,OACHuV,EAAI,EAAGA,EAAIyjC,EAAIzjC,IAChBuJ,EAAEvJ,IAAM0jC,EAAG1jC,IAAOA,EAAI,EAAKoH,EAAIH,QAM3C,IADA,IAAI08B,EAAKD,EAAGj5C,OACHw3C,EAAI,EAAGA,EAAI0B,EAAI1B,IACpB14B,EAAE04B,GAAKyB,EAAGzB,GAIlB,OAAQ14B,EAAE,IACN,IAAK,IACDnC,GAAKm8B,EACLt8B,GAAKu8B,EACL,MAEJ,IAAK,IACDp8B,EAAImC,EAAE,GACN,MAEJ,IAAK,IACDtC,EAAIsC,EAAE,GACN,MAEJ,IAAK,IACDg6B,EAAKh6B,EAAEA,EAAE9e,OAAS,GAClB+4C,EAAKj6B,EAAEA,EAAE9e,OAAS,GAClB2c,EAAImC,EAAEA,EAAE9e,OAAS,GACjBwc,EAAIsC,EAAEA,EAAE9e,OAAS,GACjB,MAEJ,QACI2c,EAAImC,EAAEA,EAAE9e,OAAS,GACjBwc,EAAIsC,EAAEA,EAAE9e,OAAS,GAG7B,CAEA,OAAOm3C,CACX,CAIYgC,CAAe7yC,GACnBo7B,EAAQ,CAAE/kB,EAAG,EAAGH,EAAG,EAAG48B,GAAI,EAAGC,GAAI,EAAGxpB,EAAG,EAAGC,EAAG,EAAGwpB,GAAI,KAAMC,GAAI,MAElE,SAASC,EAAYlzC,EAAMgf,EAAGm0B,GAE1B,IAAIC,EAAIC,EAER,IAAKrzC,EAAM,MAAO,CAAC,IAAKgf,EAAE3I,EAAG2I,EAAE9I,EAAG8I,EAAE3I,EAAG2I,EAAE9I,EAAG8I,EAAE3I,EAAG2I,EAAE9I,GAOnD,OALMlW,EAAK,IAAM,CAAEszC,EAAG,EAAGC,EAAG,KACxBv0B,EAAEg0B,GAAK,KACPh0B,EAAEi0B,GAAK,MAGHjzC,EAAK,IACT,IAAK,IACDgf,EAAEuK,EAAIvpB,EAAK,GACXgf,EAAEwK,EAAIxpB,EAAK,GACX,MAEJ,IAAK,IAKGA,EAJwB,IAAxBwX,WAAWxX,EAAK,KAAqC,IAAxBwX,WAAWxX,EAAK,IAItC,CAAC,IAAKA,EAAK,GAAIA,EAAK,IAEpB,CAAC,KAAK6Q,OAAO4/B,EAAIpnC,MAAM,EAAG,CAAC2V,EAAE3I,EAAG2I,EAAE9I,GAAGrF,OAAO7Q,EAAKgD,MAAM,MAElE,MAEJ,IAAK,IACY,MAATmwC,GAAyB,MAATA,GAChBC,EAAY,EAANp0B,EAAE3I,EAAS2I,EAAE8zB,GACnBO,EAAY,EAANr0B,EAAE9I,EAAS8I,EAAE+zB,KAEnBK,EAAKp0B,EAAE3I,EACPg9B,EAAKr0B,EAAE9I,GAEXlW,EAAO,CAAC,IAAKozC,EAAIC,GAAIxiC,OAAO7Q,EAAKgD,MAAM,IACvC,MAEJ,IAAK,IACY,MAATmwC,GAAyB,MAATA,GAChBn0B,EAAEg0B,GAAY,EAANh0B,EAAE3I,EAAS2I,EAAEg0B,GACrBh0B,EAAEi0B,GAAY,EAANj0B,EAAE9I,EAAS8I,EAAEi0B,KAErBj0B,EAAEg0B,GAAKh0B,EAAE3I,EACT2I,EAAEi0B,GAAKj0B,EAAE9I,GAEblW,EAAO,CAAC,KAAK6Q,OAAOu/B,EAAIpxB,EAAE3I,EAAG2I,EAAE9I,EAAG8I,EAAEg0B,GAAIh0B,EAAEi0B,GAAIjzC,EAAK,GAAIA,EAAK,KAC5D,MAEJ,IAAK,IACDgf,EAAEg0B,GAAKhzC,EAAK,GACZgf,EAAEi0B,GAAKjzC,EAAK,GACZA,EAAO,CAAC,KAAK6Q,OAAOu/B,EAAIpxB,EAAE3I,EAAG2I,EAAE9I,EAAGlW,EAAK,GAAIA,EAAK,GAAIA,EAAK,GAAIA,EAAK,KAClE,MAEJ,IAAK,IACDA,EAAO,CAAC,KAAK6Q,OAAO7Q,EAAK,GAAIgf,EAAE9I,GAC/B,MAEJ,IAAK,IACDlW,EAAO,CAAC,KAAK6Q,OAAOmO,EAAE3I,EAAGrW,EAAK,IAUtC,OAAOA,CACX,CAEA,SAASwzC,EAAOC,EAAIzkC,GAEhB,GAAIykC,EAAGzkC,GAAGtV,OAAS,EAAG,CAElB+5C,EAAGzkC,GAAG0kC,QAGN,IAFA,IAAIC,EAAKF,EAAGzkC,GAEL2kC,EAAGj6C,QACNk6C,EAAM5kC,GAAK,IACXykC,EAAG/qC,OAAOsG,IAAK,EAAG,CAAC,KAAK6B,OAAO8iC,EAAGjrC,OAAO,EAAG,KAGhD+qC,EAAG/qC,OAAOsG,EAAG,GACb+iC,EAAKh8B,EAAErc,MACX,CACJ,CAOA,IALA,IAAIk6C,EAAQ,GACRC,EAAS,GACTV,EAAO,GAEPpB,EAAKh8B,EAAErc,OACFsV,EAAI,EAAGA,EAAI+iC,EAAI/iC,IAAK,CACrB+G,EAAE/G,KAAI6kC,EAAS99B,EAAE/G,GAAG,IAET,MAAX6kC,IACAD,EAAM5kC,GAAK6kC,EACP7kC,EAAI,IAAGmkC,EAAOS,EAAM5kC,EAAI,KAGhC+G,EAAE/G,GAAKkkC,EAAYn9B,EAAE/G,GAAIosB,EAAO+X,GAEf,MAAbS,EAAM5kC,IAAyB,MAAX6kC,IAAgBD,EAAM5kC,GAAK,KAInDwkC,EAAOz9B,EAAG/G,GAEV,IAAI8kC,EAAM/9B,EAAE/G,GACR+kC,EAASD,EAAIp6C,OAEjB0hC,EAAM/kB,EAAIy9B,EAAIC,EAAS,GACvB3Y,EAAMllB,EAAI49B,EAAIC,EAAS,GAEvB3Y,EAAM0X,GAAKt7B,WAAWs8B,EAAIC,EAAS,KAAO3Y,EAAM/kB,EAChD+kB,EAAM2X,GAAKv7B,WAAWs8B,EAAIC,EAAS,KAAO3Y,EAAMllB,CACpD,CAOA,OAJKH,EAAE,GAAG,IAAkB,MAAZA,EAAE,GAAG,IACjBA,EAAEoP,QAAQ,CAAC,IAAK,EAAG,IAGhBpP,CACX,CAEA,OAAO,SAASwY,GACZ,OAAOxU,EAAUwU,GAAUv3B,KAAK,KAAKwB,MAAM,KAAKxB,KAAK,IACzD,CACH,CAjZqB,GAmZtBmkC,EAAEtoB,UAAYL,EAEd2oB,EAAE6Y,EAAI,EAEC7Y,CAEV,CA3kFS,GA6kFV,MC9kFA,SAAS8Y,GAAejP,GACpB,IAAIh2B,EAAIg2B,EAAMtrC,OACd,KAAOsV,KAAKklC,GAAclP,EAAMh2B,GACpC,CAEA,SAASklC,GAAcljC,GACnB,GAAEK,MAAM5E,OAAOuE,GACfrE,GAASF,OAAOuE,GAChBpE,GAASH,OAAOuE,EACpB,CAEA,SAASmjC,GAAYnP,GACjB,IAAK,IAAIh2B,EAAI,EAAGA,EAAIg2B,EAAMtrC,OAAQsV,IAAK,CACnC,MAAMgC,EAAOg0B,EAAMh2B,GACfgC,EAAKkD,YACLlD,EAAKkD,WAAWgwB,YAAYlzB,EAEpC,CACJ,CAEO,SAASvE,KACZ,IAAK,IAAIuC,EAAI,EAAGA,EAAI9G,KAAKxO,OAAQsV,IAAK,CAClC,MAAMgC,EAAO9I,KAAK8G,GAClBklC,GAAcljC,GACdijC,GAAejjC,EAAKjB,qBAAqB,KAC7C,CAEA,OADAokC,GAAYjsC,MACLA,IACX,CAEO,SAASksC,KAEZ,OADAD,GAAYjsC,MACLA,IACX,CAEO,SAAS84B,KACZ,IAAK,IAAIhyB,EAAI,EAAGA,EAAI9G,KAAKxO,OAAQsV,IAAK,CAClC,MAAMgC,EAAO9I,KAAK8G,GACI,IAAlBgC,EAAKR,WACLyjC,GAAejjC,EAAKjB,qBAAqB,MAEzCiB,EAAKisB,YAAc,GAE3B,CACA,OAAO/0B,IACX,CAEO,SAAS,KACZ,MAAMmsC,EAAS,GACf,IAAK,IAAIrlC,EAAI,EAAGA,EAAI9G,KAAKxO,OAAQsV,IAC7BqlC,EAAOv6C,KAAKoO,KAAK8G,GAAG21B,WAAU,IAElC,OAAOz8B,KAAKgI,UAAUmkC,EAC1B,CAEO,SAASC,GAAKA,GACjB,MAAO/jC,GAAMrI,KACb,OAAKqI,EACoB,IAArBzJ,UAAUpN,OAAqB6W,EAAGV,eACzBlV,IAAT25C,EAA2BpsC,MAC/B+rC,GAAetnC,GAAU4D,EAAGR,qBAAqB,MAC7B,iBAATukC,GAAqC,iBAATA,GAGnC/jC,EAAGV,UAAY,GACR3H,KAAK8zB,OAAOsY,KAHnB/jC,EAAGV,UAAYykC,EAKZpsC,OAVS,IAWpB,CAEO,SAAS8zB,MAAUgJ,GACtB,MAAOV,GAAUp8B,KACjB,OAAKo8B,GACLU,EAAMnlC,SAASmR,IACNA,IACe,iBAATA,EACPszB,EAAOtI,UAAU,GAAE9sB,UAAU8B,IACF,oBAApBA,EAAK/V,WAEZiN,KAAK8zB,UAAU9iC,MAAM8W,KAAKgB,IACnB9X,MAAMC,QAAQ6X,GACrB9I,KAAK8zB,UAAUhrB,GAGfszB,EAAO30B,YAAYqB,GACvB,IAEG9I,MAfaA,IAgBxB,CAEO,SAASk8B,MAAWY,GACvB,MAAOV,GAAUp8B,KACjB,OAAKo8B,GACLU,EAAMnlC,SAASmR,IACNA,IACe,iBAATA,EACPszB,EAAOF,WAAW,GAAEl1B,UAAU8B,IACH,oBAApBA,EAAK/V,WAEZiN,KAAKk8B,WAAWlrC,MAAM8W,KAAKgB,IACpB9X,MAAMC,QAAQ6X,GACrB9I,KAAKk8B,WAAWpzB,GAGhBszB,EAAOC,aAAavzB,EAAMszB,EAAO1I,YACrC,IAEG1zB,MAfaA,IAgBxB,CAEO,SAASo5B,GAASgD,GAErB,OADA,GAAEA,GAAQtI,OAAO9zB,MACVA,IACX,CAEO,SAASqsC,GAAUjQ,GAEtB,OADA,GAAEA,GAAQF,QAAQl8B,MACXA,IACX,CAIA,MAAMssC,GAAe,CAAC,EAStB,SAASC,GAAelkC,EAAIlR,EAAMxL,GACT,iBAAVA,GAAsB2gD,GAAa3oC,GAAUxM,MACpDxL,GAAS,MAEb0c,EAAG4xB,MAAM9iC,GAAQxL,CACrB,CAEO,SAAS6gD,GAAIr1C,EAAMxL,GACtB,IAAI65C,EACJ,GAAoB,iBAATruC,EAAmB,CAC1B,QAAc1E,IAAV9G,EAAqB,CACrB,MAAO0c,GAAMrI,KACb,OAAKqI,EACEA,EAAG4xB,MAAM9iC,GADA,IAEpB,CACIquC,EAAS,CAAE,CAACruC,GAAOxL,EAE3B,KAAO,KAAKwL,EACR,MAAM,IAAI6R,MAAM,sBAEhBw8B,EAASruC,CACb,CACA,IAAK,IAAI8iC,KAASuL,EACd,GAAIA,EAAOj6C,eAAe0uC,GACtB,IAAK,IAAInzB,EAAI,EAAGA,EAAI9G,KAAKxO,OAAQsV,IAC7BylC,GAAevsC,KAAK8G,GAAImzB,EAAOuL,EAAOvL,IAIlD,OAAOj6B,IACX,CAEO,SAASzL,GAAK4C,EAAMxL,GACvB,GAAIiT,UAAUpN,OAAS,EAAG,CACtB,MAAO6W,GAAMrI,KACb,OAAKqI,OACQ5V,IAAT0E,EACOkR,EAAGokC,QAEPpkC,EAAGokC,QAAQt1C,GAJF,IAKpB,CACA,IAAK,IAAI2P,EAAI,EAAGA,EAAI9G,KAAKxO,OAAQsV,IAC7B9G,KAAK8G,GAAG2lC,QAAQt1C,GAAQxL,EAE5B,OAAOqU,IACX,CAIA,SAAS0sC,GAAcC,EAAQ7P,EAAO77B,GAClC,IAAK,IAAI6F,EAAI,EAAGA,EAAIg2B,EAAMtrC,OAAQsV,IAAK,CACnC,MAAMgC,EAAOg0B,EAAMh2B,GACnB,GAAExb,UAAUqhD,GAAQxrC,MAAM,CAAE2H,QAAQ7H,EACxC,CACJ,CAEO,SAASs+B,KAEZ,OADAmN,GAAc,cAAe1sC,KAAMpB,WAC5BoB,IACX,CAEO,SAASi1B,KAEZ,OADAyX,GAAc,WAAY1sC,KAAMpB,WACzBoB,IACX,CAEO,SAASw/B,KAEZ,OADAkN,GAAc,cAAe1sC,KAAMpB,WAC5BoB,IACX,CAEO,SAASk9B,KACZ,MAAOp0B,GAAQ9I,KACf,QAAK8I,GACE,GAAExd,UAAU4xC,SAAS/7B,MAAM,CAAE2H,QAAQlK,UAChD,CAIO,SAASu0B,GAAS5sB,GACrB,MAAMsC,EAAU,GAChB,IAAI,IAAI/B,EAAI,EAAGA,EAAI9G,KAAKxO,OAAQsV,IAAK,CACjC,MAAMgC,EAAO9I,KAAK8G,GAClB,IAAIqsB,EAAWniC,MAAM8W,KAAKgB,EAAKqqB,UACP,iBAAb5sB,IACP4sB,EAAWA,EAASp/B,QAAO+rB,GAASA,EAAMjX,QAAQtC,MAEtDsC,EAAQjX,QAAQuhC,EACpB,CACA,OAAOnzB,KAAKgI,UAAUa,EAC1B,CAEO,SAASoH,GAAQ1J,GACpB,MAAM0J,EAAU,GAChB,IAAK,IAAInJ,EAAI,EAAGA,EAAI9G,KAAKxO,OAAQsV,IAAK,CAClC,MAAMuB,EAAKrI,KAAK8G,GAChB,GAAwB,iBAAbP,EAAuB,CAC9B,MAAMqmC,EAAYvkC,EAAG4H,QAAQ1J,GACzBqmC,GACA38B,EAAQre,KAAKg7C,EAErB,KAAO,CACH,MAAOC,GAAc,GAAEtmC,GACnBsmC,GAAcA,EAAWtkC,SAASF,IAClC4H,EAAQre,KAAKi7C,EAErB,CACJ,CACA,OAAO7sC,KAAKgI,UAAUiI,EAC1B,CAIO,SAASzG,GAAGC,EAAOlD,EAAUhS,EAAMkS,GAEtC,OADA,GAAE0C,MAAMK,GAAGxJ,KAAMyJ,EAAOlD,EAAUhS,EAAMkS,GACjCzG,IACX,CAEO,SAAS0J,GAAID,EAAOlD,EAAUhS,EAAMkS,GAEvC,OADA,GAAE0C,MAAMK,GAAGxJ,KAAMyJ,EAAOlD,EAAUhS,EAAMkS,EAAI,GACrCzG,IACX,CAEO,SAAS4J,GAAIH,EAAOlD,EAAUE,GACjC,GAAIgD,GAASA,EAAM9D,gBAAkB8D,EAAMiB,UAAW,CAElD,MAAMA,EAAYjB,EAAMiB,UAQxB,OAPA,GAAEjB,EAAM8B,gBAAgB3B,IACpBc,EAAUC,UACJD,EAAUL,SAAW,IAAMK,EAAUC,UACrCD,EAAUL,SAChBK,EAAUnE,SACVmE,EAAUb,SAEP7J,IACX,CACA,GAAqB,iBAAVyJ,EAAoB,CAE3B,IAAK,IAAItX,KAAQsX,EACbzJ,KAAK4J,IAAIzX,EAAMoU,EAAUkD,EAAMtX,IAEnC,OAAO6N,IACX,EACiB,IAAbuG,GAA0C,mBAAbA,IAE7BE,EAAKF,EACLA,OAAW9T,GAEf,IAAK,IAAIqU,EAAI,EAAGA,EAAI9G,KAAKxO,OAAQsV,IAC7B,GAAEqC,MAAM5E,OAAOvE,KAAK8G,GAAI2C,EAAOhD,EAAIF,GAEvC,OAAOvG,IACX,CAIO,SAASwQ,KACZ,MAAOnI,GAAMrI,KACb,GAAIqI,IAAOnC,OAAQ,OAAOmC,EAAGlC,SAASC,gBAAgBmxB,YACjD,IAAKlvB,EAAI,OACd,MAAMm9B,EAASt/B,OAAO4mC,iBAAiBzkC,GACjCoI,EAASpI,EAAG0kC,YACZC,EAAiB19B,WAAWk2B,EAAOwH,gBAIzC,OAAOv8B,EAHmBnB,WAAWk2B,EAAOyH,mBAGRD,EAFjB19B,WAAWk2B,EAAO0H,YACf59B,WAAWk2B,EAAO2H,cAE5C,CAEO,SAAS18B,KACZ,MAAOpI,GAAMrI,KACb,GAAIqI,IAAOnC,OAAQ,OAAOmC,EAAGlC,SAASC,gBAAgBoxB,aACtD,IAAKnvB,EAAI,OACT,MAAMm9B,EAASt/B,OAAO4mC,iBAAiBzkC,GAMvC,OALcA,EAAG+kC,aACO99B,WAAWk2B,EAAO6H,iBACjB/9B,WAAWk2B,EAAO8H,kBACvBh+B,WAAWk2B,EAAO+H,aACjBj+B,WAAWk2B,EAAOgI,aAE3C,CAEO,SAAS5P,KACZ,MAAOv1B,GAAMrI,KACb,IAAKqI,EAAI,OACT,IACIolC,EACAp8B,EACA2nB,EAHA0U,EAAM,GAAErlC,GAIRslC,EAAe,CAAE16B,IAAK,EAAGD,KAAM,GAEnC,GAA4B,UAAxB06B,EAAIlB,IAAI,YAERn7B,EAAShJ,EAAGulC,4BACT,CACHv8B,EAASq8B,EAAIr8B,SAGb2nB,EAAM3wB,EAAGwlC,cACTJ,EAAeplC,EAAGolC,cAAgBzU,EAAI5yB,gBACtC,MAAM0nC,EAAgB,GAAEL,GAClBM,EAA8BD,EAActB,IAAI,aAAe,SACrE,KAAQiB,IAAiBA,IAAiBzU,EAAItxB,MAAQ+lC,IAAiBzU,EAAI5yB,kBAAoD,WAAhC2nC,GAC3FN,EAAeA,EAAazhC,WAEhC,GAAIyhC,GAAgBA,IAAiBplC,GAAgC,IAA1BolC,EAAanlC,SAAgB,CAEpE,MAAM0lC,EAAqB9nC,OAAO4mC,iBAAiBW,GAC7CT,EAAiB19B,WAAW0+B,EAAmBhB,iBAAmB,EAClEK,EAAkB/9B,WAAW0+B,EAAmBX,kBAAoB,EAC1EM,EAAeG,EAAcz8B,SAC7Bs8B,EAAa16B,KAAO+5B,EACpBW,EAAa36B,MAAQq6B,CACzB,CACJ,CACA,MAAMY,EAAY3+B,WAAWpJ,OAAO4mC,iBAAiBzkC,GAAI4lC,YAAc,EACjEC,EAAa5+B,WAAWpJ,OAAO4mC,iBAAiBzkC,GAAI6lC,aAAe,EAEzE,MAAO,CACHj7B,IAAK5B,EAAO4B,IAAM06B,EAAa16B,IAAMg7B,EACrCj7B,KAAM3B,EAAO2B,KAAO26B,EAAa36B,KAAOk7B,EAEhD,CAEO,SAAS78B,GAAO88B,GACnB,MAAO9lC,GAAMrI,KAEb,QAAoBvN,IAAhB07C,EAA2B,CAC3B,IAAK9lC,EAAI,OAAO,KAChB,IAAKA,EAAG+lC,iBAAiB58C,OACrB,MAAO,CAAEyhB,IAAK,EAAGD,KAAM,GAE3B,MAAMiD,EAAO5N,EAAGulC,wBAChB,MAAO,CACH36B,IAAKgD,EAAKhD,IAAM/M,OAAOmoC,QACvBr7B,KAAMiD,EAAKjD,KAAO9M,OAAOooC,QAEjC,CAEA,IAAKjmC,EAAI,OAAOrI,KAChB,MAAMuuC,EAAeroC,OAAO4mC,iBAAiBzkC,GACf,WAA1BkmC,EAAa3Q,UACb59B,KAAKwsC,IAAI,WAAY,YAEzB,MAAMgC,EAAgBxuC,KAAKqR,SACrBo9B,EAAgBN,EAAYl7B,IAAMu7B,EAAcv7B,IAChDy7B,EAAiBP,EAAYn7B,KAAOw7B,EAAcx7B,KAKxD,OAJAhT,KAAKwsC,IAAI,CACLv5B,KAAM3D,WAAWi/B,EAAat7B,MAAQ,GAAKw7B,EAAgB,KAC3Dz7B,MAAO1D,WAAWi/B,EAAav7B,OAAS,GAAK07B,EAAiB,OAE3D1uC,IACX,CApQA,CACI,QAAS,SAAU,MAAO,SAAU,OAAQ,QAC5C,UAAW,aAAc,gBAAiB,cAAe,eACzD,SAAU,YAAa,eAAgB,aAAc,eACvDrI,SAASg3C,IACPrC,GAAaqC,IAAW,CAAI,ICpIhC,MAAMC,GAAe,mBACfC,GAAW,CAAC,EAWX,SAASC,GAAQC,EAAY16B,EAAM,CAAC,GACvCrU,KAAKgvC,OACL,IAAK,IAAIloC,EAAI,EAAGA,EAAI9G,KAAKxO,OAAQsV,IAC7BmoC,GAAYjvC,KAAK8G,GAAIioC,EAAY16B,GAErC,OAAOrU,IACX,CAEA,SAASivC,GAAY5mC,EAAI0mC,EAAY16B,EAAM,CAAC,GAExC,IAAI,SACA66B,EAAW,IAAG,OACdC,EAAS,cAAa,MACtBC,EAAQ,EAAC,SACTC,GACAh7B,EAEJ,MAAMi7B,EAAUC,YAAW,WAEvB,MAAM7B,EAAM,GAAErlC,GACd,IAAImnC,GAAQ,EACRC,EAAW,gBAGfP,GAAsB,IACtBE,GAAgB,IAGhB,MAAMM,EAAY,CAAC,EACnB,GAA0B,iBAAfX,EAEPW,EAAU,kBAAoBX,EAC9BW,EAAU,sBAAwBR,EAAW,IAC7CQ,EAAU,mBAAqBN,EAAQ,IACvCM,EAAU,6BAA+BP,EACzCM,EAAW,mBACR,CAEH,MAAME,EAAuB,GAC7B,IAAK,IAAI7kD,KAAOikD,EACRA,EAAWxjD,eAAeT,KAC1B4kD,EAAU5kD,GAAOikD,EAAWjkD,GAC5B6kD,EAAqB/9C,KAAK9G,IAI9BokD,EAAW,IACXQ,EAAU,uBAAyBC,EAAqB7gD,KAAK,MAC7D4gD,EAAU,uBAAyBR,EAAW,IAC9CQ,EAAU,oBAAsBN,EAAQ,IACxCM,EAAU,8BAAgCP,EAElD,CAEA,MAAMS,EAAkB,SAASzmC,GAC7B,GAAIA,EAAO,CACP,GAAIA,EAAMjE,SAAWiE,EAAMhE,cAAe,OAC1CgE,EAAMjE,OAAOkG,oBAAoBqkC,EAAUG,EAC/C,MACIvnC,EAAG+C,oBAAoBqkC,EAAUG,GAErCJ,GAAQ,EACR9B,EAAIlB,IAAIqC,IACRQ,GAAYA,EAAS7jD,KAAK6c,EAC9B,EAEA,GAAI6mC,EAAW,EAAE,CACb7mC,EAAG0C,iBAAiB0kC,EAAUG,GAG9B,MAAMC,EAAaN,YAAW,WACtBC,GACJI,EAAgB,KACpB,GAAyB,KAApBV,EAAWE,GAAiB,IAEjC3qC,GAASrR,IAAIiV,EAAIumC,GAAc,CAC3BtZ,GAAIua,EACJb,KAAM,KACFc,aAAaD,GACbxnC,EAAG+C,oBAAoBqkC,EAAUG,EAAgB,GAG7D,CAEAlC,EAAIlB,IAAIkD,GAEJR,GAAY,GACZU,EAAgB,KAExB,IAEAnrC,GAASrR,IAAIiV,EAAIumC,GAAc,CAC3BI,KAAM,IAAMc,aAAaR,IAEjC,CAEO,SAASN,KACZ,IAAK,IAAIloC,EAAI,EAAGA,EAAI9G,KAAKxO,OAAQsV,IAAK,CAClC,MAAMuB,EAAKrI,KAAK8G,GACV43B,EAAYj6B,GAAStZ,IAAIkd,EAAIumC,IAC9BlQ,IACLA,EAAUsQ,OACVvqC,GAASF,OAAO8D,EAAIumC,IACxB,CAEA,OADA5uC,KAAKwsC,IAAIqC,IACF7uC,IACX,CAnHA6uC,GAAS,uBACTA,GAAS,uBACTA,GAAS,oBACTA,GAAS,8BACTA,GAAS,kBACTA,GAAS,sBACTA,GAAS,mBACTA,GAAS,6BAA+B,GCbxC,MAAMkB,GAAkB,CACpBC,WAAY,cACZC,YAAa,eACbC,WAAY,cACZC,YAAa,eACbC,WAAY,aACZC,UAAW,YACX7xC,IAAK,QACL25B,KAAM,eAGJmY,GAAgB,CAClBrkC,SAAU,WACVtgB,MAAO,QACPwsC,KAAM,eAmDJoY,GAAU,CACZllD,KAjDJ,SAAc8L,EAAMxL,GAChB,IAAKwL,EAAM,MAAM,IAAI6R,MAAM,wBAC3B,GAAyB,IAArBpK,UAAUpN,OAAc,CACxB,MAAO6W,GAAMrI,KACb,OAAKqI,EACEA,EAAGlR,GADM,IAEpB,CACA,QAAc1E,IAAV9G,EAAqB,OAAOqU,KAChC,IAAK,IAAI8G,EAAI,EAAGA,EAAI9G,KAAKxO,OAAQsV,IAC7B9G,KAAK8G,GAAG3P,GAAQxL,EAEpB,OAAOqU,IACX,EAsCIk1B,KApCJ,SAAc/9B,EAAMxL,GAChB,IAAI+vC,EACJ,GAAoB,iBAATvkC,EAAmB,CAC1B,QAAc1E,IAAV9G,EAAqB,CACrB,MAAO0c,GAAMrI,KACb,OAAKqI,EACEA,EAAGszB,aAAaxkC,GADP,IAEpB,CACIukC,EAAa,CAAE,CAACvkC,GAAOxL,EAE/B,KAAO,KAAKwL,EACR,MAAM,IAAI6R,MAAM,0BAEhB0yB,EAAavkC,CACjB,CACA,IAAK,IAAI+9B,KAAQwG,EACb,GAAIA,EAAWnwC,eAAe2pC,GAAO,CACjC,MAAMvpC,EAAQ+vC,EAAWxG,GACzB,GAAIob,GAAcpb,GAAO,CACrBl1B,KAAK3U,KAAKilD,GAAcpb,GAAOvpC,GAC/B,QACJ,CACA,IAAK,IAAImb,EAAI,EAAGA,EAAI9G,KAAKxO,OAAQsV,IACf,OAAVnb,EACAqU,KAAK8G,GAAG20B,gBAAgBvG,GAExBl1B,KAAK8G,GAAGyzB,aAAarF,EAAMvpC,EAGvC,CAEJ,OAAOqU,IACX,GAOAhV,OAAO0F,KAAKq/C,IAAiBp4C,SAAQ64C,IACjCD,GAAQC,GAAc,YAAYvvC,GAC9B,OAAOjB,KAAK3U,KAAK0kD,GAAgBS,MAAgBvvC,EACrD,CAAC,IAGL,YC5Ea,GAMQ,SCCfmI,GAAUpe,OAAO2I,OAAO,MAE9B,MAEAyV,GAAQqnC,KAAO,CAEXC,UAAU,GAMd,CACI,CAAC,aAAc,aACf,CAAC,aAAc,YACf,CAAC,eAAgB,eACjB,CAAC,eAAgB,eACnB/4C,SAAQ,EAAEg5C,EAAMrlC,MACdlC,GAAQunC,GAAQ,CACZnmC,aAAcc,EACdb,SAAUa,EACVrB,OAAQ,SAASd,GACb,MACMynC,EAAUznC,EAAM/D,cAChBsF,EAAYvB,EAAMuB,UACxB,IAAIxC,EAQJ,OALK0oC,GANU5wC,KAMSuI,SAASqoC,KAC7BznC,EAAMhX,KAAOuY,EAAUL,SACvBnC,EAAMwC,EAAUb,QAAQ1I,MARbnB,KAQ2BpB,WACtCuK,EAAMhX,KAAOmZ,GAEVpD,CACX,EACH,IASLkB,GAAQynC,OAAS,CACbpmC,SAAU,WACVD,aAAc,WACdP,OAAQ,SAASd,KAAUlI,GACvB,MAAM,UAAEyJ,EAAS,OAAExF,GAAWiE,EACxB2nC,EAAa,GAAEv8C,KAAKZ,OAAOuR,GAC3BK,GAAM,IAAID,MAAOyrC,UACjBC,EAAQ,cAAeF,EAAavrC,EAAMurC,EAAWG,UAAY,EACnED,EDjDW,KCiDSA,EAVf,IAWLF,EAAWG,UAAY,KACvB9nC,EAAMhX,KAAOuY,EAAUL,SAEvBK,EAAUb,QAAQre,KAAKwU,KAAMmJ,KAAUlI,IAEvC6vC,EAAWG,UAAY1rC,CAE/B,GC7DJva,OAAOgP,OAAO,GAAEyM,GAAI,GACpBzb,OAAOgP,OAAO,GAAEyM,GAAI,GACpBzb,OAAOgP,OAAO,GAAEyM,GAAI7T,IACpB5H,OAAOgP,OAAO,GAAEmP,MAAMC,QAAS,IAE/B,YCkCa8nC,GAAqB,SAAS1W,GAEvC,OAAKA,EAEEA,EAAUznC,WAAWzC,MAAM,KAAKK,KAAI,SAASwgD,GAMhD,OAJIA,EAAWC,OAAO,EAAG,KAAmC,KACxDD,EAAa,GAAyBA,GAGnCA,CAEX,IAAGriD,KAAK,KAVe0rC,CAW3B,EAiBa6W,GAAe,SAASC,EAAM3mC,GAEvC,MAAM4mC,EAAY,CAAC,EACbC,EAAiB,CAAC,EAClBC,EAAe,GAAE9mC,UAAUgoB,IAE3BroB,EAAKK,GAAa8mC,EAClBC,EAAWvrC,SAASozB,yBAEpBoY,EAAY,SAASC,EAAa5lC,EAAY1B,GAChD,IAAK,IAAIxD,EAAI,EAAGA,EAAI8qC,EAAYpgD,OAAQsV,IAAK,CACzC,MAAM+qC,EAAUD,EAAY9qC,GAG5B,GAAuB,iBAAZ+qC,EAAsB,CAC7B,MAAMC,EAAW3rC,SAASkvB,eAAewc,GACzC7lC,EAAWvE,YAAYqqC,GACvB,QACJ,CAGA,IAAKD,EAAQtmD,eAAe,WAAY,MAAM,IAAIyd,MAAM,oCACxD,MAAM8yB,EAAU+V,EAAQ/V,QAExB,IAAIhzB,EAGA+oC,EAAQtmD,eAAe,kBAAiB+e,EAAKunC,EAAQE,cACzDjpC,EAAO3C,SAASwtB,gBAAgBrpB,EAAIwxB,GACpC,MAAMnJ,EAAOroB,IAAOmnC,EAEdO,EAAc,EAAQ,GAAElpC,GAAQ,GAAEA,GAElC4yB,EAAamW,EAAQnW,WACvBA,GAAYsW,EAAY9c,KAAKwG,GAEjC,MAAMzB,EAAQ4X,EAAQ5X,MAGtB,GAFIA,GAAO,GAAEnxB,GAAM0jC,IAAIvS,GAEnB4X,EAAQtmD,eAAe,aAAc,CACrC,MAAMivC,EAAYqX,EAAQrX,UACtB7H,EACA7pB,EAAK0xB,UAAUhE,QAAUgE,EAEzB1xB,EAAK0xB,UAAYA,CAEzB,CAMA,GAJIqX,EAAQtmD,eAAe,iBACvBud,EAAKisB,YAAc8c,EAAQ9c,aAG3B8c,EAAQtmD,eAAe,YAAa,CACpC,MAAM0mD,EAAeJ,EAAQtrC,SAC7B,GAAIgrC,EAAUU,GAAe,MAAM,IAAIjpC,MAAM,4CAC7CuoC,EAAUU,GAAgBnpC,EAC1BkpC,EAAY9c,KAAK,iBAAkB+c,EACvC,CAEA,GAAIJ,EAAQtmD,eAAe,iBAAkB,CACzC,IAAI2mD,EAAaL,EAAQM,cACpBnhD,MAAMC,QAAQihD,KAAaA,EAAa,CAACA,IAC9C,IAAK,IAAInrC,EAAI,EAAGA,EAAImrC,EAAW1gD,OAAQuV,IAAK,CACxC,MAAMqrC,EAAYF,EAAWnrC,GAC7B,IAAIsrC,EAAQb,EAAeY,GACtBC,IAAOA,EAAQb,EAAeY,GAAa,IAChDC,EAAMzgD,KAAKkX,EACf,CACJ,CAEAkD,EAAWvE,YAAYqB,GAGvB,MAAMwpC,EAAcT,EAAQ1e,SACxBniC,MAAMC,QAAQqhD,IACdX,EAAUW,EAAaxpC,EAAMwB,EAErC,CACJ,EAEA,OADAqnC,EAAUL,EAAMI,EAAUpnC,GACnB,CACHonC,SAAUA,EACVH,UAAWA,EACXC,eAAgBA,EAExB,EAGae,GAAW,SAASlT,GAE7B,IAAImT,EAAO,EACX,GAAmB,IAAfnT,EAAI7tC,OAAc,OAAOghD,EAC7B,IAAK,IAAI1rC,EAAI,EAAGA,EAAIu4B,EAAI7tC,OAAQsV,IAE5B0rC,GAASA,GAAQ,GAAKA,EADZnT,EAAI5vC,WAAWqX,GAEzB0rC,GAAOA,EAEX,OAAOA,CACX,EAEaC,GAAY,SAASrnD,EAAK0M,EAAM46C,GAMzC,IAJA,IACI5nD,EADA4F,EAAOM,MAAMC,QAAQ6G,GAAQA,EAAOA,EAAKxH,MAAMoiD,GAAa,KAE5D5rC,EAAI,EACJtV,EAASd,EAAKc,OACXsV,EAAItV,GAAQ,CAEf,GADA1G,EAAM4F,EAAKoW,KACP9b,OAAOI,KAASA,KAAON,KAAOM,GAG9B,OAFAA,EAAMA,EAAIN,EAIlB,CACA,OAAOM,CACX,EAEMunD,GAAY,SAASvnD,EAAKN,GAM5B,MAHmB,iBAARA,GAAmC,iBAARA,IAClCA,EAAMo/C,OAAOp/C,KAEL,gBAARA,GAA6C,mBAAbM,EAAIN,KAG5B,cAARA,CAIR,EAEa8nD,GAAY,SAASxnD,EAAK0M,EAAMnM,EAAO+mD,GAEhD,MAAMhiD,EAAOM,MAAMC,QAAQ6G,GAAQA,EAAOA,EAAKxH,MAAMoiD,GAAa,KAC5DnxC,EAAO7Q,EAAKc,OAAS,EAC3B,IAAIqhD,EAAQznD,EACR0b,EAAI,EAER,KAAOA,EAAIvF,EAAMuF,IAAK,CAClB,MAAMhc,EAAM4F,EAAKoW,GACjB,IAAK6rC,GAAUE,EAAO/nD,GAAM,OAAOM,EAInCynD,EAHcA,EAAM/nD,KAGF+nD,EAAM/nD,GAAO,CAAC,EACpC,CAIA,OAFA+nD,EAAMniD,EAAK6Q,IAAS5V,EAEbP,CACX,EAEa0nD,GAAc,SAAS1nD,EAAK0M,EAAM46C,GAE3C,MAAMhiD,EAAOM,MAAMC,QAAQ6G,GAAQA,EAAOA,EAAKxH,MAAMoiD,GAAa,KAC5DnxC,EAAO7Q,EAAKc,OAAS,EAC3B,IAAIqhD,EAAQznD,EACR0b,EAAI,EAER,KAAOA,EAAIvF,EAAMuF,IAAK,CAClB,MAAMhc,EAAM4F,EAAKoW,GACjB,IAAK6rC,GAAUE,EAAO/nD,GAAM,OAAOM,EACnC,MAAMO,EAAQknD,EAAM/nD,GACpB,IAAKa,EAAO,OAAOP,EACnBynD,EAAQlnD,CACZ,CAIA,cAFOknD,EAAMniD,EAAK6Q,IAEXnW,CACX,EA8Casb,GAAO,SAAStb,GAIzB,OAFAsb,GAAK4uB,GAAK5uB,GAAK4uB,IAAM,OAET7iC,IAARrH,EACO,KAAOsb,GAAK4uB,MAGvBlqC,EAAIkqC,QAAiB7iC,IAAXrH,EAAIkqC,GAAmB,KAAO5uB,GAAK4uB,KAAOlqC,EAAIkqC,GACjDlqC,EAAIkqC,GACf,EAOayd,GAAiB,SAASntC,GAEnC,GAAIA,EAAIotC,WAAY,OAAOptC,EAE3B,MAAM,cAAEf,EAAa,OAAEK,GAAWU,EAG5BqtC,EAAQpuC,GAAiBA,EAAcquC,gBAAkBruC,EAAcquC,eAAe,GAC5F,GAAID,EACA,IAAK,IAAIv0C,KAAYu0C,OAGKxgD,IAAlBmT,EAAIlH,KACJkH,EAAIlH,GAAYu0C,EAAMv0C,IAKlC,GAAIwG,EAAQ,CACR,MAAMiuC,EAAajuC,EAAOkuC,wBACtBD,IAAYvtC,EAAIV,OAASiuC,EACjC,CAIA,OAFAvtC,EAAIotC,YAAa,EAEVptC,CACX,EA2DaytC,GAAY,WAErB,IAAIC,EAWJ,GATsB,oBAAXptC,SAEPotC,EAAMptC,OAAOqtC,uBACTrtC,OAAOstC,6BACPttC,OAAOutC,0BACPvtC,OAAOwtC,wBACPxtC,OAAOytC,0BAGVL,EAAK,CAEN,IAAIM,EAAW,EAEfN,EAAM,SAASO,GAEX,IAAIC,GAAW,IAAIxuC,MAAOyrC,UACtBgD,EAAahyC,KAAKwL,IAAI,EAAG,IAAMumC,EAAWF,IAC1Cte,EAAKia,YAAW,WAChBsE,EAASC,EAAWC,EACxB,GAAGA,GAIH,OAFAH,EAAWE,EAAWC,EAEfze,CACX,CACJ,CAEA,OAAO,SAASue,EAAU5sC,KAAY+sC,GAClC,OACMV,OADc7gD,IAAZwU,EACE4sC,EAAS9jD,KAAKkX,KAAY+sC,GAC1BH,EACd,CAEH,CArCwB,GAuCZI,KAGLC,GAA0B,oBAAVhuC,UAIhBiuC,GAAMjuC,OAAOkuC,sBACTluC,OAAOmuC,4BACPnuC,OAAOouC,mCACPpuC,OAAOquC,wBACPruC,OAAOsuC,+BACPtuC,OAAOuuC,uBACPvuC,OAAOwuC,8BACPxuC,OAAOyuC,yBACPzuC,OAAO0uC,gCAGfT,GAAMA,IAAOrE,aAENoE,GAASC,GAAIpkD,KAAKmW,QAAUiuC,IApBZ,IAEnBA,GACAD,GAqBD,MAAMW,GAAe,SAASr2C,GAEjC,OAAOoC,GAASpC,IAA0B,MAAlBA,EAAI1D,OAAO,EACvC,EAEag6C,GAAkB,SAASt2C,EAAKu2C,GAiBzC,IAAIC,EAAS1lC,WAAW9Q,GAGxB,GAAIvD,OAAOg6C,MAAMD,GAAS,OAAO,KAGjC,IAIIE,EAJAx1B,EAAS,CAAC,EAKd,GAJAA,EAAO/zB,MAAQqpD,EAIM,MAAjBD,EAGAG,EAAe,iBAEZ,GAAIlkD,MAAMC,QAAQ8jD,GAAgB,CAErC,GAA6B,IAAzBA,EAAcvjD,OAAc,OAAO,KAGvC0jD,EAAeH,EAAcjmD,KAAK,IAEtC,MAAW8R,GAASm0C,KAEhBG,EAAeH,GAEnB,IAAII,EA1CJ,SAAiBD,GASb,IAAIrsC,EAAU,IAAI5Z,OAAO,wBAA0BimD,EAAe,MAAM76C,KAAKmE,GAE7E,OAAKqK,EACEA,EAAQ,GADM,IAEzB,CA6BWusC,CAAQF,GAGnB,OAAa,OAATC,EAAsB,MAG1Bz1B,EAAOy1B,KAAOA,EACPz1B,EACX,EAIA,SAAS21B,GAAiBpxC,EAAMmwB,GAC5B,MAAMkhB,EAAWrxC,EAAK3T,MAAM8jC,GAC5B,IAAIpkB,EAAI,EACR,IAAK,IAAIjJ,EAAI,EAAGwuC,EAAKD,EAAS9jD,OAAS,EAAGuV,EAAIwuC,EAAIxuC,IAAK,CACnD,MAAMyuC,EAAc,IAChBzuC,EAAI,GAAqB,KAAhBuuC,EAAS,KAAWE,EAAY5jD,KAPpC,GAQT4jD,EAAY5jD,KAAKwiC,IACbrtB,EAAIwuC,EAAK,GAAsB,KAAjBD,EAASC,KAAYC,EAAY5jD,KAT1C,GAUT0jD,EAAS90C,OAAOwP,EAAG,KAAMwlC,GACzBxlC,GAAKwlC,EAAYhkD,OAAS,CAC9B,CACA,OAAO8jD,EAASvhD,QAAOkQ,GAAiB,KAATA,GACnC,CAGA,SAASwxC,GAAcC,EAAaC,GAChC,GAAoB,OAAhBD,EAEA,OAAOC,EAAYve,UAAU3mB,OAGjC,OAAQilC,EAAYP,MAChB,IAAK,KACD,OAAOQ,EAAYve,UAAU3mB,OAASilC,EAAY/pD,MACtD,IAAK,KACL,IAAK,GACD,OAAO+pD,EAAY/pD,MAE/B,CAEO,MAAMiqD,GAAY,SAASzd,EAAM3gC,EAAMguC,EAAS,CAAC,EAAGnxB,EAAM,CAAC,GAE9D,IAAI7D,EAAQhZ,EAAKgZ,MACbC,EAASjZ,EAAKiZ,OAEd+zB,EAAcnwB,EAAImwB,aAAe,GAAE,OAAO17B,KAC1C+sC,EAAW,GAAE,SAAS/sC,KACtB6sC,EAAc,GAAE,QAAQzgB,KAAKsQ,GAAQ1R,OAAO+hB,GAAU/sC,KACtDgpC,EAAW3rC,SAASkvB,eAAe,IAGvCsgB,EAAY1b,MAAM6b,QAAU,EAO5BH,EAAY1b,MAAM8b,QAAU,QAC5BF,EAAS5b,MAAM8b,QAAU,QAEzBF,EAASpuC,YAAYqqC,GACrBtN,EAAY/8B,YAAYkuC,GAEnBthC,EAAImwB,aAELr+B,SAASuB,KAAKD,YAAY+8B,GAG9B,MAAMwR,EAAiB3hC,EAAI2hC,eAErB1S,EAAajvB,EAAIivB,WAA+B,KAAlBjvB,EAAIivB,UAAoBjvB,EAAIivB,UADlD,IAGR2S,EAAsC,iBAAd3S,EAA0BA,EAH1C,IAId,IAAIlP,EAAM/f,EAAI+f,KAAO,KACjB8hB,EAAS7hC,EAAI6hC,OAAS,IAAIjnD,OAAOolB,EAAI6hC,QAAU,oCAC/CC,EAAe9hC,EAAI8hC,aAClBx1C,GAASw1C,KAAeA,EAAelzC,KAE5C,IAGI4K,EAAG+J,EACHyc,EAJAtwB,EAAQo0B,EAAK7nC,MAAMgzC,GACnB8S,EAAO,GACP3c,EAAQ,GAIRuc,GACA,GAAEH,GAAU3gB,KAAK,YAAa,YAGlC,IAAK,IAAIpuB,EAAI,EAAGoN,EAAI,EAAGrN,EAAM9C,EAAMvS,OAAQsV,EAAID,EAAKC,IAAK,CAErD,IAAI7C,EAAOF,EAAM+C,GAEjB,IAAK7C,GAAS+xC,IACM,iBAAT/xC,EAAX,CAEA,IAAIoyC,GAAQ,EACZ,GAAIjiB,GAAOnwB,EAAKhL,QAAQm7B,IAAQ,EAAG,CAE/B,GAAInwB,EAAKzS,OAAS,EAAG,CAEjB,MAAM8jD,EAAWD,GAAiBtxC,EAAM+C,GAAIstB,GAC5CrwB,EAAMvD,OAAOsG,EAAG,KAAMwuC,GACtBxuC,IACAD,EAAM9C,EAAMvS,OACZ,QACJ,CAEI,GAAIwkD,GAA0C,iBAAjBjyC,EAAM+C,EAAI,GAAkB,CACrD/C,EAAMvD,OAAOsG,EArGhB,EAqG6B,GArG7B,GAsGGD,GAAO,EACPC,IACA,QACJ,CACA2yB,IAAQvlB,GAAO8hC,GAA0C,iBAAjBjyC,EAAM+C,EAAI,QAAwBrU,EAAL,GACrE4jD,GAAQ,CAEhB,CAEA,IAAKA,EAAO,CAER,IAAI9hD,EASJ,GAPIA,EADAyhD,OACoBvjD,IAAbgnC,EAAMvlB,GAAmBulB,EAAMvlB,GAAK+hC,EAAgBhyC,EAAOA,EAE3Dw1B,EAAMvlB,GAAKulB,EAAMvlB,GAAK+hC,EAAgBhyC,EAAOA,EAGxD6tC,EAASv9C,KAAOA,EAEZshD,EAASS,yBAA2B9lC,EAGpCipB,EAAMvlB,GAAK3f,GAEPsZ,GAAK+J,KAELw+B,EAAKliC,MAAO,EAGZrG,EAAI,EACJ+J,EAAI,OAGL,CAEH,IAAK6hB,EAAMvlB,IAAMrG,EAAG,CAEhB,IAAI0oC,IAAc1oC,EAIlB,GAFAA,EAAI5J,EAAKzS,OAAS,EAEd+kD,IAAc1oC,EAAG,CAGjB,IAAKA,EAAG,CAEJ,IAAK4rB,EAAMvlB,GAAI,CAGXulB,EAAQ,GAER,KACJ,CAMA11B,EAAMvD,OAAOsG,EAAG,EAAG7C,EAAOF,EAAM+C,EAAI,IAGpCD,IAEAuvC,EAAKliC,MAAO,EACZpN,IAEA,QACJ,CAGA/C,EAAM+C,GAAK7C,EAAKuyC,UAAU,EAAG3oC,GAC7B,MAAM4oC,EAAW1yC,EAAM+C,EAAI,GAC3B/C,EAAM+C,EAAI,GAAK7C,EAAKuyC,UAAU3oC,SAAmBpb,IAAbgkD,GA/K3C,IA+KqEA,EAAwB,GAAKA,EAE/F,KAAO,CAEH,GAAI7+B,EAEA7T,EAAMvD,OAAOsG,EAAG,EAAG/C,EAAM+C,GAAK/C,EAAM+C,EAAI,IACxC8Q,EAAI,MACD,CACH,IAAI8+B,EAAczyC,EAAK0yC,OAAOT,GAC1BQ,GAAe,GAAKA,IAAgBzyC,EAAKzS,OAAS,GAAqB,IAAhBklD,IACvD9+B,EAAI8+B,EAAc,EAClB7oC,EAAI,GAKR9J,EAAMvD,OAAOsG,EAAG,EAAG7C,EAAKuyC,UAAU,EAAG5+B,GAAK/J,GAAI5J,EAAKuyC,UAAU5+B,GAAI/J,IAEjEhH,GAEJ,CAEIqN,IAAMkiC,EAAKliC,EAAI,IAGfA,GAER,CAEK8hC,GAA+B,KAAbvc,EAAMvlB,IACzBpN,IAGJ,QACJ,CAEAoN,IACApN,GACJ,CACJ,CACA,IAAI8vC,EAAQ,KA6BZ,GA3BInd,EAAMjoC,OAAS2kD,EAEfS,EAAQT,EAAe,OAEL1jD,IAAXge,SAKYhe,IAAf4hC,GAA8C,KAAlByd,EAASv9C,OAIjC8/B,EADsB,SAAtBmR,EAAOnR,WACMohB,GAAc,CAAE9pD,MAAO,IAAKwpD,KAAM,MAAQQ,GAI1CF,GAFEX,GAAgBtP,EAAOnR,WAAY,CAAC,KAAM,KAAM,KAE5BshB,IAIvCthB,EAAaoF,EAAMjoC,OAASif,IAE5BmmC,EAAQ70C,KAAKC,MAAMyO,EAAS4jB,GAAc,IAIpC,OAAVuiB,EAAgB,CAEhBnd,EAAMj5B,OAAOo2C,EAAQ,GAGrB,IAAIC,EAAWxiC,EAAIwiC,SACnB,IAAKA,GAAYD,EAAQ,EAAG,MACJ,iBAAbC,IAAuBA,EAAW,KAE7C,IAAIC,EAAWrd,EAAMmd,GACrB,IAAKE,IAAaT,EAAO,MACzB,IACIU,EAAsBC,EADtBhO,EAAI8N,EAAStlD,OAEjB,EAAG,CAUC,GATAwlD,EAAWF,EAAS9N,GACpB+N,EAAuBD,EAASN,UAAU,EAAGxN,GACxCgO,EAEMA,EAAS5mD,MAAMkzC,KACtByT,GAAwBC,GAFxBD,GAAwBd,EAI5Bc,GAAwBF,EACxB/E,EAASv9C,KAAOwiD,EACZlB,EAASS,yBAA2B9lC,EAAO,CAC3CipB,EAAMmd,GAASG,EACf,KACJ,CACA/N,GACJ,OAASA,GAAK,GACd,KACJ,CA7LsC,CA8L1C,CAaA,OAXI30B,EAAImwB,YAGJA,EAAYxI,YAAY2Z,GAKxBxvC,SAASuB,KAAKs0B,YAAYwI,GAGvB/K,EAAM3qC,KAAKslC,EACtB,EAsRa6iB,GAAiB,SAAS/f,GAEnC,GAAIlsC,OAAOksC,KAASA,EAAK,CACrB,IAAI14B,EAAM,EAGV,OAFI42B,SAAS8B,KAAM14B,GAAO04B,GAEnB,CAAEjkB,IAAKzU,EAAK0U,MAAO1U,EAAK2U,OAAQ3U,EAAKwU,KAAMxU,EACtD,CAGA,IAAIyU,EAAKC,EAAOC,EAAQH,EAWxB,OAVAC,EAAMC,EAAQC,EAASH,EAAO,EAE1BoiB,SAAS8B,EAAIggB,YAAWjkC,EAAME,GAAU+jB,EAAIggB,UAC5C9hB,SAAS8B,EAAIigB,cAAajkC,EAAQF,GAAQkkB,EAAIigB,YAE9C/hB,SAAS8B,EAAIjkB,OAAMA,GAAOikB,EAAIjkB,KAC9BmiB,SAAS8B,EAAIhkB,SAAQA,GAASgkB,EAAIhkB,OAClCkiB,SAAS8B,EAAI/jB,UAASA,GAAU+jB,EAAI/jB,QACpCiiB,SAAS8B,EAAIlkB,QAAOA,GAAQkkB,EAAIlkB,MAE7B,CAAEC,IAAKA,EAAKC,MAAOA,EAAOC,OAAQA,EAAQH,KAAMA,EAC3D,EAEaokC,GAAS,CAElB5qC,OAAQ,SAASiF,GACb,OAAOA,CACX,EAEA4lC,KAAM,SAAS5lC,GACX,OAAOA,EAAIA,CACf,EAEA6lC,MAAO,SAAS7lC,GACZ,OAAOA,EAAIA,EAAIA,CACnB,EAEA8lC,MAAO,SAAS9lC,GACZ,GAAIA,GAAK,EAAG,OAAO,EACnB,GAAIA,GAAK,EAAG,OAAO,EACnB,IAAImP,EAAKnP,EAAIA,EACT+lC,EAAK52B,EAAKnP,EACd,OAAO,GAAKA,EAAI,GAAK+lC,EAAK,GAAK/lC,EAAImP,GAAM42B,EAAK,IAClD,EAEAC,YAAa,SAAShmC,GAClB,OAAO1P,KAAKqN,IAAI,EAAG,IAAMqC,EAAI,GACjC,EAEAimC,OAAQ,SAASjmC,GACb,IAAK,IAAI9V,EAAI,EAAGC,EAAI,GAAMD,GAAKC,EAAGA,GAAK,EACnC,GAAI6V,IAAM,EAAI,EAAI9V,GAAK,GAAI,CACvB,IAAImS,GAAK,GAAK,EAAInS,EAAI,GAAK8V,GAAK,EAChC,OAAQ3D,EAAIA,EAAIlS,EAAIA,CACxB,CAER,EAEA+7C,QAAS,SAASxlC,GACd,OAAO,SAASV,GACZ,OAAO,EAAIU,EAAE,EAAIV,EACrB,CACJ,EAEAmmC,QAAS,SAASzlC,GACd,OAAO,SAASV,GACZ,MAAO,IAAMA,EAAI,GAAKU,EAAE,EAAIV,GAAM,EAAIU,EAAE,EAAI,EAAIV,GACpD,CACJ,EAEAomC,MAAO,SAAS1lC,EAAGnC,EAAG7B,GAGlB,OAFA6B,EAAIA,GAAK,EACT7B,EAAIA,GAAK,EACF,SAASsD,GACZ,IAAInB,EAAI6B,EAAEV,GACV,OAAOnB,EAAIN,EAAIA,EAAIM,EAAInC,EAAIA,EAAImC,CACnC,CACJ,EAEAwnC,KAAM,SAAS3pB,GAEX,OADKA,IAAGA,EAAI,SACL,SAAS1c,GACZ,OAAOA,EAAIA,IAAM0c,EAAI,GAAK1c,EAAI0c,EAClC,CACJ,EAEA4pB,QAAS,SAAS5pC,GAEd,OADKA,IAAGA,EAAI,KACL,SAASsD,GACZ,OAAO1P,KAAKqN,IAAI,EAAG,IAAMqC,EAAI,IAAM1P,KAAK0L,IAAI,GAAK1L,KAAKuK,GAAK6B,EAAI,EAAIsD,EACvE,CACJ,GAGSumC,GAAc,CAEvBhD,OAAQ,SAASr5C,EAAGC,GAChB,IAAIkb,EAAIlb,EAAID,EACZ,OAAO,SAAS8V,GACZ,OAAO9V,EAAImb,EAAIrF,CACnB,CACJ,EAEAhhB,OAAQ,SAASkL,EAAGC,GAChB,IAAIuyB,EAAInjC,OAAO0F,KAAKiL,GACpB,OAAO,SAAS8V,GACZ,IAAI3K,EAAG+G,EACHyC,EAAI,CAAC,EACT,IAAKxJ,EAAIqnB,EAAE38B,OAAS,GAAS,GAANsV,EAASA,IAE5BwJ,EADAzC,EAAIsgB,EAAErnB,IACCnL,EAAEkS,IAAMjS,EAAEiS,GAAKlS,EAAEkS,IAAM4D,EAElC,OAAOnB,CACX,CACJ,EAEA2nC,SAAU,SAASt8C,EAAGC,GAElB,IAAIs8C,EAAK5pC,SAAS3S,EAAEb,MAAM,GAAI,IAC1Bq9C,EAAK7pC,SAAS1S,EAAEd,MAAM,GAAI,IAC1Bs9C,EAAU,IAALF,EACLG,GAAW,IAALF,GAAiBC,EACvBE,EAAU,MAALJ,EACLK,GAAW,MAALJ,GAAiBG,EACvBE,EAAU,SAALN,EACLO,GAAW,SAALN,GAAiBK,EAE3B,OAAO,SAAS/mC,GAMZ,MAAO,KAAO,GAAK,GAJV2mC,EAAKC,EAAK5mC,EAAK,IACf6mC,EAAKC,EAAK9mC,EAAK,MACf+mC,EAAKC,EAAKhnC,EAAK,UAEW1e,SAAS,IAAI+H,MAAM,EAC1D,CACJ,EAEAq6C,KAAM,SAASx5C,EAAGC,GAEd,IAAI0U,EAAI,4CACJooC,EAAKpoC,EAAEjW,KAAKsB,GACZg9C,EAAKroC,EAAEjW,KAAKuB,GACZiS,EAAI8qC,EAAG,GAAG1/C,QAAQ,KAClBkZ,EAAItE,EAAI,EAAI8qC,EAAG,GAAGnnD,OAASqc,EAAI,EAAI,EACvClS,GAAK+8C,EAAG,GACR,IAAI5hC,GAAK6hC,EAAG,GAAKh9C,EACbi9C,EAAIF,EAAG,GAEX,OAAO,SAASjnC,GACZ,OAAQ9V,EAAImb,EAAIrF,GAAGw3B,QAAQ92B,GAAKymC,CACpC,CACJ,GAKS,GAAS,CAMlBC,QAAS,SAAS53C,GAEd,IAEI63C,EAAS79C,OAAOm6B,SAASn0B,EAAK63C,QAAU73C,EAAK63C,OAAS,EACtDtoC,EAAQvV,OAAOm6B,SAASn0B,EAAKuP,OAASvP,EAAKuP,MAAQ,EAEvD,OAAOuoC,GALG,qiBAKHA,CAAc,CACjBC,MAAO/3C,EAAK+3C,OAAS,OACrBlD,QAAS76C,OAAOm6B,SAASn0B,EAAK60C,SAAW70C,EAAK60C,QAAU,EACxDlQ,YAAakT,EAAStoC,EACtBm1B,YAAamT,GAErB,EAMAG,UAAW,SAASh4C,GAIhB,OAAO83C,GAFG,+XAEHA,CAAc,CACjBC,MAAO/3C,EAAK+3C,OAAS,MACrBxoC,MAAOvV,OAAOm6B,SAASn0B,EAAKuP,OAASvP,EAAKuP,MAAQ,EAClD0oC,KAAMj+C,OAAOm6B,SAASn0B,EAAKi4C,MAAQj4C,EAAKi4C,KAAO,EAC/CpD,QAAS76C,OAAOm6B,SAASn0B,EAAK60C,SAAW70C,EAAK60C,QAAU,GAEhE,EAIAoD,KAAM,SAASj4C,GAEX,IAAIkN,EAAIlT,OAAOm6B,SAASn0B,EAAKkN,GAAKlN,EAAKkN,EAAI,EAE3C,OAAO4qC,GAAS,oEAATA,CAA8E,CACjFI,aAAcl+C,OAAOm6B,SAASn0B,EAAK+M,GAAK,CAACG,EAAGlN,EAAK+M,GAAKG,GAE9D,EAOAirC,WAAY,SAASn4C,GAEjB,IAAIo4C,EAAM,2BAA4BnzC,OAChC,kIACA,wWAEN,OAAO6yC,GAASM,EAATN,CAAc,CACjB7nC,GAAIjQ,EAAKiQ,IAAM,EACfC,GAAIlQ,EAAKkQ,IAAM,EACf2kC,QAAS76C,OAAOm6B,SAASn0B,EAAK60C,SAAW70C,EAAK60C,QAAU,EACxDkD,MAAO/3C,EAAK+3C,OAAS,QACrBE,KAAMj+C,OAAOm6B,SAASn0B,EAAKi4C,MAAQj4C,EAAKi4C,KAAO,GAEvD,EAGAI,UAAW,SAASr4C,GAEhB,IAAIs4C,EAASt+C,OAAOm6B,SAASn0B,EAAKs4C,QAAUt4C,EAAKs4C,OAAS,EAE1D,OAAOR,GAAS,8HAATA,CAAwI,CAC3Ip9C,EAAG,MAAS,OAAU,EAAI49C,GAC1B39C,EAAG,MAAS,OAAU,EAAI29C,GAC1BxjC,EAAG,MAAS,OAAU,EAAIwjC,GAC1BziC,EAAG,MAAS,OAAU,EAAIyiC,GAC1BrvC,EAAG,MAAS,OAAU,EAAIqvC,GAC1BpnC,EAAG,MAAS,OAAU,EAAIonC,GAC1BzN,EAAG,MAAS,OAAU,EAAIyN,GAC1B3hC,EAAG,MAAS,OAAU,EAAI2hC,IAElC,EAGAC,MAAO,SAASv4C,GAEZ,IAAIs4C,EAASt+C,OAAOm6B,SAASn0B,EAAKs4C,QAAUt4C,EAAKs4C,OAAS,EAE1D,OAAOR,GAAS,8HAATA,CAAwI,CAC3Ip9C,EAAG,KAAQ,MAAS,EAAI49C,GACxB39C,EAAG,KAAQ,MAAS,EAAI29C,GACxBxjC,EAAG,KAAQ,MAAS,EAAIwjC,GACxBziC,EAAG,KAAQ,MAAS,EAAIyiC,GACxBrvC,EAAG,KAAQ,MAAS,EAAIqvC,GACxBpnC,EAAG,KAAQ,MAAS,EAAIonC,GACxBzN,EAAG,KAAQ,MAAS,EAAIyN,GACxB3hC,EAAG,KAAQ,MAAS,EAAI2hC,GACxBzyC,EAAG,KAAQ,MAAS,EAAIyyC,IAEhC,EAGAE,SAAU,SAASx4C,GAEf,IAAIs4C,EAASt+C,OAAOm6B,SAASn0B,EAAKs4C,QAAUt4C,EAAKs4C,OAAS,EAE1D,OAAOR,GAAS,uEAATA,CAAiF,CACpFQ,OAAQ,EAAIA,GAEpB,EAGAG,UAAW,SAASz4C,GAEhB,OAAO83C,GAAS,uEAATA,CAAiF,CACpFjsC,MAAO7L,EAAK6L,OAAS,GAE7B,EAGA6sC,OAAQ,SAAS14C,GAEb,IAAIs4C,EAASt+C,OAAOm6B,SAASn0B,EAAKs4C,QAAUt4C,EAAKs4C,OAAS,EAE1D,OAAOR,GAAS,6OAATA,CAAuP,CAC1PQ,OAAQA,EACRK,QAAS,EAAIL,GAErB,EAGAM,WAAY,SAAS54C,GAEjB,OAAO83C,GAAS,6LAATA,CAAuM,CAC1MQ,OAAQt+C,OAAOm6B,SAASn0B,EAAKs4C,QAAUt4C,EAAKs4C,OAAS,GAE7D,EAGAO,SAAU,SAAS74C,GAEf,IAAIs4C,EAASt+C,OAAOm6B,SAASn0B,EAAKs4C,QAAUt4C,EAAKs4C,OAAS,EAE1D,OAAOR,GAAS,kQAATA,CAA4Q,CAC/QQ,OAAQA,EACRK,QAAS,GAAKL,EAAS,GAE/B,GAoQSR,GAAW,SAAS3M,GAM7B,IAAI2N,EAAQ,wDAEZ,OAAO,SAASxlD,GAIZ,OAFAA,EAAOA,GAAQ,CAAC,EAET63C,EAAKr0C,QAAQgiD,GAAO,SAAS3pD,GAUhC,IARA,IAKI4pD,EALOhpD,MAAM8W,KAAKlJ,WACN9D,MAAM,EAAG,GAAGsN,MAAK,SAAS6xC,GACtC,QAASA,CACb,IAEqB3pD,MAAM,KACvB3E,EAAQ4I,EAAKylD,EAAUxO,cAEV/4C,IAAV9G,GAAuBquD,EAAUxoD,QACpC7F,EAAQA,EAAMquD,EAAUxO,SAG5B,YAAiB/4C,IAAV9G,EAAsBA,EAAQ,EACzC,GACJ,CACJ,EA+BA,SAASuuD,GAAe9uD,EAAK+uD,EAASC,EAAcC,GAEhD,GAAID,IAAiBC,EACjB,MAAO,CAAC,EAGZ,MAAMthD,EAAO,CAAC,EAuBd,OArBA/N,OAAO0F,KAAKtF,GAAKuM,SAAS7M,IAEtB,MAAM0H,EAAWpH,EAAIN,GACfwvD,EAAYH,EAAQrvD,GAE1B,IAAKkG,MAAMC,QAAQuB,KAAcxB,MAAMC,QAAQqpD,IAAcpoD,GAASM,IAAaN,GAASooD,GAAY,CAEpG,MAAMC,EAAcH,EAAe,EAC7BI,EAAaN,GAAe1nD,EAAU8nD,EAAWC,EAAaF,GAEhErvD,OAAO0F,KAAK8pD,GAAYhpD,OAAS,EACjCuH,EAAKjO,GAAO0vD,EACa,IAAjBJ,GAAsBG,IAAgBF,IAC9CthD,EAAKjO,GAAO,CAAC,EAGrB,MAAY0X,GAAQhQ,EAAU8nD,KAC1BvhD,EAAKjO,GAAO0H,EAChB,IAGGuG,CACX,CAEO,SAAS0hD,GAAiBhqD,EAAQ2W,EAAMiN,GAE3C,MAAM,SAAEgmC,EAAWp/C,OAAOy/C,mBAAsBrmC,GAAO,CAAC,EAExD,OAAO6lC,GAAezpD,EAAQ2W,EAAM,EAAGizC,EAC3C,CCjsDO,IAMHM,GANOC,GAAS,CAAC,EAGjBC,GAAgB,MAQhBC,GAAY,SAASr+C,EAAU8M,EAAQpS,EAAM08C,EAAUkH,GACvD,IAAWC,EAAPl0C,EAAI,EACR,GAAI3P,GAAwB,iBAATA,EAAmB,MAEjB,IAAb08C,GAAuB,YAAakH,QAAyB,IAAjBA,EAAK9zC,UAAoB8zC,EAAK9zC,QAAU4sC,GACxF,IAAKmH,EAAQhwD,OAAO0F,KAAKyG,GAAO2P,EAAIk0C,EAAMxpD,OAASsV,IAC/CyC,EAASuxC,GAAUr+C,EAAU8M,EAAQyxC,EAAMl0C,GAAI3P,EAAK6jD,EAAMl0C,IAAKi0C,EAEvE,MAAO,GAAI5jD,GAAQ0jD,GAAc/qD,KAAKqH,GAElC,IAAK6jD,EAAQ7jD,EAAK7G,MAAMuqD,IAAgB/zC,EAAIk0C,EAAMxpD,OAAQsV,IACtDyC,EAAS9M,EAAS8M,EAAQyxC,EAAMl0C,GAAI+sC,EAAUkH,QAIlDxxC,EAAS9M,EAAS8M,EAAQpS,EAAM08C,EAAUkH,GAE9C,OAAOxxC,CACX,EAIAqxC,GAAOpxC,GAAK,SAASrS,EAAM08C,EAAU5sC,GAejC,OAdAjH,KAAKi7C,QAAUH,GAAUI,GAAOl7C,KAAKi7C,SAAW,CAAC,EAAG9jD,EAAM08C,EAAU,CAChE5sC,QAASA,EACTk0C,IAAKn7C,KACLo7C,UAAWT,KAGXA,MACgB36C,KAAKq7C,aAAer7C,KAAKq7C,WAAa,CAAC,IAC7CV,GAAWrlB,IAAMqlB,GAG3BA,GAAWW,SAAU,GAGlBt7C,IACX,EAKA46C,GAAOW,SAAW,SAASnwD,EAAK+L,EAAM08C,GAClC,IAAKzoD,EAAK,OAAO4U,KACjB,IAAIs1B,EAAKlqC,EAAIowD,YAAcpwD,EAAIowD,UAAYp3C,GAAS,MAChDq3C,EAAcz7C,KAAK07C,eAAiB17C,KAAK07C,aAAe,CAAC,GACzDN,EAAYT,GAAac,EAAYnmB,GAIpC8lB,IACDp7C,KAAKw7C,YAAcx7C,KAAKw7C,UAAYp3C,GAAS,MAC7Cg3C,EAAYT,GAAac,EAAYnmB,GAAM,IAAIqmB,GAAU37C,KAAM5U,IAInE,IAAI+2C,EAAQyZ,GAAWxwD,EAAK+L,EAAM08C,EAAU7zC,MAG5C,GAFA26C,QAAa,EAETxY,EAAO,MAAMA,EAIjB,OAFIiZ,EAAUE,SAASF,EAAU5xC,GAAGrS,EAAM08C,GAEnC7zC,IACX,EAGA,IAAIk7C,GAAQ,SAAS3xC,EAAQpS,EAAM08C,EAAUlc,GACzC,GAAIkc,EAAU,CACV,IAAIjpC,EAAWrB,EAAOpS,KAAUoS,EAAOpS,GAAQ,IAC3C8P,EAAU0wB,EAAQ1wB,QAASk0C,EAAMxjB,EAAQwjB,IAAKC,EAAYzjB,EAAQyjB,UAClEA,GAAWA,EAAUS,QAEzBjxC,EAAShZ,KAAK,CAAEiiD,SAAUA,EAAU5sC,QAASA,EAASk0C,IAAKl0C,GAAWk0C,EAAKC,UAAWA,GAC1F,CACA,OAAO7xC,CACX,EAIIqyC,GAAa,SAASxwD,EAAK+L,EAAM08C,EAAU5sC,GAC3C,IACI7b,EAAIoe,GAAGrS,EAAM08C,EAAU5sC,EAC3B,CAAE,MAAOiD,GACL,OAAOA,CACX,CACJ,EAMA0wC,GAAOhxC,IAAM,SAASzS,EAAM08C,EAAU5sC,GAClC,OAAKjH,KAAKi7C,SACVj7C,KAAKi7C,QAAUH,GAAUgB,GAAQ97C,KAAKi7C,QAAS9jD,EAAM08C,EAAU,CAC3D5sC,QAASA,EACT80C,UAAW/7C,KAAKq7C,aAGbr7C,MANmBA,IAO9B,EAIA46C,GAAOoB,cAAgB,SAAS5wD,EAAK+L,EAAM08C,GACvC,IAAI4H,EAAcz7C,KAAK07C,aACvB,IAAKD,EAAa,OAAOz7C,KAGzB,IADA,IAAIi8C,EAAM7wD,EAAM,CAACA,EAAIowD,WAAaxwD,OAAO0F,KAAK+qD,GACrC30C,EAAI,EAAGA,EAAIm1C,EAAIzqD,OAAQsV,IAAK,CACjC,IAAIs0C,EAAYK,EAAYQ,EAAIn1C,IAIhC,IAAKs0C,EAAW,MAEhBA,EAAUhwD,IAAIwe,IAAIzS,EAAM08C,EAAU7zC,MAC9Bo7C,EAAUE,SAASF,EAAUxxC,IAAIzS,EAAM08C,EAC/C,CAGA,OAFIvxC,GAAQm5C,KAAcz7C,KAAK07C,kBAAe,GAEvC17C,IACX,EAGA,IAAI87C,GAAS,SAASvyC,EAAQpS,EAAM08C,EAAUlc,GAC1C,GAAKpuB,EAAL,CAEA,IACWyxC,EADP/zC,EAAU0wB,EAAQ1wB,QAAS80C,EAAYpkB,EAAQokB,UAC/Cj1C,EAAI,EAGR,GAAK3P,GAAS8P,GAAY4sC,EAA1B,CASA,IADAmH,EAAQ7jD,EAAO,CAACA,GAAQnM,OAAO0F,KAAK6Y,GAC7BzC,EAAIk0C,EAAMxpD,OAAQsV,IAAK,CAE1B,IAAI8D,EAAWrB,EADfpS,EAAO6jD,EAAMl0C,IAIb,IAAK8D,EAAU,MAIf,IADA,IAAIsxC,EAAY,GACPn1C,EAAI,EAAGA,EAAI6D,EAASpZ,OAAQuV,IAAK,CACtC,IAAI8C,EAAUe,EAAS7D,GACvB,GACI8sC,GAAYA,IAAahqC,EAAQgqC,UACzCA,IAAahqC,EAAQgqC,SAASsI,WAC5Bl1C,GAAWA,IAAY4C,EAAQ5C,QAEzBi1C,EAAUtqD,KAAKiY,OACZ,CACH,IAAIuxC,EAAYvxC,EAAQuxC,UACpBA,GAAWA,EAAUxxC,IAAIzS,EAAM08C,EACvC,CACJ,CAGIqI,EAAU1qD,OACV+X,EAAOpS,GAAQ+kD,SAER3yC,EAAOpS,EAEtB,CAEA,OAAOoS,CAjCP,CANI,GAAgB,MAAbwyC,EACC,IAAKf,EAAQhwD,OAAO0F,KAAKqrD,GAAYj1C,EAAIk0C,EAAMxpD,OAAQsV,IACnDi1C,EAAUf,EAAMl0C,IAAIs1C,SATb,CA+CvB,EAMAxB,GAAOyB,KAAO,SAASllD,EAAM08C,EAAU5sC,GAEnC,IAAIsC,EAASuxC,GAAUwB,GAAS,CAAC,EAAGnlD,EAAM08C,EAAU7zC,KAAK4J,IAAI7Z,KAAKiQ,OAElE,MADoB,iBAAT7I,GAAgC,MAAX8P,IAAiB4sC,OAAW,GACrD7zC,KAAKwJ,GAAGD,EAAQsqC,EAAU5sC,EACrC,EAGA2zC,GAAO2B,aAAe,SAASnxD,EAAK+L,EAAM08C,GAEtC,IAAItqC,EAASuxC,GAAUwB,GAAS,CAAC,EAAGnlD,EAAM08C,EAAU7zC,KAAKg8C,cAAcjsD,KAAKiQ,KAAM5U,IAClF,OAAO4U,KAAKu7C,SAASnwD,EAAKme,EAC9B,EAIA,IAAI+yC,GAAU,SAAS3rD,EAAKwG,EAAM08C,EAAU2I,GACxC,GAAI3I,EAAU,CACV,IAAIwI,EAAO1rD,EAAIwG,GAAQslD,IAAW,WAC9BD,EAAMrlD,EAAMklD,GACZxI,EAAS1yC,MAAMnB,KAAMpB,UACzB,IACAy9C,EAAKF,UAAYtI,CACrB,CACA,OAAOljD,CACX,EAII8rD,GAAa,SAASn7C,GACtB,IAAI7P,EACJ,GAAmB,mBAAR6P,EACP,MAAM,IAAIo7C,UAAU,uBAExB,IAAI1sC,EAAI,EACR,OAAO,WAOH,QANMA,EAAI,IACNve,EAAS6P,EAAKH,MAAMnB,KAAMpB,YAE1BoR,GAAK,IACL1O,OAAO7O,GAEJhB,CACX,CACJ,EAMAmpD,GAAO+B,QAAU,SAASxlD,GACtB,IAAK6I,KAAKi7C,QAAS,OAAOj7C,KAI1B,IAFA,IAAIxO,EAASuQ,KAAKwL,IAAI,EAAG3O,UAAUpN,OAAS,GACxCyP,EAAOjQ,MAAMQ,GACRsV,EAAI,EAAGA,EAAItV,EAAQsV,IAAK7F,EAAK6F,GAAKlI,UAAUkI,EAAI,GAGzD,OADAg0C,GAAU8B,GAAY58C,KAAKi7C,QAAS9jD,OAAM,EAAQ8J,GAC3CjB,IACX,EAGA,IAAI48C,GAAa,SAASC,EAAW1lD,EAAM08C,EAAU5yC,GACjD,GAAI47C,EAAW,CACX,IAAItzC,EAASszC,EAAU1lD,GACnB2lD,EAAYD,EAAUE,IACtBxzC,GAAUuzC,IAAWA,EAAYA,EAAUhiD,SAC3CyO,GAAQyzC,GAAczzC,EAAQtI,GAC9B67C,GAAWE,GAAcF,EAAW,CAAC3lD,GAAMwR,OAAO1H,GAC1D,CACA,OAAO47C,CACX,EAKIG,GAAgB,SAASzzC,EAAQtI,GACjC,IAAIg8C,EAAIn2C,GAAK,EAAGoN,EAAI3K,EAAO/X,OAAQ+kB,EAAKtV,EAAK,GAAIuV,EAAKvV,EAAK,GAAIi8C,EAAKj8C,EAAK,GACzE,OAAQA,EAAKzP,QACT,KAAK,EAAG,OAASsV,EAAIoN,IAAI+oC,EAAK1zC,EAAOzC,IAAI+sC,SAASroD,KAAKyxD,EAAG9B,KAAM,OAChE,KAAK,EAAG,OAASr0C,EAAIoN,IAAI+oC,EAAK1zC,EAAOzC,IAAI+sC,SAASroD,KAAKyxD,EAAG9B,IAAK5kC,GAAK,OACpE,KAAK,EAAG,OAASzP,EAAIoN,IAAI+oC,EAAK1zC,EAAOzC,IAAI+sC,SAASroD,KAAKyxD,EAAG9B,IAAK5kC,EAAIC,GAAK,OACxE,KAAK,EAAG,OAAS1P,EAAIoN,IAAI+oC,EAAK1zC,EAAOzC,IAAI+sC,SAASroD,KAAKyxD,EAAG9B,IAAK5kC,EAAIC,EAAI0mC,GAAK,OAC5E,QAAS,OAASp2C,EAAIoN,IAAI+oC,EAAK1zC,EAAOzC,IAAI+sC,SAAS1yC,MAAM87C,EAAG9B,IAAKl6C,GAAO,OAEhF,EAII06C,GAAY,SAASwB,EAAU/xD,GAC/B4U,KAAKs1B,GAAK6nB,EAAS3B,UACnBx7C,KAAKm9C,SAAWA,EAChBn9C,KAAK5U,IAAMA,EACX4U,KAAKs7C,SAAU,EACft7C,KAAK67C,MAAQ,EACb77C,KAAKi7C,aAAU,CACnB,EAEAU,GAAUrwD,UAAUke,GAAKoxC,GAAOpxC,GAMhCmyC,GAAUrwD,UAAUse,IAAM,SAASzS,EAAM08C,GACrC,IAAIuI,EACAp8C,KAAKs7C,SACLt7C,KAAKi7C,QAAUH,GAAUgB,GAAQ97C,KAAKi7C,QAAS9jD,EAAM08C,EAAU,CAC3D5sC,aAAS,EACT80C,eAAW,IAEfK,GAAWp8C,KAAKi7C,UAEhBj7C,KAAK67C,QACLO,EAAyB,IAAfp8C,KAAK67C,OAEfO,GAASp8C,KAAKo8C,SACtB,EAGAT,GAAUrwD,UAAU8wD,QAAU,kBACnBp8C,KAAKm9C,SAASzB,aAAa17C,KAAK5U,IAAIowD,WACtCx7C,KAAKs7C,gBAAgBt7C,KAAK5U,IAAIiwD,WAAWr7C,KAAKs1B,GACvD,EAGAslB,GAAO7qD,KAAS6qD,GAAOpxC,GACvBoxC,GAAOwC,OAASxC,GAAOhxC,IChUhB,IAAI,GAAS,SAASyzC,EAAYC,GACrC,IACIx9B,EADAsc,EAASp8B,KAwBb,OAjBI8f,EADAu9B,GAAc,GAAIA,EAAY,eACtBA,EAAW/qD,YAEX,WAAY,OAAO8pC,EAAOj7B,MAAMnB,KAAMpB,UAAY,EAI9D,GAAOkhB,EAAOsc,EAAQkhB,GAItBx9B,EAAMx0B,UAAYN,OAAOgP,OAAOhP,OAAO2I,OAAOyoC,EAAO9wC,WAAY+xD,GACjEv9B,EAAMx0B,UAAUgH,YAAcwtB,EAI9BA,EAAMy9B,UAAYnhB,EAAO9wC,UAElBw0B,CACX,EAmCIq4B,GAAK,SAAS17C,EAAU+gD,GACxB,OAAI,GAAW/gD,GAAkBA,EAC7BvK,GAASuK,KAAc+gD,EAASC,SAAShhD,GAAkBihD,GAAajhD,GACxEmE,GAASnE,GAAkB,SAASkhD,GAAS,OAAOA,EAAMxyD,IAAIsR,EAAW,EACtEA,CACX,EAEIihD,GAAe,SAASxqB,GACxB,IAAI0qB,EhCggDGz/C,GAAY5E,GgChgDG25B,GhCggDe,IgC//CrC,OAAO,SAASyqB,GACZ,OAAOC,EAAQD,EAAMjiB,WACzB,CACJ,ECjEWmiB,GAAQ,SAASniB,EAAY/D,GACpC,IAAIzE,EAAQwI,GAAc,CAAC,EAC3B/D,IAAYA,EAAU,CAAC,GACvB33B,KAAK89C,cAAc38C,MAAMnB,KAAMpB,WAC/BoB,KAAK+9C,IAAM35C,GAASpE,KAAKg+C,WACzBh+C,KAAK07B,WAAa,CAAC,EACf/D,EAAQn7B,aAAYwD,KAAKxD,WAAam7B,EAAQn7B,YAClD,IAAIyhD,EAAoBxsD,GAAOuO,KAAM,YAIrCkzB,EAAQryB,GAAS,GAAO,CAAC,EAAGo9C,EAAmB/qB,GAAQ+qB,GAEvDj+C,KAAK5M,IAAI8/B,EAAOyE,GAChB33B,KAAKk+C,QAAU,CAAC,EAChBl+C,KAAKm+C,WAAWh9C,MAAMnB,KAAMpB,UAChC,EC7BO,SAASw/C,GAAWC,GAEvBA,EAAQn8C,GAAKm8C,GAKb,MAAMC,EAAW57C,GAAQ27C,GAAOr6C,QAAO,SAASrT,EAAK4tD,GAEjD,OADA5tD,EAAI4tD,EAAKjpB,IAAMipB,EAAKn8C,QACbzR,CACX,GAAG,CAAC,GA2CJ,OAzCA+R,GAAQ27C,GAAO1mD,SAAQ,SAAS4mD,GAE5B,MAAMn8C,EAAQk8C,EAASC,EAAKjpB,IAG5B,GAAIlzB,EAAMo8C,SAAU,CAChB,MAAM7rD,EAASyP,EAAMzP,SACfuS,EAAS9C,EAAM8C,SACjBvS,EAAO2iC,IAAMgpB,EAAS3rD,EAAO2iC,KAG7BlzB,EAAM/W,KAAK,YAAaizD,EAAS3rD,EAAO2iC,IAAIA,IAE5CpwB,EAAOowB,IAAMgpB,EAASp5C,EAAOowB,KAG7BlzB,EAAM/W,KAAK,YAAaizD,EAASp5C,EAAOowB,IAAIA,GAEpD,CAGA,MAAM8G,EAASmiB,EAAKpzD,IAAI,UACpBixC,GAAUkiB,EAASliB,IACnBh6B,EAAMhP,IAAI,SAAUkrD,EAASliB,GAAQ9G,IAIzC,MAAMmpB,EAAS/7C,GAAQ67C,EAAKpzD,IAAI,WAAW6Y,QAAO,SAAS06C,EAAWC,GAMlE,OAHIL,EAASK,IACTD,EAAU9sD,KAAK0sD,EAASK,GAAOrpB,IAE5BopB,CACX,GAAG,IAEEp8C,GAAQm8C,IACTr8C,EAAMhP,IAAI,SAAUqrD,EAE5B,IAEOH,CACX,CDtBA,GAAOT,GAAMvyD,UAAWsvD,GAAQ,CAG5BsD,QAAS,KAGTU,gBAAiB,KAIjBC,YAAa,KAIbb,UAAW,IAIXF,cAAe,WAAW,EAI1BK,WAAY,WAAW,EAGvB3rC,OAAQ,SAASmlB,GACb,OAAOv1B,GAAMpC,KAAK07B,WACtB,EAGAvwC,IAAK,SAAS+pC,GACV,OAAOl1B,KAAK07B,WAAWxG,EAC3B,EAIAl+B,IAAK,SAASk+B,GACV,OAAyB,MAAlBl1B,KAAK7U,IAAI+pC,EACpB,EAKA9hC,IAAK,SAAStI,EAAK0T,EAAKm5B,GACpB,GAAW,MAAP7sC,EAAa,OAAOkV,KAGxB,IAAIkzB,EAWJ,GAVmB,iBAARpoC,GACPooC,EAAQpoC,EACR6sC,EAAUn5B,IAET00B,EAAQ,CAAC,GAAGpoC,GAAO0T,EAGxBm5B,IAAYA,EAAU,CAAC,IAGlB33B,KAAK8+C,UAAU5rB,EAAOyE,GAAU,OAAO,EAG5C,IAAIx8B,EAAaw8B,EAAQx8B,MACrB4jD,EAAapnB,EAAQonB,OACrBC,EAAa,GACbC,EAAaj/C,KAAKk/C,UACtBl/C,KAAKk/C,WAAY,EAEZD,IACDj/C,KAAKm/C,oBAAsB/8C,GAAMpC,KAAK07B,YACtC17B,KAAKk+C,QAAU,CAAC,GAGpB,IAAIkB,EAAUp/C,KAAK07B,WACfwiB,EAAUl+C,KAAKk+C,QACfzX,EAAUzmC,KAAKm/C,oBAGnB,IAAK,IAAIjqB,KAAQhC,EACb10B,EAAM00B,EAAMgC,GACP1yB,GAAQ48C,EAAQlqB,GAAO12B,IAAMwgD,EAAQptD,KAAKsjC,GAC1C1yB,GAAQikC,EAAKvR,GAAO12B,UAGd0/C,EAAQhpB,GAFfgpB,EAAQhpB,GAAQ12B,EAIpBrD,SAAeikD,EAAQlqB,GAAQkqB,EAAQlqB,GAAQ12B,EAInD,GAAIwB,KAAK6+C,eAAe3rB,EAAO,CAC3B,IAAImsB,EAASr/C,KAAKs1B,GAClBt1B,KAAKs1B,GAAKt1B,KAAK7U,IAAI6U,KAAK6+C,aACxB7+C,KAAK28C,QAAQ,WAAY38C,KAAMq/C,EAAQ1nB,EAC3C,CAGA,IAAKonB,EAAQ,CACLC,EAAQxtD,SAAQwO,KAAKs/C,SAAW3nB,GACpC,IAAK,IAAI7wB,EAAI,EAAGA,EAAIk4C,EAAQxtD,OAAQsV,IAChC9G,KAAK28C,QAAQ,UAAYqC,EAAQl4C,GAAI9G,KAAMo/C,EAAQJ,EAAQl4C,IAAK6wB,EAExE,CAIA,GAAIsnB,EAAU,OAAOj/C,KACrB,IAAK++C,EACD,KAAO/+C,KAAKs/C,UACR3nB,EAAU33B,KAAKs/C,SACft/C,KAAKs/C,UAAW,EAChBt/C,KAAK28C,QAAQ,SAAU38C,KAAM23B,GAKrC,OAFA33B,KAAKs/C,UAAW,EAChBt/C,KAAKk/C,WAAY,EACVl/C,IACX,EAIA7E,MAAO,SAAS+5B,EAAMyC,GAClB,OAAO33B,KAAK5M,IAAI8hC,OAAM,EAAQ,GAAO,CAAC,EAAGyC,EAAS,CAAEx8B,OAAO,IAC/D,EAGA+E,MAAO,SAASy3B,GACZ,IAAIzE,EAAQ,CAAC,EACb,IAAK,IAAIpoC,KAAOkV,KAAK07B,WAAYxI,EAAMpoC,QAAO,EAC9C,OAAOkV,KAAK5M,IAAI8/B,EAAO,GAAO,CAAC,EAAGyE,EAAS,CAAEx8B,OAAO,IACxD,EAIAokD,WAAY,SAASrqB,GACjB,OAAY,MAARA,GAAsB5yB,GAAQtC,KAAKk+C,SAChC,GAAIl+C,KAAKk+C,QAAShpB,EAC7B,EAQAsqB,kBAAmB,SAASzmD,GACxB,IAAKA,EAAM,QAAOiH,KAAKu/C,cAAen9C,GAAMpC,KAAKk+C,SACjD,IAEIqB,EAFAE,EAAMz/C,KAAKk/C,UAAYl/C,KAAKm/C,oBAAsBn/C,KAAK07B,WACvDwiB,EAAU,CAAC,EAEf,IAAK,IAAIhpB,KAAQn8B,EAAM,CACnB,IAAIyF,EAAMzF,EAAKm8B,GACX1yB,GAAQi9C,EAAIvqB,GAAO12B,KACvB0/C,EAAQhpB,GAAQ12B,EAChB+gD,GAAa,EACjB,CACA,QAAOA,GAAarB,CACxB,EAIAwB,SAAU,SAASxqB,GACf,OAAY,MAARA,GAAiBl1B,KAAKm/C,oBACnBn/C,KAAKm/C,oBAAoBjqB,GADsB,IAE1D,EAIAyqB,mBAAoB,WAChB,OAAOv9C,GAAMpC,KAAKm/C,oBACtB,EAGA/8C,MAAO,WACH,OAAO,IAAIpC,KAAK1N,YAAY0N,KAAK07B,WACrC,EAGAvS,QAAS,SAASwO,GACd,OAAO33B,KAAK8+C,UAAU,CAAC,EAAG,GAAO,CAAC,EAAGnnB,EAAS,CAAE9O,UAAU,IAC9D,EAIAi2B,UAAW,SAAS5rB,EAAOyE,GACvB,IAAKA,EAAQ9O,WAAa7oB,KAAK6oB,SAAU,OAAO,EAChDqK,EAAQ,GAAO,CAAC,EAAGlzB,KAAK07B,WAAYxI,GACpC,IAAIiP,EAAQniC,KAAK4+C,gBAAkB5+C,KAAK6oB,SAASqK,EAAOyE,IAAY,KACpE,OAAKwK,IACLniC,KAAK28C,QAAQ,UAAW38C,KAAMmiC,EAAO,GAAOxK,EAAS,CAAEinB,gBAAiBzc,MACjE,EACX,IAKJ0b,GAAMh+B,OAAS,GE5Of,MAEM+/B,GAFsB,CAAC,UAAW,WAAY,WAAY,WAAY,kBAAmB,QAAS,iBAE5D57C,QAAO,CAAC6hB,EAAK/6B,KACrD+6B,EAAI/6B,IAAO,EACJ+6B,IACR,CAAC,GAsBJ,GApBc,CACVg6B,QAAS,SAAS9Q,GACd,OAAO3yC,GAAc2yC,EACzB,EACA37C,IAAK,SAAS27C,EAAY+Q,EAAGh3C,GACzB9d,OAAO0F,KAAKq+C,GAAYp3C,SAAQ,SAAS7M,GACrC,GAAI80D,GAAgB90D,IAAQA,KAAOge,EAAM,CACrC,MAAMnd,EAAQojD,EAAWjkD,GACJ,WAAjBge,EAAKgzB,SAAwB9qC,MAAMC,QAAQtF,GAC3CqF,MAAM8W,KAAKgB,EAAK6uB,SAAShgC,SAAQ,SAASooD,EAAQruD,GAC9CquD,EAAOC,SAAWr0D,EAAMqN,SAAS+mD,EAAOp0D,MAC5C,IAEAmd,EAAKhe,GAAOa,CAEpB,CACJ,GACJ,GCvBJ,SAASs0D,GAAgBC,EAAMC,EAAW1wC,GACtC,OAAO,SAAS9jB,EAAOy0D,GACnB,IAMIpP,EANAqP,EAAkBxL,GAAalpD,GAOnC,GANAA,EAAQ2jB,WAAW3jB,GACf00D,IACA10D,GAAS,KAITypC,SAASzpC,GAAQ,CACjB,IAAI20D,EAAYF,EAAQ3wC,KAEpBuhC,EADAqP,GAAmB10D,EAAQ,GAAKA,EAAQ,EAChC20D,EAAUJ,GAAQE,EAAQD,GAAax0D,EAEvC20D,EAAUJ,GAAQv0D,CAElC,CAEA,IAAIqlB,EAAQrC,KAEZ,OADAqC,EAAMkvC,GAAQlP,GAAS,EAChBhgC,CACX,CACJ,CAEA,SAASuvC,GAAW3kB,EAAUukB,GAC1B,OAAO,SAASx0D,EAAOy0D,GACnB,IAAII,EAAoB3L,GAAalpD,GACrCA,EAAQ2jB,WAAW3jB,GACf60D,IACA70D,GAAS,KAGb,IAAIunC,EAAQ,CAAC,EACb,GAAIkC,SAASzpC,GAAQ,CACjB,IAAI80D,EAAaD,GAAqB70D,GAAS,GAAKA,GAAS,EACvDA,EAAQy0D,EAAQD,GAChBp+C,KAAKwL,IAAI5hB,EAAQy0D,EAAQD,GAAY,GAC3CjtB,EAAM0I,GAAY6kB,CACtB,CAEA,OAAOvtB,CACX,CACJ,CAEA,MAAMwtB,GAAqB,CAKvB,QAAS,CACL9iB,SAAUqiB,GAAgB,IAAK,QAAS,WAG5C,QAAS,CACLriB,SAAUqiB,GAAgB,IAAK,SAAU,WAM7C,SAAU,CACNriB,SAAUqiB,GAAgB,IAAK,QAAS,WAG5C,SAAU,CACNriB,SAAUqiB,GAAgB,IAAK,SAAU,WAQ7C,YAAa,CACT7sD,IAAKmtD,GAAW,QAAS,UAG7B,aAAc,CACVntD,IAAKmtD,GAAW,SAAU,WAG9B,SAAU,CACNntD,IAAKmtD,GAAW,KAAM,UAG1B,SAAU,CACNntD,IAAKmtD,GAAW,KAAM,WAG1B,SAAU,CACNntD,IAAKmtD,GAAW,KAAM,UAG1B,SAAU,CACNntD,IAAKmtD,GAAW,KAAM,WAG1B,kBAAmB,CACfntD,KACQutD,GAAUJ,GAMf,IANoC,SAC/BK,GAAWL,GAKhB,IALqC,UAC7B,SAAS50D,EAAOy0D,GAEnB,OADUA,EAAQ3vC,OAAS2vC,EAAQ5vC,MAASmwC,GAAUC,IAC5Cj1D,EAAOy0D,EACrB,IAIR,sBAAuB,CACnBhtD,IAAK,SAASzH,EAAOy0D,GACjB,IAAII,EAAoB3L,GAAalpD,GACrCA,EAAQ2jB,WAAW3jB,GACf60D,IACA70D,GAAS,KAGb,IAEIk1D,EAFAC,EAAiB/+C,KAAK2M,KAAM0xC,EAAQ3vC,OAAS2vC,EAAQ3vC,OAAW2vC,EAAQ5vC,MAAQ4vC,EAAQ5vC,OAQ5F,OALI4kB,SAASzpC,KAC0Ck1D,EAA/CL,GAAqB70D,GAAS,GAAKA,GAAS,EAAYA,EAAQm1D,EACtD/+C,KAAKwL,IAAI5hB,EAAQm1D,EAAgB,IAG5C,CAAExwC,EAAGuwC,EAChB,IA3BK,IACGF,GACAC,GA+BhBF,GAAyB,KAAIA,GAAmB,SAChDA,GAAyB,KAAIA,GAAmB,SAIhDA,GAAmB,UAAYA,GAAmB,SAClDA,GAAmB,UAAYA,GAAmB,SAClDA,GAAmB,cAAgBA,GAAmB,aACtDA,GAAmB,eAAiBA,GAAmB,cAGvDA,GAAmB,SAAWA,GAAmB,mBAEjD,YCnJM,GAAQ,CACVvyC,EAAG,IACHH,EAAG,IACHwC,MAAO,IACPC,OAAQ,IACRswC,QAAS,IACTC,QAAS,IACTC,SAAU,KAERC,GAAYl2D,OAAO0F,KAAK,IAAOC,KAAI7F,GAAO,GAAMA,KAAMgE,KAAK,IAC3DqyD,GAAgB,4CAChBC,GAAkB,MAClBC,GAAqB,IAAIpyD,OAAO,KAAKkyD,YAAuBD,SAAgBC,iBAA4BA,QAAoB,KAElI,SAASG,GAAatpD,GAClB,MAAM,IAAIgR,MAAM,8BAA8BhR,IAClD,CAMO,SAASupD,GAAgBC,EAASvrC,GACrC,MAAM7lB,EAAQixD,GAAmBhnD,KAAKmnD,EAAQzpD,QAAQqpD,GAAiB,KAClEhxD,GAAOkxD,GAAaE,GACzBH,GAAmB/mD,UAAY,EAC/B,MAAO,CAACw7B,EAAUp3B,EAAUokB,EAAQloB,GAAOxK,GACrC,EAAE+d,EAAC,EAAEH,EAAC,MAAEwC,EAAK,OAAEC,GAAWwF,EAChC,IAAItqB,EAAQ,EACZ,OAAQ+S,GACJ,KAAK,GAAM8R,MACP7kB,EAAQ6kB,EACR,MAEJ,KAAK,GAAMC,OACP9kB,EAAQ8kB,EACR,MAEJ,KAAK,GAAMtC,EACPxiB,EAAQwiB,EACR,MAEJ,KAAK,GAAMH,EACPriB,EAAQqiB,EACR,MAEJ,KAAK,GAAM+yC,QACPp1D,EAAQoW,KAAKE,IAAIwO,EAAQD,GACzB,MAEJ,KAAK,GAAMwwC,QACPr1D,EAAQoW,KAAKwL,IAAIkD,EAAQD,GACzB,MAEJ,KAAK,GAAMywC,SACPt1D,EAAQoW,KAAK2M,KAAM+B,EAASA,EAAWD,EAAQA,GAevD,OAXIslB,IAEAnqC,GAAS2jB,WAAWwmB,IAEpBhT,IAEAn3B,GAAS2jB,WAAWwT,EAAOhoB,MAAM,KAEjCF,IACAjP,GAKR,SAA2B81D,GACvB,IAAKA,EAAe,OAAO,EAC3B,MAAOC,GAAQD,EACf,OAAQC,GACJ,IAAK,IACD,OAAOpyC,WAAWmyC,EAAcrQ,OAAO,IAE3C,IAAK,IACD,OAAQ9hC,WAAWmyC,EAAcrQ,OAAO,IAGhD,OAAO9hC,WAAWmyC,EACtB,CAjBiBE,CAAkB/mD,IAExBjP,CACX,CAoBO,SAASi2D,GAAiBj2D,GAC7B,MAAwB,iBAAVA,GAAsBA,EAAMqN,SAAS,OACvD,CASO,SAAS6oD,GAAmB7pD,EAAYie,GAC3C,IAAItqB,EAAQqM,EACR8pD,EAAmB,EACvB,OAAG,CACC,IAAIC,EAAYp2D,EAAMsN,QAXZ,QAW+B6oD,GACzC,IAAmB,IAAfC,EAAkB,OAAOp2D,EAC7B,IAAIq2D,EAAeD,EAZHE,EAaZC,EAAW,EACfC,EAAoB,OAAG,CACnB,OAAQx2D,EAAMq2D,IACV,IAAK,IACDE,IACA,MAEJ,IAAK,IAED,GADAA,IACiB,IAAbA,EAAgB,MAAMC,EAC1B,MAEJ,UAAK1vD,EAED6uD,GAAa31D,GAGrBq2D,GACJ,CAEA,IAAIhqD,EAAarM,EAAMmP,MAAMinD,EAjCbE,EAiC0CD,GACtDJ,GAAiB5pD,KACjBA,EAAa6pD,GAAmB7pD,EAAYie,IAGhD,MAAMmsC,EAAYlY,OAAOqX,GAAgBvpD,EAAYie,IAErDtqB,EAAQA,EAAMmP,MAAM,EAAGinD,GAAaK,EAAYz2D,EAAMmP,MAAMknD,EAAe,GAC3EF,EAAmBC,EAAYK,EAAU5wD,MAC7C,CACJ,CCtIA,SAAS6wD,GAAYC,EAAQC,EAAOrvB,GAChC,YAAuBzgC,IAAfygC,EAAMiF,IAClB,CAEA,MAAMqqB,GAAkB,CAAC,cAAe,cAAe,YAAa,iBAAkB,kBAEhFC,GAAmB,CAErB,cAAe,CACX5C,QAASwC,IAGb,uBAAwB,CACpBxC,QAASwC,IAGb,YAAa,CACTxC,QAASwC,IAGb,YAAe,CACXxC,QAASwC,IAGb,IAAO,CACHxC,QAASwC,IAGb,gBAAiB,CACbxC,QAASwC,IAGb,KAAQ,CACJxC,QAAS,SAAS6C,EAAOH,EAAOrvB,GAC5B,MAAMyvB,EAAWzvB,EAAM,aACvB,OAAQyvB,IAAavmD,GAAcumD,EACvC,EACAxnD,MAAO,SAAS2N,GACZA,EAAKisB,YAAc,EACvB,EACA3hC,IAAK,SAAS+kC,EAAMioB,EAASt3C,EAAMoqB,GAC/B,MAAM0vB,EAAY,aACZ7rD,EAAQ,GAAExC,KAAKpJ,IAAI2d,EAAM85C,GACzBvuB,EAAanB,EAAM,eACnBuF,EAAqBvF,EAAM,wBAC3BoF,EAAepF,EAAM,iBACrByB,EAAWzB,EAAM,aACjBiC,EAAcjC,EAAMiC,YACpBf,EAAMlB,EAAMkB,IACZjmB,EAAI+kB,EAAM/kB,EAChB,IAAIoqB,EAAWrF,EAAM,aAGrB,MAAM2vB,EAAWlc,KAAKC,UAAU,CAACzO,EAAM9D,EAAYc,EAAasD,EAAoBrE,EAAKkE,EAAcC,EAAUpqB,EAAGwmB,IACpH,QAAcliC,IAAVsE,GAAuBA,IAAU8rD,EAAU,CAM3C,GAFIluB,GAAU7rB,EAAKyxB,aAAa,YAAa5F,GAEzCziC,GAASqmC,GAAW,CACpB,MAAMuqB,EAAevqB,EAAShyB,SAC9B,GAA4B,iBAAjBu8C,EAA2B,CAClC,MAAMC,EAAW/iD,KAAKgjD,SAASF,GAC3BC,aAAoBE,iBACpB1qB,EAAW,GAAO,CAAE,aAAc,IAAMwqB,EAASztB,IAAMiD,GAE/D,CACJ,CACA,GAAEzvB,GAAMqvB,KAAK,GAAKA,EAAM,CACpB9D,aACAc,cACAoD,WACApqB,IACAsqB,qBACArE,MACAkE,iBAEJ,GAAE/jC,KAAKnB,IAAI0V,EAAM85C,EAAWC,EAChC,CACJ,GAGJ,YAAa,CACThD,QAASzjD,GACThJ,IAAK,SAASzH,EAAOy0D,EAASt3C,EAAMoqB,GAChC,IAAI17B,EAAO,CAAC,EAERgZ,EAAQ7kB,EAAM6kB,OAAS,EACvBqkC,GAAarkC,GACbhZ,EAAKgZ,MAAQ4vC,EAAQ5vC,MAAQlB,WAAWkB,GAAS,IAC1CoxC,GAAiBpxC,GACxBhZ,EAAKgZ,MAAQvV,OAAO4mD,GAAmBrxC,EAAO4vC,IAE1B,OAAhBz0D,EAAM6kB,MAENhZ,EAAKgZ,MAAQvN,IAEbzL,EAAKgZ,MADEA,GAAS,EACH4vC,EAAQ5vC,MAAQA,EAEhBA,EAIrB,IAgBI0yC,EAhBAzyC,EAAS9kB,EAAM8kB,QAAU,EACzBokC,GAAapkC,GACbjZ,EAAKiZ,OAAS2vC,EAAQ3vC,OAASnB,WAAWmB,GAAU,IAC7CmxC,GAAiBnxC,GACxBjZ,EAAKiZ,OAASxV,OAAO4mD,GAAmBpxC,EAAQ2vC,IAE3B,OAAjBz0D,EAAM8kB,SAINjZ,EAAKiZ,OADEA,GAAU,EACH2vC,EAAQ3vC,OAASA,EAEjBA,GAKtB,IAAI0nB,EAAOxsC,EAAMwsC,KAEjB,QADa1lC,IAAT0lC,IAAoBA,EAAOjF,EAAMiF,WACxB1lC,IAAT0lC,EAAoB,CAEpB,MAAMgrB,EAAcx3D,EAAMiqD,WAAaA,GACjCwN,EAAiBtW,iBAAiBhkC,GAClCu6C,EAAqB,CAAC,EAI5B,IAAK,IAAIv8C,EAAI,EAAGA,EAAI07C,GAAgBhxD,OAAQsV,IAAK,CAC7C,MAAM3P,EAAOqrD,GAAgB17C,GACzB3P,KAAQ+7B,GACRpqB,EAAKyxB,aAAapjC,EAAM+7B,EAAM/7B,IAIlCksD,EAAmBlsD,GAAQisD,EAAejsD,EAC9C,CAIAksD,EAAmBhvB,WAAanB,EAAM,eAEtCgwB,EAAcC,EAAY,GAAKhrB,EAAM3gC,EAAM6rD,EAAoB,CAG3D7e,YAAaxkC,KAAKsjD,MAAM3wB,IACxBkkB,SAAUlrD,EAAMkrD,SAChBX,OAAQvqD,EAAMuqD,OACd5S,UAAW33C,EAAM23C,UACjB6S,aAAcxqD,EAAMwqD,aACpBH,eAAgBrqD,EAAMqqD,gBAE9B,MACIkN,EAAc,GAElBT,GAAiBtqB,KAAK/kC,IAAI5H,KAAKwU,KAAMkjD,EAAa9C,EAASt3C,EAAMoqB,EACrE,EAIAsvB,oBAGJ,MAAS,CACL3C,QAAS,SAAS0D,EAAOz6C,GAErB,OAAOA,aAAgBy7B,UAC3B,EACAppC,MAAO,SAAS2N,GACZ,GAAEvU,KAAKgQ,OAAOuE,EAAM,eACpB,MAAM06C,EAAY16C,EAAK26C,kBACnBD,GACAA,EAAUj/C,QAElB,EACAnR,IAAK,SAASmwD,EAAOnD,EAASt3C,GAC1B,IAAI85C,EAAY,cACZ7rD,EAAQ,GAAExC,KAAKpJ,IAAI2d,EAAM85C,GAC7B,QAAcnwD,IAAVsE,GAAuBA,IAAUwsD,EAAO,CAExC,GADA,GAAEhvD,KAAKnB,IAAI0V,EAAM85C,EAAWW,GACP,UAAjBz6C,EAAKgzB,QAGL,YADAhzB,EAAKisB,YAAcwuB,GAIvB,IAAI7vB,EAAa5qB,EAAK26C,kBACtB,GAAI/vB,GAAqC,UAAvBA,EAAWoI,QAEzBpI,EAAWqB,YAAcwuB,MACtB,CAEH,IAAIC,EAAYr9C,SAASwtB,gBAAgB7qB,EAAKipC,aAAc,SAC5DyR,EAAUzuB,YAAcwuB,EACxBz6C,EAAKuzB,aAAamnB,EAAW9vB,EACjC,CACJ,CACJ,IAIR,MC/MA,SAASgwB,GAAoB/W,EAAQt4B,GACjC,IAAIsvC,EAAa,IAAIh1C,GAAM,EAAG,GAC9B,OAAO,SAAShjB,GACZ,IAAIkiB,EAAGf,EACH82C,EAAU5jD,KAAK2sC,GAAQhhD,GAQ3B,OAPIi4D,GACA92C,EAASuH,EAAU,OAAIuvC,EAAQnwC,SAASb,YAAY+wC,GAAc,EAClE91C,EAAI+1C,EAAQhkD,QAEZiO,EAAI7N,KAAKlI,KAAK8H,MACdkN,EAAQ,GAEE,IAAVA,EAAoB,CAAEkpB,UAAW,aAAenoB,EAAEM,EAAI,IAAMN,EAAEG,EAAI,KAC/D,CAAEgoB,UAAW,aAAenoB,EAAEM,EAAI,IAAMN,EAAEG,EAAI,YAAclB,EAAQ,IAC/E,CACJ,CAEA,SAAS+2C,KACL,OAAO7jD,KAAK29C,MAAMa,QACtB,CAEA,MAAMsF,GAAyB,CAE3B,WAAc,CACVjE,QAASgE,GACT1oD,MAAO,IACP/H,IAAK,UAAS,MAAE2wD,EAAQ,IACpB,IAAIjtC,EACJ,GAAIse,SAAS2uB,IAAoB,IAAVA,EAAa,CAChC,IAAI1yC,EAEAA,EADA0yC,EAAQ,GACE/jD,KAAKgkD,sBAAwBD,GAAS,EAEvCA,EAEb,MAAMjsD,EAAOkI,KAAKikD,gBACZh9B,EAAsBjnB,KAAKkkD,4BAC3BC,EAAcrsD,EAAKkc,eAAe3C,EAAQ,CAAE4V,wBAC5Cm9B,EAActsD,EAAKkc,gBAAgB3C,EAAQ,CAAE4V,wBAC/Ck9B,GAAeC,IACfttC,EAAI,GAAGqtC,EAAY,GAAGzxC,eAAe0xC,EAAY,GAAG1xC,cAE5D,CAEA,MAAO,CAAEoE,EAAGA,GAAK9W,KAAKqkD,0BAC1B,GAGJ,qCAAsC,CAClCxE,QAASgE,GACT1oD,MAAO,YACP/H,IAAKswD,GAAoB,qBAAsB,CAAE3xC,QAAQ,KAG7D,uCAAwC,CACpC8tC,QAASgE,GACT1oD,MAAO,YACP/H,IAAKswD,GAAoB,qBAAsB,CAAE3xC,QAAQ,KAG7D,oCAAqC,CACjC8tC,QAASgE,GACT1oD,MAAO,YACP/H,IAAKswD,GAAoB,oBAAqB,CAAE3xC,QAAQ,KAG5D,sCAAuC,CACnC8tC,QAASgE,GACT1oD,MAAO,YACP/H,IAAKswD,GAAoB,oBAAqB,CAAE3xC,QAAQ,MAKhE+xC,GAAuB,wBAA0BA,GAAuB,sCACxEA,GAAuB,uBAAyBA,GAAuB,qCAEvE,YC3EA,SAASQ,GAAaC,EAAkBlwC,GACpC,IAAIuuC,EAAY,cACZ4B,EAAcnwC,GAAOA,EAAImwC,YAC7B,OAAO,SAAS74D,EAAOy0D,EAASt3C,GAC5B,IAAI/R,EAAQ,GAAExC,KAAKpJ,IAAI2d,EAAM85C,GAC7B,IAAK7rD,GAASA,EAAMpL,QAAUA,EAAO,CAEjC,IAAI84D,EAAcF,EAAiB54D,GACnCoL,EAAQ,CACJpL,MAAOA,EACPyoB,MAAOqwC,EACPC,UAAWD,EAAY1xC,QAE3B,GAAExe,KAAKnB,IAAI0V,EAAM85C,EAAW7rD,EAChC,CAEA,IAAIqd,EAAQrd,EAAMqd,MAAMhS,QACpBsiD,EAAY3tD,EAAM2tD,UAAUtiD,QAC5BuiD,EAAcD,EAAUj1C,SACxB6wC,EAAYF,EAAQ3wC,SAExBi1C,EAAUv2C,EAAImyC,EAAUnyC,EACxBu2C,EAAU12C,EAAIsyC,EAAUtyC,EAExB,IAAI42C,EAAWxE,EAAQ7lC,kBAAkBmqC,EAAWpE,GAEhDluC,EAA0B,IAApBsyC,EAAUl0C,OAAiC,IAAlB4vC,EAAQ5vC,MAAe,EAAIo0C,EAASxyC,GACnEC,EAA2B,IAArBqyC,EAAUj0C,QAAmC,IAAnB2vC,EAAQ3vC,OAAgB,EAAIm0C,EAASvyC,GAOzE,OALA+B,EAAM7H,MAAM6F,EAAIC,EAAIsyC,GAChBH,GACApwC,EAAMvB,WAAW8xC,EAAYx2C,GAAIw2C,EAAY32C,GAG1CoG,CACX,CACJ,CAGA,SAASywC,GAASxwC,GAKd,IAAID,EAAQkwC,IAJZ,SAAyB34D,GACrB,OAAO,IAAIujB,GAAK,GAAE6sB,kBAAkBpwC,GACxC,GAE0C0oB,GAC1C,OAAO,SAAS1oB,EAAOy0D,EAASt3C,GAE5B,MAAO,CACHgO,EAFO1C,EAAMzoB,EAAOy0D,EAASt3C,GAErB4J,YAEhB,CACJ,CAGA,SAASoyC,GAAczwC,GACnB,IAAID,EAAQkwC,GAAav1C,GAAUsF,GACnC,OAAO,SAAS1oB,EAAOy0D,EAASt3C,GAE5B,MAAO,CACHiH,OAFWqE,EAAMzoB,EAAOy0D,EAASt3C,GAEhB4J,YAEzB,CACJ,CAEA,MAAMqyC,GAAoB,CAEtB,qBAAsB,CAClB5pD,MAAO,IACP/H,IAAKyxD,GAAS,CAAEL,aAAa,KAGjC,oBAAqB,CACjBrpD,MAAO,IACP/H,IAAKyxD,GAAS,CAAEL,aAAa,KAGjC,0BAA2B,CACvBrpD,MAAO,SACP/H,IAAK0xD,GAAc,CAAEN,aAAa,KAGtC,yBAA0B,CACtBrpD,MAAO,SACP/H,IAAK0xD,GAAc,CAAEN,aAAa,MAK1CO,GAAkB,SAAWA,GAAkB,sBAC/CA,GAAkB,cAAgBA,GAAkB,2BAEpD,YC7FA,SAASC,GAAc/9C,GACnB,IAAIg+C,EAAS,CAAC,EAIVC,EAASj+C,EAAQi+C,OACC,iBAAXA,IACPD,EAAe,OAAIC,EACnBD,EAAa,KAAIC,GAIrB,IAAI/qB,EAAgBlzB,EAAQ,kBAM5B,YALsBxU,IAAlB0nC,IAA6BA,EAAgBlzB,EAAQ6uC,cACnCrjD,IAAlB0nC,IACA8qB,EAAO,kBAAoB9qB,EAC3B8qB,EAAO,gBAAkB9qB,GAEtB8qB,CACX,CAEA,SAASE,GAAYC,GACjB,MAAM,MAAE9B,GAAUtjD,KAIlB,MAAO,QAHmB,YAAbolD,EAAIjzD,KACXmxD,EAAM+B,cAAcD,GACpB9B,EAAMgC,eAAeF,KAE/B,CAEA,MA+CA,GA/CyB,CAErB,gBAAiB,CACbvF,QAASzjD,GACTjB,MAAO,eACP/H,IAAK,SAAS6xD,EAAQ7E,EAASt3C,EAAMoqB,GAEjC,OADA+xB,EAAS,GAAOD,GAAc9xB,GAAQ+xB,GAC/B,CAAE,eAAgB,QAAUjlD,KAAKsjD,MAAMiC,aAAaN,GAAU,IACzE,GAGJ,gBAAiB,CACbpF,QAASzjD,GACTjB,MAAO,aACP/H,IAAK,SAAS6xD,EAAQ7E,EAASt3C,EAAMoqB,GAEjC,OADA+xB,EAAS,GAAOD,GAAc9xB,GAAQ,CAAE,UAAa,eAAiB+xB,GAC/D,CAAE,aAAc,QAAUjlD,KAAKsjD,MAAMiC,aAAaN,GAAU,IACvE,GAGJ,gBAAiB,CACbpF,QAASzjD,GACTjB,MAAO,aACP/H,IAAK,SAAS6xD,EAAQ7E,EAASt3C,EAAMoqB,GAEjC,OADA+xB,EAAS,GAAOD,GAAc9xB,GAAQ+xB,GAC/B,CAAE,aAAc,QAAUjlD,KAAKsjD,MAAMiC,aAAaN,GAAU,IACvE,GAGJ,KAAQ,CACJpF,QAASzjD,GACThJ,IAAK+xD,IAGT,OAAU,CACNtF,QAASzjD,GACThJ,IAAK+xD,IAGT,OAAU,CACNtF,QAASzjD,GACThJ,IAAK,SAASW,GACV,MAAO,QAAUiM,KAAKsjD,MAAMkC,aAAazxD,GAAU,GACvD,ICnER,SAAS0xD,GAAcvF,EAAMC,EAAW7mC,GACpC,OAAO,SAAS3tB,EAAO+5D,GACnB,IAAI1U,EAEAA,EADU,WAAVrlD,EACQ+5D,EAASvF,GAAa,EACvBx0D,IAAU2tB,EACTosC,EAASvF,GACV/qB,SAASzpC,GAEPA,GAAS,GAAKA,EAAQ,GAAO+5D,EAASvF,GAAax0D,GAAUA,EAC/DkpD,GAAalpD,GACZ+5D,EAASvF,GAAa7wC,WAAW3jB,GAAS,IAE1C,EAGZ,IAAIqlB,EAAQ,IAAIrC,GAEhB,OADAqC,EAAMkvC,KAAUwF,EAASxF,GAAQlP,GAC1BhgC,CACX,CACJ,CAEA,MAuBA,GAvB2B,CAIvB,cAAe,CACXK,OAAQo0C,GAAc,IAAK,QAAS,UAKxC,cAAe,CACXp0C,OAAQo0C,GAAc,IAAK,SAAU,WAGzC,eAAgB,CACZp0C,OAAQ,SAAS7S,EAAKknD,GAClB,OAAO,EACD,CAAEv3C,GAAIu3C,EAASv3C,EAAGH,GAAI03C,EAAS13C,GAC/B,CAAEG,EAAG,EAAGH,EAAG,EACrB,ICpCR,SAAS23C,GAAoBC,GACzB,OAAO,SAAsBj6D,EAAOm0D,EAAGh3C,GACnC,MAAMmwB,EAAM,GAAEnwB,GACVmwB,EAAI/D,KAAK0wB,KAAej6D,GAC5BstC,EAAI/D,KAAK0wB,EAAWj6D,EACxB,CACJ,CAEA,MAAMk6D,GAAe,CAEjB,IAAO,CAGP,EAEA,KAAQ,CACJzyD,IAAKuyD,GAAoB,SAG7B,aAAc,CACVvyD,IAAKuyD,GAAoB,eAI7B,KAAQ,CACJvyD,IAAK,SAAS0yD,GACV,OAAiB,OAATA,QAA6BrzD,IAAZqzD,EAAKxwB,GAAoBwwB,EAAOA,EAAKxwB,EAClE,GAIJ,MAAS,CACLuqB,QAASzjD,GACThJ,IAAK,SAASoyC,EAAQ4a,EAASt3C,GAC3B,GAAEA,GAAM0jC,IAAIhH,EAChB,GAGJ,KAAQ,CACJrqC,MAAO,SAAS2N,GACZ,GAAEA,GAAMgwB,OACZ,EACA1lC,IAAK,SAASg5C,EAAMgU,EAASt3C,GACzB,GAAEA,GAAMsjC,KAAKA,EAAO,GACxB,GAIJx5C,MAAK,IAGT,GAAOizD,GAAcE,IACrB,GAAOF,GAAc,IACrB,GAAOA,GAAcG,IACrB,GAAOH,GAAczxC,IACrB,GAAOyxC,GAAcxsB,IACrB,GAAOwsB,GAAc,IAEd,MAAMnqB,GAAamqB,GC/BpBI,GAAmB,SAAStqD,EAAGC,GACjC,GAAI5K,MAAMC,QAAQ0K,GACd,OAAOC,CAEf,EAEA,SAASsqD,GAAsB96D,GAG3B,IAAK,MAAMN,KAAOM,EAAK,CAEnB,MAAMoH,EAAWpH,EAAIN,GACAoH,GAASM,KAAcxB,MAAMC,QAAQuB,IAItD8P,GAAQ9P,WACDpH,EAAIN,EAEnB,CACJ,CAEO,MAAMq7D,GAAOtI,GAAMh+B,OAAO,CAI7BvtB,YAAa,SAASopC,EAAY/D,GAE9B,IAAI92B,EACAqyB,EAAQwI,GAAc,CAAC,EAS3B,GARkC,mBAAvB17B,KAAK89C,eAEZ99C,KAAK89C,cAAc38C,MAAMnB,KAAMpB,WAEnCoB,KAAK+9C,IAAM35C,GAAS,KACpBpE,KAAK07B,WAAa,CAAC,EACf/D,GAAWA,EAAQn7B,aAAYwD,KAAKxD,WAAam7B,EAAQn7B,YACzDm7B,GAAWA,EAAQxZ,QAAO+U,EAAQlzB,KAAKme,MAAM+U,EAAOyE,IAAY,CAAC,GAChE92B,EAAWpP,GAAOuO,KAAM,YAAc,CAGvC,MAAMtG,IAAci+B,IAAmC,IAAxBA,EAAQyuB,cAAgCH,GACvE/yB,EAAQhyB,GAAM,CAAC,EAAGL,EAAUqyB,EAAOx5B,EAEvC,CACAsG,KAAK5M,IAAI8/B,EAAOyE,GAChB33B,KAAKk+C,QAAU,CAAC,EAChBl+C,KAAKm+C,WAAWh9C,MAAMnB,KAAMpB,UAChC,EAEAiU,UAAW,SAAS3B,EAAIC,EAAIkD,GAExB,MAAM,IAAIrL,MAAM,oCACpB,EAEAwJ,OAAQ,SAAS6B,GAEb,MAAM,eAAEgyC,EAAc,sBAAEC,GAAwB,GAAUjyC,GAAO,CAAC,EAC5DxT,EAAWpP,GAAOuO,KAAK1N,YAAYhH,UAAW,YAEpD,IAAuB,IAAnB+6D,EAA0B,CAE1B,MAAME,EAAkBlkD,GAAUrC,KAAK07B,YAEvC,OAAK4qB,GAELJ,GAAsBK,GAEfA,GAJ4BA,CAKvC,CAEA,IAAIC,EAAoB,CAAC,EACrB9qB,EAAar5B,GAAUrC,KAAK07B,aAET,IAAnB2qB,EAEAG,EAAoB3lD,GAGM7P,MAAMC,QAAQo1D,GAAkBA,EAAiB,CAAC,UAE1D1uD,SAAS7M,IACvB07D,EAAkB17D,GAAO+V,EAAS/V,IAAQ,CAAC,CAAC,IAKpD,MAAMy7D,EAAkB9L,GAAiB/e,EAAY,GAAK8qB,EAAmB,KAAM,QAAS,CAAEnM,SAAU,IAMxG,OAJIiM,GACAJ,GAAsBK,GAGnBA,CACX,EAEApI,WAAY,SAASxmB,GAEjB,MAAMknB,EAAc7+C,KAAKymD,iBACpB9uB,QAAoCllC,IAAzBklC,EAAQknB,IACpB7+C,KAAK5M,IAAIyrD,EAAa7+C,KAAK0mD,aAAc,CAAE3H,QAAQ,IAGvD/+C,KAAK2mD,eAAiB,CAAC,EACvB3mD,KAAK4mD,wBAA0B,CAAC,EAGhC5mD,KAAK6mD,eACL7mD,KAAKwJ,GAAG,eAAgBxJ,KAAK6mD,aAAc7mD,KAC/C,EAEAymD,eAAgB,WACZ,OAAOzmD,KAAK6+C,aAAe,IAC/B,EAEA6H,WAAY,WACR,MdiIG,uCAAuC3uD,QAAQ,SAAS,SAASge,GACpE,IAAIzF,EAAqB,GAAhBvO,KAAKuL,SAAiB,EAE/B,OADe,MAANyI,EAAazF,EAAS,EAAJA,EAAU,GAC5Bvd,SAAS,GACtB,GcpIA,EAKA8zD,aAAc,WAOV,IAAIC,EAAgB9mD,KAAK+mD,MAGrBA,EAAQ,CAAC,EACb,GAAM/mD,KAAK7U,IAAI,UAAU,SAAS+nC,EAAO3sB,GAEjC2sB,GAASA,EAAM4yB,YAGOrzD,IAAlBygC,EAAM4yB,KAAKxwB,GACXyxB,EAAM7zB,EAAM4yB,KAAKxwB,IAAMpC,EAAM4yB,KAE7BiB,EAAM7zB,EAAM4yB,MAAQ,CAAExwB,GAAIpC,EAAM4yB,MAG5C,IAIA,IAAIkB,EAAe,CAAC,EACpB,GAAMF,GAAe,SAAShB,EAAMxwB,GAE3ByxB,EAAMzxB,KAAK0xB,EAAa1xB,IAAM,EACvC,IAGIt1B,KAAKinD,QAAU3kD,GAAQ0kD,KAEJhnD,KAAKinD,MAAMC,kBAAkBlnD,KAAM,CAAEmnD,SAAS,IACpDxvD,SAAQ,SAASyvD,GAEtBJ,EAAaI,EAAKj8D,IAAI,UAAU26D,OAAOsB,EAAK7iD,QACpD,IAEoBvE,KAAKinD,MAAMC,kBAAkBlnD,KAAM,CAAEqnD,UAAU,IACrD1vD,SAAQ,SAASyvD,GAEvBJ,EAAaI,EAAKj8D,IAAI,UAAU26D,OAAOsB,EAAK7iD,QACpD,KAIJvE,KAAK+mD,MAAQA,CACjB,EAEAxiD,OAAQ,SAAS8P,EAAM,CAAC,GAIpB,MAAM,MAAE4yC,EAAK,WAAEzqD,GAAewD,KAC9B,IAAKinD,EAGD,OADIzqD,GAAYA,EAAW+H,OAAOvE,KAAMqU,GACjCrU,KAGXinD,EAAMK,WAAW,UAGjB,MAAMC,EAAavnD,KAAKwnD,gBACpBD,GACAA,EAAWE,QAAQznD,KAAMqU,GAI7B,MAAMqzC,EAAgB1nD,KAAK2nD,mBAC3B,IAAK,IAAI7gD,EAAI,EAAGkJ,EAAI03C,EAAcl2D,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAClD,MAAM63C,EAAQ+I,EAAc5gD,GACxB63C,GACAA,EAAMp6C,OAAO8P,EAErB,CAMA,OAJArU,KAAK28C,QAAQ,SAAU38C,KAAMinD,EAAMvrB,WAAW2iB,MAAOhqC,GAErD4yC,EAAMW,UAAU,UAET5nD,IACX,EAEA6nD,QAAS,SAASxzC,GACd,IAAI4yC,EAAQjnD,KAAKinD,MACjB,GAAIA,EAAO,CAGP,IAAI5I,GAFJhqC,EAAMxT,GAASwT,GAAO,CAAC,EAAG,CAAEyzC,kBAAkB,KAGtCC,MACJ1J,EAAQr+C,KAAK2nD,iBAAiB,CAAEI,MAAM,EAAMC,cAAmC,IAArB3zC,EAAI2zC,aAAwBC,aAAc5zC,EAAIyzC,mBACxGzJ,EAAMphC,QAAQjd,OAEdq+C,EAAQ,CAACr+C,MAGb,MAAMkoD,EAAc7zC,EAAIyzC,iBAAmBzJ,EAAQv7C,GAAOu7C,GAAOE,GAAQA,EAAKhzB,MAG9E,IAAIA,EADS07B,EAAMkB,YACJ9J,EAAM7sD,OAAS,EAE9B,MAAMgL,EAAayqD,EAAM97D,IAAI,SAE7B,IAAIi9D,EAAgB5rD,EAAWkG,UAAUzJ,QAAQivD,EAAY,MAAS1rD,EAAWhL,OAAS6sD,EAAM7sD,OAC3F42D,IACDA,EAAeF,EAAYvxD,MAAK,SAAS4nD,EAAM7sD,GAC3C,OAAO6sD,EAAKhzB,MAAQA,EAAI75B,CAC5B,KAGA02D,IACApoD,KAAKsnD,WAAW,YAEhB/7B,GAAQ8yB,EAAM7sD,OAEd02D,EAAYvwD,SAAQ,SAAS4mD,EAAM7sD,GAC/B6sD,EAAKnrD,IAAI,IAAKm4B,EAAI75B,EAAO2iB,EAC7B,IAEArU,KAAK4nD,UAAU,YAEvB,CAEA,OAAO5nD,IACX,EAEAqoD,OAAQ,SAASh0C,GACb,IAAI4yC,EAAQjnD,KAAKinD,MACjB,GAAIA,EAAO,CAGP,IAAI5I,GAFJhqC,EAAMxT,GAASwT,GAAO,CAAC,EAAG,CAAEyzC,kBAAkB,KAGtCC,MACJ1J,EAAQr+C,KAAK2nD,iBAAiB,CAAEI,MAAM,EAAMC,cAAmC,IAArB3zC,EAAI2zC,aAAwBC,aAAc5zC,EAAIyzC,mBACxGzJ,EAAMphC,QAAQjd,OAEdq+C,EAAQ,CAACr+C,MAGb,MAAMkoD,EAAc7zC,EAAIyzC,iBAAmBzJ,EAAQv7C,GAAOu7C,GAAOE,GAAQA,EAAKhzB,MAE9E,IAAIA,EAAI07B,EAAMqB,YAIVF,EAAiE,IAFpDnB,EAAM97D,IAAI,SAEIuX,UAAUzJ,QAAQivD,EAAY,IACxDE,IACDA,EAAeF,EAAYvxD,MAAK,SAAS4nD,EAAM7sD,GAC3C,OAAO6sD,EAAKhzB,MAAQA,EAAI75B,CAC5B,KAGA02D,IACApoD,KAAKsnD,WAAW,WAEhB/7B,GAAK8yB,EAAM7sD,OAEX02D,EAAYvwD,SAAQ,SAAS4mD,EAAM7sD,GAC/B6sD,EAAKnrD,IAAI,IAAKm4B,EAAI75B,EAAO2iB,EAC7B,IAEArU,KAAK4nD,UAAU,WAEvB,CAEA,OAAO5nD,IACX,EAEAo8B,OAAQ,SAASA,EAAQ/nB,GAGrB,YAAe5hB,IAAX2pC,EAA6Bp8B,KAAK7U,IAAI,UAEnC6U,KAAK5M,IAAI,SAAUgpC,EAAQ/nB,EACtC,EAEAsqC,MAAO,SAASJ,EAAMlqC,EAAM,CAAC,GACzB,MAAMgqC,EAAQrtD,MAAMC,QAAQstD,GAAQA,EAAO,CAACA,GAC5C,IAAKv+C,KAAKuoD,SAASlK,GACf,MAAM,IAAIr1C,MAAM,oCAEpB,GAAIqL,EAAIm0C,SACYtmD,GAAKm8C,EAAM1tD,KAAIolB,GAAKA,EAAEyxC,mBAG9B7vD,SAASykC,IAERA,GAILA,EAAOqsB,cAAcpK,EAAOhqC,EAAI,SAGjC,GAAIgqC,EAAM1nD,MAAKof,GAAKA,EAAE2yC,cAAgB1oD,KAAKs1B,KAAOvf,EAAEqmB,WACvD,MAAM,IAAIpzB,MAAM,uDAGpB,OADAhJ,KAAK2oD,YAAYtK,EAAOhqC,GACjBrU,IACX,EAEAynD,QAAS,SAASlJ,EAAMlqC,GACpB,MAAMgqC,EAAQrtD,MAAMC,QAAQstD,GAAQA,EAAO,CAACA,GAE5C,OADAv+C,KAAKyoD,cAAcpK,EAAOhqC,GACnBrU,IACX,EAEAuoD,SAAU,SAAShK,GAEf,OADcvtD,MAAMC,QAAQstD,GAAQA,EAAO,CAACA,IAC/BqK,OAAM7yC,GAAK/V,OAAS+V,IAAM/V,KAAK6oD,aAAa9yC,IAC7D,EAEA4yC,YAAa,SAAStK,EAAOhqC,GACzB,MAAMy0C,EAAY,QAClB9oD,KAAKsnD,WAAWwB,GAChB,MAAMrK,EAAS,GAAO,GAAIz+C,KAAK7U,IAAI,WACnCkzD,EAAM1mD,SAAQ4mD,IAEVE,EAAOF,EAAKC,SAAW,UAAY,QAAQD,EAAKjpB,IAChDipB,EAAKniB,OAAOp8B,KAAKs1B,GAAIjhB,EAAI,IAE7BrU,KAAK5M,IAAI,SAAU8O,GAAKu8C,GAASpqC,GACjCrU,KAAK4nD,UAAUkB,EACnB,EAEAL,cAAe,SAASpK,EAAOhqC,GAC3B,MAAMy0C,EAAY,UAClB9oD,KAAKsnD,WAAWwB,GAChBzK,EAAM1mD,SAAQ4mD,GAAQA,EAAKpjD,MAAM,SAAUkZ,KAC3CrU,KAAK5M,IAAI,SAAU8P,GAAQlD,KAAK7U,IAAI,aAAckzD,EAAM1tD,KAAI4tD,GAAQA,EAAKjpB,MAAMjhB,GAC/ErU,KAAK4nD,UAAUkB,EACnB,EAEAtB,cAAe,WAGX,IAAIuB,EAAW/oD,KAAKo8B,SAChB6qB,EAAQjnD,KAAKinD,MAEjB,OAAQ8B,GAAY9B,GAASA,EAAM+B,QAAQD,IAAc,IAC7D,EAKAE,aAAc,WAEV,IAAIC,EAAY,GAEhB,IAAKlpD,KAAKinD,MACN,OAAOiC,EAIX,IADA,IAAI3B,EAAavnD,KAAKwnD,gBACfD,GACH2B,EAAUt3D,KAAK21D,GACfA,EAAaA,EAAWC,gBAG5B,OAAO0B,CACX,EAEAvB,iBAAkB,SAAStzC,GAQvB,GANAA,EAAMA,GAAO,CAAC,GAMTrU,KAAKinD,MACN,MAAO,GAGX,GAAI5yC,EAAI0zC,KACJ,OAAI1zC,EAAI2zC,aACGhoD,KAAKmpD,qBAAqB90C,EAAI4zC,cAE9BjoD,KAAKopD,qBAAqB/0C,EAAI4zC,cAI7C,MAAMoB,EAAcrpD,KAAK7U,IAAI,UAC7B,GAAImX,GAAQ+mD,GACR,MAAO,GAGX,IAAIhL,EAAQgL,EAAY14D,IAAIqP,KAAKinD,MAAM+B,QAAShpD,KAAKinD,OAKrD,OAJI5yC,EAAI4zC,eACJ5J,EAAQv7C,GAAOu7C,GAAOE,GAAQA,EAAKhzB,OAGhC8yB,CACX,EAEA8K,qBAAsB,SAASlB,GAC3B,MAAM5J,EAAQ,GAERiL,EAAQ,GAGd,IAFAA,EAAM13D,KAAKoO,MAEJspD,EAAM93D,OAAS,GAAG,CACrB,MAAM4tD,EAAUkK,EAAM9d,QACtB6S,EAAMzsD,KAAKwtD,GAEX,MAAMsI,EAAgBtI,EAAQuI,iBAAiB,CAAEM,aAAcA,IAE/DqB,EAAM13D,QAAQ81D,EAClB,CAGA,OAFArJ,EAAM7S,QAEC6S,CACX,EAEA+K,qBAAsB,SAASnB,GAC3B,MAAM5J,EAAQ,GAER3pD,EAAQ,GAGd,IAFAA,EAAM9C,KAAKoO,MAEJtL,EAAMlD,OAAS,GAAG,CACrB,MAAM4tD,EAAU1qD,EAAM6L,MACtB89C,EAAMzsD,KAAKwtD,GAEX,MAAMsI,EAAgBtI,EAAQuI,iBAAiB,CAAEM,aAAcA,IAI/D,IAAK,IAAInhD,EAAI4gD,EAAcl2D,OAAS,EAAGsV,GAAK,IAAKA,EAC7CpS,EAAM9C,KAAK81D,EAAc5gD,GAEjC,CAGA,OAFAu3C,EAAM7S,QAEC6S,CACX,EAEAwK,aAAc,SAAStK,EAAMlqC,GAEzB,IAAIk1C,EAAS3oD,GAAS29C,GAAQA,EAAOA,EAAKjpB,GACtCyzB,EAAW/oD,KAAKo8B,SAKpB,GAHA/nB,EAAM,GAAO,CAAE0zC,MAAM,GAAQ1zC,GAGzBrU,KAAKinD,OAAS5yC,EAAI0zC,KAAM,CAExB,KAAOgB,GAAU,CACb,GAAIA,IAAaQ,EACb,OAAO,EAEXR,EAAW/oD,KAAKinD,MAAM+B,QAAQD,GAAU3sB,QAC5C,CAEA,OAAO,CAEX,CAII,OAAO2sB,IAAaQ,CAE5B,EAGAb,WAAY,WAER,QAAS1oD,KAAKo8B,QAClB,EAKAh6B,MAAO,SAASiS,GAIZ,IAFAA,EAAMA,GAAO,CAAC,GAEL0zC,KAkBL,OAAOrlD,GAAQ07C,GAAW,CAACp+C,MAAM2I,OAAO3I,KAAK2nD,iBAAiB,CAAEI,MAAM,OAftE,IAAI3lD,EAAQy7C,GAAMvyD,UAAU8W,MAAMjB,MAAMnB,KAAMpB,WAS9C,OAPAwD,EAAMhP,IAAI4M,KAAKymD,iBAAkBzmD,KAAK0mD,cAEtCtkD,EAAMjH,MAAM,UAGZiH,EAAMjH,MAAM,UAELiH,CAQf,EAaA/W,KAAM,SAASuH,EAAOjH,EAAO0oB,GAEzB,IACIm1C,EAAY5oD,GAAShO,GAEzB,GAAI42D,GAAax4D,MAAMC,QAAQ2B,GAAQ,CAInC,GAAIgM,UAAUpN,OAAS,EAAG,CAEtB,IAAIsG,EACAgyC,EAEA0f,EAEA1f,GADAhyC,EAAOlF,GACUtC,MAAM,MAEvBwH,EAAOlF,EAAM9D,KAhBb,KAiBAg7C,EAAYl3C,EAAMkI,SAGtB,IAAI4D,EAAWorC,EAAU,GACrB2f,EAAkB3f,EAAUt4C,OAEhC,MAAMmmC,EAAUtjB,GAAO,CAAC,EACxBsjB,EAAQ+xB,aAAe5xD,EACvB6/B,EAAQgyB,cAAgBh+D,EACxBgsC,EAAQiyB,kBAAoB9f,EACtB,YAAanS,IACfA,EAAQkyB,SAAU,GAWtB,IARA,IAAIl3C,EAAS,CAAC,EAKVm3C,EAAcn3C,EACdo3C,EAAerrD,EAEVoI,EAAI,EAAGA,EAAI2iD,EAAiB3iD,IAAK,CACtC,IAAIkjD,EAAWlgB,EAAUhjC,GACrBmjD,EAAehvD,OAAOm6B,SAASo0B,EAAYvuD,OAAO+uD,GAAYA,GAClEF,EAAcA,EAAYC,GAAgBE,EAAe,GAAK,CAAC,EAC/DF,EAAeC,CACnB,CAGAr3C,EAASigC,GAAUjgC,EAAQm3B,EAAWn+C,EAAO,KAE7C,IAAIu+D,EAAiBhpD,GAAM,CAAC,EAAGlB,KAAK07B,YAGpC/D,EAAQkyB,SAAW/W,GAAYoX,EAAgBpyD,EAAM,KAGrD,IAAI4jC,EAAax6B,GAAMgpD,EAAgBv3C,GAEvC,OAAO3S,KAAK5M,IAAIsL,EAAUg9B,EAAWh9B,GAAWi5B,EAEpD,CAEI,OAAO8a,GAAUzyC,KAAK07B,WAAY9oC,EA7D9B,IA+DZ,CAEA,MAAM+kC,EAAUhsC,GAAS,CAAC,EAE1BgsC,EAAQ+xB,aAAe,KACvB/xB,EAAQgyB,cAAgB/2D,EACxB+kC,EAAQiyB,kBAAoB,GACtB,YAAajyB,IACfA,EAAQkyB,SAAU,GAItB,MAAMrK,EAAoB,CAAC,EAC3B,IAAK,MAAM10D,KAAO8H,EAAO,CAErB,MAAM,aAAEu3D,GAAiBjpD,GAAM,CAAC,EAAG,CAAEipD,aAAcnqD,KAAK07B,WAAW5wC,IAAQ,CAAEq/D,aAAcv3D,EAAM9H,KACjG00D,EAAkB10D,GAAOq/D,CAC7B,CAEA,OAAOnqD,KAAK5M,IAAIosD,EAAmB7nB,EACvC,EAGAyyB,WAAY,SAAStyD,EAAMuc,GAEvBA,EAAMA,GAAO,CAAC,EAEd,IAAIy1B,EAAY94C,MAAMC,QAAQ6G,GAAQA,EAAOA,EAAKxH,MAAM,KAKpDoO,EAAWorC,EAAU,GAGzB,GAFiB,UAAbprC,IAAsB2V,EAAIg2C,OAAQ,GAEb,IAArBvgB,EAAUt4C,OAEV,OAAOwO,KAAK7E,MAAMrD,EAAMuc,GAI5B,IAAIi2C,EAAaxgB,EAAUhvC,MAAM,GAC7B6uD,EAAgB3pD,KAAK7U,IAAIuT,GAC7B,OAAIirD,QAA8D3pD,MAClE2pD,EAAgBtnD,GAAUsnD,GAE1B7W,GAAY6W,EAAeW,EAAY,KAEhCtqD,KAAK5M,IAAIsL,EAAUirD,EAAet1C,GAC7C,EAGA6gB,KAAM,SAAShC,EAAOvnC,EAAO0oB,GAEzB,IAAIpT,EAAOjQ,MAAM8W,KAAKlJ,WACtB,OAAoB,IAAhBqC,EAAKzP,OACEwO,KAAK7U,IAAI,UAGhB6F,MAAMC,QAAQiiC,GACdjyB,EAAK,GAAK,CAAC,SAAS0H,OAAOuqB,GACpBtyB,GAASsyB,GAGhBjyB,EAAK,GAAK,SAAWiyB,EAIrBjyB,EAAK,GAAK,CAAE,MAAUiyB,GAGnBlzB,KAAK3U,KAAK8V,MAAMnB,KAAMiB,GACjC,EAGAg6B,WAAY,SAASnjC,EAAMuc,GAEvB,OAAIrjB,MAAMC,QAAQ6G,GAEPkI,KAAKoqD,WAAW,CAAC,SAASzhD,OAAO7Q,IAGrCkI,KAAKoqD,WAAW,SAAWtyD,EAAMuc,EAC5C,EAEAk2C,WAAY,SAASzyD,EAAMnM,EAAO0oB,EAAKm2C,GAEnCA,EAAQA,GAAS,IASjBn2C,EAAM,GAPS,CACX66B,SAAU,IACVE,MAAO,GACPqb,eAAgBrT,GAAO5qC,OACvBk+C,cAAe1S,GAAYhD,QAGR3gC,GAEvB,IACIs2C,EADAC,EAAiB,EAGjBC,EAAS,SAASC,GAElB,IAAIx1B,EAAIy1B,EAAUpB,GAIlBoB,GADAD,GADAF,EAAiBA,GAAkBE,GAEdz2C,EAAI66B,UAEV,EACXlvC,KAAK2mD,eAAe7uD,GAAQw9B,EAAK+d,GAAUwX,IAE3CE,EAAW,SACJ/qD,KAAK2mD,eAAe7uD,IAG/B6xD,EAAgBgB,EAAsBt2C,EAAIo2C,eAAeM,IAEzD12C,EAAI22C,aAAe11B,EAEnBt1B,KAAK3U,KAAKyM,EAAM6xD,EAAet1C,GAE1BihB,GAAIt1B,KAAK28C,QAAQ,iBAAkB38C,KAAMlI,EAElD,EAAE/H,KAAKiQ,MAEP,MAAM,wBAAE4mD,GAA4B5mD,KACpC,IAAIirD,EA0BJ,OALAA,EAAY1b,YAnBKsE,IAET+S,EAAwB9uD,KACxB8uD,EAAwB9uD,GAAQoL,GAAQ0jD,EAAwB9uD,GAAOmzD,GAC1B,IAAzCrE,EAAwB9uD,GAAMtG,eACvBo1D,EAAwB9uD,IAIvCkI,KAAKkrD,uBAAuBpzD,EAAM0yD,GAElCG,EAAwBt2C,EAAIq2C,cAAcjY,GAAUzyC,KAAK07B,WAAY5jC,EAAM0yD,GAAQ7+D,GAEnFqU,KAAK2mD,eAAe7uD,GAAQu7C,GAAUQ,GAEtC7zC,KAAK28C,QAAQ,mBAAoB38C,KAAMlI,EAAK,GAIduc,EAAI+6B,MAAOyb,GAE7CjE,EAAwB9uD,KAAU8uD,EAAwB9uD,GAAQ,IAClE8uD,EAAwB9uD,GAAMlG,KAAKq5D,GAE5BA,CACX,EAEAE,eAAgB,WACZ,OAAO/nD,GACHpY,OAAO0F,KAAKsP,KAAK2mD,gBACjB37D,OAAO0F,KAAKsP,KAAK4mD,yBAEzB,EAEAwE,yBAA0B,SAAStzD,EAAM0yD,EAAQ,KAC7C,MAAM,wBAAE5D,EAA0B,CAAC,GAAK5mD,KACxC,IAAIqrD,EAAcrgE,OAAO0F,KAAKk2D,GAC9B,GAAI9uD,EAAM,CACN,MAAMgyC,EAAYhyC,EAAKxH,MAAMk6D,GAC7Ba,EAAcA,EAAYt3D,QAAQjJ,GACvB0X,GAAQsnC,EAAWh/C,EAAIwF,MAAMk6D,GAAO1vD,MAAM,EAAGgvC,EAAUt4C,UAEtE,CAQA,OAPA65D,EAAY1zD,SAAS7M,IACK87D,EAAwB97D,GAEhC6M,SAAQqzD,GAAgBlb,aAAakb,YAC5CpE,EAAwB97D,EAAI,IAGhCkV,IACX,EAEA,sBAAAkrD,CAAuBpzD,EAAM0yD,EAAQ,KACjC,MAAM,eAAE7D,EAAiB,CAAC,GAAK3mD,KAC/B,IAAIqrD,EAAcrgE,OAAO0F,KAAKi2D,GAC9B,GAAI7uD,EAAM,CACN,MAAMgyC,EAAYhyC,EAAKxH,MAAMk6D,GAC7Ba,EAAcA,EAAYt3D,QAAQjJ,GACvB0X,GAAQsnC,EAAWh/C,EAAIwF,MAAMk6D,GAAO1vD,MAAM,EAAGgvC,EAAUt4C,UAEtE,CACA65D,EAAY1zD,SAAS7M,IACjB,MAAMkgE,EAAerE,EAAe77D,GAEpCmpD,GAAY+W,UACLrE,EAAe77D,GACtBkV,KAAK28C,QAAQ,iBAAkB38C,KAAMlV,EAAI,GAEjD,EAEAwgE,gBAAiB,SAASxzD,EAAM0yD,EAAQ,KAGpC,OAFAxqD,KAAKorD,yBAAyBtzD,EAAM0yD,GACpCxqD,KAAKkrD,uBAAuBpzD,EAAM0yD,GAC3BxqD,IACX,EAIAurD,MAAO,SAAStE,EAAO5yC,GAGnB,OADA4yC,EAAMuE,QAAQxrD,KAAMqU,GACbrU,IACX,EAKAyrD,SAAU,SAASnI,GAEf,OAAOA,EAAMoI,gBAAgB1rD,KACjC,EAEA2rD,UAAW,WAEP,OAAO,CACX,EAEAnN,OAAQ,WAEJ,OAAO,CACX,EAEA8I,WAAY,SAASnwD,EAAMkd,GAGvB,OADIrU,KAAKinD,OAASjnD,KAAKinD,MAAMK,WAAWnwD,EAAM,GAAO,CAAC,EAAGkd,EAAK,CAAEkqC,KAAMv+C,QAC/DA,IACX,EAEA4nD,UAAW,SAASzwD,EAAMkd,GAGtB,OADIrU,KAAKinD,OAASjnD,KAAKinD,MAAMW,UAAUzwD,EAAM,GAAO,CAAC,EAAGkd,EAAK,CAAEkqC,KAAMv+C,QAC9DA,IACX,EAEA4rD,cAAe,SAASlwB,GAEpB,IAAImwB,EAAO,EACX,IAAKnwB,EAAY,OAAOmwB,EACxB,IAAK,IAAI/gE,KAAO4wC,EACPA,EAAWnwC,eAAeT,IAASkV,KAAKu/C,WAAWz0D,KACxD+gE,GAAQnwB,EAAW5wC,IAEvB,OAAO+gE,CACX,EAEA/+C,MAAO,WAGH,OAAO,CACX,EAEA8wB,SAAU,WAGN,OAAO,IAAI,GAAQ,EAAG,EAC1B,EAEArS,EAAG,WACC,OAAOvrB,KAAK7U,IAAI,MAAQ,CAC5B,EAEA2gE,0BAA2B,WAGvB,OAAO,IAAI,EACf,EAEA10B,QAAS,WAGL,OAAO,IAAI,GAAO,EAAG,EAAG,EAAG,EAC/B,EAEA,2BAAA20B,CAA4Bj/C,EAAOqB,EAAGH,GAClC,MAAMgD,EAAQ,IAAI,GAAQ7C,EAAGH,GAE7B,OADIlB,GAAOkE,EAAMe,OAAO/R,KAAKo3B,UAAUlhB,SAAUpJ,GAC1CkE,CACX,EAEA,4BAAAg7C,CAA6B79C,EAAGH,GAE5B,OAAOhO,KAAK+rD,6BACP/rD,KAAK8M,QAEN9M,KAAK49B,WAAWvsB,OAAOlD,EAAGH,GAElC,EAEA,4BAAAi+C,CAA6B99C,EAAGH,GAC5B,OAAOhO,KAEF+rD,4BAA4B/rD,KAAK8M,QAASqB,EAAGH,GAE7C7K,WAAWnD,KAAK49B,WACzB,GAED,CAECsuB,uBAAwB,SAAStwB,GAE7B,IAAIuwB,EAAQnsD,KAAK07B,WACb0wB,EAAc1wB,GAClB,OAAQywB,GAASA,EAAMvwB,IAAcwwB,EAAYxwB,EACrD,EAEAywB,OAAQ,SAASl6D,EAAM0O,EAAUw8C,EAAYC,GAEzCD,EAAa,GAAO,CAChBx8C,SAAUG,GAAa,CAAE7O,KAAMA,GAAQ0O,EAAUb,KAAK1U,UAAUuV,WACjEw8C,GAEH,IAAI8I,EAAOnmD,KAAK6f,OAAOw9B,EAAYC,GAOnC,MAJqB,oBAAVgP,OAAyB,GAAIA,MAAO,WAC3C1Z,GAAU0Z,MAAMC,OAAQp6D,EAAMg0D,EAAM,KAGjCA,CACX,ICt8BJ,SAASqG,GAAmBx7C,EAAOlE,EAAOuH,GAEtC,IAAIo4C,EAAQz7C,EAAMwB,SAIlB,OAFAi6C,EAAM3/C,MAAQA,GAAS,EAEhB,GAAc,CAAC,EAAGuH,EAAKo4C,EAClC,CAEA,SAASC,GAAW3F,EAAOp2C,EAAIC,EAAI+7C,GAC/B,OAAO5F,EAAMp2D,KAAI,SAASm1D,EAAMp0D,EAAOq1D,GACnC,IAAIl5C,EAAI7N,KAAKqT,SAAU3hB,EAAQ,IAAOq1D,EAAMv1D,QAK5C,OAHIs0D,EAAK50C,IAAM40C,EAAK30C,KAChBtD,EAAEwD,OAAOy0C,EAAK50C,IAAM,EAAG40C,EAAK30C,IAAM,GAE/Bq7C,GAAmB3+C,EAAExB,QAAS,EAAGugD,GAAaD,EAAQ7G,GACjE,GAAG,GAAOn1C,EAAIC,GAClB,CAEA,SAASi8C,GAAc9F,EAAO4F,EAAQ9mB,EAAYinB,GAE9C,IAAI52C,EAASy2C,EAAOz2C,SAChBpC,EAAQ64C,EAAOn8C,MAAQm8C,EAAOl8C,OAC9BE,EAAKg8C,EAAO1wC,YAEZ7F,EAAU,GAAUJ,SAAS22C,GAEjC,OAAO5F,EAAMp2D,KAAI,SAASm1D,EAAMp0D,EAAOq1D,GAEnC,IAAIj6C,EAAQ+4B,EAAainB,EAAOp7D,EAAOq1D,EAAMv1D,QACzCof,EAAKD,EAAGvO,QACP2P,OAAOmE,GAASpJ,GAChBP,MAAMuH,EAAO,EAAGoC,GAEjBnF,EAAQ+0C,EAAKiH,oBAAsB32C,EAAQoB,aAAa5G,GAAM,EAYlE,OATIk1C,EAAK50C,IAAM40C,EAAK30C,KAChBP,EAAGS,OAAOy0C,EAAK50C,IAAM,EAAG40C,EAAK30C,IAAM,GAInC20C,EAAKkH,IACLp8C,EAAGgB,KAAKsE,EAAQ4vC,EAAKkH,IAGlBR,GAAmB57C,EAAGvE,QAAS0E,EAAO67C,GAAaD,EAAQ7G,GACtE,GACJ,CAGA,SAAS8G,GAAa75C,EAAM9R,GACxB,IAAI,EAAEkN,EAAC,EAAEH,EAAC,MAAElB,GAAU7L,EAWtB,OAVI,GAAkBkN,GAClBA,EAAImB,WAAWnB,GAAK,IAAM4E,EAAKvC,MACxB,GAAsBrC,KAC7BA,EAAIlT,OAAO,GAAwBkT,EAAG4E,KAEtC,GAAkB/E,GAClBA,EAAIsB,WAAWtB,GAAK,IAAM+E,EAAKtC,OACxB,GAAsBzC,KAC7BA,EAAI/S,OAAO,GAAwB+S,EAAG+E,KAEnC,CAAE5E,IAAGH,IAAGlB,QACnB,CAGA,SAASmgD,GAASl6C,EAAM9R,GACpB,MAAM,EAAEkN,EAAC,EAAEH,GAAM4+C,GAAa75C,EAAM9R,GACpC,OAAO,IAAI,GAAQkN,GAAK,EAAGH,GAAK,EACpC,CASO,MAAMooB,GAAW,SAAS2wB,EAAO4F,GACpC,OAAO5F,EAAMp2D,KAAIm1D,IACb,MAAMoH,EAAiBD,GAASN,EAAQ7G,GAAMz5C,QAAQmG,SAEtD,OADA06C,EAAepgD,MAAQg5C,EAAKh5C,OAAS,EAC9BogD,CAAc,GAE7B,EAQazmD,GAAK,SAASsgD,EAAO4F,EAAQt4C,GACtC,OAAOA,EAAI5N,GAAGsgD,EAAO4F,EAAQt4C,EACjC,EAQaG,GAAO,SAASuyC,EAAO4F,EAAQt4C,GAKxC,OAAOq4C,GAAW3F,EAHNkG,GAASN,EAAQt4C,EAAIzU,OAAS+sD,EAAOl9C,UACvCw9C,GAASN,EAAQt4C,EAAIxU,KAAO8sD,EAAOrzC,UAERqzC,EACzC,EAQa35C,GAAO,SAAS+zC,EAAO4F,EAAQt4C,GACxC,OAAOq4C,GAAW3F,EAAO4F,EAAOl9C,SAAUk9C,EAAOj0C,aAAci0C,EACnE,EAQaz5C,GAAQ,SAAS6zC,EAAO4F,EAAQt4C,GACzC,OAAOq4C,GAAW3F,EAAO4F,EAAOxxC,WAAYwxC,EAAOrzC,SAAUqzC,EACjE,EAQa,GAAM,SAAS5F,EAAO4F,EAAQt4C,GACvC,OAAOq4C,GAAW3F,EAAO4F,EAAOl9C,SAAUk9C,EAAOxxC,WAAYwxC,EACjE,EAQax5C,GAAS,SAAS4zC,EAAO4F,EAAQt4C,GAC1C,OAAOq4C,GAAW3F,EAAO4F,EAAOj0C,aAAci0C,EAAOrzC,SAAUqzC,EACnE,EAQaQ,GAAgB,SAASpG,EAAO4F,EAAQt4C,GAEjD,IAAIwxB,EAAaxxB,EAAIwxB,YAAc,EAC/BunB,EAAY/4C,EAAIg5C,MAAQ,IAAMtG,EAAMv1D,OAExC,OAAOq7D,GAAc9F,EAAO4F,EAAQ9mB,GAAY,SAASn0C,GACrD,OAAOA,EAAQ07D,CACnB,GACJ,EAQa,GAAU,SAASrG,EAAO4F,EAAQt4C,GAE3C,IAAIwxB,EAAaxxB,EAAIwxB,YAAc,EAC/BunB,EAAY/4C,EAAIg5C,MAAQ,GAE5B,OAAOR,GAAc9F,EAAO4F,EAAQ9mB,GAAY,SAASn0C,EAAOmqD,GAC5D,OAAQnqD,EAAQ,GAAMmqD,EAAQ,GAAKuR,CACvC,GACJ,ECtLA,SAASE,GAAgBC,EAAMC,GAI3B,OAAO,GAAkB,CAAC,EAAGD,EAAMC,EAAM,CACrCr/C,EAAG,EACHH,EAAG,EACHlB,MAAO,EACPomB,MAAO,CAAC,GAEhB,CAEA,SAASu6B,GAAcd,GAEnB,IAAIz2C,EAASy2C,EAAOz2C,SAEhBw3C,EAAKx3C,EAAOnF,MAAM47C,EAAOl9C,UACzBk+C,EAAKz3C,EAAOnF,MAAM47C,EAAOj0C,cACzBk1C,EAAK13C,EAAOnF,MAAM47C,EAAOrzC,UAG7B,MAAO,CAACo0C,EAFCx3C,EAAOnF,MAAM47C,EAAOxxC,YAEbyyC,EAAID,EACxB,CAEA,SAASE,GAAcC,EAAcnB,EAAQoB,EAAY15C,GAErDA,EAAM,GAAc,CAAC,EAAGA,EAAK,CAAEhD,OAAQ,KACvC,IAEIwE,EAAIC,EAAI9H,EAAGggD,EAFXlhD,EAAQ6/C,EAAOz2C,SAASnF,MAAM+8C,GAG9Bz8C,EAASgD,EAAIhD,OACb48C,EAAc,EAElB,MAAOC,EAAcC,EAAiBC,EAAkBC,GAAiBZ,GAAcd,GAClF7/C,EAAQqhD,GAAqBrhD,EAAQshD,GACtCpgD,EAAI,OACJ6H,EAAKxE,EACLyE,EAAK,EACLk4C,EAAa,SACNlhD,EAAQohD,GACfr4C,EAAK,EACLC,GAAMzE,EACF08C,GACAE,GAAe,GACfD,EAAa,QACbhgD,EAAI,SAEJggD,EAAa,SACbhgD,EAAI,MAEDlB,EAAQuhD,GACfrgD,EAAI,OACJ6H,GAAMxE,EACNyE,EAAK,EACLk4C,EAAa,QAEbn4C,EAAK,EACLC,EAAKzE,EACD08C,GACAE,EAAc,GACdD,EAAa,QACbhgD,EAAI,SAEJggD,EAAa,SACbhgD,EAAI,SAIZ,IAAI3B,EAAQtK,KAAKsK,MACjB,OAAOihD,GAAgBj5C,EAAK,CACxBlG,EAAG9B,EAAMwJ,GACT7H,EAAG3B,EAAMyJ,GACThJ,MAAOmhD,EACP/6B,MAAO,CAAEo7B,UAAW,CAAEtgD,IAAGggD,gBAEjC,CAEA,SAASO,GAAaT,EAAcnB,EAAQoB,EAAY15C,GAEpDA,EAAM,GAAc,CAAC,EAAGA,EAAK,CAAEhD,OAAQ,KACvC,IAEIwE,EAAIC,EAAI9H,EAAGggD,EAFXlhD,EAAQ6/C,EAAOz2C,SAASnF,MAAM+8C,GAG9Bz8C,EAASgD,EAAIhD,OACb48C,EAAc,EAElB,MAAOC,EAAcC,EAAiBC,EAAkBC,GAAiBZ,GAAcd,GAClF7/C,EAAQqhD,GAAqBrhD,EAAQshD,GACtCpgD,EAAI,OACJ6H,GAAMxE,EACNyE,EAAK,EACLk4C,EAAa,OACNlhD,EAAQohD,GACfr4C,EAAK,EACLC,EAAKzE,EACD08C,GACAE,EAAc,GACdD,EAAa,QACbhgD,EAAI,SAEJggD,EAAa,SACbhgD,EAAI,SAEDlB,EAAQuhD,GACfrgD,EAAI,OACJ6H,EAAKxE,EACLyE,EAAK,EACLk4C,EAAa,UAEbn4C,EAAK,EACLC,GAAMzE,EACF08C,GACAE,GAAe,GACfD,EAAa,QACbhgD,EAAI,SAEJggD,EAAa,SACbhgD,EAAI,MAIZ,IAAI3B,EAAQtK,KAAKsK,MACjB,OAAOihD,GAAgBj5C,EAAK,CACxBlG,EAAG9B,EAAMwJ,GACT7H,EAAG3B,EAAMyJ,GACThJ,MAAOmhD,EACP/6B,MAAO,CAAEo7B,UAAW,CAAEtgD,IAAGggD,gBAEjC,CAEA,SAASQ,GAAaC,EAAkBV,EAAY15C,GAEhDA,EAAM,GAAc,CAAC,EAAGA,EAAK,CAAEhD,OAAQ,KAEvC,IASI28C,EATAv+C,EAAS,GAAQ,EAAG,GACpB3C,GAAS2hD,EAAiB19C,MAAMtB,GAChCw+C,EAAcnhD,EACduE,EAASo9C,EAAiBrsD,QACzBwP,KAAKnC,EAAQ4E,EAAIhD,QACjBlO,WAAWsrD,GACXpiD,QAED2B,EAAI,QAGHlB,EAAQ,IAAM,KAAQ,GACvBkhD,EAAaD,EAAa,MAAQ,SAC7BA,IAAyB,MAAXjhD,IACfkB,EAAI,QAEDlB,GAAS,KAAOA,GAAS,IAChCkhD,EAAa,QACbC,EAAcnhD,EAAQ,KAEtBkhD,EAAa,MAGjB,IAAI3hD,EAAQtK,KAAKsK,MACjB,OAAOihD,GAAgBj5C,EAAK,CACxBlG,EAAG9B,EAAMgF,EAAOlD,GAChBH,EAAG3B,EAAMgF,EAAOrD,GAChBlB,MAAQ,EAAemhD,EAAc,EACrC/6B,MAAO,CAAEo7B,UAAW,CAAEtgD,IAAGggD,gBAEjC,CAEO,MAAMU,GAAS,SAASC,EAAeC,EAASv6C,GACnD,OAAOi5C,GAAgBj5C,EAC3B,EAEa,GAAO,SAASy5C,EAAcnB,EAAQt4C,GAC/C,OAAOi5C,GAAgBj5C,EAAK,CACxBlG,GAAI,GACJ+kB,MAAO,CAAEo7B,UAAW,CAAEtgD,EAAG,OAAQggD,WAAY,SAErD,EAEa,GAAQ,SAASF,EAAcnB,EAAQt4C,GAChD,OAAOi5C,GAAgBj5C,EAAK,CACxBlG,EAAG,GACH+kB,MAAO,CAAEo7B,UAAW,CAAEtgD,EAAG,OAAQggD,WAAY,WAErD,EAEa,GAAM,SAASF,EAAcnB,EAAQt4C,GAC9C,OAAOi5C,GAAgBj5C,EAAK,CACxBrG,GAAI,GACJklB,MAAO,CAAEo7B,UAAW,CAAEtgD,EAAG,IAAKggD,WAAY,YAElD,EAEa,GAAS,SAASF,EAAcnB,EAAQt4C,GACjD,OAAOi5C,GAAgBj5C,EAAK,CACxBrG,EAAG,GACHklB,MAAO,CAAEo7B,UAAW,CAAEtgD,EAAG,OAAQggD,WAAY,YAErD,EAEaa,GAAkB,SAASf,EAAcnB,EAAQt4C,GAC1D,OAAOw5C,GAAcC,EAAcnB,GAAQ,EAAMt4C,EACrD,EAEay6C,GAAU,SAAShB,EAAcnB,EAAQt4C,GAClD,OAAOw5C,GAAcC,EAAcnB,GAAQ,EAAOt4C,EACtD,EAEa06C,GAAiB,SAASjB,EAAcnB,EAAQt4C,GACzD,OAAOk6C,GAAaT,EAAcnB,GAAQ,EAAMt4C,EACpD,EAEa26C,GAAS,SAASlB,EAAcnB,EAAQt4C,GACjD,OAAOk6C,GAAaT,EAAcnB,GAAQ,EAAOt4C,EACrD,EAEa46C,GAAS,SAASnB,EAAcnB,EAAQt4C,GACjD,OAAOm6C,GAAaV,EAAa3qD,WAAWwpD,EAAOz2C,WAAW,EAAO7B,EACzE,EAEa66C,GAAiB,SAASpB,EAAcnB,EAAQt4C,GACzD,OAAOm6C,GAAaV,EAAa3qD,WAAWwpD,EAAOz2C,WAAW,EAAM7B,EACxE,ECzNA,IAAI86C,GAAW,SAAS56D,GAEpB,IAAI66D,EAAa,GAAe76D,IAAS,CAAC,EAC1CyL,KAAK+mD,MAAQ,GACb/mD,KAAKqvD,OAAS,CAAC,EACfrvD,KAAKsvD,oBAAsB,EAC3BtvD,KAAKuvD,yBAA2B,EAEhCvvD,KAAKwvD,MAAMJ,EACf,EAEAD,GAAS7jE,UAAY,CAEjBmkE,SAAU,WACN,OAAOzvD,KAAK+mD,KAChB,EAEA2I,SAAU,SAASv4D,GACf,OAAO6I,KAAKqvD,OAAOl4D,IAAS,CAAC,CACjC,EAEAw4D,gBAAiB,SAASC,GAEtB,OAAO5vD,KAAK+mD,MAAMhzD,QAAO,SAAS+xD,GAC9B,OAAOA,EAAKzT,QAAUud,CAC1B,GACJ,EAEAC,qBAAsB,SAASD,EAAWjD,GAEtC,IAAIta,EAAQryC,KAAK0vD,SAASE,GACtB7I,EAAQ/mD,KAAK2vD,gBAAgBC,GAE7BE,EAAgBzd,EAAMzU,UAAY,CAAC,EACnCmyB,EAAoBD,EAAc34D,KAClCwT,EAAY3K,KAAKsvD,oBAChB3kD,EAAUolD,KACXA,EAAoB,QAGxB,IAAIC,EAAYF,EAAc7uD,MAAQ,CAAC,EACnCgvD,EAAYlJ,EAAMp2D,KAAI,SAASm1D,GAC/B,OAAOA,GAAQA,EAAKloB,UAAYkoB,EAAKloB,SAAS38B,IAClD,IACIivD,EAA2BvlD,EAAUolD,GAAmBE,EAAWtD,EAAQqD,GAE3ElxD,EAAc,CACdioD,MAAOA,EACPt1D,OAAQ,IAgBZ,OAbA,GAAay+D,GAA0BlsD,OAAO,SAAS2kC,EAAKwnB,EAAoBz+D,GAC5E,IAAIo0D,EAAOnd,EAAIoe,MAAMr1D,GASrB,OARAi3C,EAAIl3C,OAAOG,KAAK,CACZw+D,OAAQtK,EAAKxwB,GACb66B,mBAAoBA,EACpBE,oBAAqBrwD,KAAKswD,oBAAoBxK,EAAMn3C,GAAMwhD,GAAqBxD,GAC/E4D,UAAWzK,EAAK5yB,MAChBs9B,SAAU1K,EAAKtuD,KACfi5D,UAAW3K,EAAK4K,MAAMl5D,OAEnBmxC,CACX,EAAE54C,KAAKiQ,MAAOlB,GAEPA,EAAYrN,MACvB,EAEA6+D,oBAAqB,SAASxK,EAAMgI,EAAcnB,GAE9C,IAAIhiD,EAAY3K,KAAKuvD,yBACjBoB,EAAgB7K,EAAK4K,MAAM9yB,SAASzmC,MAAQ,OAEhD,OAAIwT,EAAUgmD,GACHhmD,EAAUgmD,GAAe7C,EAAcnB,EAAQ7G,EAAK4K,MAAM9yB,SAAS38B,MAGvE,IACX,EAEAuuD,MAAO,SAASj7D,GAGZ,GAAI,GAAcA,EAAK86D,QAEnB,IADA,IAAIA,EAASrkE,OAAO0F,KAAK6D,EAAK86D,QACrBvoD,EAAI,EAAGkJ,EAAIq/C,EAAO79D,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAC3C,IAAIhc,EAAMukE,EAAOvoD,GACjB9G,KAAKqvD,OAAOvkE,GAAOkV,KAAK4wD,eAAer8D,EAAK86D,OAAOvkE,GACvD,CAKJ,IADA,IAAIi8D,EAAQ,GAAaxyD,EAAKs8D,OACrB9pD,EAAI,EAAGqQ,EAAI2vC,EAAMv1D,OAAQuV,EAAIqQ,EAAGrQ,IACrC/G,KAAK+mD,MAAMn1D,KAAKoO,KAAK8wD,cAAc/J,EAAMhgD,IAEjD,EAEA6pD,eAAgB,SAASve,GAErB,OAAO,GAAWA,EAAO,CACrBzU,SAAU59B,KAAK+wD,aAAa1e,EAAMzU,UAAU,GAC5C8yB,MAAO1wD,KAAKgxD,UAAU3e,GAAO,IAErC,EAEAye,cAAe,SAAShL,GAEpB,IAAImL,EAAY,GAAY,CAAC,EAAGnL,GAE5BzT,EAAQryC,KAAK0vD,SAAS5J,EAAKzT,OAS/B,OAPA4e,EAAUC,OAASD,EAAUC,QAAU7e,EAAM6e,OAC7CD,EAAU/9B,MAAQ,GAAW,CAAC,EAAGmf,EAAMnf,MAAO+9B,EAAU/9B,OACxD+9B,EAAUrzB,SAAW59B,KAAKmxD,oBAAoB9e,EAAO4e,GACrDA,EAAUP,MAAQ,GAAW,CAAC,EAAGre,EAAMqe,MAAO1wD,KAAKgxD,UAAUC,IAC7DA,EAAU1lC,EAAIvrB,KAAKoxD,WAAW/e,EAAO4e,GACrCA,EAAUz5D,KAAO,GAAY,CAAC,EAAG66C,EAAM76C,KAAMy5D,EAAUz5D,MAEhDy5D,CACX,EAEAG,WAAY,SAAS/e,EAAOyT,GAExB,OAAI,GAAcA,EAAKv6B,GACZu6B,EAAKv6B,EAEZ,GAAc8mB,EAAM9mB,IAAkB,SAAZ8mB,EAAM9mB,EACzB8mB,EAAM9mB,EAEV,MACX,EAEA4lC,oBAAqB,SAAS9e,EAAOyT,GAEjC,OAAO,GAAW,CACd3uD,KAAM,OACN8J,KAAM,CAAC,GACRoxC,EAAMzU,SAAU,CAAE38B,KAAM6kD,EAAK7kD,MACpC,EAEA8vD,aAAc,SAASnzB,EAAUyzB,GAE7B,IACIC,EADArwD,EAAO,CAAC,EAGR,GAAgB28B,IAChB0zB,EAAe,KACfrwD,EAAKwF,GAAKm3B,GACH,GAAcA,GACrB0zB,EAAe1zB,OACKnrC,IAAbmrC,EACP0zB,EAAeD,EAAa,OAAS,KAC9BrgE,MAAMC,QAAQ2sC,IACrB0zB,EAAe,WACfrwD,EAAKkN,EAAIyvB,EAAS,GAClB38B,EAAK+M,EAAI4vB,EAAS,IACX,GAAcA,KACrB0zB,EAAe1zB,EAASzmC,KACxB,GAAY8J,EAAM28B,EAAS38B,OAG/B,IAAIxP,EAAS,CAAEwP,KAAMA,GAKrB,OAHIqwD,IACA7/D,EAAO0F,KAAOm6D,GAEX7/D,CACX,EAEAu/D,UAAW,SAASxqB,EAAM+qB,GAEtB,IAAIb,EAAQlqB,EAAKkqB,OAAS,CAAC,EAEvBxoD,EAAMwoD,EAGV,OAFAxoD,EAAI01B,SAAW59B,KAAK+wD,aAAaL,EAAM9yB,SAAU2zB,GAE1CrpD,CACX,GAGG,MAAMspD,GAAuB,CAEhCC,iBAAkB,WAEdzxD,KAAK0xD,kBACL1xD,KAAKwJ,GAAG,gBAAgB,WAEpBxJ,KAAK2xD,sBACL3xD,KAAK0xD,iBACT,GAAG1xD,KACP,EAMA2xD,oBAAqB,WAEjB,IAAIvS,EAAUp/C,KAAK7U,IAAI,UAAY,CAAC,EAChCymE,EAAkB,CAAC,EAEvB,GAAaxS,EAAQyR,OAAOl5D,SAAQ,SAAS6uC,GACzCorB,EAAgBprB,EAAKlR,KAAM,CAC/B,IAEA,IAAIoqB,EAAW1/C,KAAK0/C,SAAS,UAAY,CAAC,EACtCmS,EAAU,CAAC,EAEf,GAAanS,EAASmR,OAAOl5D,SAAQ,SAAS6uC,GACrCorB,EAAgBprB,EAAKlR,MACtBu8B,EAAQrrB,EAAKlR,KAAM,EAE3B,IAEA,IAAI2xB,EAAQjnD,KAAKinD,MACbA,IAAU,GAAa4K,KAEJ5K,EAAMC,kBAAkBlnD,KAAM,CAAEmnD,SAAS,IAC/CxvD,SAAQ,SAASyvD,GAEtByK,EAAQzK,EAAKj8D,IAAI,UAAU26D,OAAOsB,EAAK7iD,QAC/C,IAEoB0iD,EAAMC,kBAAkBlnD,KAAM,CAAEqnD,UAAU,IAChD1vD,SAAQ,SAASyvD,GAEvByK,EAAQzK,EAAKj8D,IAAI,UAAU26D,OAAOsB,EAAK7iD,QAC/C,IAER,EAKAutD,SAAU,WAEN,IAAI/K,EAAQ/mD,KAAK3U,KAAK,eACtB,OAAO2F,MAAMC,QAAQ81D,IAAUA,EAAMv1D,OAAS,CAClD,EAMAugE,QAAS,SAASz8B,GAEd,OAAkC,IAA3Bt1B,KAAKgyD,aAAa18B,EAC7B,EAKAm6B,SAAU,WAEN,OAAO,GAAezvD,KAAK3U,KAAK,iBAAmB,EACvD,EAKA4mE,cAAe,SAASrC,GACpB,MAAMsC,EAAa,GAAalyD,KAAK3U,KAAK,CAAC,QAAQ,WAAW0I,QAAO+xD,GAAQA,EAAKzT,QAAUud,IAC5F,OAAO,GAAesC,EAC1B,EAMAC,QAAS,SAAS78B,GAEd,OAAO,GAAe,GAAat1B,KAAK3U,KAAK,gBAAgB+c,MAAK,SAAS09C,GACvE,OAAOA,EAAKxwB,IAAMwwB,EAAKxwB,KAAOA,CAClC,IACJ,EAEA88B,kBAAmB,WACf,OAAOpnE,OAAO0F,KAAKsP,KAAKqyD,kBAAkBhD,OAC9C,EAMAiD,kBAAmB,SAAS1C,GAIxB,OAFmB5vD,KAAKqyD,kBAAkBxC,qBAAqBD,EAAW9gD,GAAK9O,KAAKxI,SAEhEwM,QAAO,SAASuuD,EAAWC,GAC3C,IAAItF,EAAiBsF,EAAQrC,mBAM7B,OALAoC,EAAUC,EAAQpC,QAAU,CACxBjiD,EAAG++C,EAAe/+C,EAClBH,EAAGk/C,EAAel/C,EAClBlB,MAAOogD,EAAepgD,OAEnBylD,CACX,GAAG,CAAC,EACR,EAMAP,aAAc,SAASlM,GAEnB,IAAIxwB,EAAK,GAAcwwB,GAAQA,EAAKxwB,GAAKwwB,EAEzC,OAAK9lD,KAAKyyD,eAAen9B,GAIlB,GAAat1B,KAAK3U,KAAK,gBAAgBqnE,WAAU,SAASlsB,GAC7D,OAAOA,EAAKlR,KAAOA,CACvB,KALY,CAMhB,EAOAq9B,QAAS,SAAS7M,EAAMzxC,GAEpB,IAAK,GAAcyxC,IAAS90D,MAAMC,QAAQ60D,GACtC,MAAM,IAAI98C,MAAM,wCAGpB,IAAI+9C,EAAQ,GAAY,GAAI/mD,KAAK3U,KAAK,gBAItC,OAHA07D,EAAMn1D,KAAKk0D,GACX9lD,KAAK3U,KAAK,cAAe07D,EAAO1yC,GAEzBrU,IACX,EAQA4yD,WAAY,SAASz2B,EAAQ2pB,EAAMzxC,GAC/B,MAAM3iB,EAA2B,iBAAXyqC,EAAuBA,EAASn8B,KAAKgyD,aAAa71B,GAExE,IAAK,GAAc2pB,IAAS90D,MAAMC,QAAQ60D,GACtC,MAAM,IAAI98C,MAAM,+CAGpB,MAAM+9C,EAAQ,GAAY,GAAI/mD,KAAK3U,KAAK,gBAIxC,OAHA07D,EAAMvmD,OAAO9O,EAAO,EAAGo0D,GACvB9lD,KAAK3U,KAAK,cAAe07D,EAAO1yC,GAEzBrU,IACX,EASA6yD,SAAU,SAASzC,EAAQt4D,EAAMnM,EAAO0oB,GAEpC,IAAI3iB,EAAQsO,KAAKgyD,aAAa5B,GAE9B,IAAe,IAAX1+D,EACA,MAAM,IAAIsX,MAAM,wCAA0ConD,GAG9D,IAAInvD,EAAOjQ,MAAM1F,UAAUwP,MAAMtP,KAAKoT,UAAW,GAkBjD,OAjBI5N,MAAMC,QAAQ6G,GACdmJ,EAAK,GAAK,CAAC,QAAS,QAASvP,GAAOiX,OAAO7Q,GACpC,GAAcA,GAIrBmJ,EAAK,GAAK,CAAC,eAAgBvP,EAAO,IAAKoG,GAAMhJ,KAAK,KAIlDmS,EAAO,CAAC,eAAiBvP,GACrB,GAAmBoG,KACnBmJ,EAAKrP,KAAKkG,GACVmJ,EAAKrP,KAAKjG,KAIXqU,KAAK3U,KAAK8V,MAAMnB,KAAMiB,EACjC,EAEA6xD,eAAgB,WAEZ,IAAIC,EAAY/yD,KAAK7U,IAAI,UAAY,CAAC,EAElC6nE,EAAgB,GAEhBjM,EAAQ,IADZgM,EAAYA,GAAa,CAAC,GACSlC,OAiBnC,OAfA9J,EAAMpvD,SAAQ,SAASkW,GAEF,iBAANA,GACPmlD,EAAcphE,KAAK,yBAA0Bic,GAG5C7N,KAAKyyD,eAAe5kD,EAAEynB,MACvBznB,EAAEynB,GAAKt1B,KAAKizD,iBAEpB,GAAGjzD,MAEC,GAAU+mD,EAAO,MAAMv1D,SAAWu1D,EAAMv1D,QACxCwhE,EAAcphE,KAAK,2CAGhBohE,CACX,EAEAC,eAAgB,WACZ,OAAOjzD,KAAK0mD,YAChB,EAOA+L,eAAgB,SAASn9B,GAErB,OAAOA,UAAoC,GAAcA,EAC7D,EAEA49B,SAAU,SAASnM,EAAO1yC,GAMtB,OAJI0yC,EAAMv1D,QACNwO,KAAK3U,KAAK,cAAe,GAAY,GAAI2U,KAAK3U,KAAK,gBAAgBsd,OAAOo+C,GAAQ1yC,GAG/ErU,IACX,EAEAmzD,WAAY,SAASrN,EAAMzxC,GACvB,MAAMsjB,EAAUtjB,GAAO,CAAC,EAClB3iB,EAAQsO,KAAKgyD,aAAalM,GAChC,IAAe,IAAXp0D,EAAc,CACd,MAAMq1D,EAAQ,GAAY,GAAI/mD,KAAK3U,KAAK,CAAC,QAAS,WAClD07D,EAAMvmD,OAAO9O,EAAO,GACpBimC,EAAQkyB,SAAU,EAClB7pD,KAAKsnD,WAAW,eAChBtnD,KAAK3U,KAAK,CAAC,QAAS,SAAU07D,EAAOpvB,GACrC33B,KAAK4nD,UAAU,cACnB,CACA,OAAO5nD,IACX,EAEAozD,YAAa,SAASC,EAAiBh/C,GACnC,IAAIsjB,EAAS27B,EACb,GAAItiE,MAAMC,QAAQoiE,GAAkB,CAEhC,GADA17B,EAAUtjB,GAAO,CAAC,EACa,IAA3Bg/C,EAAgB7hE,OAAc,OAAOwO,KAAKA,KAE9CszD,EADqB,GAAY,GAAItzD,KAAK3U,KAAK,CAAC,QAAS,WACjC0I,QAAO,SAASw/D,GACpC,OAAQF,EAAgB18D,MAAK,SAAS68D,GAClC,MAAMC,EAAO,GAAcD,GAAMA,EAAGl+B,GAAKk+B,EACzC,OAAOD,EAAGj+B,KAAOm+B,CACrB,GACJ,GACJ,MACI97B,EAAU07B,GAAmB,CAAC,EAC9BC,EAAW,GAMf,OAJAtzD,KAAKsnD,WAAW,eAChB3vB,EAAQkyB,SAAU,EAClB7pD,KAAK3U,KAAK,CAAC,QAAS,SAAUioE,EAAU37B,GACxC33B,KAAK4nD,UAAU,eACR5nD,IACX,EAKA0xD,gBAAiB,WAEb,IAOIgC,EAPAC,EAAM3zD,KAAK8yD,iBAEf,GAAIa,EAAIniE,OAAS,EAEb,MADAwO,KAAK5M,IAAI,QAAS4M,KAAK0/C,SAAS,UAC1B,IAAI12C,MAAM2qD,EAAI7kE,KAAK,MAKzBkR,KAAKqyD,oBAELqB,EAAe1zD,KAAKqyD,kBAAkB5C,YAG1CzvD,KAAKqyD,kBAAoB,IAAIlD,GAASnvD,KAAK7U,IAAI,UAE/C,IAAIyoE,EAAc5zD,KAAKqyD,kBAAkB5C,WAEzC,GAAIiE,EAAc,CAEd,IAAIG,EAAQD,EAAY7/D,QAAO,SAASyyC,GACpC,IAAKktB,EAAatrD,MAAK,SAAS0rD,GAC5B,OAAOA,EAASx+B,KAAOkR,EAAKlR,EAChC,IACI,OAAOkR,CAEf,IAEIqrB,EAAU6B,EAAa3/D,QAAO,SAASyyC,GACvC,IAAKotB,EAAYxrD,MAAK,SAAS2rD,GAC3B,OAAOA,EAAQz+B,KAAOkR,EAAKlR,EAC/B,IACI,OAAOkR,CAEf,IAEIqrB,EAAQrgE,OAAS,GACjBwO,KAAK28C,QAAQ,eAAgB38C,KAAM6xD,GAGnCgC,EAAMriE,OAAS,GACfwO,KAAK28C,QAAQ,YAAa38C,KAAM6zD,EAExC,CACJ,GAGSG,GAA2B,CAEpCC,oBAAqB,IACrBC,WAAY,CAAC,CACTp4B,QAAS,SACTv1B,SAAU,SACVm1B,WAAY,CACR,EAAK,GACL,KAAQ,UACR,OAAU,aAGlBy4B,gBAAiB,CAAC,CACdr4B,QAAS,OACTv1B,SAAU,OACVm1B,WAAY,CACR,KAAQ,aAIhB04B,mBAAoB,KAKpB3C,iBAAkB,WACdzxD,KAAKq0D,kBACT,EAgBAC,cAAe,WAEXt0D,KAAKu0D,eACLv0D,KAAKq0D,mBACLr0D,KAAKw0D,cACT,EAEAH,iBAAkB,WACdr0D,KAAKo0D,mBAAqB,CAAC,CAC/B,EAKAI,aAAc,WAMV,IAHA,IAAIC,EAAoB,GACpBprD,EAAOrJ,KAAK00D,uBAEP5tD,EAAI,EAAG+0C,EAAQxyC,EAAKP,KAAKf,WAAWvW,OAAQsV,EAAI+0C,EAAO/0C,IAC5D2tD,EAAkB7iE,KAAKyX,EAAKP,KAAKf,WAAWjB,IAGhD,I/CkmDgBtK,EAAYC,E+ClmDxBk4D,G/CkmDYn4D,E+ClmDiBwD,KAAK29C,MAAM0U,kBAAkB5C,W/CmmDlEhzD,EAAWkC,GADqBlC,E+ClmD8C,I/CmmD7C,GA9uBrC,SAAgBD,EAAYC,EAAUqC,GAGlC,OAFa9N,MAAMC,QAAQuL,GAAcqC,GAAcG,IAE3CxC,EAAYC,EAAUqC,EADhBF,UAAUpN,OAAS,EACqB+K,GAC9D,CA4uBWyH,CAAOxH,GAAY,CAAC/K,EAAQ9F,EAAOb,KACtCA,EAAM2R,EAAS9Q,GACXJ,eAAeC,KAAKiG,EAAQ3G,GAC5B2G,EAAO3G,GAAK8G,KAAKjG,GAEjB4G,GAAYd,EAAQ3G,EAAK,CAACa,IAEvB8F,IACR,CAAC,I+C5mDImjE,EAAc,OAGlB,GAAaD,EAAcC,IAAcj9D,SAAQ,SAASmuD,GACtD,IAAI+O,EAAc70D,KAAK80D,gBAAgBhP,GACvCz8C,EAAKyqB,OAAO+gC,GACZJ,EAAkB7iE,KAAKijE,EAC3B,GAAG70D,MAGH,IADA,IAAI+0D,EAAa/pE,OAAO0F,KAAKikE,GACpB3rB,EAAI,EAAGA,EAAI+rB,EAAWvjE,OAAQw3C,IAAK,CACxC,IAAI4mB,EAAYmF,EAAW/rB,GAC3B,GAAI4mB,IAAcgF,EAAa,CAC3B,IAAIrpC,EAAIjd,SAASshD,EAAW,IAC5B5vD,KAAKg1D,aAAaL,EAAc/E,GAAYrkC,EAAGkpC,EACnD,CACJ,CAEAz0D,KAAKi1D,cACT,EAMAP,qBAAsB,WAElB,OAAO10D,KAAKk1D,eAAiBl1D,KAAKi5B,GACtC,EAQA+7B,aAAc,SAASjO,EAAOx7B,EAAG4pC,GAE7B,IAAIC,EAAmBp1D,KAAK00D,uBACxBW,EAAe,GAAatO,GAAOp2D,IAAIqP,KAAK80D,gBAAiB90D,MAE7Dm1D,EAAK5pC,IAAMA,EAAI,EACf,GAAE4pC,EAAKpzD,KAAKwL,IAAIge,EAAG,KAAK4Q,OAAOk5B,GAE/BD,EAAiBthC,OAAOuhC,EAEhC,EAQAP,gBAAiB,SAAShP,GAEtB,OAAI9lD,KAAKo0D,mBAAmBtO,EAAKxwB,IACtBt1B,KAAKo0D,mBAAmBtO,EAAKxwB,IAAIu/B,YAErC70D,KAAKs1D,mBAAmBxP,EACnC,EAEAyP,cAAe,SAASnF,EAAQ7pD,GAC5B,MAAMivD,EAAYx1D,KAAKo0D,mBAAmBhE,GAC1C,IAAKoF,EAAW,MAAO,GACvB,IAAKjvD,EAAU,MAAO,CAACivD,EAAUC,mBAAmB3sD,MACpD,MAAM4sD,EAAWF,EAAUX,YAAY/rD,KACjC6sD,EAAgBH,EAAUG,cAChC,OAAO31D,KAAK41D,eAAervD,EAAUmvD,EAAUC,EACnD,EAEAE,aAAc,SAASzF,EAAQ7pD,GAC3B,MAAOuC,EAAO,MAAQ9I,KAAKu1D,cAAcnF,EAAQ7pD,GACjD,OAAOuC,CACX,EAKAmsD,aAAc,WAGVj1D,KAAK81D,sBAAiBrjE,GAEJzH,OAAO0F,KAAKsP,KAAK29C,MAAM0U,kBAAkBhD,QAC/C13D,QAAQqI,KAAK81D,iBAAkB91D,KAC/C,EAKAu0D,aAAc,WACV,GAAYv0D,KAAKo0D,mBAAoB,qBACzC,EAOAkB,mBAAoB,SAASxP,GAEzB,IAAI+O,EACAkB,EACAC,EACAL,EAEJ,IAAIM,EAAuB,GAAEj2D,KAAKi0D,qBAAqBh/B,SAAS,cAE5Di/B,EAAal0D,KAAKk2D,eAAepQ,GACrC,GAAI90D,MAAMC,QAAQijE,GAAa,CAC3B,IAAIiC,EAAUn2D,KAAKqxC,aAAa6iB,EAAY+B,EAAqBntD,MAC7DstD,EAAeD,EAAQzkB,SAEvBmjB,EADAuB,EAAaruD,WAAWvW,OAAS,EACnB,GAAE,KAAKsiC,OAAOsiC,GAEd,GAAEA,EAAa1iC,YAEjCiiC,EAAgBQ,EAAQ5kB,SAC5B,MACIsjB,EAAc,GAAEX,GACZljE,MAAMC,QAAQ4jE,KACdA,EAAc,GAAE,KAAK/gC,OAAO+gC,IAIpC,IAAKA,EACD,MAAM,IAAI7rD,MAAM,qCAGpB6rD,EAAY3/B,KAAK,CACb,KAAQ4wB,EAAKxwB,GACb,aAAcwwB,EAAKzT,QAMnB,GAAcyT,EAAKxwB,KACnBu/B,EAAY3/B,KAAK,eAAgB,UAGrC,MAAMmhC,EAAiBr2D,KAAKs2D,oBAAoBxQ,EAAK4K,OACrD,GAAI1/D,MAAMC,QAAQolE,GAAiB,CAE/B,MAAM,SAAE3kB,EAAQ,UAAEH,GAAcvxC,KAAKqxC,aAAaglB,EAAgBJ,EAAqBntD,MACjFytD,EAAa7kB,EAAS3pC,WAAWvW,OACnC+kE,EAAa,IACbP,EAAiBzkB,EACjBwkB,EAA+B,IAAfQ,EAAoB,GAAE7kB,EAAShe,YAAc,GAAE,KAAKI,OAAO4d,GAEnF,MAEIqkB,EAAe,GAAEM,GACbrlE,MAAMC,QAAQ8kE,KACdA,EAAe,GAAE,KAAKjiC,OAAOiiC,IAIrC,IAAIS,EACJ,GAAIb,GAAiBK,EAAgB,CACjC,IAAK,IAAIlrE,KAAOkrE,EACZ,GAAIL,EAAc7qE,IAAQA,IAAQkV,KAAKuG,SAAU,MAAM,IAAIyC,MAAM,sDAErEwtD,EAAyB,GAAY,CAAC,EAAGb,EAAeK,EAC5D,MACIQ,EAAyBb,GAAiBK,GAAkB,CAAC,EAMjE,MAAMS,EAAmB,WAEnBC,EAAoB,YAEpBC,EAAoB,YAM1B,GAJMF,KAAoBD,IACtBA,EAAuBC,GAAoB5B,EAAY/rD,MAGvDitD,EAAc,CACd,MAAMa,EAAYb,EAAajtD,KAI/B,GAHM4tD,KAAqBF,IACvBA,EAAuBE,GAAqBE,KAE1CD,KAAqBH,GAAyB,CAGhD,MAAMK,EAA4C,SAA3Bd,EAAaj6B,UAC9B86B,EACA5lE,MAAM8W,KAAK8uD,EAAUpuD,iBAAiB,SAC5CguD,EAAuBG,GAAqBE,EACvCb,IAAgBA,EAAiB,CAAC,GACvCA,EAAeW,GAAqBE,CACxC,CACJ,CAgBA,OAdAZ,EAAqBniC,OAAO+gC,EAAY5/B,SAAS,oBAC7C8gC,GACAE,EAAqBniC,OAAOiiC,EAAa9gC,SAAS,qBAGtDj1B,KAAKo0D,mBAAmBtO,EAAKxwB,IAAM,CAC/Bu/B,YAAaoB,EACba,iBAAkBf,EAClBJ,cAAea,EACfO,mBAAoBf,EACpBP,mBAAoBZ,EACpBmC,qBAAsBrB,GAGnBM,CACX,EAMAH,iBAAkB,SAASlG,GAKvB,IAHA,IAAIqH,EAAcnoD,GAAK9O,KAAK29C,MAAMnmD,QAC9B0/D,EAAel3D,KAAK29C,MAAM0U,kBAAkBxC,qBAAqBD,EAAWqH,GAEvEnwD,EAAI,EAAGkJ,EAAIknD,EAAa1lE,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CACjD,IAAI0rD,EAAU0E,EAAapwD,GACvBspD,EAASoC,EAAQpC,OACjB+G,EAASn3D,KAAKo0D,mBAAmBhE,IAAW,CAAC,EAC7CD,EAAqBqC,EAAQrC,mBAC7BE,EAAsBmC,EAAQnC,oBAC9BA,GAAuB8G,EAAOL,mBAC9B92D,KAAKo3D,2BAA2BD,EAAOL,iBAAiBhuD,KAAMunD,EAAoBn9B,MAAO,CACrFmkC,SAAU,IAAIvoD,GAAK0jD,EAAQ/B,WAC3Blf,UAAW4lB,EAAOJ,qBAEtB/2D,KAAKs3D,mBAAmBH,EAAOL,iBAAkBzG,GAAuBF,EAAmBrjD,OAAS,IAExG9M,KAAKo3D,2BAA2BD,EAAOtC,YAAY/rD,KAAM0pD,EAAQjC,UAAW,CACxE8G,SAAU,IAAIvoD,GAAK0jD,EAAQhC,UAC3Bjf,UAAW4lB,EAAOxB,gBAEtB31D,KAAKs3D,mBAAmBH,EAAOtC,YAAa1E,EAChD,CACJ,EAQAmH,mBAAoB,SAASC,EAASC,EAAeC,GAEjD,IAAIxhC,EAAS,GAAEF,kBACVhkB,OAAO0lD,GAAgB,GACvB5kD,UAAU2kD,EAAcrpD,GAAK,EAAGqpD,EAAcxpD,GAAK,GACnD+D,OAAOylD,EAAc1qD,OAAS,GAEnCyqD,EAAQvhC,UAAUC,EAAQ,CAAEG,UAAU,GAC1C,EAOA8/B,eAAgB,SAASpQ,GAErB,OAAOA,EAAKoL,QAAUlxD,KAAK29C,MAAMxyD,IAAI,eAAiB6U,KAAK29C,MAAMuW,YAAcl0D,KAAKk0D,UACxF,EAOAoC,oBAAqB,SAAS5F,GAE1B,OAAOA,EAAMQ,QAAUlxD,KAAK29C,MAAMxyD,IAAI,oBAAsB6U,KAAK29C,MAAMwW,iBAAmBn0D,KAAKm0D,eACnG,GC12BS,GAAUhO,GAAKtmC,OAAO,CAE/Bhf,SAAU,CACN+8B,SAAU,CAAEzvB,EAAG,EAAGH,EAAG,GACrBxW,KAAM,CAAEgZ,MAAO,EAAGC,OAAQ,GAC1B3D,MAAO,GAGXqxC,WAAY,WAERn+C,KAAKyxD,mBACLtL,GAAK76D,UAAU6yD,WAAWh9C,MAAMnB,KAAMpB,UAC1C,EAKA6yD,iBAAkB,WAElB,EAEA6C,cAAe,WAEf,EAEA3I,UAAW,WAEP,OAAO,CACX,EAEA/tB,SAAU,SAASzvB,EAAGH,EAAGqG,GAErB,MAAMqjD,EAAW/2D,GAASqN,GAC1BqG,GAAOqjD,EAAWrjD,EAAMlG,IAAM,CAAC,EAC/B,MAAM,eAAEwpD,EAAc,KAAE5P,EAAI,eAAE6P,GAAmBvjD,EAIjD,IAAIwjD,EACJ,GAAIF,EAAgB,CAIhB,IAAK33D,KAAKinD,MAAO,MAAM,IAAIj+C,MAAM,oCAEjC,MAAMozB,EAASp8B,KAAKwnD,gBAChBprB,IAAWA,EAAOoiB,WAClBqZ,EAAiBz7B,EAAOjxC,IAAI,YAEpC,CAEA,GAAIusE,EAAU,CAOV,GALIG,IACA1pD,GAAK0pD,EAAe1pD,EACpBH,GAAK6pD,EAAe7pD,GAGpB+5C,GAAQ6P,EAAgB,CACxB,MAAQzpD,EAAGK,EAAIR,EAAGS,GAAOzO,KAAK7U,IAAI,YAClC6U,KAAK6S,UAAU1E,EAAIK,EAAIR,EAAIS,EAAI4F,EACnC,MACIrU,KAAK5M,IAAI,WAAY,CAAE+a,IAAGH,KAAKqG,GAGnC,OAAOrU,IAEX,CAAO,CAEH,MAAM83D,EAAkBnpD,GAAM3O,KAAK7U,IAAI,aACvC,OAAOwsE,EACDG,EAAgB30D,WAAW00D,GAC3BC,CACV,CACJ,EAEAjlD,UAAW,SAASgD,EAAIC,EAAIzB,GAKxB,GAFAyB,EAAKA,GAAM,EAEA,KAHXD,EAAKA,GAAM,IAGY,IAAPC,EAEZ,OAAO9V,MAGXqU,EAAMA,GAAO,CAAC,GAEV0jD,YAAc1jD,EAAI0jD,aAAe/3D,KAAKs1B,GAE1C,IAAIsI,EAAW59B,KAAK7U,IAAI,aAAe,CAAEgjB,EAAG,EAAGH,EAAG,GAC9CoqC,EAAK/jC,EAAIujD,eACb,GAAIxf,GAAM/jC,EAAI0jD,cAAgB/3D,KAAKs1B,GAE/B,GAAkB,mBAAP8iB,EAAmB,CAE1B,IAAI4f,EAAc5f,EAAG5sD,KAAKwU,KAAM49B,EAASzvB,EAAI0H,EAAI+nB,EAAS5vB,EAAI8H,EAAIzB,GAElEwB,EAAKmiD,EAAY7pD,EAAIyvB,EAASzvB,EAC9B2H,EAAKkiD,EAAYhqD,EAAI4vB,EAAS5vB,CAElC,KAAQ,CAIJ,IAAI+E,EAAO/S,KAAKo3B,QAAQ,CAAE2wB,MAAM,IAY5B72C,EAAK0sB,EAASzvB,EAAI4E,EAAK5E,EACvBgD,EAAKysB,EAAS5vB,EAAI+E,EAAK/E,EAGvBG,EAAIpM,KAAKwL,IAAI6qC,EAAGjqC,EAAI+C,EAAInP,KAAKE,IAAIm2C,EAAGjqC,EAAIiqC,EAAG5nC,MAAQU,EAAK6B,EAAKvC,MAAOotB,EAASzvB,EAAI0H,IACjF7H,EAAIjM,KAAKwL,IAAI6qC,EAAGpqC,EAAImD,EAAIpP,KAAKE,IAAIm2C,EAAGpqC,EAAIoqC,EAAG3nC,OAASU,EAAK4B,EAAKtC,OAAQmtB,EAAS5vB,EAAI8H,IAEvFD,EAAK1H,EAAIyvB,EAASzvB,EAClB2H,EAAK9H,EAAI4vB,EAAS5vB,CACtB,CAGJ,IAAIiqD,EAAqB,CACrB9pD,EAAGyvB,EAASzvB,EAAI0H,EAChB7H,EAAG4vB,EAAS5vB,EAAI8H,GA0BpB,OAtBAzB,EAAIwB,GAAKA,EACTxB,EAAIyB,GAAKA,EAELzB,EAAIk2C,YAECr4D,GAASmiB,EAAIk2C,cAAal2C,EAAIk2C,WAAa,CAAC,GAEjDvqD,KAAKuqD,WAAW,WAAY0N,EAAoB,GAAO,CAAC,EAAG5jD,EAAIk2C,WAAY,CACvEG,cAAe1S,GAAYvnD,UAI/B2Q,GAAOpB,KAAK2nD,mBAAoB,YAAa9xC,EAAIC,EAAIzB,KAIrDrU,KAAKsnD,WAAW,YAAajzC,GAC7BrU,KAAK5M,IAAI,WAAY6kE,EAAoB5jD,GACzCjT,GAAOpB,KAAK2nD,mBAAoB,YAAa9xC,EAAIC,EAAIzB,GACrDrU,KAAK4nD,UAAU,YAAavzC,IAGzBrU,IACX,EAEAxI,KAAM,SAASgZ,EAAOC,EAAQ4D,GAE1B,IAAI6jD,EAAcl4D,KAAK7U,IAAI,QAG3B,YAAcsH,IAAV+d,EACO,CACHA,MAAO0nD,EAAY1nD,MACnBC,OAAQynD,EAAYznD,SAKxBve,GAASse,KACT6D,EAAM5D,EACNA,EAAS9P,GAAS6P,EAAMC,QAAUD,EAAMC,OAASynD,EAAYznD,OAC7DD,EAAQ7P,GAAS6P,EAAMA,OAASA,EAAMA,MAAQ0nD,EAAY1nD,OAGvDxQ,KAAKm4D,OAAO3nD,EAAOC,EAAQ4D,GACtC,EAEA8jD,OAAQ,SAAS3nD,EAAOC,EAAQ4D,GAM5B,GAJAA,EAAMA,GAAO,CAAC,EAEdrU,KAAKsnD,WAAW,SAAUjzC,GAEtBA,EAAI+jD,UAAW,CAEf,IAAIF,EAAcl4D,KAAK7U,IAAI,QAE3B,OAAQkpB,EAAI+jD,WAER,IAAK,OACL,IAAK,QAED3nD,EAASynD,EAAYznD,OACrB,MAEJ,IAAK,MACL,IAAK,SAEDD,EAAQ0nD,EAAY1nD,MAK5B,IAKIf,EALA3C,EAAQD,GAAe7M,KAAK7U,IAAI,UAAY,GAG5C4nB,EAAO/S,KAAKo3B,UAIhB,GAAItqB,EAAO,CAEP,IAAIurD,EAAW,CACX,YAAa,EACb,MAAS,EACT,WAAY,EACZ,IAAO,EACP,cAAe,EACf,KAAQ,EACR,eAAgB,EAChB,OAAU,GACZhkD,EAAI+jD,WAEF/jD,EAAI+hB,WAGJiiC,GAAYt2D,KAAKC,OAAO8K,EAAQ,IAAM,IACtCurD,GAAY,GAKhB,IAAIC,EAAavlD,EAAK,CAAC,aAAc,SAAU,WAAY,UAAUslD,MAIjEE,EAAkB5pD,GAAM2pD,GAAYvmD,OAAOgB,EAAKmD,UAAWpJ,GAQ3D0rD,EAASz2D,KAAK2M,KAAM8B,EAAQA,EAAUC,EAASA,GAAW,EAY1DoE,EAAQwjD,EAAWt2D,KAAKuK,GAAK,EAKjCuI,GAAS9S,KAAK02D,KAAKJ,EAAW,GAAK,EAAI5nD,EAASD,EAAQA,EAAQC,GAGhEoE,GAAS1H,GAAML,GAIf,IAAIoJ,EAASvH,GAAMY,UAAUipD,EAAQ3jD,EAAO0jD,GAK5C9oD,EAASd,GAAMuH,GAAQ7E,OAAOb,GAAS,EAAGC,GAAU,EAExD,MAII,OAFAhB,EAASsD,EAAKsH,UAENhG,EAAI+jD,WACR,IAAK,MACL,IAAK,YACD3oD,EAAO4B,OAAO,EAAG0B,EAAKtC,OAASA,GAC/B,MACJ,IAAK,OACL,IAAK,cACDhB,EAAO4B,OAAO0B,EAAKvC,MAAOA,EAAO,GACjC,MACJ,IAAK,WACDf,EAAO4B,OAAO0B,EAAKvC,MAAQA,EAAOuC,EAAKtC,OAASA,GAM5DzQ,KAAK5M,IAAI,OAAQ,CAAEod,MAAOA,EAAOC,OAAQA,GAAU4D,GAGnDrU,KAAK49B,SAASnuB,EAAOtB,EAAGsB,EAAOzB,EAAGqG,EAEtC,MAGIrU,KAAK5M,IAAI,OAAQ,CAAEod,MAAOA,EAAOC,OAAQA,GAAU4D,GAKvD,OAFArU,KAAK4nD,UAAU,SAAUvzC,GAElBrU,IACX,EAEAuM,MAAO,SAAS6F,EAAIC,EAAI5C,EAAQ4E,GAE5B,IAAIqkD,EAAa14D,KAAKo3B,UAAU7qB,MAAM6F,EAAIC,EAAI5C,GAK9C,OAJAzP,KAAKsnD,WAAW,QAASjzC,GACzBrU,KAAK49B,SAAS86B,EAAWvqD,EAAGuqD,EAAW1qD,EAAGqG,GAC1CrU,KAAKm4D,OAAOO,EAAWloD,MAAOkoD,EAAWjoD,OAAQ4D,GACjDrU,KAAK4nD,UAAU,SACR5nD,IACX,EAEA24D,UAAW,SAAStkD,GAEhB,OAAOrU,KAAK44D,cAAcvkD,EAC9B,EAEAukD,cAAe,SAASvkD,EAAM,CAAC,GAI3B,MAAM,MAAE4yC,GAAUjnD,KAClB,IAAKinD,EAAO,MAAM,IAAIj+C,MAAM,oCAE5B,MAAM6vD,EAAgB74D,KAAK2nD,mBAAmB5zD,QAAOwqD,GAAQA,EAAKoN,cAClE,OAA6B,IAAzBkN,EAAcrnE,SAElBwO,KAAKsnD,WAAW,aAAcjzC,GAE1BA,EAAI0zC,MAIJ3mD,GAAOy3D,EAAe,gBAAiBxkD,GAM3CrU,KAAK84D,eAAe9tE,OAAOgP,OAAO,CAAEiO,SAAU4wD,GAAiBxkD,IAE/DrU,KAAK4nD,UAAU,eAhBwB5nD,IAmB3C,EAEA+4D,UAAW,SAAS1kD,EAAM,CAAC,GAEvB,MAAM,MAAE4yC,GAAUjnD,KAClB,IAAKinD,EAAO,MAAM,IAAIj+C,MAAM,oCAI5B,GAAIqL,EAAI0zC,MAAQ1zC,EAAI4oB,aAAgB5oB,EAAI4oB,aAAej9B,MAAUqU,EAAI4oB,aAAej9B,KAAKs1B,IAAM,OAAOt1B,KAEtG,MAAMg5D,EAAgBh5D,KAAKwnD,gBAC3B,IAAKwR,IAAkBA,EAAcrN,YAAa,OAAO3rD,KAGzD,MAAMi5D,EAAkBD,EAAcrR,mBAAmB5zD,QAAOwqD,GAAQA,EAAKoN,cAC7E,OAA+B,IAA3BsN,EAAgBznE,SAEpBwO,KAAKsnD,WAAW,aAAcjzC,GAK9B2kD,EAAcF,eAAe9tE,OAAOgP,OAAO,CAAEiO,SAAUgxD,GAAmB5kD,IAEtEA,EAAI0zC,MAIJiR,EAAcD,UAAU1kD,GAG5BrU,KAAK4nD,UAAU,eAhB0B5nD,IAmB7C,EAGA84D,eAAgB,SAASzkD,EAAM,CAAC,GAE5B,MAAM6kD,EAAel5D,KAAKinD,MAAMkS,aAAa9kD,EAAIpM,UAEjD,IAAKixD,EAAc,OAEnB,MAAM,WAAEE,EAAU,WAAEC,GAAehlD,EAEnC,GAAI+kD,GAAcC,EAAY,OAK9B,IAAI,EAAElrD,EAAC,EAAEH,EAAC,MAAEwC,EAAK,OAAEC,GAAWyoD,EAC9B,MAAM,KAAElmD,EAAI,MAAEE,EAAK,IAAED,EAAG,OAAEE,GAAW8jC,GAAe5iC,EAAIilD,SACxDnrD,GAAK6E,EACLhF,GAAKiF,EACLzC,GAASwC,EAAOE,EAChBzC,GAAU0C,EAASF,EACnB,IAAIsmD,EAAa,IAAIzqD,GAAKX,EAAGH,EAAGwC,EAAOC,GAEvC,GAAI2oD,EAEAG,EAAav5D,KAAKo3B,UAAUh0B,MAAMm2D,QAE/B,GAAIF,EAAY,CAEnB,MAAMG,EAAmBx5D,KAAKo3B,UAAUjjB,UAAUolD,GAElD,IAAKC,EAAkB,OAEvBD,EAAcC,CAClB,CAGAx5D,KAAK5M,IAAI,CACLwqC,SAAU,CAAEzvB,EAAGorD,EAAWprD,EAAGH,EAAGurD,EAAWvrD,GAC3CxW,KAAM,CAAEgZ,MAAO+oD,EAAW/oD,MAAOC,OAAQ8oD,EAAW9oD,SACrD4D,EACP,EAMAtC,OAAQ,SAASjF,EAAOspB,EAAU3mB,EAAQ4E,GAEtC,GAAI5E,EAAQ,CAER,IAAIyG,EAASlW,KAAKo3B,UAAUlhB,SACxB1e,EAAOwI,KAAK7U,IAAI,QAChByyC,EAAW59B,KAAK7U,IAAI,YACxB+qB,EAAOnE,OAAOtC,EAAQzP,KAAK7U,IAAI,SAAW2hB,GAC1C,IAAIoE,EAAKgF,EAAO/H,EAAI3W,EAAKgZ,MAAQ,EAAIotB,EAASzvB,EAC1CgD,EAAK+E,EAAOlI,EAAIxW,EAAKiZ,OAAS,EAAImtB,EAAS5vB,EAC/ChO,KAAKsnD,WAAW,SAAU,CAAEx6C,MAAOA,EAAOspB,SAAUA,EAAU3mB,OAAQA,IACtEzP,KAAK49B,SAASA,EAASzvB,EAAI+C,EAAI0sB,EAAS5vB,EAAImD,EAAIkD,GAChDrU,KAAK+R,OAAOjF,EAAOspB,EAAU,KAAM/hB,GACnCrU,KAAK4nD,UAAU,SAEnB,MAEI5nD,KAAK5M,IAAI,QAASgjC,EAAWtpB,GAAS9M,KAAK7U,IAAI,SAAW2hB,GAAS,IAAKuH,GAG5E,OAAOrU,IACX,EAEA8M,MAAO,WACH,OAAOD,GAAe7M,KAAK7U,IAAI,UAAY,EAC/C,EAEAisC,QAAS,SAAS/iB,EAAM,CAAC,GAErB,MAAM,MAAE4yC,EAAK,WAAEvrB,GAAe17B,MACxB,KAAE+nD,EAAI,OAAEh2C,GAAWsC,EAEzB,GAAI0zC,GAAQd,EAAO,CAEf,MAAMh/C,EAAWjI,KAAK2nD,iBAAiB,CAAEI,MAAM,EAAMC,cAAc,IAKnE,OAHA//C,EAASrW,KAAKoO,MAGPinD,EAAMkS,aAAalxD,EAAUoM,EACxC,CAEA,MAAM,MAAEvH,EAAQ,EAAG8wB,UAAU,EAAEzvB,EAAC,EAAEH,GAAKxW,MAAM,MAAEgZ,EAAK,OAAEC,IAAYirB,EAC5D3oB,EAAO,IAAIjE,GAAKX,EAAGH,EAAGwC,EAAOC,GAInC,OAHIsB,GACAgB,EAAKwF,mBAAmBzL,GAErBiG,CACX,EAEA+4C,0BAA2B,SAAS1E,EAAMqS,GAEtC,IAAI1mD,EAAO/S,KAAKo3B,UACZlhB,EAASnD,EAAKmD,SAEdwjD,EAAStS,EAAKj8D,IAAIsuE,GACtB,IAAKC,EAAQ,OAAOxjD,EACpB,IAAIk6C,EAASsJ,EAAO5T,KACpB,IAAKsK,IAAWpwD,KAAK+xD,QAAQ3B,GAAS,OAAOl6C,EAC7C,IAAIyjD,EAAY35D,KAAK6yD,SAASzC,EAAQ,CAAC,UACnCwJ,EAAiB55D,KAAKsyD,kBAAkBqH,GACxCE,EAAa,IAAIlrD,GAAMirD,EAAexJ,IAAS/+C,OAAO0B,EAAKtD,UAC3D3C,EAAQ9M,KAAK8M,QAEjB,OADIA,GAAO+sD,EAAW9nD,OAAOmE,GAASpJ,GAC/B+sD,CACX,IAGJ,GAAO,GAAQvuE,UAAWkmE,IC9fnB,MAAMsI,GAAO3T,GAAKtmC,OAAO,CAG5Bk6C,kBAActnE,EAKdunE,iBAAavnE,EAGbwnE,UAAW,CACPF,aAAc,CAIV7I,OAAQ,CACJ,CACIp1B,QAAS,OACTv1B,SAAU,QACX,CACCu1B,QAAS,OACTv1B,SAAU,SAKlB2sB,MAAO,CACHiF,KAAM,CACF+hC,KAAM,UACNvlC,SAAU,GACVq5B,WAAY,SACZv1B,mBAAoB,SACpB0hC,cAAe,QAEnBlkD,KAAM,CACF7E,IAAK,OACL8oD,KAAM,UACNzjD,GAAI,EACJC,GAAI,EACJvI,EAAG,UACHH,EAAG,UACHwC,MAAO,UACPC,OAAQ,YAMhBmtB,SAAU,CACNpuB,SAAU,MAKtB3O,SAAU,CACNlO,OAAQ,CAAC,EACTuS,OAAQ,CAAC,GAGbs5C,OAAQ,WAEJ,OAAO,CACX,EAEA4b,WAAY,SAAS/lD,GAEjB,OAAOrU,KAAK5M,IAAI,CACZT,OAAQ,CAAEwb,EAAG,EAAGH,EAAG,GACnB9I,OAAQ,CAAEiJ,EAAG,EAAGH,EAAG,IACpBqG,EACP,EAEA1hB,OAAQ,SAASA,EAAQsO,EAAMoT,GAG3B,YAAe5hB,IAAXE,EACOyP,GAAMpC,KAAK7U,IAAI,WASLwH,aAAkBwzD,KAEnCkU,EAAYj4D,GAAMnB,IAAS,CAAC,GAClBq0B,GAAK3iC,EAAO2iC,GACtBglC,EAASjmD,EACFrU,KAAK5M,IAAI,SAAUinE,EAAWC,IAMlBl+D,GAAczJ,IAYrC0nE,EAAY1nE,EACZ2nE,EAASr5D,EACFjB,KAAK5M,IAAI,SAAUinE,EAAWC,MAZjCD,EAAYj4D,GAAMnB,IAAS,CAAC,GAClBkN,EAAIxb,EAAOwb,EACrBksD,EAAUrsD,EAAIrb,EAAOqb,EACrBssD,EAASjmD,EACFrU,KAAK5M,IAAI,SAAUinE,EAAWC,IAtBzC,IAAID,EACAC,CA8BR,EAEAp1D,OAAQ,SAASA,EAAQjE,EAAMoT,GAG3B,YAAe5hB,IAAXyS,EACO9C,GAAMpC,KAAK7U,IAAI,WASL+Z,aAAkBihD,KAEnCoU,EAAYn4D,GAAMnB,IAAS,CAAC,GAClBq0B,GAAKpwB,EAAOowB,GACtBglC,EAASjmD,EACFrU,KAAK5M,IAAI,SAAUmnE,EAAWD,IAMlBl+D,GAAc8I,IAYrCq1D,EAAYr1D,EACZo1D,EAASr5D,EACFjB,KAAK5M,IAAI,SAAUmnE,EAAWD,MAZjCC,EAAYn4D,GAAMnB,IAAS,CAAC,GAClBkN,EAAIjJ,EAAOiJ,EACrBosD,EAAUvsD,EAAI9I,EAAO8I,EACrBssD,EAASjmD,EACFrU,KAAK5M,IAAI,SAAUmnE,EAAWD,IAtBzC,IAAIC,EACAD,CA8BR,EAEAE,OAAQ,SAASrjE,EAAM8J,EAAMoT,GAGzB,QAAa5hB,IAAT0E,EAAoB,CACpB,IAAIqjE,EAASx6D,KAAK7U,IAAI,UACtB,OAAKqvE,EAGiB,iBAAXA,EAA4Bp4D,GAAMo4D,GACtCA,EAHI,IAIf,CAGA,IAAIC,EAAqC,iBAATtjE,GAAuC,mBAATA,EAC1DujE,EAAcD,EAAmBtjE,EAAO,CAAEA,KAAMA,EAAM8J,KAAMA,GAC5DygB,EAAW+4C,EAAmBx5D,EAAOoT,EAEzC,OAAOrU,KAAK5M,IAAI,SAAUsnE,EAAah5C,EAC3C,EAEAtH,UAAW,SAASjjB,EAAM8J,EAAMoT,GAG5B,QAAa5hB,IAAT0E,EAAoB,CACpB,IAAIijB,EAAYpa,KAAK7U,IAAI,aACzB,OAAKivB,EAGoB,iBAAdA,EAA+BhY,GAAMgY,GACzCA,EAHI,IAIf,CAGA,IAAIugD,EAAwC,iBAATxjE,GAAqC,mBAATA,EAC3DyjE,EAAiBD,EAAsBxjE,EAAO,CAAEA,KAAMA,EAAM8J,KAAMA,GAClEygB,EAAWi5C,EAAsB15D,EAAOoT,EAE5C,OAAOrU,KAAK5M,IAAI,YAAawnE,EAAgBl5C,EACjD,EAKAgvC,MAAO,SAASmK,EAAKnK,EAAOr8C,GAExB,IAAIymD,EAAS96D,KAAK86D,SAMlB,OAJAD,EAAOzlC,SAASylC,IAAgB,OAARA,EAAuB,EAANA,EAAW,GAC1C,IAAGA,EAAMC,EAAOtpE,OAASqpE,GAG/Bj8D,UAAUpN,QAAU,EAAUwO,KAAK3U,KAAK,CAAC,SAAUwvE,IAEhD76D,KAAK3U,KAAK,CAAC,SAAUwvE,GAAMnK,EAAOr8C,EAC7C,EAEAymD,OAAQ,SAASA,EAAQzmD,GAGrB,OAAyB,IAArBzV,UAAUpN,QACVspE,EAAS96D,KAAK7U,IAAI,UACb6F,MAAMC,QAAQ6pE,GACZA,EAAOhgE,QADqB,KAIlC9J,MAAMC,QAAQ6pE,KAASA,EAAS,IAC9B96D,KAAK5M,IAAI,SAAU0nE,EAAQzmD,GACtC,EAEA0mD,UAAW,WACP,MAAM,OAAED,GAAW96D,KAAK07B,WACxB,OAAO1qC,MAAMC,QAAQ6pE,IAAWA,EAAOtpE,OAAS,CACpD,EAEAwpE,YAAa,SAASH,EAAKnK,EAAOr8C,GAE9B,IAAKq8C,EAAO,MAAM,IAAI1nD,MAAM,+BAE5B,IAAI8xD,EAAS96D,KAAK86D,SACd9qD,EAAI8qD,EAAOtpE,OAKf,OAJAqpE,EAAOzlC,SAASylC,IAAgB,OAARA,EAAuB,EAANA,EAAW7qD,GAC1C,IAAG6qD,EAAM7qD,EAAI6qD,EAAM,GAE7BC,EAAOt6D,OAAOq6D,EAAK,EAAGnK,GACf1wD,KAAK86D,OAAOA,EAAQzmD,EAC/B,EAIA4mD,YAAa,SAASvK,EAAOr8C,GAEzB,OAAOrU,KAAKg7D,aAAa,EAAGtK,EAAOr8C,EACvC,EAEA6mD,YAAa,SAASL,EAAKxmD,GAEvB,IAAIymD,EAAS96D,KAAK86D,SAIlB,OAHAD,EAAOzlC,SAASylC,IAAgB,OAARA,EAAuB,EAANA,GAAY,EAErDC,EAAOt6D,OAAOq6D,EAAK,GACZ76D,KAAK86D,OAAOA,EAAQzmD,EAC/B,EAIA8mD,OAAQ,SAASN,EAAKM,EAAQ9mD,GAE1B,IAAI+mD,EAAWp7D,KAAKo7D,WAMpB,IAJAP,EAAOzlC,SAASylC,IAAgB,OAARA,EAAuB,EAANA,EAAW,GAC1C,IAAGA,EAAMO,EAAS5pE,OAASqpE,GAGjCj8D,UAAUpN,QAAU,EAAG,OAAOwO,KAAK3U,KAAK,CAAC,WAAYwvE,IAGzD,IAAIQ,EAAYr7D,KAAKs7D,iBAAiBH,GACtC,OAAOn7D,KAAK3U,KAAK,CAAC,WAAYwvE,GAAMQ,EAAWhnD,EACnD,EAEA+mD,SAAU,SAASA,EAAU/mD,GAGzB,GAAyB,IAArBzV,UAAUpN,OAEV,OADA4pE,EAAWp7D,KAAK7U,IAAI,YACf6F,MAAMC,QAAQmqE,GACZA,EAAStgE,QADqB,GAKpC9J,MAAMC,QAAQmqE,KAAWA,EAAW,IAEzC,IADA,IAAIG,EAAc,GACTz0D,EAAI,EAAGA,EAAIs0D,EAAS5pE,OAAQsV,IAAK,CACtC,IAAIq0D,EAASC,EAASt0D,GAClBu0D,EAAYr7D,KAAKs7D,iBAAiBH,GACtCI,EAAY3pE,KAAKypE,EACrB,CACA,OAAOr7D,KAAK5M,IAAI,WAAYmoE,EAAalnD,EAC7C,EAEAmnD,aAAc,SAASX,EAAKM,EAAQ9mD,GAEhC,IAAK8mD,EAAQ,MAAM,IAAInyD,MAAM,gCAE7B,IAAIoyD,EAAWp7D,KAAKo7D,WAChBprD,EAAIorD,EAAS5pE,QACjBqpE,EAAOzlC,SAASylC,IAAgB,OAARA,EAAuB,EAANA,EAAW7qD,GAC1C,IAAG6qD,EAAM7qD,EAAI6qD,EAAM,GAE7B,IAAIQ,EAAYr7D,KAAKs7D,iBAAiBH,GAEtC,OADAC,EAAS56D,OAAOq6D,EAAK,EAAGQ,GACjBr7D,KAAKo7D,SAASA,EAAU/mD,EACnC,EAEAonD,aAAc,SAASZ,EAAKxmD,GAExB,IAAI+mD,EAAWp7D,KAAKo7D,WAIpB,OAHAP,EAAOzlC,SAASylC,IAAgB,OAARA,EAAuB,EAANA,GAAY,EAErDO,EAAS56D,OAAOq6D,EAAK,GACd76D,KAAKo7D,SAASA,EAAU/mD,EACnC,EAEAinD,iBAAkB,SAASH,GAKvB,OADuB/+D,GAAc++D,GAI9BA,EAHqB,CAAEhtD,EAAGgtD,EAAOhtD,EAAGH,EAAGmtD,EAAOntD,EAIzD,EAIA6E,UAAW,SAASgD,EAAIC,EAAIzB,GAQxB,OALAA,EAAMA,GAAO,CAAC,GACV0jD,YAAc1jD,EAAI0jD,aAAe/3D,KAAKs1B,GAC1CjhB,EAAIwB,GAAKA,EACTxB,EAAIyB,GAAKA,EAEF9V,KAAK07D,eAAc,SAAS7tD,GAC/B,MAAO,CAAEM,GAAIN,EAAEM,GAAK,GAAK0H,EAAI7H,GAAIH,EAAEG,GAAK,GAAK8H,EACjD,GAAGzB,EACP,EAEA9H,MAAO,SAAS6F,EAAIC,EAAI5C,EAAQ4E,GAE5B,OAAOrU,KAAK07D,eAAc,SAAS7tD,GAC/B,OAAOc,GAAMd,GAAGtB,MAAM6F,EAAIC,EAAI5C,GAAQ+C,QAC1C,GAAG6B,EACP,EAEAqnD,cAAe,SAASj1D,EAAI4N,GAExB,IAAK,GAAW5N,GACZ,MAAM,IAAIi2C,UAAU,yEAGxB,IAAIxpB,EAAQ,CAAC,GAET,OAAEvgC,EAAM,OAAEuS,GAAWlF,KAAK07B,WACzB/oC,EAAO2iC,KACRpC,EAAMvgC,OAAS8T,EAAG9T,IAEjBuS,EAAOowB,KACRpC,EAAMhuB,OAASuB,EAAGvB,IAGtB,IAAIk2D,EAAWp7D,KAAKo7D,WAKpB,OAJIA,EAAS5pE,OAAS,IAClB0hC,EAAMkoC,SAAWA,EAASzqE,IAAI8V,IAG3BzG,KAAK5M,IAAI8/B,EAAO7e,EAC3B,EAEAsnD,eAAgB,WACZ,IAAIC,EAAa57D,KAAK67D,gBACtB,OAAKD,EACEA,EAAW9P,0BAA0B9rD,KAAM,UAD1B,IAAI2O,GAAM3O,KAAKrN,SAE3C,EAEAmpE,eAAgB,WACZ,IAAIC,EAAa/7D,KAAKg8D,gBACtB,OAAKD,EACEA,EAAWjQ,0BAA0B9rD,KAAM,UAD1B,IAAI2O,GAAM3O,KAAKkF,SAE3C,EAEA4mD,0BAA2B,WACvB,OAAO9rD,KAAKi8D,cAAc5oD,QAAQ,GACtC,EAEA4oD,YAAa,WACT,MAAMlsD,EAAS,CACX/P,KAAK27D,oBACF37D,KAAKo7D,WAAWzqE,IAAIge,IACvB3O,KAAK87D,kBAET,OAAO,IAAI/sD,GAASgB,EACxB,EAEAqnB,QAAS,WACL,OAAOp3B,KAAKi8D,cAAclpD,MAC9B,EAEAy1C,SAAU,SAASn0C,GAEf,IAAI6nD,EAEJ,GAAIl8D,KAAKinD,MAAO,CAEZ,IAAIt0D,EAASqN,KAAKm8D,mBACdj3D,EAASlF,KAAKo8D,mBACdC,EAAar8D,KAAKwnD,gBAElB70D,GAAUuS,IAENg3D,EADAvpE,IAAWuS,GAAUvS,EAAOk2D,aAAa3jD,GAC7BA,EACLA,EAAO2jD,aAAal2D,GACfA,EAEAqN,KAAKinD,MAAMqV,kBAAkB3pE,EAAQuS,KAIrDm3D,GAAgBH,GAAaA,EAAU5mC,KAAO+mC,EAAW/mC,IAGzD+mC,EAAW5U,QAAQznD,KAAMqU,GAGzB6nD,GACAA,EAAUvd,MAAM3+C,KAAMqU,EAE9B,CAEA,OAAO6nD,CACX,EAEAK,QAAS,SAASloD,GAEdA,EAAMA,GAAO,CAAC,EAEd,IAAI,OAAE1hB,EAAM,OAAEuS,GAAWlF,KAAK07B,WAC1B8gC,EAAW7pE,EAAO2iC,GAClBmnC,EAAWv3D,EAAOowB,GAEtB,IAAKknC,IAAaC,EAEd,OAAO,EAGX,IAAIC,EAAOF,IAAaC,EAKxB,IAAKC,GAAQroD,EAAI0zC,MAAQ/nD,KAAKinD,MAAO,CAEjC,IAAI0V,EAAgB38D,KAAK67D,gBACrBe,EAAgB58D,KAAKg8D,gBAEzBU,EAAOC,EAAc9T,aAAa+T,IAAkBA,EAAc/T,aAAa8T,EACnF,CAEA,OAAOD,CACX,EAGAb,cAAe,WAEX,MAAM,MAAE5U,EAAK,WAAEvrB,GAAe17B,KAC9B,IAAIrN,EAAS+oC,EAAW/oC,OACxB,OAAQA,GAAUA,EAAO2iC,IAAM2xB,GAASA,EAAM+B,QAAQr2D,EAAO2iC,KAAQ,IACzE,EAEA6mC,iBAAkB,WACd,IAAI5d,EAAOv+C,KACP68D,EAAU,CAAC,EACf,EAAG,CACC,GAAIA,EAAQte,EAAKjpB,IAAK,OAAO,KAC7BunC,EAAQte,EAAKjpB,KAAM,EACnBipB,EAAOA,EAAKsd,eAChB,OAAStd,GAAQA,EAAKC,UACtB,OAAOD,CACX,EAGAyd,cAAe,WAEX,MAAM,MAAE/U,EAAK,WAAEvrB,GAAe17B,KAC9B,IAAIkF,EAASw2B,EAAWx2B,OACxB,OAAQA,GAAUA,EAAOowB,IAAM2xB,GAASA,EAAM+B,QAAQ9jD,EAAOowB,KAAQ,IACzE,EAEA8mC,iBAAkB,WACd,IAAI7d,EAAOv+C,KACP68D,EAAU,CAAC,EACf,EAAG,CACC,GAAIA,EAAQte,EAAKjpB,IAAK,OAAO,KAC7BunC,EAAQte,EAAKjpB,KAAM,EACnBipB,EAAOA,EAAKyd,eAChB,OAASzd,GAAQA,EAAKC,UACtB,OAAOD,CACX,EAIAue,wBAAyB,WAErB,IAAIC,EAEJ,GAAI/8D,KAAKinD,MAAO,CAEZ,IAAI5I,EAAQ,CACRr+C,KACAA,KAAKm8D,mBACLn8D,KAAKo8D,oBACProE,QAAO,SAASyyC,GACd,QAASA,CACb,IAEAu2B,EAAqB/8D,KAAKinD,MAAMqV,kBAAkBn7D,MAAMnB,KAAKinD,MAAO5I,EACxE,CAEA,OAAO0e,GAAsB,IACjC,EAGAC,yBAA0B,SAASze,GAE/B,IAAIgL,EAAU3oD,GAAS29C,IAAS59C,GAAS49C,GAASA,EAAOA,EAAKjpB,GAC1D2nC,EAAWj9D,KAAK88D,0BAEpB,QAASG,IAAaA,EAAS3nC,KAAOi0B,GAAU0T,EAASpU,aAAaU,GAC1E,EAGA2T,iBAAkB,WAEd,IAAInD,EAAe/5D,KAAK7U,IAAI,iBAAmB6U,KAAK+5D,cAAgB,CAAC,EAEjErJ,EAAQ,CAAC,EAMb,OALAA,EAAMQ,OAAS6I,EAAa7I,QAAUlxD,KAAK7U,IAAI,gBAAkB6U,KAAKg6D,YACtEtJ,EAAM9yB,SAAWm8B,EAAan8B,SAC9B8yB,EAAMx9B,MAAQ6mC,EAAa7mC,MAC3Bw9B,EAAMl5D,KAAOuiE,EAAaviE,KAEnBk5D,CACX,GACD,CAECyM,UAAW,SAASxhE,EAAGC,GAEnB,IAAIwhE,EAAazhE,EAAEmqD,OAASlqD,EAAEkqD,OAASnqD,EAAEmqD,OAASlqD,EAAEkqD,KACpD,OAAOnqD,EAAE25B,KAAO15B,EAAE05B,IAAM8nC,CAC5B,ICljBSC,GAAM,CAEfC,SAAU,CAAC,EAEXC,OAAQ,CAEJC,iBAAkB,WACd,QAASr3D,SAASwtB,iBACd,mBAAmB7jC,KAAK,CAAG,EAAEiD,SAASvH,KAAK2a,SAASwtB,gBAAgB,6BAA8B,kBAC1G,EAGA8pC,SAAU,WACN,MAAO,SAAS3tE,KAAK4tE,UAAUC,YAAc,iBAAiB7tE,KAAK4tE,UAAUE,OACjF,GAGJC,QAAS,SAAS1mE,EAAMsP,GAEpB,OAAOzG,KAAKu9D,OAAOpmE,GAAQsP,CAC/B,EAEA3W,KAAM,SAASqH,GAEX,IAAIsP,EAAKzG,KAAKu9D,OAAOpmE,GAErB,IAAKsP,EACD,MAAM,IAAIuC,MAAM,sBAAwB7R,EAAO,4DAGnD,IAAI1F,EAASuO,KAAKs9D,SAASnmE,GAE3B,QAAsB,IAAX1F,EACP,OAAOA,EAGX,IACIA,EAASgV,GACb,CAAE,MAAO07B,GACL1wC,GAAS,CACb,CAKA,OAFAuO,KAAKs9D,SAASnmE,GAAQ1F,EAEfA,CACX,GCpCSqsE,GAAY,GAAQzR,OAAO,qBAAsB,CAC1Dn5B,MAAO,CACHnc,KAAM,CACFgnD,OAAQ,QAEZr2D,KAAM,CACF8I,MAAO,UACPC,OAAQ,UACRutD,YAAa,EACb9Y,OAAQ,UACRgV,KAAM,WAEVxJ,MAAO,CACHj4B,mBAAoB,SACpBu1B,WAAY,SACZ7/C,EAAG,YACHH,EAAG,YACH2mB,SAAU,GACVulC,KAAM,aAGf,CACChJ,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,QACX,CACCu1B,QAAS,OACTv1B,SAAU,YAIL03D,GAAS,GAAQ5R,OAAO,kBAAmB,CACpDn5B,MAAO,CACHnc,KAAM,CACFgnD,OAAQ,QAEZr2D,KAAM,CACFmvB,GAAI,YACJC,GAAI,YACJxmB,EAAG,YACH0tD,YAAa,EACb9Y,OAAQ,UACRgV,KAAM,WAEVxJ,MAAO,CACHj4B,mBAAoB,SACpBu1B,WAAY,SACZ7/C,EAAG,YACHH,EAAG,YACH2mB,SAAU,GACVulC,KAAM,aAGf,CACChJ,OAAQ,CAAC,CACLp1B,QAAS,SACTv1B,SAAU,QACX,CACCu1B,QAAS,OACTv1B,SAAU,YAIL,GAAU,GAAQ8lD,OAAO,mBAAoB,CACtDn5B,MAAO,CACHnc,KAAM,CACFgnD,OAAQ,QAEZr2D,KAAM,CACFmvB,GAAI,YACJC,GAAI,YACJrgB,GAAI,YACJC,GAAI,YACJsnD,YAAa,EACb9Y,OAAQ,UACRgV,KAAM,WAEVxJ,MAAO,CACHj4B,mBAAoB,SACpBu1B,WAAY,SACZ7/C,EAAG,YACHH,EAAG,YACH2mB,SAAU,GACVulC,KAAM,aAGf,CACChJ,OAAQ,CAAC,CACLp1B,QAAS,UACTv1B,SAAU,QACX,CACCu1B,QAAS,OACTv1B,SAAU,YAIL,GAAO,GAAQ8lD,OAAO,gBAAiB,CAChDn5B,MAAO,CACHnc,KAAM,CACFgnD,OAAQ,QAEZr2D,KAAM,CACFoP,EAAG,kCACHknD,YAAa,EACb9Y,OAAQ,UACRgV,KAAM,WAEVxJ,MAAO,CACHj4B,mBAAoB,SACpBu1B,WAAY,SACZ7/C,EAAG,YACHH,EAAG,YACH2mB,SAAU,GACVulC,KAAM,aAGf,CACChJ,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,QACX,CACCu1B,QAAS,OACTv1B,SAAU,YAIL,GAAU,GAAQ8lD,OAAO,mBAAoB,CACtDn5B,MAAO,CACHnc,KAAM,CACFgnD,OAAQ,QAEZr2D,KAAM,CACFqI,OAAQ,0CACRiuD,YAAa,EACb9Y,OAAQ,UACRgV,KAAM,WAEVxJ,MAAO,CACHj4B,mBAAoB,SACpBu1B,WAAY,SACZ7/C,EAAG,YACHH,EAAG,YACH2mB,SAAU,GACVulC,KAAM,aAGf,CACChJ,OAAQ,CAAC,CACLp1B,QAAS,UACTv1B,SAAU,QACX,CACCu1B,QAAS,OACTv1B,SAAU,YAIL,GAAW,GAAQ8lD,OAAO,oBAAqB,CACxDn5B,MAAO,CACHnc,KAAM,CACFgnD,OAAQ,QAEZr2D,KAAM,CACFqI,OAAQ,0CACRiuD,YAAa,EACb9Y,OAAQ,UACRgV,KAAM,WAEVxJ,MAAO,CACHj4B,mBAAoB,SACpBu1B,WAAY,SACZ7/C,EAAG,YACHH,EAAG,YACH2mB,SAAU,GACVulC,KAAM,aAGf,CACChJ,OAAQ,CAAC,CACLp1B,QAAS,WACTv1B,SAAU,QACX,CACCu1B,QAAS,OACTv1B,SAAU,YAIL23D,GAAQ,GAAQ7R,OAAO,iBAAkB,CAClDn5B,MAAO,CACHnc,KAAM,CACFgnD,OAAQ,QAEZI,MAAO,CACH3tD,MAAO,UACPC,OAAQ,WAGZigD,MAAO,CACHj4B,mBAAoB,MACpBu1B,WAAY,SACZ7/C,EAAG,YACHH,EAAG,aACH2mB,SAAU,GACVulC,KAAM,aAGf,CACChJ,OAAQ,CAAC,CACLp1B,QAAS,QACTv1B,SAAU,SACX,CACCu1B,QAAS,OACTv1B,SAAU,YAIL63D,GAAgB,GAAQ/R,OAAO,yBAA0B,CAClEn5B,MAAO,CACHnc,KAAM,CACFgnD,OAAQ,QAEZM,OAAQ,CACJ7tD,MAAO,UACPC,OAAQ,UACRy0C,OAAQ,UACR8Y,YAAa,GAEjBM,WAAY,CACR9tD,MAAO,YACPC,OAAQ,YACRtC,EAAG,GACHH,EAAG,GACHksD,KAAM,WAEViE,MAAO,CAEH3tD,MAAO,YACPC,OAAQ,YACRtC,EAAG,GACHH,EAAG,IAEP0iD,MAAO,CACHj4B,mBAAoB,MACpBu1B,WAAY,SACZ7/C,EAAG,YACHH,EAAG,aACH2mB,SAAU,GACVulC,KAAM,aAGf,CACChJ,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,aACVm1B,WAAY,CACR,OAAU,SAEf,CACCI,QAAS,QACTv1B,SAAU,SACX,CACCu1B,QAAS,OACTv1B,SAAU,SACVm1B,WAAY,CACR,KAAQ,SAEb,CACCI,QAAS,OACTv1B,SAAU,YAILg4D,GAAgB,GAAQlS,OAAO,yBAA0B,CAClEn5B,MAAO,CACHnc,KAAM,CACFgnD,OAAQ,QAEZr2D,KAAM,CACF8I,MAAO,UACPC,OAAQ,UACRy0C,OAAQ,UACRgV,KAAM,UACN8D,YAAa,GAEjBG,MAAO,CAEH3tD,MAAO,cACPC,OAAQ,aACRtC,EAAG,GACHH,EAAG,GACHwwD,oBAAqB,YAEzB9N,MAAO,CACHj4B,mBAAoB,MACpBu1B,WAAY,OACZ7/C,EAAG,iBACHH,EAAG,GACH2mB,SAAU,GACVulC,KAAM,aAGf,CACChJ,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,QACX,CACCu1B,QAAS,QACTv1B,SAAU,SACX,CACCu1B,QAAS,OACTv1B,SAAU,YAILk4D,GAAiB,GAAQpS,OAAO,0BAA2B,CACpEn5B,MAAO,CACHnc,KAAM,CACFgnD,OAAQ,QAEZM,OAAQ,CACJ5nD,GAAI,YACJC,GAAI,YACJmgB,GAAI,YACJC,GAAI,YACJouB,OAAQ,UACR8Y,YAAa,GAEjBM,WAAY,CACR7nD,GAAI,YACJC,GAAI,YACJmgB,GAAI,YACJC,GAAI,YACJojC,KAAM,WAEViE,MAAO,CAEH3tD,MAAO,eACPC,OAAQ,eAERtC,EAAG,eACHH,EAAG,eACHwwD,oBAAqB,YAGzB9N,MAAO,CACHj4B,mBAAoB,MACpBu1B,WAAY,SACZ7/C,EAAG,YACHH,EAAG,aACH2mB,SAAU,GACVulC,KAAM,aAGf,CACChJ,OAAQ,CAAC,CACLp1B,QAAS,UACTv1B,SAAU,cACX,CACCu1B,QAAS,QACTv1B,SAAU,SACX,CACCu1B,QAAS,UACTv1B,SAAU,SACVm1B,WAAY,CACR,KAAQ,SAEb,CACCI,QAAS,OACTv1B,SAAU,YAILm4D,GAAoB,GAAQrS,OAAO,6BAA8B,CAC1En5B,MAAO,CACHnc,KAAM,CACFgnD,OAAQ,QAEZr2D,KAAM,CACF8I,MAAO,UACPC,OAAQ,UACRutD,YAAa,EACb9Y,OAAQ,UACRgV,KAAM,WAEVyE,OAAQ,CACJnuD,MAAO,UACPC,OAAQ,GACRutD,YAAa,EACb9Y,OAAQ,UACRgV,KAAM,WAEV0E,WAAY,CACRnmC,mBAAoB,SACpBu1B,WAAY,SACZ7/C,EAAG,YACHH,EAAG,GACH2mB,SAAU,GACVulC,KAAM,WAEV2E,SAAU,CACNpmC,mBAAoB,SACpBu1B,WAAY,SACZ7/C,EAAG,YACHH,EAAG,eACH2mB,SAAU,GACVulC,KAAM,aAGf,CACChJ,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,QACX,CACCu1B,QAAS,OACTv1B,SAAU,UACX,CACCu1B,QAAS,OACTv1B,SAAU,cACX,CACCu1B,QAAS,OACTv1B,SAAU,eAMLu4D,GAAW,GAAQzS,OAAO,oBAAqB,CACxDn5B,MAAO,CACHnc,KAAM,CACFgnD,OAAQ,QAEZr2D,KAAM,CACFq3D,YARQ,GASR7E,KAAM,UACNhV,OAAQ,UACR8Y,YAAa,GAEjB/qD,IAAK,CACD4jB,GAAI,YACJC,GAfQ,GAgBRrgB,GAAI,YACJC,GAjBQ,GAkBRwjD,KAAM,UACNhV,OAAQ,UACR8Y,YAAa,GAEjBtN,MAAO,CACHj4B,mBAAoB,SACpBu1B,WAAY,SACZ7/C,EAAG,YACHH,EAAG,aACH2mB,SAAU,GACVulC,KAAM,aAGf,CACChJ,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,QACX,CACCu1B,QAAS,UACTv1B,SAAU,OACX,CACCu1B,QAAS,OACTv1B,SAAU,UAGdohC,MAAO,SAASl2B,EAAG4C,GAEf,QAAU5hB,IAANgf,EAAiB,OAAOzR,KAAKk1B,KAAK,oBAGtC,IAAI8pC,EAAY,CAAED,YAAattD,GAG3BqE,EADqB++B,GAAapjC,GACN,QAAQnC,WAAWmC,GAAK,SAAWA,EAC/DwtD,EAAW,CAAEnoC,GAAIhhB,EAAIY,GAAIZ,GAE7B,OAAO9V,KAAKk1B,KAAK,CAAExtB,KAAMs3D,EAAW/rD,IAAKgsD,GAAY5qD,EACzD,GAED,CACCqnB,WAAY,CACR,eAAgB,CACZtoC,IAAK,SAASqe,EAAG2uC,GACb,IAAI8e,EAAqBrqB,GAAapjC,GAClCytD,IAAoBztD,EAAInC,WAAWmC,GAAK,KAE5C,IAAItD,EAAIiyC,EAAQjyC,EACZH,EAAIoyC,EAAQpyC,EACZ2J,EAAIyoC,EAAQ5vC,MACZoH,EAAIwoC,EAAQ3vC,OAGZgG,EAAKkB,EAAI,EACTjB,EAAKwoD,EAAsBtnD,EAAInG,EAAKA,EAEpC0tD,EAAQ,GAAEh4B,MACVtQ,EAAKsoC,EAAQ1oD,EACbqgB,EAAKqoC,GAASD,EAAsBtnD,EAAInG,EAAKA,GAI7C2tD,EAAUjxD,EAAKwJ,EAAI,EACnB0nD,EAASlxD,EAAIwJ,EAEb2nD,EAAWtxD,EAAI0I,EACf6oD,EAAYD,EAAW5oD,EACvB8oD,EAAcxxD,EAAI4J,EAAIlB,EACtB+oD,EAAezxD,EAAI4J,EAavB,MAAO,CAAEd,EAVE,CACP,IAXQ3I,EAWImxD,EACZ,IAZQnxD,EAYIqxD,EACZ,IAAKrxD,EAAIqxD,EAAc1oC,EAAMsoC,EAAUvoC,EAAK4oC,EAAcL,EAASK,EACnE,IAAML,EAAUvoC,EAAK4oC,EAAcJ,EAASG,EAAc1oC,EAAKuoC,EAAQG,EACvE,IAAKH,EAAQC,EACb,IAAKD,EAASC,EAAWxoC,EAAMsoC,EAAUvoC,EAAK0oC,EAAWH,EAASG,EAClE,IAAMH,EAAUvoC,EAAK0oC,EAjBbpxD,EAiBgCmxD,EAAWxoC,EAjB3C3oB,EAiBuDmxD,EAC/D,KAEaxwE,KAAK,KAC1B,EACAqM,MAAO,QAKnB,IAkCI6+D,GAAeqD,GAAIvtE,KAAK,oBAlCR,CAChBgsC,QAAS,gBACTv1B,SAAU,gBACVm1B,WAAY,CACR,SAAY,UAEhBvI,SAAU,CAAC,CACP2I,QAAS,MACTiW,aAAc,+BACdxrC,SAAU,QACV0zB,MAAO,CACHzpB,MAAO,OACPC,OAAQ,OACRmtB,SAAU,SACV8hC,gBAAiB,cACjBC,UAAW,SACX7mB,OAAQ,EACRwgB,QAAS,UACTsG,UAAW,aACX7pB,QAAS,OACT8pB,WAAY,SACZC,eAAgB,aAKP,CACjBhkC,QAAS,OACTv1B,SAAU,QACVm1B,WAAY,CACR,cAAe,WAMhB,MAAMqkC,GAAY,GAAQ1T,OAAO,qBAAsB,CAC1Dn5B,MAAO,CACHnc,KAAM,CACFgnD,OAAQ,QAEZr2D,KAAM,CACF8I,MAAO,UACPC,OAAQ,UACRy0C,OAAQ,UACRgV,KAAM,UACN8D,YAAa,GAEjBgC,cAAe,CACXxvD,MAAO,UACPC,OAAQ,WAEZigD,MAAO,CACHz2B,MAAO,CACHtF,SAAU,OAIvB,CACCu8B,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,QACXyzD,KACJ,CACCt+B,WAAY,CACRvD,KAAM,CACF/kC,IAAK,SAAS+kC,EAAMioB,EAASt3C,EAAMoqB,GAC/B,KAAIpqB,aAAgBm3D,aAEb,CAEH,IAAIhmC,EAAQ/G,EAAa,OAAK,CAAC,EAC3BgtC,EAAY,CAAE/nC,OAAM3nB,OAAQ,EAAGC,OAAQ,QACvC0vD,EAAY,GAAO,CAAE,uBAAwB,UAAYlmC,GAE7D,OADAyB,GAAW,aAAatoC,IAAI5H,KAAKwU,KAAMkgE,EAAW9f,EAASt3C,EAAMq3D,GAC1D,CAAEjG,KAAMjgC,EAAM+e,OAAS,KAClC,CARIlwC,EAAKisB,YAAcoD,CAS3B,EACAh9B,MAAO,SAAS2N,GAEZ,GADAA,EAAKisB,YAAc,GACfjsB,aAAgBy7B,WAChB,MAAO,MAEf,EACA3G,SAAU,SAASzF,EAAMioB,EAASt3C,GAE9B,GAAIA,aAAgBy7B,WAAY,OAAO6b,EAAQlqC,QACnD,MAOC,GAAO4jD,GAASzN,OAAO,gBAAiB,CACjDn5B,MAAO,CACH1e,KAAM,CACFwxC,YAAY,EACZd,OAAQ,UACR8Y,YAAa,EACboC,eAAgB,QAChBC,aAAc,CACV,KAAQ,OACR,EAAK,uBAGbC,QAAS,CACLta,YAAY,EACZgY,YAAa,GACboC,eAAgB,WAGzB,CACClP,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,UACVm1B,WAAY,CACR,KAAQ,OACR,OAAU,UACV,OAAU,cACV,iBAAkB,UAEvB,CACCI,QAAS,OACTv1B,SAAU,OACVm1B,WAAY,CACR,KAAQ,OACR,iBAAkB,YAKjB6kC,GAAazG,GAASzN,OAAO,sBAAuB,CAC7Dn5B,MAAO,CACH1e,KAAM,CACFwxC,YAAY,EACZd,OAAQ,UACR8Y,YAAa,EACboC,eAAgB,QAChBC,aAAc,CACVluE,KAAM,OACN+yD,OAAQ,UACRpuC,EAAG,mCAGX+hC,QAAS,CACLmN,YAAY,EACZd,OAAQ,UACR8Y,YAAa,EACboC,eAAgB,WAGzB,CACClP,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,UACVm1B,WAAY,CACR,KAAQ,OACR,OAAU,YAEf,CACCI,QAAS,OACTv1B,SAAU,OACVm1B,WAAY,CACR,KAAQ,OACR,iBAAkB,YAKjB8kC,GAAa1G,GAASzN,OAAO,sBAAuB,CAC7Dn5B,MAAO,CACH1e,KAAM,CACFwxC,YAAY,EACZd,OAAQ,UACR8Y,YAAa,GACboC,eAAgB,QAChBC,aAAc,CACV,KAAQ,OACR,OAAU,OACV,EAAK,wBAETI,aAAc,CACV,KAAQ,OACR,OAAU,OACV,EAAK,sCAGbC,OAAQ,CACJ1a,YAAY,EACZhwB,UAAW,iBACXkvB,OAAQ,UACR/qB,cAAe,GACf6jC,YAAa,GACboC,eAAgB,QAChBC,aAAc,CACV,KAAQ,OACR,EAAK,uBACL,OAAU,QAEdI,aAAc,CACV,KAAQ,OACR,OAAU,OACV,EAAK,wCAIlB,CACCvP,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,SACVm1B,WAAY,CACR,KAAQ,OACR,iBAAkB,SAEvB,CACCI,QAAS,OACTv1B,SAAU,OACVm1B,WAAY,CACR,KAAQ,OACR,OAAU,eCpvBTilC,GAAY,CACrBC,IAAK,MACLC,MAAO,QACPC,OAAQ,SACRC,KAAM,OACNC,SAAU,WACVC,UAAW,YACXC,YAAa,cACbC,aAAc,eACdC,OAAQ,UAGL,SAASC,GAAaprD,EAAM2nB,GAC/B,MAAMttB,EAAI,IAAI,GAAO2F,GACrB,OAAQ2nB,GACJ,UAAKnrC,EACD,MAAM,IAAIuW,MAAM,qBAGpB,KAAK23D,GAAUI,KACf,IAAK,aACD,OAAOzwD,EAAEgK,aAEb,KAAKqmD,GAAUE,MACf,IAAK,cACD,OAAOvwD,EAAEsL,cAEb,KAAK+kD,GAAUC,IACf,IAAK,YACD,OAAOtwD,EAAE2L,YAEb,KAAK0kD,GAAUG,OACf,IAAK,eACD,OAAOxwD,EAAEuI,eAGb,KAAK8nD,GAAUK,SACf,IAAK,UACL,IAAK,SACD,OAAO1wD,EAAE+J,UAEb,KAAKsmD,GAAUM,UACf,IAAK,WACD,OAAO3wD,EAAE6K,WAEb,KAAKwlD,GAAUO,YACf,IAAK,aACD,OAAO5wD,EAAEoI,aAEb,KAAKioD,GAAUQ,aACf,IAAK,cACL,IAAK,SACD,OAAO7wD,EAAEsI,cAGb,KAAK+nD,GAAUS,OACX,OAAO9wD,EAAE4F,SAGb,QACI,MAAM,IAAIlN,MAAM,qBAAqB40B,KAEjD,CCtCO,IAAI0jC,GAAa,SAASC,EAAQ5pC,GACrCA,IAAYA,EAAU,CAAC,GACvB33B,KAAK89C,cAAc38C,MAAMnB,KAAMpB,WAC3B+4B,EAAQgmB,QAAO39C,KAAK29C,MAAQhmB,EAAQgmB,YACb,IAAvBhmB,EAAQ6pC,aAAuBxhE,KAAKwhE,WAAa7pC,EAAQ6pC,YAC7DxhE,KAAKyhE,SACLzhE,KAAKm+C,WAAWh9C,MAAMnB,KAAMpB,WACxB2iE,GAAQvhE,KAAK0hE,MAAMH,EAAQ,GAAO,CAAExiB,QAAQ,GAAQpnB,GAC5D,EAGIgqC,GAAa,CAAE/mE,KAAK,EAAM2J,QAAQ,EAAMrD,OAAO,GAC/C0gE,GAAa,CAAEhnE,KAAK,EAAM2J,QAAQ,GAGlC/D,GAAS,SAAS1O,EAAO+vE,EAAQC,GACjCA,EAAK//D,KAAKE,IAAIF,KAAKwL,IAAIu0D,EAAI,GAAIhwE,EAAMN,QACrC,IAEIsV,EAFAi7D,EAAO/wE,MAAMc,EAAMN,OAASswE,GAC5BtwE,EAASqwE,EAAOrwE,OAEpB,IAAKsV,EAAI,EAAGA,EAAIi7D,EAAKvwE,OAAQsV,IAAKi7D,EAAKj7D,GAAKhV,EAAMgV,EAAIg7D,GACtD,IAAKh7D,EAAI,EAAGA,EAAItV,EAAQsV,IAAKhV,EAAMgV,EAAIg7D,GAAMD,EAAO/6D,GACpD,IAAKA,EAAI,EAAGA,EAAIi7D,EAAKvwE,OAAQsV,IAAKhV,EAAMgV,EAAItV,EAASswE,GAAMC,EAAKj7D,EACpE,EAGA,GAAOw6D,GAAWh2E,UAAWsvD,GAAQ,CAIjC+C,MAAOE,GAKPC,cAAe,WAAW,EAI1BK,WAAY,WAAW,EAIvB3rC,OAAQ,SAASmlB,GACb,OAAO33B,KAAKrP,KAAI,SAASgtD,GAAS,OAAOA,EAAMnrC,OAAOmlB,EAAU,GACpE,EAKA/8B,IAAK,SAAS2mE,EAAQ5pC,GAClB,OAAO33B,KAAK5M,IAAImuE,EAAQ,GAAO,CAAErgE,OAAO,GAASy2B,EAASiqC,IAC9D,EAGAr9D,OAAQ,SAASg9D,EAAQ5pC,GACrBA,EAAU,GAAO,CAAC,EAAGA,GACrB,IAAIqqC,GAAYhxE,MAAMC,QAAQswE,GAC9BA,EAASS,EAAW,CAACT,GAAUA,EAAOzmE,QACtC,IAAI+2D,EAAU7xD,KAAKiiE,cAAcV,EAAQ5pC,GAKzC,OAJKA,EAAQonB,QAAU8S,EAAQrgE,SAC3BmmC,EAAQqnB,QAAU,CAAE6U,MAAO,GAAIqO,OAAQ,GAAIrQ,QAASA,GACpD7xD,KAAK28C,QAAQ,SAAU38C,KAAM23B,IAE1BqqC,EAAWnQ,EAAQ,GAAKA,CACnC,EAMAz+D,IAAK,SAASmuE,EAAQ5pC,GAClB,GAAc,MAAV4pC,EAAJ,CAEA5pC,EAAU,GAAO,CAAC,EAAGgqC,GAAYhqC,GAEjC,IAAIqqC,GAAYhxE,MAAMC,QAAQswE,GAC9BA,EAASS,EAAW,CAACT,GAAUA,EAAOzmE,QAEtC,IAAIgnE,EAAKnqC,EAAQmqC,GACP,MAANA,IAAYA,GAAMA,GAClBA,EAAK9hE,KAAKxO,SAAQswE,EAAK9hE,KAAKxO,QAC5BswE,EAAK,IAAGA,GAAM9hE,KAAKxO,OAAS,GAEhC,IAgBImsD,EAAO72C,EAhBP1T,EAAM,GACNqsC,EAAQ,GACR0iC,EAAU,GACVC,EAAW,GACXC,EAAW,CAAC,EAEZznE,EAAM+8B,EAAQ/8B,IACdsG,EAAQy2B,EAAQz2B,MAChBqD,EAASozB,EAAQpzB,OAEjBhH,GAAO,EACP+kE,EAAWtiE,KAAKwhE,YAAoB,MAANM,IAA+B,IAAjBnqC,EAAQp6B,KACpDglE,EAAW3hE,GAASZ,KAAKwhE,YAAcxhE,KAAKwhE,WAAa,KAK7D,IAAK16D,EAAI,EAAGA,EAAIy6D,EAAO/vE,OAAQsV,IAAK,CAChC62C,EAAQ4jB,EAAOz6D,GAIf,IAAI07D,EAAWxiE,KAAK7U,IAAIwyD,GACxB,GAAI6kB,EAAU,CACV,GAAIthE,GAASy8C,IAAU6kB,EAAU,CAC7B,IAAItvC,EAAQlzB,KAAKy9C,SAASE,GAASA,EAAMjiB,WAAaiiB,EACtD6kB,EAASpvE,IAAI8/B,EAAOyE,GACpBwqC,EAAQvwE,KAAK4wE,GACTF,IAAa/kE,IAAMA,EAAOilE,EAASjjB,WAAWgjB,GACtD,CACKF,EAASG,EAASzkB,OACnBskB,EAASG,EAASzkB,MAAO,EACzB3qD,EAAIxB,KAAK4wE,IAEbjB,EAAOz6D,GAAK07D,CAGhB,MAAW5nE,IACP+iD,EAAQ4jB,EAAOz6D,GAAK9G,KAAKyiE,cAAc9kB,EAAOhmB,MAE1C8H,EAAM7tC,KAAK+rD,GACX39C,KAAK0iE,cAAc/kB,EAAOhmB,GAC1B0qC,EAAS1kB,EAAMI,MAAO,EACtB3qD,EAAIxB,KAAK+rD,GAGrB,CAGA,GAAIp5C,EAAQ,CACR,IAAKuC,EAAI,EAAGA,EAAI9G,KAAKxO,OAAQsV,IAEpBu7D,GADL1kB,EAAQ39C,KAAKuhE,OAAOz6D,IACAi3C,MAAMqkB,EAASxwE,KAAK+rD,GAExCykB,EAAS5wE,QAAQwO,KAAKiiE,cAAcG,EAAUzqC,EACtD,CAGA,IAAIgrC,GAAe,EACf5qE,GAAWuqE,GAAY1nE,GAAO2J,EAkBlC,GAjBInR,EAAI5B,QAAUuG,GACd4qE,EAAe3iE,KAAKxO,SAAW4B,EAAI5B,QAAUwO,KAAKuhE,OAAO5qE,MAAK,SAASygB,EAAG1lB,GACtE,OAAO0lB,IAAMhkB,EAAI1B,EACrB,IACAsO,KAAKuhE,OAAO/vE,OAAS,EACrBgP,GAAOR,KAAKuhE,OAAQnuE,EAAK,GACzB4M,KAAKxO,OAASwO,KAAKuhE,OAAO/vE,QACnBiuC,EAAMjuC,SACT8wE,IAAU/kE,GAAO,GACrBiD,GAAOR,KAAKuhE,OAAQ9hC,EAAa,MAANqiC,EAAa9hE,KAAKxO,OAASswE,GACtD9hE,KAAKxO,OAASwO,KAAKuhE,OAAO/vE,QAI1B+L,GAAMyC,KAAKzC,KAAK,CAAEwhD,QAAQ,KAGzBpnB,EAAQonB,OAAQ,CACjB,IAAKj4C,EAAI,EAAGA,EAAI24B,EAAMjuC,OAAQsV,IAChB,MAANg7D,IAAYnqC,EAAQjmC,MAAQowE,EAAKh7D,IACrC62C,EAAQle,EAAM34B,IACR61C,QAAQ,MAAOgB,EAAO39C,KAAM23B,IAElCp6B,GAAQolE,IAAc3iE,KAAK28C,QAAQ,OAAQ38C,KAAM23B,IACjD8H,EAAMjuC,QAAU4wE,EAAS5wE,QAAU2wE,EAAQ3wE,UAC3CmmC,EAAQqnB,QAAU,CACd6U,MAAOp0B,EACPoyB,QAASuQ,EACTF,OAAQC,GAEZniE,KAAK28C,QAAQ,SAAU38C,KAAM23B,GAErC,CAGA,OAAOqqC,EAAWT,EAAO,GAAKA,CA3GJ,CA4G9B,EAMAG,MAAO,SAASH,EAAQ5pC,GACpBA,EAAUA,EAAUv1B,GAAMu1B,GAAW,CAAC,EACtC,IAAK,IAAI7wB,EAAI,EAAGA,EAAI9G,KAAKuhE,OAAO/vE,OAAQsV,IACpC9G,KAAK4iE,iBAAiB5iE,KAAKuhE,OAAOz6D,GAAI6wB,GAM1C,OAJAA,EAAQkrC,eAAiB7iE,KAAKuhE,OAC9BvhE,KAAKyhE,SACLF,EAASvhE,KAAKpF,IAAI2mE,EAAQ,GAAO,CAAExiB,QAAQ,GAAQpnB,IAC9CA,EAAQonB,QAAQ/+C,KAAK28C,QAAQ,QAAS38C,KAAM23B,GAC1C4pC,CACX,EAGA3vE,KAAM,SAAS+rD,EAAOhmB,GAClB,OAAO33B,KAAKpF,IAAI+iD,EAAO,GAAO,CAAEmkB,GAAI9hE,KAAKxO,QAAUmmC,GACvD,EAGAp3B,IAAK,SAASo3B,GACV,IAAIgmB,EAAQ39C,KAAK8hE,GAAG9hE,KAAKxO,OAAS,GAClC,OAAOwO,KAAKuE,OAAOo5C,EAAOhmB,EAC9B,EAGA1a,QAAS,SAAS0gC,EAAOhmB,GACrB,OAAO33B,KAAKpF,IAAI+iD,EAAO,GAAO,CAAEmkB,GAAI,GAAKnqC,GAC7C,EAGA6T,MAAO,SAAS7T,GACZ,IAAIgmB,EAAQ39C,KAAK8hE,GAAG,GACpB,OAAO9hE,KAAKuE,OAAOo5C,EAAOhmB,EAC9B,EAGA78B,MAAO,WACH,OAAO9J,MAAM1F,UAAUwP,MAAMqG,MAAMnB,KAAKuhE,OAAQ3iE,UACpD,EAIAzT,IAAK,SAASC,GACV,GAAW,MAAPA,EACJ,OAAO4U,KAAK8iE,MAAM13E,IAClB4U,KAAK8iE,MAAM9iE,KAAK+iE,QAAQ/iE,KAAKy9C,SAASryD,GAAOA,EAAIswC,WAAatwC,EAAKA,EAAIyzD,eACvEzzD,EAAI2yD,KAAO/9C,KAAK8iE,MAAM13E,EAAI2yD,IAC9B,EAGA/mD,IAAK,SAAS5L,GACV,OAAwB,MAAjB4U,KAAK7U,IAAIC,EACpB,EAGA02E,GAAI,SAASpwE,GAET,OADIA,EAAQ,IAAGA,GAASsO,KAAKxO,QACtBwO,KAAKuhE,OAAO7vE,EACvB,EAKA6L,KAAM,SAASo6B,GACX,IAAI6pC,EAAaxhE,KAAKwhE,WACtB,IAAKA,EAAY,MAAM,IAAIx4D,MAAM,0CACjC2uB,IAAYA,EAAU,CAAC,GAEvB,IAAInmC,EAASgwE,EAAWhwE,OAUxB,OATI,GAAWgwE,KAAaA,EAAaA,EAAWzxE,KAAKiQ,OAG1C,IAAXxO,GAAgBoP,GAAS4gE,GACzBxhE,KAAKuhE,OAASvhE,KAAK8C,OAAO0+D,GAE1BxhE,KAAKuhE,OAAOhkE,KAAKikE,GAEhB7pC,EAAQonB,QAAQ/+C,KAAK28C,QAAQ,OAAQ38C,KAAM23B,GACzC33B,IACX,EAGAoC,MAAO,WACH,OAAO,IAAIpC,KAAK1N,YAAY0N,KAAKuhE,OAAQ,CACrC5jB,MAAO39C,KAAK29C,MACZ6jB,WAAYxhE,KAAKwhE,YAEzB,EAGAuB,QAAS,SAAS7vC,EAAO2rB,GACrB,OAAO3rB,EAAM2rB,GAAe7+C,KAAK29C,MAAMryD,UAAUuzD,aAAe,KACpE,EAGAruD,OAAQ,WACJ,OAAO,IAAIwyE,GAAmBhjE,KAAMijE,GACxC,EAGAvyE,KAAM,WACF,OAAO,IAAIsyE,GAAmBhjE,KAAMkjE,GACxC,EAGAnjE,QAAS,WACL,OAAO,IAAIijE,GAAmBhjE,KAAMmjE,GACxC,EAGAC,KAAM,SAAS38D,EAAIQ,GACfjH,KAAKuhE,OAAO5pE,QAAQ8O,EAAIQ,EAC5B,EAGAlT,OAAQ,SAAS0S,EAAIQ,GACjB,OAAOjH,KAAKuhE,OAAOxtE,OAAO0S,EAAIQ,EAClC,EAEAmB,KAAM,SAAS3B,EAAIQ,GACf,OAAOjH,KAAKuhE,OAAOn5D,KAAK3B,EAAIQ,EAChC,EAEAyrD,UAAW,SAASjsD,EAAIQ,GACpB,OAAOjH,KAAKuhE,OAAO7O,UAAUjsD,EAAIQ,EACrC,EAGAN,MAAO,WACH,OAAO3G,KAAKuhE,OAAO,EACvB,EAGAvoE,SAAU,SAASrN,GACf,OAAOqU,KAAKuhE,OAAOvoE,SAASrN,EAChC,EAGA4V,KAAM,WACF,OAAOvB,KAAKuhE,OAAOvhE,KAAKuhE,OAAO/vE,OAAS,EAC5C,EAGA8Q,QAAS,WACL,OAAQtC,KAAKuhE,OAAO/vE,MACxB,EAGAb,IAAK,SAAS8V,EAAIQ,GACd,OAAOjH,KAAKuhE,OAAO5wE,IAAI8V,EAAIQ,EAC/B,EAGAjD,OAAQ,SAASyC,EAAI48D,EAAUrjE,KAAK2G,SAChC,OAAO3G,KAAKuhE,OAAOv9D,OAAOyC,EAAI48D,EAClC,EAIA5B,OAAQ,WACJzhE,KAAKxO,OAAS,EACdwO,KAAKuhE,OAAS,GACdvhE,KAAK8iE,MAAS,CAAC,CACnB,EAIAL,cAAe,SAASvvC,EAAOyE,GAC3B,OAAI33B,KAAKy9C,SAASvqB,IACTA,EAAM12B,aAAY02B,EAAM12B,WAAawD,MACnCkzB,KAEXyE,EAAUA,EAAUv1B,GAAMu1B,GAAW,CAAC,GAC9Bn7B,WAAawD,MAIjB29C,EADA39C,KAAK29C,MAAMryD,UACH,IAAI0U,KAAK29C,MAAMzqB,EAAOyE,GAGtB33B,KAAK29C,MAAMzqB,EAAOyE,IAGnBinB,iBACX5+C,KAAK28C,QAAQ,UAAW38C,KAAM29C,EAAMiB,gBAAiBjnB,IAC9C,GAF4BgmB,GARnC,IAAIA,CAWR,EAGAskB,cAAe,SAASV,EAAQ5pC,GAE5B,IADA,IAAIk6B,EAAU,GACL/qD,EAAI,EAAGA,EAAIy6D,EAAO/vE,OAAQsV,IAAK,CACpC,IAAI62C,EAAQ39C,KAAK7U,IAAIo2E,EAAOz6D,IAC5B,GAAK62C,EAAL,CAEA,IAAIjsD,EAAQsO,KAAKuhE,OAAOtoE,QAAQ0kD,GAChC39C,KAAKuhE,OAAO/gE,OAAO9O,EAAO,GAC1BsO,KAAKxO,gBAIEwO,KAAK8iE,MAAMnlB,EAAMI,KACxB,IAAIzoB,EAAKt1B,KAAK+iE,QAAQplB,EAAMjiB,WAAYiiB,EAAMkB,aACpC,MAANvpB,UAAmBt1B,KAAK8iE,MAAMxtC,GAE7BqC,EAAQonB,SACTpnB,EAAQjmC,MAAQA,EAChBisD,EAAMhB,QAAQ,SAAUgB,EAAO39C,KAAM23B,IAGzCk6B,EAAQjgE,KAAK+rD,GACb39C,KAAK4iE,iBAAiBjlB,EAAOhmB,EAlBT,CAmBxB,CAEA,OADI4pC,EAAO/vE,OAAS,IAAMmmC,EAAQonB,eAAepnB,EAAQjmC,MAClDmgE,CACX,EAIApU,SAAU,SAASE,GACf,OAAOA,aAAiBE,EAC5B,EAGA6kB,cAAe,SAAS/kB,EAAOhmB,GAC3B33B,KAAK8iE,MAAMnlB,EAAMI,KAAOJ,EACxB,IAAIroB,EAAKt1B,KAAK+iE,QAAQplB,EAAMjiB,WAAYiiB,EAAMkB,aACpC,MAANvpB,IAAYt1B,KAAK8iE,MAAMxtC,GAAMqoB,GACjCA,EAAMn0C,GAAG,MAAOxJ,KAAKsjE,cAAetjE,KACxC,EAGA4iE,iBAAkB,SAASjlB,EAAOhmB,UACvB33B,KAAK8iE,MAAMnlB,EAAMI,KACxB,IAAIzoB,EAAKt1B,KAAK+iE,QAAQplB,EAAMjiB,WAAYiiB,EAAMkB,aACpC,MAANvpB,UAAmBt1B,KAAK8iE,MAAMxtC,GAC9Bt1B,OAAS29C,EAAMnhD,mBAAmBmhD,EAAMnhD,WAC5CmhD,EAAM/zC,IAAI,MAAO5J,KAAKsjE,cAAetjE,KACzC,EAMAsjE,cAAe,SAASn6D,EAAOw0C,EAAOnhD,EAAYm7B,GAC9C,GAAIgmB,EAAO,CACP,IAAe,QAAVx0C,GAA6B,WAAVA,IAAuB3M,IAAewD,KAAM,OACpE,GAAc,aAAVmJ,EAAsB,CACtB,IAAIk2C,EAASr/C,KAAK+iE,QAAQplB,EAAMgC,qBAAsBhC,EAAMkB,aACxDvpB,EAAKt1B,KAAK+iE,QAAQplB,EAAMjiB,WAAYiiB,EAAMkB,aAChC,MAAVQ,UAAuBr/C,KAAK8iE,MAAMzjB,GAC5B,MAAN/pB,IAAYt1B,KAAK8iE,MAAMxtC,GAAMqoB,EACrC,CACJ,CACA39C,KAAK28C,QAAQx7C,MAAMnB,KAAMpB,UAC7B,IAMJ,IAAI2kE,GAA+B,mBAAX93E,QAAyBA,OAAOkX,SACpD4gE,KACAjC,GAAWh2E,UAAUi4E,IAAcjC,GAAWh2E,UAAUkF,QAU5D,IA2DoBgzE,GA3DhBR,GAAqB,SAASxmE,EAAYinE,GAC1CzjE,KAAK0jE,YAAclnE,EACnBwD,KAAK2jE,MAAQF,EACbzjE,KAAK4jE,OAAS,CAClB,EAKIX,GAAkB,EAClBC,GAAgB,EAChBC,GAAsB,EAGtBI,KACAP,GAAmB13E,UAAUi4E,IAAc,WACvC,OAAOvjE,IACX,GAGJgjE,GAAmB13E,UAAUsX,KAAO,WAChC,GAAI5C,KAAK0jE,YAAa,CAGlB,GAAI1jE,KAAK4jE,OAAS5jE,KAAK0jE,YAAYlyE,OAAQ,CACvC,IAII7F,EAJAgyD,EAAQ39C,KAAK0jE,YAAY5B,GAAG9hE,KAAK4jE,QAKrC,GAJA5jE,KAAK4jE,SAID5jE,KAAK2jE,QAAUV,GACft3E,EAAQgyD,MACL,CACH,IAAIroB,EAAKt1B,KAAK0jE,YAAYX,QAAQplB,EAAMjiB,WAAYiiB,EAAMkB,aAEtDlzD,EADAqU,KAAK2jE,QAAUT,GACP5tC,EAEA,CAACA,EAAIqoB,EAErB,CACA,MAAO,CAAEhyD,MAAOA,EAAOkX,MAAM,EACjC,CAIA7C,KAAK0jE,iBAAc,CACvB,CAEA,MAAO,CAAE/3E,WAAO,EAAQkX,MAAM,EAClC,ErB/c4B,SAASghE,EAAOz8D,EAAMmpC,EAASqV,GACvD,GAAMrV,GAAS,SAAS/+C,EAAQm7C,GACxBvlC,EAAKulC,KAASk3B,EAAMv4E,UAAUqhD,GAxB1B,SAASvlC,EAAM5V,EAAQm7C,EAAQiZ,GAC3C,OAAQp0D,GACJ,KAAK,EAAG,OAAO,WACX,OAAO4V,EAAKulC,GAAQ3sC,KAAK4lD,GAC7B,EACA,KAAK,EAAG,OAAO,SAASj6D,GACpB,OAAOyb,EAAKulC,GAAQ3sC,KAAK4lD,GAAYj6D,EACzC,EACA,KAAK,EAAG,OAAO,SAAS8Q,EAAUwK,GAC9B,OAAOG,EAAKulC,GAAQ3sC,KAAK4lD,GAAYzN,GAAG17C,EAAUuD,MAAOiH,EAC7D,EACA,KAAK,EAAG,OAAO,SAASxK,EAAUqnE,EAAY78D,GAC1C,OAAOG,EAAKulC,GAAQ3sC,KAAK4lD,GAAYzN,GAAG17C,EAAUuD,MAAO8jE,EAAY78D,EACzE,EACA,QAAS,OAAO,WACZ,IAAIhG,EAAOjQ,MAAM1F,UAAUwP,MAAMtP,KAAKoT,WAEtC,OADAqC,EAAKgc,QAAQjd,KAAK4lD,IACXx+C,EAAKulC,GAAQxrC,MAAMiG,EAAMnG,EACpC,EAER,CAIoD8iE,CAAU38D,EAAM5V,EAAQm7C,EAAQiZ,GAChF,GACJ,CqB+dIoe,EAVgBR,GAFP,CAAElC,GALS,CAAE5+D,QAAS,EAAGI,OAAQ,GAKA,WAGxB,GAIG,CACjBA,OAAM,GACNJ,QAAO,IALG8gE,GAAO,GACLA,GAAO,IAa3BlC,GAAWzhD,OAAS,GC5iBb,MAoBMokD,GAAW,CAEpB5lB,MAAO,SAAS53C,GAEZ,OAAO,WAEH,IAAIxF,EAAOjQ,MAAM8W,KAAKlJ,WAClBoR,EAAI/O,EAAKzP,OACT6sD,EAAQruC,EAAI,GAAK/O,EAAK,IAAM,GAC5BoT,EAAMrE,EAAI,GAAK/O,EAAK+O,EAAI,IAAM,CAAC,EAkBnC,OAhBKhf,MAAMC,QAAQotD,KAEXhqC,aAAe8xC,GACf9H,EAAQp9C,EACDo9C,aAAiB8H,KACpBllD,EAAKzP,OAAS,GACdyP,EAAKV,MAET89C,EAAQp9C,IAIZoT,aAAe8xC,KACf9xC,EAAM,CAAC,GAGJ5N,EAAGjb,KAAKwU,KAAMq+C,EAAOhqC,EAChC,CACJ,GC5CE6vD,GAAa5C,GAAWzhD,OAAO,CAEjCs+B,WAAY,SAASojB,EAAQltD,GAGrBA,EAAI8vD,cACJnkE,KAAKmkE,cAAgB9vD,EAAI8vD,cAGzBnkE,KAAKmkE,cAAiC,oBAAV7X,OAAyB,GAASA,MAAO,UAAYA,MAAMC,OAAS,KAKpGvsD,KAAKinD,MAAQ5yC,EAAI4yC,KACrB,EAEAtJ,MAAO,SAASzqB,EAAO7e,GAEnB,MACM1J,EADa0J,EAAI7X,WACM2nE,eACvB,KAAEhyE,GAAS+gC,EAGXkxC,EAAa,GAAez5D,EAAWxY,EAAM,KACnD,IAAKiyE,EACD,MAAM,IAAIp7D,MAAM,yDAAyD7W,4DAG7E,OAAO,IAAIiyE,EAAWlxC,EAAO7e,EACjC,EAEAquD,cAAe,SAAS/kB,EAAOhmB,GAC3B2pC,GAAWh2E,UAAUo3E,cAAcvhE,MAAMnB,KAAMpB,WAG1C+4B,EAAQ0sC,KAAQ1mB,EAAMsJ,QACvBtJ,EAAMsJ,MAAQjnD,KAAKinD,MAE3B,EAEA2b,iBAAkB,SAASjlB,EAAOhmB,GAC9B2pC,GAAWh2E,UAAUs3E,iBAAiBzhE,MAAMnB,KAAMpB,WAG7C+4B,EAAQ0sC,KAAO1mB,EAAMsJ,QAAUjnD,KAAKinD,QACrCtJ,EAAMsJ,MAAQ,KAEtB,EAGAua,WAAY,SAAS7jB,GAEjB,OAAOA,EAAMxyD,IAAI,MAAQ,CAC7B,IAISm5E,GAAQzmB,GAAMh+B,OAAO,CAE9Bs+B,WAAY,SAASjrB,EAAO7e,GAOxB,IAAIgqC,EAAQ,IAAI6lB,GAAW,GAAI,CAC3BvmB,OANJtpC,EAAMA,GAAO,CAAC,GAMCkwD,UACXJ,cAAe9vD,EAAI8vD,cACnBld,MAAOjnD,OAEX69C,GAAMvyD,UAAU8H,IAAI5H,KAAKwU,KAAM,QAASq+C,GAIxCA,EAAM70C,GAAG,MAAOxJ,KAAK28C,QAAS38C,MAI9BA,KAAKwJ,GAAG,WAAYxJ,KAAKwkE,eAAgBxkE,MAWzCA,KAAKykE,KAAO,CAAC,EAGbzkE,KAAK0kE,IAAM,CAAC,EAIZ1kE,KAAK2kE,OAAS,CAAC,EAIf3kE,KAAK4kE,OAAS,CAAC,EAEf5kE,KAAK6kE,SAAW,CAAC,EAEjBxmB,EAAM70C,GAAG,MAAOxJ,KAAK8kE,kBAAmB9kE,MACxCq+C,EAAM70C,GAAG,SAAUxJ,KAAK+kE,qBAAsB/kE,MAC9Cq+C,EAAM70C,GAAG,QAASxJ,KAAKglE,oBAAqBhlE,MAC5Cq+C,EAAM70C,GAAG,gBAAiBxJ,KAAKilE,2BAA4BjlE,MAC3Dq+C,EAAM70C,GAAG,gBAAiBxJ,KAAKklE,2BAA4BllE,MAC3Dq+C,EAAM70C,GAAG,SAAUxJ,KAAKmlE,YAAanlE,KACzC,EAEAwkE,eAAgB,WAEZxkE,KAAK7U,IAAI,SAASoS,MACtB,EAEAunE,kBAAmB,SAASvmB,GAExB,GAAIA,EAAKC,SAAU,CACfx+C,KAAK4kE,OAAOrmB,EAAKjpB,KAAM,EACvB,IAAI,OAAE3iC,EAAM,OAAEuS,GAAWq5C,EAAK7iB,WAC1B/oC,EAAO2iC,MACNt1B,KAAKykE,KAAK9xE,EAAO2iC,MAAQt1B,KAAKykE,KAAK9xE,EAAO2iC,IAAM,CAAC,IAAIipB,EAAKjpB,KAAM,GAEjEpwB,EAAOowB,MACNt1B,KAAK0kE,IAAIx/D,EAAOowB,MAAQt1B,KAAK0kE,IAAIx/D,EAAOowB,IAAM,CAAC,IAAIipB,EAAKjpB,KAAM,EAEvE,MACIt1B,KAAK2kE,OAAOpmB,EAAKjpB,KAAM,CAE/B,EAEAyvC,qBAAsB,SAASxmB,GAE3B,GAAIA,EAAKC,SAAU,QACRx+C,KAAK4kE,OAAOrmB,EAAKjpB,IACxB,IAAI,OAAE3iC,EAAM,OAAEuS,GAAWq5C,EAAK7iB,WAC1B/oC,EAAO2iC,IAAMt1B,KAAKykE,KAAK9xE,EAAO2iC,KAAOt1B,KAAKykE,KAAK9xE,EAAO2iC,IAAIipB,EAAKjpB,YACxDt1B,KAAKykE,KAAK9xE,EAAO2iC,IAAIipB,EAAKjpB,IAEjCpwB,EAAOowB,IAAMt1B,KAAK0kE,IAAIx/D,EAAOowB,KAAOt1B,KAAK0kE,IAAIx/D,EAAOowB,IAAIipB,EAAKjpB,YACtDt1B,KAAK0kE,IAAIx/D,EAAOowB,IAAIipB,EAAKjpB,GAExC,aACWt1B,KAAK2kE,OAAOpmB,EAAKjpB,GAEhC,EAEA0vC,oBAAqB,SAAS3mB,GAG1BA,EAAQA,EAAMkjB,OAEdvhE,KAAKykE,KAAO,CAAC,EACbzkE,KAAK0kE,IAAM,CAAC,EACZ1kE,KAAK2kE,OAAS,CAAC,EACf3kE,KAAK4kE,OAAS,CAAC,EAEfvmB,EAAM1mD,QAAQqI,KAAK8kE,kBAAmB9kE,KAC1C,EAEAilE,2BAA4B,SAAS7d,GAEjC,IAAIge,EAAahe,EAAK1H,SAAS,UAC3B0lB,EAAW9vC,IAAMt1B,KAAKykE,KAAKW,EAAW9vC,YAC/Bt1B,KAAKykE,KAAKW,EAAW9vC,IAAI8xB,EAAK9xB,IAEzC,IAAI3iC,EAASy0D,EAAK1rB,WAAW/oC,OACzBA,EAAO2iC,MACNt1B,KAAKykE,KAAK9xE,EAAO2iC,MAAQt1B,KAAKykE,KAAK9xE,EAAO2iC,IAAM,CAAC,IAAI8xB,EAAK9xB,KAAM,EAEzE,EAEA4vC,2BAA4B,SAAS9d,GAEjC,IAAIie,EAAaje,EAAK1H,SAAS,UAC3B2lB,EAAW/vC,IAAMt1B,KAAK0kE,IAAIW,EAAW/vC,YAC9Bt1B,KAAK0kE,IAAIW,EAAW/vC,IAAI8xB,EAAK9xB,IAExC,IAAIpwB,EAASkiD,EAAKj8D,IAAI,UAClB+Z,EAAOowB,MACNt1B,KAAK0kE,IAAIx/D,EAAOowB,MAAQt1B,KAAK0kE,IAAIx/D,EAAOowB,IAAM,CAAC,IAAI8xB,EAAK9xB,KAAM,EAEvE,EAIAgwC,iBAAkB,SAASx8D,GAEvB,OAAQ9I,KAAKykE,MAAQzkE,KAAKykE,KAAK37D,IAAU,CAAC,CAC9C,EAIAy8D,gBAAiB,SAASz8D,GAEtB,OAAQ9I,KAAK0kE,KAAO1kE,KAAK0kE,IAAI57D,IAAU,CAAC,CAC5C,EAEA0J,OAAQ,SAAS6B,EAAM,CAAC,GAIpB,IAAIi9B,EAAOuM,GAAMvyD,UAAUknB,OAAOrR,MAAMnB,KAAMpB,WAE9C,OADA0yC,EAAK+M,MAAQr+C,KAAK7U,IAAI,SAASqnB,OAAO6B,EAAImxD,gBACnCl0B,CACX,EAEAm0B,SAAU,SAASn0B,EAAMj9B,GAErB,IAAKi9B,EAAK+M,MAEN,MAAM,IAAIr1C,MAAM,wCAGpB,OAAOhJ,KAAK5M,IAAIk+C,EAAMj9B,EAC1B,EAEAjhB,IAAK,SAAStI,EAAK0T,EAAK6V,GAEpB,IAAI6e,EAiBJ,MAdmB,iBAARpoC,GACPooC,EAAQpoC,EACRupB,EAAM7V,IAEL00B,EAAQ,CAAC,GAAGpoC,GAAO0T,EAIpB00B,EAAM3nC,eAAe,WACrByU,KAAK0lE,WAAWxyC,EAAMmrB,MAAOhqC,GAC7B6e,EAAQ,GAAUA,EAAO,UAItB2qB,GAAMvyD,UAAU8H,IAAI5H,KAAKwU,KAAMkzB,EAAO7e,EACjD,EAEAnU,MAAO,SAASmU,GAEZA,EAAM,GAAY,CAAC,EAAGA,EAAK,CAAEnU,OAAO,IAEpC,IAAI1D,EAAawD,KAAK7U,IAAI,SAE1B,GAA0B,IAAtBqR,EAAWhL,OAAc,OAAOwO,KAEpCA,KAAKsnD,WAAW,QAASjzC,GAGzB,IAAIgqC,EAAQ7hD,EAAWsG,QAAO,SAASy7C,GACnC,OAAOA,EAAKC,SAAW,EAAI,CAC/B,IAEA,GAMIH,EAAM7S,QAAQjnC,OAAO8P,SAEhBgqC,EAAM7sD,OAAS,GAIxB,OAFAwO,KAAK4nD,UAAU,SAER5nD,IACX,EAEA2lE,aAAc,SAASpnB,GAEnB,IAAIrrB,EAOJ,GALIA,EADAqrB,aAAgBV,GACRU,EAAK7iB,WAEL6iB,GAGP,GAAcrrB,EAAM/gC,MACrB,MAAM,IAAIuqD,UAAU,0CAGxB,OAAO6B,CACX,EAEA+J,UAAW,WAEP,IAAIsd,EAAY5lE,KAAK7U,IAAI,SAASwb,QAClC,OAAOi/D,GAAaA,EAAUz6E,IAAI,MAAa,CACnD,EAEAg9D,UAAW,WAEP,IAAI0d,EAAW7lE,KAAK7U,IAAI,SAASoW,OACjC,OAAOskE,GAAYA,EAAS16E,IAAI,MAAa,CACjD,EAEAqgE,QAAS,SAASjN,EAAMlqC,GAEpB,OAAIrjB,MAAMC,QAAQstD,GAEPv+C,KAAK8lE,SAASvnB,EAAMlqC,IAG3BkqC,aAAgBV,GAEXU,EAAKvnD,IAAI,MACVunD,EAAKnrD,IAAI,IAAK4M,KAAKmoD,YAAc,QAGnB11D,IAAX8rD,EAAKhzB,IAEZgzB,EAAKhzB,EAAIvrB,KAAKmoD,YAAc,GAGhCnoD,KAAK7U,IAAI,SAASyP,IAAIoF,KAAK2lE,aAAapnB,EAAMlqC,GAAMA,GAAO,CAAC,GAErDrU,KACX,EAEA8lE,SAAU,SAASznB,EAAOhqC,GAEtB,OAAqB,IAAjBgqC,EAAM7sD,SAEV6sD,EAAQ,GAAiBA,GACzBhqC,EAAI0xD,YAAc1xD,EAAIupB,SAAWygB,EAAM7sD,OAAS,EAEhDwO,KAAKsnD,WAAW,MAAOjzC,GACvBgqC,EAAM1mD,SAAQ,SAAS4mD,GACnBv+C,KAAKwrD,QAAQjN,EAAMlqC,GACnBA,EAAIupB,UACR,GAAG59B,MACHA,KAAK4nD,UAAU,MAAOvzC,IAVSrU,IAanC,EAKA0lE,WAAY,SAASrnB,EAAOhqC,GAExB,IAAI2xD,EAAgB,GAAa3nB,GAAO1tD,KAAI,SAAS4tD,GACjD,OAAOv+C,KAAK2lE,aAAapnB,EAAMlqC,EACnC,GAAGrU,MAGH,OAFAA,KAAK7U,IAAI,SAASu2E,MAAMsE,EAAe3xD,GAEhCrU,IACX,EAEAimE,YAAa,SAAS5nB,EAAOhqC,GASzB,OAPIgqC,EAAM7sD,SAENwO,KAAKsnD,WAAW,UAChB,GAAYjJ,EAAO,SAAUhqC,GAC7BrU,KAAK4nD,UAAU,WAGZ5nD,IACX,EAEAmlE,YAAa,SAAS5mB,EAAM/hD,EAAYm7B,IAEpCA,EAAUA,GAAW,CAAC,GAETz3B,QAILy3B,EAAQuuC,gBAERlmE,KAAKkmE,gBAAgB3nB,EAAM5mB,GAI3B33B,KAAKmmE,YAAY5nB,EAAM5mB,IAO/B33B,KAAK7U,IAAI,SAASoZ,OAAOg6C,EAAM,CAAEQ,QAAQ,GAC7C,EAEAqnB,mBAAoB,SAASxK,EAAYG,EAAY1nD,EAAM,CAAC,GAExD,MAAMy0C,EAAY,kBAClB9oD,KAAKsnD,WAAWwB,GAGhB,MAAM31B,EAAWyoC,EAAWjU,mBAC5BoU,EAAWpd,MAAMxrB,EAAU,IAAK9e,EAAKm0C,UAAU,IAE/CxoD,KAAK4nD,UAAUkB,EACnB,EAEAud,2BAA4B,SAASzK,EAAYG,EAAY1nD,EAAM,CAAC,GAEhE,MAAMy0C,EAAY,2BAClB9oD,KAAKsnD,WAAWwB,GAGO9oD,KAAKknD,kBAAkB0U,EAAYvnD,GAC3C1c,SAASyvD,IAEhBA,EAAKyU,kBAAoBD,GACzBxU,EAAK/7D,KAAK,CAAC,SAAU,MAAO0wE,EAAWzmC,GAAIjhB,GAG3C+yC,EAAK4U,kBAAoBJ,GACzBxU,EAAK/7D,KAAK,CAAC,SAAU,MAAO0wE,EAAWzmC,GAAIjhB,EAC/C,IAGJrU,KAAK4nD,UAAUkB,EACnB,EAGAE,QAAS,SAAS1zB,GAEd,OAAOt1B,KAAK7U,IAAI,SAASA,IAAImqC,EACjC,EAEAgxC,SAAU,WAEN,OAAOtmE,KAAK7U,IAAI,SAASuX,SAC7B,EAEA6jE,YAAa,WAET,OAAOvmE,KAAK7U,IAAI,SAASuX,UAAU3O,QAAOwqD,GAAQA,EAAKoN,aAC3D,EAEA6a,SAAU,WAEN,OAAOxmE,KAAK7U,IAAI,SAASuX,UAAU3O,QAAOwqD,GAAQA,EAAKC,UAC3D,EAEAioB,aAAc,WAEV,OAAOzmE,KAAK7U,IAAI,SAASwb,OAC7B,EAEA+/D,YAAa,WAET,OAAO1mE,KAAK7U,IAAI,SAASoW,MAC7B,EAGA2lD,kBAAmB,SAASvJ,EAAOtpC,GAI/B,IAAIsyD,GAFJtyD,EAAMA,GAAO,CAAC,GAEKsyD,SACfxf,EAAU9yC,EAAI8yC,QACdE,EAAWhzC,EAAIgzC,cACF50D,IAAZ00D,QAAwC10D,IAAb40D,IAC5BF,EAAUE,GAAW,GAIzB,IAAIuf,EAAQ,GAGRC,EAAQ,CAAC,EASb,SAASC,EAAa7f,EAAOtJ,GAczB,GAbA,GAAWsJ,EAAMqe,iBAAiB3nB,EAAMroB,IAAK,SAASwqB,EAAGinB,GAIrD,IAAIF,EAAME,GAAV,CACA,IAAI3f,EAAOH,EAAM+B,QAAQ+d,GACzBH,EAAMh1E,KAAKw1D,GACXyf,EAAME,IAAQ,EACVJ,IACIxf,GAAS6f,EAAY/f,EAAOG,GAC5BC,GAAUyf,EAAa7f,EAAOG,GANf,CAQ3B,EAAEr3D,KAAKk3D,IACH0f,GAAYhpB,EAAMa,SAAU,CAC5B,IAAIyoB,EAAUtpB,EAAMqe,gBAChBiL,GAAWA,EAAQzoB,WACdqoB,EAAMI,EAAQ3xC,MACfsxC,EAAMh1E,KAAKq1E,GACXH,EAAa7f,EAAOggB,IAGhC,CACJ,CAEA,SAASD,EAAY/f,EAAOtJ,GAcxB,GAbA,GAAWsJ,EAAMse,gBAAgB5nB,EAAMroB,IAAK,SAASwqB,EAAGinB,GAIpD,IAAIF,EAAME,GAAV,CACA,IAAI3f,EAAOH,EAAM+B,QAAQ+d,GACzBH,EAAMh1E,KAAKw1D,GACXyf,EAAME,IAAQ,EACVJ,IACIxf,GAAS6f,EAAY/f,EAAOG,GAC5BC,GAAUyf,EAAa7f,EAAOG,GANf,CAQ3B,EAAEr3D,KAAKk3D,IACH0f,GAAYhpB,EAAMa,SAAU,CAC5B,IAAI0oB,EAASvpB,EAAMke,gBACfqL,GAAUA,EAAO1oB,WACZqoB,EAAMK,EAAO5xC,MACdsxC,EAAMh1E,KAAKs1E,GACXF,EAAY/f,EAAOigB,IAG/B,CACJ,CAGA,GA1DI7f,GACAyf,EAAa9mE,KAAM29C,GAEnBwJ,GACA6f,EAAYhnE,KAAM29C,GAsDlBtpC,EAAI0zC,KAAM,CAEV,IAAIL,EAAgB/J,EAAMgK,iBAAiB,CAAEI,MAAM,IAG/Cof,EAAmB,CAAC,EACxBzf,EAAc/vD,SAAQ,SAAS4mD,GACvBA,EAAKoN,cACLwb,EAAiB5oB,EAAKjpB,KAAM,EAEpC,IAEAoyB,EAAc/vD,SAAQ,SAAS4mD,GACvBA,EAAKC,WACL6I,GACA,GAAWrnD,KAAKslE,iBAAiB/mB,EAAKjpB,IAAK,SAASrJ,EAAQ86C,GACxD,IAAKF,EAAME,GAAO,CACd,IAAIK,EAAWpnE,KAAKgpD,QAAQ+d,IACxB,OAAEp0E,EAAM,OAAEuS,GAAWkiE,EAAS1rC,WAC9B8gC,EAAW7pE,EAAO2iC,GAClBmnC,EAAWv3D,EAAOowB,GAGtB,IAAKjhB,EAAIgzD,iBACD7K,GAAY2K,EAAiB3K,IAC7BC,GAAY0K,EAAiB1K,GACjC,OAGJmK,EAAMh1E,KAAKoO,KAAKgpD,QAAQ+d,IACxBF,EAAME,IAAQ,CAClB,CACJ,EAAEh3E,KAAKiQ,OAEPmnD,GACA,GAAWnnD,KAAKulE,gBAAgBhnB,EAAKjpB,IAAK,SAASrJ,EAAQ86C,GACvD,IAAKF,EAAME,GAAO,CACd,IAAIK,EAAWpnE,KAAKgpD,QAAQ+d,IACxB,OAAEp0E,EAAM,OAAEuS,GAAWkiE,EAAS1rC,WAC9B8gC,EAAW7pE,EAAO2iC,GAClBmnC,EAAWv3D,EAAOowB,GAGtB,IAAKjhB,EAAIgzD,iBACD7K,GAAY2K,EAAiB3K,IAC7BC,GAAY0K,EAAiB1K,GACjC,OAGJmK,EAAMh1E,KAAKoO,KAAKgpD,QAAQ+d,IACxBF,EAAME,IAAQ,CAClB,CACJ,EAAEh3E,KAAKiQ,OAEf,GAAGA,KACP,CAEA,OAAO4mE,CACX,EAEAU,aAAc,SAAS3pB,EAAOtpC,GAE1BA,IAAQA,EAAM,CAAC,GAEf,IAAI8yC,EAAU9yC,EAAI8yC,QACdE,EAAWhzC,EAAIgzC,cACH50D,IAAZ00D,QAAsC10D,IAAb40D,IACzBF,EAAUE,GAAW,GAGzB,IAAIkgB,EAAYvnE,KAAKknD,kBAAkBvJ,EAAOtpC,GAAKrQ,OAAO,SAAS2kC,EAAKye,GAEpE,IAAI,OAAEz0D,EAAM,OAAEuS,GAAWkiD,EAAK1rB,WAC1BghC,EAAOtV,EAAKmV,QAAQloD,GAGxB,GAAI8yC,GAAW,GAASx0D,EAAQ,QAAUg2C,EAAIh2C,EAAO2iC,IAAK,CAEtD,IAAIqnC,EAAgB38D,KAAKgpD,QAAQr2D,EAAO2iC,IACpCqnC,EAAchR,eACV+Q,KAASC,GAAiBA,IAAkBhf,GAAWtpC,EAAI0zC,MAAS4U,EAAc9T,aAAalL,MAC/FhV,EAAIh2C,EAAO2iC,IAAMqnC,GAG7B,CAGA,GAAItV,GAAY,GAASniD,EAAQ,QAAUyjC,EAAIzjC,EAAOowB,IAAK,CAEvD,IAAIsnC,EAAgB58D,KAAKgpD,QAAQ9jD,EAAOowB,IACpCsnC,EAAcjR,eACV+Q,KAASE,GAAiBA,IAAkBjf,GAAWtpC,EAAI0zC,MAAS6U,EAAc/T,aAAalL,MAC/FhV,EAAIzjC,EAAOowB,IAAMsnC,GAG7B,CAEA,OAAOj0B,CACX,EAAE54C,KAAKiQ,MAAO,CAAC,GAEf,GAAI29C,EAAMa,SAAU,CAChB,GAAI2I,EAAS,CACT,IAAIyU,EAAaje,EAAMke,gBACnBD,GAAcA,EAAWjQ,cAAgB4b,EAAU3L,EAAWtmC,MAC9DiyC,EAAU3L,EAAWtmC,IAAMsmC,EAEnC,CACA,GAAIvU,EAAU,CACV,IAAI0U,EAAape,EAAMqe,gBACnBD,GAAcA,EAAWpQ,cAAgB4b,EAAUxL,EAAWzmC,MAC9DiyC,EAAUxL,EAAWzmC,IAAMymC,EAEnC,CACJ,CAEA,OAAO,GAAawL,EACxB,EAEAjL,kBAAmB,WAEf,IAAIkL,EAAiBx2E,MAAM8W,KAAKlJ,WAAWjO,KAAI,SAAS4tD,GAKpD,IAHA,IAAI2K,EAAY,GACZH,EAAWxK,EAAKpzD,IAAI,UAEjB49D,GAEHG,EAAUt3D,KAAKm3D,GACfA,EAAW/oD,KAAKgpD,QAAQD,GAAU59D,IAAI,UAG1C,OAAO+9D,CAEX,GAAGlpD,MAEHwnE,EAAiBA,EAAejqE,MAAK,SAAS5B,EAAGC,GAC7C,OAAOD,EAAEnK,OAASoK,EAAEpK,MACxB,IAEA,IAAIi2E,EAAiB,GAAaD,EAAeh8B,SAASpjC,MAAK,SAAS60D,GACpE,OAAOuK,EAAe5e,OAAM,SAAS8e,GACjC,OAAOA,EAAc1uE,SAASikE,EAClC,GACJ,IAEA,OAAOj9D,KAAKgpD,QAAQye,EACxB,EAKAE,cAAe,SAASpQ,EAASljD,GAE7BA,EAAMA,GAAO,CAAC,EACd,IAAIs0B,EAAM,GAOV,OALA3oC,KAAK22C,OAAO4gB,GAAS,SAASlvD,GACtBA,IAAOkvD,GACP5uB,EAAI/2C,KAAKyW,EAEjB,GAAG,GAAY,CAAC,EAAGgM,EAAK,CAAEgzC,UAAU,KAC7B1e,CACX,EAEAyV,WAAYA,GAIZwpB,cAAe,SAASvpB,EAAOhqC,GAE3B,IAAIwzD,EAAW7nE,KAAK8nE,YAAYzpB,EAAOhqC,GACvC,OAAOrU,KAAKo+C,WAAWypB,EAC3B,EAQAC,YAAa,SAASzpB,EAAOhqC,GAEzBA,EAAMA,GAAO,CAAC,EAEd,IAAIwzD,EAAW,GAEXE,EAAU,CAAC,EACX9/D,EAAW,GACX2+D,EAAQ,GA0DZ,OAxDA,GAAavoB,GAAO1mD,SAAQ,SAAS4mD,GAC5BwpB,EAAQxpB,EAAKjpB,MACduyC,EAASj2E,KAAK2sD,GACdwpB,EAAQxpB,EAAKjpB,IAAMipB,EACfA,EAAKC,SACLooB,EAAMh1E,KAAK2sD,GAEXt2C,EAASrW,KAAK2sD,IAIlBlqC,EAAI0zC,MACSxJ,EAAKoJ,iBAAiB,CAAEI,MAAM,IACpCpwD,SAAQ,SAASgnD,GACfopB,EAAQppB,EAAMrpB,MACfuyC,EAASj2E,KAAK+sD,GACdopB,EAAQppB,EAAMrpB,IAAMqpB,EAChBA,EAAMH,SACNooB,EAAMh1E,KAAK+sD,GAEX12C,EAASrW,KAAK+sD,GAG1B,GAER,IAEAioB,EAAMjvE,SAAQ,SAASyvD,GAEnB,IAAI,OAAEz0D,EAAM,OAAEuS,GAAWkiD,EAAK1rB,WAC9B,GAAI/oC,EAAO2iC,KAAOyyC,EAAQp1E,EAAO2iC,IAAK,CAClC,IAAIqnC,EAAgB38D,KAAKgpD,QAAQr2D,EAAO2iC,IACxCuyC,EAASj2E,KAAK+qE,GACdoL,EAAQpL,EAAcrnC,IAAMqnC,EAC5B10D,EAASrW,KAAK+qE,EAClB,CACA,GAAIz3D,EAAOowB,KAAOyyC,EAAQ7iE,EAAOowB,IAAK,CAClC,IAAIsnC,EAAgB58D,KAAKgpD,QAAQ9jD,EAAOowB,IACxCuyC,EAASj2E,KAAKoO,KAAKgpD,QAAQ9jD,EAAOowB,KAClCyyC,EAAQnL,EAActnC,IAAMsnC,EAC5B30D,EAASrW,KAAKgrE,EAClB,CACJ,GAAG58D,MAEHiI,EAAStQ,SAAQ,SAAS4/D,GAEVv3D,KAAKknD,kBAAkBqQ,EAASljD,GACtC1c,SAAQ,SAASyvD,GACnB,IAAI,OAAEz0D,EAAM,OAAEuS,GAAWkiD,EAAK1rB,YACzBqsC,EAAQ3gB,EAAK9xB,KAAO3iC,EAAO2iC,IAAMyyC,EAAQp1E,EAAO2iC,KAAOpwB,EAAOowB,IAAMyyC,EAAQ7iE,EAAOowB,MACpFuyC,EAASj2E,KAAKw1D,GACd2gB,EAAQ3gB,EAAK9xB,IAAM8xB,EAE3B,GACJ,GAAGpnD,MAEI6nE,CACX,EAKAG,gBAAiB,SAASzQ,EAASljD,GAE/BA,EAAMA,GAAO,CAAC,EACd,IAAIs0B,EAAM,GAOV,OALA3oC,KAAK22C,OAAO4gB,GAAS,SAASlvD,GACtBA,IAAOkvD,GACP5uB,EAAI/2C,KAAKyW,EAEjB,GAAG,GAAY,CAAC,EAAGgM,EAAK,CAAE8yC,SAAS,KAC5Bxe,CACX,EAQAgO,OAAQ,SAAS4gB,EAAS96D,EAAU4X,IAEhCA,EAAMA,GAAO,CAAC,GACN2zC,aACJhoD,KAAKioE,IAAI1Q,EAAS96D,EAAU4X,GAE5BrU,KAAKkoE,IAAI3Q,EAAS96D,EAAU4X,EAEpC,EAWA4zD,IAAK,SAAS1Q,EAAS96D,EAAU4X,EAAM,CAAC,GAEpC,MAAMwoD,EAAU,CAAC,EACXrtD,EAAW,CAAC,EACZ85C,EAAQ,GAKd,IAHAA,EAAM13D,KAAK2lE,GACX/nD,EAAS+nD,EAAQjiC,IAAM,EAEhBg0B,EAAM93D,OAAS,GAAG,CACrB,IAAIoR,EAAO0mD,EAAM9d,QACjB,GAAIqxB,EAAQj6D,EAAK0yB,IAAK,SAEtB,GADAunC,EAAQj6D,EAAK0yB,KAAM,GACkC,IAAjD74B,EAASjR,KAAKwU,KAAM4C,EAAM4M,EAAS5M,EAAK0yB,KAAgB,SAC5D,MAAMiyC,EAAYvnE,KAAKsnE,aAAa1kE,EAAMyR,GAC1C,IAAK,IAAIvN,EAAI,EAAGkJ,EAAIu3D,EAAU/1E,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAC9C,MAAMqhE,EAAWZ,EAAUzgE,GAC3B0I,EAAS24D,EAAS7yC,IAAM9lB,EAAS5M,EAAK0yB,IAAM,EAC5Cg0B,EAAM13D,KAAKu2E,EACf,CACJ,CACJ,EAOAD,IAAK,SAAS3Q,EAAS96D,EAAU4X,EAAM,CAAC,GAEpC,MAAMwoD,EAAU,CAAC,EACXrtD,EAAW,CAAC,EACZ85C,EAAQ,GAKd,IAHAA,EAAM13D,KAAK2lE,GACX/nD,EAAS+nD,EAAQjiC,IAAM,EAEhBg0B,EAAM93D,OAAS,GAAG,CACrB,MAAMoR,EAAO0mD,EAAM/oD,MACnB,GAAIs8D,EAAQj6D,EAAK0yB,IAAK,SAEtB,GADAunC,EAAQj6D,EAAK0yB,KAAM,GACkC,IAAjD74B,EAASjR,KAAKwU,KAAM4C,EAAM4M,EAAS5M,EAAK0yB,KAAgB,SAC5D,MAAMiyC,EAAYvnE,KAAKsnE,aAAa1kE,EAAMyR,GACpC/Z,EAAYgvD,EAAM93D,OACxB,IAAK,IAAIsV,EAAI,EAAGkJ,EAAIu3D,EAAU/1E,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAC9C,MAAMqhE,EAAWZ,EAAUzgE,GAC3B0I,EAAS24D,EAAS7yC,IAAM9lB,EAAS5M,EAAK0yB,IAAM,EAC5Cg0B,EAAM9oD,OAAOlG,EAAW,EAAG6tE,EAC/B,CACJ,CACJ,EAGAC,WAAY,WAER,IAAI3sE,EAAU,GAMd,OALA,GAAWuE,KAAK2kE,OAAQ,SAAS14C,EAAQnjB,GAChC9I,KAAK0kE,IAAI57D,KAAS,GAAa9I,KAAK0kE,IAAI57D,KACzCrN,EAAQ7J,KAAKoO,KAAKgpD,QAAQlgD,GAElC,EAAE/Y,KAAKiQ,OACAvE,CACX,EAGA4sE,SAAU,WAEN,IAAIC,EAAQ,GAMZ,OALA,GAAWtoE,KAAK2kE,OAAQ,SAAS14C,EAAQnjB,GAChC9I,KAAKykE,KAAK37D,KAAS,GAAa9I,KAAKykE,KAAK37D,KAC3Cw/D,EAAM12E,KAAKoO,KAAKgpD,QAAQlgD,GAEhC,EAAE/Y,KAAKiQ,OACAsoE,CACX,EAGAC,SAAU,SAAShR,GAEf,OAAQv3D,KAAK0kE,IAAInN,EAAQjiC,KAAO,GAAat1B,KAAK0kE,IAAInN,EAAQjiC,IAClE,EAGAkzC,OAAQ,SAASjR,GAEb,OAAQv3D,KAAKykE,KAAKlN,EAAQjiC,KAAO,GAAat1B,KAAKykE,KAAKlN,EAAQjiC,IACpE,EAGAmzC,YAAa,SAASC,EAAUC,GAE5B,IAAIF,GAAc,EAOlB,OANAzoE,KAAK22C,OAAO+xB,GAAU,SAASnR,GAC3B,GAAIA,IAAYoR,GAAYpR,IAAYmR,EAEpC,OADAD,GAAc,GACP,CAEf,GAAG,CAAEphB,UAAU,IACRohB,CACX,EAGAG,cAAe,SAASF,EAAUC,GAE9B,IAAIC,GAAgB,EAOpB,OANA5oE,KAAK22C,OAAO+xB,GAAU,SAASnR,GAC3B,GAAIA,IAAYoR,GAAYpR,IAAYmR,EAEpC,OADAE,GAAgB,GACT,CAEf,GAAG,CAAEzhB,SAAS,IACPyhB,CACX,EAOAC,WAAY,SAASH,EAAUC,EAAUt0D,GAIrC,IAAI8yC,GAFJ9yC,EAAMA,GAAO,CAAC,GAEI8yC,QACdE,EAAWhzC,EAAIgzC,cACF50D,IAAZ00D,QAAwC10D,IAAb40D,IAC5BF,EAAUE,GAAW,GAGzB,IAAIwhB,GAAa,EAmBjB,OAjBA7oE,KAAKknD,kBAAkBwhB,EAAUr0D,GAAK1c,SAAQ,SAASyvD,GAEnD,IAAI,OAAEz0D,EAAM,OAAEuS,GAAWkiD,EAAK1rB,WAG9B,OAAIyrB,GAAW,GAASx0D,EAAQ,OAAUA,EAAO2iC,KAAOqzC,EAASrzC,IAM7D+xB,GAAY,GAASniD,EAAQ,OAAUA,EAAOowB,KAAOqzC,EAASrzC,IAL9DuzC,GAAa,GACN,QAIX,CAIJ,IAEOA,CACX,EAGA3C,gBAAiB,SAASvoB,EAAOtpC,GAE7BrU,KAAKknD,kBAAkBvJ,GAAOhmD,SAAQ,SAASyvD,GAE3CA,EAAKh0D,IAAKg0D,EAAK1rB,WAAW/oC,OAAO2iC,KAAOqoB,EAAMroB,GAAK,SAAW,SAAW,CAAEnnB,EAAG,EAAGH,EAAG,GAAKqG,EAC7F,GACJ,EAGA8xD,YAAa,SAASxoB,EAAOtpC,GAEzB,GAAYrU,KAAKknD,kBAAkBvJ,GAAQ,SAAUtpC,EACzD,EAIAy0D,oBAAqB,SAAS93D,EAAOqD,GACjC,OAAOrU,KAAK+oE,eAAe/oE,KAAKumE,cAAev1D,EAAOqD,EAC1D,EAEA20D,iBAAkB,SAASh4D,EAAOqD,GAC9B,OAAOrU,KAAK+oE,eAAe/oE,KAAKwmE,WAAYx1D,EAAOqD,EACvD,EAEA40D,iBAAkB,SAASj4D,EAAOqD,GAC9B,OAAOrU,KAAK+oE,eAAe/oE,KAAKsmE,WAAYt1D,EAAOqD,EACvD,EAEA00D,eAAgB,SAAS1qB,EAAOrtC,EAAOqD,EAAM,CAAC,GAC1C,OAAOgqC,EAAMtqD,QAAOsU,GAAMA,EAAG+uB,QAAQ,CAAErlB,QAAQ,IAAQxB,cAAcS,EAAOqD,IAChF,EAIA60D,mBAAoB,SAASC,EAAM90D,EAAM,CAAC,GACtC,OAAOrU,KAAKopE,cAAcppE,KAAKumE,cAAe4C,EAAM90D,EACxD,EAEAg1D,gBAAiB,SAASF,EAAM90D,EAAM,CAAC,GACnC,OAAOrU,KAAKopE,cAAcppE,KAAKwmE,WAAY2C,EAAM90D,EACrD,EAEAi1D,gBAAiB,SAASH,EAAM90D,EAAM,CAAC,GACnC,OAAOrU,KAAKopE,cAAcppE,KAAKsmE,WAAY6C,EAAM90D,EACrD,EAEA+0D,cAAe,SAAS/qB,EAAO8qB,EAAM90D,EAAM,CAAC,GACxC,MAAM/D,EAAI,IAAI,GAAO64D,IACf,OAAErwD,GAAS,GAAUzE,EACrBs4B,EAAS7zB,EAAS,eAAiB,YACzC,OAAOulC,EAAMtqD,QAAOsU,GAAMiI,EAAEq8B,GAAQtkC,EAAG+uB,QAAQ,CAAErlB,QAAQ,MAC7D,EAIAw3D,yBAA0B,SAAShS,EAASljD,GACxC,OAAOrU,KAAKwpE,yBAAyBxpE,KAAKumE,cAAehP,EAASljD,EACtE,EAEAo1D,sBAAuB,SAASlS,EAASljD,GACrC,OAAOrU,KAAKwpE,yBAAyBxpE,KAAKwmE,WAAYjP,EAASljD,EACnE,EAEAq1D,sBAAuB,SAASnS,EAASljD,GACrC,OAAOrU,KAAKwpE,yBAAyBxpE,KAAKsmE,WAAY/O,EAASljD,EACnE,EAEAs1D,4BAA6B,SAASC,EAAKC,GACvC,OAAOD,EAAIt0C,KAAOu0C,EAAIv0C,KAAOs0C,EAAI/gB,aAAaghB,EAClD,EAEAC,yBAA0B,SAAS1iB,EAAM/+C,GACrC,OACI++C,EAAKz0D,SAAS2iC,KAAOjtB,EAAGitB,IACxB8xB,EAAKliD,SAASowB,KAAOjtB,EAAGitB,KACvB8xB,EAAKyB,aAAaxgD,EAE3B,EAEA0hE,2BAA4B,SAAS1rB,EAAOkZ,GACxC,OAAOlZ,EAAMtqD,QAAOwqD,GACTA,EAAKC,SACNx+C,KAAK8pE,yBAAyBvrB,EAAMgZ,GACpCv3D,KAAK2pE,4BAA4BprB,EAAMgZ,IAErD,EAEAyS,6BAA8B,SAASzS,EAAS0S,EAAW,QACvD,MAAMl3D,EAAOwkD,EAAQngC,QAAQ,CAAErlB,QAAQ,IACvC,MAAqB,SAAbk4D,EAAuB,GAAkBl3D,EAAMk3D,GAAYl3D,CACvE,EAEAy2D,yBAA0B,SAASnrB,EAAOkZ,EAASljD,EAAM,CAAC,GACtD,MAAM61D,EAAWlqE,KAAKgqE,6BAA6BzS,EAASljD,EAAI41D,UAC1DE,EAAiBD,EAAS/3E,OAAS,GAAQwc,MAC3C3O,KAAK+oE,eAAe1qB,EAAO6rB,GAC3BlqE,KAAKopE,cAAc/qB,EAAO6rB,EAAU71D,GAC1C,OAAOrU,KAAK+pE,2BAA2BI,EAAe5S,EAC1D,EAGA6S,iBAAkB,SAASjB,EAAM90D,GAC7B,OAAOrU,KAAKkpE,mBAAmBC,EAAM90D,EACzC,EAGAg2D,oBAAqB,SAASr5D,GAC1B,OAAOhR,KAAK8oE,oBAAoB93D,EACpC,EAGAs5D,uBAAwB,SAAS/S,EAASljD,GACtC,OAAOrU,KAAKupE,yBAAyBhS,EAASljD,EAClD,EAGA+iB,QAAS,WAEL,OAAOp3B,KAAKm5D,aAAan5D,KAAKsmE,WAClC,EAGAnN,aAAc,SAAS9a,EAAOhqC,EAAM,CAAC,GACjC,MAAM,OAAEtC,GAAS,GAASsC,EAC1B,OAAO,GAAagqC,GAAOr6C,QAAO,SAASumE,EAAMhsB,GAC7C,MAAMtoC,EAAOsoC,EAAKnnB,QAAQ,CAAErlB,WAC5B,OAAKkE,EACDs0D,EACOA,EAAKnnE,MAAM6S,GAEfA,EAJWs0D,CAKtB,GAAG,KACP,EAEA13D,UAAW,SAAS3B,EAAIC,EAAIkD,GAGxB,IAAIgqC,EAAQr+C,KAAKsmE,WAAWvyE,QAAO,SAASwqD,GACxC,OAAQA,EAAKmK,YACjB,IAIA,OAFA,GAAYrK,EAAO,YAAantC,EAAIC,EAAIkD,GAEjCrU,IACX,EAEAm4D,OAAQ,SAAS3nD,EAAOC,EAAQ4D,GAE5B,OAAOrU,KAAKwqE,YAAYh6D,EAAOC,EAAQzQ,KAAKsmE,WAAYjyD,EAC5D,EAEAm2D,YAAa,SAASh6D,EAAOC,EAAQ4tC,EAAOhqC,GAIxC,IAAItB,EAAO/S,KAAKm5D,aAAa9a,GAC7B,GAAItrC,EAAM,CACN,IAAIX,EAAKrQ,KAAKwL,IAAIiD,EAAQuC,EAAKvC,MAAO,GAClC6B,EAAKtQ,KAAKwL,IAAIkD,EAASsC,EAAKtC,OAAQ,GACxC,GAAY4tC,EAAO,QAASjsC,EAAIC,EAAIU,EAAKtD,SAAU4E,EACvD,CAEA,OAAOrU,IACX,EAEAsnD,WAAY,SAASnwD,EAAM5C,GAKvB,OAHAA,EAAOA,GAAQ,CAAC,EAChByL,KAAK6kE,SAAS1tE,IAAS6I,KAAK6kE,SAAS1tE,IAAS,GAAK,EAE5C6I,KAAK28C,QAAQ,cAAe,GAAY,CAAC,EAAGpoD,EAAM,CAAEu0D,UAAW3xD,IAC1E,EAEAywD,UAAW,SAASzwD,EAAM5C,GAKtB,OAHAA,EAAOA,GAAQ,CAAC,EAChByL,KAAK6kE,SAAS1tE,IAAS6I,KAAK6kE,SAAS1tE,IAAS,GAAK,EAE5C6I,KAAK28C,QAAQ,aAAc,GAAY,CAAC,EAAGpoD,EAAM,CAAEu0D,UAAW3xD,IACzE,EAEAszE,eAAgB,SAAStzE,GAErB,MAAMuzE,EAAU1qE,KAAK6kE,SACrB,IAAI7pB,EAUJ,OAPIA,EADqB,IAArBp8C,UAAUpN,OACFxG,OAAO0F,KAAKg6E,GACb15E,MAAMC,QAAQkG,GACbA,EAEA,CAACA,GAGN6jD,EAAMrkD,MAAM4vC,GAAUmkC,EAAQnkC,GAAS,GAClD,GAED,CAECokC,YAAa,CAETC,WAAY,SAAS3jB,EAAOG,GAGxB,IAAI,OAAEz0D,EAAM,OAAEuS,GAAWkiD,EAAK1rB,WAE9B,GAAI/oC,EAAO2iC,IAAMpwB,EAAOowB,GAAI,CAExB,IAAIu1C,EAAczjB,EAAKyU,gBACvB,GAAIgP,GAEqB5jB,EAAMC,kBAAkB2jB,EAAa,CAAExjB,UAAU,IACvCtzD,QAAO,SAAS+2E,GAE3C,IAAMn4E,OAAQo4E,EAAS7lE,OAAQ8lE,GAAYF,EAAMpvC,WACjD,OAAOqvC,GAAWA,EAAQz1C,KAAO3iC,EAAO2iC,MAClCy1C,EAAQjlB,MAASilB,EAAQjlB,OAASnzD,EAAOmzD,OAC3CklB,GAAWA,EAAQ11C,KAAOpwB,EAAOowB,MAC/B01C,EAAQllB,MAASklB,EAAQllB,OAAS5gD,EAAO4gD,KAEnD,IAEct0D,OAAS,EACnB,OAAO,CAGnB,CAEA,OAAO,CACX,EAEAy5E,YAAa,SAASC,EAAQ9jB,GAC1B,IAAI,OAAEz0D,EAAM,OAAEuS,GAAWkiD,EAAK1rB,WAC9B,OAAO/oC,EAAO2iC,IAAMpwB,EAAOowB,EAC/B,MD3rCgB,SAAS7kC,EAAQ8/C,EAAS+vB,GAE9C,GAAI1/D,GAAS0/D,GAAU,CAEnB,IAAK2D,GAAS3D,GACV,MAAM,IAAIt3D,MAAM,qBAAuBs3D,EAAU,KAGrDA,EAAU2D,GAAS3D,EACvB,CAEA,IAAK,GAAWA,GACZ,MAAM,IAAIt3D,MAAM,+BAGpBtG,GCirCsB,CAAC,aAAc,WAAY,gBDjrChC/K,SAAQ,SAASg1C,GAC9Bl8C,EAAOk8C,GAAU2zB,EAAQ7vE,EAAOk8C,GACpC,GACJ,CC8qCAw+B,CAAS7G,GAAMh5E,UAAW,EAA2C24E,GAAS5lB,OC1qCvE,IAAI+sB,GAAW,SAASzzC,GAC3B33B,KAAK+9C,IAAM35C,GAAS,QACpBpE,KAAK89C,cAAc38C,MAAMnB,KAAMpB,WAC/B,GAAOoB,KAAMwD,GAAKm0B,EAAS0zC,KAC3BrrE,KAAKsrE,iBACLtrE,KAAKm+C,WAAWh9C,MAAMnB,KAAMpB,UAChC,EAGI2sE,GAAwB,iBAIxBF,GAAc,CAAC,QAAS,aAAc,KAAM,KAAM,aAAc,YAAa,UAAW,SAAU,SAGtG,GAAOD,GAAS9/E,UAAWsvD,GAAQ,CAG/B9e,QAAS,MAIT0vC,EAAG,SAASjlE,GACR,OAAOvG,KAAK0tC,IAAItlC,KAAK7B,EACzB,EAIAu3C,cAAe,WAAW,EAI1BK,WAAY,WAAW,EAKvBstB,OAAQ,WACJ,OAAOzrE,IACX,EAIAuE,OAAQ,WAGJ,OAFAvE,KAAK0rE,iBACL1rE,KAAKg8C,gBACEh8C,IACX,EAKA0rE,eAAgB,WACZ1rE,KAAK0tC,IAAInpC,QACb,EAIAonE,WAAY,SAASpU,GAIjB,OAHAv3D,KAAK4rE,mBACL5rE,KAAK6rE,YAAYtU,GACjBv3D,KAAK8rE,iBACE9rE,IACX,EAOA6rE,YAAa,SAASxjE,GAClBrI,KAAK0tC,IAAMrlC,aAAc,GAAIA,EAAK,GAAEA,GACpCrI,KAAKqI,GAAKrI,KAAK0tC,IAAI,EACvB,EAeAo+B,eAAgB,SAASviE,GAErB,GADAA,IAAWA,EAAS9X,GAAOuO,KAAM,YAC5BuJ,EAAQ,OAAOvJ,KAEpB,IAAK,IAAIlV,KADTkV,KAAK4rE,mBACWriE,EAAQ,CACpB,IAAIojC,EAASpjC,EAAOze,GAEpB,GADK,GAAW6hD,KAASA,EAAS3sC,KAAK2sC,IAClCA,EAAL,CACA,IAAIv8C,EAAQtF,EAAIsF,MAAMm7E,IACtBvrE,KAAK+rE,SAAS37E,EAAM,GAAIA,EAAM,GAAIu8C,EAAO58C,KAAKiQ,MAFzB,CAGzB,CACA,OAAOA,IACX,EAKA+rE,SAAU,SAASC,EAAWzlE,EAAU42C,GAEpC,OADAn9C,KAAK0tC,IAAIlkC,GAAGwiE,EAAY,kBAAoBhsE,KAAK+9C,IAAKx3C,EAAU42C,GACzDn9C,IACX,EAKA4rE,iBAAkB,WAEd,OADI5rE,KAAK0tC,KAAK1tC,KAAK0tC,IAAI9jC,IAAI,kBAAoB5J,KAAK+9C,KAC7C/9C,IACX,EAIAisE,WAAY,SAASD,EAAWzlE,EAAU42C,GAEtC,OADAn9C,KAAK0tC,IAAI9jC,IAAIoiE,EAAY,kBAAoBhsE,KAAK+9C,IAAKx3C,EAAU42C,GAC1Dn9C,IACX,EAIAksE,eAAgB,SAASpwC,GACrB,OAAO31B,SAASkB,cAAcy0B,EAClC,EAMAwvC,eAAgB,WACZ,GAAKtrE,KAAKqI,GAONrI,KAAK2rE,WAAWl6E,GAAOuO,KAAM,WAPnB,CACV,IAAIkzB,EAAQ,GAAO,CAAC,EAAGzhC,GAAOuO,KAAM,eAChCA,KAAKs1B,KAAIpC,EAAMoC,GAAK7jC,GAAOuO,KAAM,OACjCA,KAAKw6B,YAAWtH,EAAa,MAAIzhC,GAAOuO,KAAM,cAClDA,KAAK2rE,WAAW3rE,KAAKksE,eAAez6E,GAAOuO,KAAM,aACjDA,KAAKmsE,eAAej5C,EACxB,CAGJ,EAIAi5C,eAAgB,SAASzwC,GACrB17B,KAAK0tC,IAAIxY,KAAKwG,EAClB,IAKJ0vC,GAASvrD,OAAS,GChLX,MAAMusD,GAAQ,CAAC,EAETC,GAAOjB,GAASvrD,OAAO,CAEhC8X,QAAS,CAAC,EACV20C,MAAO,KACPC,qBAAsB,GAAwB,UAC9CC,yBAAyB,EACzBC,a9BPc,U8BQdt5C,SAAU,KACVprB,WAAY,KAEZ2kE,YAAY,EACZC,gBAAiB,EACjBC,YAAa,GAAG,GAChBC,YAAa,GAAG,GAChBC,UAAW,GAAG,GAEdx6E,YAAa,SAASqlC,GAElB33B,KAAKwsE,wBAA0B70C,KAAaA,EAAQ20C,MACpDtsE,KAAK23B,QAAU,GAAY,CAAC,EAAG33B,KAAK23B,QAASA,GAE7CyzC,GAAS5/E,KAAKwU,KAAM23B,EACxB,EAEAwmB,WAAY,WAERiuB,GAAMpsE,KAAK+9C,KAAO/9C,KAElBA,KAAK+sE,SAAS/sE,KAAK23B,QAAQ20C,OAAStsE,KAAKysE,cACzCzsE,KAAKgtE,MACT,EAEAC,QAAS,WACDjtE,KAAKktE,WACLltE,KAAKi5B,IAAI10B,SAETvE,KAAK0tC,IAAInpC,QAEjB,EAEA4oE,UAAW,WACP,OAA8B,OAAvBntE,KAAKqI,GAAG2D,UACnB,EAEAohE,eAAgB,SAASj6C,GAErB,GADAA,IAAaA,EAAW,GAAYnzB,KAAM,aACtCmzB,EAAU,CACV,IAAIk6C,EAAQrtE,KAAKktE,WACbviE,EAAY,GAAEA,UAAU0iE,EAAQ,MAAQ,SACxCr0C,EAAM,GAAkB7F,EAAUxoB,IACrC0iE,EAAQrtE,KAAKi5B,IAAMj5B,KAAK0tC,KAAK5U,QAAQhF,OAAOkF,EAAI0Y,UACjD1xC,KAAK+H,WAAaixB,EAAIuY,SAC1B,CACA,OAAOvxC,IACX,EAEAstE,kBAAmB,SAASC,EAAezkE,GACvC,IAAI0kE,EAAc1kE,EAClB,KAAO0kE,GAAwC,IAAzBA,EAAYllE,UAAgB,CAG9C,GAAIklE,EAAY7xC,aAAa4xC,GAAgB,OAAOC,EAEpD,GAAIA,IAAgBxtE,KAAKqI,GAAI,OAAO,KAEpCmlE,EAAcA,EAAYxhE,UAC9B,CACA,OAAO,IACX,EAEAyhE,cAAe,SAASF,EAAezkE,GACnC,MAAM4kE,EAAc1tE,KAAKstE,kBAAkBC,EAAezkE,GAC1D,OAAO4kE,GAAeA,EAAY/xC,aAAa4xC,EACnD,EAKAjC,eAAgB,WACZ,GAAKtrE,KAAKqI,GASNrI,KAAK2rE,WAAW,GAAY3rE,KAAM,WATxB,CACV,IAAI87B,EAAU,GAAY97B,KAAM,WAC5BkzB,EAAQ,GAAY,CAAC,EAAG,GAAYlzB,KAAM,eAC1Ci6B,EAAQ,GAAY,CAAC,EAAG,GAAYj6B,KAAM,UAC1CA,KAAKs1B,KAAIpC,EAAMoC,GAAK,GAAYt1B,KAAM,OAC1CA,KAAK2rE,WAAW3rE,KAAKksE,eAAepwC,IACpC97B,KAAKmsE,eAAej5C,GACpBlzB,KAAK2tE,UAAU1zC,EACnB,CAGAj6B,KAAK4tE,oBACT,EAEAzB,eAAgB,SAASj5C,GACjBlzB,KAAKktE,WACLltE,KAAKi5B,IAAI/D,KAAKhC,GAEdlzB,KAAK0tC,IAAIxY,KAAKhC,EAEtB,EAEAy6C,UAAW,SAAS1zC,GAChBj6B,KAAK0tC,IAAIlB,IAAIvS,EACjB,EAEAiyC,eAAgB,SAASpwC,GACrB,OAAI97B,KAAKktE,WACE/mE,SAASwtB,gBAAgB,GAAEhpB,UAAUgoB,IAAKmJ,GAE1C31B,SAASkB,cAAcy0B,EAEtC,EAIA+vC,YAAa,SAASxjE,GAClBrI,KAAK0tC,IAAMrlC,aAAc,GAAIA,EAAK,GAAEA,GACpCrI,KAAKqI,GAAKrI,KAAK0tC,IAAI,GACf1tC,KAAKktE,aAAYltE,KAAKi5B,IAAM,GAAEj5B,KAAKqI,IAC3C,EAEAulE,mBAAoB,WAChB,IAAIpzC,EAAY,GAAYx6B,KAAM,aAClC,GAAKw6B,EAAL,CACA,IAAIqzC,EAAoB,GAAwBrzC,GAE5Cx6B,KAAKktE,WACLltE,KAAKi5B,IAAIsG,YAAY/E,GAAWvF,SAAS44C,GAEzC7tE,KAAK0tC,IAAInO,YAAY/E,GAAWvF,SAAS44C,EANvB,CAQ1B,EAEAb,KAAM,WAGN,EAEAc,SAAU,WAGV,EAEAC,cAAe,WAGX,OAAO,CACX,EAEAhB,SAAU,SAAST,EAAOj4D,GAMtB,OAJAA,EAAMA,GAAO,CAAC,EAIVrU,KAAKssE,OAAStsE,KAAKwsE,0BAA4Bn4D,EAAI25D,WAIvDhuE,KAAKiuE,uBACLjuE,KAAKkuE,kBAAkB5B,GACvBtsE,KAAKmuE,WAAWnuE,KAAKssE,MAAqBA,GAC1CtsE,KAAKssE,MAAQA,GANFtsE,IASf,EAEAkuE,kBAAmB,SAAS5B,GAGxB,KADAA,EAAQA,GAAStsE,KAAKssE,OACV,OAAOtsE,KAEnB,IAAIw6B,EAAYx6B,KAAKusE,qBAAuBD,EAQ5C,OANItsE,KAAKktE,WACLltE,KAAKi5B,IAAIhE,SAASuF,GAElBx6B,KAAK0tC,IAAIzY,SAASuF,GAGfx6B,IACX,EAEAiuE,qBAAsB,SAAS3B,GAE3BA,EAAQA,GAAStsE,KAAKssE,MAEtB,IAAI9xC,EAAYx6B,KAAKusE,qBAAuBD,EAQ5C,OANItsE,KAAKktE,WACLltE,KAAKi5B,IAAIsG,YAAY/E,GAErBx6B,KAAK0tC,IAAInO,YAAY/E,GAGlBx6B,IACX,EAEAmuE,WAAY,SAASC,EAAUC,GAG/B,EAEA9pE,OAAQ,WASJ,OAPAvE,KAAKsuE,WACLtuE,KAAKuuE,2BAELnC,GAAMpsE,KAAK+9C,KAAO,KAElBqtB,GAAS9/E,UAAUiZ,OAAOpD,MAAMnB,KAAMpB,WAE/BoB,IACX,EAEAsuE,SAAU,WAGV,EAEAE,kBAAmB,WAEf,MAAO,mBAAqBxuE,KAAK+9C,GACrC,EAEA0wB,sBAAuB,SAASlX,EAAShuD,EAAQhV,GAC7C,IAAKgV,EAAQ,OAAOvJ,KACpBzL,IAASA,EAAO,CAAC,GACjB,IAAIm6E,EAAU1uE,KAAKwuE,oBACnB,IAAK,IAAIxC,KAAaziE,EAAQ,CAC1B,IAAIojC,EAASpjC,EAAOyiE,GACE,mBAAXr/B,IAAuBA,EAAS3sC,KAAK2sC,IAC3CA,GACL,GAAE4qB,GAAS/tD,GAAGwiE,EAAY0C,EAASn6E,EAAMo4C,EAAO58C,KAAKiQ,MACzD,CACA,OAAOA,IACX,EAEA2uE,wBAAyB,SAASpX,GAE9B,OADA,GAAEA,GAAS3tD,IAAI5J,KAAKwuE,qBACbxuE,IACX,EAEA4uE,uBAAwB,SAASrlE,EAAQhV,GAErC,OADAgV,IAAWA,EAAS,GAAYvJ,KAAM,mBAC/BA,KAAKyuE,sBAAsBtoE,SAAUoD,EAAQhV,EACxD,EAEAg6E,yBAA0B,WACtB,OAAOvuE,KAAK2uE,wBAAwBxoE,SACxC,EAEA0oE,UAAW,SAASjpE,EAAKrR,GACrB,IAAKqR,EAAK,MAAM,IAAIoD,MAAM,uCAC1B,IAAI8lE,EAAclpE,EAAIrR,KAClBzJ,EAAM,KAAOkV,KAAK+9C,IAAM,KAC5B,YAAatrD,IAAT8B,EACKu6E,GACEA,EAAYhkF,IADM,CAAC,GAG9BgkF,IAAgBA,EAAclpE,EAAIrR,KAAO,CAAC,GAC1Cu6E,EAAYhkF,KAASgkF,EAAYhkF,GAAO,CAAC,GACzC,GAAYgkF,EAAYhkF,GAAMyJ,GACvByL,KACX,EAEA6F,gBAAiB,SAASD,GAEtB,OADA5F,KAAK6uE,UAAUjpE,EAAK,CAAEmpE,oBAAoB,IACnC/uE,IACX,EAEAyF,qBAAsB,SAASG,GAC3B,QAAS5F,KAAK6uE,UAAUjpE,GAAKmpE,kBACjC,GAED,CAEClvD,OAAQ,WAEJ,IAAI5e,EAAOjQ,MAAM8W,KAAKlJ,WAIlBy+C,EAAap8C,EAAK,IAAM,GAAY,CAAC,EAAGA,EAAK,KAAO,CAAC,EACrDq8C,EAAcr8C,EAAK,IAAM,GAAY,CAAC,EAAGA,EAAK,KAAO,CAAC,EAGtD+tE,EAAW3xB,EAAWouB,QAAWzrE,KAAK1U,WAAa0U,KAAK1U,UAAUmgF,QAAW,KA0BjF,OAnBApuB,EAAWouB,OAAS,WAchB,MAZwB,mBAAbuD,GAEPA,EAAS7tE,MAAMnB,KAAMpB,WAGrBoB,KAAKyrE,OAAOwD,aAAeD,GAG3BhvE,KAAK8tE,WAIF9tE,IACX,EAEAq9C,EAAWouB,OAAOwD,WAAaD,EAExB5D,GAASvrD,OAAOr0B,KAAKwU,KAAMq9C,EAAYC,EAClD,IC9TJ,SAAS,GAAQlyD,GACb,OAAKA,EACD4F,MAAMC,QAAQ7F,GAAaA,EACxB,CAACA,GAFS,EAGrB,CAEO,MAAM8jF,GAAkB,GAASrvD,OAAO,CAE3Cic,QAAS,IACToxC,YAAY,EACZ1yC,UAAW,YAEX20C,eAAgB,EAChBxC,gBAAiB,EACjBD,YAAY,EACZ0C,WAAW,EACXC,WAAW,EAEXC,SAAU,KACVr9B,aAAc,KACdnpC,KAAM,KACNymE,iBAAiB,EACjBC,iBAAiB,EACjBC,eAAgB,KAChBC,uBAAwB,KAExB,aAAAC,CAAcL,EAAUr9B,GACpB,MAAM,MAAEqR,GAAUgsB,EAClBtvE,KAAKsvE,SAAWA,EAChBtvE,KAAKiyC,aAAeA,EAChBqR,IACAtjD,KAAKuvE,iBAAkB,EACvBjsB,EAAMssB,kBAAkB5vE,KAAMA,KAAKmvE,eAAgBnvE,KAAK2sE,iBAEhE,EAEA,aAAAoB,GAEI/tE,KAAKuvE,iBAAkB,EACvB,MAAM,SAAED,EAAQ,aAAEr9B,GAAiBjyC,KACnC,OAAKsvE,EAASnC,aAIdntE,KAAK2S,OAAO28D,EAAUr9B,GACtBjyC,KAAK6vE,QACL7vE,KAAKg2B,YACE,IANHh2B,KAAKwvE,iBAAkB,EAChB,EAMf,EAEA,QAAAxsB,CAASssB,EAAUr9B,EAAe,MAC9B,IAAI5pC,EACJ,GAA4B,iBAAjB4pC,EACP5pC,EAAKinE,EAAStsB,SAAS/Q,QACpB,GAAI71C,GAAc61C,GAAe,CACpC,MAAMuM,EAAS8wB,EAAS3xB,MAAMa,UACxB,MAAEkS,EAAQ,KAAI,KAAE5K,EAAI,SAAEv/C,GAAa0rC,EAGrC5pC,EAFAm2C,GAAoB,OAAVkS,EAEL4e,EAASQ,cAAcpf,EAAOnqD,IAC3Bi4C,GAAUsH,EAEbwpB,EAASzZ,aAAa/P,EAAMv/C,GAG5B+oE,EAAStsB,SAASz8C,EAE/B,MAAW0rC,IACP5pC,EAAK,GAAEqtB,OAAOuc,GACR5pC,aAAck8B,aAAal8B,EAAK,OAE1C,OAAOA,GAAU,IACrB,EAEA,aAAA0nE,CAAcT,EAAUxmE,GACpB,MAAM,QAAE6uB,GAAY33B,MACd,MAAEgwE,GAAUr4C,GACZ,cAAEu9B,GAAkBoa,EACpBW,EAAaX,EAASS,cAAcjnE,GAC1C,OAAIosD,EACI8a,EACI9a,EAAc3sD,SAASO,GAChBmnE,EAIJX,EAASY,sBAAsBr6C,UAAUC,SAASm6C,GAElDX,EAASa,oBAAoBrnE,GAAMgtB,SAASm6C,GAGpDA,CACX,EAEA,KAAAJ,GACI,MAAM,UAAER,EAAS,SAAEC,EAAQ,GAAEjnE,EAAE,QAAEsvB,EAAO,eAAE83C,EAAc,uBAAEC,EAAsB,gBAAEF,EAAe,aAAEv9B,GAAiBjyC,KACpH,IAAKqvE,GAAaI,EAAgB,OAClC,GAAID,EAKA,OAFAxvE,KAAK2S,OAAO28D,EAAUr9B,QACtBjyC,KAAKg2B,YAGT,MAAQiD,IAAKm3C,EAAY,MAAE9sB,GAAUgsB,GAC7BU,MAAOK,GAAc14C,EAC7B,GAAI04C,EAAW,CACX,IAAIC,EACAZ,GACAY,EAASZ,EACT1vE,KAAK0vE,uBAAyB,MAE9BY,EAAS,GAAE,KAAKr7C,SAAS,uBAAuBnB,OAAOzrB,GAE3DrI,KAAKyvE,eAAiBa,EACtBhtB,EAAMitB,aAAaF,GAAWG,iBAAiBF,EAAOxnE,KAAM6uB,EAAQpM,EACxE,MAESljB,EAAG2D,aAAc3D,EAAGooE,aAErBL,EAAat8C,OAAOzrB,EAGhC,EAEA,OAAA4kE,GACI,MAAM,UAAEoC,EAAS,eAAEI,EAAc,IAAEx2C,GAAQj5B,KACtCqvE,IACDI,GACAzvE,KAAKyvE,eAAiB,KACtBzvE,KAAK0vE,uBAAyBD,EAC9BA,EAAelrE,UAEf00B,EAAI10B,SAEZ,EAEA,SAAAyxB,GACI,MAAM,eAAEy5C,EAAc,SAAEH,EAAQ,gBAAEC,GAAoBvvE,KACtD,IAAKyvE,GAAkBH,EAAS3xB,MAAMa,UAAY+wB,EAAiB,OACnE,MAAMmB,EAAkBpB,EAASqB,yBAC3BC,EAAetB,EAASY,sBACxBW,EAAkBH,EAAgB56C,SAAS86C,GACjDnB,EAAev6C,KAAK,YAAa,GAAEmB,wBAAwBw6C,GAC/D,EAEA,MAAAl+D,GACI,MAAQ7J,KAAMgoE,EAAQ,SAAExB,EAAQ,aAAEr9B,EAAY,gBAAEs9B,EAAe,GAAEj6C,GAAOt1B,KACxE,GAAIuvE,EAAiB,OACrBvvE,KAAKwvE,iBAAkB,EACvB,MAAM1mE,EAAO9I,KAAK8I,KAAO9I,KAAKgjD,SAASssB,EAAUr9B,GAC7C6+B,GACA9wE,KAAK+wE,YAAYzB,EAAUwB,GAE3BhoE,GACA9I,KAAKi5C,UAAUq2B,EAAUxmE,GACzB9I,KAAK6vE,UAEL7vE,KAAKitE,UACLqC,EAAS0B,OAAO,yBAA0B17C,EAAIt1B,MAEtD,EAEA,QAAAsuE,GACI,MAAM,KAAExlE,EAAI,SAAEwmE,EAAQ,GAAEh6C,EAAE,YAAEhjC,GAAgB0N,KACxC8I,GACA9I,KAAK+wE,YAAYzB,EAAUxmE,GAE/B9I,KAAKitE,UACL36E,EAAY2+E,WAAW3B,EAAUh6C,EACrC,EAEA,SAAA2jB,CAAUi4B,EAAW3uB,GAErB,EAEA,WAAAwuB,CAAYG,EAAW3uB,GAEvB,EAIA,wBAAA4uB,CAAyB7B,GACrB,MAAM5zC,EAAajqC,GAAOuO,KAAM,qBAC3BhP,MAAMC,QAAQyqC,IAAqC,IAAtBA,EAAWlqC,QAC7CwO,KAAKu7C,SAAS+zB,EAAS3xB,MAAO,SAAU39C,KAAKoxE,sBACjD,EAEA,qBAAAA,GACI,MAAM,SAAE9B,GAAatvE,KACrB,IAAKsvE,EAAU,OACf,MAAM,MAAE3xB,EAAK,MAAE2F,GAAUgsB,EACN79E,GAAOuO,KAAM,qBAChBrJ,MAAKivD,GAAajI,EAAM4B,WAAWqG,MACnDtC,EAAMssB,kBAAkB5vE,KAAMA,KAAKmvE,eAAgBnvE,KAAK2sE,gBAC5D,GAED,CAEC0E,OAAQ,CAAC,EAGTp4B,UAAW,SAASq2B,EAAUxmE,EAAMuL,GAChC,MAAMihB,EAAKt1B,KAAKoE,SAAS0E,EAAMuL,GAC/BrU,KAAKpF,IAAI00E,EAAUxmE,EAAMwsB,EAAIjhB,EACjC,EAGA08D,YAAa,SAASzB,EAAUxmE,EAAMuL,GAClC,MAAMihB,EAAKt1B,KAAKoE,SAAS0E,EAAMuL,GAC/BrU,KAAKuE,OAAO+qE,EAAUh6C,EAC1B,EAEA,GAAAnqC,CAAImkF,EAAUh6C,EAAK,MACf,MAAM,IAAEyoB,GAAQuxB,GACV,OAAE+B,GAAWrxE,KACbm1D,EAAOkc,EAAOtzB,GACpB,GAAW,OAAPzoB,EAAa,CAEb,MAAM82C,EAAQ,GACd,IAAKjX,EAAM,OAAOiX,EAClB,IAAK,IAAIkF,KAAOnc,EAAM,CAClB,MAAM/jD,EAAM+jD,EAAKmc,GACblgE,aAAepR,MACfosE,EAAMx6E,KAAKwf,EAEnB,CACA,OAAOg7D,CACX,CAEI,IAAKjX,EAAM,OAAO,KAClB,GAAI7/B,KAAM6/B,EAAM,CACZ,MAAM/jD,EAAM+jD,EAAK7/B,GACjB,GAAIlkB,aAAepR,KAAM,OAAOoR,CACpC,CACA,OAAO,IAEf,EAEA,GAAAxW,CAAI00E,EAAUr9B,EAAc3c,EAAIjhB,EAAM,CAAC,GACnC,IAAKihB,EAAI,MAAM,IAAItsB,MAAM,wCAEzB,MAAMuoE,EAAerC,GAAgB/jF,IAAImkF,EAAUh6C,GAC/Ci8C,GAAcA,EAAahtE,SAC/B,MAAMitE,EAAO,IAAIxxE,KAAKqU,GAKtB,OAJAm9D,EAAKl8C,GAAKA,EACVt1B,KAAKyxE,QAAQnC,EAAUh6C,EAAIk8C,GAC3BA,EAAK7B,cAAcL,EAAUr9B,GAC7Bu/B,EAAKL,yBAAyB7B,GACvBkC,CACX,EAEA,OAAAC,CAAQnC,EAAUh6C,EAAIk8C,GAClB,MAAM,IAAEzzB,GAAQuxB,GACV,OAAE+B,GAAWrxE,KACnB,IAAIm1D,EAAOkc,EAAOtzB,GACboX,IAAMA,EAAOkc,EAAOtzB,GAAO,CAAC,GACjCoX,EAAK7/B,GAAMk8C,CACf,EAEA,UAAAP,CAAW3B,EAAUh6C,GACjB,MAAM,IAAEyoB,GAAQuxB,GACV,OAAE+B,GAAWrxE,KACbm1D,EAAOkc,EAAOtzB,GACpB,GAAKoX,EAAL,CACI7/B,UAAW6/B,EAAK7/B,GACpB,IAAK,IAAIwqB,KAAKqV,EAAM,cACbkc,EAAOtzB,EAHG,CAIrB,EAEA,MAAAx5C,CAAO+qE,EAAUh6C,EAAK,MAClB,GAAQt1B,KAAK7U,IAAImkF,EAAUh6C,IAAK39B,SAAQ65E,IACpCA,EAAKjtE,QAAQ,GAErB,EAEA,MAAAmtE,CAAOpuB,EAAOhuB,EAAK,MACf,MAAM82C,EAAQ,IACR,OAAEiF,GAAWrxE,KACnB,IAAK,IAAI+9C,KAAOszB,EACZ,IAAK,IAAIC,KAAOD,EAAOtzB,GAAM,CACzB,MAAMyzB,EAAOH,EAAOtzB,GAAKuzB,GACrBE,EAAKlC,SAAShsB,QAAUA,GAASkuB,aAAgBxxE,OAAgB,OAAPs1B,GAAeg8C,IAAQh8C,IACjF82C,EAAMx6E,KAAK4/E,EAEnB,CAEJ,OAAOpF,CACX,EAEA,SAAAuF,CAAUruB,EAAOhuB,EAAK,MAClBt1B,KAAK0xE,OAAOpuB,EAAOhuB,GAAI39B,SAAQ65E,GAAQA,EAAKjtE,UAChD,EAEA,MAAAoO,CAAO28D,EAAUh6C,EAAK,KAAM+0B,GAAQ,GAChC,GAAQrqD,KAAK7U,IAAImkF,EAAUh6C,IAAK39B,SAAQ65E,KAChCnnB,GAASmnB,EAAKpC,YAAWoC,EAAK7+D,QAAQ,GAElD,EAEA,SAAAqjB,CAAUs5C,EAAUh6C,EAAK,MACrB,GAAQt1B,KAAK7U,IAAImkF,EAAUh6C,IAAK39B,SAAQ65E,IAChCA,EAAKpC,WAAWoC,EAAKx7C,WAAW,GAE5C,EAEA,OAAAi3C,CAAQqC,EAAUh6C,EAAK,MACnB,GAAQt1B,KAAK7U,IAAImkF,EAAUh6C,IAAK39B,SAAQ65E,GAAQA,EAAKvE,WACzD,EAEA,KAAA4C,CAAMP,EAAUh6C,EAAK,MACjB,GAAQt1B,KAAK7U,IAAImkF,EAAUh6C,IAAK39B,SAAQ65E,GAAQA,EAAK3B,SACzD,EAEAzrE,SAAQ,CAAC0E,EAAMuL,EAAM,KACV,GAAEuf,SAAS9qB,GAAQ69B,KAAKC,UAAUvyB,KC5R3Cu9D,GAjCqB,CACvB,YACA,IACA,IACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,SACA,IACA,IACA,KACA,KACA,QACA,SACA,eACA,aAasC5tE,QAAO,CAAC6hB,EAAK+V,KACnD/V,EAAI+V,IAAY,EACT/V,IACR,CAAC,GAEEgsD,GAfoB,CACtB,IACA,KACA,KACA,QACA,SACA,eACA,aAQ8C7tE,QAAO,CAAC6hB,EAAK+V,KAC3D/V,EAAI+V,IAAY,EACT/V,IACR,CAAC,GAEG,SAASisD,GAAe5+C,EAAOktB,GAClC,MAAM2xB,EAAY,CAAC,EACnB,IAAK,IAAIn2C,KAAY1I,EACZA,EAAM3nC,eAAeqwC,KAC1Bm2C,EAAUn2C,GAAYo2C,GAAcp2C,EAAU1I,EAAM0I,GAAWwkB,IAEnE,OAAO2xB,CACX,CAEO,SAASC,GAAcp2C,EAAU6kB,EAAWL,GAC/C,GAAIxkB,KAAYg2C,IAAkBhwB,GAAiBnB,GAAY,CAC3D,IAAIwxB,EAAgBpwB,GAAmBpB,EAAWL,GAIlD,OAHIxkB,KAAYi2C,KACZI,EAAgBlwE,KAAKwL,IAAI,EAAG0kE,IAEzBA,CACX,CACA,OAAOxxB,CACX,CCvCA,MAAMyxB,GAAoB,CACtBC,QAAS,UACTC,UAAW,YACXC,WAAY,aACZC,oBAAqB,qBACrBC,qBAAsB,uBAWbC,GAAWnG,GAAKxsD,OAAO,CAEhCic,QAAS,IAEToxC,YAAY,EAEZ3mE,SAAU,OAEVisD,QAAS,KAETh4B,UAAW,WAEP,IAAIi4C,EAAa,CAAC,QACdtgF,EAAO6N,KAAK29C,MAAMxyD,IAAI,QAS1B,OAPIgH,GAEAA,EAAK+R,cAAc5T,MAAM,KAAKqH,SAAQ,SAAShM,EAAO+F,EAAOghF,GACzDD,EAAW7gF,KAAK,QAAU8gF,EAAK53E,MAAM,EAAGpJ,EAAQ,GAAG5C,KAAK,KAC5D,IAGG2jF,EAAW3jF,KAAK,IAC3B,EAEA6jF,wBAAyB,KACzBC,OAAQ,KAERC,SAAU,WACN,IAGI/rE,EAAGkJ,EAAG0gD,EAHNoiB,EAAQ,CAAC,EACTp3C,EAAa,CAAC,EACd8P,EAAQ,EAERunC,EAAyBthF,GAAOuO,KAAM,0BAC1C,IAAK,IAAI4lD,KAAamtB,EAClB,GAAKA,EAAuBxnF,eAAeq6D,GAA3C,CACA,IAAIkV,EAASiY,EAAuBntB,GAEpC,IADK50D,MAAMC,QAAQ6pE,KAASA,EAAS,CAACA,IACjCh0D,EAAI,EAAGkJ,EAAI8qD,EAAOtpE,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAEvC,IAAI+kD,EAAOinB,EADXpiB,EAAQoK,EAAOh0D,IAEV+kD,IACDA,EAAOinB,EAAMpiB,GAAS,GAAIllB,KAE9B9P,EAAWkqB,IAAciG,CAC7B,CAV+D,CAYnE,IAAImnB,EAAWvhF,GAAOuO,KAAM,YAE5B,IADKhP,MAAMC,QAAQ+hF,KAAWA,EAAW,CAACA,IACrClsE,EAAI,EAAGkJ,EAAIgjE,EAASxhF,OAAQsV,EAAIkJ,EAAGlJ,IAE/BgsE,EADLpiB,EAAQsiB,EAASlsE,MACEgsE,EAAMpiB,GAAS,GAAIllB,KAK1C,GAAIA,EAAQ,GAAI,MAAM,IAAIxiC,MAAM,mDAEhChJ,KAAK4yE,OAASE,EACd9yE,KAAK2yE,wBAA0Bj3C,CACnC,EAEAu3C,QAAS,SAASpnB,EAAM6E,GACpB,OAAO7E,EAAO7rD,KAAKkzE,QAAQxiB,EAC/B,EAEAyiB,WAAY,SAAStnB,EAAM6E,GACvB,OAAO7E,EAAQA,EAAO7rD,KAAKkzE,QAAQxiB,EACvC,EAEAwiB,QAAS,SAASxiB,GACd,IAAIoiB,EAAQ9yE,KAAK4yE,OACjB,IAAKE,EAAO,OAAO,EACnB,IAAIjnB,EAAO,EACX,GAAI76D,MAAMC,QAAQy/D,GACd,IAAK,IAAI5pD,EAAI,EAAGkJ,EAAI0gD,EAAMl/D,OAAQsV,EAAIkJ,EAAGlJ,IAAK+kD,GAAQinB,EAAMpiB,EAAM5pD,SAElE+kD,GAAQinB,EAAMpiB,GAElB,OAAO7E,CACX,EAEAnwB,WAAY,WACR,IAAI6iB,EAAOv+C,KAAK29C,MAChB,MAAO,CACH,WAAYY,EAAKjpB,GACjB,YAAaipB,EAAK7iB,WAAWvpC,KAErC,EAEAG,YAAa,SAASqlC,GAMlBA,EAAQrC,GAAKqC,EAAQrC,IAAM5uB,GAAK1G,MAEhCqsE,GAAK7gF,KAAKwU,KAAM23B,EACpB,EAEAwmB,WAAY,WAERn+C,KAAK6yE,WAELxG,GAAK/gF,UAAU6yD,WAAWh9C,MAAMnB,KAAMpB,WAEtCoB,KAAKozE,kBAELpzE,KAAKqzE,gBACT,EAEAA,eAAgB,WACZrzE,KAAKu7C,SAASv7C,KAAK29C,MAAO,SAAU39C,KAAKszE,mBAC7C,EAEAA,mBAAoB,SAAS31B,EAAOtpC,GAChC,IAAIw3C,EAAOlO,EAAMiO,cAAc5rD,KAAK2yE,0BAChCt+D,EAAIk/D,eAAkB1nB,IACtBx3C,EAAIg2C,OAASrqD,KAAKizE,QAAQpnB,EAAM,YAAWA,GAAQ7rD,KAAKkzE,QAAQ,WAGhE7+D,EAAIm/D,OAAMn/D,EAAIqtB,OAAQ,GAC1B1hC,KAAK2vE,cAAc9jB,EAAMx3C,GAC7B,EAEAs7D,cAAe,SAASmD,EAAOz+D,GAC3B,MAAM,MAAEivC,GAAUtjD,KACdsjD,GAASwvB,EAAQ,GACjBxvB,EAAMssB,kBAAkB5vE,KAAM8yE,EAAO9yE,KAAK2sE,gBAAiBt4D,EAEnE,EAEAg9B,aAAc,SAAS6f,EAAQn6C,GAE3B,IAAIiiB,EAAMqY,GAAa6f,GACnB3f,EAAYvY,EAAIuY,UAChB8d,EAASr2B,EAAIwY,eACjB,IAAK,IAAIa,KAASgd,EAAQ,CACtB,GAAI9d,EAAUc,GAAQ,MAAM,IAAIrpC,MAAM,0CACtCuoC,EAAUc,GAASgd,EAAOhd,EAC9B,CACA,GAAIt7B,EAAM,CACN,IAAI08D,EAAezzE,KAAKuG,SACxB,GAAIgrC,EAAUkiC,GAAe,MAAM,IAAIzqE,MAAM,0CAC7CuoC,EAAUkiC,GAAgB18D,CAC9B,CACA,MAAO,CAAE26B,SAAU1Y,EAAI0Y,SAAUH,UAAWA,EAChD,EAIAmiC,IAAK,SAASC,GAEV,I5D6mD0BhoF,EAC1BoH,E4D9mDI6gF,EAAc,GAAW5zE,KAAK23B,QAAQi8C,aACpC5zE,KAAK23B,QAAQi8C,YAAY5zE,MACzBA,KAAK23B,QAAQi8C,YAEnB,OAAQ1hF,GAAS0hF,KAAyC,IAAzBA,EAAYD,K5DymDnBhoF,E4DxmDXioF,E5DymDf7gF,EAAW/H,OAAOM,UAAUyH,WACf,IAAVpH,IAA4B,IAAVA,KAAsBA,GAA0B,iBAAVA,GAAsBoH,EAASvH,KAAKG,KAAWG,K4D1mD3D,IAAhB8nF,EACnC,EAEAhe,eAAgB,SAASrvD,EAAUwQ,EAAMw6B,GAIrC,IAAKhrC,GAAyB,MAAbA,EAAkB,MAAO,CAACwQ,GAC3C,GAAIw6B,EAAW,CACX,IAAIzU,EAAQyU,EAAUhrC,GACtB,GAAIu2B,EACA,OAAI9rC,MAAMC,QAAQ6rC,GAAeA,EAC1B,CAACA,EAEhB,CAIA,OAAI98B,KAAK6zE,gBAAwB,GAAE98D,GAAM3O,KAAK7B,GAAU7D,UAEjD,EACX,EAEAoxE,UAAW,SAASvtE,GAChB,OAAOvG,KAAK41D,eAAervD,EAAUvG,KAAKqI,GAAIrI,KAAKuxC,UACvD,EAEAyR,SAAU,SAASz8C,GACf,MAAOuC,EAAO,MAAQ9I,KAAK8zE,UAAUvtE,GACrC,OAAOuC,CACX,EAEAkoE,OAAQ,SAAShF,GAEb,GAAIhsE,KAAKsjD,MAAO,CAEZ,IAAIriD,EAAOjQ,MAAM1F,UAAUwP,MAAMtP,KAAKoT,UAAW,GAGjDoB,KAAK28C,QAAQx7C,MAAMnB,KAAM,CAACgsE,GAAWrjE,OAAO1H,IAG5CjB,KAAKsjD,MAAM3G,QAAQx7C,MAAMnB,KAAKsjD,MAAO,CAAC0oB,EAAWhsE,MAAM2I,OAAO1H,GAClE,CACJ,EAEAm2B,QAAS,SAAS/iB,GAEd,IAAItB,EACJ,GAAIsB,GAAOA,EAAI0/D,iBAAkB,CAC7B,IAAIp2B,EAAQ39C,KAAK29C,MACjB5qC,EAAO4qC,EAAMvmB,UAAUrkB,KAAK4qC,EAAM7wC,QACtC,MACIiG,EAAO/S,KAAKg0E,YAAYh0E,KAAKqI,IAGjC,OAAOrI,KAAKsjD,MAAM2wB,iBAAiBlhE,EACvC,EAEAihE,YAAa,SAASE,GAElB,MAAMj+D,EAAOjW,KAAKm0E,oBAAoBD,GAChCrD,EAAkB7wE,KAAK2wE,yBAAyB76C,SAAS91B,KAAKmwE,oBAAoB+D,IAClFE,EAAep0E,KAAK+vE,cAAcmE,GACxC,OAAO,GAAEz8C,cAAcxhB,EAAM46D,EAAgB/6C,SAASs+C,GAC1D,EAEA,mBAAAjE,CAAoBrnE,GAChB,OAAK9I,KAAKk1D,eAAiBl1D,KAAKk1D,cAAc3sD,SAASO,GAG5C9I,KAAKkwE,sBAGT,GAAEn6C,iBACb,EAEAs+C,qBAAsB,SAASH,GAE3B,IAAIj+D,EAAOjW,KAAKm0E,oBAAoBD,GAChCE,EAAep0E,KAAK+vE,cAAcmE,GAClCxD,EAAkB1wE,KAAK2wE,yBAC3B,OAAO,GAAEl5C,cAAcxhB,EAAMy6D,EAAgB56C,SAASs+C,GAC1D,EAEAzD,uBAAwB,WAEpB,IACI/yC,EADQ59B,KAAK29C,MACI/f,WAErB,OADS,GAAE7H,kBAAkBljB,UAAU+qB,EAASzvB,EAAGyvB,EAAS5vB,EAEhE,EAEAkiE,oBAAqB,WAEjB,IAAI32D,EAAK,GAAEwc,kBACP4nB,EAAQ39C,KAAK29C,MACb7wC,EAAQ6wC,EAAM7wC,QAClB,GAAIA,EAAO,CACP,IAAIiG,EAAO4qC,EAAMvmB,UACbP,EAAK9jB,EAAKvC,MAAQ,EAClBsmB,EAAK/jB,EAAKtC,OAAS,EACvB8I,EAAKA,EAAG1G,UAAUgkB,EAAIC,GAAI/kB,OAAOjF,GAAO+F,WAAWgkB,GAAKC,EAC5D,CACA,OAAOvd,CACX,EAEA+6D,iBAAkB,SAAStI,EAAW3jE,EAAIgM,EAAM,CAAC,GAC7C,MAAQhM,GAAIksE,GAAav0E,KACzB,IAAI8I,EASJ,GARkB,iBAAPT,EACPS,EAAO9I,KAAKgjD,SAAS36C,IAAOksE,GAE3BzrE,EAAOyrE,GAAYv0E,KAAKwrE,EAAEnjE,GAG/BgM,EAAImgE,QAAW1rE,IAASyrE,OAEP9hF,IAAb4hB,EAAIliB,KAAoB,CACxB,IAAIA,EACJ,QAAQ,GACJ,KAAKkiB,EAAIogE,UACLtiF,EAAO+/E,GAAkBE,UACzB,MACJ,KAAK/9D,EAAIqgE,WACLviF,EAAO+/E,GAAkBG,WACzB,MACJ,KAAKh+D,EAAIsgE,mBACLxiF,EAAO+/E,GAAkBI,oBACzB,MACJ,KAAKj+D,EAAIugE,oBACLziF,EAAO+/E,GAAkBK,qBACzB,MACJ,QACIpgF,EAAO+/E,GAAkBC,QAGjC99D,EAAIliB,KAAOA,CACf,CAEA,OADA6N,KAAKgxE,OAAOhF,EAAWljE,EAAMuL,GACtBrU,IACX,EAEAi5C,UAAW,SAAS5wC,EAAIgM,GACpB,OAAOrU,KAAKs0E,iBAAiB,iBAAkBjsE,EAAIgM,EACvD,EAEA08D,YAAa,SAAS1oE,EAAIgM,EAAM,CAAC,GAC7B,OAAOrU,KAAKs0E,iBAAiB,mBAAoBjsE,EAAIgM,EACzD,EAIAwgE,WAAY,SAASxsE,GAEjB,MAAM0O,EAAO/W,KAAKqI,GAClB,IAAI6rE,EAASl0E,KAAKwrE,EAAEnjE,GAAI,GACnB6rE,IACDA,EAASn9D,GAGb,EAAG,CACC,MAAM+9D,EAAkBZ,EAAOv4C,aAAa,UACtCo5C,EAAgBb,IAAWn9D,EACjC,IAAK+9D,GAAmBC,IAAqC,UAApBD,EACrC,OAAOZ,EAEX,GAAIa,EAKA,OAEJb,EAASA,EAAOloE,UACpB,OAASkoE,EAGb,EAEAc,cAAe,SAAS3sE,EAAIlW,GACxBkW,IAAOA,EAAKrI,KAAKqI,IACjB,MAAM4pC,EAAe5pC,EAAGszB,aAAa,GAAGxpC,cACxC,GAAI8/C,EAAc,CACd,MAAMgjC,EAAYj1E,KAAKgjD,SAAS/Q,GAChC,GAAIgjC,EAAW,OAAOA,CAC1B,CACA,OAAO5sE,CACX,EAKA6sE,YAAa,SAAS7sE,EAAI8sE,GAEtB,IAAI5uE,EAEJ,GAAI8B,IAAOrI,KAAKqI,GAEZ,MAD4B,iBAAjB8sE,IAA2B5uE,EAAW,YAAc4uE,GACxD5uE,EAGX,GAAI8B,EAAI,CAEJ,IAAI+sE,EAAW,GAAE/sE,GAAI3W,QAAU,EAC/B6U,EAAW8B,EAAGyzB,QAAU,cAAgBs5C,EAAW,IAE/CD,IACA5uE,GAAY,MAAQ4uE,GAGxB5uE,EAAWvG,KAAKk1E,YAAY7sE,EAAG2D,WAAYzF,EAC/C,CAEA,OAAOA,CACX,EAEA8uE,kBAAmB,SAASnB,EAAQ/lE,EAAGH,GAEnC,IAAIs1C,EAAQtjD,KAAKsjD,MACb2D,EAAQ3D,EAAM3F,MAEdyJ,EAAO9D,EAAMgyB,eAAet1E,KAAMk0E,GAStC,OARA9sB,EAAKh0D,IAAI,CACLT,OAAQqN,KAAKu1E,WAAWrB,EAAQ/lE,EAAGH,EAAGo5C,EAAM,UAC5CliD,OAAQ,CAAEiJ,EAAGA,EAAGH,EAAGA,KACpBu9C,MAAMtE,EAAO,CACZvlB,OAAO,EACP8zC,IAAI,IAGDpuB,EAAKqE,SAASnI,EACzB,EAEAiyB,WAAY,SAASrB,KAAWjzE,GAE5B,MAAM08C,EAAQ39C,KAAK29C,MACbroB,EAAKqoB,EAAMroB,GAEXmgD,EAAWz1E,KAAKstE,kBAAkB,OAAQ4G,GAE1C3tE,EAAW2tE,EAAOv4C,aAAa,kBAE/B97B,EAAM,CAAEy1B,GAAIA,GAElB,GADgB,MAAZ/uB,IAAkB1G,EAAIq0E,OAAS3tE,GACnB,MAAZkvE,EAAkB,CAClB,IAAI3vB,EAAO2vB,EAAS95C,aAAa,QACa,WAA1C85C,EAAS95C,aAAa,kBACtBmqB,EAAOx3C,SAASw3C,EAAM,KAE1BjmD,EAAIimD,KAAOA,EACNnI,EAAMoU,QAAQjM,IAAUv/C,IAEzB1G,EAAI0G,SAAWvG,KAAKk1E,YAAYhB,GAExC,MAAuB,MAAZ3tE,GAAoBvG,KAAKqI,KAAO6rE,IACvCr0E,EAAI0G,SAAWvG,KAAKk1E,YAAYhB,IAGpC,OAAOl0E,KAAK01E,iBAAiB71E,EAAKq0E,KAAWjzE,EACjD,EAEAy0E,iBAAkB,SAAS71E,EAAKq0E,EAAQ/lE,EAAGH,EAAGo5C,EAAMqS,GAChD,MAAM,MAAEnW,GAAUtjD,MACZ,mBAAE21E,GAAuBryB,EAAM3rB,QACrC,GAAkC,mBAAvBg+C,EAAmC,CAC1C,IAAIC,EAAWD,EAAmBnqF,KAAK83D,EAAOzjD,EAAKG,KAAMk0E,EAAQ,IAAIvlE,GAAMR,EAAGH,GAAIo5C,EAAMqS,EAASnW,GACjG,GAAIsyB,EAAU,OAAOA,CACzB,CACA,OAAO/1E,CACX,EAEAg2E,qBAAsB,SAASh2E,GAE3B,IAGIq0E,EAHApuB,EAAOjmD,EAAIimD,KACXv/C,EAAW1G,EAAIq0E,OACfv2B,EAAQ39C,KAAK29C,MAcjB,OAZY,MAARmI,GAAgBnI,EAAMgO,aAAehO,EAAMoU,QAAQjM,GACnDouB,EAASl0E,KAAK61D,aAAa/P,EAAMv/C,IAAavG,KAAKqI,IAE9C9B,IAAUA,EAAW1G,EAAI0G,UACzBA,GAAoB,MAARu/C,IAGbv/C,EAAW,UAAYu/C,EAAO,MAElCouB,EAASl0E,KAAKgjD,SAASz8C,IAGpBvG,KAAKg1E,cAAcd,EAAQ,SACtC,EAEA4B,cAAe,SAASlwE,EAAKsuE,EAAQ/lE,EAAGH,GACpChO,KAAK29C,MAAM2J,WAAW,YACtB,MAAMyuB,EAAW/1E,KAAKq1E,kBAAkBnB,EAAQ/lE,EAAGH,GAEnD+nE,EAASC,kBAAkBpwE,EAAKuI,EAAGH,GACnC+nE,EAASlH,UAAUjpE,EAAKmwE,EAASE,mBAAmB,SAAU,CAAEC,eAAgB,YAChFl2E,KAAK6uE,UAAUjpE,EAAK,CAAEmwE,YAC1B,EAEAI,SAAU,SAASvwE,EAAKuI,EAAGH,GACvB,IAAIzZ,EAAOyL,KAAK6uE,UAAUjpE,GACtBmwE,EAAWxhF,EAAKwhF,SACpB,GAAIA,EACAA,EAASK,YAAYxwE,EAAKuI,EAAGH,OAC1B,CACH,IAAIs1C,EAAQtjD,KAAKsjD,MACb+yB,EAAkB/yB,EAAM3rB,QAAQ0+C,gBAChClxE,EAAgBnF,KAAKs2E,eAAe1wE,GACpC2wE,EAAehiF,EAAKgiF,aACxB,GAAwB,YAApBF,GAEA,GAAIE,IAAiBpxE,GAAiB,GAAEoxE,GAAchuE,SAASpD,GAAgB,YAG/E,GAAIm+C,EAAMurB,UAAUjpE,GAAK4wE,YAAcH,EAAiB,OAE5Dr2E,KAAK81E,cAAclwE,EAAK2wE,EAAcpoE,EAAGH,EAC7C,CACJ,EAEAyoE,YAAa,SAAS7wE,EAAKuI,EAAGH,GAC1B,IACI+nE,EADO/1E,KAAK6uE,UAAUjpE,GACNmwE,SACfA,IACLA,EAASW,UAAU9wE,EAAKuI,EAAGH,GAC3BhO,KAAK29C,MAAMiK,UAAU,YACzB,EAEAsE,uBAAwB,SAAStwB,GAE7B,OAAO57B,KAAK29C,MAAMrrD,YAAY45D,uBAAuBtwB,EACzD,EAEA+6C,kBAAmB,SAAS7tE,EAAMoqB,GAEzB5wB,GAAQ4wB,KACLpqB,aAAgBy7B,WAChB,GAAEz7B,GAAMosB,KAAKhC,GAEb,GAAEpqB,GAAMosB,KAAKhC,GAGzB,EAEA0jD,sBAAuB,SAAS9tE,EAAMoqB,GAElC,IAAI0I,EAAUi7C,EAASzxB,EAAKt+C,EAAGkJ,EAC3B8mE,EAAaC,EAAUC,EAAeC,EACtCC,EAAY,GAChB,MAAMC,EAAW,CAAC,EAClB,IAAKv7C,KAAY1I,EACRA,EAAM3nC,eAAeqwC,KAC1Bu7C,EAAS,GAAEh8C,eAAeS,IAAa1I,EAAM0I,IAGjD,IAAKA,KAAYu7C,EACb,GAAKA,EAAS5rF,eAAeqwC,GAG7B,GAFAi7C,EAAUM,EAASv7C,GACnBwpB,EAAMplD,KAAKksD,uBAAuBtwB,GAE9B,GAAgB,OAAZi7C,EAAkB,CAElB,IAAIO,EAeJ,GAbIA,EADA,GAAWhyB,EAAIjqD,OACCiqD,EAAIjqD,MAAM3P,KAAKwU,KAAM8I,EAAMquE,EAAUn3E,MAErColD,EAAIjqD,OAEnBi8E,GAAiBx2E,GAASwkD,EAAIhyD,OAE/BgkF,EAAgBhyB,EAAIhyD,KAEnBgkF,IAEDA,EAAgBx7C,GAGhBh7B,GAASw2E,IAAkBA,EAAe,CAI1C,GAFAN,IAAgBA,EAAc,CAAC,GAE3BM,KAAiBN,EAAa,SAClCA,EAAYM,GAAiBP,CACjC,MAAO,GAAI7lF,MAAMC,QAAQmmF,IAAkBA,EAAc5lF,OAAS,EAG9D,IADAslF,IAAgBA,EAAc,CAAC,GAC1BhwE,EAAI,EAAGkJ,EAAIonE,EAAc5lF,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAC9C,MAAM80B,EAAWw7C,EAActwE,GAE3B80B,KAAYk7C,IAChBA,EAAYl7C,GAAYi7C,EAC5B,CAIR,MACS,GAAWzxB,EAAIvF,UAAYuF,EAAIvF,QAAQr0D,KAAKwU,KAAM62E,EAAS/tE,EAAMquE,EAAUn3E,OACxEY,GAASwkD,EAAIhyD,OAEb0jF,IAAgBA,EAAc,CAAC,GAC/BA,EAAY1xB,EAAIhyD,KAAOyjF,GAE3BK,EAAUtlF,KAAKgqC,EAAUwpB,KAEzB0xB,IAAgBA,EAAc,CAAC,GAC/BA,EAAYl7C,GAAYi7C,QAIhCC,IAAgBA,EAAc,CAAC,GAC/BA,EAAYl7C,GAAYi7C,EAMhC,IAAK/vE,EAAI,EAAGkJ,EAAIknE,EAAU1lF,OAAQsV,EAAIkJ,EAAGlJ,GAAG,EACxC80B,EAAWs7C,EAAUpwE,GACrBs+C,EAAM8xB,EAAUpwE,EAAE,GAClB+vE,EAAU3jD,EAAM0I,GACZ,GAAWwpB,EAAIhyD,OACf2jF,IAAaA,EAAW,CAAC,GACzBA,EAASn7C,GAAYi7C,GAErB,GAAWzxB,EAAIxnB,YACfo5C,IAAkBA,EAAgB,CAAC,GACnCA,EAAcp7C,GAAYi7C,GAE1B,GAAWzxB,EAAI/zC,UACf4lE,IAAgBA,EAAc,CAAC,GAC/BA,EAAYr7C,GAAYi7C,GAIhC,MAAO,CACHQ,IAAKF,EACLG,OAAQR,EACR1jF,IAAK2jF,EACLn5C,SAAUo5C,EACV3lE,OAAQ4lE,EAEhB,EAEAM,yBAA0B,SAASzuE,EAAMoqB,EAAOktB,EAAS/rC,GAIrD,IAAIunB,EAAUi7C,EAFdxiE,IAAQA,EAAM,CAAC,GAGf,IAAI09D,EAAYD,GAAe5+C,EAAMmkD,KAAO,CAAC,EAAGj3B,GAC5Co3B,EAAYtkD,EAAMokD,QAAU,CAAC,EACjC,IAAK,MAAMG,KAAgBD,EACvBA,EAAUC,GAAgB1F,EAAU0F,GAExC,IAAIV,EAAW7jD,EAAM9/B,IACjB4jF,EAAgB9jD,EAAM0K,SACtBq5C,EAAc/jD,EAAM7hB,OAExB,IAAKuqB,KAAYm7C,EAAU,CACvBF,EAAU9E,EAAUn2C,GAKpB,IAAI87C,EAJE13E,KAAKksD,uBAAuBtwB,GAIdxoC,IAAI5H,KAAKwU,KAAM62E,EAASz2B,EAAQh+C,QAAS0G,EAAMipE,EAAW/xE,MAC1E9N,GAASwlF,GACT,GAAOF,EAAWE,QACGjlF,IAAdilF,IACPF,EAAU57C,GAAY87C,EAE9B,CAEA,GAAI5uE,aAAgBm3D,YAIhBjgE,KAAK22E,kBAAkB7tE,EAAM0uE,OAJjC,CASA,IAUIplE,EAAIC,EAAIslE,EAVRC,EAAgBJ,EAAUxhD,UAC1Bi6C,EAAa,GAAE95C,wBAAwByhD,GACvCC,EAAelpE,GAAMshE,EAAW/lE,EAAG+lE,EAAW99D,GASlD,GARIylE,IACAJ,EAAY,GAAKA,EAAW,aAC5BvH,EAAW/lE,EAAI+lE,EAAW99D,EAAI,GAM9B6kE,GAAiBC,EAAa,CAC9B,IAAIa,EAAY93E,KAAK+3E,aAAajvE,EAAMuL,EAAI2jE,cAC5C5lE,EAAK0lE,EAAU1lE,GACfC,EAAKylE,EAAUzlE,EACnB,CAEA,IAAI4lE,GAAa,EACjB,IAAKr8C,KAAYo7C,EACbH,EAAU9E,EAAUn2C,IAMpB+7C,EALM33E,KAAKksD,uBAAuBtwB,GAKhBgC,SAASpyC,KAAKwU,KAAM62E,EAASz2B,EAAQh+C,QAAS0G,EAAMipE,EAAW/xE,SAE7E63E,EAAaxmE,OAAO1C,GAAMgpE,GAAaprE,MAAM6F,EAAIC,IACjD4lE,IAAeA,GAAa,IAMpCj4E,KAAK22E,kBAAkB7tE,EAAM0uE,GAE7B,IAAIU,GAAW,EACf,GAAIjB,EAAa,CAEb,IAAIkB,EAAmBn4E,KAAKm0E,oBAAoBrrE,GAChD,GAAIqvE,EAAiB3nE,MAAQ,GAAK2nE,EAAiB1nE,OAAS,EAAG,CAC3D,IAAIi1C,EAAW,GAAEjuB,cAAc0gD,EAAkBlI,GAAY1jE,MAAM,EAAI6F,EAAI,EAAIC,GAC/E,IAAKupB,KAAYq7C,EACbJ,EAAU9E,EAAUn2C,IAKpB+7C,EAJM33E,KAAKksD,uBAAuBtwB,GAIhBvqB,OAAO7lB,KAAKwU,KAAM62E,EAASnxB,EAAU58C,EAAMipE,EAAW/xE,SAEpE63E,EAAaxmE,OAAO1C,GAAMgpE,GAAaprE,MAAM6F,EAAIC,IACjD6lE,IAAaA,GAAW,GAGpC,CACJ,OAGsBzlF,IAAlBmlF,GAA+BK,GAAcC,KAE7CL,EAAaxrE,MAAM,GACnB4jE,EAAW/lE,EAAI2tE,EAAa1pE,EAC5B8hE,EAAW99D,EAAI0lE,EAAa7pE,EAC5BlF,EAAKyxB,aAAa,YAAa,GAAElE,wBAAwB45C,IAlE7D,CAqEJ,EAEA8H,aAAc,SAASjvE,EAAMkvE,GAGzB,IAAI5lE,EAAIC,EACR,GAAI2lE,GAAgBA,EAAazvE,SAASO,GAAO,CAC7C,IAAIyD,EAAQyrE,EAAazrE,QACzB6F,EAAK,EAAI7F,EAAM6F,GACfC,EAAK,EAAI9F,EAAM8F,EACnB,MACID,EAAK,EACLC,EAAK,EAGT,MAAO,CAAED,GAAIA,EAAIC,GAAIA,EACzB,EAEA+gE,gBAAiB,WACbpzE,KAAKwyD,QAAU,CAAC,CACpB,EAEA4lB,eAAgB,SAAStvE,GACrB,MAAMwsB,EAAKxsB,EAAKwsB,GACXA,UACEt1B,KAAKwyD,QAAQl9B,EACxB,EAEA+iD,UAAW,SAASnE,GAEhB,IAAI1hB,EAAUxyD,KAAKwyD,QAEnB,IAAKA,EAAS,MAAO,CAAC,EACtB,IAAIl9B,EAAK,GAAE1B,SAASsgD,GAChBvoF,EAAQ6mE,EAAQl9B,GAEpB,OADK3pC,IAAOA,EAAQ6mE,EAAQl9B,GAAM,CAAC,GAC5B3pC,CACX,EAEA2sF,YAAa,SAASpE,GAElB,IAAI1hB,EAAUxyD,KAAKq4E,UAAUnE,GAE7B,OADK1hB,EAAQj+D,OAAMi+D,EAAQj+D,KAAO,CAAC,GAC5Bi+D,EAAQj+D,IACnB,EAEA4/E,oBAAqB,SAASD,GAE1B,IAAI1hB,EAAUxyD,KAAKq4E,UAAUnE,GAE7B,YAD6BzhF,IAAzB+/D,EAAQ+lB,eAA4B/lB,EAAQ+lB,aAAe,GAAErE,GAAQ98C,WAClE,IAAItoB,GAAK0jD,EAAQ+lB,aAC5B,EAEAxI,cAAe,SAASmE,GAEpB,MAAM1hB,EAAUxyD,KAAKq4E,UAAUnE,GAC/B,QAA6BzhF,IAAzB+/D,EAAQ4hB,aAA4B,CACpC,MAAM,cAAElf,EAAa,GAAE7sD,GAAOrI,KAC9B,IAAIkF,EAEAA,EADAgwD,GAAiBA,EAAc3sD,SAAS2rE,GAC/Bhf,EAEA7sD,EAEbmqD,EAAQ4hB,aAAe,GAAEF,GAAQ3+C,sBAAsBrwB,EAC3D,CACA,OAAO,GAAE6wB,gBAAgBy8B,EAAQ4hB,aACrC,EAEAoE,aAAc,SAAStE,GAEnB,IAAI1hB,EAAUxyD,KAAKq4E,UAAUnE,GAE7B,YAD8BzhF,IAA1B+/D,EAAQimB,gBAA6BjmB,EAAQimB,cAAgB,GAAEvE,GAAQzzC,mBACpE+xB,EAAQimB,cAAcr2E,OACjC,EAEAs2E,iBAAkB,SAAS5vE,GACvB,OAAO9I,KAAK29C,MAAMa,YAAc11C,GAAQA,IAAS9I,KAAKqI,GAC1D,EAEAswE,oBAAqB,SAASzlD,EAAOnc,EAAM6hE,EAAernC,GAEtD,IAAIzqC,EAAGkJ,EAAGwnE,EAAWqB,EACjBC,EAAa,CAAC,EACdC,EAAW,GACf,IAAK,IAAIxyE,KAAY2sB,EACjB,GAAKA,EAAM3nC,eAAegb,KAC1BixE,EAAYtkD,EAAM3sB,GACbnK,GAAco7E,IAAnB,CACA,IAAIx3B,EAAW44B,EAAcryE,GAAYvG,KAAK41D,eAAervD,EAAUwQ,EAAMw6B,GAC7E,IAAKzqC,EAAI,EAAGkJ,EAAIgwC,EAASxuD,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CACzC,IAAIgC,EAAOk3C,EAASl5C,GACpB+xE,EAAS,GAAEjlD,SAAS9qB,GAGpB,IAAIkwE,EAAUznC,GAAaA,EAAUhrC,KAAcuC,EAC/CmwE,EAAgBH,EAAWD,GAC/B,GAAII,EAAe,CAGVA,EAAcnnF,QACfinF,EAASnnF,KAAKinF,GACdI,EAAcnnF,OAAQ,EACtBmnF,EAAcv9C,WAAa,CAACu9C,EAAcv9C,YAC1Cu9C,EAAcC,eAAiB,CAACD,EAAcC,iBAElD,IAAIx9C,EAAau9C,EAAcv9C,WAC3Bw9C,EAAiBD,EAAcC,eACnC,GAAIF,EAEAt9C,EAAWze,QAAQu6D,GACnB0B,EAAej8D,SAAS,OACrB,CAEH,IAAIk8D,EAAY33E,GAAY03E,EAAgBlpE,GAC5C0rB,EAAWl7B,OAAO24E,EAAW,EAAG3B,GAChC0B,EAAe14E,OAAO24E,EAAW,EAAGnpE,EACxC,CACJ,MACI8oE,EAAWD,GAAU,CACjBn9C,WAAY87C,EACZ0B,eAAgBF,GAAU,EAAIhpE,EAC9BlH,KAAMA,EACNhX,OAAO,EAGnB,CAtCuC,CAyC3C,IAAKgV,EAAI,EAAGkJ,EAAI+oE,EAASvnF,OAAQsV,EAAIkJ,EAAGlJ,KAEpC0wE,EAAYsB,EADZD,EAASE,EAASjyE,KAER40B,WAAax6B,GAAM,CAAC,KAAMs2E,EAAU97C,WAAWic,WAG7D,OAAOmhC,CACX,EAEAxC,eAAgB,SAAS1wE,EAAKyO,EAAM,CAAC,GACjC,MAAM,OAAEnP,EAAM,KAAE/S,EAAI,QAAEinF,EAAU,EAAC,QAAEC,EAAU,GAAMzzE,EACnD,OAEIyO,EAAIilE,WAGK,cAATnnF,GAAiC,aAATA,GAEvB,cAAeyT,GAAOV,EAAOq0E,kBAAkB3zE,EAAI4zE,WAE7CrzE,SAASszE,iBAAiBL,EAASC,GAGvCn0E,CACX,EAIAkyD,2BAA4B,SAASmd,EAAUrhD,EAAO7e,GAElDA,IAAQA,EAAM,CAAC,GACfA,EAAIgjD,WAAahjD,EAAIgjD,SAAWvoD,MAChCuF,EAAIk9B,YAAcl9B,EAAIk9B,UAAYvxC,KAAKuxC,WAOvC,IAII/K,EAAM19B,EAAM0uE,EAAWkC,EAAUC,EAJjCf,EAAgB,CAAC,EACjBgB,EAAY,CAAC,EACbC,EAAgB,GAChBC,EAAmB,GAGnBC,EAAU1lE,EAAI2lE,aACdlB,EAAa94E,KAAK24E,oBAAoBoB,GAAW7mD,EAAOqhD,EAAUqE,EAAevkE,EAAIk9B,WAGrF0oC,EAAgB,EACdj6E,KAAK24E,oBAAoBzlD,EAAOqhD,EAAUqE,EAAevkE,EAAIk9B,WAC7DunC,EAEN,IAAK,IAAID,KAAUC,EAMf,GAJAtB,GADAkC,EAAWZ,EAAWD,IACDn9C,WACrB5yB,EAAO4wE,EAAS5wE,MAChB6wE,EAAiB35E,KAAK42E,sBAAsB9tE,EAAM0uE,IAE9BpkF,KAAQumF,EAAe/7C,UAAa+7C,EAAetoE,QAAWsoE,EAAetC,IAAIjmE,IAI9F,CAEH,IAKI8oE,EALAC,EAAeF,EAAcpB,IAAWoB,EAAcpB,GAAQn9C,WAC9D0+C,EAAeD,QAAmC1nF,IAAlB+kF,EAAUpmE,IACxC+oE,EAAa/oE,IACbomE,EAAUpmE,IAGhB,GAAIgpE,GAEA,KADAF,GAAWtB,EAAcwB,IAAgBp6E,KAAK41D,eAAewkB,EAAa7F,EAAUlgE,EAAIk9B,YAAY,IAEhG,MAAM,IAAIvoC,MAAM,kBAAoBoxE,EAAc,oCAGtDF,EAAU,KAUd,GAPA1zC,EAAO,CACH19B,KAAMA,EACNoxE,QAASA,EACTG,oBAAqBV,EACrBW,cAAeH,GAGfD,EAAS,CAGT,IAAIK,EAAYT,EAAiBpnB,WAAU,SAASlsB,GAChD,OAAOA,EAAK0zC,UAAYpxE,CAC5B,IAEIyxE,GAAa,EACbT,EAAiBt5E,OAAO+5E,EAAW,EAAG/zC,GAEtCszC,EAAiBloF,KAAK40C,EAE9B,MAGIqzC,EAAcjoF,KAAK40C,EAE3B,MA3CIxmC,KAAK22E,kBAAkB7tE,EAAMgpE,GAAe6H,EAAerC,OAAQjjE,EAAIgjD,WA8C/EwiB,EAAcjoF,QAAQkoF,GAEtB,IAAK,IAAIhzE,EAAI,EAAGkJ,EAAI6pE,EAAcroF,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAClD0/B,EAAOqzC,EAAc/yE,GACrBgC,EAAO09B,EAAK19B,KAKZ,MAAM0xE,GAJNN,EAAU1zC,EAAK0zC,SAIa,GAAEtmD,SAASsmD,GAAW,GAClD,IAAI95B,EAAUw5B,EAAUY,GACnBp6B,IAyBDA,EAAUw5B,EAAUY,GAAa,EAC3B,GAAEN,GAAS9iD,QAAQ,CAAElyB,OAAQu1E,GAAsB3xE,EAAMoxE,KACzD7lE,EAAIgjD,UAGV0iB,GAIAJ,EAAiB35E,KAAK42E,sBAAsB9tE,EAAM09B,EAAK8zC,eACvDt6E,KAAK06E,yBAAyBf,EAAgBnzC,EAAK6zC,sBAGnDV,EAAiBnzC,EAAK6zC,oBAG1Br6E,KAAKu3E,yBAAyBzuE,EAAM6wE,EAAgBv5B,EAAS/rC,EACjE,CACJ,EAEAqmE,yBAA0B,SAASf,EAAgBgB,GAE/ChB,EAAevmF,MAAQumF,EAAevmF,IAAM,CAAC,GAC7CumF,EAAe/7C,WAAa+7C,EAAe/7C,SAAW,CAAC,GACvD+7C,EAAetoE,SAAWsoE,EAAetoE,OAAS,CAAC,GAEnD,GAAOsoE,EAAevmF,IAAKunF,EAAiBvnF,KAC5C,GAAOumF,EAAe/7C,SAAU+8C,EAAiB/8C,UACjD,GAAO+7C,EAAetoE,OAAQspE,EAAiBtpE,QAG/C,IAAI2kB,EAAY2jD,EAAerC,QAAUqC,EAAerC,OAAOthD,eAC7CvjC,IAAdujC,GAA2B2kD,EAAiBrD,SAC5CqD,EAAiBrD,OAAOthD,UAAYA,GAExC2jD,EAAerC,OAASqD,EAAiBrD,MAC7C,EAOA,OAAAsD,CAAQC,GACAA,IACJ76E,KAAK86E,aACL5L,GAAgBW,MAAM7vE,MAC1B,EAIA,QAAA+6E,GACI/6E,KAAKg7E,eACL9L,GAAgBjC,QAAQjtE,KAC5B,EAIAsuE,SAAU,WACNtuE,KAAKi7E,cACLj7E,KAAKk7E,oBACT,EAEAC,WAAY,KAEZC,SAAU,SAASjkF,GACf,IAAIkkF,EAAYr7E,KAAKm7E,WACrB,SAAKE,GACAlkF,GACGkkF,EAAUC,YAAcnkF,EACpC,EAEAokF,SAAU,SAASF,GASf,OAPAr7E,KAAKi7E,cAEDI,IACAr7E,KAAKm7E,WAAaE,EAClBA,EAAUG,UAAU,CAAEC,YAAaz7E,OACnCq7E,EAAU9/B,SAASv7C,KAAKsjD,MAAO,cAAetjD,KAAK07E,YAAY3rF,KAAKiQ,QAEjEA,IACX,EAEA,YAAAg7E,GACI,MAAMK,EAAYr7E,KAAKm7E,WAEvB,OADIE,GAAWA,EAAUpO,UAClBjtE,IACX,EAEA,UAAA86E,GACI,MAAMO,EAAYr7E,KAAKm7E,WAGvB,OADIE,IAAcA,EAAUlO,aAAakO,EAAUxL,QAC5C7vE,IACX,EAEA27E,YAAa,SAAStnE,GAElB,IAAIgnE,EAAYr7E,KAAKm7E,WAErB,OADIE,GAAWA,EAAU1oE,OAAO0B,GACzBrU,IACX,EAEAi7E,YAAa,WAET,IAAII,EAAYr7E,KAAKm7E,WAKrB,OAJIE,IACAA,EAAU92E,SACVvE,KAAKm7E,WAAa,MAEfn7E,IACX,EAEA47E,UAAW,WAEP,IAAIP,EAAYr7E,KAAKm7E,WAErB,OADIE,GAAWA,EAAUQ,OAClB77E,IACX,EAEA87E,UAAW,WAEP,IAAIT,EAAYr7E,KAAKm7E,WAErB,OADIE,GAAWA,EAAUU,OAClB/7E,IACX,EAEA07E,YAAa,SAASvyE,GAClB,OAAQA,GACJ,IAAK,SACDnJ,KAAKi7E,cACL,MACJ,IAAK,OACDj7E,KAAK47E,YACL,MACJ,IAAK,OACD57E,KAAK87E,YAGjB,EAEAZ,mBAAoB,WAChBhM,GAAgB3qE,OAAOvE,KAC3B,EAEAg8E,mBAAoB,SAAS3xB,GAAQ,GACjC6kB,GAAgBv8D,OAAO3S,KAAM,KAAMqqD,EACvC,EAEA4xB,sBAAuB,WACnB/M,GAAgBl5C,UAAUh2B,KAC9B,EAKA,yBAAAk8E,CAA0Bt2E,GACtB5F,KAAK6uE,UAAUjpE,EAAK,CAAEu2E,6BAA6B,GACvD,EAEA,6BAAAC,CAA8Bx2E,GAC1B,MAAM,4BAAEu2E,GAA8B,GAAUn8E,KAAK6uE,UAAUjpE,GAC/D,OAAOu2E,CACX,EASAE,gBAAiB,SAASz2E,EAAKuI,EAAGH,GAE9BhO,KAAKgxE,OAAO,uBAAwBprE,EAAKuI,EAAGH,EAChD,EAEAsuE,aAAc,SAAS12E,EAAKuI,EAAGH,GAE3BhO,KAAKgxE,OAAO,oBAAqBprE,EAAKuI,EAAGH,EAC7C,EAEAuuE,YAAa,SAAS32E,EAAKuI,EAAGH,GAE1BhO,KAAKgxE,OAAO,mBAAoBprE,EAAKuI,EAAGH,EAC5C,EAEAwuE,YAAa,SAAS52E,EAAKuI,EAAGH,GAE1B,MAAM,MAAE2vC,GAAU39C,MACZ,MAAEinD,GAAUtJ,EACdsJ,IACAtJ,EAAM2J,WAAW,WACjBtnD,KAAK6uE,UAAUjpE,EAAK,CAAEqhD,WAG1BjnD,KAAKgxE,OAAO,mBAAoBprE,EAAKuI,EAAGH,EAC5C,EAEAooE,YAAa,SAASxwE,EAAKuI,EAAGH,GAE1BhO,KAAKgxE,OAAO,mBAAoBprE,EAAKuI,EAAGH,EAC5C,EAEA0oE,UAAW,SAAS9wE,EAAKuI,EAAGH,GAExB,MAAM,MAAEi5C,GAAUjnD,KAAK6uE,UAAUjpE,GAEjC5F,KAAKgxE,OAAO,iBAAkBprE,EAAKuI,EAAGH,GAElCi5C,GAGAA,EAAMW,UAAU,UAAW,CAAErJ,KAAMv+C,KAAK29C,OAEhD,EAEA8+B,UAAW,SAAS72E,GAEhB5F,KAAKgxE,OAAO,iBAAkBprE,EAClC,EAEA82E,SAAU,SAAS92E,GAEf5F,KAAKgxE,OAAO,gBAAiBprE,EACjC,EAEA+2E,WAAY,SAAS/2E,GAEjB5F,KAAKgxE,OAAO,kBAAmBprE,EACnC,EAEAg3E,WAAY,SAASh3E,GAEjB5F,KAAKgxE,OAAO,kBAAmBprE,EACnC,EAEAi3E,WAAY,SAASj3E,EAAKuI,EAAGH,EAAGgjC,GAE5BhxC,KAAKgxE,OAAO,kBAAmBprE,EAAKuI,EAAGH,EAAGgjC,EAC9C,EAEA8rC,QAAS,SAASl3E,EAAKomE,EAAW79D,EAAGH,GAEjChO,KAAKgxE,OAAOhF,EAAWpmE,EAAKuI,EAAGH,EACnC,EAEA+uE,SAAU,WAGV,EAEAC,sBAAuB,WAGvB,EAEAC,kBAAmB,WAGnB,EAEA,eAAAC,CAAgBt3E,GACZ,MAAM,MAAE09C,EAAK,MAAE3F,GAAU39C,KACzB,GAAIsjD,EAAM65B,UAAW,CAMjB,GAAIx/B,EAAMa,SAAU,CAGhB,MAAMme,EAAgBhf,EAAMwe,mBAC5B,GAAIQ,EAAe,CACf,MAAMygB,EAAa95B,EAAMoI,gBAAgBiR,GACrCygB,IACA95B,EAAM+5B,SAASD,GACf95B,EAAMg6B,oBAAoBF,GAElC,CACA,MAAMxgB,EAAgBjf,EAAMye,mBAC5B,GAAIQ,EAAe,CACf,MAAM2gB,EAAaj6B,EAAMoI,gBAAgBkR,GACrC2gB,IACAj6B,EAAM+5B,SAASE,GACfj6B,EAAMg6B,oBAAoBC,GAElC,CACJ,CAEAj6B,EAAM+5B,SAASr9E,MACfsjD,EAAMg6B,oBAAoBt9E,KAC9B,CACA,MAAMkF,EAASlF,KAAKs2E,eAAe1wE,EAAK,CAAE0zE,WAAW,IAC/C9H,EAAOluB,EAAMmI,SAASvmD,GACxBssE,IAASxxE,OAEbA,KAAK48E,WAAWh3E,GACX4rE,GAELA,EAAKmL,WAAW/2E,GACpB,EAEA43E,iBAAkB,SAAS7xF,GAEvBqU,KAAK23B,QAAQi8C,YAAcjoF,CAC/B,EAEA8xF,eAAgB,SAAShF,EAAeiF,GACpC,OAAO,GAAazxD,OAAOwsD,EAAez4E,KAAKg0E,YAAYh0E,KAAKqI,IAAKq1E,EACzE,EAEAC,aAAc,SAASC,GACnB,OAAOA,EAAa7kE,aAAa/Y,KAAKg0E,YAAYh0E,KAAKqI,IAC3D,EAEAw1E,SAAU,SAASD,EAAcjmD,EAAU,CAAC,GACxC,OAAIA,EAAQ7e,OACD9Y,KAAK29E,aAAaC,GAEtB59E,KAAKy9E,eAAeG,EAC/B,EAEAE,UAAW,SAAS9sE,EAAO2mB,GACvB,OAAO33B,KAAKg0E,YAAYh0E,KAAKqI,IAAIkI,cAAcS,EAAO2mB,EAC1D,GAED,CAEComD,MAvyCU,CACVC,MAAO,SAwyCPC,aAAc/L,GAEdgM,0BAA2B,SAASnL,GAChC,OAAO7xE,GAAM,CAAC,EAAGzP,GAAOuO,KAAK1U,UAAW,0BAA2BynF,GAAwB,SAASp3E,EAAGC,GACnG,GAAKD,GAAMC,EAGX,MAFiB,iBAAND,IAAgBA,EAAI,CAACA,IACf,iBAANC,IAAgBA,EAAI,CAACA,IAC5B5K,MAAMC,QAAQ0K,IAAM3K,MAAMC,QAAQ2K,GAAWsG,GAAKvG,EAAEgN,OAAO/M,SAA/D,CACJ,GACJ,EAEAo2E,cAAa,KAcjB,SAASyI,GAAsB0D,EAAOC,GAClC,IAAIhiD,EAAS+hD,EACb,EAAG,CACC,GAAI/hD,EAAO7zB,SAAS61E,GAAQ,OAAOhiD,EACnCA,EAASA,EAAOpwB,UACpB,OAASowB,GACT,OAAO,IACX,CAhBApxC,OAAOC,eAAeunF,GAASlnF,UAAW,kBAAmB,CACzD,GAAAH,GACI,MAAMkzF,EAAWr+E,KAAK29C,MAAMk2B,gBAC5B,YAAiBphF,IAAb4rF,GAA+BA,CAEvC,ICv1CJ,MAAM,GAAQ,CACVL,MAAOxL,GAASuL,MAAMC,MACtBM,OAAQ,SACRC,UAAW,YACXC,OAAQ,SACRC,MAAO,QACPC,OAAQ,SACRC,OAAQ,UAGNC,GACI,OADJA,GAEM,SAKCC,GAAcrM,GAAS3yD,OAAO,CAKvC00C,aAAc,WAEd,EAMAC,aAAc,WAEd,EAEAh6B,UAAW,WAEP,IAAIi4C,EAAaD,GAASlnF,UAAUkvC,UAAUr5B,MAAMnB,MAAM1P,MAAM,KAIhE,OAFAmiF,EAAW7gF,KAAK,WAET6gF,EAAW3jF,KAAK,IAC3B,EAEAqvD,WAAY,WAERq0B,GAASlnF,UAAU6yD,WAAWh9C,MAAMnB,KAAMpB,WAE1CoB,KAAKyxD,kBACT,EAEAshB,uBAAwB,CACpB,MAAS,CAAC,GAAMuL,QAChB,SAAY,CAAC,GAAMC,UAAW,GAAMP,OACpC,KAAQ,CAAC,GAAMQ,OAAQ,GAAMC,MAAO,GAAMT,OAC1C,MAAS,CAAC,GAAMU,OAAQ,GAAMV,OAC9B,OAAU,CAAC,GAAMW,QACjB,MAAS,CAAC,GAAMF,QAGpBzL,SAAU,CAAC,GAAM2L,QAEjBhS,gBAAiB,EAEjBoB,cAAe,SAASliB,EAAMx3C,GAE1B,MAAM,gBAAEw/D,GAAoB7zE,KACxBA,KAAKizE,QAAQpnB,EAAM,GAAM4yB,SACzBz+E,KAAKu0D,eACLv0D,KAAKq0D,oBAET,IAAI4nB,GAAwB,EAC5B,GAAIj8E,KAAKizE,QAAQpnB,EAAM,GAAM8yB,QACzB3+E,KAAKyrE,SACLzrE,KAAK27E,YAAYtnE,GACjBrU,KAAKg8E,oBAAmB,GACxBC,GAAwB,EACxBpwB,EAAO7rD,KAAKmzE,WAAWtnB,EAAM,CAAC,GAAM8yB,OAAQ,GAAML,OAAQ,GAAME,OAAQ,GAAMD,UAAW,GAAMG,OAAQ,GAAMD,MAAO,GAAMT,YACvH,CACH,IAAIhC,GAAqB,EAGrBh8E,KAAKizE,QAAQpnB,EAAM,GAAM2yB,UACzBx+E,KAAKm4D,OAAO9jD,GACZ2nE,GAAqB,EAErBnwB,EAAO7rD,KAAKmzE,WAAWtnB,EAAM,CAAC,GAAM2yB,OAAQ,GAAMF,SAC9CzK,IAEAhoB,EAAO7rD,KAAKmzE,WAAWtnB,EAAM,GAAM4yB,SAGvCz+E,KAAKizE,QAAQpnB,EAAM,GAAMyyB,UACzBt+E,KAAK2S,OAAO3S,KAAK29C,MAAO,KAAMtpC,GAC9Bw3C,EAAO7rD,KAAKmzE,WAAWtnB,EAAM,GAAMyyB,QACnCtC,GAAqB,EACjBnI,IAEAhoB,EAAO7rD,KAAKmzE,WAAWtnB,EAAM,GAAM4yB,SAGvCz+E,KAAKizE,QAAQpnB,EAAM,GAAM0yB,aACzBv+E,KAAK6S,YACLg5C,EAAO7rD,KAAKmzE,WAAWtnB,EAAM,GAAM0yB,WACnCtC,GAAwB,GAExBj8E,KAAKizE,QAAQpnB,EAAM,GAAM6yB,UACzB1+E,KAAK+R,SACL85C,EAAO7rD,KAAKmzE,WAAWtnB,EAAM,GAAM6yB,QACnCzC,GAAwB,GAExBj8E,KAAKizE,QAAQpnB,EAAM,GAAM4yB,SACzBz+E,KAAKw0D,eACLwnB,GAAqB,EACrBnwB,EAAO7rD,KAAKmzE,WAAWtnB,EAAM,GAAM4yB,QAGnCzC,GACAh8E,KAAKg8E,oBAAmB,EAEhC,CAWA,OATIC,GACAj8E,KAAKi8E,wBAGLj8E,KAAKizE,QAAQpnB,EAAM,GAAMmyB,SACzBh+E,KAAK27E,YAAYtnE,GACjBw3C,EAAO7rD,KAAKmzE,WAAWtnB,EAAM,GAAMmyB,QAGhCnyB,CACX,EAKA4F,iBAAkB,WAElB,EAEA9+C,OAAQ,SAASmtC,EAAGg/B,GAEhB9+E,KAAKozE,kBAGL,MAAM,gBAAES,GAAoB7zE,KACxB6zE,GAAiB7zE,KAAKu0D,eAE1B,IAAI5W,EAAQ39C,KAAK29C,MACbohC,EAAaphC,EAAMzoB,OACvBl1B,KAAKo3D,2BAA2Bp3D,KAAKqI,GAAI02E,EAAY,CACjD1nB,SAAU,IAAIvoD,GAAK6uC,EAAMnmD,QACzB+5C,UAAWvxC,KAAKuxC,UAChBymC,aAAch4E,KAAKg4E,aACnB9iB,cAAel1D,KAAKk1D,cAEpB8kB,aAAe8E,IAAuBC,EAAc,KAAOD,IAG3DjL,GACA7zE,KAAKw0D,cAEb,EAEAwqB,kBAAmB,YACnBC,iBAAkB,WAClBjH,aAAc,KACd9iB,cAAe,KAIfgqB,aAAc,WAEV,IAAI3nB,EAAUv3D,KAAK29C,MACfuT,EAASqG,EAAQpsE,IAAI,WAAaosE,EAAQrG,OAC9C,IAAKA,EAAQ,MAAM,IAAIloD,MAAM,oCAC7B,GAAIhY,MAAMC,QAAQigE,GAAS,OAAOlxD,KAAKm/E,iBAAiBjuB,GACxD,GAAsB,iBAAXA,EAAqB,OAAOlxD,KAAKo/E,mBAAmBluB,GAC/D,MAAM,IAAIloD,MAAM,kCACpB,EAEAm2E,iBAAkB,SAASjuB,GAEvB,IAAIl4B,EAAMh5B,KAAKqxC,aAAa6f,EAAQlxD,KAAKqI,IACrCkpC,EAAYvxC,KAAKuxC,UAAYvY,EAAIuY,UACrCvxC,KAAKk1D,cAAgB,GAAE3jB,EAAUvxC,KAAKg/E,qBAAuB,KAC7Dh/E,KAAKg4E,aAAe,GAAEzmC,EAAUvxC,KAAKi/E,oBAAsB,KAE3Dj/E,KAAKi5B,IAAInF,OAAOkF,EAAI0Y,SACxB,EAEA0tC,mBAAoB,SAASluB,GAEzB,IAAIj4B,EAAMj5B,KAAKi5B,IACfA,EAAInF,OAAO,GAAEo9B,IAEblxD,KAAKk1D,cAAgBj8B,EAAIyD,QAAQ,cACjC18B,KAAKg4E,aAAe/+C,EAAIyD,QAAQ,cAEhB18B,KAAKuxC,UAAY,CAAC,GACxBvxC,KAAKuG,UAAYvG,KAAKqI,EACpC,EAEAojE,OAAQ,WAmBJ,OAjBAzrE,KAAKi5B,IAAIH,QACT94B,KAAKk/E,eACDl/E,KAAKg4E,cAGLh4E,KAAK2S,SAET3S,KAAKm4D,SACDn4D,KAAKk1D,eAGLl1D,KAAK+R,SACL/R,KAAK6S,aAEL7S,KAAKq/E,uBAEJr/E,KAAK6zE,iBAAiB7zE,KAAKw0D,eACzBx0D,IACX,EAEAm4D,OAAQ,SAAS9jD,GAEb,GAAIrU,KAAKg4E,aAAc,OAAOh4E,KAAKs/E,SAASjrE,GACxCrU,KAAK29C,MAAMjiB,WAAW5uB,OAAO9M,KAAK+R,SACtC/R,KAAK2S,QACT,EAEAE,UAAW,WAEP,GAAI7S,KAAKk1D,cAAe,OAAOl1D,KAAKu/E,cACpCv/E,KAAKq/E,sBACT,EAEAttE,OAAQ,WAEJ,GAAI/R,KAAKk1D,cAKL,OAJAl1D,KAAKw/E,gBAGLx/E,KAAK2S,SAGT3S,KAAKq/E,sBACT,EAEAA,qBAAsB,WAElB,IAAInyB,EAAiBltD,KAAKy/E,qBACtBC,EAAe1/E,KAAK2/E,kBACpBD,IAAcxyB,GAAkB,IAAMwyB,GAC1C1/E,KAAKi5B,IAAI/D,KAAK,YAAag4B,EAC/B,EAEAuyB,mBAAoB,WAEhB,MAAM,EAAEtxE,EAAC,EAAEH,GAAMhO,KAAK29C,MAAM/f,WAC5B,MAAO,aAAazvB,KAAKH,IAC7B,EAEA2xE,gBAAiB,WAEb,MAAM7yE,EAAQ9M,KAAK29C,MAAM7wC,QACzB,IAAKA,EAAO,OAAO,KACnB,MAAM,MAAE0D,EAAK,OAAEC,GAAWzQ,KAAK29C,MAAMnmD,OACrC,MAAO,UAAUsV,KAAS0D,EAAQ,KAAKC,EAAS,IACpD,EAKA+uE,SAAU,WAENx/E,KAAKk1D,cAAchgC,KAAK,YAAal1B,KAAK2/E,kBAC9C,EAEAJ,YAAa,WAETv/E,KAAKi5B,IAAI/D,KAAK,YAAal1B,KAAKy/E,qBACpC,EAEAH,SAAU,SAASjrE,GAEf,IAAIspC,EAAQ39C,KAAK29C,MACb7wC,EAAQ6wC,EAAM7wC,QACdtV,EAAOmmD,EAAMnmD,OACbooF,EAAW5/E,KAAKg4E,aAKhBpgD,GAAY,EACZgoD,EAAS92E,KAAKjB,qBAAqB,QAAQrW,OAAS,IAGpDomC,GAAY,GAEhB,IAAIioD,EAAeD,EAASxoD,QAAQ,CAAEQ,UAAWA,IAI7CxlB,EAAM5a,EAAKgZ,OAASqvE,EAAarvE,OAAS,GAC1C6B,EAAM7a,EAAKiZ,QAAUovE,EAAapvE,QAAU,GAChDmvE,EAAS1qD,KAAK,YAAa,SAAW9iB,EAAK,IAAMC,EAAK,KAWtD,IAAIytE,EAAY9/E,KAAKk1D,cACjBh0B,EAAW4+C,GAAaA,EAAU5qD,KAAK,aAC3C,GAAIgM,EAAU,CAEV4+C,EAAU5qD,KAAK,YAAagM,EAAW,YAAep0B,EAAS,IAAOtV,EAAKgZ,MAAQ,EAAK,IAAOhZ,EAAKiZ,OAAS,EAAK,KAClH,IAAIsvE,EAAgBH,EAASxoD,QAAQ,CAAElyB,OAAQlF,KAAKsjD,MAAMjF,QAG1DV,EAAMvqD,IAAI,WAAY,CAAE+a,EAAG4xE,EAAc5xE,EAAGH,EAAG+xE,EAAc/xE,GAAK,GAAO,CAAEulE,eAAe,GAAQl/D,IAClGrU,KAAK6S,YACL7S,KAAK+R,QACT,CAIA/R,KAAK2S,QACT,EAKAqtE,iBAAkB,SAASzrF,EAAO,CAAC,GAE/B,MAAMgjE,EAAUhjE,EAAKopD,OAAS39C,KAAK29C,MAE7BsJ,GADQ1yD,EAAK+uD,OAAStjD,KAAKsjD,OACb3F,MAEdsiC,EAAkB1rF,EAAK0rF,gBAAkB,CAAC,EAC1Cv4B,EAAgB6P,EAAQ5P,iBAAiB,CAAEI,MAAM,IACjDm4B,EAAiBj5B,EAAMC,kBAAkBqQ,EAAS,CAAExP,MAAM,EAAMsf,iBAAiB,IAIvF,CACI9P,KACG7P,KACAw4B,GACLvoF,SAAQ4mD,GAAQ0hC,EAAgB1hC,EAAKjpB,IAAMipB,EAAK7iB,WAAWnQ,IAE7DgsC,EAAQjQ,WAAW,YAGnBiQ,EAAQ1P,QAAQ,CAAEE,MAAM,EAAMytB,IAAI,IAIlC,MAAM2K,EAAOl5B,EAAMsf,cAAcviE,QAAO,CAACuJ,EAAKgxC,IAASx8C,KAAKwL,IAAIA,EAAKgxC,EAAK7iB,WAAWnQ,GAAK,IAAI,GAK9F20D,EAAevoF,SAASyvD,IAChBA,EAAK1rB,WAAWnQ,GAAK40D,GACrB/4B,EAAKh0D,IAAI,IAAK+sF,EAAO,EAAG,CAAE3K,IAAI,GAClC,IAGJje,EAAQ3P,UAAU,YAGlB,MAAMmB,EAAWwO,EAAQn7B,SACrB2sB,GACe9B,EAAM+B,QAAQD,GACtBtB,QAAQ8P,EAAS,CAAEie,IAAI,IAC9BjhF,EAAK6rF,gBAAkBr3B,GAEvBx0D,EAAK6rF,gBAAkB,IAE/B,EAEAC,iBAAkB,SAAS9rF,EAAO,CAAC,EAAGqR,EAAKuI,EAAGH,GAE1C,MAAM2vC,EAAQppD,EAAKopD,OAAS39C,KAAK29C,MAC3B2F,EAAQ/uD,EAAK+uD,OAAStjD,KAAKsjD,MAC3B2D,EAAQ3D,EAAM3F,OACd,aAAE2iC,EAAY,gBAAEC,EAAe,kBAAEC,GAAsBl9B,EAAM3rB,QAEnE,IAAI8oD,EAEAA,EADA,GAAWH,GACE59E,GAAQ49E,EAAa90F,KAAKy7D,EAAOjnD,KAAM4F,EAAKuI,EAAGH,IACpC,YAAjBsyE,EACMr5B,EAAM6hB,oBAAoB,CAAE36D,IAAGH,MAE/Bi5C,EAAMsiB,yBAAyB5rB,EAAO,CAAEssB,SAAUqW,IAGnEG,EAAaA,EAAW1sF,QAAQsU,GACpBA,aAAc89C,IAAUxI,EAAMroB,KAAOjtB,EAAGitB,KAAQjtB,EAAGwgD,aAAalL,KAGxE4iC,IAEAE,EAAaA,EAAW3lF,OAAO,IAGnC,IAAI4lF,EAAmB,KACvB,MAAMC,EAAoBpsF,EAAKqsF,mBAG/B,IAAK,IAAI95E,EAAI25E,EAAWjvF,OAAS,EAAGsV,GAAK,EAAGA,IAAK,CAC7C,MAAM+5E,EAAYJ,EAAW35E,GAC7B,GAAI65E,GAAqBA,EAAkBhjC,MAAMroB,IAAMurD,EAAUvrD,GAAI,CAEjEorD,EAAmBC,EACnB,KACJ,CAAO,CACH,MAAMnP,EAAOqP,EAAUp1B,SAASnI,GAChC,IAAK,GAAWk9B,IAAsBA,EAAkBh1F,KAAK83D,EAAOtjD,KAAMwxE,GAAO,CAE7EkP,EAAmBlP,EACnB,KACJ,CACJ,CACJ,CAEIkP,GAAoBA,GAAoBC,IAExC3gF,KAAK8gF,eAAevsF,GACpBA,EAAKqsF,mBAAqBF,EAAiBznC,UACvCynC,EAAiB1L,cAAc,KAAM,aACrC,CAAEP,WAAW,MAIhBiM,GAAoBC,GAErB3gF,KAAK8gF,eAAevsF,EAE5B,EAEAusF,eAAgB,SAASvsF,GAErBA,IAASA,EAAO,CAAC,GAEjB,IAAIwsF,EAAgBxsF,EAAKqsF,mBACrBG,IAEAA,EAAchQ,YACVgQ,EAAc/L,cAAc,KAAM,aAClC,CAAEP,WAAW,IAEjBlgF,EAAKqsF,mBAAqB,KAElC,EAEAI,kBAAmB,SAASzsF,EAAO,CAAC,GAEhC,MAAMwsF,EAAgBxsF,EAAKqsF,mBACrBrpB,EAAUhjE,EAAKopD,OAAS39C,KAAK29C,MAC7B2F,EAAQ/uD,EAAK+uD,OAAStjD,KAAKsjD,MAEjC,GAAIy9B,EAGAA,EAAcpjC,MAAMgB,MAAM4Y,EAAS,CAAEie,IAAI,IACzCuL,EAAchQ,YAAYgQ,EAAc/L,cAAc,KAAM,aAAc,CAAEP,WAAW,IAEvFlgF,EAAKqsF,mBAAqB,SAEvB,CAEH,MAAM,oBAAEK,GAAwB39B,EAAM3rB,SAChC,gBAAEyoD,GAAoB7rF,EAI5B,GACI6rF,GAC+B,mBAAxBa,IACNA,EAAoBz1F,KAAK83D,EAAOtjD,MAGjC,YADAA,KAAKkhF,iBAAiB3sF,EAG9B,CAEA+uD,EAAM3F,MAAMuJ,kBAAkBqQ,EAAS,CAAExP,MAAM,IAAQpwD,SAAQyvD,IAC3DA,EAAKoB,SAAS,CAAEgtB,IAAI,GAAO,GAEnC,EAEA0L,iBAAkB,SAAS3sF,GACvB,MAAM,MAAEopD,EAAK,eAAEu4B,EAAiB,UAAa3hF,EACvCgjE,EAAU5Z,GAAS39C,KAAK29C,MAExBsJ,GADQ1yD,EAAK+uD,OAAStjD,KAAKsjD,OACb3F,MACpB,OAAQu4B,GACJ,IAAK,SACD3e,EAAQhzD,OAAO,CAAEixE,IAAI,IACrB,MAEJ,IAAK,SAAU,CACX,MAAM,gBAAE4K,EAAe,gBAAEe,EAAe,gBAAElB,GAAoB1rF,EAE9D,GAAI4sF,EAAiB,CACjB,MAAM,EAAEhzE,EAAC,EAAEH,GAAMmzE,EACjB5pB,EAAQ35B,SAASzvB,EAAGH,EAAG,CAAE+5C,MAAM,EAAMytB,IAAI,GAC7C,CAEIyK,GACAj1F,OAAO0F,KAAKuvF,GAAiBtoF,SAAQ29B,IACjC,MAAMipB,EAAO0I,EAAM+B,QAAQ1zB,GACvBipB,GACAA,EAAKnrD,IAAI,IAAK6sF,EAAgB3qD,GAAK,CAAEkgD,IAAI,GAC7C,IAIR,MAAMp5C,EAAS6qB,EAAM+B,QAAQo3B,GACzBhkD,GACAA,EAAOuiB,MAAM4Y,EAAS,CAAEie,IAAI,IAEhC,KACJ,EAER,EAEA4L,oBAAqB,SAASx7E,GAC1B,MAAM,mBAAEg7E,EAAqB,MAAS5gF,KAAK6uE,UAAUjpE,GACrD,OAAOg7E,CACX,EAEAS,iBAAkB,WAMd,IAJA,IAAI7P,EAAOxxE,KACP29C,EAAQ6zB,EAAK7zB,MACb2F,EAAQkuB,EAAKluB,MAEVkuB,IACC7zB,EAAMa,UADD,CAET,IAAKb,EAAM+K,cAAgB8oB,EAAKkC,IAAI,kBAAmB,OAAOlC,EAC9D7zB,EAAQA,EAAM6J,gBACdgqB,EAAOluB,EAAMoI,gBAAgB/N,EACjC,CAEA,OAAO,IACX,EAEAq3B,cAAe,SAAS3sE,EAAIlW,GACxBkW,IAAOA,EAAKrI,KAAKqI,IACjB,MAAM4pC,EAAe5pC,EAAGszB,aAAa,GAAGxpC,cACxC,GAAI8/C,EAAc,CACd,MAAM6T,EAAO9lD,KAAKytE,cAAc,OAAQplE,GACxC,GAAIy9C,EAAM,CACN,MAAMw7B,EAAgBthF,KAAK61D,aAAa/P,EAAM7T,GAC9C,GAAIqvC,EAAe,OAAOA,CAC9B,KAAO,CACH,MAAMrM,EAAYj1E,KAAKgjD,SAAS/Q,GAChC,GAAIgjC,EAAW,OAAOA,CAC1B,CACJ,CACA,OAAO5sE,CACX,EAKA,iBAAA2tE,CAAkBpwE,EAAKuI,EAAGH,GACtBwkE,GAASlnF,UAAUkxF,YAAYhxF,KAAKwU,KAAM4F,EAAKuI,EAAGH,GAClDhO,KAAKgxE,OAAO,sBAAuBprE,EAAKuI,EAAGH,EAC/C,EAEA,iBAAAuzE,CAAkB37E,EAAKuI,EAAGH,GACtBwkE,GAASlnF,UAAU8qF,YAAY5qF,KAAKwU,KAAM4F,EAAKuI,EAAGH,GAClDhO,KAAKgxE,OAAO,sBAAuBprE,EAAKuI,EAAGH,EAC/C,EAEA,eAAAwzE,CAAgB57E,EAAKuI,EAAGH,GACpBhO,KAAKgxE,OAAO,oBAAqBprE,EAAKuI,EAAGH,GACzCwkE,GAASlnF,UAAUorF,UAAUlrF,KAAKwU,KAAM4F,EAAKuI,EAAGH,EACpD,EAEAquE,gBAAiB,SAASz2E,EAAKuI,EAAGH,GAE9BwkE,GAASlnF,UAAU+wF,gBAAgBl7E,MAAMnB,KAAMpB,WAC/CoB,KAAKgxE,OAAO,0BAA2BprE,EAAKuI,EAAGH,EACnD,EAEAsuE,aAAc,SAAS12E,EAAKuI,EAAGH,GAE3BwkE,GAASlnF,UAAUgxF,aAAan7E,MAAMnB,KAAMpB,WAC5CoB,KAAKgxE,OAAO,uBAAwBprE,EAAKuI,EAAGH,EAChD,EAEAuuE,YAAa,SAAS32E,EAAKuI,EAAGH,GAE1BwkE,GAASlnF,UAAUixF,YAAYp7E,MAAMnB,KAAMpB,WAC3CoB,KAAKgxE,OAAO,sBAAuBprE,EAAKuI,EAAGH,EAC/C,EAEAwuE,YAAa,SAAS52E,EAAKuI,EAAGH,GAE1BhO,KAAKg2E,kBAAkBpwE,EAAKuI,EAAGH,GAC/BhO,KAAKyhF,UAAU77E,EAAKuI,EAAGH,EAC3B,EAEAooE,YAAa,SAASxwE,EAAKuI,EAAGH,GAE1B,MAAMzZ,EAAOyL,KAAK6uE,UAAUjpE,IACtB,aAAE2wE,EAAY,OAAEmL,EAAM,cAAEC,GAAkBptF,EAMhD,OAJIgiF,GACAv2E,KAAK4hF,kBAAkBh8E,EAAK2wE,EAAcpoE,EAAGH,GAGzC0zE,GACJ,KAAK9C,GACD5+E,KAAK6hF,WAAWj8E,EAAKuI,EAAGH,GACxB,MACJ,KAAK4wE,IACA+C,GAAiB3hF,MAAM8hF,KAAKl8E,EAAKuI,EAAGH,GAEzC,QACI,GAAIzZ,EAAKwtF,qBAAsB,MAC/B/hF,KAAKuhF,kBAAkB37E,EAAKuI,EAAGH,GAMvChO,KAAK6uE,UAAUjpE,EAAKrR,EACxB,EAEAmiF,UAAW,SAAS9wE,EAAKuI,EAAGH,GAExB,MAAMzZ,EAAOyL,KAAK6uE,UAAUjpE,IACtB,aAAE2wE,EAAY,OAAEmL,EAAM,cAAEC,GAAkBptF,EAMhD,OAJIgiF,GACAv2E,KAAKgiF,gBAAgBp8E,EAAK2wE,EAAcpoE,EAAGH,GAGvC0zE,GACJ,KAAK9C,GACD5+E,KAAKiiF,cAAcr8E,EAAKuI,EAAGH,GAC3B,MACJ,KAAK4wE,IACA+C,GAAiB3hF,MAAMkiF,QAAQt8E,EAAKuI,EAAGH,GAE5C,QACI,GAAIzZ,EAAKwtF,qBAAsB,MAC/B/hF,KAAKwhF,gBAAgB57E,EAAKuI,EAAGH,GAGjCuoE,GACAv2E,KAAKmiF,mBAAmBv8E,EAAK2wE,EAAcpoE,EAAGH,GAGlDhO,KAAKk9E,gBAAgBt3E,EACzB,EAEA62E,UAAW,SAAS72E,GAEhB4sE,GAASlnF,UAAUmxF,UAAUt7E,MAAMnB,KAAMpB,WACzCoB,KAAKgxE,OAAO,oBAAqBprE,EACrC,EAEA82E,SAAU,SAAS92E,GAEf4sE,GAASlnF,UAAUoxF,SAASv7E,MAAMnB,KAAMpB,WACxCoB,KAAKgxE,OAAO,mBAAoBprE,EACpC,EAEA+2E,WAAY,SAAS/2E,GAEjB4sE,GAASlnF,UAAUqxF,WAAWx7E,MAAMnB,KAAMpB,WAC1CoB,KAAKgxE,OAAO,qBAAsBprE,EACtC,EAEAg3E,WAAY,SAASh3E,GAEjB4sE,GAASlnF,UAAUsxF,WAAWz7E,MAAMnB,KAAMpB,WAC1CoB,KAAKgxE,OAAO,qBAAsBprE,EACtC,EAEAi3E,WAAY,SAASj3E,EAAKuI,EAAGH,EAAGgjC,GAE5BwhC,GAASlnF,UAAUuxF,WAAW17E,MAAMnB,KAAMpB,WAC1CoB,KAAKgxE,OAAO,qBAAsBprE,EAAKuI,EAAGH,EAAGgjC,EACjD,EAEA+rC,SAAU,SAASn3E,EAAKuI,EAAGH,GAEvB,MAAQ7I,cAAeoxE,GAAiB3wE,EACxC5F,KAAKoiF,kBAAkBx8E,EAAK2wE,EAAcpoE,EAAGH,GAC7ChO,KAAK6uE,UAAUjpE,EAAK,CAAE2wE,iBACtBv2E,KAAKqiF,gBAAgBz8E,EAAKuI,EAAGH,EACjC,EAEAo0E,kBAAmB,SAASx8E,EAAKsuE,EAAQ/lE,EAAGH,GAExChO,KAAKgxE,OAAO,6BAA8BprE,EAAKsuE,EAAQ/lE,EAAGH,EAC9D,EAEA4zE,kBAAmB,SAASh8E,EAAKsuE,EAAQ/lE,EAAGH,GAExChO,KAAKgxE,OAAO,6BAA8BprE,EAAKsuE,EAAQ/lE,EAAGH,EAC9D,EAEAg0E,gBAAiB,SAASp8E,EAAKsuE,EAAQ/lE,EAAGH,GAEtChO,KAAKgxE,OAAO,2BAA4BprE,EAAKsuE,EAAQ/lE,EAAGH,EAC5D,EAEAgvE,sBAAuB,SAASp3E,EAAKsuE,EAAQ/lE,EAAGH,GAE5ChO,KAAKgxE,OAAO,iCAAkCprE,EAAKsuE,EAAQ/lE,EAAGH,EAClE,EAEAivE,kBAAmB,SAASr3E,EAAKsuE,EAAQ/lE,EAAGH,GAExChO,KAAKgxE,OAAO,6BAA8BprE,EAAKsuE,EAAQ/lE,EAAGH,EAC9D,EAIAyzE,UAAW,SAAS77E,EAAKuI,EAAGH,GAExB,GAAIhO,KAAKo8E,8BAA8Bx2E,GAAM,OAE7C,IAAI4rE,EAAOxxE,KAAKqhF,mBAChB,IAAK7P,IAASA,EAAKkC,IAAI,eAAgB,OAEvC1zE,KAAK6uE,UAAUjpE,EAAK,CAChB87E,OAAQ9C,GACR+C,cAAenQ,IAGnB,MAAM5zC,EAAW4zC,EAAK7zB,MAAM/f,WAC5B4zC,EAAK3C,UAAUjpE,EAAK,CAChBu7E,gBAAiBvjD,EACjB0kD,cAAe1kD,EAASz6B,WAAWgL,EAAGH,GACtC4pD,eAAgB53D,KAAKsjD,MAAMi/B,kBAAkB/Q,EAAMrjE,EAAGH,IAE9D,EAEAq0E,gBAAiB,SAASz8E,EAAKuI,EAAGH,GAE9B,MAAM,MAAEs1C,GAAUtjD,KACZwiF,EAA8B58E,EAAIH,uBASxC,GARI+8E,GAKAxiF,KAAK6uE,UAAUjpE,EAAK,CAAEm8E,sBAAsB,IAG5C/hF,KAAKo8E,8BAA8Bx2E,KAAS5F,KAAK0zE,IAAI,qBAErD,OAGJ,MAAM,aAAE6C,EAAe3wE,EAAIT,eAAkBnF,KAAK6uE,UAAUjpE,GAC5DA,EAAIC,kBAGCy9C,EAAM3rB,QAAQ8qD,eAAej3F,KAAK83D,EAAOtjD,KAAMu2E,EAAc3wE,IAgB9D09C,EAAM3rB,QAAQ0+C,iBAAmB,GACjCr2E,KAAK81E,cAAclwE,EAAK2wE,EAAcpoE,EAAGH,GAE7ChO,KAAK6uE,UAAUjpE,EAAK,CAAE87E,OAAQ9C,MAlBtB4D,EAGAxiF,KAAKyhF,UAAU77E,EAAKuI,EAAGH,GAMvBhO,KAAKw8E,YAAY52E,EAAKuI,EAAGH,EAUrC,EAIA8zE,KAAM,SAASl8E,EAAKuI,EAAGH,GAEnB,IAAIs1C,EAAQtjD,KAAKsjD,MACbo/B,EAAOp/B,EAAM3rB,QAAQ3qB,SACrBuqD,EAAUv3D,KAAK29C,MACfppD,EAAOyL,KAAK6uE,UAAUjpE,IACtB,cAAE08E,EAAa,eAAE1qB,EAAc,UAAE6c,GAAclgF,EAG/CouF,EAAM51E,GAAWoB,EAAIm0E,EAAcn0E,EAAGu0E,GACtCE,EAAM71E,GAAWiB,EAAIs0E,EAAct0E,EAAG00E,GAE1CnrB,EAAQ35B,SAAS+kD,EAAKC,EAAK,CAAEhrB,iBAAgB7P,MAAM,EAAMytB,IAAI,IAEzDlyB,EAAM3rB,QAAQkrD,gBACTpO,IAIDz0E,KAAKggF,iBAAiBzrF,GACtBkgF,GAAY,GAEhBz0E,KAAKqgF,iBAAiB9rF,EAAMqR,EAAKuI,EAAGH,IAGxChO,KAAK6uE,UAAUjpE,EAAK,CAChB6uE,aAER,EAEAoN,WAAY,SAASj8E,EAAKuI,EAAGH,GACzBhO,KAAKm2E,SAASvwE,EAAKuI,EAAGH,EAC1B,EAIAk0E,QAAS,SAASt8E,EAAKuI,EAAGH,GAEtB,IAAIzZ,EAAOyL,KAAK6uE,UAAUjpE,GACtBrR,EAAKkgF,WAAWz0E,KAAKghF,kBAAkBzsF,EAC/C,EAEA0tF,cAAe,SAASr8E,EAAKuI,EAAGH,GAC5BhO,KAAKy2E,YAAY7wE,EAAKuI,EAAGH,EAC7B,EAEAm0E,mBAAoB,SAASv8E,EAAKsuE,EAAQ/lE,EAAGH,GACzC,IAAIs1C,EAAQtjD,KAAKsjD,MACbA,EAAMurB,UAAUjpE,GAAK4wE,WAAalzB,EAAM3rB,QAAQmrD,gBACpD9iF,KAAKgxE,OAAO,8BAA+BprE,EAAKsuE,EAAQ/lE,EAAGH,EAC/D,GAED,CAEC+vE,MAAO,KAGX,GAAOc,GAAYvzF,UAAW0oE,IC71BvB,MAAMsjB,GAAS,SAASlc,EAAU/mD,EAAK0hE,GAE1C,OAAO3a,CACX,ECGa2nB,GAAU,SAAS3nB,EAAU/mD,EAAK0hE,GAE3C,IAUIiN,EAAY7iC,EAAWiY,EAVvBp8C,EAAO3H,EAAI2H,MAAQ,SACnBs9C,EAAU,GAAoBjlD,EAAIilD,SAAW,IAI7C2pB,EAAalN,EAASkN,WACtBC,EAAanN,EAASmN,WACtBC,EAAcF,EAAW/sE,SACzBktE,EAAcF,EAAWhtE,SAI7B,OAAQ8F,GACJ,IAAK,SACDo8C,EAAY,EACZ4qB,EAAa,IACb7iC,EAAY,SACZ,MACJ,IAAK,MACDiY,GAAa,EACb4qB,EAAa,IACb7iC,EAAY,SACZ,MACJ,IAAK,OACDiY,GAAa,EACb4qB,EAAa,IACb7iC,EAAY,QACZ,MACJ,IAAK,QACDiY,EAAY,EACZ4qB,EAAa,IACb7iC,EAAY,QACZ,MACJ,QACI,MAAM,IAAIn3C,MAAM,wBAcxB,OAVAm6E,EAAYH,IAAe5qB,GAAa6qB,EAAW9iC,GAAa,EAAImZ,EAAQt9C,IAC5EonE,EAAYJ,IAAe5qB,GAAa8qB,EAAW/iC,GAAa,EAAImZ,EAAQt9C,IAGvEo8C,GAAa+qB,EAAYH,GAAcI,EAAYJ,IAAgB,EACpEI,EAAYJ,GAAcG,EAAYH,GAEtCG,EAAYH,GAAcI,EAAYJ,GAGnC,CAACG,GAAax6E,OAAOyyD,EAAUgoB,EAC1C,ECvDA,IAAIC,GAAY,CACZC,EAAG,IACHC,EAAG,IACHC,EAAG,IACHC,EAAG,KAIHC,GAAU,CACVJ,GAAIvhF,KAAKuK,GAAK,EAAI,EAClBi3E,GAAIxhF,KAAKuK,GAAK,EACdk3E,EAAG,EACHC,EAAG1hF,KAAKuK,IAOZ,SAASq3E,GAAShzE,EAAIC,EAAImC,GAEtB,IAAIlF,EAAI,IAAI,GAAQ8C,EAAGxC,EAAGyC,EAAG5C,GAK7B,OAJI+E,EAAKxC,cAAc1C,KAAIA,EAAI,IAAI,GAAQ+C,EAAGzC,EAAGwC,EAAG3C,IAI7CH,CACX,CAGA,SAAS+1E,GAAY7wE,EAAMnF,GAEvB,OAAOmF,EAAkB,MAAZnF,GAA+B,MAAZA,EAAmB,QAAU,SACjE,CAGA,SAASi2E,GAAW/7E,EAAMg8E,GAEtB,OAAIh8E,EAAKqG,IAAM21E,EAAG31E,EAAWrG,EAAKkG,EAAI81E,EAAG91E,EAAK,IAAM,IAChDlG,EAAKkG,IAAM81E,EAAG91E,EAAWlG,EAAKqG,EAAI21E,EAAG31E,EAAK,IAAM,IAC7C,IACX,CAGA,SAAS41E,GAAYl2E,GAEjB,OAAO,IAAI,GAAOA,EAAEM,EAAGN,EAAEG,EAAG,EAAG,EACnC,CAEA,SAASg2E,GAAc3vE,GAGnB,IAAI8F,EAAQ,GAAoB9F,EAAIilD,SAAWjlD,EAAI4vE,gBAAkB,IAErE,MAAO,CACH91E,GAAIgM,EAAMnH,KACVhF,GAAImM,EAAMlH,IACVzC,MAAO2J,EAAMnH,KAAOmH,EAAMjH,MAC1BzC,OAAQ0J,EAAMlH,IAAMkH,EAAMhH,OAElC,CAGA,SAAS+wE,GAAcnO,EAAU1hE,GAE7B,OAAO0hE,EAASkN,WAAW7gF,QAAQkZ,cAAc0oE,GAAc3vE,GACnE,CAGA,SAAS8vE,GAAcpO,EAAU1hE,GAE7B,OAAO0hE,EAASmN,WAAW9gF,QAAQkZ,cAAc0oE,GAAc3vE,GACnE,CAwBA,SAAS+vE,GAAat8E,EAAMg8E,EAAIl2E,GAE5B,IAAI+C,EAAK,IAAI,GAAQ7I,EAAKqG,EAAG21E,EAAG91E,GAC5B4C,EAAK,IAAI,GAAQkzE,EAAG31E,EAAGrG,EAAKkG,GAC5Bq2E,EAAKR,GAAW/7E,EAAM6I,GACtB2zE,EAAKT,GAAW/7E,EAAM8I,GACtB2zE,EAAWlB,GAAUz1E,GAErBC,EAAKw2E,IAAOz2E,GAAYy2E,IAAOE,IAAaD,IAAOC,GAAYD,IAAO12E,GAAa+C,EAAKC,EAE5F,MAAO,CAAEb,OAAQ,CAAClC,GAAIuqD,UAAWyrB,GAAWh2E,EAAGi2E,GACnD,CAEA,SAASU,GAAc18E,EAAMg8E,EAAIW,GAE7B,IAAI52E,EAAI81E,GAAS77E,EAAMg8E,EAAIW,GAE3B,MAAO,CAAE10E,OAAQ,CAAClC,GAAIuqD,UAAWyrB,GAAWh2E,EAAGi2E,GACnD,CAEA,SAASY,GAAc58E,EAAMg8E,EAAIa,EAAQ/2E,GAErC,IAUIC,EAVA+2E,EAAQ,CAAC,EAET70E,EAAS,CAAC,IAAI,GAAQjI,EAAKqG,EAAG21E,EAAG91E,GAAI,IAAI,GAAQ81E,EAAG31E,EAAGrG,EAAKkG,IAC5D62E,EAAa90E,EAAOhc,QAAO,SAAS8lB,GACpC,OAAQ8qE,EAAOp0E,cAAcsJ,EACjC,IACIirE,EAAoBD,EAAW9wF,QAAO,SAAS8lB,GAC/C,OAAOgqE,GAAWhqE,EAAI/R,KAAU8F,CACpC,IAIA,GAAIk3E,EAAkBtzF,OAAS,EAM3Bqc,GAHAA,EAAIi3E,EAAkB/wF,QAAO,SAAS8lB,GAClC,OAAOgqE,GAAW/7E,EAAM+R,KAAQjM,CACpC,IAAGrN,QACMukF,EAAkB,GAE3BF,EAAM70E,OAAS,CAAClC,GAChB+2E,EAAMxsB,UAAYyrB,GAAWh2E,EAAGi2E,OAE7B,CAMHj2E,EAAI,GAAgBkC,EAAQ80E,GAAY,GAExC,IAAIj0E,EAAK,IAAK,GAAQkzE,GAAKlyE,KAAK/D,GAAI+1E,GAAYe,EAAQ/2E,GAAW,GAC/D+C,EAAKgzE,GAAS/yE,EAAI9I,EAAM68E,GAE5BC,EAAM70E,OAAS,CAACY,EAAIC,GACpBg0E,EAAMxsB,UAAYyrB,GAAWjzE,EAAIkzE,EACrC,CAEA,OAAOc,CACX,CAEA,SAASG,GAAej9E,EAAMg8E,EAAIW,EAAUE,GAExC,IAAIC,EAAQJ,GAAcV,EAAIh8E,EAAM68E,GAChCh0E,EAAKi0E,EAAM70E,OAAO,GAEtB,GAAI00E,EAASl0E,cAAcI,GAAK,CAG5B,IAAIC,GADJg0E,EAAQJ,GAAc18E,EAAMg8E,EAAIW,IACjB10E,OAAO,GAEtB,GAAI40E,EAAOp0E,cAAcK,GAAK,CAE1B,IAAIo0E,EAAa,IAAK,GAAQl9E,GAAO8J,KAAKhB,GAAKgzE,GAAYa,EAAUZ,GAAW/7E,EAAM8I,IAAO,GACzFq0E,EAAW,IAAK,GAAQnB,GAAKlyE,KAAKjB,GAAKizE,GAAYe,EAAQd,GAAWC,EAAInzE,IAAO,GACjF7O,EAAM,IAAK,GAAOkjF,EAAYC,GAAWjwE,WAEzCkwE,EAAaV,GAAc18E,EAAMhG,EAAK2iF,GACtCU,EAAWf,GAAatiF,EAAKgiF,EAAIoB,EAAW9sB,WAEhDwsB,EAAM70E,OAAS,CAACm1E,EAAWn1E,OAAO,GAAIo1E,EAASp1E,OAAO,IACtD60E,EAAMxsB,UAAY+sB,EAAS/sB,SAC/B,CACJ,CAEA,OAAOwsB,CACX,CAKA,SAASQ,GAAct9E,EAAMg8E,EAAIW,EAAUE,EAAQ/2E,GAE/C,IAQI+C,EAAIC,EAAIsK,EARR0pE,EAAQ,CAAC,EACTS,EAAWZ,EAASrhF,MAAMuhF,GAAQtuE,QAAQ,GAG1CivE,EAAWD,EAASnvE,SAAS1G,SAASs0E,GAAMuB,EAASnvE,SAAS1G,SAAS1H,GACvElI,EAAQ0lF,EAAWxB,EAAKh8E,EACxBjI,EAAMylF,EAAWx9E,EAAOg8E,EA4B5B,OAxBIl2E,GAGA+C,EAAK,GAAQpB,UAAU81E,EAAS70E,MAAQ60E,EAAS50E,OAAQizE,GAAQ91E,GAAUhO,GAC3E+Q,EAAK00E,EAASluE,oBAAoBxG,GAAIiB,KAAKjB,GAAK,IAGhDA,EAAK00E,EAASluE,oBAAoBvX,GAAOgS,KAAKhS,EAAO,GAGzDgR,EAAK+yE,GAAShzE,EAAI9Q,EAAKwlF,GAEnB10E,EAAGtE,QAAQwE,OAAOD,EAAGvE,UACrBuE,EAAK,GAAQrB,UAAU81E,EAAS70E,MAAQ60E,EAAS50E,OAAQ,GAAQE,EAAGI,MAAMnR,IAAUmC,KAAKuK,GAAK,EAAGzM,GAEjGqb,EAAKyoE,GAAShzE,EADdC,EAAKy0E,EAASluE,oBAAoBvG,GAAIgB,KAAK/R,EAAK,GAAGwM,QAC7Bg5E,GACtBT,EAAM70E,OAASu1E,EAAW,CAAC10E,EAAIsK,EAAIvK,GAAM,CAACA,EAAIuK,EAAItK,IAGlDg0E,EAAM70E,OAASu1E,EAAW,CAAC10E,EAAID,GAAM,CAACA,EAAIC,GAG9Cg0E,EAAMxsB,UAAuByrB,GAAXyB,EAAsB30E,EAAqBC,EAAjBkzE,GAErCc,CACX,CAMO,SAASW,GAAWnqB,EAAU/mD,EAAK0hE,GAEtC,IAcInoE,EAdAq1E,EAAaiB,GAAcnO,EAAU1hE,GACrC6uE,EAAaiB,GAAcpO,EAAU1hE,GAErCmxE,EAlKR,SAAyBzP,EAAU1hE,GAE/B,OAAI0hE,EAASyP,aAAqBzP,EAASyP,aAG1BtB,GAAcnO,EAAU1hE,GACvB6B,QACtB,CA2JuBuvE,CAAgB1P,EAAU1hE,GACzCqxE,EAzJR,SAAyB3P,EAAU1hE,GAE/B,OAAI0hE,EAAS2P,aAAqB3P,EAAS2P,aAG1BvB,GAAcpO,EAAU1hE,GACvB6B,QACtB,CAkJuByvE,CAAgB5P,EAAU1hE,GAG7C4uE,EAAaA,EAAW7/E,MAAM2gF,GAAYyB,IAC1CtC,EAAaA,EAAW9/E,MAAM2gF,GAAY2B,KAE1CtqB,EAAW,GAAaA,GAAUzqE,IAAI,KAC7BssB,QAAQuoE,GACjBpqB,EAASxpE,KAAK8zF,GAKd,IADA,IAAIE,EAAqB,GAChB9+E,EAAI,EAAGyG,EAAM6tD,EAAS5pE,OAAS,EAAGsV,EAAIyG,EAAKzG,IAAK,CAErD,IAAI89E,EAAQ,KAER98E,EAAOszD,EAASt0D,GAChBg9E,EAAK1oB,EAASt0D,EAAI,GAElB++E,IAAiBhC,GAAW/7E,EAAMg8E,GAEtC,GAAU,IAANh9E,EAEIA,EAAI,IAAMyG,EAIN01E,EAAW9uE,UAAU+uE,EAAW9gF,QAAQiU,QAAQ,IAChDuuE,EAAQQ,GAAct9E,EAAMg8E,EAAIb,EAAYC,GAEpC2C,IACRjB,EAAQG,GAAej9E,EAAMg8E,EAAIb,EAAYC,IAK7CD,EAAW1yE,cAAcuzE,GACzBc,EAAQQ,GAAct9E,EAAMg8E,EAAIb,EAAYc,GAAYD,GAAIxoE,cAAc0oE,GAAc3vE,KAEhFwxE,IACRjB,EAAQJ,GAAc18E,EAAMg8E,EAAIb,SAIrC,GAAIn8E,EAAI,IAAMyG,EAAK,CAGtB,IAAIu4E,EAAmBD,GAAgBhC,GAAWC,EAAIh8E,KAAU8F,EAE5Ds1E,EAAW3yE,cAAczI,IAASg+E,EAClClB,EAAQQ,GAAct9E,EAAMg8E,EAAIC,GAAYj8E,GAAMwT,cAAc0oE,GAAc3vE,IAAO6uE,EAAYt1E,GAEzFi4E,IACRjB,EAAQF,GAAc58E,EAAMg8E,EAAIZ,EAAYt1E,GAGpD,MAAYi4E,IACRjB,EAAQR,GAAat8E,EAAMg8E,EAAIl2E,IAM/Bg3E,GACA5zF,MAAM1F,UAAUsG,KAAKuP,MAAMykF,EAAoBhB,EAAM70E,QACrDnC,EAAUg3E,EAAMxsB,WAIhBxqD,EAAUi2E,GAAW/7E,EAAMg8E,GAI3Bh9E,EAAI,EAAIyG,GACRq4E,EAAmBh0F,KAAKkyF,EAEhC,CAEA,OAAO8B,CACX,CC9TA,IAAI,GAAS,CAGTv4B,KAAM,GAIN04B,aAAc,IAGd7zE,UAAW,EAGX8zE,0BAA2B,GAK3BC,eAAe,EAGfC,YAAa,GAGbC,aAAc,GAGdC,gBAAiB,CAAC,MAAO,QAAS,SAAU,QAG5CC,cAAe,CAAC,MAAO,QAAS,SAAU,QAG1CC,aAAc,CACVrzE,IAAK,CAAE9E,EAAG,EAAGH,GAAI,GACjBkF,MAAO,CAAE/E,EAAG,EAAGH,EAAG,GAClBmF,OAAQ,CAAEhF,EAAG,EAAGH,EAAG,GACnBgF,KAAM,CAAE7E,GAAI,EAAGH,EAAG,IAItBu4E,KAAM,WAEF,OAAOvmF,KAAKqtD,IAChB,EAIAm5B,WAAY,WAER,IAAIn5B,EAAOrtD,KAAKqtD,KACZk5B,EAAOvmF,KAAKumF,OAEhB,MAAO,CACH,CAAEE,QAASp5B,EAAMq5B,QAAS,EAAGH,KAAMA,GACnC,CAAEE,SAAUp5B,EAAMq5B,QAAS,EAAGH,KAAMA,GACpC,CAAEE,QAAS,EAAGC,QAASr5B,EAAMk5B,KAAMA,GACnC,CAAEE,QAAS,EAAGC,SAAUr5B,EAAMk5B,KAAMA,GAE5C,EAGAI,UAAW,WAEP,MAAO,CACH,EAAG,EACH,GAAI3mF,KAAKqtD,KAAO,EAChB,GAAIrtD,KAAKqtD,KAAO,EAExB,EAGAu5B,WAAY,WAER,IAAIv5B,EAAOrtD,KAAKqtD,KAEhB,MAAO,CACHl/C,GAAIk/C,EACJr/C,GAAIq/C,EACJ78C,MAAO,EAAI68C,EACX58C,OAAQ,EAAI48C,EAEpB,EAKAw5B,gBAAiB,KAIjBC,eAAgB,SAAS1rB,EAAU/mD,EAAK0hE,GAEpC,IAAK,GAAgBwP,IACjB,MAAM,IAAIv8E,MAAM,iEAGpB,OAAOu8E,GAAWnqB,EAAU,GAAY,CAAC,EAAG,GAAQ/mD,GAAM0hE,EAC9D,EAKAgR,cAAe,SAASj/E,EAAMg8E,EAAIzvE,GAE9B,OAAO,IAUX,EAIA2yE,cAAe,MAOnB,SAASC,GAAY5yE,GAEjBrU,KAAKrP,IAAM,CAAC,EACZqP,KAAK23B,QAAUtjB,EAEfrU,KAAKknF,YAAc,GACvB,CAqFA,SAASC,KACLnnF,KAAK6wD,MAAQ,GACb7wD,KAAKwyC,KAAO,CAAC,EACbxyC,KAAKxP,OAAS,CAAC,EACfwP,KAAKonF,KAAO,EACZpnF,KAAKqnF,MAAQ,CACjB,CAkDA,SAAS,GAActR,EAAU1hE,GAG7B,OAAIA,GAAOA,EAAIuyE,WAAmB7Q,EAASkN,WAAW7gF,QAAQkZ,cAAcjH,EAAIuyE,YAEzE7Q,EAASkN,WAAW7gF,OAC/B,CAGA,SAAS,GAAc2zE,EAAU1hE,GAG7B,OAAIA,GAAOA,EAAIuyE,WAAmB7Q,EAASmN,WAAW9gF,QAAQkZ,cAAcjH,EAAIuyE,YAEzE7Q,EAASmN,WAAW9gF,OAC/B,CAGA,SAAS,GAAgB2zE,EAAU1hE,GAE/B,OAAI0hE,EAASyP,aAAqBzP,EAASyP,aAG1B,GAAczP,EAAU1hE,GACvB6B,QACtB,CAcA,SAASoxE,GAAkB1nF,EAAOC,EAAK0nF,EAAe7E,EAAMruE,GAExD,IAAIgkD,EAAW,IAAMkvB,EACjBC,EAAa5nF,EAAMmR,MAU3B,SAAqBnR,EAAOC,EAAK6iF,EAAMruE,GAEnC,IAAIg5C,EAAOh5C,EAAIg5C,KAEXo6B,EAAQ5nF,EAAIsO,EAAIvO,EAAMuO,EACtBu5E,EAAQ7nF,EAAImO,EAAIpO,EAAMoO,EAKtB25E,EAHaF,EAAQ/E,EAAKv0E,EAGDk/C,EACzBu6B,EAHaF,EAAQhF,EAAK10E,EAGDq/C,EAE7B,OAAO,IAAI,GAAQztD,EAAMuO,EAAIw5E,EAAW/nF,EAAMoO,EAAI45E,EACtD,CAxBiCC,CAAYjoF,EAAOC,EAAK6iF,EAAMruE,IACvDyzE,EAAkB,GAAiBN,EAAcnvB,EAAW,GAChE,OAAOA,EAAWt2D,KAAKC,MAAM8lF,EAAkBzvB,EACnD,CAwBA,SAAS0vB,GAAmBC,EAAQC,GAEhC,IAAIC,EAAkBnmF,KAAKoN,IAAI64E,EAASC,GACxC,OAAQC,EAAkB,IAAQ,IAAMA,EAAmBA,CAC/D,CAyBA,SAASC,GAAiBpvF,EAAMs0D,GAG5B,IAAKt0D,EAAM,OAAOs0D,EAElB,IAAI+6B,EAAUrmF,KAAKoN,IAAIpW,GACnBsvF,EAAWtmF,KAAKsK,MAAM+7E,EAAU/6B,GAGpC,OAAKg7B,EAOEh7B,GAHS+6B,EADEC,EAAWh7B,GAEIg7B,EALXD,CAQ1B,CAcA,SAAS,GAAMp3E,EAAOkB,GAElB,OAAOlB,EAAM3E,MAAM6F,EACvB,CAGA,SAASo2E,GAAMt3E,EAAO0xE,EAAMxwE,GAExB,OAAO,GAnBX,SAAoBlB,EAAO0xE,GAEvB,IAAI/vF,EAAS+vF,EAAK/vF,OAEd41F,EAAW,GAAav3E,EAAM7C,EAAIxb,EAAOwb,EAAGu0E,EAAKv0E,GAAKxb,EAAOwb,EAC7Dq6E,EAAW,GAAax3E,EAAMhD,EAAIrb,EAAOqb,EAAG00E,EAAK10E,GAAKrb,EAAOqb,EAEjE,OAAO,IAAI,GAAQu6E,EAAUC,EACjC,CAWiB,CAAWx3E,EAAM5O,QAASsgF,GAAOxwE,EAClD,CAIA,SAASu2E,GAAOz3E,GAEZ,OAAOA,EAAM5O,QAAQrP,UACzB,CAIA,SAAS21F,GAAe13E,GAEpB,OAAO,IAAI,GACK,IAAZA,EAAM7C,EAAU,EAAIpM,KAAKoN,IAAI6B,EAAM7C,GAAK6C,EAAM7C,EAClC,IAAZ6C,EAAMhD,EAAU,EAAIjM,KAAKoN,IAAI6B,EAAMhD,GAAKgD,EAAMhD,EAEtD,CAKA,SAAS26E,GAAiBC,EAAS74E,EAAQ84E,EAAW/gF,EAAMg8E,EAAIpB,EAAMruE,GAWlE,IATA,IAQIrD,EARA4zE,EAAQ,GAERkE,EAAWJ,GAAe5E,EAAG3gF,WAAW0lF,IAGxCE,EAAaN,GAAOI,GACpBzsD,EAASwsD,EAAQG,GAGd3sD,GAAQ,CAKX,IAAIrjC,EAAO2vF,IAFX13E,EAAQjB,EAAOg5E,IAEiB5lF,WAAWi5B,IACtCrjC,EAAK8X,OAAOi4E,KACblE,EAAM3nE,QAAQjM,GACd83E,EAAW/vF,GAKfqjC,EAASwsD,EADTG,EAAaN,GAAOrsD,GAExB,CAGA,IAAI4sD,EAAYj5E,EAAOg5E,GAOvB,OALeL,GAAeM,EAAU7lF,WAAW2E,IACrC+I,OAAOi4E,IACjBlE,EAAM3nE,QAAQ+rE,GAGXpE,CACX,CAGA,SAASqE,GAAanhF,EAAMohF,GAIxB,IAFA,IAAIjnF,EAAMgB,IAED6D,EAAI,EAAGD,EAAMqiF,EAAU13F,OAAQsV,EAAID,EAAKC,IAAK,CAClD,IAAIy/E,EAAOz+E,EAAK6J,kBAAkBu3E,EAAUpiF,IACxCy/E,EAAOtkF,IAAKA,EAAMskF,EAC1B,CAEA,OAAOtkF,CACX,CAOA,SAASknF,GAAcC,EAAQr2E,EAAMs2E,EAAe3G,EAAMruE,GAEtD,IAAInC,EAAYmC,EAAInC,UAChBo0E,EAAejyE,EAAIiyE,aAEnBgD,EAAqBF,EAAOjmF,WAAW4P,EAAKmD,UAE5CxlB,EAAO,GAAc41F,GAAgBt7F,OAAO0F,KAAK41F,GAAgB,GACjEiD,EAAU,GAAaF,GACvBG,EAAa94F,EAAKsT,QAAO,SAAS2kC,EAAK79C,GAEvC,GAAIy+F,EAAQvwF,SAASlO,GAAM,CAiBvB,IAhBA,IAcI2+F,EAdArxB,EAAYkuB,EAAax7F,GAIzB4+F,EAAW,IAAI,GACfN,EAAOj7E,EAAIiqD,EAAUjqD,GAAKpM,KAAKoN,IAAIm6E,EAAmBn7E,GAAK4E,EAAKvC,OAChE44E,EAAOp7E,EAAIoqD,EAAUpqD,GAAKjM,KAAKoN,IAAIm6E,EAAmBt7E,GAAK+E,EAAKtC,SAMhE6F,EAJmB,IAAI,GAAO8yE,EAAQM,GAILv1E,UAAUpB,IAAS,GACpDyL,EAAmBlI,EAAc9kB,OAEjCm4F,EAAuB,KAClB7iF,EAAI,EAAGA,EAAI0X,EAAkB1X,IAAK,CACvC,IAAI8iF,EAAsBtzE,EAAcxP,GACpC0I,EAAW45E,EAAOh5E,gBAAgBw5E,SACAn3F,IAAjCg3F,GAAgDj6E,EAAWi6E,KAC5DA,EAA+Bj6E,EAC/Bm6E,EAAuBC,EAE/B,CAGA,GAAID,EAAsB,CACtB,IAAI34E,EAAQs3E,GAAMqB,EAAsBjH,EAAMxwE,GAG1Ca,EAAKxC,cAAcS,KACnBA,EAAQs3E,GAAMt3E,EAAMK,OAAO+mD,EAAUjqD,EAAIu0E,EAAKv0E,EAAGiqD,EAAUpqD,EAAI00E,EAAK10E,GAAI00E,EAAMxwE,IAKlFy2B,EAAI/2C,KAAKof,EACb,CACJ,CAEA,OAAO23B,CACX,GAAG,IAQH,OALK51B,EAAKxC,cAAc64E,IAEpBI,EAAW53F,KAAK02F,GAAMc,EAAQ1G,EAAMxwE,IAGjCs3E,CACX,CAIA,SAASK,GAAU/hF,EAAMg8E,EAAI+C,EAAiBxyE,GAE1C,IAIImxE,EAAcE,EAJdxzE,EAAYmC,EAAInC,UAOhBszE,EAAe,GADf19E,aAAgB,GACK,GAAgB9H,KAAMqU,GAAKjS,QAE3B0F,EAAK1F,QAF+B8P,GAMzDwzE,EAAe,GADf5B,aAAc,GA5QtB,SAAyB/N,EAAU1hE,GAE/B,OAAI0hE,EAAS2P,aAAqB3P,EAAS2P,aAG1B,GAAc3P,EAAU1hE,GACvB6B,QACtB,CAsQ6B,CAAgBlW,KAAMqU,GAAKjS,QAE3B0hF,EAAG1hF,QAFiC8P,GAK7D,IAtNam7C,EAAM16D,EAAQuS,EA0NvBtF,EAAOC,EACPiqF,EAAaZ,EALbxG,GAtNSr1B,EAsNMh5C,EAAIg5C,KAtNInoD,EAsNgBwgF,EApNpC,CACH/yF,QAHeA,EAsNU6yF,GAnNVpjF,QACf+L,EAAGg6E,GAAiBjjF,EAAOiJ,EAAIxb,EAAOwb,EAAGk/C,GACzCr/C,EAAGm6E,GAAiBjjF,EAAO8I,EAAIrb,EAAOqb,EAAGq/C,KAkP7C,GAvBIy8B,EAFAhiF,aAAgB,GAEFqhF,GADdvpF,EAAQ4lF,EAC2B19E,EAAMuM,EAAI+xE,gBAAiB1D,EAAMruE,GAItD,CADdzU,EAAQ4lF,GAKR1B,aAAc,IACdjkF,EAAM6lF,EACNwD,EAAYC,GAAczD,EAAc5B,EAAIzvE,EAAIgyE,cAAe3D,EAAMruE,IAIrE60E,EAAY,CADZrpF,EAAM6lF,GAKVoE,EAAcA,EAAY/1F,QAAO8Z,IAAMg5E,EAAgBh5E,KACvDq7E,EAAYA,EAAUn1F,QAAO8Z,IAAMg5E,EAAgBh5E,KAI/Ci8E,EAAYt4F,OAAS,GAAK03F,EAAU13F,OAAS,EAAG,CAYhD,IARA,IAAIu4F,EAAU,IAAI5C,GAEdp3E,EAAS,CAAC,EAEV64E,EAAU,CAAC,EAEXoB,EAAQ,CAAC,EAEJljF,EAAI,EAAGkJ,EAAI85E,EAAYt4F,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAEhD,IAAI6V,EAAamtE,EAAYhjF,GAEzBhc,EAAM29F,GAAO9rE,GAEjBotE,EAAQnvF,IAAI9P,EAAKm+F,GAAatsE,EAAYusE,IAC1Cn5E,EAAOjlB,GAAO6xB,EACdqtE,EAAMl/F,GAAO,CACjB,CAEA,IAIIstE,EAAW8vB,EAJX+B,EAA8B51E,EAAI61E,uBAClCC,OAAmD13F,IAAhCw3F,EAInBzD,EAAanyE,EAAImyE,YA/R7B,SAAwBA,EAAY9D,EAAMruE,GAEtC,IAAIg5C,EAAOh5C,EAAIg5C,KAEf,GAAah5C,EAAImyE,YAAY7uF,SAAQ,SAASygE,GAE1CA,EAAUgyB,YAAehyB,EAAUquB,QAAUp5B,EAAQq1B,EAAKv0E,EAC1DiqD,EAAUiyB,YAAejyB,EAAUsuB,QAAUr5B,EAAQq1B,EAAK10E,CAC9D,GACJ,CAuRQs8E,CAAe9D,EAAY9D,EAAMruE,GAcjC,IAZA,IAAIkzE,EAAgBf,EAAWh1F,OAE3B+4F,EAAgB,GAAarB,GAAWllF,QAAO,SAAS2kC,EAAK6hD,GAG7D,IAAI1/F,EAAM29F,GAAO+B,GAEjB,OADA7hD,EAAI/2C,KAAK9G,GACF69C,CACX,GAAG,IAGC8hD,EAAiBp2E,EAAI0xE,cACjBgE,EAAQznF,WAAamoF,EAAiB,GAAG,CAG7C,IAQIP,EARAnB,EAAagB,EAAQxpF,MACrB4c,EAAepN,EAAOg5E,GACtB2B,EAAgB9B,EAAQG,GACxB4B,EAAcX,EAAMjB,GAEpB6B,OAAsCn4F,IAAlBi4F,EACpBG,EAAU1tE,EAAatM,OAAOjR,GAM7BsqF,EAHAU,EACKT,EACAU,EACoB,KADcvD,GAAkB1nF,EAAOud,EAAcoqE,EAAe7E,EAAMruE,GADpD41E,EADJ3C,GAAkBoD,EAAevtE,EAAcoqE,EAAe7E,EAAMruE,GAMpH,IAAIy2E,EAAahB,EAAYt4F,SAAW03F,EAAU13F,OAClD,GAAIs5F,EACA,IAAK,IAAI/jF,EAAI,EAAGA,EAAI+iF,EAAYt4F,OAAQuV,IACpC,IAAK+iF,EAAY/iF,GAAG8J,OAAOq4E,EAAUniF,IAAK,CACtC+jF,GAAa,EACb,KACJ,CAIR,KADoBF,IAAoBE,IAClBP,EAActxF,QAAQ8vF,IAAe,EAEvD,OADA10E,EAAI61E,uBAAyBA,EACtBvB,GAAiBC,EAAS74E,EAAQoN,EAAcvd,EAAOC,GAIlE,IAAKiH,EAAI,EAAGA,EAAIygF,EAAezgF,IAAK,CAGhC,IAAIikF,GAFJ3yB,EAAYouB,EAAW1/E,IAEQgG,MAK/B,GAJAo7E,EAAkBH,GAAmBmC,EAAwBa,GAIvDZ,GAAmBU,KAAY3C,EAAkB7zE,EAAI2xE,2BAA3D,CAEA,IAAIgF,EAAgB1C,GAAMnrE,EAAa/a,QAAQiP,OAAO+mD,EAAUgyB,YAAahyB,EAAUiyB,aAAc3H,EAAMxwE,GACvG+4E,EAAcxC,GAAOuC,GAGzB,IAAIjB,EAAQmB,QAAQD,KAAgBpE,EAAgBmE,GAApD,CAGA,GAAIT,EAActxF,QAAQgyF,IAAgB,IAElBD,EAAcn6E,OAAOhR,IAIZkoF,GAAmBgD,EADpBzD,GAAkB0D,EAAenrF,EAAK0nF,EAAe7E,EAAMruE,IAG1DA,EAAI2xE,0BAA2B,SAMhE,IAEImF,EAAgBR,EAFDvyB,EAAUmuB,MACPsE,EAAU,EAAIx2E,EAAIsyE,UAAUuB,MAG7C6B,EAAQqB,OAAOH,IAAiBE,EAAgBnB,EAAMiB,MAIvDl7E,EAAOk7E,GAAeD,EACtBpC,EAAQqC,GAAe9tE,EACvB6sE,EAAMiB,GAAeE,EACrBpB,EAAQnvF,IAAIqwF,EAAaE,EAAgBlC,GAAa+B,EAAe9B,IA5BG,CANkB,CAoClG,CAEAuB,GACJ,CACJ,CAIA,OAAOp2E,EAAI0yE,cAAcv7F,KAAKwU,KAAMJ,EAAOC,EAAKwU,EACpD,CA5lBA4yE,GAAY37F,UAAU+/F,MAAQ,SAASpkC,EAAOG,GAE1C,IAAI/yC,EAAMrU,KAAK23B,QAGX2zD,EAAe,GAAaj3E,EAAI6xE,aAAaliF,QAAO,SAAS2kC,EAAKnC,GAElE,IAAI3mC,EAAMunD,EAAKj8D,IAAIq7C,GACnB,GAAI3mC,EAAK,CACL,IAAI0+C,EAAO0I,EAAM+B,QAAQnpD,EAAIy1B,IACzBipB,GACA5V,EAAI/2C,KAAK2sD,EAEjB,CAEA,OAAO5V,CACX,GAAG,IAGC4iD,EAAoB,GAEpB54F,EAASs0D,EAAM+B,QAAQ5B,EAAKj8D,IAAI,UAAUmqC,IAC1C3iC,IACA44F,EAAoB,GAAWA,EAAmB54F,EAAOs2D,eAAet4D,KAAI,SAAS4tD,GACjF,OAAOA,EAAKjpB,EAChB,MAGJ,IAAIpwB,EAAS+hD,EAAM+B,QAAQ5B,EAAKj8D,IAAI,UAAUmqC,IAC1CpwB,IACAqmF,EAAoB,GAAWA,EAAmBrmF,EAAO+jD,eAAet4D,KAAI,SAAS4tD,GACjF,OAAOA,EAAKjpB,EAChB,MAQJ,IAAI4xD,EAAclnF,KAAKknF,YA6BvB,OA3BAjgC,EAAMsf,cAAcviE,QAAO,SAASrT,EAAK4mE,GAErC,IAAIi0B,EAAiB,GAAan3E,EAAI8xE,cAAcntF,SAASu+D,EAAQpsE,IAAI,SACrEsgG,EAAgBH,EAAaljF,MAAK,SAASsjF,GAC3C,OAAOA,EAASp2D,KAAOiiC,EAAQjiC,EACnC,IACIq2D,EAAqBJ,EAAkBvyF,SAASu+D,EAAQjiC,IAG5D,KADiBk2D,GAAkBC,GAAiBE,GAOhD,IALA,IAAI54E,EAAOwkD,EAAQngC,UAAU9b,cAAcjH,EAAIuyE,YAE3Cn3E,EAASsD,EAAKtD,SAAS1C,WAAWm6E,GAClC5tE,EAASvG,EAAKuG,SAASvM,WAAWm6E,GAE7B/4E,EAAIsB,EAAOtB,EAAGA,GAAKmL,EAAOnL,EAAGA,GAAK+4E,EACvC,IAAK,IAAIl5E,EAAIyB,EAAOzB,EAAGA,GAAKsL,EAAOtL,EAAGA,GAAKk5E,EAAa,CACpD,IAAI0E,EAAUz9E,EAAI,IAAMH,EACxBrd,EAAIi7F,GAAWj7F,EAAIi7F,IAAY,GAC/Bj7F,EAAIi7F,GAASh6F,KAAKmhB,EACtB,CAIR,OAAOpiB,CACX,GAAGqP,KAAKrP,KAEDqP,IACX,EAEAinF,GAAY37F,UAAUugG,kBAAoB,SAAS76E,GAE/C,IAAI86E,EAAS96E,EAAM5O,QAAQ2K,WAAW/M,KAAKknF,aAAan0F,WAExD,OAAO,GAAaiN,KAAKrP,IAAIm7F,IAASljC,OAAM,SAASmjC,GACjD,OAAQA,EAASx7E,cAAcS,EACnC,GACJ,EAYAm2E,GAAU77F,UAAUsP,IAAM,SAAS4rC,EAAM76C,GAEjCqU,KAAKwyC,KAAKhM,GAEVxmC,KAAK6wD,MAAMrwD,OAAOR,KAAK6wD,MAAM53D,QAAQutC,GAAO,GAE5CxmC,KAAKwyC,KAAKhM,GAAQxmC,KAAKonF,KAG3BpnF,KAAKxP,OAAOg2C,GAAQ76C,EAEpB,IAAI+F,EAAQ,GAAiBsO,KAAK6wD,MAAOrqB,EAAM,SAAS1/B,GACpD,OAAO9G,KAAKxP,OAAOsW,EACvB,EAAE/W,KAAKiQ,OAEPA,KAAK6wD,MAAMrwD,OAAO9O,EAAO,EAAG80C,EAChC,EAEA2gD,GAAU77F,UAAUiZ,OAAS,SAASiiC,GAElCxmC,KAAKwyC,KAAKhM,GAAQxmC,KAAKqnF,KAC3B,EAEAF,GAAU77F,UAAU8/F,OAAS,SAAS5kD,GAElC,OAAOxmC,KAAKwyC,KAAKhM,KAAUxmC,KAAKonF,IACpC,EAEAD,GAAU77F,UAAU4/F,QAAU,SAAS1kD,GAEnC,OAAOxmC,KAAKwyC,KAAKhM,KAAUxmC,KAAKqnF,KACpC,EAEAF,GAAU77F,UAAUgX,QAAU,WAE1B,OAA6B,IAAtBtC,KAAK6wD,MAAMr/D,MACtB,EAEA21F,GAAU77F,UAAUiV,IAAM,WAEtB,IAAIimC,EAAOxmC,KAAK6wD,MAAMrlB,QAEtB,OADAxrC,KAAKuE,OAAOiiC,GACLA,CACX,EAqkBO,MAAMwlD,GAAY,SAAS5wB,EAAU/mD,EAAK0hE,GAC7C,OAjFJ,SAAgB3a,EAAU/mD,EAAK0hE,IA5B/B,SAAwB1hE,GAOpB,GALAA,EAAImyE,WAAa,GAAYnyE,EAAK,cAClCA,EAAIsyE,UAAY,GAAYtyE,EAAK,aACjCA,EAAIuyE,WAAa,GAAYvyE,EAAK,cAClCA,EAAIilD,QAAU,GAAYjlD,EAAK,WAE3BA,EAAIilD,QAAS,CAEb,IAAIn/C,EAAQ,GAAoB9F,EAAIilD,SACpCjlD,EAAIuyE,WAAa,CACbz4E,GAAIgM,EAAMnH,KACVhF,GAAImM,EAAMlH,IACVzC,MAAO2J,EAAMnH,KAAOmH,EAAMjH,MAC1BzC,OAAQ0J,EAAMlH,IAAMkH,EAAMhH,OAElC,CAEA,GAAakB,EAAImyE,YAAY7uF,SAAQ,SAASygE,GAE1C,IAAI6zB,EAAS,IAAI,GAAQ,EAAG,GACxBC,EAAS,IAAI,GAAQ9zB,EAAUquB,QAASruB,EAAUsuB,SAEtDtuB,EAAUtrD,MAAQ,GAAiBm/E,EAAOl7E,MAAMm7E,GACpD,GACJ,CAKIC,CAAe93E,GAGf0hE,EAASp+C,QAAQsuD,gBAAkB5xE,EAAI4xE,cAEvC,IAAIhD,EAAa,GAAclN,EAAU1hE,GACrC6uE,EAAa,GAAcnN,EAAU1hE,GAErCmxE,EAAe,GAAgBzP,EAAU1hE,GAI7C,IAAIwyE,EACJ,GAAmC,mBAAxBxyE,EAAIwyE,gBACXA,EAAkBxyE,EAAIwyE,oBACnB,CACH,MAAMl2F,EAAM,IAAIs2F,GAAY5yE,GAC5B1jB,EAAI06F,MAAMtV,EAASzyB,MAAM3F,MAAOo4B,EAASp4B,OACzCkpC,EAAmB71E,IAAWrgB,EAAIk7F,kBAAkB76E,EACxD,CAUA,IARA,IAMI8yE,EAAIh8E,EANJskF,EAAc,GAAahxB,GAAUzqE,IAAI,IACzC07F,EAAc,GACdxD,EAAYrD,EAMP1+E,EAAI,EAAGD,EAAMulF,EAAY56F,OAAQsV,GAAKD,EAAKC,IAAK,CAErD,IAAIwlF,EAAe,KAKnB,GAHAxkF,EAAOg8E,GAAMb,IACba,EAAKsI,EAAYtlF,MAObg9E,EAAKZ,IAIkBnN,EAASp4B,MAAMxyD,IAAI,UAAUmqC,KAAOygD,EAASp4B,MAAMxyD,IAAI,UAAUmqC,KAEjE,GAAgBjhB,EAAI2yE,gBAAgB,CAEvD,IAAIuF,EAAYzkF,IAASm7E,EAAcuC,EAAe19E,EAClD0kF,EAAS1I,EAAGr0E,SAEhB68E,EAAej4E,EAAI2yE,cAAcx7F,KAAKuqF,EAAUwW,EAAUC,EAAQn4E,EACtE,CAMJ,GAAqB,QAFrBi4E,EAAeA,GAAgBzC,GAAUr+F,KAAKuqF,EAAUjuE,EAAMg8E,EAAI+C,EAAiBxyE,IAG/E,OAAOA,EAAIyyE,eAAe1rB,EAAU/mD,EAAK0hE,GAG7C,IAAIiT,EAAYsD,EAAa,GAGzBtD,GAAaA,EAAUn4E,OAAOg4E,IAAYyD,EAAa9gD,QAG3Dq9C,EAAYyD,EAAaA,EAAa96F,OAAS,IAAMq3F,EAErD73F,MAAM1F,UAAUsG,KAAKuP,MAAMkrF,EAAaC,EAC5C,CAEA,OAAOD,CACX,CAIW7xB,CAAOY,EAAU,GAAY,CAAC,EAAG,GAAQ/mD,GAAM0hE,EAC1D,ECn1BA,IAAI,GAAS,CAETiQ,0BAA2B,GAG3ByG,aAAc,WAEV,IAAIp/B,EAAOrtD,KAAKqtD,KAChB,OAAOtrD,KAAK2qF,KAAK3qF,KAAK2M,KAAK2+C,EAAOA,GAAQ,GAC9C,EAIAm5B,WAAY,WAER,IAAIn5B,EAAOrtD,KAAKqtD,KACZk5B,EAAOvmF,KAAKumF,OACZkG,EAAezsF,KAAKysF,eAExB,MAAO,CACH,CAAEhG,QAASp5B,EAAMq5B,QAAS,EAAGH,KAAMA,GACnC,CAAEE,QAASp5B,EAAMq5B,QAASr5B,EAAMk5B,KAAMkG,GACtC,CAAEhG,QAAS,EAAGC,QAASr5B,EAAMk5B,KAAMA,GACnC,CAAEE,SAAUp5B,EAAMq5B,QAASr5B,EAAMk5B,KAAMkG,GACvC,CAAEhG,SAAUp5B,EAAMq5B,QAAS,EAAGH,KAAMA,GACpC,CAAEE,SAAUp5B,EAAMq5B,SAAUr5B,EAAMk5B,KAAMkG,GACxC,CAAEhG,QAAS,EAAGC,SAAUr5B,EAAMk5B,KAAMA,GACpC,CAAEE,QAASp5B,EAAMq5B,SAAUr5B,EAAMk5B,KAAMkG,GAE/C,EAIA1F,cAAe,SAASj/E,EAAMg8E,EAAIzvE,GAI9B,IAAItD,EAAQjJ,EAAKiJ,MAAM+yE,GAEnBc,EAAQ,GAERjpF,EAAI,CAAEwS,EAAG21E,EAAG31E,EAAGH,EAAGlG,EAAKkG,GACvBpS,EAAI,CAAEuS,EAAGrG,EAAKqG,EAAGH,EAAG81E,EAAG91E,GAE3B,GAAI+C,EAAQ,IAAM,GAAI,CAClB,IAAIU,EAAI9V,EACRA,EAAIC,EACJA,EAAI6V,CACR,CAEA,IAAId,EAAMI,EAAQ,GAAM,GAAKpV,EAAIC,EAC7Bk1B,EAAK,IAAI,GAAOhpB,EAAM6I,GAEtBkE,EAAQ,GAAK9S,KAAK2qF,KAAK37E,EAAQ,IAE/BH,EAAK,GAAQrB,UAAUuhB,EAAGviB,gBAAiB,GAAQsG,EAAQ,KAAMlE,GACjEqO,EAAK,IAAI,GAAO8kE,EAAIlzE,GAEpB+7E,EAAoB77D,EAAGvc,aAAayK,GACpChO,EAAQ27E,GAAwC7I,EAEhD8I,EAAgBD,EAAoB37E,EAAQlJ,EAE5CuwD,EAAW,IAAMhkD,EAAImyE,WAAWh1F,OAChCg2F,EAAaoF,EAAc77E,MAAM+yE,GACjCgE,EAAkB,GAAiBN,EAAcnvB,EAAW,GAC5D0yB,EAAiB1yB,EAAWt2D,KAAKC,MAAM8lF,EAAkBzvB,GAO7D,OALAhkD,EAAI61E,uBAAyBa,EAEzB/5E,GAAO4zE,EAAMhzF,KAAKof,EAAM3E,SAC5Bu4E,EAAMhzF,KAAKkyF,GAEJc,CACX,GAIG,MAAMiI,GAAQ,SAASzxB,EAAU/mD,EAAK0hE,GAEzC,IAAK,GAAgBiW,IACjB,MAAM,IAAIhjF,MAAM,wCAGpB,OAAOgjF,GAAU5wB,EAAU,GAAY,CAAC,EAAG,GAAQ/mD,GAAM0hE,EAC7D,ECvFM+W,GAAa,CACfC,KAAM,OACNhsB,KAAM,OACNF,MAAO,QACPD,IAAK,MACLE,OAAQ,SACRksB,YAAa,cACbC,YAAa,eAGXC,GAAqB,CAACJ,GAAW/rB,KAAM+rB,GAAWjsB,MAAOisB,GAAWlsB,IAAKksB,GAAWhsB,QAEpFqsB,GAAsB,CACxB,CAACL,GAAW/rB,MAAO+rB,GAAWjsB,MAC9B,CAACisB,GAAWjsB,OAAQisB,GAAW/rB,KAC/B,CAAC+rB,GAAWlsB,KAAMksB,GAAWhsB,OAC7B,CAACgsB,GAAWhsB,QAASgsB,GAAWlsB,KAG9BwsB,GAAsB,CAACN,GAAWlsB,IAAKksB,GAAWhsB,QAElDusB,GAAsB,CACxB,EAAGP,GAAWjsB,MACd,IAAKisB,GAAW/rB,KAChB,IAAK+rB,GAAWlsB,IAChB,GAAIksB,GAAWhsB,QAGnB,SAASwsB,GAAgB94E,GAErB,OAAOA,EAAK1H,OAChB,CAEA,SAASygF,GAAex9E,GAGpB,OAAO,IAAI,GAAWA,GAAQmP,SAAS,CAAEC,UAAW,IAAKpP,MAC7D,CAEA,SAASy9E,GAAa76F,EAAQuS,GAC1B,MAAQ8L,MAAOmyE,EAAa30E,GAAIi/E,EAAKh/E,GAAIi/E,EAAKlc,KAAM4L,EAAYrqE,KAAMkwE,EAAY7qB,UAAWu1B,GAAoBh7F,GACzGqe,MAAOoyE,EAAa50E,GAAIo/E,EAAKn/E,GAAIo/E,EAAKrc,KAAM+L,EAAYxqE,KAAMmwE,EAAY9qB,UAAW01B,GAAoB5oF,EAEjH,IAAI6oF,EAeAC,EAbJ,GAAK5Q,EAID2Q,EADO3Q,EAAWz/B,MAAMa,SACXyvC,GAA8B7K,EAAaD,EAAa/F,GAC9DuQ,IAAoBb,GAAWE,YACzB/J,EAAWtnE,mBAAmBwnE,GACpCwK,IAAoBb,GAAWG,YACzB7P,EAAWz/B,MAAMvmB,UAAUzb,mBAAmBwnE,GAE9CwK,MAVA,CACb,MAAMO,EAAuB,IAAI,GAAOT,EAAKC,EAAK,EAAG,GACrDK,EAAab,GAAmBl0F,SAAS20F,GAAmBA,EAAkBO,EAAqBvyE,mBAAmBynE,EAC1H,CAYA,GAAK7F,EAIDyQ,EADOzQ,EAAW5/B,MAAMa,SACXyvC,GAA8B9K,EAAaC,EAAa7F,GAC9DuQ,IAAoBhB,GAAWE,YACzB9J,EAAWvnE,mBAAmBynE,GACpC0K,IAAoBhB,GAAWG,YACzB1P,EAAW5/B,MAAMvmB,UAAUzb,mBAAmBynE,GAE9C0K,MAVA,CACb,MAAMK,EAAuB,IAAI,GAAOP,EAAKC,EAAK,EAAG,GACrDG,EAAad,GAAmBl0F,SAAS80F,GAAmBA,EAAkBK,EAAqBxyE,mBAAmBwnE,EAC1H,CAUA,MAAO,CAAC4K,EAAYC,EACxB,CAiKA,SAASC,GAA8BG,EAAYC,EAAiBtY,GAChE,MAAMnyB,EAAUmyB,EAASuY,mBAAmBvY,EAASwY,sBAAsBF,IACrEG,EAA2D,GAA5CzsF,KAAKsK,MAAMihF,GAAgB1pC,GAAW,IAE3D,GAAI4qC,EAAe,KAAQ,GAAKJ,EAAWpgF,IAAMqgF,EAAgBrgF,EAC7D,OAAOogF,EAAWjgF,EAAIkgF,EAAgBlgF,EAAI2+E,GAAW/rB,KAAO+rB,GAAWjsB,MACpE,GAAIutB,EAAWjgF,IAAMkgF,EAAgBlgF,EACxC,OAAOigF,EAAWpgF,EAAIqgF,EAAgBrgF,EAAI8+E,GAAWlsB,IAAMksB,GAAWhsB,OAG1E,OAAQ0tB,GACJ,KAAK,EACL,KAAK,IACL,KAAK,IACD,OAAOJ,EAAWpgF,EAAIqgF,EAAgBrgF,EAAI8+E,GAAWlsB,IAAMksB,GAAWhsB,OAC1E,KAAK,GACL,KAAK,IACD,OAAOstB,EAAWjgF,EAAIkgF,EAAgBlgF,EAAI2+E,GAAW/rB,KAAO+rB,GAAWjsB,MAEnF,CAEA,SAAS4tB,GAAoBjd,EAAMxgE,EAAO+B,EAAMqlD,EAAWs2B,EAAQC,EAAgB71C,GAC3Esf,IAAc00B,GAAWC,OACzB30B,EAAYs2B,EAAS5B,GAAWG,YAAcH,GAAWE,aAG7D,MAAMrhC,EAAY6lB,GAAQA,EAAK7zB,MAAMgO,aAGjCx9C,EAAGK,EACHR,EAAGS,EAAE,MACL+B,EAAQ,EAAC,OACTC,EAAS,GACTk7C,EAAY,GAAOxzC,cAAcpF,EAAMy+D,EAAK7zB,MAAMvmB,WAAau3D,EAEnE,MAAO,CACH39E,QACAxC,KACAC,KACA+iE,OACAz+D,OACAvC,QACAC,SACA2nD,YACAtf,OAAQ6S,EAAY7S,EAAS,EAErC,CAkBA,SAAS81C,GAAgB5yE,EAAM6yE,EAAW/1C,GACtC,MAAMg2C,EAAeD,EAAU79E,MAAM5O,SAE/B,GAAEoM,EAAE,GAAEC,EAAE,MAAE+B,EAAK,OAAEC,GAAWo+E,EAElC,OAAQ7yE,GACJ,IAAK,OACD8yE,EAAa3gF,EAAIK,EAAKsqC,EACtB,MACJ,IAAK,QACDg2C,EAAa3gF,EAAIK,EAAKgC,EAAQsoC,EAC9B,MACJ,IAAK,MACDg2C,EAAa9gF,EAAIS,EAAKqqC,EACtB,MACJ,IAAK,SACDg2C,EAAa9gF,EAAIS,EAAKgC,EAASqoC,EAIvC,OAAOg2C,CACX,CAEA,SAASC,GAAWjnF,EAAMg8E,GAAI,GAAE5yE,EAAK,EAAC,GAAEC,EAAK,IACzC,MAAMR,EAAK,CAAExC,EAAGrG,EAAKkJ,MAAM7C,EAAI+C,EAAIlD,EAAGlG,EAAKkJ,MAAMhD,EAAImD,GAC/CP,EAAK,CAAEzC,EAAG21E,EAAG9yE,MAAM7C,EAAI+C,EAAIlD,EAAG81E,EAAG9yE,MAAMhD,EAAImD,GAEjD,MAAO,CAACrJ,EAAKkJ,MAAOL,EAAIC,EAAIkzE,EAAG9yE,MACnC,CAEA,SAASg+E,GAAYlnF,EAAMg8E,EAAImL,EAAwBn2C,GAEnD,MAAMhsC,EAAQ,GAAiBmiF,EAAyB,IAExD,IAAI/9E,EAAK,EACLC,EAAK,EAEK,KAAVrE,EACAqE,GAAM2nC,EACW,MAAVhsC,EACPoE,GAAM4nC,EACW,MAAVhsC,EACPqE,EAAK2nC,EACY,IAAVhsC,IACPoE,EAAK4nC,GAGT,MAAMo2C,EAAYH,GAAWjnF,EAAMg8E,EAAI,CAAE5yE,KAAIC,OAEvCg+E,EAAqBD,EAAU,GAC/BE,EAAiB,IAAI,GAAOtL,EAAG9yE,MAAOm+E,GAI5C,MAAO,CACHD,YACAG,kBAJsBhC,GAAoBC,GAAgB8B,IAMlE,CAsFA,SAASE,GAAkBv8E,EAAMqlD,EAAWtf,GACxC,OAAQsf,GACJ,KAAK00B,GAAW/rB,KACZhuD,EAAKsD,QAAQ,EAAGyiC,GAAQx9B,cAAc,CAAEnN,GAAI2qC,EAAQtoC,MAAOsoC,IAC3D,MACJ,KAAKg0C,GAAWjsB,MACZ9tD,EAAKsD,QAAQ,EAAGyiC,GAAQx9B,cAAc,CAAE9K,MAAOsoC,IAC/C,MACJ,KAAKg0C,GAAWlsB,IACZ7tD,EAAKsD,QAAQyiC,EAAQ,GAAGx9B,cAAc,CAAEtN,GAAI8qC,EAAQroC,OAAQqoC,IAC5D,MACJ,KAAKg0C,GAAWhsB,OACZ/tD,EAAKsD,QAAQyiC,EAAQ,GAAGx9B,cAAc,CAAE7K,OAAQqoC,IAIxD,OAAO/lC,CACX,CAEA,SAASw8E,GAAmB58F,EAAQuS,EAAQmP,EAAM,CAAC,GAC/C,MAAQrD,MAAOmyE,EAAa30E,GAAIi/E,EAAKh/E,GAAIi/E,EAAKl9E,MAAOg/E,EAAa/+E,OAAQg/E,EAAc32C,OAAQ42C,GAAiB/8F,GACzGqe,MAAOoyE,EAAa50E,GAAIo/E,EAAKn/E,GAAIo/E,EAAKr9E,MAAOm/E,EAAal/E,OAAQm/E,EAAc92C,OAAQ+2C,GAAiB3qF,GAC3G,mBAAE4qF,GAAqB,GAAUz7E,EAEjC07E,EAAMnC,EAAM+B,EACZK,EAAMnC,EAAM+B,EACZp1E,EAAMizE,EAAM+B,EACZ50E,EAAM8yE,EAAM+B,EAGZQ,EAAOxC,EAAMiC,EACbQ,EAAO11E,EAAMk1E,EACbS,EAAOzC,EAAMgC,EACbU,EAAOx1E,EAAM80E,EAEbW,EAAOzC,EAAMiC,EACbS,EAAOP,EAAMF,EACbU,EAAO1C,EAAMgC,EACbW,EAAOR,EAAMH,GAEZ9B,EAAYC,GAAcR,GAAa76F,EAAQuS,GAEhDurF,EAAqB7B,GAAgBb,EAAY,CAAE/8E,MAAOmyE,EAAa30E,GAAIi/E,EAAKh/E,GAAIi/E,EAAKl9E,MAAOg/E,EAAa/+E,OAAQg/E,GAAgBC,GACrIgB,EAAqB9B,GAAgBZ,EAAY,CAAEh9E,MAAOoyE,EAAa50E,GAAIo/E,EAAKn/E,GAAIo/E,EAAKr9E,MAAOm/E,EAAal/E,OAAQm/E,GAAgBC,IAEnI1hF,EAAGwiF,EAAK3iF,EAAG4iF,GAAQH,GACnBtiF,EAAG0iF,EAAK7iF,EAAG8iF,GAAQJ,EAKrBK,IAFOtD,EAAMjzE,GAAO,GAFbozE,EAAMmC,GAAO,EAIkBv1E,EAAMozE,EAAQmC,EAAMtC,GAAQ,EAClEuD,IAFOtD,EAAM9yE,GAAO,GAFbizE,EAAMmC,GAAO,EAIoBp1E,EAAMizE,EAAQmC,EAAMtC,GAAQ,EAEpEzK,EAAa,IAAI,GAAOwK,EAAKC,EAAK8B,EAAaC,GAC/CvM,EAAa,IAAI,GAAO0K,EAAKC,EAAK8B,EAAaC,GAC/CqB,EAAqBhO,EAAW7gF,QAAQiU,QAAQq5E,GAChDwB,EAAqBhO,EAAW9gF,QAAQiU,QAAQw5E,GAEhDsB,EAAoBnmG,OAAOgP,OAAO,CAAC,EAAGrH,EAAQ,CAAE+c,GAAI8K,EAAK5K,GAAIgL,EAAKk0E,aAAc2B,EAAoBr4B,UAAW21B,IAC/GqD,EAAoBpmG,OAAOgP,OAAO,CAAC,EAAGkL,EAAQ,CAAEwK,GAAIqgF,EAAKngF,GAAIogF,EAAKlB,aAAc4B,EAAoBt4B,UAAW41B,KAO9GqD,EAAOC,GAtJlB,SAA+B3+F,EAAQuS,GAEnC,MAAQsJ,GAAIi/E,EAAK/9E,GAAI8K,EAAKs0E,aAAc3L,GAAgBxwF,GAChD6b,GAAIo/E,EAAKl+E,GAAIqgF,EAAKjB,aAAc1L,GAAgBl+E,EAGxD,IAAIqsF,EAAexvF,KAAKE,IAAIwrF,EAAKG,GAE7B4D,EAAgBzvF,KAAKwL,IAAIiN,EAAKu1E,GAGlC,GAAIp9F,EAAOylE,YAAclzD,EAAOkzD,UAAW,CAEvC,MAAMq5B,EAAa9+F,EAAO8b,GAAKvJ,EAAOuJ,GAAK9b,EAASuS,EAC9CwsF,EAAaD,IAAe9+F,EAASuS,EAASvS,EAI9Cg/F,EAAwBh/F,EAAOylE,YAAc00B,GAAWlsB,IAAM6wB,EAAaC,EAEjFH,EAAeI,EAAsBnjF,GACrCgjF,EAAgBG,EAAsBjiF,EAC1C,CAEA,MAAQvB,EAAGwiF,GAAQxN,GACXh1E,EAAG0iF,GAAQzN,EAYnB,MAAO,CATerhF,KAAKoN,IAAIwhF,EAAMY,GACfxvF,KAAKoN,IAAI0hF,EAAMU,GAIdxvF,KAAKoN,IAAIwhF,EAAMa,GACfzvF,KAAKoN,IAAI0hF,EAAMW,GAI1C,CAgH4BI,CAAsBT,EAAmBC,IAO1DS,EAAMC,GApHjB,SAA6Bn/F,EAAQuS,GAEjC,MAAQuJ,GAAIi/E,EAAK99E,GAAIgL,EAAKk0E,aAAc3L,GAAgBxwF,GAChD8b,GAAIo/E,EAAKj+E,GAAIogF,EAAKlB,aAAc1L,GAAgBl+E,EAGxD,IAAI6sF,EAAchwF,KAAKE,IAAIyrF,EAAKG,GAE5BmE,EAAiBjwF,KAAKwL,IAAIqN,EAAKo1E,GAGnC,GAAIr9F,EAAOylE,YAAclzD,EAAOkzD,UAAW,CAEvC,MAAM65B,EAAYt/F,EAAO6b,GAAKtJ,EAAOsJ,GAAK7b,EAASuS,EAC7CgtF,EAAaD,IAAct/F,EAASuS,EAASvS,EAI7Cg/F,EAAwBh/F,EAAOylE,YAAc00B,GAAW/rB,KAAOkxB,EAAYC,EAEjFH,EAAcJ,EAAsBljF,GACpCujF,EAAiBL,EAAsB/hF,EAC3C,CAEA,MAAQ5B,EAAG4iF,GAAQzN,GACXn1E,EAAG8iF,GAAQ1N,EAYnB,MAAO,CATcrhF,KAAKoN,IAAIyhF,EAAMmB,GACfhwF,KAAKoN,IAAI2hF,EAAMiB,GAIZhwF,KAAKoN,IAAIyhF,EAAMoB,GACfjwF,KAAKoN,IAAI2hF,EAAMkB,GAI3C,CA8E4BG,CAAoBhB,EAAmBC,GAG/D,GAAmB,SAAfrD,GAAwC,UAAfC,EAAwB,CACjD,MAAMoE,EAAsBnB,EAAmB1gF,cAAcmgF,GACvD2B,EAAsBnB,EAAmB3gF,cAAckgF,GAG7D,GAAI2B,GAAuBC,EAAqB,CAC5C,MAAMC,GAAmB1B,EAAME,GAAO,EAEtC,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGwiF,EAAK3iF,EAAGskF,GACb,CAAEnkF,EAAG0iF,EAAK7iF,EAAGskF,GACb,CAAEnkF,EAAG0iF,EAAK7iF,EAAG8iF,GAErB,CAEA,GAAIb,EAAOY,EAAK,CACZ,IAAI7iF,EAAIgjF,EACJthF,EAAKihF,EACLhhF,EAAKkhF,EAET,MAAM0B,EAAmBV,EAAOC,EA0BhC,OAtBK9jF,GAAKmiF,GAAQniF,GAAKoiF,GAAUpiF,GAAKuiF,GAAQviF,GAAKwiF,KAC3CJ,GAAQG,GAAQgC,EAChBvkF,EAAIjM,KAAKE,IAAIsuF,EAAMJ,GACZA,GAAQK,IAAS+B,IACxBvkF,EAAIjM,KAAKwL,IAAIijF,EAAMJ,IAKvB1gF,EAAK3N,KAAKE,IAAI0uF,EAAKN,GACnB1gF,EAAK5N,KAAKwL,IAAIsjF,EAAKX,GAGdqC,GAAoB3B,EAAM/C,IAAU0E,GAAoB3B,EAAMZ,EAE/DtgF,EAAKihF,GACG4B,GAAoBzB,EAAMpD,IAAU6E,GAAoBzB,EAAMl2E,KAEtEjL,EAAKkhF,IAIN,CACH,CAAE1iF,EAAGuB,EAAI1B,EAAG4iF,GACZ,CAAEziF,EAAGuB,EAAI1B,KACT,CAAEG,EAAGwB,EAAI3B,KACT,CAAEG,EAAGwB,EAAI3B,EAAG8iF,GAEpB,CAEA,MAAM3iF,GAAKwiF,EAAME,GAAO,EACxB,MAAO,CACH,CAAE1iF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,EAAG8iF,GAEhB,CAAO,GAAmB,UAAf/C,GAAyC,SAAfC,EAAuB,CACxD,MAAMoE,EAAsBnB,EAAmB1gF,cAAcmgF,GACvD2B,EAAsBnB,EAAmB3gF,cAAckgF,GAG7D,GAAI2B,GAAuBC,EAAqB,CAC5C,MAAMC,GAAmB1B,EAAME,GAAO,EAEtC,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGwiF,EAAK3iF,EAAGskF,GACb,CAAEnkF,EAAG0iF,EAAK7iF,EAAGskF,GACb,CAAEnkF,EAAG0iF,EAAK7iF,EAAG8iF,GAErB,CAEA,GAAIZ,EAAOW,EAAK,CACZ,IAAI7iF,EAAIgjF,EACJthF,EAAKihF,EACLhhF,EAAKkhF,EAET,MAAM0B,EAAmBV,EAAOC,EA0BhC,OAtBK9jF,GAAKmiF,GAAQniF,GAAKoiF,GAAUpiF,GAAKuiF,GAAQviF,GAAKwiF,KAC3CJ,GAAQG,GAAQgC,EAChBvkF,EAAIjM,KAAKE,IAAIsuF,EAAMJ,GACZA,GAAQK,IAAS+B,IACxBvkF,EAAIjM,KAAKwL,IAAIijF,EAAMJ,IAKvB1gF,EAAK3N,KAAKwL,IAAIojF,EAAKL,GACnB3gF,EAAK5N,KAAKE,IAAI4uF,EAAKZ,GAGdsC,GAAoB3B,EAAM/C,IAAU0E,GAAoB3B,EAAMZ,EAE/DtgF,EAAKihF,GACG4B,GAAoBzB,EAAMpD,IAAU6E,GAAoBzB,EAAMl2E,KAEtEjL,EAAKkhF,IAIN,CACH,CAAE1iF,EAAGuB,EAAI1B,EAAG4iF,GACZ,CAAEziF,EAAGuB,EAAI1B,KACT,CAAEG,EAAGwB,EAAI3B,KACT,CAAEG,EAAGwB,EAAI3B,EAAG8iF,GAEpB,CAEA,MAAM3iF,GAAKwiF,EAAME,GAAO,EACxB,MAAO,CACH,CAAE1iF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,EAAG8iF,GAEhB,CAAO,GAAmB,QAAf/C,GAAuC,WAAfC,EAAyB,CACxD,MAAMoE,EAAsBnB,EAAmB1gF,cAAcmgF,GACvD2B,EAAsBnB,EAAmB3gF,cAAckgF,GAG7D,GAAI2B,GAAuBC,EAAqB,CAC5C,MAAMC,GAAmB3B,EAAME,GAAO,EAEtC,MAAO,CACH,CAAE1iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGmkF,EAAiBtkF,EAAG4iF,GACzB,CAAEziF,EAAGmkF,EAAiBtkF,EAAG8iF,GACzB,CAAE3iF,EAAG0iF,EAAK7iF,EAAG8iF,GAErB,CAEA,GAAIX,EAAOW,EAAK,CACZ,IAAI3iF,EAAI4iF,EACJnhF,EAAKghF,EACL/gF,EAAKihF,EAET,MAAM0B,EAAgBnB,EAAQC,EA0B9B,OAtBKnjF,GAAK8hF,GAAQ9hF,GAAK+hF,GAAU/hF,GAAKkiF,GAAQliF,GAAKmiF,KAC3CJ,GAAQG,GAAQmC,EAChBrkF,EAAIpM,KAAKE,IAAIouF,EAAMJ,GACZA,GAAQK,IAASkC,IACxBrkF,EAAIpM,KAAKwL,IAAI+iF,EAAMJ,IAKvBtgF,EAAK7N,KAAKE,IAAI2uF,EAAKL,GACnB1gF,EAAK9N,KAAKwL,IAAIujF,EAAKV,GAGdoC,GAAiB7B,EAAM/C,IAAU4E,GAAiB7B,EAAMZ,EAEzDngF,EAAKghF,GACG4B,GAAiB3B,EAAMpD,IAAU+E,GAAiB3B,EAAMr2E,KAEhE3K,EAAKihF,IAIN,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4B,GACb,CAAEzB,IAAGH,EAAG4B,GACR,CAAEzB,IAAGH,EAAG6B,GACR,CAAE1B,EAAG0iF,EAAK7iF,EAAG6B,GAErB,CAEA,MAAM7B,GAAK4iF,EAAME,GAAO,EACxB,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAG0iF,EAAK7iF,KAElB,CAAO,GAAmB,WAAf+/E,GAA0C,QAAfC,EAAsB,CACxD,MAAMoE,EAAsBnB,EAAmB1gF,cAAcmgF,GACvD2B,EAAsBnB,EAAmB3gF,cAAckgF,GAG7D,GAAI2B,GAAuBC,EAAqB,CAC5C,MAAMC,GAAmB3B,EAAME,GAAO,EAEtC,MAAO,CACH,CAAE1iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGmkF,EAAiBtkF,EAAG4iF,GACzB,CAAEziF,EAAGmkF,EAAiBtkF,EAAG8iF,GACzB,CAAE3iF,EAAG0iF,EAAK7iF,EAAG8iF,GAErB,CAEA,GAAIV,EAAOU,EAAK,CACZ,IAAI3iF,EAAI4iF,EACJnhF,EAAKghF,EACL/gF,EAAKihF,EAET,MAAM0B,EAAgBnB,EAAQC,EA0B9B,OAtBKnjF,GAAK8hF,GAAQ9hF,GAAK+hF,GAAU/hF,GAAKkiF,GAAQliF,GAAKmiF,KAC3CJ,GAAQG,GAAQmC,EAChBrkF,EAAIpM,KAAKE,IAAIouF,EAAMJ,GACZA,GAAQK,IAASkC,IACxBrkF,EAAIpM,KAAKwL,IAAI+iF,EAAMJ,IAKvBtgF,EAAK7N,KAAKwL,IAAIqjF,EAAKJ,GACnB3gF,EAAK9N,KAAKE,IAAI6uF,EAAKX,GAGdqC,GAAiB7B,EAAM/C,IAAU4E,GAAiB7B,EAAMZ,EAEzDngF,EAAKghF,GACG4B,GAAiB3B,EAAMpD,IAAU+E,GAAiB3B,EAAMr2E,KAEhE3K,EAAKihF,IAIN,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4B,GACb,CAAEzB,IAAGH,EAAG4B,GACR,CAAEzB,IAAGH,EAAG6B,GACR,CAAE1B,EAAG0iF,EAAK7iF,EAAG6B,GAErB,CAEA,MAAM7B,GAAK4iF,EAAME,GAAO,EACxB,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAG0iF,EAAK7iF,KAElB,CAAO,GAAmB,QAAf+/E,GAAuC,QAAfC,EAAsB,CAQrD,IANI8B,GACA,GAAenjE,aAAaskE,EAAoB/N,IAC/C0N,GAAO/C,IAAQoD,EAAmBr4E,cAAczK,GAAK0iF,GAAOI,EAAmBv4E,aAAavK,GAAK0iF,IACjGD,GAAO/C,IAAQqD,EAAmBt4E,cAAczK,GAAKwiF,GAAOO,EAAmBx4E,aAAavK,GAAKwiF,KAG3EA,IAAQE,EAC/B,MAAO,CACH,CAAE1iF,EAAGwiF,EAAK3iF,EAAGjM,KAAKE,IAAI2uF,EAAKE,IAC3B,CAAE3iF,EAAG0iF,EAAK7iF,EAAGjM,KAAKE,IAAI2uF,EAAKE,KAInC,IAAI3iF,EACAyB,EAAK7N,KAAKE,KAAK2Y,EAAMizE,GAAO,EAAGiD,GAC/BjhF,EAAK9N,KAAKE,KAAKyrF,EAAMsC,GAAO,EAAGY,GAiBnC,OAZQziF,EAHJ2iF,EAAMF,EAEFU,EAASD,EACLtvF,KAAKE,IAAI0uF,EAAKN,GAEdtuF,KAAKwL,IAAIojF,EAAKL,GAGlBgB,EAASD,EACLtvF,KAAKE,IAAI4uF,EAAKZ,GAEdluF,KAAKwL,IAAIsjF,EAAKX,GAInB,CACH,CAAE/hF,EAAGwiF,EAAK3iF,EAAG6B,GACb,CAAE1B,IAAGH,EAAG6B,GACR,CAAE1B,IAAGH,EAAG4B,GACR,CAAEzB,EAAG0iF,EAAK7iF,EAAG4B,GAErB,CAAO,GAAmB,WAAfm+E,GAA0C,WAAfC,EAAyB,CAQ3D,IANI8B,GACA,GAAenjE,aAAaskE,EAAoB/N,IAC/C0N,GAAOE,IAAQG,EAAmB91E,WAAWhN,GAAK0iF,GAAOI,EAAmB52E,UAAUlM,GAAK0iF,IAC3FD,GAAOE,IAAQI,EAAmB/1E,WAAWhN,GAAKwiF,GAAOO,EAAmB72E,UAAUlM,GAAKwiF,KAGrEA,IAAQE,EAC/B,MAAO,CACH,CAAE1iF,EAAGwiF,EAAK3iF,EAAGjM,KAAKwL,IAAIqjF,EAAKE,IAC3B,CAAE3iF,EAAG0iF,EAAK7iF,EAAGjM,KAAKwL,IAAIqjF,EAAKE,KAInC,IAAI3iF,EACAyB,EAAK7N,KAAKwL,KAAKmgF,EAAMsC,GAAO,EAAGc,GAC/BjhF,EAAK9N,KAAKwL,KAAKqN,EAAMizE,GAAO,EAAG+C,GAiBnC,OAZQziF,EAHJ2iF,EAAMF,EAEFU,EAASD,EACLtvF,KAAKE,IAAI0uF,EAAKN,GAEdtuF,KAAKwL,IAAIojF,EAAKL,GAGlBgB,EAASD,EACLtvF,KAAKE,IAAI4uF,EAAKZ,GAEdluF,KAAKwL,IAAIsjF,EAAKX,GAInB,CACH,CAAE/hF,EAAGwiF,EAAK3iF,EAAG6B,GACb,CAAE1B,IAAGH,EAAG6B,GACR,CAAE1B,IAAGH,EAAG4B,GACR,CAAEzB,EAAG0iF,EAAK7iF,EAAG4B,GAErB,CAAO,GAAmB,SAAfm+E,GAAwC,SAAfC,EAAuB,CAQvD,IANI8B,GACA,GAAenjE,aAAaskE,EAAoB/N,IAC/CyN,GAAOE,IAAQI,EAAmBr4E,cAAc5K,GAAK8iF,GAAOG,EAAmB91E,WAAWnN,GAAK8iF,IAC/FH,GAAOE,IAAQK,EAAmBt4E,cAAc5K,GAAK4iF,GAAOM,EAAmB/1E,WAAWnN,GAAK4iF,KAGzEA,IAAQE,EAC/B,MAAO,CACH,CAAE3iF,EAAGpM,KAAKE,IAAI0uF,EAAKE,GAAM7iF,EAAG4iF,GAC5B,CAAEziF,EAAGpM,KAAKE,IAAI0uF,EAAKE,GAAM7iF,EAAG8iF,IAIpC,IAAI9iF,EACA0B,EAAK3N,KAAKE,KAAKuY,EAAMozE,GAAO,EAAGiD,GAC/BlhF,EAAK5N,KAAKE,KAAKwrF,EAAMsC,GAAO,EAAGY,GAgBnC,OAZQ3iF,EAFJ6iF,EAAMF,EACFkB,GAAQC,EACJ/vF,KAAKE,IAAIkuF,EAAMW,GAEf/uF,KAAKwL,IAAI6iF,EAAMU,GAGnBe,GAAQC,EACJ/vF,KAAKE,IAAIsuF,EAAMK,GAEf7uF,KAAKwL,IAAIijF,EAAMI,GAIpB,CACH,CAAEziF,EAAGwB,EAAI3B,EAAG4iF,GACZ,CAAEziF,EAAGwB,EAAI3B,KACT,CAAEG,EAAGuB,EAAI1B,KACT,CAAEG,EAAGuB,EAAI1B,EAAG8iF,GAEpB,CAAO,GAAmB,UAAf/C,GAAyC,UAAfC,EAAwB,CAQzD,IANI8B,GACA,GAAenjE,aAAaskE,EAAoB/N,IAC/CyN,GAAOE,IAAQI,EAAmBv4E,aAAa1K,GAAK8iF,GAAOG,EAAmB52E,UAAUrM,GAAK8iF,IAC7FH,GAAOE,IAAQK,EAAmBx4E,aAAa1K,GAAK4iF,GAAOM,EAAmB72E,UAAUrM,GAAK4iF,KAGvEA,IAAQE,EAC/B,MAAO,CACH,CAAE3iF,EAAGpM,KAAKwL,IAAIojF,EAAKE,GAAM7iF,EAAG4iF,GAC5B,CAAEziF,EAAGpM,KAAKwL,IAAIojF,EAAKE,GAAM7iF,EAAG8iF,IAIpC,IAAI9iF,EACA0B,EAAK3N,KAAKwL,KAAKkgF,EAAMsC,GAAO,EAAGc,GAC/BlhF,EAAK5N,KAAKwL,KAAKiN,EAAMozE,GAAO,EAAG+C,GAgBnC,OAZQ3iF,EAFJ6iF,GAAOF,EACHkB,GAAQC,EACJ/vF,KAAKE,IAAIkuF,EAAMW,GAEf/uF,KAAKwL,IAAI6iF,EAAMU,GAGnBe,GAAQC,EACJ/vF,KAAKE,IAAIsuF,EAAMK,GAEf7uF,KAAKwL,IAAIijF,EAAMI,GAIpB,CACH,CAAEziF,EAAGwB,EAAI3B,EAAG4iF,GACZ,CAAEziF,EAAGwB,EAAI3B,KACT,CAAEG,EAAGuB,EAAI1B,KACT,CAAEG,EAAGuB,EAAI1B,EAAG8iF,GAEpB,CAAO,GAAmB,QAAf/C,GAAuC,UAAfC,EAAwB,CAIvD,GAH4BiD,EAAmB1gF,cAAc6yE,GAGpC,CACrB,GAAIuN,GAAOL,EAAM,CACb,MAAMniF,EAAIpM,KAAKwL,IAAIojF,EAAMjB,EAAcmB,GACjC7iF,EAAIjM,KAAKE,IAAIkuF,EAAMI,GAGzB,MAAO,CACH,CAAEpiF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAGA,EAAGH,KACR,CAAEG,EAAGA,EAAGH,EAAG8iF,GAEnB,CAIA,MAAM2B,GAAiB9B,EAAMjB,EAAemB,GAAO,EAEnD,MAAO,CACH,CAAE1iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGskF,EAAezkF,EAAG4iF,GACvB,CAAEziF,EAAGskF,EAAezkF,EAAG8iF,GAE/B,CAEA,GAAIX,EAAOW,EAAK,CACZ,GAAIH,EAAME,EAAK,CACX,IAAI7iF,EAAIuiF,EAMR,OAJIC,GAAQL,GAAQG,GAAQK,IACxB3iF,EAAIgjF,GAGD,CACH,CAAE7iF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAG0iF,EAAK7iF,KACV,CAAEG,EAAG0iF,EAAK7iF,EAAG8iF,GAErB,CAEA,MAAO,CAAC,CAAE3iF,EAAGwiF,EAAK3iF,EAAG8iF,GACzB,CAEA,MAAM3iF,EAAIpM,KAAKwL,IAAIwjF,EAAuBT,GAE1C,GAAIK,EAAME,GAAOj2E,GAAOk2E,EACpB,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,EAAG8iF,IAIhB,GAAI3iF,EAAI8hF,GAAQW,EAAMZ,EAAK,CACvB,MAAMhiF,EAAIjM,KAAKE,IAAIkuF,EAAMI,GACnBpiF,EAAIpM,KAAKwL,IAAI2iF,EAAMI,GACzB,MAAO,CACH,CAAEniF,EAAGwiF,EAAK3iF,KACV,CAAEG,IAAGH,KACL,CAAEG,IAAGH,EAAG8iF,GAEhB,CAEA,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,EAAG8iF,GAEhB,CAAO,GAAmB,QAAf/C,GAAuC,SAAfC,EAAuB,CAItD,GAH4BiD,EAAmB1gF,cAAc6yE,GAGpC,CACrB,GAAIuN,GAAON,EAAM,CACb,MAAMliF,EAAIpM,KAAKE,IAAI0uF,EAAMjB,EAAcmB,GACjC7iF,EAAIjM,KAAKE,IAAIkuF,EAAMI,GAGzB,MAAO,CACH,CAAEpiF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAGA,EAAGH,KACR,CAAEG,EAAGA,EAAGH,EAAG8iF,GAEnB,CAIA,MAAM2B,GAAiB9B,EAAMjB,EAAemB,GAAO,EAEnD,MAAO,CACH,CAAE1iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGskF,EAAezkF,EAAG4iF,GACvB,CAAEziF,EAAGskF,EAAezkF,EAAG8iF,GAE/B,CAEA,GAAIX,EAAOW,EAAK,CACZ,GAAIH,EAAME,EAAK,CACX,IAAI7iF,EAAIuiF,EAMR,OAJIC,GAAQL,GAAQE,GAAQM,IACxB3iF,EAAIgjF,GAGD,CACH,CAAE7iF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAG0iF,EAAK7iF,KACV,CAAEG,EAAG0iF,EAAK7iF,EAAG8iF,GAErB,CAEA,MAAO,CAAC,CAAE3iF,EAAGwiF,EAAK3iF,EAAG8iF,GACzB,CAEA,MAAM3iF,EAAIpM,KAAKE,IAAIouF,EAAMU,GAEzB,GAAIJ,EAAME,GAAOj2E,GAAOk2E,EACpB,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,EAAG8iF,IAGhB,GAAI3iF,EAAI+hF,GAAQU,EAAMZ,EAAK,CACvB,MAAMhiF,EAAIjM,KAAKE,IAAIkuF,EAAMI,GACnBpiF,EAAIpM,KAAKE,IAAIguF,EAAMI,GACzB,MAAO,CACH,CAAEliF,EAAGwiF,EAAK3iF,KACV,CAAEG,IAAGH,KACL,CAAEG,IAAGH,EAAG8iF,GAEhB,CAEA,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,EAAG8iF,GAEhB,CAAO,GAAmB,WAAf/C,GAA0C,UAAfC,EAAwB,CAI1D,GAH4BiD,EAAmB1gF,cAAc6yE,GAGpC,CACrB,GAAIuN,GAAOL,EAAM,CACb,MAAMniF,EAAIpM,KAAKwL,IAAIojF,EAAMjB,EAAcmB,GACjC7iF,EAAIjM,KAAKwL,IAAI6iF,EAAMI,GAGzB,MAAO,CACH,CAAEriF,EAAGwiF,EAAK3iF,KACV,CAAEG,IAAGH,KACL,CAAEG,IAAGH,EAAG8iF,GAEhB,CAIA,MAAM2B,GAAiB9B,EAAMjB,EAAemB,GAAO,EAEnD,MAAO,CACH,CAAE1iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGskF,EAAezkF,EAAG4iF,GACvB,CAAEziF,EAAGskF,EAAezkF,EAAG8iF,GAE/B,CAEA,GAAIV,EAAOU,EAAK,CACZ,GAAIH,EAAME,EAAK,CACX,IAAI7iF,EAAIwiF,EAMR,OAJID,GAAQH,GAAQE,GAAQK,IACxB3iF,EAAIgjF,GAGD,CACH,CAAE7iF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAG0iF,EAAK7iF,KACV,CAAEG,EAAG0iF,EAAK7iF,EAAG8iF,GAErB,CAEA,MAAO,CAAC,CAAE3iF,EAAGwiF,EAAK3iF,EAAG8iF,GACzB,CAEA,MAAM3iF,EAAIpM,KAAKwL,IAAIwjF,EAAuBT,GAE1C,GAAIK,EAAME,GAAOnD,GAAOoD,EACpB,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,EAAG8iF,IAIhB,GAAI3iF,EAAI8hF,GAAQW,EAAM/C,EAAK,CACvB,MAAM7/E,EAAIjM,KAAKwL,IAAI6iF,EAAMI,GACnBriF,EAAIpM,KAAKwL,IAAI2iF,EAAMI,GACzB,MAAO,CACH,CAAEniF,EAAGwiF,EAAK3iF,KACV,CAAEG,IAAGH,KACL,CAAEG,IAAGH,EAAG8iF,GAEhB,CAEA,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,EAAG8iF,GAEhB,CAAO,GAAmB,WAAf/C,GAA0C,SAAfC,EAAuB,CAIzD,GAH4BiD,EAAmB1gF,cAAc6yE,GAGpC,CACrB,GAAIuN,GAAON,EAAM,CACb,MAAMliF,EAAIpM,KAAKE,IAAI0uF,EAAMjB,EAAcmB,GACjC7iF,EAAIjM,KAAKwL,IAAI6iF,EAAMI,GAGzB,MAAO,CACH,CAAEriF,EAAGwiF,EAAK3iF,KACV,CAAEG,IAAGH,KACL,CAAEG,IAAGH,EAAG8iF,GAEhB,CAIA,MAAM2B,GAAiB9B,EAAMjB,EAAemB,GAAO,EAEnD,MAAO,CACH,CAAE1iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGskF,EAAezkF,EAAG4iF,GACvB,CAAEziF,EAAGskF,EAAezkF,EAAG8iF,GAE/B,CAEA,GAAIV,EAAOU,EAAK,CACZ,GAAIH,EAAME,EAAK,CACX,IAAI7iF,EAAIwiF,EAMR,OAJID,GAAQH,GAAQC,GAAQM,IACxB3iF,EAAIgjF,GAGD,CACH,CAAE7iF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAG0iF,EAAK7iF,KACV,CAAEG,EAAG0iF,EAAK7iF,EAAG8iF,GAErB,CAEA,MAAO,CAAC,CAAE3iF,EAAGwiF,EAAK3iF,EAAG8iF,GACzB,CAEA,MAAM3iF,EAAIpM,KAAKE,IAAIouF,EAAMU,GAEzB,GAAIJ,EAAME,GAAOnD,GAAOoD,EACpB,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,EAAG8iF,IAIhB,GAAI3iF,EAAI+hF,GAAQU,EAAM/C,EAAK,CACvB,MAAM7/E,EAAIjM,KAAKwL,IAAI6iF,EAAMI,GACnBriF,EAAIpM,KAAKE,IAAIguF,EAAMI,GACzB,MAAO,CACH,CAAEliF,EAAGwiF,EAAK3iF,KACV,CAAEG,IAAGH,KACL,CAAEG,IAAGH,EAAG8iF,GAEhB,CAEA,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,EAAG8iF,GAEhB,CAAO,GAAmB,SAAf/C,GAAwC,WAAfC,EAAyB,CAIzD,GAH4BiD,EAAmB1gF,cAAc6yE,GAGpC,CACrB,GAAIwN,GAAOJ,EAAM,CACb,MAAMriF,EAAIpM,KAAKE,IAAIguF,EAAMI,GACnBriF,EAAIjM,KAAKwL,IAAIqjF,EAAMlB,EAAcoB,GAEvC,MAAO,CACH,CAAE3iF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,KACL,CAAEG,EAAG0iF,EAAK7iF,KAElB,CAGA,MAAM0kF,GAAiB9B,EAAMlB,EAAeoB,GAAO,EAEnD,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGwiF,EAAK3iF,EAAG0kF,GACb,CAAEvkF,EAAG0iF,EAAK7iF,EAAG0kF,GAErB,CAEA,GAAIzC,EAAOY,EAAK,CACZ,GAAID,EAAME,EAAK,CACX,IAAI3iF,EAAIkiF,EAMR,OAJIC,GAAQL,GAAQO,GAAQI,IACxBziF,EAAI4iF,GAGD,CACH,CAAE5iF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,EAAG8iF,GACR,CAAE3iF,EAAG0iF,EAAK7iF,EAAG8iF,GAErB,CAEA,MAAO,CAAC,CAAE3iF,EAAG0iF,EAAK7iF,EAAG4iF,GACzB,CAEA,MAAM5iF,EAAIjM,KAAKwL,IAAIijF,EAAMQ,GAEzB,GAAIJ,EAAME,GAAOt2E,GAAOq2E,EACpB,MAAO,CACH,CAAE1iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAG0iF,EAAK7iF,MAIlB,GAAIA,EAAImiF,GAAQQ,EAAMZ,EAAK,CACvB,MAAM5hF,EAAIpM,KAAKE,IAAIguF,EAAMI,GACnBriF,EAAIjM,KAAKwL,IAAI6iF,EAAMI,GAEzB,MAAO,CACH,CAAEriF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,KACL,CAAEG,EAAG0iF,EAAK7iF,KAElB,CAEA,MAAO,CACH,CAAEG,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAG0iF,EAAK7iF,KAElB,CAAO,GAAmB,SAAf+/E,GAAwC,QAAfC,EAAsB,CAItD,GAH4BiD,EAAmB1gF,cAAc6yE,GAGpC,CACrB,GAAIwN,GAAOL,EAAM,CACb,MAAMviF,EAAIjM,KAAKE,IAAI2uF,EAAMlB,EAAcoB,GACjC3iF,EAAIpM,KAAKE,IAAIguF,EAAMI,GAGzB,MAAO,CACH,CAAEliF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,KACL,CAAEG,EAAG0iF,EAAK7iF,KAElB,CAIA,MAAM0kF,GAAiB9B,EAAMlB,EAAeoB,GAAO,EAEnD,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGwiF,EAAK3iF,EAAG0kF,GACb,CAAEvkF,EAAG0iF,EAAK7iF,EAAG0kF,GAErB,CAEA,GAAIzC,EAAOY,EAAK,CACZ,GAAID,EAAME,EAAK,CACX,IAAI3iF,EAAIkiF,EAMR,OAJIC,GAAQL,GAAQM,GAAQK,IACxBziF,EAAI4iF,GAGD,CACH,CAAE5iF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,EAAG8iF,GACR,CAAE3iF,EAAG0iF,EAAK7iF,EAAG8iF,GAErB,CAEA,MAAO,CAAC,CAAE3iF,EAAG0iF,EAAK7iF,EAAG4iF,GACzB,CAEA,MAAM5iF,EAAIjM,KAAKE,IAAIsuF,EAAMS,GAEzB,GAAIJ,EAAME,GAAOt2E,GAAOq2E,EACpB,MAAO,CACH,CAAE1iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAG0iF,EAAK7iF,MAGlB,GAAIA,EAAIoiF,GAAQO,EAAMZ,EAAK,CACvB,MAAM5hF,EAAIpM,KAAKE,IAAIguF,EAAMI,GACnBriF,EAAIjM,KAAKE,IAAIkuF,EAAMI,GACzB,MAAO,CACH,CAAEpiF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,KACL,CAAEG,EAAG0iF,EAAK7iF,KAElB,CAEA,MAAO,CACH,CAAEG,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAG0iF,EAAK7iF,KAElB,CAAO,GAAmB,UAAf+/E,GAAyC,QAAfC,EAAsB,CAIvD,GAH4BiD,EAAmB1gF,cAAc6yE,GAGpC,CACrB,GAAIwN,GAAOL,EAAM,CACb,MAAMpiF,EAAIpM,KAAKwL,IAAI2iF,EAAMI,GACnBtiF,EAAIjM,KAAKE,IAAI2uF,EAAMlB,EAAcoB,GAGvC,MAAO,CACH,CAAE3iF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,KACL,CAAEG,EAAG0iF,EAAK7iF,KAElB,CAIA,MAAM0kF,GAAiB9B,EAAMlB,EAAeoB,GAAO,EAEnD,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGwiF,EAAK3iF,EAAG0kF,GACb,CAAEvkF,EAAG0iF,EAAK7iF,EAAG0kF,GAErB,CAEA,GAAIxC,EAAOW,EAAK,CACZ,GAAID,EAAME,EAAK,CACX,IAAI3iF,EAAImiF,EAMR,OAJID,GAAQH,GAAQK,GAAQK,IACxBziF,EAAI4iF,GAGD,CACH,CAAE5iF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,EAAG8iF,GACR,CAAE3iF,EAAG0iF,EAAK7iF,EAAG8iF,GAErB,CAEA,MAAO,CAAC,CAAE3iF,EAAG0iF,EAAK7iF,EAAG4iF,GACzB,CAEA,MAAM5iF,EAAIjM,KAAKE,IAAIsuF,EAAMS,GAEzB,GAAIJ,EAAME,GAAOrD,GAAOoD,EACpB,MAAO,CACH,CAAE1iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAG0iF,EAAK7iF,MAGlB,GAAIA,EAAIoiF,GAAQO,EAAM/C,EAAK,CACvB,MAAMz/E,EAAIpM,KAAKwL,IAAI2iF,EAAMI,GACnBtiF,EAAIjM,KAAKE,IAAIkuF,EAAMI,GAEzB,MAAO,CACH,CAAEpiF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,KACL,CAAEG,EAAG0iF,EAAK7iF,KAElB,CAEA,MAAO,CACH,CAAEG,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAG0iF,EAAK7iF,KAElB,CAAO,GAAmB,UAAf+/E,GAAyC,WAAfC,EAAyB,CAI1D,GAH4BiD,EAAmB1gF,cAAc6yE,GAGpC,CACrB,GAAIwN,GAAOJ,EAAM,CACb,MAAMriF,EAAIpM,KAAKwL,IAAI2iF,EAAMI,GACnBtiF,EAAIjM,KAAKwL,IAAIqjF,EAAMlB,EAAcoB,GAEvC,MAAO,CACH,CAAE3iF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,KACL,CAAEG,EAAG0iF,EAAK7iF,KAElB,CAGA,MAAM0kF,GAAiB9B,EAAMlB,EAAeoB,GAAO,EAEnD,MAAO,CACH,CAAE3iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGwiF,EAAK3iF,EAAG0kF,GACb,CAAEvkF,EAAG0iF,EAAK7iF,EAAG0kF,GAErB,CAEA,GAAIxC,EAAOW,EAAK,CACZ,GAAID,EAAME,EAAK,CACX,IAAI3iF,EAAImiF,EAMR,OAJID,GAAQH,GAAQM,GAAQI,IACxBziF,EAAI4iF,GAGD,CACH,CAAE5iF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,EAAG8iF,GACR,CAAE3iF,EAAG0iF,EAAK7iF,EAAG8iF,GAErB,CAEA,MAAO,CAAC,CAAE3iF,EAAG0iF,EAAK7iF,EAAG4iF,GACzB,CAEA,MAAM5iF,EAAIjM,KAAKwL,IAAIijF,EAAMQ,GAEzB,GAAIJ,EAAME,GAAOrD,GAAOoD,EACpB,MAAO,CACH,CAAE1iF,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAG0iF,EAAK7iF,MAIlB,GAAIA,EAAImiF,GAAQQ,EAAM/C,EAAK,CACvB,MAAMz/E,EAAIpM,KAAKwL,IAAI2iF,EAAMI,GACnBtiF,EAAIjM,KAAKwL,IAAI6iF,EAAMI,GAEzB,MAAO,CACH,CAAEriF,IAAGH,EAAG4iF,GACR,CAAEziF,IAAGH,KACL,CAAEG,EAAG0iF,EAAK7iF,KAElB,CAEA,MAAO,CACH,CAAEG,EAAGwiF,EAAK3iF,EAAG4iF,GACb,CAAEziF,EAAGwiF,EAAK3iF,KACV,CAAEG,EAAG0iF,EAAK7iF,KAElB,CACJ,CAEA,SAAS2kF,GAAmBv6B,EAAWtrD,EAAOgsC,GAC1C,MAAM85C,EAAex6B,IAAc00B,GAAW/rB,MAAQ3I,IAAc00B,GAAWjsB,MAE/E,IAAI3vD,EAAK,EACLC,EAAK,EAET,OAAQ,GAAiBpP,KAAKsK,MAAMS,KAChC,KAAK,EACL,KAAK,GACDoE,EAAK0hF,EAAe,EAAI95C,EACxB3nC,EAAKyhF,EAAe95C,EAAS,EAC7B,MACJ,KAAK,IACL,KAAK,IACD5nC,EAAK0hF,EAAe,GAAK95C,EACzB3nC,EAAKyhF,GAAgB95C,EAAS,EAItC,MAAO,CAAE5nC,KAAIC,KACjB,CAEA,SAAS0hF,GAAiBz3B,EAAU/mD,EAAK0hE,GACrC,MAAM,gBAAE4X,EAAkBb,GAAWC,KAAI,gBAAEe,EAAkBhB,GAAWC,MAAS14E,EAC3EykC,EAASzkC,EAAIykC,QAAU,GACvBg6C,EAAcz+E,EAAIy+E,cAAe,EAEjCC,IAAiBhd,EAASp4B,MAAMhrD,SAASmzD,KACzCq9B,EAAcsL,GAAoB1Y,EAASqH,WAAYrH,EAASyP,aAAczP,EAASkN,WAAY0K,EAAiBoF,EAAchd,EAASyP,aAAc1sC,GAEzJk6C,IAAiBjd,EAASp4B,MAAMz4C,SAAS4gD,KACzCs9B,EAAcqL,GAAoB1Y,EAASwH,WAAYxH,EAAS2P,aAAc3P,EAASmN,WAAY4K,EAAiBkF,EAAcjd,EAAS2P,aAAc5sC,GAE/J,IAAIm6C,EAAiB,GAErB,IAAKH,GAAmC,IAApB13B,EAAS5pE,OACzB,OAAO+7F,GAAegC,GAAmBpM,EAAaC,IAG1D,MAAM8P,EAAe93B,EAASzqE,KAAKs5C,GAztCvC,UAA6B,EAAE97B,EAAC,EAAEH,IAC9B,MAAMgD,EAAQ,IAAI,GAAQ7C,EAAGH,GAE7B,MAAO,CACHgD,QACAxC,GAAIwC,EAAM7C,EACVM,GAAIuC,EAAMhD,EACVwjE,KAAM,KACNz+D,KAAM,IAAI,GAAO5E,EAAGH,EAAG,EAAG,GAC1BwC,MAAO,EACPC,OAAQ,EACR2nD,UAAW,KACXtf,OAAQ,EAEhB,CA2sC6Cq6C,CAAoBlpD,MACtDmpD,GAAeF,GAEfG,GAA2B7F,GAAarK,EAAaiQ,GACtDznC,EAAYw3B,EAAY3R,MAAQ2R,EAAY3R,KAAK7zB,MAAMgO,YACvDs3B,EAAat3B,EAAY2jC,GAAkBnM,EAAY3R,KAAK7zB,MAAMvmB,UAAWi8D,EAAyBv6C,GAAU,KAChHw6C,IAAiB3nC,GAAYs3B,EAAW1yE,cAAc6iF,EAAYpiF,OAExE,GAAIsiF,EAAgB,CAChB,MAAMxE,EAAeF,GAAgByE,EAAyBlQ,EAAarqC,GACrEy6C,EAAoBzE,EAAaj+E,OAAOuiF,EAAYpiF,OAEpDwiF,EAAmBrQ,EAAYnyE,MAAM7C,IAAMilF,EAAYpiF,MAAM7C,EAC7DslF,EAAqBtQ,EAAYnyE,MAAMhD,IAAMolF,EAAYpiF,MAAMhD,EAE/D0lF,EAAsBF,IAAqBH,IAA4BvG,GAAWlsB,KAAOyyB,IAA4BvG,GAAWhsB,QAChI6yB,EAAwBF,IAAuBJ,IAA4BvG,GAAW/rB,MAAQsyB,IAA4BvG,GAAWjsB,OAErI+yB,EAAe,IAAI,GAAOzQ,EAAYnyE,MAAO89E,GAC7C+E,EAAoBD,EAAarjF,cAAc6iF,EAAYpiF,OAE3D8iF,EAA2BR,IAAmBK,GAAyBD,GAI7E,GAAIH,EACAN,EAAerhG,KAAKuxF,EAAYnyE,MAAOoiF,EAAYpiF,OAEnDoiF,EAAYh7B,UAAY+0B,GAAoBkG,QACzC,GAAIQ,GAAqBC,EAA0B,CAEtD,MAAMhnF,EAAQwgF,GAAgBuG,EAAoBD,EAAe,IAAI,GAAOzQ,EAAYnyE,MAAOoiF,EAAYpiF,SACrG,GAAEE,EAAE,GAAEC,GAAOwhF,GAAmBU,EAAyBvmF,EAAOgsC,GAEhE4jB,EAAOqyB,GAAW,CAAE/9E,MAAO89E,GAAgBsE,EAAa,CAAEliF,KAAIC,OAC9Dg+E,EAAqBzyB,EAAK,GAC1B0yB,EAAiB,IAAI,GAAOgE,EAAYpiF,MAAOm+E,GAE/C4E,EAAkB1G,GAAoBC,GAAgB8B,IAC5DgE,EAAYh7B,UAAY27B,EACxBd,EAAerhG,QAAQ8qE,EAC3B,MAEI02B,EAAYh7B,UAAYi7B,EACxBD,EAAYt6C,OAASA,EACrBm6C,EAAerhG,QAAQ29F,GAAmBpM,EAAaiQ,EAAa,CAAEtD,oBAAoB,IAASsD,EAAYpiF,MAEvH,KAAO,CAEH,MACMonD,EA10Cd,SAAiCzlE,EAAQuS,EAAQ8uF,GAC7C,MAAOjG,GAAcP,GAAa76F,EAAQuS,GAE1C,OAAQ6oF,GACJ,KAAKjB,GAAWlsB,IACZ,OArJZ,SAAiCjuE,EAAQuS,EAAQ8uF,GAC7C,MAAQxlF,GAAIi/E,EAAKh/E,GAAIi/E,EAAG,MAAEl9E,EAAK,OAAEC,EAAQO,MAAOo4E,EAAM,OAAEtwC,GAAWnmD,EAE7DioB,EAAM8yE,EAAMj9E,EACZw/E,EAAOxC,EAAM30C,EACbo3C,EAHMzC,EAAMj9E,EAGCsoC,EACbq3C,EAAOzC,EAAM50C,GAEX3qC,EAAGg6B,GAAOihD,GACV56E,GAAIqH,EAAIpH,GAAIqH,GAAO5Q,EAE3B,OAAI2Q,IAAOsyB,GAAMryB,EAAK43E,EAAYZ,GAAWhsB,OACzCjrD,EAAKsyB,GAAMryB,EAAKq6E,EACZ6D,EAAWhjF,MAAM7C,IAAMg6B,EAAW2kD,GAAWhsB,OAC1CgsB,GAAWjsB,MAElBhrD,EAAKsyB,GAAMryB,EAAKq6E,EACZ6D,EAAWhjF,MAAM7C,IAAMg6B,EAAW2kD,GAAWhsB,OAC1CgsB,GAAW/rB,KAElBlrD,EAAKo6E,GAAQn6E,EAAKq6E,GAClBt6E,EAAKq6E,GAAQp6E,EAAKq6E,EADarD,GAAWlsB,IAE1C/qD,GAAMo6E,GAAQp6E,GAAMsyB,GAAMryB,EAAK8E,GAM/B/E,GAAMq6E,GAAQr6E,GAAMsyB,GAAMryB,EAAK8E,EAL3Bo5E,EAAWhjF,MAAM7C,EAAI0H,EACdi3E,GAAWjsB,MAEfisB,GAAW/rB,KASf+rB,GAAWhsB,MACtB,CAiHmBmzB,CAAwBthG,EAAQuS,EAAQ8uF,GACnD,KAAKlH,GAAWjsB,MACZ,OAzCZ,SAAmCluE,EAAQuS,EAAQ8uF,GAC/C,MAAQvlF,GAAIi/E,EAAKl/E,GAAIi/E,EAAG,MAAEj9E,EAAK,OAAEC,EAAQO,MAAOo4E,EAAM,OAAEtwC,GAAWnmD,EAG7Du9F,EAFMzC,EAAMj9E,EAECsoC,EACbq3C,EAAOzC,EAAM50C,EACbs3C,EAHM1C,EAAMj9E,EAGCqoC,GAEX3qC,EAAGg6B,EAAIn6B,EAAGo6B,GAAOghD,GACjB56E,GAAIqH,EAAIpH,GAAIqH,GAAO5Q,EAE3B,OAAI2Q,EAAKsyB,GAAMryB,IAAOsyB,EAAW0kD,GAAW/rB,KACxClrD,GAAMq6E,GAAQp6E,EAAKsyB,EAAW0kD,GAAWhsB,OACzCjrD,GAAMq6E,GAAQp6E,EAAKsyB,EAAW0kD,GAAWlsB,IACzC/qD,GAAMq6E,GAAQp6E,EAAKq6E,GACnBt6E,GAAMq6E,GAAQp6E,EAAKs6E,EADatD,GAAWjsB,MAE3ChrD,EAAK43E,GAAO33E,GAAMq6E,GAAQr6E,GAAMsyB,GAOhCvyB,EAAK43E,GAAO33E,GAAMs6E,GAAQt6E,GAAMsyB,EAN5B4rD,EAAWhjF,MAAMhD,EAAI8H,EACdg3E,GAAWhsB,OAGfgsB,GAAWlsB,IAUfksB,GAAW/rB,IACtB,CASmBmzB,CAA0BvhG,EAAQuS,EAAQ8uF,GACrD,KAAKlH,GAAWhsB,OACZ,OAnHZ,SAAoCnuE,EAAQuS,EAAQ8uF,GAChD,MAAQxlF,GAAIi/E,EAAKh/E,GAAIi/E,EAAG,MAAEl9E,EAAK,OAAEC,EAAQO,MAAOo4E,EAAM,OAAEtwC,GAAWnmD,EAE7DioB,EAAM8yE,EAAMj9E,EACZw/E,EAAOxC,EAAM30C,EACbo3C,EAHMzC,EAAMj9E,EAGCsoC,EACbs3C,EAAOx1E,EAAMk+B,GAEX3qC,EAAGg6B,GAAOihD,GACV56E,GAAIqH,EAAIpH,GAAIqH,GAAO5Q,EAE3B,OAAI2Q,IAAOsyB,GAAMryB,EAAK8E,EAAYkyE,GAAWlsB,IACzC/qD,EAAKsyB,GAAMryB,EAAKs6E,EACZ4D,EAAWhjF,MAAM7C,IAAMg6B,EAAW2kD,GAAWlsB,IAC1CksB,GAAWjsB,MAElBhrD,EAAKsyB,GAAMryB,EAAKs6E,EACZ4D,EAAWhjF,MAAM7C,IAAMg6B,EAAW2kD,GAAWlsB,IAC1CksB,GAAW/rB,KAElBlrD,EAAKo6E,GAAQn6E,EAAKs6E,GAClBv6E,EAAKq6E,GAAQp6E,EAAKs6E,EADatD,GAAWhsB,OAE1CjrD,GAAMo6E,GAAQp6E,GAAMsyB,GAAMryB,EAAK43E,GAM/B73E,GAAMq6E,GAAQr6E,GAAMsyB,GAAMryB,EAAK43E,EAL3BsG,EAAWhjF,MAAM7C,EAAI0H,EACdi3E,GAAWjsB,MAEfisB,GAAW/rB,KASf+rB,GAAWlsB,GACtB,CA+EmBuzB,CAA2BxhG,EAAQuS,EAAQ8uF,GACtD,KAAKlH,GAAW/rB,KACZ,OA/EZ,SAAkCpuE,EAAQuS,EAAQ8uF,GAC9C,MAAQvlF,GAAIi/E,EAAKl/E,GAAIi/E,EAAG,MAAEj9E,EAAK,OAAEC,EAAQO,MAAOo4E,EAAM,OAAEtwC,GAAWnmD,EAC7D6nB,EAAMizE,EAAMj9E,EAEZy/E,EAAOxC,EAAM30C,EACbq3C,EAAOzC,EAAM50C,EACbs3C,EAHM1C,EAAMj9E,EAGCqoC,GAEX3qC,EAAGg6B,EAAIn6B,EAAGo6B,GAAOghD,GACjB56E,GAAIqH,EAAIpH,GAAIqH,GAAO5Q,EAE3B,OAAI2Q,EAAKsyB,GAAMryB,IAAOsyB,EAAW0kD,GAAWjsB,MACxChrD,GAAMo6E,GAAQn6E,EAAKsyB,EAAW0kD,GAAWhsB,OACzCjrD,GAAMo6E,GAAQn6E,EAAKsyB,EAAW0kD,GAAWlsB,IACzC/qD,GAAMo6E,GAAQn6E,EAAKq6E,GACnBt6E,GAAMo6E,GAAQn6E,EAAKs6E,EADatD,GAAW/rB,KAE3ClrD,EAAK2E,GAAO1E,GAAMq6E,GAAQr6E,GAAMsyB,GAOhCvyB,EAAK2E,GAAO1E,GAAMs6E,GAAQt6E,GAAMsyB,EAN5B4rD,EAAWhjF,MAAMhD,EAAI8H,EACdg3E,GAAWhsB,OAGfgsB,GAAWlsB,IAUfksB,GAAWjsB,KACtB,CA+CmBuzB,CAAyBzhG,EAAQuS,EAAQ8uF,GAE5D,CA6zC0BK,CAAwBlR,EAAaiQ,EAD1CF,EAAa,IAAM9P,GAEhCgQ,EAAYh7B,UAAYA,EAExB66B,EAAerhG,QAAQ29F,GAAmBpM,EAAaiQ,GAAcA,EAAYpiF,MACrF,CAEA,IAAK,IAAIlK,EAAI,EAAGA,EAAIosF,EAAa1hG,OAAS,EAAGsV,IAAK,CAC9C,MAAMgB,EAAOorF,EAAapsF,GACpBg9E,EAAKoP,EAAapsF,EAAI,GAGtBmoF,EAAyB3B,GADL,IAAI,GAAOxlF,EAAKkJ,MAAO8yE,EAAG9yE,QAEpD,GAAIi+E,EAAyB,IAAO,EAAG,CAEnC,MAAMqF,EAAsBjH,GAAoB4B,GAE1CsF,EAAkBhH,GAAe,IAAI0F,EAAgBnrF,EAAKkJ,QAG1DwjF,EAAgB,IAAI,GAAOD,EAAgBA,EAAgB/iG,OAAS,GAAI+iG,EAAgBA,EAAgB/iG,OAAS,IAEjHuiG,EAAkB1G,GAAoBtrF,KAAKsK,MAAMihF,GAAgBkH,KASvE,GAAIF,IAAwBnH,GAAoB4G,GAAkB,CAE9Dd,EAAerhG,KAAKkW,EAAKkJ,MAAO8yE,EAAG9yE,OACnC,MAAO,CAAEyjF,GAAejH,GAAa1lF,EAAMg8E,GAC3CA,EAAG1rB,UAAYq8B,CACnB,KAAO,CAEH,MAAM,UAAEvF,EAAS,kBAAEG,GAAsBL,GAAYlnF,EAAMg8E,EAAImL,EAAwBn2C,GACvFgrC,EAAG1rB,UAAYi3B,EAEf4D,EAAerhG,QAAQs9F,EAC3B,CAEA,QACJ,CAKA,MAAOwF,EAAeD,GAAeE,GAAiB7sF,EAAMg8E,GAE5Dh8E,EAAKswD,UAAYs8B,EACjB5Q,EAAG1rB,UAAYq8B,EAEfxB,EAAerhG,QAAQ29F,GAAmBznF,EAAMg8E,GAAKA,EAAG9yE,MAC5D,CAEA,MAAM4jF,EAAa1B,EAAaA,EAAa1hG,OAAS,GAEtD,GAAI4xF,EAAY5R,MAAQ4R,EAAY5R,KAAK7zB,MAAMgO,YAAa,CACxD,MAAO,CAAEkpC,GAA2BrH,GAAaoH,EAAYxR,GACvD0L,EAAeF,GAAgBiG,EAAyBzR,EAAatqC,GAIrEg8C,EAAavH,GAAe,IAAI0F,EAAgB2B,EAAW5jF,QAC3D+jF,EAAoB,IAAI,GAAOD,EAAWA,EAAWtjG,OAAS,GAAIsjG,EAAWA,EAAWtjG,OAAS,IACjGwjG,EAAyBjzF,KAAKsK,MAAMihF,GAAgByH,IACpDE,EAAmB5H,GAAoB2H,GAEvCE,EAAmBpG,EAAaj+E,OAAO+jF,EAAW5jF,OAExD,IAAKkkF,GAAqBA,GAAoBD,IAAqBJ,EAA0B,CAEzFD,EAAWx8B,UAAY68B,EAEvB,IAAIE,EAAmB5F,GAAmBqF,EAAYxR,GACtD,MAAOzyE,EAAIC,GAAM28E,GAAe,IAAI4H,EAAkB/R,EAAYpyE,QAE5D5V,EAAc,IAAI,GAAOuV,EAAIC,GAC7BwkF,EAA0BrzF,KAAKsK,MAAMihF,GAAgBlyF,IACrDi6F,EAAuBhI,GAAoB+H,GAE3ClS,EAAaoM,GAAkBlM,EAAY5R,KAAK7zB,MAAMvmB,UAAWy9D,EAAyB/7C,GAE1F06C,EAAmBoB,EAAW5jF,MAAM7C,IAAMi1E,EAAYpyE,MAAM7C,EAC5DslF,EAAqBmB,EAAW5jF,MAAMhD,IAAMo1E,EAAYpyE,MAAMhD,EAC9DslF,EAAiBpQ,EAAW3yE,cAAcqkF,EAAW5jF,OAErD0iF,EAAsBF,IAAqBqB,IAA4B/H,GAAWlsB,KAAOi0B,IAA4B/H,GAAWhsB,QAChI6yB,EAAwBF,IAAuBoB,IAA4B/H,GAAW/rB,MAAQ8zB,IAA4B/H,GAAWjsB,OAG3I,IAAKq0B,GAAoB5B,IAAmBK,GAAyBD,GAAsB,CAGvF,MAAM,GAAExiF,EAAE,GAAEC,GAAOwhF,GAAmBkC,EAAyBG,EAAwBl8C,GACvFq8C,EAAmBpG,GAAW6F,EAAY,CAAE5jF,MAAO89E,GAAgB,CAAE59E,KAAIC,MAC7E,MAAWmiF,GAAkBuB,IAA4B1H,GAAoB8H,IACzEL,EAAW97C,OAASA,EACpB87C,EAAWx8B,UAAYy8B,EACvBM,EAAmB5F,GAAmBqF,EAAYxR,IAC3CiS,IAAyBJ,GAAoBA,IAAqB9H,GAAoBkI,KAC7FT,EAAW97C,OAASA,EACpBq8C,EAAmB5F,GAAmBqF,EAAYxR,IAGtD6P,EAAerhG,QAAQujG,EAC3B,CACJ,KAAO,CAEH,MAAMrtF,EAAO8sF,EACP9Q,EAAKV,EAGL6L,EAAyB3B,GADL,IAAI,GAAOxlF,EAAKkJ,MAAO8yE,EAAG9yE,QAEpD,GAAIi+E,EAAyB,IAAO,EAAG,CAEnC,MAAMqF,EAAsBjH,GAAoB4B,GAE1CsF,EAAkBhH,GAAe0F,GAEjCuB,EAAgB,IAAI,GAAOD,EAAgBA,EAAgB/iG,OAAS,GAAIsW,EAAKkJ,OAC7E+iF,EAAkB1G,GAAoBtrF,KAAKsK,MAAMihF,GAAgBkH,KAEvE,GAAIF,IAAwBnH,GAAoB4G,GAG5Cd,EAAerhG,KAAKkW,EAAKkJ,WACtB,CAEH,MAAM,UAAEk+E,GAAcF,GAAYlnF,EAAMg8E,EAAImL,EAAwBn2C,GAEpEo2C,EAAU3uF,MAEV0yF,EAAerhG,QAAQs9F,EAC3B,CACJ,KAAO,CAGH,MAAOwF,EAAeD,GAAeE,GAAiB7sF,EAAMg8E,GAE5Dh8E,EAAKswD,UAAYs8B,EACjB5Q,EAAG1rB,UAAYq8B,EAEfxB,EAAerhG,QAAQ29F,GAAmBznF,EAAMg8E,GACpD,CACJ,CAEA,OAAOyJ,GAAe0F,EAC1B,CAEA,SAAS0B,GAAiB7sF,EAAMg8E,GAC5B,MAAMiQ,EAAkBjsF,EAAKswD,UACvBk9B,EAAsBlI,GAAoBp0F,SAAS+6F,GAEzD,IAAIpG,EAAkB7lF,EAAKswD,UACvB01B,EAAkBhK,EAAG1rB,UAEzB,GAAIk9B,EAAqB,CACrB,MAAMC,EAAYztF,EAAKkJ,MAAMhD,EAAI81E,EAAG9yE,MAAMhD,EACpCkD,EAAK4yE,EAAG9yE,MAAM7C,EAAIrG,EAAKkJ,MAAM7C,EAE/B4lF,IAAoBjH,GAAWhsB,QAE/B6sB,EAAkB4H,EAAYpI,GAAoB4G,GAAmB7iF,GAAM,EAAI47E,GAAWjsB,MAAQisB,GAAW/rB,KAEzG7vD,EAAK,EACL48E,EAAkByH,EAAYzI,GAAW/rB,KAAO+rB,GAAWlsB,IACpD1vD,EAAK,IACZ48E,EAAkByH,EAAYzI,GAAWjsB,MAAQisB,GAAWlsB,OAIhE+sB,EAAkB4H,EAAYrkF,GAAM,EAAI47E,GAAWjsB,MAAQisB,GAAW/rB,KAAOosB,GAAoB4G,GAE7F7iF,EAAK,EACL48E,EAAkByH,EAAYzI,GAAWhsB,OAASgsB,GAAW/rB,KACtD7vD,EAAK,IACZ48E,EAAkByH,EAAYzI,GAAWhsB,OAASgsB,GAAWjsB,OAGzE,KAAO,CACH,MAAM20B,EAAW1tF,EAAKkJ,MAAM7C,EAAI21E,EAAG9yE,MAAM7C,EACnCgD,EAAK2yE,EAAG9yE,MAAMhD,EAAIlG,EAAKkJ,MAAMhD,EAE/B+lF,IAAoBjH,GAAWjsB,OAC/B8sB,EAAkB6H,EAAWrI,GAAoB4G,GAAmB5iF,GAAM,EAAI27E,GAAWhsB,OAASgsB,GAAWlsB,IAEzGzvD,EAAK,EACL28E,EAAkB0H,EAAW1I,GAAWlsB,IAAMksB,GAAW/rB,KAClD5vD,EAAK,IACZ28E,EAAkB0H,EAAW1I,GAAWhsB,OAASgsB,GAAW/rB,QAGhE4sB,EAAkB6H,EAAWrkF,GAAM,EAAI27E,GAAWhsB,OAASgsB,GAAWlsB,IAAMusB,GAAoB4G,GAE5F5iF,EAAK,EACL28E,EAAkB0H,EAAW1I,GAAWjsB,MAAQisB,GAAWlsB,IACpDzvD,EAAK,IACZ28E,EAAkB0H,EAAW1I,GAAWjsB,MAAQisB,GAAWhsB,QAGvE,CAEA,MAAO,CAAC6sB,EAAiBG,EAC7B,CAEA+E,GAAiB/F,WAAaA,GAEvB,MAAM2I,GAAa5C,GCxvDpB6C,GAAc,CAChBC,MAAO,QACPC,MAAO,QACPC,KAAM,OACNC,IAAK,OAGHC,GAAuB/qG,OAAOwF,OAAOklG,IAErCM,GAAgB,GAChBv0E,GAAY,EAELw0E,GAAW,SAAS9S,EAAaC,EAAa8S,EAAc,GAAI7hF,EAAM,CAAC,GAEhF,MAAM,WACF8hF,EAAaT,GAAYC,MAAK,aAC9BS,EAAeJ,GAAa,0BAC5BK,GAA4B,EAAK,UACjCnkF,EAAYuP,GAAS,IACrB41D,GAAM,GACNhjE,EAEJ,IAAkD,IAA9C0hF,GAAqB98F,QAAQk9F,GAE7B,MAAM,IAAIntF,MAAM,0DAGpB,IAAIlR,EAEJ,GAAKq+F,IAAeT,GAAYC,OAAWS,EAOpC,CAOH,IAAIE,EALJx+F,EAAO,IAAI,GAGXA,EAAKiuB,cAAc,GAAOE,cAAc,IAAKk9D,IAG7C,MAAMoT,EAAoBL,EAAY1kG,OACtC,IAAK,IAAIsV,EAAI,EAAGA,EAAIyvF,EAAmBzvF,IAAK,CAExC,MAAM0vF,EAAO,IAAI,GAAQN,EAAYpvF,IAC/B2/B,EAAQyvD,EAAYpvF,EAAI,IAAMq8E,EAC9BvgF,EAAQszF,EAAYpvF,EAAI,IAAMs8E,EAC9BqT,EAAgBH,GAAiBE,EAAKhnF,SAASi3B,GAAQ,EAG7D,IAAIiwD,EAAWC,EAFfL,EAAgBE,EAAKhnF,SAAS5M,GAAQ,EAGjCyzF,EAODK,EAAYC,GAAW50F,KAAKE,IAAIm0F,EAAcK,EAAcH,IAJ5DI,GAAa30F,KAAKE,IAAIm0F,EAAcK,GACpCE,GAAW50F,KAAKE,IAAIm0F,EAAcE,IAUtC,MAAMM,EAAcJ,EAAKp0F,QAAQwP,KAAK60B,EAAMiwD,GAAWrqF,MAAM6F,GACvD2kF,EAAYL,EAAKp0F,QAAQwP,KAAKhP,EAAM+zF,GAAStqF,MAAM6F,GAOzD,OAHApa,EAAKiuB,cAAc,GAAOE,cAAc,IAAK2wE,IAGrCT,GACJ,KAAKT,GAAYE,MAAO,CAEpB,MAAMvtD,EAAO,EAAI,EACXC,EAAO,EAAI,EACXjkB,EAAW,IAAI,GAASgkB,EAAMuuD,EAAYzoF,EAAMm6B,EAAMkuD,EAAKroF,EAAKm6B,EAAMkuD,EAAKxoF,EAAMq6B,EAAMuuD,EAAY5oF,GACnGsW,EAAW,IAAI,GAAS+jB,EAAMwuD,EAAU1oF,EAAMm6B,EAAMkuD,EAAKroF,EAAKm6B,EAAMkuD,EAAKxoF,EAAMq6B,EAAMwuD,EAAU7oF,GACrGlW,EAAKiuB,cAAc,GAAOE,cAAc,IAAK5B,EAAUC,EAAUuyE,IACjE,KACJ,CACA,KAAKnB,GAAYG,KAEb/9F,EAAKiuB,cAAc,GAAOE,cAAc,IAAK4wE,IAC7C,MAEJ,KAAKnB,GAAYI,IAEbh+F,EAAKiuB,cAAc,GAAOE,cAAc,IAAK4wE,IAKzD,CAKA/+F,EAAKiuB,cAAc,GAAOE,cAAc,IAAKm9D,GACjD,KA3EyD,CAGrD,MAAMrzE,EAAS,CAACozE,GAAax6E,OAAOutF,GAAavtF,OAAO,CAACy6E,IACnDn6D,EAAW,IAAI,GAAWlZ,GAChCjY,EAAO,IAAI,GAAOmxB,EAEtB,CAsEA,OAAQ,EAAQnxB,EAAOA,EAAK4a,WAChC,ECzGA,IAIIokF,GAAa,CAAC,MAAO,MAAO,SAS5BC,GAAqB,CAAC,UAGtB1uD,GAAM,EAAI,EACVC,GAAM,EAAI,EAEd,SAAS0uD,GAAoBrmF,EAAIC,GAE7B,IAAMzC,EAAGuB,EAAI1B,EAAG4B,GAAOe,GACjBxC,EAAGwB,EAAI3B,EAAG6B,GAAOe,EAEvB,GAAIlB,EAAKC,EAAI,CAET,IAAIsnF,EAAOvnF,EACXA,EAAKC,EACLA,EAAKsnF,EAELA,EAAOrnF,EACPA,EAAKC,EACLA,EAAKonF,CACT,CAEA,GAAIrnF,EAAKC,EAAI,CACT,IAAIonF,EAAOvnF,EACXA,EAAKC,EACLA,EAAKsnF,EAELA,EAAOrnF,EACPA,EAAKC,EACLA,EAAKonF,CACT,CAEA,MAAO,CAAC,IAAI,GAAQvnF,EAAIE,GAAK,IAAI,GAAQD,EAAIE,GACjD,CAoBA,SAASqnF,GAAY/T,EAAaC,EAAawB,GAE3C,IAAI70E,EAAS,GAAGpH,OAAOw6E,EAAayB,EAAOxB,GAC3C,OAAOrzE,EAAO/L,QAAO,SAASmzF,EAAanmF,EAAO6pD,GAE9C,IAAIu8B,EAAYrnF,EAAO8qD,EAAM,GAI7B,OAHiB,MAAbu8B,IACAD,EAAYt8B,GAAO,GAAO7pD,EAAOomF,IAE9BD,CACX,GAAG,GACP,CAoEA,SAASE,GAAW1mF,EAAIC,GACpB,OAAO,GAAOD,EAAIC,GAAIrC,eAC1B,CAyEA,SAAS+oF,GAAU79D,EAAO89D,EAAUC,EAAUh/B,GAE1C,IACI/5C,EADA3mB,EAAO,IAAI,GAgFf,OA5EA2mB,EAAU,GAAOwH,cAAc,IAAKwT,EAAM,GAAG75B,OAC7C9H,EAAKiuB,cAActH,GAGnB,GAAagb,GAAO9hC,SAAQ,SAAS6c,EAAM9iB,GAEvC,GAAI8iB,EAAKijF,OAAQ,CACb,IAAI3qF,EAAO/T,EAEPsrB,EAAUC,EAEd,GAAiB,QAAbkzE,EAAoB,CACpB1qF,GAAS,GAET/T,EAAOyb,EAAK5U,MAAMuD,WAAWqR,EAAK3U,KAElC,IAAI63F,EAAcz8F,OAAQlC,EAAKoV,EAAI,GAAkB,IAAXpV,EAAKoV,GAAWpV,EAAKiV,EAAI,GAC/D0pF,IAAa5qF,GAAS,KAE1B,IAGI6qF,EAHA3iF,EAAWR,EAAKQ,WAChB4iF,EAAa,IAAI,GAAO5iF,EAAUR,EAAK3U,KAAKkS,OAAOiD,EAAUlI,GAOjEuX,GAFAszE,EAAW,IAAI,GAAOnjF,EAAK5U,MAAOoV,IAEd3B,QAAQ,EAAI,GAAGtB,OAAOyC,EAAK5U,MAAOkN,GACtDwX,EAAWszE,EAAWvkF,QAAQ,EAAI,GAAGtB,OAAO6lF,EAAW/3F,KAAMiN,GAE7D2R,EAAU,GAAOwH,cAAc,IAAK5B,EAAUC,EAAUszE,EAAW/3F,KACnE/H,EAAKiuB,cAActH,GAGnBk5E,EAAW,IAAI,GAAO3iF,EAAUR,EAAK3U,KAErCwkB,EAAWuzE,EAAWvkF,QAAQ,EAAI,GAAGtB,OAAO6lF,EAAW/3F,IAAKiN,GAC5DwX,EAAWqzE,EAAStkF,QAAQ,EAAI,GAAGtB,OAAOyC,EAAK3U,KAAMiN,GAErD2R,EAAU,GAAOwH,cAAc,IAAK5B,EAAUC,EAAU9P,EAAK3U,KAC7D/H,EAAKiuB,cAActH,EAEvB,MAAO,GAAiB,QAAb+4E,EACP/4E,EAAU,GAAOwH,cAAc,IAAKzR,EAAK3U,KACzC/H,EAAKiuB,cAActH,QAEhB,GAAiB,UAAb+4E,EAAsB,CAC7B1qF,EAAQ0H,EAAK5U,MAAMmR,MAAMyD,EAAK3U,KAE9B,IAAIg4F,EAAqB,GAAXN,EACVO,EAAqB,KAAXP,EAGdx+F,EAAOyb,EAAK5U,MAAMuD,WAAWqR,EAAK3U,MAElC63F,EAAcz8F,OAAQlC,EAAKoV,EAAI,GAAkB,IAAXpV,EAAKoV,GAAWpV,EAAKiV,EAAI,MAC9C8pF,IAAY,GAE7BzzE,EAAW,GAAQ7P,EAAK5U,MAAMuO,EAAI0pF,EAASrjF,EAAK5U,MAAMoO,EAAI8pF,GAAS/lF,OAAOyC,EAAK5U,MAAOkN,GACtFwX,EAAW,GAAQ9P,EAAK3U,IAAIsO,EAAI0pF,EAASrjF,EAAK3U,IAAImO,EAAI8pF,GAAS/lF,OAAOyC,EAAK3U,IAAKiN,GAEhF2R,EAAU,GAAOwH,cAAc,IAAK5B,EAAUC,EAAU9P,EAAK3U,KAC7D/H,EAAKiuB,cAActH,EACvB,CAEJ,KAAO,CACH,IAAIs5E,EAAWt+D,EAAM/nC,EAAQ,GACf,GAAV8mE,IAAgBu/B,GAAYA,EAASN,QACrCh5E,EAAU,GAAOwH,cAAc,IAAKzR,EAAK3U,KACzC/H,EAAKiuB,cAActH,IAUnC,SAA6BpN,EAAQvZ,EAAM0+F,EAAM/vD,EAAM7jC,GACnD,IAYI6b,EAZAg4E,EAAeD,EAAKhnF,SAASi3B,GAAQ,EACrC6vD,EAAeE,EAAKhnF,SAAS5M,GAAQ,EAErC8zF,GAAa30F,KAAKE,IAAIoP,EAAQolF,GAC9BE,GAAW50F,KAAKE,IAAIoP,EAAQilF,GAE5B0B,EAAexB,EAAKp0F,QAAQwP,KAAK60B,EAAMiwD,GAAWrqF,QAClD4rF,EAAazB,EAAKp0F,QAAQwP,KAAKhP,EAAM+zF,GAAStqF,QAE9CgY,EAAW,IAAI,GAASgkB,GAAM2vD,EAAa7pF,EAAMm6B,GAAMkuD,EAAKroF,EAAKm6B,GAAMkuD,EAAKxoF,EAAMq6B,GAAM2vD,EAAahqF,GACrGsW,EAAW,IAAI,GAAS+jB,GAAM4vD,EAAW9pF,EAAMm6B,GAAMkuD,EAAKroF,EAAKm6B,GAAMkuD,EAAKxoF,EAAMq6B,GAAM4vD,EAAWjqF,GAGrGyQ,EAAU,GAAOwH,cAAc,IAAK+xE,GACpClgG,EAAKiuB,cAActH,GAEnBA,EAAU,GAAOwH,cAAc,IAAK5B,EAAUC,EAAU2zE,GACxDngG,EAAKiuB,cAActH,EACvB,CA3BgBy5E,CAAoB1/B,EAAQ1gE,EAAM0c,EAAK3U,IAAK2U,EAAK5U,MAAOm4F,EAASl4F,IAEzE,CACJ,IAEO/H,CACX,CAgCO,MAAMqgG,GAAW,SAAShV,EAAaC,EAAawB,EAAOvwE,IAhQlE,SAAuB+jF,GACnB,IAAI90C,EAAQ80C,EAAiB90C,MACzB+0C,EAAa/0C,EAAMg1C,oBAGvB,GAAkB,MAAdD,EAAoB,CACpBA,EAAa/0C,EAAMg1C,oBAAsB,GACzC,IAAIrxC,EAAQ3D,EAAM3F,MAClBsJ,EAAMz9C,GAAG,cAAc,WACfxJ,KAAKyqE,kBAyBrB,SAAwBnnB,GAEpB,IADA,IAAI+0C,EAAa/0C,EAAMg1C,oBACdxxF,EAAI,EAAGA,EAAIuxF,EAAW7mG,OAAQsV,IAAK,CACxC,MAAMivE,EAAWsiB,EAAWvxF,GACtByxF,EAAaxiB,EAAS7C,QAAQ6C,EAASzjF,YAAYyrF,MAAMya,WAC/DziB,EAASpG,cAAc4oB,EAC3B,CACJ,CA/BYE,CAAen1C,EACnB,IACA2D,EAAMz9C,GAAG,SAAS,WACd6uF,EAAa/0C,EAAMg1C,oBAAsB,EAC7C,GACJ,CAGID,EAAWp/F,QAAQm/F,GAAoB,IACvCC,EAAWzmG,KAAKwmG,GAIhBA,EAAiB77C,aAAa67C,EAAiBz6C,MAAO,2BAA2B,WAC7E06C,EAAW73F,OAAO63F,EAAWp/F,QAAQm/F,GAAmB,EAC5D,IAER,CAuOIM,CAAc14F,MAEd,IAAIq3E,EAAMhjE,EAAIgjE,IACVkgB,EAAWljF,EAAI7c,MApVP,EAqVRggG,EAAWnjF,EAAIskF,OAAS,GAAKtkF,EAAIskF,MAAMz0F,cACvCs0D,EAASnkD,EAAImkD,QA/UR,EAgVLogC,EAAmBvkF,EAAIukF,kBAAoB7B,IAGT,IAAlCD,GAAW79F,QAAQu+F,KACnBA,EAAWV,GAAW,IAG1B,IAAIxzC,EAAQtjD,KAAKsjD,MAEbu1C,EADQv1C,EAAM3F,MACG6oB,WAGrB,GAAwB,IAApBqyB,EAASrnG,OACT,OAAO8lG,GACHJ,GAAY/T,EAAaC,EAAawB,GACtC2S,EAAUC,EAAUh/B,GAI5B,IAAIsgC,EAAY94F,KAAK29C,MACjBo7C,EAAYF,EAAS5/F,QAAQ6/F,GAC7BE,EAAmB11C,EAAM3rB,QAAQqhE,kBAAoB,CAAC,EAGtDpyB,EAAQiyB,EAAS9kG,QAAO,SAASqzD,EAAMyT,GAEvC,IAAIzgD,EAAYgtC,EAAKj8D,IAAI,cAAgB6tG,EAGzC,QAAI,GAAaJ,GAAkB5/F,SAASohB,EAAUjjB,OAKlD0jE,EAAMk+B,GACoB,aAAnB3+E,EAAUjjB,KAGzB,IAGI8hG,EAAYryB,EAAMj2E,KAAI,SAASy2D,GAC/B,OAAO9D,EAAMoI,gBAAgBtE,EACjC,IAGI8xC,EAAYhC,GACZ/T,EACAC,EACAwB,GAIAuU,EAAYF,EAAUtoG,KAAI,SAASolF,GACnC,OAAgB,MAAZA,EACO,GAEPA,IAAa/1E,KACNk5F,EAEJhC,GACHnhB,EAASoN,YACTpN,EAASqN,YACTrN,EAAS6O,MAEjB,GAAG5kF,MAICo5F,EAAeF,EAAUl1F,QAAO,SAASmzF,EAAakC,GAGtD,IAAI/iF,EAAgBswD,EAAM5iE,QAAO,SAAS2kC,EAAKye,EAAMtgD,GAEjD,GAAIsgD,IAAS0xC,EAAW,CAEpB,MAAMQ,EAAkBH,EAAUryF,GAAGhM,QAC/By+F,EAAeD,EAAgB5mC,WAAWl+C,GApXhE,SAAuBmZ,EAAOC,GAE1B,OAASzf,EAAGuB,EAAI1B,EAAG4B,IAAQzB,EAAGwB,EAAI3B,EAAG6B,IAAQmnF,GAAoBrpE,EAAM/tB,MAAO+tB,EAAM9tB,OAC3EsO,EAAG4S,EAAI/S,EAAGgT,IAAQ7S,EAAGqrF,EAAIxrF,EAAGyrF,IAAQzC,GAAoBppE,EAAMhuB,MAAOguB,EAAM/tB,KAKpF,OAHe6P,GAAM8pF,GAAMz4E,GAAMpR,GAClBC,GAAM6pF,GAAMz4E,GAAMnR,CAGrC,CA2WyE6pF,CAAcL,EAAU7kF,KAG7E+kF,GAAgB,GAAKF,EAAS9oF,cAAc+oF,EAAgBC,GAAc15F,MAE1Ey5F,EAAgB94F,OAAO+4F,EAAe,EAAG,GAE7C,MAAMI,EA1StB,SAA+BnlF,EAAMolF,GACjC,OAAO,GAAaA,GAAiB51F,QAAO,SAAS2kC,EAAKkxD,GACtD,IAAItlF,EAAeC,EAAKD,aAAaslF,GAIrC,OAHItlF,GACAo0B,EAAI/2C,KAAK2iB,GAENo0B,CACX,GAAG,GACP,CAkS0CmxD,CAAsBT,EAAUC,GAC1D3wD,EAAI/2C,KAAKuP,MAAMwnC,EAAKgxD,EACxB,CACA,OAAOhxD,CACX,GAAG,IAAIprC,MAAK,SAAS5B,EAAGC,GACpB,OAAOy7F,GAAWgC,EAASz5F,MAAOjE,GAAK07F,GAAWgC,EAASz5F,MAAOhE,EACtE,IASA,OAPI0a,EAAc9kB,OAAS,EAEvB2lG,EAAYvlG,KAAKuP,MAAMg2F,EAzRnC,SAAqB3iF,EAAM8B,EAAeihF,GACtC,OAAOjhF,EAActS,QAAO,SAASmzF,EAAanmF,EAAO6pD,GAGrD,IAAmB,IAAf7pD,EAAM+oF,KACN,OAAO5C,EAIX,IAAIrgD,EAAWqgD,EAAY52F,OAASiU,EAGhCwlF,EAAY,GAAQhpF,GAAOY,KAAKklC,EAASl3C,OAAQ,GACjDq6F,EAAU,GAAQjpF,GAAOY,KAAKklC,EAASl3C,OAAQ,GAG/Cw3F,EAAY9gF,EAAcukD,EAAM,GACpC,GAAiB,MAAbu8B,EAAmB,CACnB,IAAI5nF,EAAWyqF,EAAQzqF,SAAS4nF,GAC5B5nF,GAAY+nF,IAGZ0C,EAAU7C,EAAUxlF,KAAKklC,EAASl3C,MAAO4P,GACzC4nF,EAAU2C,MAAO,EAEzB,MAKI,GAFkBC,EAAUxqF,SAASsnC,EAASj3C,KAEjB,EAAX03F,EAhLA,EAkLd,OADAJ,EAAYvlG,KAAKklD,GACVqgD,EAKf,GADoB8C,EAAQzqF,SAASsnC,EAASl3C,OACf,EAAX23F,EAvLE,EA0LlB,OADAJ,EAAYvlG,KAAKklD,GACVqgD,EAIX,IAAI+C,EAAW,GAAOF,EAAWC,GASjC,OAPAC,EAASzC,QAAS,EAElBN,EAAYvlG,KACR,GAAOklD,EAASl3C,MAAOo6F,GACvBE,EACA,GAAOD,EAASnjD,EAASj3C,MAEtBs3F,CACX,GAAG,GACP,CAkOgDgD,CAAYd,EAAU/iF,EAAeihF,IAGzEJ,EAAYvlG,KAAKynG,GAEdlC,CACX,GAAG,IAECr/F,EAAOw/F,GAAU8B,EAAc7B,EAAUC,EAAUh/B,GACvD,OAAO,EAAQ1gE,EAAOA,EAAK4a,WAC/B,ECjca,GAAS,SAASywE,EAAaC,EAAawB,EAAQ,GAAIvwE,EAAM,CAAC,GAExE,MAAM,IAAEgjE,GAAQhjE,EAMhB,OAAO4hF,GAAS9S,EAAaC,EAAawB,EALzB,CACbuR,WAAY,QACZ9e,OAIR,ECTM,GAAgB,GAGT+iB,GAAU,SAASjX,EAAaC,EAAawB,EAAQ,GAAIvwE,EAAM,CAAC,GAEzE,MAAM,OAAEmkD,EAAS,GAAa,IAAE6e,GAAQhjE,EAQxC,OAAO4hF,GAAS9S,EAAaC,EAAawB,EAPzB,CACbuR,WAAY,QACZC,aAAc59B,EACdtmD,UARU,EASVmlE,OAIR,ECdagjB,GAAS,SAASlX,EAAaC,EAAawB,EAAOvwE,GAE5D,IACIvc,EADAu/E,EAAMhjE,GAAOA,EAAIgjE,IAGrB,GAAIuN,GAA0B,IAAjBA,EAAMpzF,OAAc,CAE7B,IAAIue,EAAS,CAACozE,GAAax6E,OAAOi8E,GAAOj8E,OAAO,CAACy6E,IAC7C1iE,EAAS,GAAQT,cAAclQ,GAEnCjY,EAAO,IAAI,GAAO4oB,EAEtB,KAAO,CAQH,IAAIjC,EAKJ,GAPA3mB,EAAO,IAAI,GAIX2mB,EAAU,GAAOwH,cAAc,IAAKk9D,GACpCrrF,EAAKiuB,cAActH,GAEd1c,KAAKoN,IAAIg0E,EAAYh1E,EAAIi1E,EAAYj1E,IAAQpM,KAAKoN,IAAIg0E,EAAYn1E,EAAIo1E,EAAYp1E,GAAK,CACxF,IAAIssF,GAAiBnX,EAAYh1E,EAAIi1E,EAAYj1E,GAAK,EAEtDsQ,EAAU,GAAOwH,cAAc,IAAKq0E,EAAenX,EAAYn1E,EAAGssF,EAAelX,EAAYp1E,EAAGo1E,EAAYj1E,EAAGi1E,EAAYp1E,GAC3HlW,EAAKiuB,cAActH,EAEvB,KAAO,CACH,IAAI87E,GAAiBpX,EAAYn1E,EAAIo1E,EAAYp1E,GAAK,EAEtDyQ,EAAU,GAAOwH,cAAc,IAAKk9D,EAAYh1E,EAAGosF,EAAenX,EAAYj1E,EAAGosF,EAAenX,EAAYj1E,EAAGi1E,EAAYp1E,GAC3HlW,EAAKiuB,cAActH,EAEvB,CACJ,CAEA,OAAO,EAAQ3mB,EAAOA,EAAK4a,WAC/B,ECzCM,GAAa,CACfq6E,KAAM,OACNyN,WAAY,aACZC,SAAU,WACVC,cAAe,gBACfC,SAAU,YAGRC,GAAoB,CACtBC,GAAI,KACJC,KAAM,OACN/5B,KAAM,OACNF,MAAO,QACPksB,KAAM,OACN2N,cAAe,gBACfC,SAAU,YAGDxwE,GAAQ,SAASg5D,EAAaC,EAAawB,EAAQ,GAAIvwE,EAAM,CAAC,EAAG0hE,GAC1E,MAAMsB,EAAM0jB,QAAQ1mF,EAAIgjE,MASlB,UAAEjf,EAAY,GAAW20B,KAAI,UAAE76E,EAAY,GAAMmC,EACjDsjB,EAAU,CACZqjE,MAAO3mF,EAAI4mF,qBAAuB,GAClCC,wBAAyB7mF,EAAI6mF,yBAA2B,GACxDC,IAAK9mF,EAAI+mF,SAAW,GACpBC,cAAehnF,EAAIgnF,cAAgB,IAAI1sF,GAAM0F,EAAIgnF,eAAiB,KAClEC,cAAejnF,EAAIinF,cAAgB,IAAI3sF,GAAM0F,EAAIinF,eAAiB,KAClEvpF,OAAQgpF,QAAQ1mF,EAAItC,SAEW,iBAAxBsC,EAAIs5E,gBACXh2D,EAAQg2D,gBAAkBt5E,EAAIs5E,gBACM,iBAAxBt5E,EAAIs5E,gBAChBh2D,EAAQg2D,gBAAkB,IAAIh/E,GAAM,EAAG,GAAGoD,OAAO,KAAMsC,EAAIs5E,iBAE3Dh2D,EAAQg2D,gBAAkBt5E,EAAIs5E,gBAAkB,IAAIh/E,GAAM0F,EAAIs5E,iBAAiB97E,YAAc,KAE9D,iBAAxBwC,EAAIy5E,gBACXn2D,EAAQm2D,gBAAkBz5E,EAAIy5E,gBACM,iBAAxBz5E,EAAIy5E,gBAChBn2D,EAAQm2D,gBAAkB,IAAIn/E,GAAM,EAAG,GAAGoD,OAAO,KAAMsC,EAAIy5E,iBAE3Dn2D,EAAQm2D,gBAAkBz5E,EAAIy5E,gBAAkB,IAAIn/E,GAAM0F,EAAIy5E,iBAAiBj8E,YAAc,KAEjG,MAAM0pF,EAAgB,CAACpY,KAAgByB,EAAOxB,GAAazyF,KAAIkd,GAAK,IAAIc,GAAMd,KAG9E,IAAIwtF,EAiBAC,EAhBJ,GAAI3jE,EAAQ0jE,cACRA,EAAgB1jE,EAAQ0jE,kBACrB,CACH,MAAM1N,EAiTd,SAAmC5X,EAAU6O,EAAOxsB,EAAWzgC,GAC3D,GAAIA,EAAQg2D,gBACR,OAAQh2D,EAAQg2D,iBACZ,KAAKiN,GAAkBC,GACnB,OAAO,IAAIlsF,GAAM,GAAI,GACzB,KAAKisF,GAAkBE,KACnB,OAAO,IAAInsF,GAAM,EAAG,GACxB,KAAKisF,GAAkB75B,KACnB,OAAO,IAAIpyD,IAAO,EAAG,GACzB,KAAKisF,GAAkB/5B,MACnB,OAAO,IAAIlyD,GAAM,EAAG,GACxB,KAAKisF,GAAkB7N,KACnB,OAAOyO,GAAuBzlB,EAAU6O,EAAOjtD,GACnD,KAAKijE,GAAkBF,cACnB,OAAOe,GAA+B1lB,EAAU6O,GACpD,KAAKgW,GAAkBD,SACnB,OAAOe,GAA2B3lB,EAAU6O,GAChD,QACI,OAAOjtD,EAAQg2D,gBAI3B,OAAQv1B,GACJ,KAAK,GAAWoiC,WACZ,OAlSZ,SAAsCzkB,EAAU6O,EAAOjtD,GACnD,MAAM,WAAEsrD,GAAelN,EAEvB,IAAIgY,EACA7sD,EAkBAk3B,EAjBJ,GAAK2d,EAASqH,WAOV,GADAl8C,EAAW60C,EAASqH,WAAWz/B,MAAM7wC,QACjC6qB,EAAQ5lB,QAAUmvB,EAAU,CAC5B,MAAMy6D,EAAgB5lB,EAASqH,WAAW/I,qBAAqB0B,EAASqH,WAAW/0E,IAC7E86E,EAAcyB,EAAM,GAAGxiF,QAC7B+gF,EAAYpxE,OAAOkxE,EAAW/sE,SAAUgrB,GACxC6sD,EAAa4N,EAAchgF,mBAAmBwnE,EAClD,MACI4K,EAAa9K,EAAWtnE,mBAAmBipE,EAAM,SAXjDmJ,EADA9K,EAAW90E,EAAIy2E,EAAM,GAAGz2E,EACX,QAEA,OA4BrB,OAZQiqD,EAAY,IAAIzpD,GADf,SADDo/E,GAEuB,EAID,EAJI,GAQ9Bp2D,EAAQ5lB,QAAUmvB,GAClBk3B,EAAUrmD,OAAO,MAAOmvB,GAGrBk3B,CACX,CA4PmBwjC,CAA6B7lB,EAAU6O,EAAOjtD,GACzD,KAAK,GAAW8iE,SACZ,OApNZ,SAAoC1kB,EAAU6O,EAAOjtD,GACjD,MAAM,WAAEsrD,GAAelN,EAEvB,IAAIgY,EACA7sD,EAkBAk3B,EAjBJ,GAAK2d,EAASqH,WAOV,GADAl8C,EAAW60C,EAASqH,WAAWz/B,MAAM7wC,QACjC6qB,EAAQ5lB,QAAUmvB,EAAU,CAC5B,MAAMy6D,EAAgB5lB,EAASqH,WAAW/I,qBAAqB0B,EAASqH,WAAW/0E,IAC7E86E,EAAcyB,EAAM,GAAGxiF,QAC7B+gF,EAAYpxE,OAAOkxE,EAAW/sE,SAAUgrB,GACxC6sD,EAAa4N,EAAchgF,mBAAmBwnE,EAClD,MACI4K,EAAa9K,EAAWtnE,mBAAmBipE,EAAM,SAXjDmJ,EADA9K,EAAWj1E,EAAI42E,EAAM,GAAG52E,EACX,SAEA,MA4BrB,OAZQoqD,EAAY,IAAIzpD,GAAM,EADrB,QADDo/E,GAE0B,EAID,GAI7Bp2D,EAAQ5lB,QAAUmvB,GAClBk3B,EAAUrmD,OAAO,MAAOmvB,GAGrBk3B,CACX,CA8KmByjC,CAA2B9lB,EAAU6O,EAAOjtD,GACvD,KAAK,GAAW+iE,cACZ,OAAOe,GAA+B1lB,EAAU6O,GACpD,KAAK,GAAW+V,SACZ,OAAOe,GAA2B3lB,EAAU6O,GAChD,KAAK,GAAWmI,KAChB,QACI,OAAOyO,GAAuBzlB,EAAU6O,EAAOjtD,GAE3D,CApVgCmkE,CAA0B/lB,EAAUwlB,EAAenjC,EAAWzgC,GAChFokE,EAAgBR,EAAc,GAAG/rF,SAAS+rF,EAAc,IAAM5jE,EAAQqjE,MAEtEluF,EAAQkvF,GAAoBrO,EADb4N,EAAc,GAAGp4F,WAAWo4F,EAAc,IAAI1pF,aAEnE,GAAI/E,EAAQ/K,KAAKuK,GAAK,EAAG,CACrB,MAAM2vF,EAAgBF,GAAiBjvF,EAAQ/K,KAAKuK,GAAK,GAAKqrB,EAAQujE,wBACtEG,EAAgB1N,EAAgBvrF,QAAQmK,MAAM0vF,EAAeA,EACjE,MACIZ,EAAgB1N,EAAgBvrF,QAAQmK,MAAMwvF,EAAeA,EAErE,CAIA,GAAIpkE,EAAQ2jE,cACRA,EAAgB3jE,EAAQ2jE,kBACrB,CACH,MAAMxN,EAqUd,SAAmC/X,EAAU6O,EAAOxsB,EAAWzgC,GAC3D,GAAIA,EAAQm2D,gBACR,OAAQn2D,EAAQm2D,iBACZ,KAAK8M,GAAkBC,GACnB,OAAO,IAAIlsF,GAAM,GAAI,GACzB,KAAKisF,GAAkBE,KACnB,OAAO,IAAInsF,GAAM,EAAG,GACxB,KAAKisF,GAAkB75B,KACnB,OAAO,IAAIpyD,IAAO,EAAG,GACzB,KAAKisF,GAAkB/5B,MACnB,OAAO,IAAIlyD,GAAM,EAAG,GACxB,KAAKisF,GAAkB7N,KACnB,OAAOmP,GAAuBnmB,EAAU6O,EAAOjtD,GACnD,KAAKijE,GAAkBF,cACnB,OAAOyB,GAA+BpmB,EAAU6O,GACpD,KAAKgW,GAAkBD,SACnB,OAAOyB,GAA2BrmB,EAAU6O,GAChD,QACI,OAAOjtD,EAAQm2D,gBAI3B,OAAQ11B,GACJ,KAAK,GAAWoiC,WACZ,OA/RZ,SAAsCzkB,EAAU6O,EAAOjtD,GACnD,MAAM,WAAEurD,GAAenN,EAEvB,IAAIiY,EACA9sD,EAkBAk3B,EAjBJ,GAAK2d,EAASwH,WAOV,GADAr8C,EAAW60C,EAASwH,WAAW5/B,MAAM7wC,QACjC6qB,EAAQ5lB,QAAUmvB,EAAU,CAC5B,MAAMy6D,EAAgB5lB,EAASwH,WAAWlJ,qBAAqB0B,EAASwH,WAAWl1E,IAC7E+6E,EAAcwB,EAAMA,EAAMpzF,OAAS,GAAG4Q,QAC5CghF,EAAYrxE,OAAOmxE,EAAWhtE,SAAUgrB,GACxC8sD,EAAa2N,EAAchgF,mBAAmBynE,EAClD,MACI4K,EAAa9K,EAAWvnE,mBAAmBipE,EAAMA,EAAMpzF,OAAS,SAXhEw8F,EADA9K,EAAW/0E,EAAIy2E,EAAMA,EAAMpzF,OAAS,GAAG2c,EAC1B,OAEA,QA4BrB,OAZQiqD,EAAY,IAAIzpD,GADf,SADDq/E,GAEuB,EAID,EAJI,GAQ9Br2D,EAAQ5lB,QAAUmvB,GAClBk3B,EAAUrmD,OAAO,MAAOmvB,GAGrBk3B,CACX,CAyPmBikC,CAA6BtmB,EAAU6O,EAAOjtD,GACzD,KAAK,GAAW8iE,SACZ,OAjNZ,SAAoC1kB,EAAU6O,EAAOjtD,GACjD,MAAM,WAAEurD,GAAenN,EAEvB,IAAIiY,EACA9sD,EAmBAk3B,EAlBJ,GAAK2d,EAASwH,WAOV,GADAr8C,EAAW60C,EAASwH,WAAW5/B,MAAM7wC,QACjC6qB,EAAQ5lB,QAAUmvB,EAAU,CAC5B,MAAMy6D,EAAgB5lB,EAASwH,WAAWlJ,qBAAqB0B,EAASwH,WAAWl1E,IAC7E+6E,EAAcwB,EAAMA,EAAMpzF,OAAS,GAAG4Q,QAC5CghF,EAAYrxE,OAAOmxE,EAAWhtE,SAAUgrB,GACxC8sD,EAAa2N,EAAchgF,mBAAmBynE,EAClD,MACI4K,EAAa9K,EAAWvnE,mBAAmBipE,EAAMA,EAAMpzF,OAAS,SAXhEw8F,EADA9K,EAAWl1E,EAAI42E,EAAMA,EAAMpzF,OAAS,GAAGwc,EAC1B,MAEA,SA6BrB,OAZQoqD,EAAY,IAAIzpD,GAAM,EADrB,QADDq/E,GAE0B,EAID,GAI7Br2D,EAAQ5lB,QAAUmvB,GAClBk3B,EAAUrmD,OAAO,MAAOmvB,GAGrBk3B,CACX,CA0KmBkkC,CAA2BvmB,EAAU6O,EAAOjtD,GACvD,KAAK,GAAW+iE,cACZ,OAAOyB,GAA+BpmB,EAAU6O,GACpD,KAAK,GAAW+V,SACZ,OAAOyB,GAA2BrmB,EAAU6O,GAChD,KAAK,GAAWmI,KAChB,QACI,OAAOmP,GAAuBnmB,EAAU6O,EAAOjtD,GAE3D,CAxWgC4kE,CAA0BxmB,EAAUwlB,EAAenjC,EAAWzgC,GAChFp2B,EAAOg6F,EAAc/pG,OAAS,EAC9BuqG,EAAgBR,EAAch6F,EAAO,GAAGiO,SAAS+rF,EAAch6F,IAASo2B,EAAQqjE,MAEhFluF,EAAQkvF,GAAoBlO,EADbyN,EAAch6F,EAAO,GAAG4B,WAAWo4F,EAAch6F,IAAOsQ,aAE7E,GAAI/E,EAAQ/K,KAAKuK,GAAK,EAAG,CACrB,MAAM2vF,EAAgBF,GAAiBjvF,EAAQ/K,KAAKuK,GAAK,GAAKqrB,EAAQujE,wBACtEI,EAAgBxN,EAAgB1rF,QAAQmK,MAAM0vF,EAAeA,EACjE,MACIX,EAAgBxN,EAAgB1rF,QAAQmK,MAAMwvF,EAAeA,EAErE,CAEA,MAAMS,EAiXV,SAAgCzsF,EAAQsrF,EAAeC,EAAe3jE,GAClE,MAAM,IAAEwjE,EAAG,MAAEH,GAAUrjE,EACjB8kE,EAAY,GACZC,EAAW,GACXF,EAAmB,GACnBxsF,EAAID,EAAOve,OAAS,EAE1B,IAAK,IAAIsV,EAAI,EAAGA,EAAIkJ,EAAGlJ,IACnB21F,EAAU31F,GAAKiJ,EAAOjJ,GAAG0I,SAASO,EAAOjJ,EAAI,IAGjD41F,EAAS,GAAKrB,EACdqB,EAAS1sF,GAAKsrF,EAGd,IAAK,IAAIx0F,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CACxB,IAAI61F,EACAC,EAEAD,EADM,IAAN71F,EACSiJ,EAAOjJ,EAAI,GAAG1E,QAAQiP,OAAOqrF,EAAS51F,EAAI,GAAGqH,EAAGuuF,EAAS51F,EAAI,GAAGkH,GAEhE+B,EAAOjJ,EAAI,GAAG1E,QAGvBw6F,EADA91F,IAAMkJ,EAAI,EACDD,EAAOjJ,EAAI,GAAG1E,QAAQiP,OAAOqrF,EAAS51F,EAAI,GAAGqH,EAAGuuF,EAAS51F,EAAI,GAAGkH,GAEhE+B,EAAOjJ,EAAI,GAAG1E,QAE3B,MAAMy6F,EAAKF,EAAOx5F,WAAW4M,EAAOjJ,IAAI+K,YAClCirF,EAAKF,EAAOz5F,WAAW4M,EAAOjJ,IAAI+K,YAClCkrF,EAASf,GAAoBa,EAAIC,GAEvC,IACIrrF,EADAurF,GAAOj7F,KAAKuK,GAAKywF,GAAU,EAE/B,MAAME,EAAoBC,GAAYL,EAAIC,GAC1C,IAAIK,EACJA,EAAoBD,GAAYntF,EAAOjJ,GAAG3D,WAAW4M,EAAOjJ,EAAI,IAAKiJ,EAAOjJ,GAAG3D,WAAW4M,EAAOjJ,EAAI,KACjGm2F,EAAoB,IACpBD,GAAOA,GAEND,EAASh7F,KAAKuK,GAAK,IAAQ0wF,EAAM,GAAKG,EAAoB,GAAOH,EAAM,GAAKG,EAAoB,KACjGH,GAAYj7F,KAAKuK,IAErBmF,EAAIqrF,EAAG16F,QACPg7F,GAAa3rF,EAAGurF,GAEhB,MAAMr8E,EAAKlP,EAAErP,QACPwe,EAAKnP,EAAErP,QACPi7F,EAAeZ,EAAU31F,EAAI,GAAKk0F,EAClCsC,EAAeb,EAAU31F,GAAKk0F,EACpCr6E,EAAGpU,MAAM8wF,EAAcA,GACvBz8E,EAAGrU,MAAM+wF,EAAcA,GAEvBZ,EAAS51F,GAAK,CAAC6Z,EAAIC,EACvB,CAGA,IAAK,IAAI9Z,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CACxB,IAAIilB,EACA7Q,EAEA6Q,EADM,IAANjlB,EACKiJ,EAAOjJ,EAAI,GAAG3D,WAAWu5F,EAAS51F,GAAGqH,EAAIgtF,EAAKuB,EAAS51F,GAAGkH,EAAImtF,GAE9DprF,EAAOjJ,EAAI,GAAG3D,WAAWu5F,EAAS51F,GAAG,GAAGqH,EAAIgtF,EAAKuB,EAAS51F,GAAG,GAAGkH,EAAImtF,GAGzEjgF,EADApU,IAAMkJ,EAAI,EACLD,EAAOjJ,GAAG1E,QAAQiP,OAAOqrF,EAAS51F,EAAI,GAAGqH,EAAIgtF,EAAKuB,EAAS51F,EAAI,GAAGkH,EAAImtF,GAEtEprF,EAAOjJ,GAAG3D,WAAWu5F,EAAS51F,EAAI,GAAG,GAAGqH,EAAIgtF,EAAKuB,EAAS51F,EAAI,GAAG,GAAGkH,EAAImtF,GAGjFqB,EAAiB11F,GAAK,CAACilB,EAAIhc,EAAOjJ,GAAIiJ,EAAOjJ,EAAI,GAAIoU,EACzD,CACA,OAAOshF,CACX,CA3b6Be,CAAuBhC,EAAeF,EAAeC,EAAe3jE,GACvF6lE,EAAehB,EAAiB7rG,KAAIw5B,GA6b9C,SAA4Bpa,EAAQ4nB,GAChC,MAAM,IAAEwjE,GAAQxjE,EAEV8lE,EAAO,IAAI9uF,GACjB8uF,EAAKtvF,EAAI4B,EAAO,GAAG5B,GAAK4B,EAAO,GAAG5B,EAAI4B,EAAO,GAAG5B,IAAM,EAAIgtF,GAC1DsC,EAAKzvF,EAAI+B,EAAO,GAAG/B,GAAK+B,EAAO,GAAG/B,EAAI+B,EAAO,GAAG/B,IAAM,EAAImtF,GAE1D,MAAMuC,EAAO,IAAI/uF,GAGjB,OAFA+uF,EAAKvvF,EAAI4B,EAAO,GAAG5B,GAAK4B,EAAO,GAAG5B,EAAI4B,EAAO,GAAG5B,IAAM,EAAIgtF,GAC1DuC,EAAK1vF,EAAI+B,EAAO,GAAG/B,GAAK+B,EAAO,GAAG/B,EAAI+B,EAAO,GAAG/B,IAAM,EAAImtF,GACnD,IAAIlsF,GACPc,EAAO,GACP0tF,EACAC,EACA3tF,EAAO,GAEf,CA7cuD4tF,CAAmBxzE,EAAOwN,KACvE7/B,EAAO,IAAIoX,GAAKsuF,GAAcnxF,MAAM6F,GAE1C,OAAO,EAAQpa,EAAOA,EAAK4a,WAC/B,EAqKA,SAAS8oF,GAAuBzlB,EAAU6O,EAAOjtD,GAC7C,MAAM,WAAEsrD,GAAelN,EAEvB,IAAIgY,EACA7sD,EAeAk3B,EAdJ,GAAK2d,EAASqH,WAIV,GADAl8C,EAAW60C,EAASqH,WAAWz/B,MAAM7wC,QACjC6qB,EAAQ5lB,QAAUmvB,EAAU,CAC5B,MAAMy6D,EAAgB5lB,EAASqH,WAAW/I,qBAAqB0B,EAASqH,WAAW/0E,IAC7E86E,EAAcyB,EAAM,GAAGxiF,QAC7B+gF,EAAYpxE,OAAOkxE,EAAW/sE,SAAUgrB,GACxC6sD,EAAa4N,EAAchgF,mBAAmBwnE,EAClD,MACI4K,EAAa9K,EAAWtnE,mBAAmBipE,EAAM,SATrDmJ,EAAa9K,EAAWtnE,mBAAmBipE,EAAM,IAcrD,OAAQmJ,GACJ,IAAK,MACD31B,EAAY,IAAIzpD,GAAM,GAAI,GAC1B,MACJ,IAAK,SACDypD,EAAY,IAAIzpD,GAAM,EAAG,GACzB,MACJ,IAAK,QACDypD,EAAY,IAAIzpD,GAAM,EAAG,GACzB,MACJ,IAAK,OACDypD,EAAY,IAAIzpD,IAAO,EAAG,GAQlC,OAJIgpB,EAAQ5lB,QAAUmvB,GAClBk3B,EAAUrmD,OAAO,MAAOmvB,GAGrBk3B,CACX,CAEA,SAAS8jC,GAAuBnmB,EAAU6O,EAAOjtD,GAC7C,MAAM,WAAEurD,GAAenN,EAEvB,IAAIiY,EACA9sD,EAeAk3B,EAdJ,GAAK2d,EAASwH,WAIV,GADAr8C,EAAW60C,EAASwH,WAAW5/B,MAAM7wC,QACjC6qB,EAAQ5lB,QAAUmvB,EAAU,CAC5B,MAAMy6D,EAAgB5lB,EAASwH,WAAWlJ,qBAAqB0B,EAASwH,WAAWl1E,IAC7E+6E,EAAcwB,EAAMA,EAAMpzF,OAAS,GAAG4Q,QAC5CghF,EAAYrxE,OAAOmxE,EAAWhtE,SAAUgrB,GACxC8sD,EAAa2N,EAAchgF,mBAAmBynE,EAClD,MACI4K,EAAa9K,EAAWvnE,mBAAmBipE,EAAMA,EAAMpzF,OAAS,SATpEw8F,EAAa9K,EAAWvnE,mBAAmBipE,EAAMA,EAAMpzF,OAAS,IAcpE,OAAQw8F,GACJ,IAAK,MACD51B,EAAY,IAAIzpD,GAAM,GAAI,GAC1B,MACJ,IAAK,SACDypD,EAAY,IAAIzpD,GAAM,EAAG,GACzB,MACJ,IAAK,QACDypD,EAAY,IAAIzpD,GAAM,EAAG,GACzB,MACJ,IAAK,OACDypD,EAAY,IAAIzpD,IAAO,EAAG,GAQlC,OAJIgpB,EAAQ5lB,QAAUmvB,GAClBk3B,EAAUrmD,OAAO,MAAOmvB,GAGrBk3B,CACX,CAEA,SAASqjC,GAA+B1lB,EAAU6O,EAAOjtD,GACrD,OAAOitD,EAAM,GAAGzhF,WAAWyhF,EAAM,IAAI/yE,WACzC,CAEA,SAASsqF,GAA+BpmB,EAAU6O,EAAOjtD,GACrD,MAAMp2B,EAAOqjF,EAAMpzF,OAAS,EAC5B,OAAOozF,EAAMrjF,EAAO,GAAG4B,WAAWyhF,EAAMrjF,IAAOsQ,WACnD,CAEA,SAAS6pF,GAA2B3lB,EAAU6O,EAAOjtD,GACjD,MAAM,WAAEsrD,GAAelN,EACjB6nB,EAAe3a,EAAW/sE,SAChC,OAAO0uE,EAAM,GAAGzhF,WAAWy6F,GAAc/rF,WAC7C,CAEA,SAASuqF,GAA2BrmB,EAAU6O,EAAOjtD,GACjD,MAAM,WAAEurD,GAAenN,EACjB8nB,EAAe3a,EAAWhtE,SAChC,OAAO0uE,EAAMA,EAAMpzF,OAAS,GAAG2R,WAAW06F,GAAchsF,WAC5D,CA4EA,SAASurF,GAAa3pF,EAAQ3G,GAC1B,MAAMW,EAAM1L,KAAK0L,IAAIX,GACfY,EAAM3L,KAAK2L,IAAIZ,GACfqB,EAAIV,EAAMgG,EAAOtF,EAAIT,EAAM+F,EAAOzF,EAClCA,EAAIN,EAAM+F,EAAOtF,EAAIV,EAAMgG,EAAOzF,EACxCyF,EAAOtF,EAAIA,EACXsF,EAAOzF,EAAIA,CACf,CAEA,SAASguF,GAAoBa,EAAIC,GAC7B,IAAIrvF,EAAMovF,EAAGtrF,IAAIurF,IAAOD,EAAGnrF,YAAcorF,EAAGprF,aAG5C,OAFIjE,GAAO,IAAGA,GAAO,GACjBA,EAAM,IAAGA,EAAM,GACZ1L,KAAK+7F,KAAKrwF,EACrB,CAEA,SAASyvF,GAAYL,EAAIC,GACrB,OAAOD,EAAG1uF,EAAI2uF,EAAG9uF,EAAI6uF,EAAG7uF,EAAI8uF,EAAG3uF,CACnC,CAzWAgc,GAAM2iE,WAAa,GACnB3iE,GAAMywE,kBAAoBA,GCxF1B,MAAM,GAAQ,CACV5c,MAAOxL,GAASuL,MAAMC,MACtBW,OAAQ,SACRL,OAAQ,SACRyf,OAAQ,SACRC,OAAQ,SACRC,OAAQ,SACRzF,UAAW,aAMF0F,GAAW1rB,GAAS3yD,OAAO,CAEpC2a,UAAW,WAEP,IAAIi4C,EAAaD,GAASlnF,UAAUkvC,UAAUr5B,MAAMnB,MAAM1P,MAAM,KAIhE,OAFAmiF,EAAW7gF,KAAK,QAET6gF,EAAW3jF,KAAK,IAC3B,EAEAqvG,YAAa,KACbC,gBAAiB,KACjBC,GAAI,KACJC,UAAW,KAEX9rC,QAAS,KACT+rC,iBAAkB,EAElBpgD,WAAY,WAERq0B,GAASlnF,UAAU6yD,WAAWh9C,MAAMnB,KAAMpB,WAK1CoB,KAAKm+F,YAAc,CAAC,EAGpBn+F,KAAKo+F,gBAAkB,CAAC,EAGxBp+F,KAAKq+F,GAAK,CAAC,EAGXr+F,KAAKozE,iBACT,EAEAL,uBAAwB,CACpB7hB,OAAQ,CAAC,GAAMytB,QACfzrD,MAAO,CAAC,GAAMorD,QACd9jB,OAAQ,CAAC,GAAM8jB,QACflkE,UAAW,CAAC,GAAMo+E,WAClB19B,OAAQ,CAAC,GAAMijC,OAAQ,GAAM/f,OAC7BhkB,YAAa,CAAC,GAAM+jC,QACpB3iC,SAAU,CAAC,GAAMkjB,QACjB3rF,OAAQ,CAAC,GAAMqrG,OAAQ,GAAM1f,QAC7Bp5E,OAAQ,CAAC,GAAM+4F,OAAQ,GAAM3f,SAGjCtL,SAAU,CAAC,GAAM2L,OAAQ,GAAMqf,OAAQ,GAAMC,OAAQ,GAAMjgB,OAE3DrR,gBAAiB,EACjB6xB,QAAS,KAETzwB,cAAe,SAAS+E,EAAOz+D,GAI3B,GAFAA,IAAQA,EAAM,CAAC,GAEXrU,KAAKizE,QAAQH,EAAO,GAAMkrB,QAAS,CACnC,IAAKh+F,KAAKy+F,oBAAoB,UAAW,OAAO3rB,EAChDA,EAAQ9yE,KAAKmzE,WAAWL,EAAO,GAAMkrB,OACzC,CAEA,GAAIh+F,KAAKizE,QAAQH,EAAO,GAAMmrB,QAAS,CACnC,IAAKj+F,KAAKy+F,oBAAoB,UAAW,OAAO3rB,EAChDA,EAAQ9yE,KAAKmzE,WAAWL,EAAO,GAAMmrB,OACzC,CAEA,MAAM,MAAE36C,EAAK,WAAE85B,EAAU,WAAEG,GAAev9E,KAC1C,GAAIsjD,IAAW85B,IAAe95B,EAAMo7C,cAActhB,IAAiBG,IAAej6B,EAAMo7C,cAAcnhB,IAElG,OAAOzK,EAGX,GAAI9yE,KAAKizE,QAAQH,EAAO,GAAM6L,QAU1B,OATA3+E,KAAKyrE,SACLzrE,KAAKg8E,oBAAmB,GACxBh8E,KAAK27E,YAAYtnE,GACjBy+D,EAAQ9yE,KAAKmzE,WAAWL,EAAO,CAAC,GAAM6L,OAAQ,GAAML,OAAQ,GAAMyf,OAAQ,GAAM/f,MAAO,GAAMwa,YAEzFn7B,GAAIvtE,KAAK,aACTkQ,KAAK2+F,uBAGF7rB,EAGX,IAAIkJ,GAAqB,EAEzB,MAAM,MAAEr+B,GAAU39C,MACZ,WAAE07B,GAAeiiB,EACvB,IAAIihD,EAAe5+F,KAAKizE,QAAQH,EAAO,GAAMirB,QAEzCa,IACA5+F,KAAK6+F,eAAelhD,EAAOjiB,EAAWo/B,OAAQzmD,GAC9Cy+D,EAAQ9yE,KAAKmzE,WAAWL,EAAO,GAAMirB,QACrC/hB,GAAqB,GAGzB,MAAM8iB,EAAY9+F,KAAKizE,QAAQH,EAAO,GAAMwL,QACtCygB,EAAkB/+F,KAAKizE,QAAQH,EAAO,GAAM0lB,WAiClD,OAhCIsG,GAAaC,KACRD,EAIMzqF,EAAI0jD,aAAepa,EAAMqf,yBAAyB3oD,EAAI0jD,aAI7D/3D,KAAK6S,UAAUwB,EAAIwB,GAAIxB,EAAIyB,IAE3B9V,KAAK2S,UARL3S,KAAKg/F,aACLh/F,KAAKi/F,aASTj/F,KAAK27E,YAAYtnE,GACjBy+D,EAAQ9yE,KAAKmzE,WAAWL,EAAO,CAAC,GAAMwL,OAAQ,GAAMN,MAAO,GAAMwa,YACjEoG,GAAe,EACf5iB,GAAqB,GAGrB4iB,GACA5+F,KAAKk/F,uBAGLljB,GACAh8E,KAAKg8E,qBAGLh8E,KAAKizE,QAAQH,EAAO,GAAMkL,SAC1Bh+E,KAAK27E,YAAYtnE,GACjBy+D,EAAQ9yE,KAAKmzE,WAAWL,EAAO,GAAMkL,QAGlClL,CACX,EAEA6rB,qBAAsB,WAGlB,MAAM,GAAEt2F,GAAOrI,KACT+H,EAAa/W,MAAM8W,KAAKO,EAAGN,YAC3B2pC,EAAWvrC,SAASozB,yBAC1B,IAAK,IAAIzyB,EAAI,EAAGkJ,EAAIjI,EAAWvW,OAAQsV,EAAIkJ,EAAGlJ,IAC1CuB,EAAG2zB,YAAYj0B,EAAWjB,IAC1B4qC,EAASjqC,YAAYM,EAAWjB,IAEpCuB,EAAGZ,YAAYiqC,EACnB,EAEAytD,wBAAyB,SAAS9qF,GAC9BrU,KAAK2vE,cAAc3vE,KAAKkzE,QAAQ,GAAMoL,QAASjqE,EACnD,EAEA+qF,uBAAwB,SAAS/qF,EAAM,CAAC,GAEpC,MAAMgrF,EAAiBr/F,KAAK29C,MAAM+B,SAAS,UAC3C,IAAK2/C,EAAgB,OAAO,EAI5B,GAAK,sBAAuBhrF,GAAS,kBAAmBA,EAAM,CAE1D,IAAIy1B,EAAYz1B,EAAIu1C,mBAAqB,GACrC01C,EAAax1D,EAAUt4C,OAC3B,GAAI8tG,EAAa,GAEOD,EAAev1D,EAAU,IAC5B,CACb,GAAmB,IAAfw1D,EAGA,MAAQ,WAAYt0G,OAAOqpB,EAAIs1C,eAC5B,GAAqB,WAAjB7f,EAAU,GAEjB,OAAO,CAEf,CAER,CAEA,OAAO,CACX,EAEA+0D,eAAgB,SAAS/zB,EAAOy0B,EAASlrF,GAGjCrU,KAAKo/F,uBAAuB/qF,GAC5BrU,KAAKw/F,eAELx/F,KAAK4+F,cAEb,EAKAnzB,OAAQ,WAWJ,OATAzrE,KAAKi5B,IAAIH,QACT94B,KAAKy/F,gBACLz/F,KAAKq+F,GAAK,CAAC,EACXr+F,KAAKk/E,eAGLl/E,KAAKw/F,eACLx/F,KAAK2S,SAEE3S,IACX,EAEAk/E,aAAc,WAEV,IAAI93B,EAAOpnD,KAAK29C,MACZuT,EAAS9J,EAAKj8D,IAAI,WAAai8D,EAAK8J,OACxC,IAAKA,EAAQ,MAAM,IAAIloD,MAAM,iCAC7B,GAAIhY,MAAMC,QAAQigE,GAAS,OAAOlxD,KAAKm/E,iBAAiBjuB,GACxD,GAAsB,iBAAXA,EAAqB,OAAOlxD,KAAKo/E,mBAAmBluB,GAC/D,MAAM,IAAIloD,MAAM,+BACpB,EAEAm2E,iBAAkB,SAASjuB,GAEvB,IAAIl4B,EAAMh5B,KAAKqxC,aAAa6f,EAAQlxD,KAAKqI,IAEzCrI,KAAKuxC,UAAYvY,EAAIuY,UAErBvxC,KAAKi5B,IAAInF,OAAOkF,EAAI0Y,SACxB,EAEA0tC,mBAAoB,SAASluB,GAOzB,IAAI/9B,EAAW,GAAE+9B,GAEZlgE,MAAMC,QAAQkiC,KAAWA,EAAW,CAACA,IAE1CnzB,KAAKi5B,IAAInF,OAAOX,EACpB,EAEAusE,gBAAiB,SAAS1lC,GAEtB,GAAKA,EAAL,CAEA,GAAIhpE,MAAMC,QAAQ+oE,GAAc,OAAOh6D,KAAKqxC,aAAa2oB,EAAa,MACtE,GAA2B,iBAAhBA,EAA0B,OAAOh6D,KAAK2/F,sBAAsB3lC,GACvE,MAAM,IAAIhxD,MAAM,qCAJkB,CAKtC,EAEA22F,sBAAuB,SAAS3lC,GAE5B,IAAI7mC,EAAW,GAAE6mC,GACbtoB,EAAWvrC,SAASozB,yBAExB,GAAKvoC,MAAMC,QAAQkiC,GAIf,IAAK,IAAIrsB,EAAI,EAAGkJ,EAAImjB,EAAS3hC,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAC7C,IAAIgxB,EAAe3E,EAASrsB,GAAGgC,KAC/B4oC,EAASjqC,YAAYqwB,EACzB,MANA4Z,EAASjqC,YAAY0rB,EAASrqB,MASlC,MAAO,CAAE4oC,SAAUA,EAAUH,UAAW,CAAC,EAC7C,EAIAquD,sBAAuB,SAAS1uC,GAE5B,GAAKA,EAAL,CAEA,IAGI2uC,EAHAnuD,EAAWwf,EAAOxf,SACtB,KAAMwf,EAAOxf,oBAAoBouD,kBAAsB5uC,EAAOxf,SAASquD,iBAAiB,MAAM,IAAI/2F,MAAM,uCAGxG,IAAIjB,EAAa2pC,EAAS3pC,WAY1B,OAPI83F,EAHC93F,EAAWvW,OAAS,GAA+C,MAAzCuW,EAAW,GAAGg6B,SAASxF,cAG1C,GAAE,KAAKzI,OAAO4d,GAEd,GAAE3pC,EAAW,KAGnBktB,SAAS,SAER,CAAEnsB,KAAM+2F,EAAM/2F,KAAMyoC,UAAW2f,EAAO3f,UAlBhB,CAmBjC,EAEAiuD,aAAc,WAEV,IAAIzoG,EAAQiJ,KAAKq+F,GACb2B,EAAUjpG,EAAM+jE,OAChBmlC,EAAajgG,KAAKm+F,YAAc,CAAC,EACjCnoC,EAAiBh2D,KAAKo+F,gBAAkB,CAAC,EACzCzgD,EAAQ39C,KAAK29C,MACbmd,EAASnd,EAAMjiB,WAAWo/B,QAAU,GACpColC,EAAcplC,EAAOtpE,OAEzB,GAAoB,IAAhB0uG,EAEA,OADIF,GAASA,EAAQz7F,SACdvE,KAGPggG,EACAA,EAAQlnE,SAIRknE,EAAUjpG,EAAM+jE,OAAS,GAAE,KAAK7lC,SAAS,UACrCj1B,KAAK23B,QAAQwoE,cACbH,EAAQ/qE,SAASic,GAAmBz/C,GAAOuO,KAAM,eACjDggG,EAAQ9qE,KAAK,WAAYyoB,EAAMroB,MAIvC,IAAK,IAAIxuB,EAAI,EAAGA,EAAIo5F,EAAap5F,IAAK,CAElC,IAEI8vD,EACArlB,EAHAmf,EAAQoK,EAAOh0D,GACfkzD,EAAch6D,KAAK4/F,sBAAsB5/F,KAAK0/F,gBAAgBhvC,EAAMQ,SAGxE,GAAI8I,EAEApD,EAAYoD,EAAYlxD,KACxByoC,EAAYyoB,EAAYzoB,cAErB,CAEH,IAAI6uD,EAAuBziD,EAAMsc,UAAUF,aACvCsmC,EAA4BrgG,KAAK4/F,sBAAsB5/F,KAAK0/F,gBAAgBU,EAAoBlvC,SAChG6I,EAAepc,EAAMuf,mBAErBojC,EADqBtgG,KAAK4/F,sBAAsB5/F,KAAK0/F,gBAAgB3lC,EAAa7I,UAC5CmvC,EAE1CzpC,EAAY0pC,EAAcx3F,KAC1ByoC,EAAY+uD,EAAc/uD,SAC9B,CAEAqlB,EAAUr8B,aAAa,YAAazzB,GACpCk5F,EAAQlsE,OAAO8iC,GACfqpC,EAAWn5F,GAAK8vD,EAEhB,IAAI6c,EAAezzE,KAAKuG,SACxB,GAAIgrC,EAAUkiC,GAAe,MAAM,IAAIzqE,MAAM,gDAC7CuoC,EAAUkiC,GAAgB7c,EAE1BZ,EAAelvD,GAAKyqC,CACxB,CAOA,OANKyuD,EAAQ5jE,UACTp8B,KAAKugG,cAGTvgG,KAAK4+F,eAEE5+F,IACX,EAEAugG,YAAa,WACT,MAAM,GAAEl4F,EAAE,MAAEi7C,EAAK,MAAE3F,EAAK,GAAE0gD,EAAE,QAAE1mE,GAAY33B,MAClC86D,OAAQklC,GAAY3B,EAC5B,IAAK2B,IAAYriD,EAAMod,YAAa,OACpC,MAAM,KAAEjyD,GAASk3F,EACbroE,EAAQwoE,YACR78C,EAAMitB,aAAa54C,EAAQwoE,aAAa3vB,iBAAiB1nE,EAAM60C,EAAMxyD,IAAI,MAErE2d,EAAKkD,aAAe3D,GACpBA,EAAGZ,YAAYqB,EAG3B,EAEA22F,cAAe,WACX,MAAM,QAAE9nE,EAAO,GAAE0mE,GAAOr+F,KACxB,IAAKq+F,EAAI,OACT,MAAQvjC,OAAQklC,GAAY3B,EACxB2B,GAAWroE,EAAQwoE,aACnBH,EAAQz7F,QAEhB,EAEAi8F,eAAgB,SAASC,EAAYl6F,GACjC,MAAMm6F,EAAY1gG,KAAKm+F,YAAYsC,GACnC,IAAKC,EAAW,MAAO,GACvB,MAAM1qC,EAAiBh2D,KAAKo+F,gBAAgBqC,GAC5C,OAAOzgG,KAAK41D,eAAervD,EAAUm6F,EAAW1qC,EACpD,EAEA8Z,cAAe,SAAS2wB,EAAYl6F,GAChC,MAAOuC,EAAO,MAAQ9I,KAAKwgG,eAAeC,EAAYl6F,GACtD,OAAOuC,CACX,EAIA63F,iBAAkB,SAASC,EAAiBC,EAAYC,EAAmBC,GAEvE,GAAmB,OAAfF,EAAqB,OAAO,KAChC,QAAmBpuG,IAAfouG,EAA0B,CAE1B,GAA0B,OAAtBC,EAA4B,OAAO,KACvC,QAA0BruG,IAAtBquG,EAAiC,CAEjC,GAAIF,EAAiB,OACrB,OAAOG,CACX,CAEA,OAAIH,EAAwBE,EACrB5/F,GAAM,CAAC,EAAG6/F,EAA0BD,EAC/C,CAEA,OAAIF,EAAwB1/F,GAAM,CAAC,EAAG4/F,EAAmBD,GAClD3/F,GAAM,CAAC,EAAG6/F,EAA0BD,EAAmBD,EAClE,EAIAG,gBAAiB,SAASvwC,EAAWwwC,GAEjC,GAAkB,OAAdxwC,EAAoB,OAAO,KAC/B,QAAkBh+D,IAAdg+D,EAAyB,CAEzB,GAAyB,OAArBwwC,EAA2B,OAAO,KACtC,QAAyBxuG,IAArBwuG,EAAgC,OAEpC,OAAOA,CACX,CAEA,OAAO//F,GAAM,CAAC,EAAG+/F,EAAkBxwC,EACvC,EAEAmuC,aAAc,WAEV,IAAK5+F,KAAKq+F,GAAGvjC,OAAQ,OAAO96D,KAEvBA,KAAKsjD,MAAM3rB,QAAQupE,YAIpBlhG,KAAKo4E,eAAep4E,KAAKqI,IAe7B,IAZA,IAAIs1C,EAAQ39C,KAAK29C,MACbmd,EAASnd,EAAMxyD,IAAI,WAAa,GAChCg2G,EAAenhG,KAAK0zE,IAAI,aAGxBqtB,EADsBpjD,EAAMsc,UAAUF,aACS7mC,MAE/C6mC,EAAepc,EAAMuf,mBACrBkkC,EAAqBrnC,EAAa7I,OAClC4vC,EAAoB/mC,EAAa7mC,MACjC+tE,EAAmBlnC,EAAaviE,KAE3BsP,EAAI,EAAGkJ,EAAI8qD,EAAOtpE,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAE3C,IAAI8vD,EAAY52D,KAAKm+F,YAAYr3F,GACjC8vD,EAAUr8B,aAAa,SAAW4mE,EAAe,OAAS,WAE1D,IAAI5vD,EAAYvxC,KAAKo+F,gBAAgBt3F,GAEjC4pD,EAAQoK,EAAOh0D,GACfkzD,EAActJ,EAAMQ,OACpB2vC,EAAanwC,EAAMx9B,MACnBu9B,EAAYC,EAAMl5D,KAElB07B,EAAQlzB,KAAK2gG,iBACZ3mC,GAAeonC,EAChBP,EACAC,EACAC,GAGAvpG,EAAOwI,KAAKghG,gBACZvwC,EACAwwC,GAGJjhG,KAAKo3D,2BAA2BR,EAAW1jC,EAAO,CAC9CmkC,SAAU,IAAIvoD,GAAKtX,GACnB+5C,UAAWA,GAEnB,CAEA,OAAOvxC,IACX,EAIAqhG,8BAA+B,SAAShtF,GAEpC,MAEM+yC,EAAOpnD,KAAK29C,MACZyd,EAAWhU,EAAKgU,WAChB86B,EAAc,CAACl2F,KAAKwlF,gBAAiBpqB,EAAUp7D,KAAK0lF,cACpD4b,EAAiBpL,EAAY1kG,OAG7By3B,EAAW,IAAIla,GAASmnF,GAC9BjtE,EAAS/J,SAAS,CAAEC,UATO,OAU3B,MAAMoiF,EAAiBt4E,EAASlZ,OAAOpf,KAAKqgB,GAAWA,EAAMwB,WACvDgvF,EAAoBD,EAAe/vG,OAGzC,OAAI8vG,IAAmBE,EAA0B,GAIjDp6C,EAAKgU,SAASmmC,EAAezmG,MAAM,EAAG0mG,EAAoB,GAAIntF,GACtDitF,EAAiBE,EAC7B,EAEAC,WAAY,SAAStvG,GACjB,OAAQA,GACJ,IAAK,SACD,OAAO6N,KAAKo9E,YAAc,KAC9B,IAAK,SACD,OAAOp9E,KAAKu9E,YAAc,KAC9B,QACI,MAAM,IAAIv0E,MAAM,0CAE5B,EAEA04F,aAAc,SAASvvG,GACnB,OAAQA,GACJ,IAAK,SACD,OAAO,IAAIwc,GAAM3O,KAAKwlF,cAC1B,IAAK,SACD,OAAO,IAAI72E,GAAM3O,KAAK0lF,cAC1B,QACI,MAAM,IAAI18E,MAAM,0CAE5B,EAEA24F,sBAAuB,SAASxvG,GAC5B,OAAQA,GACJ,IAAK,SACD,OAAO,IAAIwc,GAAM3O,KAAKmjF,aAC1B,IAAK,SACD,OAAO,IAAIx0E,GAAM3O,KAAKojF,aAC1B,QACI,MAAM,IAAIp6E,MAAM,0CAE5B,EAEA44F,aAAc,SAASzvG,GACnB,OAAQA,GACJ,IAAK,SACD,IAAIirF,EAAap9E,KAAKo9E,WACtB,IAAKA,EAAY,MACjB,OAAOp9E,KAAK6hG,cAAgBzkB,EAAW/0E,GAC3C,IAAK,SACD,IAAIk1E,EAAav9E,KAAKu9E,WACtB,IAAKA,EAAY,MACjB,OAAOv9E,KAAKu2E,cAAgBgH,EAAWl1E,GAC3C,QACI,MAAM,IAAIW,MAAM,0CAExB,OAAO,IACX,EAMA2J,OAAQ,WAIJ,OAHA3S,KAAK8hG,cACL9hG,KAAKg/F,aACLh/F,KAAKi/F,YACEj/F,IACX,EAEA6S,UAAW,SAASgD,EAAK,EAAGC,EAAK,GAC7B,MAAM,MAAE8uE,EAAK,KAAE9sF,GAASkI,KACxB,IAAK4kF,IAAU9sF,EAAM,OAErB,MAAMmxB,EAAW,IAAIla,GAAS61E,GAC9B37D,EAASpW,UAAUgD,EAAIC,GACvB9V,KAAK4kF,MAAQ37D,EAASlZ,OAEtB/P,KAAKmjF,YAAY9xE,OAAOwE,EAAIC,GAC5B9V,KAAKojF,YAAY/xE,OAAOwE,EAAIC,GAC5B9V,KAAKwlF,aAAan0E,OAAOwE,EAAIC,GAC7B9V,KAAK0lF,aAAar0E,OAAOwE,EAAIC,GAE7Bhe,EAAK+a,UAAUgD,EAAIC,GACnB9V,KAAKi/F,WACT,EAEA,SAAAA,GACI,MAAM,GAAE52F,EAAE,MAAEs1C,EAAK,UAAEpM,GAAcvxC,KACjCA,KAAKozE,kBAELpzE,KAAKo3D,2BAA2B/uD,EAAIs1C,EAAMzoB,OAAQ,CAAEqc,cAEpDvxC,KAAKk/F,uBAKLl/F,KAAK23B,QAAQsuD,cAAgB,IACjC,EAEA6b,YAAa,WACT,MAAM,MAAEnkD,GAAU39C,KACZo7D,EAAWzd,EAAMyd,WAEjB2mC,EAAU/hG,KAAKgiG,YAAY5mC,GAC3BoqB,EAAexlF,KAAKwlF,aAAeuc,EAAQpvG,OAC3C+yF,EAAe1lF,KAAK0lF,aAAeqc,EAAQ78F,OAE3C0/E,EAAQ5kF,KAAK6pF,UAAUzuB,GAC7Bp7D,KAAK4kF,MAAQA,EAEb,IAAIqd,EAAmBjiG,KAAKkiG,qBAAqBtd,EAAOY,EAAcE,GACtE1lF,KAAKmjF,YAAc8e,EAAiBtvG,OACpCqN,KAAKojF,YAAc6e,EAAiB/8F,MACxC,EAEA85F,WAAY,WACR,MAAM,MAAEpa,EAAK,YAAEzB,EAAW,YAAEC,GAAgBpjF,KAEtClI,EAAOkI,KAAKmiG,SAASvd,EAAOzB,EAAY/gF,QAASghF,EAAYhhF,SACnEpC,KAAKlI,KAAOA,CAChB,EAEAsqG,mBAAoB,SAASC,EAAcC,EAAUC,EAAeC,GAEhE,IAAIC,EAAaC,EACbC,EAAgBC,EAChBjlD,EAAQ39C,KAAK29C,MACbklD,EAAWllD,EAAMxyD,IAAIk3G,GACrBS,EAAYnlD,EAAMxyD,IAAIo3G,GACtBQ,EAAY/iG,KAAKyhG,WAAWY,GAC5BW,EAAahjG,KAAKyhG,WAAWc,GAC7BU,EAAcjjG,KAAK4hG,aAAaS,GAChCa,EAAeljG,KAAK4hG,aAAaW,GAGjCQ,GAEIJ,EADAL,EACiB,IAAI3zF,GAAM2zF,GACpBU,EACUE,EAEA,IAAIv0F,GAAMm0F,GAE/BL,EAAcziG,KAAKmjG,UAAUN,EAASzZ,OAAQ2Z,EAAWE,EAAaN,EAAgBN,IAEtFI,EAAc,IAAI9zF,GAAMk0F,GAIxBG,GACAJ,EAAkB,IAAIj0F,GAAM6zF,GAAaC,GACzCC,EAAe1iG,KAAKmjG,UAAUL,EAAU1Z,OAAQ4Z,EAAYE,EAAcN,EAAiBL,IAE3FG,EAAe,IAAI/zF,GAAMm0F,GAG7B,IAAIn6D,EAAM,CAAC,EAGX,OAFAA,EAAI05D,GAAgBI,EACpB95D,EAAI45D,GAAiBG,EACd/5D,CACX,EAEAq5D,YAAa,SAAS5mC,GAElB,IAAIzd,EAAQ39C,KAAK29C,MACby1C,EAAch4B,EAAS,GACvBw5B,EAAax5B,EAASA,EAAS5pE,OAAS,GAE5C,OAAImsD,EAAMz4C,SAASk+F,WAAazlD,EAAMhrD,SAASywG,SAEpCpjG,KAAKoiG,mBAAmB,SAAUxN,EAAY,SAAUxB,GAI5DpzF,KAAKoiG,mBAAmB,SAAUhP,EAAa,SAAUwB,EACpE,EAEAsN,qBAAsB,SAAStd,EAAOY,EAAcE,GAEhD,IAQImc,EAActrB,EAGd4M,EAiBAC,EA5BAigB,EAAgBze,EAAM,GACtB0e,EAAe1e,EAAMA,EAAMpzF,OAAS,GACpCmsD,EAAQ39C,KAAK29C,MACb4lD,EAAY5lD,EAAMxyD,IAAI,UACtBq4G,EAAY7lD,EAAMxyD,IAAI,UACtBiyF,EAAap9E,KAAKo9E,WAClBG,EAAav9E,KAAKu9E,WAClBkmB,EAAezjG,KAAKsjD,MAAM3rB,QAK9B,GAAIylD,IAAeA,EAAW1E,iBAAiB14E,KAAK6hG,cAAe,CAC/DA,EAAgB7hG,KAAK6hG,cAAgBzkB,EAAW/0E,GAChD,IAAIq7F,EAA2BH,EAAUlV,iBAAmBoV,EAAaE,uBAErEC,EAAa,IAAIh1F,GADAy0F,GAAiB3d,EACIF,GAC1CrC,EAAcnjF,KAAK6jG,mBACfH,EACAtmB,EACAykB,EACA+B,EACA,SAER,MACIzgB,EAAcqC,EAIlB,GAAIjI,IAAeA,EAAW7E,iBAAiB14E,KAAKu2E,cAAe,CAC/DA,EAAgBv2E,KAAKu2E,cAAgBgH,EAAWl1E,GAChD,IAAIy7F,EAA2BN,EAAUnV,iBAAmBoV,EAAaE,uBAErEI,EAAa,IAAIn1F,GADA00F,GAAgB9d,EACKE,GAC1CtC,EAAcpjF,KAAK6jG,mBACfC,EACAvmB,EACAhH,EACAwtB,EACA,SAER,MACI3gB,EAAcsC,EAGlB,MAAO,CACH/yF,OAAQwwF,EACRj+E,OAAQk+E,EAEhB,EAEA+f,UAAW,SAASa,EAAW10B,EAAU4E,EAAQ9iE,EAAKqoD,GAElD,IAiBIwqC,EAjBAC,EAAe50B,EAASoJ,iBAAiBxE,GACzCuvB,EAAezjG,KAAKsjD,MAAM3rB,QAe9B,GAdKqsE,IAEGA,EADAE,EACYT,EAAaU,kBAErBnkG,KAAK23B,QAAQsuD,cAGD,CAAE9uF,KAAM,iBAERssG,EAAaW,gBAKhCJ,EAAW,MAAM,IAAIh7F,MAAM,oBAEhC,GAAyB,mBAAdg7F,EACPC,EAAWD,MACR,CACH,IAAIK,EAAaL,EAAU7sG,KAG3B,GAAwB,mBADxB8sG,EAAWR,EADWS,EAAe,sBAAwB,mBACpBG,IACL,MAAM,IAAIr7F,MAAM,mBAAqBq7F,EAC7E,CACA,IAAIjb,EAAS6a,EAASz4G,KAClBwU,KACAsvE,EACA4E,EACA9iE,EACA4yF,EAAU/iG,MAAQ,CAAC,EACnBw4D,EACAz5D,MAEJ,OAAKopF,EACEA,EAAO/8E,MAAMrM,KAAKu+F,kBADL,IAAI5vF,EAE5B,EAGAk1F,mBAAoB,SAASS,EAAoB9yB,EAAM0C,EAAQ1/D,EAAMilD,GAEjE,IAAI40B,EAKAkW,EAJAnb,EAAS50E,EAAK3U,IACd4jG,EAAezjG,KAAKsjD,MAAM3rB,QAE9B,IAAK2sE,EAAoB,OAAOlb,EAEhC,GAAkC,mBAAvBkb,EACPC,EAAoBD,MACjB,CACH,IAAIE,EAAsBF,EAAmBntG,KAE7C,GAAiC,mBADjCotG,EAAoBd,EAAagB,yBAAyBD,IACb,MAAM,IAAIx7F,MAAM,6BAA+Bw7F,EAChG,CAEA,OADAnW,EAAkBkW,EAAkB/4G,KAAKwU,KAAMwU,EAAMg9D,EAAM0C,EAAQowB,EAAmBrjG,MAAQ,CAAC,EAAGw4D,EAASz5D,OAEpGquF,EAAgBhiF,MAAMrM,KAAKu+F,kBADLnV,CAEjC,EAEA3L,eAAgB,SAAShF,EAAeiF,GACpC,MAAM13B,EAAahmD,KAAKikD,gBACxB,QAAK+B,GACE,GAAa/5B,OAChBwsD,EACAzyB,EACA03B,EACA,CAAEz2D,oBAAqBjnB,KAAKkkD,6BAEpC,EAEAy5B,aAAc,SAASC,GACnB,MAAM53B,EAAahmD,KAAKikD,gBACxB,IAAK+B,EAAY,OAAO,EACxB,MAAMjzC,EAAOizC,EAAWjzC,OACxB,QAAKA,GACE6qE,EAAa7kE,aAAahG,EACrC,EAEA+qE,UAAW,SAAS9sE,GAGhB,MAAMm4D,EAAO,IAAIr6D,GAAKkC,GAGtB,OADAm4D,EAAK9yD,QAAQrW,KAAKw+F,SACXx+F,KAAKy9E,eAAetU,EAC/B,EAGAu7B,iCAAkC,WAE9B,IAAI/mD,EAAQ39C,KAAK29C,MAGbgnD,EADsBhnD,EAAMsc,UAAUF,aACYn8B,SAElDm8B,EAAepc,EAAMuf,mBACrB0nC,EAAuB5kG,KAAK6kG,wBAAwB9qC,EAAan8B,UAErE,OAAO18B,GAAM,CAAC,EAAGyjG,EAA6BC,EAClD,EAIAC,wBAAyB,SAASl0C,GAE9B,MAA6B,iBAAlBA,EAAmC,CAAEnhD,SAAUmhD,EAAet/C,OAAQ,KAAMvE,MAAO,EAAG7L,KAAM,MAChG0vD,CACX,EAIAm0C,4BAA6B,SAASC,EAAyBC,GAE3D,OAAgC,OAA5BD,EAAyC,UACbtyG,IAA5BsyG,EAEuC,OAAnCC,EAAgD,KAC7CA,EAGJ9jG,GAAM,CAAC,EAAG8jG,EAAgCD,EACrD,EAEA7F,qBAAsB,WAElB,IAAKl/F,KAAKq+F,GAAGvjC,OAAQ,OAAO96D,KAG5B,IADWA,KAAKlI,KACL,OAAOkI,KAKlB,IACI86D,EADQ96D,KAAK29C,MACExyD,IAAI,WAAa,GACpC,IAAK2vE,EAAOtpE,OAAQ,OAAOwO,KAI3B,IAFA,IAAI4kG,EAAuB5kG,KAAK0kG,mCAEvB7pC,EAAM,EAAG7qD,EAAI8qD,EAAOtpE,OAAQqpE,EAAM7qD,EAAG6qD,IAAO,CACjD,IAAIjE,EAAY52D,KAAKm+F,YAAYtjC,GACjC,GAAKjE,EAAL,CACA,IAAIlG,EAAQoK,EAAOD,GACflK,EAAgB3wD,KAAK6kG,wBAAwBn0C,EAAM9yB,UACnDA,EAAW59B,KAAK8kG,4BAA4Bn0C,EAAei0C,GAC3D9hE,EAAuB9iC,KAAKilG,8BAA8BrnE,GAC9Dg5B,EAAUr8B,aAAa,YAAa,GAAElE,wBAAwByM,IAC9D9iC,KAAKklG,oBAAoBrqC,EAND,CAO5B,CAEA,OAAO76D,IACX,EAEAklG,oBAAqB,SAASxzG,GAI1B,MAAM,QAAE8gE,EAAO,gBAAE4rC,GAAoBp+F,KAC/BuxC,EAAY6sD,EAAgB1sG,GAClC,GAAK6/C,EACL,IAAK,IAAIhrC,KAAYgrC,EAAW,CAC5B,MAAM,GAAEjc,GAAOic,EAAUhrC,GACrB+uB,GAAOA,KAAMk9B,UAAiBA,EAAQl9B,GAAI8+C,YAClD,CACJ,EAEAqqB,oBAAqB,SAAShlC,GAE1B,MAAM,MAAE9b,EAAK,MAAE2F,GAAUtjD,KACnBmlG,EAAkB,GAAG1rC,QACrBC,EAAS/b,EAAMxyD,IAAIsuE,GACnB2rC,EAAQ1rC,GAAUA,EAAOpkC,GAE/B,IAAK8vE,EAID,OAFAplG,KAAKmlG,GAAmB,KACxBnlG,KAAKqlG,gBAAgB5rC,IACd,EAGX,MAAM6rC,EAAWhiD,EAAMiiD,aAAaH,GACpC,IAAKE,EAAU,MAAM,IAAIt8F,MAAM,qBAAuBywD,EAAU,UAEhE,MAAM+rC,EAAUF,EAAS75C,SAASnI,GAClC,QAAKkiD,IAKLxlG,KAAKmlG,GAAmBK,EACxBxlG,KAAKqlG,gBAAgB5rC,IACd,EACX,EAEA4rC,gBAAiB,SAAS5rC,GAEtB,MAAMgsC,EAAoB,GAAGhsC,UACvB+rC,EAAUxlG,KAAKyhG,WAAWhoC,GAChC,GAAI+rC,EAAS,CACT,IAAIE,EAAkBF,EAAQ3vB,qBAAqB71E,KAAK29C,MAAMxyD,IAAIsuE,IAC9DisC,IAAoBF,EAAQn9F,KAAIq9F,EAAkB,MACtD1lG,KAAKylG,GAAqBC,CAC9B,MACI1lG,KAAKylG,GAAqB,IAElC,EAEAE,0BAA2B,SAAS9qC,GAEhC,OAAQ76D,KAAK29C,MAAM+S,MAAMmK,GAAKj9B,UAAY,CAAC,CAC/C,EAEAgoE,uBAAwB,SAAS/qC,GAG7B,OADoB76D,KAAK2lG,0BAA0B9qC,GAC7B/tD,OAAS,CACnC,EAEA+4F,sBAAuB,SAAShrC,GAG5B,OADoB76D,KAAK2lG,0BAA0B9qC,GAC9B55D,IACzB,EAEA6kG,6BAA8B,WAI1B,OAFmB9lG,KAAK29C,MAAMuf,mBACUt/B,UAAY,CAAC,GACzB38B,IAChC,EAIA8kG,wBAAyB,SAASC,EAAmBC,GAEjD,OAA0B,OAAtBD,EAAmC,UACbvzG,IAAtBuzG,EAEiC,OAA7BC,EAA0C,KACvCA,EAGJ/kG,GAAM,CAAC,EAAG+kG,EAA0BD,EAC/C,EAeAE,SAAU,SAASv1F,EAAIC,EAAIsK,EAAIE,GAG3B,IAAI+qF,EACAC,EAEA1kF,EADA2kF,EAAa,EAEC,iBAAP11F,GAEPw1F,EAASx1F,EAAGxC,EACZi4F,EAASz1F,EAAG3C,EACM,iBAAP4C,GAEPy1F,EAAaz1F,EACb8Q,EAAWxG,GAGXwG,EAAW9Q,IAIfu1F,EAASx1F,EACTy1F,EAASx1F,EACS,iBAAPsK,GAEPmrF,EAAanrF,EACbwG,EAAWtG,GAGXsG,EAAWxG,GAKnB,IAAI+qF,EAA2BjmG,KAAK8lG,+BAChCE,EAAoBtkF,EACpB4kF,EAAetmG,KAAK+lG,wBAAwBC,EAAmBC,GAG/Dv1C,EAAQ,CAAE9yB,SAAU59B,KAAKumG,iBAAiBJ,EAAQC,EAAQC,EAAYC,IAG1E,OADAtmG,KAAK29C,MAAMqd,aADD,EACkBtK,EAAOhvC,IADzB,CAGd,EAGA8kF,UAAW,SAASr4F,EAAGH,EAAGqG,GAGtB,IAAIoyF,EAAgC,iBAANt4F,EAC1Bg4F,EAASM,EAAkBt4F,EAAEA,EAAIA,EACjCi4F,EAASK,EAAkBt4F,EAAEH,EAAIA,EACjC0T,EAAW+kF,EAAkBz4F,EAAIqG,EAEjC8mD,EAAS,CAAEhtD,EAAGg4F,EAAQn4F,EAAGo4F,GACzBvrC,EAAM76D,KAAK0mG,eAAeP,EAAQC,GAEtC,OADApmG,KAAK29C,MAAM6d,aAAaX,EAAKM,EAAQz5C,GAC9Bm5C,CACX,EAQA8rC,UAAW,SAASC,EAAOvyF,EAAKw/B,GAW5B,IAAI3E,EAAU23D,EAAYtgG,EACtBrU,GAASmiB,IACT66B,EAAW76B,EAAI66B,SACf23D,EAAgC,YAAlBxyF,EAAI+jD,UAClB7xD,EAAW8N,EAAI2xC,aAGf9W,EAAW76B,EACXwyF,GAAa,EACbtgG,EAAW,MAKf,IAAIugG,EAAsB,CACtBC,KAHJ73D,EAAWA,GAAY,KAGH,KAChB83D,YAAa,EACbC,SAAU,SACV/sC,KAAM,UAGN2sC,IACAC,EAAoBI,UAAY,MAChCJ,EAAoBK,SAAW,OAGnC,IACInhD,EADAohD,EAAS,GAAER,GAEf,GAAwB,iBAAbrgG,EAEPy/C,EAAahmD,KAAKgjD,SAASz8C,OACxB,CAEH,IAAIxP,EAAQiJ,KAAKq+F,GACjBr4C,EAAcjvD,EAAgB,WAAIA,EAAMivD,WAAWl9C,KAAO9I,KAAKqI,GAAGu0B,cAAc,OACpF,CAEA,KAAMopB,aAAsB/C,gBACxB,MAAM,IAAIj6C,MAAM,mEAGpBo+F,EACKhuE,SAASp5B,KAAKsjD,MAAMjF,OACpB/f,iBAAiBwoE,EAAqB9gD,GAE3CzW,WAtDA,SAAwB63D,EAAQvzD,GAC5B,OAAO,WACHuzD,EAAO7iG,SACiB,mBAAbsvC,GACPA,GAER,CACJ,CA+CWwzD,CAAeD,EAAQvzD,GAAW3E,EACjD,EAEA26C,UAAW,SAASzuB,GAEhBA,IAAaA,EAAW,IAExB,IAAIzwD,EAAY3K,KAAKsjD,MAAM3rB,QAAQ2vE,iBAAmB,EAClD9sC,EAASx6D,KAAK29C,MAAM6c,SACpB+sC,EAAgBvnG,KAAKsjD,MAAM3rB,QAAQ4vE,cAEvC,IAAK/sC,EAAQ,CACT,IAAI+sC,EACC,OAAOnsC,EAASzqE,IAAIge,IADN6rD,EAAS+sC,CAEhC,CAEA,IAAIC,EAAW,GAAWhtC,GAAUA,EAAS7vD,EAAU6vD,EAAOrjE,MAC9D,IAAK,GAAWqwG,GACZ,MAAM,IAAIx+F,MAAM,kCAAoCwxD,EAAOrjE,KAAO,MAGtE,IAAI8J,EAAOu5D,EAAOv5D,MAAQ,CAAC,EAS3B,OAPYumG,EAASh8G,KACjBwU,KACAo7D,EACAn6D,EACAjB,OAGeo7D,EAASzqE,IAAIge,GAEpC,EAIAwzF,SAAU,SAASvd,EAAOzB,EAAaC,GAEnC,IAAIz4E,EAAY3K,KAAKsjD,MAAM3rB,QAAQ8vE,oBAAsB,EACrDrtF,EAAYpa,KAAK29C,MAAMvjC,YACvB4+E,EAAmBh5F,KAAKsjD,MAAM3rB,QAAQqhE,iBAErC5+E,IACDA,EAAY4+E,GAAoB,CAAC,GAGrC,IAAI0O,EAAc,GAAWttF,GAAaA,EAAYzP,EAAUyP,EAAUjjB,MAC1E,IAAK,GAAWuwG,GACZ,MAAM,IAAI1+F,MAAM,qCAAuCoR,EAAUjjB,KAAO,MAG5E,IAAI8J,EAAOmB,GAAMgY,EAAUnZ,MAAQ,CAAC,GACpCA,EAAKo2E,KAAM,EAEX,IAAIv/E,EAAO4vG,EAAYl8G,KACnBwU,KACAmjF,EACAC,EACAwB,EACA3jF,EACAjB,MAQJ,MALoB,iBAATlI,IAEPA,EAAO,IAAIoX,GAAK,GAAE6sB,kBAAkBjkC,KAGjCA,CACX,EAKAmsD,cAAe,WAEX,IAAInsD,EAAOkI,KAAKlI,KAChB,OAAKA,EAEEA,EAAKsK,QAFM,IAGtB,EAEAiiD,wBAAyB,WAErB,IAAIvsD,EAAOkI,KAAKlI,KAChB,IAAKA,EAAM,OAAO,KAElB,IAAI06D,EAAUxyD,KAAKwyD,QACnB,GAAIA,EAAQjnE,eAAe,QAAS,OAAOinE,EAAQj+D,KACnD,IAAIA,EAAOuD,EAAK4a,YAEhB,OADA8/C,EAAQj+D,KAAOA,EACRA,CACX,EAEA2vD,0BAA2B,WAEvB,IAAIpsD,EAAOkI,KAAKlI,KAChB,IAAKA,EAAM,OAAO,KAElB,IAAI06D,EAAUxyD,KAAKwyD,QACnB,GAAIA,EAAQjnE,eAAe,uBAAwB,OAAOinE,EAAQvrC,oBAClE,IAAItF,EAAe7pB,EAAKovB,yBAExB,OADAsrC,EAAQvrC,oBAAsBtF,EACvBA,CACX,EAEAqiC,oBAAqB,WAEjB,IAAIlsD,EAAOkI,KAAKlI,KAChB,IAAKA,EAAM,OAAO,EAElB,IAAI06D,EAAUxyD,KAAKwyD,QACnB,GAAIA,EAAQjnE,eAAe,UAAW,OAAOinE,EAAQhhE,OACrD,IAAIA,EAASsG,EAAKtG,OAAO,CAAEy1B,oBAAqBjnB,KAAKkkD,8BAErD,OADAsO,EAAQhhE,OAASA,EACVA,CACX,EAEAwuC,iBAAkB,SAASxuC,GAEvB,IAAIsG,EAAOkI,KAAKlI,KAChB,OAAKA,EAEEA,EAAKmc,cAAcziB,EAAQ,CAAEy1B,oBAAqBjnB,KAAKkkD,8BAF5C,IAGtB,EAEAyjD,gBAAiB,SAAS7zF,GAEtB,IAAIhc,EAAOkI,KAAKlI,KAChB,OAAKA,GACD+8C,GAAa/gC,KAAQA,EAAQxE,WAAWwE,GAAS,KAC9Chc,EAAKub,QAAQS,EAAO,CAAEmT,oBAAqBjnB,KAAKkkD,+BAFrC,IAGtB,EAEAoqC,mBAAoB,SAAS98F,GAEzB,IAAIsG,EAAOkI,KAAKlI,KAChB,OAAKA,EAEEA,EAAK8d,gBAAgBpkB,EAAQ,CAAEy1B,oBAAqBjnB,KAAKkkD,8BAF9C,IAGtB,EAEA0jD,kBAAmB,SAAS9zF,GAExB,IAAIhc,EAAOkI,KAAKlI,KAChB,OAAKA,EAEEA,EAAK8b,UAAUE,EAAO,CAAEmT,oBAAqBjnB,KAAKkkD,8BAFvC,IAGtB,EAEA2jD,gBAAiB,SAAS72F,GAEtB,IAAIlZ,EAAOkI,KAAKlI,KAChB,OAAKA,EAEEA,EAAKsb,aAAapC,EAAO,CAAEiW,oBAAqBjnB,KAAKkkD,8BAF1C,IAGtB,EAEAqqC,sBAAuB,SAASv9E,GAE5B,IAAIlZ,EAAOkI,KAAKlI,KAChB,OAAKA,EAEEA,EAAKyb,mBAAmBvC,EAAO,CAAEiW,oBAAqBjnB,KAAKkkD,8BAFhD,IAGtB,EAEA4jD,qBAAsB,SAAS92F,GAE3B,IAAIlZ,EAAOkI,KAAKlI,KAChB,OAAKA,EAEEA,EAAKwb,6BAA6BtC,EAAO,CAAEiW,oBAAqBjnB,KAAKkkD,8BAF1D,IAGtB,EAUAqiD,iBAAkB,SAASp4F,EAAGH,EAAGkN,EAAIE,GAEjC,IAIIsG,EAJAkc,EAAW,CAAC,EAGZyoE,EAAa,EAEC,iBAAPnrF,GAEPmrF,EAAanrF,EACbwG,EAAWtG,GAGXsG,EAAWxG,EAIXwG,IAAUkc,EAAS38B,KAAOygB,GAG9B,IAoBIkiC,EAEAmkD,EAtBAC,IAAuBtmF,GAAYA,EAASumF,kBAC5CC,EAA6BxmF,GAAYA,EAASumF,kBAAoBvmF,EAASymF,gBAC/EC,EAAmB1mF,GAAYA,EAAS2mF,eAGxCvwG,EAAOkI,KAAKlI,KACZm6B,EAAU,CAAEhL,oBAAqBjnB,KAAKkkD,6BACtCokD,EAAa,IAAI35F,GAAMR,EAAGH,GAC1ByD,EAAI3Z,EAAK0pB,cAAc8mF,EAAYr2E,GAGnCs2E,EAAgBzwG,EAAK+pB,UAAUpQ,EAAGwgB,GAYtC,GAXI+1E,IAAoBO,EAAiBA,EAAgBvoG,KAAKgkD,uBAA0B,GACpFkkD,IAA2BK,GAAkB,GAAKvoG,KAAKgkD,sBAAwBukD,IAAmB,GACtG3qE,EAASpuB,SAAW+4F,EAOfH,IAAkBxkD,EAAU9rD,EAAKsrB,WAAW3R,IAE7CmyC,EACAmkD,EAAcnkD,EAAQtuC,YAAYgzF,OAC/B,CACH,IAAIl1F,EAAetb,EAAKypB,SAAS9P,GAC7B+2F,EAAkBF,EAAWnlG,WAAWiQ,GAC5C20F,EAAc,CAAE55F,EAAGq6F,EAAgBr6F,EAAGH,EAAGw6F,EAAgBx6F,EAC7D,CAMA,OALA4vB,EAASvsB,OAAS02F,EAGlBnqE,EAAS9wB,MAAQu5F,EAEVzoE,CACX,EAEAqnE,8BAA+B,SAASt0C,GAEpC,IAAI43C,EACAE,EAAa,EACbxnG,EAAO,CAAC,EACZ,GAA6B,iBAAlB0vD,EACP43C,EAAgB53C,MACb,IAAsC,iBAA3BA,EAAcnhD,SAK5B,MAAM,IAAIxG,MAAM,kDAJhB/H,EAAO0vD,EAAc1vD,MAAQ,CAAC,EAC9BsnG,EAAgB53C,EAAcnhD,SAC9Bi5F,EAAa93C,EAAc7jD,OAAS,CAGxC,CAEA,IAAIk7F,EAAuBO,EAAgB,GAAOA,GAAiB,EAE/DR,EAAc,EACdW,EAAyB,CAAEv6F,EAAG,EAAGH,EAAG,GACxC,GAAI2iD,EAAct/C,OAAQ,CACtB,IAAIs3F,EAAiBh4C,EAAct/C,OACL,iBAAnBs3F,IAA6BZ,EAAcY,GAClDA,EAAex6F,IAAGu6F,EAAuBv6F,EAAIw6F,EAAex6F,GAC5Dw6F,EAAe36F,IAAG06F,EAAuB16F,EAAI26F,EAAe36F,EACpE,CAEA,IAWI2pE,EAXAywB,EAAkD,IAA7BM,EAAuBv6F,GAA0C,IAA7Bu6F,EAAuB16F,GAA4B,IAAhB+5F,EAE5Fa,EAAiB3nG,EAAK4nG,aACtBC,EAAqB7nG,EAAK8nG,iBAE1BjxG,EAAOkI,KAAKlI,KACZm6B,EAAU,CAAEhL,oBAAqBjnB,KAAKkkD,6BAEtC10C,EAAWw4F,EAAsBO,EAAgBvoG,KAAKgkD,sBAAyBukD,EAC/E3kD,EAAU9rD,EAAK8d,gBAAgBpG,EAAUyiB,GAGzCnlB,EAAQ27F,EACZ,GAAI7kD,EAAS,CACT,GAAIwkD,GACAzwB,EAAc/zB,EAAQhkD,MAAMwC,SAChBiP,OAAOq3F,OAChB,CACH,IAAIpxB,EAAS1zB,EAAQxhD,QACrBk1E,EAAOvlE,OAAO6xC,EAAQhkD,OAAQ,IAC9B03E,EAAO/hE,UAAUwyF,GACjBpwB,EAAcL,EAAOz3E,GACzB,CAEI+oG,IACA97F,EAAS82C,EAAQ92C,QAAU27F,EACvBK,IACAh8F,EAAQD,IAAiBC,EAAQ,IAAM,IAAO,KAI1D,MAEI6qE,EAAc7/E,EAAK8H,MAAMwC,QACrBgmG,GAAkBzwB,EAAYtmE,OAAOq3F,GAG7C,OAAO,GAAE3yE,kBACJljB,UAAU8kE,EAAYxpE,EAAGwpE,EAAY3pE,GACrC+D,OAAOjF,EAChB,EAEAk8F,oBAAqB,SAASr4C,GAE1B,IAAI7tB,EAAuB9iC,KAAKilG,8BAA8Bt0C,GAC9D,OAAO,IAAIhiD,GAAMm0B,EAAqB54B,EAAG44B,EAAqB3wB,EAClE,EAEAu0F,eAAgB,SAASv4F,EAAGH,GAQxB,IANA,IACIotD,EADQp7D,KAAK29C,MACIyd,WAEjB6tC,EAAejpG,KAAKuuF,sBAAsB,IAAI5/E,GAAMR,EAAGH,IAEvD6sD,EAAM,EACD7qD,EAAIorD,EAAS5pE,OAAQqpE,EAAM7qD,EAAG6qD,IAAO,CAC1C,IAAIquC,EAAgB9tC,EAASP,GAE7B,GAAIouC,EADsBjpG,KAAKuuF,sBAAsB2a,GACb,KAC5C,CAEA,OAAOruC,CACX,EAKA,iBAAAmb,CAAkBpwE,EAAKuI,EAAGH,GACtBwkE,GAASlnF,UAAUkxF,YAAYhxF,KAAKwU,KAAM4F,EAAKuI,EAAGH,GAClDhO,KAAKgxE,OAAO,mBAAoBprE,EAAKuI,EAAGH,EAC5C,EAEA,iBAAAuzE,CAAkB37E,EAAKuI,EAAGH,GACtBwkE,GAASlnF,UAAU8qF,YAAY5qF,KAAKwU,KAAM4F,EAAKuI,EAAGH,GAClDhO,KAAKgxE,OAAO,mBAAoBprE,EAAKuI,EAAGH,EAC5C,EAEA,eAAAwzE,CAAgB57E,EAAKuI,EAAGH,GACpBhO,KAAKgxE,OAAO,iBAAkBprE,EAAKuI,EAAGH,GACtCwkE,GAASlnF,UAAUorF,UAAUlrF,KAAKwU,KAAM4F,EAAKuI,EAAGH,EACpD,EAEAquE,gBAAiB,SAASz2E,EAAKuI,EAAGH,GAE9BwkE,GAASlnF,UAAU+wF,gBAAgBl7E,MAAMnB,KAAMpB,WAC/CoB,KAAKgxE,OAAO,uBAAwBprE,EAAKuI,EAAGH,EAChD,EAEAsuE,aAAc,SAAS12E,EAAKuI,EAAGH,GAE3BwkE,GAASlnF,UAAUgxF,aAAan7E,MAAMnB,KAAMpB,WAC5CoB,KAAKgxE,OAAO,oBAAqBprE,EAAKuI,EAAGH,EAC7C,EAEAuuE,YAAa,SAAS32E,EAAKuI,EAAGH,GAE1BwkE,GAASlnF,UAAUixF,YAAYp7E,MAAMnB,KAAMpB,WAC3CoB,KAAKgxE,OAAO,mBAAoBprE,EAAKuI,EAAGH,EAC5C,EAEAwuE,YAAa,SAAS52E,EAAKuI,EAAGH,GAE1BhO,KAAKg2E,kBAAkBpwE,EAAKuI,EAAGH,GAC/BhO,KAAKyhF,UAAU77E,EAAKuI,EAAGH,EAC3B,EAEAooE,YAAa,SAASxwE,EAAKuI,EAAGH,GAG1B,IAAIm7F,EAAWnpG,KAAKs+F,UAIpB,OAHI6K,GAAUnpG,KAAK6uE,UAAUjpE,EAAKujG,GAEvBnpG,KAAK6uE,UAAUjpE,GACb87E,QAET,IAAK,aACD1hF,KAAKopG,UAAUxjG,EAAKuI,EAAGH,GACvB,MAEJ,IAAK,iBACDhO,KAAKqpG,cAAczjG,EAAKuI,EAAGH,GAC3B,MAEJ,IAAK,OACDhO,KAAK8hF,KAAKl8E,EAAKuI,EAAGH,GAKtBm7F,GAAU,GAAOA,EAAUnpG,KAAK6uE,UAAUjpE,IAE9C5F,KAAKuhF,kBAAkB37E,EAAKuI,EAAGH,EACnC,EAEA0oE,UAAW,SAAS9wE,EAAKuI,EAAGH,GAGxB,IAAIm7F,EAAWnpG,KAAKs+F,UAOpB,OANI6K,IACAnpG,KAAK6uE,UAAUjpE,EAAKujG,GACpBnpG,KAAKs+F,UAAY,MAGVt+F,KAAK6uE,UAAUjpE,GACb87E,QAET,IAAK,aACD1hF,KAAKspG,aAAa1jG,EAAKuI,EAAGH,GAC1B,MAEJ,IAAK,iBACDhO,KAAKupG,iBAAiB3jG,EAAKuI,EAAGH,GAC9B,MAEJ,IAAK,OACDhO,KAAKkiF,QAAQt8E,EAAKuI,EAAGH,GAG7BhO,KAAKwhF,gBAAgB57E,EAAKuI,EAAGH,GAC7BhO,KAAKk9E,gBAAgBt3E,EACzB,EAEA62E,UAAW,SAAS72E,GAEhB4sE,GAASlnF,UAAUmxF,UAAUt7E,MAAMnB,KAAMpB,WACzCoB,KAAKgxE,OAAO,iBAAkBprE,EAClC,EAEA82E,SAAU,SAAS92E,GAEf4sE,GAASlnF,UAAUoxF,SAASv7E,MAAMnB,KAAMpB,WACxCoB,KAAKgxE,OAAO,gBAAiBprE,EACjC,EAEA+2E,WAAY,SAAS/2E,GAEjB4sE,GAASlnF,UAAUqxF,WAAWx7E,MAAMnB,KAAMpB,WAC1CoB,KAAKgxE,OAAO,kBAAmBprE,EACnC,EAEAg3E,WAAY,SAASh3E,GAEjB4sE,GAASlnF,UAAUsxF,WAAWz7E,MAAMnB,KAAMpB,WAC1CoB,KAAKgxE,OAAO,kBAAmBprE,EACnC,EAEAi3E,WAAY,SAASj3E,EAAKuI,EAAGH,EAAGgjC,GAE5BwhC,GAASlnF,UAAUuxF,WAAW17E,MAAMnB,KAAMpB,WAC1CoB,KAAKgxE,OAAO,kBAAmBprE,EAAKuI,EAAGH,EAAGgjC,EAC9C,EAEAw4D,QAAS,SAAS5jG,EAAKuI,EAAGH,GAEtBhO,KAAKg2E,kBAAkBpwE,EAAKuI,EAAGH,GAE/BhO,KAAKypG,eAAe7jG,EAAKuI,EAAGH,GAENhO,KAAK6uE,UAAUjpE,GAAKC,iBACrBD,EAAIC,iBAC7B,EAIA4jG,eAAgB,SAAS7jG,EAAKuI,EAAGH,GAE7B,GAAIhO,KAAK0zE,IAAI,aAAc,CAEvB,GAAI1zE,KAAKo8E,8BAA8Bx2E,GAAM,OAE7C,IAAIgxD,EAAYhxD,EAAIT,cAChBukG,EAAWp7F,SAASsoD,EAAUj7B,aAAa,aAAc,IAEzDipE,EAAuB5kG,KAAK0kG,mCAC5BiF,EAAuB3pG,KAAK6kG,wBAAwB7kG,KAAK2lG,0BAA0B+D,IACnF9rE,EAAW59B,KAAK8kG,4BAA4B6E,EAAsB/E,GAElEvoF,EAASrc,KAAKgpG,oBAAoBprE,GAClC1sB,EAAKmL,EAAOlO,EAAIA,EAChBgD,EAAKkL,EAAOrO,EAAIA,EAEhB47F,EAAgB5pG,KAAK4lG,uBAAuB8D,GAC5C1D,EAAoBhmG,KAAK6lG,sBAAsB6D,GAC/CzD,EAA2BjmG,KAAK8lG,+BAChCQ,EAAetmG,KAAK+lG,wBAAwBC,EAAmBC,GAEnEjmG,KAAK6uE,UAAUjpE,EAAK,CAChB87E,OAAQ,aACRgoB,SAAUA,EACVx4F,GAAIA,EACJC,GAAIA,EACJy4F,cAAeA,EACftD,aAAcA,EACdzgG,iBAAiB,GAGzB,MAII7F,KAAK6uE,UAAUjpE,EAAK,CAAEC,iBAAiB,IAG3C7F,KAAKsjD,MAAMumD,mBAAmB7pG,KAAM4F,EAAIrR,KAC5C,EAEAu1G,mBAAoB,SAASlkG,EAAKuI,EAAGH,GAEjC,GAAKhO,KAAK0zE,IAAI,iBAAd,CAEA,IACIq2B,EADgBnkG,EAAIV,OACUy2B,aAAa,OAC3CpnC,EAAOyL,KAAKi2E,mBAAmB8zB,EAAe,CAAEC,8BAA8B,IAElFhqG,KAAK6uE,UAAUjpE,EAAKrR,EANkB,CAO1C,EAEAktF,UAAW,SAAS77E,EAAKuI,EAAGH,GAEpBhO,KAAKo8E,8BAA8Bx2E,IAElC5F,KAAK0zE,IAAI,aAEd1zE,KAAK6uE,UAAUjpE,EAAK,CAChB87E,OAAQ,OACRxwE,GAAI/C,EACJgD,GAAInD,GAEZ,EAGAo7F,UAAW,SAASxjG,EAAKuI,EAAGH,GAExB,IAAIzZ,EAAOyL,KAAK6uE,UAAUjpE,GACtB8qD,EAAQ,CAAE9yB,SAAU59B,KAAKumG,iBAAkBp4F,EAAI5Z,EAAK2c,GAAMlD,EAAIzZ,EAAK4c,GAAK5c,EAAKq1G,cAAer1G,EAAK+xG,eACjGtmG,KAAKsjD,MAAM3rB,QAAQsyE,mBAAmBv5C,EAAM9yB,SAASvsB,OAOzD,MAAMswD,EAAa,CAAE6T,IAAI,GACrBx1E,KAAKsjD,MAAM65B,WAA0B,cAAbv3E,EAAIzT,OAC5BwvE,EAAWjgC,OAAQ,GAEvB1hC,KAAK29C,MAAM+S,MAAMn8D,EAAKm1G,SAAUh5C,EAAOiR,EAC3C,EAEA0nC,cAAe,SAASzjG,EAAKuI,EAAGH,GACxBhO,KAAKsjD,MAAM3rB,QAAQuyE,WACDlqG,KAAKmqG,eAAevkG,EAAKuI,EAAGH,IAC5BhO,KAAKsjD,MAAM3rB,QAAQyyE,eACjCpqG,KAAKqqG,mBAAmBzkG,EAAKuI,EAAGH,GAGhChO,KAAKsjD,MAAM3rB,QAAQyyE,cACnBpqG,KAAKqqG,mBAAmBzkG,EAAKuI,EAAGH,GAEhChO,KAAKsqG,kBAAkBtqG,KAAKs2E,eAAe1wE,GAAMuI,EAAGH,EAAGhO,KAAK6uE,UAAUjpE,GAGlF,EAEAk8E,KAAM,SAASl8E,EAAKuI,EAAGH,GAEnB,IAAIzZ,EAAOyL,KAAK6uE,UAAUjpE,GAC1B5F,KAAK29C,MAAM9qC,UAAU1E,EAAI5Z,EAAK2c,GAAIlD,EAAIzZ,EAAK4c,GAAI,CAAEqkE,IAAI,IACrDx1E,KAAK6uE,UAAUjpE,EAAK,CAChBsL,GAAI/C,EACJgD,GAAInD,GAEZ,EAIAs7F,aAAc,WAEd,EAEAC,iBAAkB,SAAS3jG,EAAKuI,EAAGH,GAE/B,IAAIzZ,EAAOyL,KAAK6uE,UAAUjpE,GACtB09C,EAAQtjD,KAAKsjD,MAEbA,EAAM3rB,QAAQuyE,UACdlqG,KAAKuqG,kBAAkBh2G,GAEvByL,KAAKwqG,qBAAqBj2G,EAAM4Z,EAAGH,GAGlCs1C,EAAMmnD,YAAYzqG,OAInBA,KAAK0qG,iBAAiBn2G,GACtByL,KAAK2qG,oBAAoBp2G,EAAMqR,IAH/B5F,KAAK4qG,UAAUr2G,GAMnByL,KAAK6qG,oBAAoBt2G,EAC7B,EAEA2tF,QAAS,WAET,EAEA0oB,UAAW,SAASr2G,GAIP,WAFDA,EAAK2hF,eAGLl2E,KAAK29C,MAAMp5C,OAAO,CAAEixE,IAAI,IAKxBx1E,KAAK29C,MAAMvqD,IAAImB,EAAKu2G,UAAWv2G,EAAKw2G,WAAY,CAAEv1B,IAAI,GAGlE,EAEAk1B,iBAAkB,SAASn2G,GAGnByL,KAAKsjD,MAAM3rB,QAAQkrD,eAAiB7iF,KAAK29C,MAAM6K,aAE/Cj0D,EAAKg3B,EAAI,KAEjB,EAEAo/E,oBAAqB,SAASp2G,EAAMqR,GAEhC,IAAIklG,EAAYv2G,EAAKu2G,UACjBC,EAAax2G,EAAKw2G,WAClBC,EAAahrG,KAAK29C,MAAMtyD,KAAKy/G,GAEjC,GADiBE,IAAelxC,GAAKqD,UAAU4tC,EAAYC,GAC3C,CACZ,IAAI1nD,EAAQtjD,KAAKsjD,MACbynD,EAAWz1E,IACXt1B,KAAKgxE,OAAO,kBAAmBprE,EAAK09C,EAAMoI,gBAAgBq/C,EAAWz1E,IAAK/gC,EAAK02G,cAAeH,GAE9FE,EAAW11E,IACXt1B,KAAKgxE,OAAO,eAAgBprE,EAAK09C,EAAMoI,gBAAgBs/C,EAAW11E,IAAK/gC,EAAK22G,mBAAoBJ,EAExG,CACJ,EAEAK,cAAe,SAASC,EAAWr7F,EAAQyoD,GACvC,IAAI6yC,EAAgB,KAChBC,EAAmBroG,IAEnBsoG,EAAgB,KAChBC,EAAmBvoG,IAEnBkL,EAAIi9F,EAAUj9F,EACdH,EAAIo9F,EAAUp9F,EAElB,IAAK,IAAIlH,EAAI,EAAGA,EAAIiJ,EAAOve,OAAQsV,IAAK,CACpC,MAAM2kG,EAAQ1pG,KAAKoN,IAAIY,EAAOjJ,GAAGqH,EAAIi9F,EAAUj9F,GAC3Cs9F,EAAQH,IACRA,EAAmBG,EACnBJ,EAAgBt7F,EAAOjJ,IAG3B,MAAM4kG,EAAQ3pG,KAAKoN,IAAIY,EAAOjJ,GAAGkH,EAAIo9F,EAAUp9F,GAC3C09F,EAAQF,IACRA,EAAmBE,EACnBH,EAAgBx7F,EAAOjJ,GAE/B,CASA,OAPIwkG,EAAmB9yC,IACnBrqD,EAAIk9F,EAAcl9F,GAElBq9F,EAAmBhzC,IACnBxqD,EAAIu9F,EAAcv9F,GAGf,CAAEG,IAAGH,IAChB,EAEAq8F,mBAAoB,SAASzkG,EAAKuI,EAAGH,GAEjC,MAAM,MAAEs1C,EAAK,MAAE3F,GAAU39C,MACnB,cAAEoqG,GAAkB9mD,EAAM3rB,QAC1BpjC,EAAOyL,KAAK6uE,UAAUjpE,GACtB4yD,EAAS4xC,EAAc5xC,QAAU,GAIjCzoD,EAAS,CAFA/P,KAAK0hG,aAAgC,WAAnBntG,EAAKu2G,UAAyB,SAAW,aACzDntD,EAAMyd,YAGjBgwC,EAAYprG,KAAKmrG,cAAc,CAAEh9F,EAAGA,EAAGH,EAAGA,GAAK+B,EAAQyoD,GAEvDxnD,EAAQsyC,EAAMqoD,mBAAmBP,GACvCprG,KAAKsqG,kBAAkBnkG,SAASszE,iBAAiBzoE,EAAM7C,EAAG6C,EAAMhD,GAAIo9F,EAAUj9F,EAAGi9F,EAAUp9F,EAAGhO,KAAK6uE,UAAUjpE,GACjH,EAEAukG,eAAgB,SAASvkG,EAAKuI,EAAGH,GAE7B,MAAM,MAAEs1C,GAAUtjD,MACZ,UAAEkqG,EAAS,mBAAEv0B,GAAuBryB,EAAM3rB,QAC1CpjC,EAAOyL,KAAK6uE,UAAUjpE,GAC5B,IAAIgmG,GAAY,EAGhB,IAAIt7F,EAAI45F,EAAU1xC,QAAU,GACxBqzC,EAAcvoD,EAAMwoD,uBACpB,CAAE39F,EAAGA,EAAImC,EAAGtC,EAAGA,EAAIsC,EAAGE,MAAO,EAAIF,EAAGG,OAAQ,EAAIH,GAChD45F,EAAU6B,mBAGVC,EAAkBz3G,EAAK03G,aAAe,KACtCC,EAAoB33G,EAAK43G,eAAiB,KAC1CC,EAAkB73G,EAAK83G,aAAe,KAE1C93G,EAAK03G,YAAc13G,EAAK43G,cAAgB53G,EAAK83G,YAAc,KAE3D,IAuCIxsG,EAvCAwhC,EAAcpmC,OAAOqxG,UACrBC,EAAU,IAAI59F,GAAMR,EAAGH,GAE3B69F,EAAYl0G,SAAQ,SAAS65E,GACzB,MAAMiP,EAAa,GAEoB,UAAnCjP,EAAKnpE,GAAGszB,aAAa,WACrB8kD,EAAW7uF,KAAK,CACZmhB,KAAMy+D,EAAK7zB,MAAMvmB,UACjB88C,OAAQ1C,EAAKnpE,KAIrBmpE,EAAKhG,EAAE,YAAY9oE,UAAU/K,SAAQu8E,IACjCuM,EAAW7uF,KAAK,CACZmhB,KAAMy+D,EAAKwC,YAAYE,GACvBA,UACF,IAGNuM,EAAW9oF,SAAQkpF,IACf,MAAM,OAAE3M,EAAM,KAAEnhE,GAAS8tE,EAEnBrxE,EAAWuD,EAAKmD,SAAS9F,gBAAgBm8F,GAE3C/8F,EAAW6xB,IACgB6qE,IAAsBh4B,GACvB5wB,EAAM3rB,QAAQ60E,mBAAmBrrG,MACvDmiD,EAAO/uD,EAAKk4G,uBAAuBj7B,EAAOA,EAAKnpE,KAAO6rE,EAAU,KAAOA,OAEvE7yC,EAAc7xB,EACdjb,EAAK03G,YAAcz6B,EACnBj9E,EAAK43G,cAAgBj4B,EAE7B,GAGR,GAAGl0E,MAGH,IAAIqsG,EAAc,KACdJ,EAAc13G,EAAK03G,YACnBE,EAAgB53G,EAAK43G,cACrBA,IACAE,EAAc93G,EAAK83G,YAAcJ,EAAYj3B,cAAcm3B,EAAe,gBAE9E,IAAI1yC,EAAUllE,EAAKu2G,UACf4B,EAAoBR,IAAsBC,EAQ9C,GAPIH,GAAmBU,GACnBV,EAAgBj7B,YAAYq7B,EAAiB,CACzC13B,YAAY,EACZi4B,UAAU,IAIdV,EAAa,CACb,MAAM,QAAEW,EAAO,MAAEC,EAAK,MAAEC,GAAUv4G,EAKlC,GAJAA,EAAKs4G,MAAQ1+F,EACb5Z,EAAKu4G,MAAQ9+F,EACb49F,GAAY,GAEPc,IACiC,mBAAvB/2B,GAAsCk3B,IAAU1+F,GAAK2+F,IAAU9+F,GAEtE,OAAO49F,EAKf,GADA/rG,EAAMosG,EAAY12B,WAAW42B,EAAeh+F,EAAGH,EAAGhO,KAAK29C,MAAO8b,IACzDizC,GAAoBlqG,GAAQoqG,EAAS/sG,GAEtC,OAAO+rG,EAGXr3G,EAAKq4G,QAAU/sG,EAEX6sG,GACAT,EAAYhzD,UAAUozD,EAAa,CAC/B33B,YAAY,EACZi4B,UAAU,GAItB,MAEI9sG,EAAM,CAAEsO,EAAGA,EAAGH,EAAGA,GAYrB,OATAhO,KAAK29C,MAAMvqD,IAAIqmE,EAAS55D,GAAO,CAAEsO,EAAGA,EAAGH,EAAGA,GAAK,CAAEwnE,IAAI,IAEjDw2B,GACAhsG,KAAKgxE,OAAO,uBAAwBprE,EAAKomG,EAAiBE,EAAmBzyC,GAE7EwyC,GACAjsG,KAAKgxE,OAAO,oBAAqBprE,EAAKqmG,EAAaE,EAAe1yC,GAG/DmyC,CACX,EAEArB,kBAAmB,SAASh2G,GAIxB,IAAI03G,EAAc13G,EAAK03G,YACnBE,EAAgB53G,EAAK43G,cACrBF,GAAeE,IAEfF,EAAYl7B,YAAYx8E,EAAK83G,YAAa,CAAE33B,YAAY,EAAMi4B,UAAU,IACxEp4G,EAAK22G,mBAAqBe,EAAYp3B,WAAWs3B,IAGrD53G,EAAK03G,YAAc13G,EAAK43G,cAAgB,IAC5C,EAEA7B,kBAAmB,SAASplG,EAAQiJ,EAAGH,EAAGzZ,GAGtC,MAAM,MAAE+uD,EAAK,MAAE3F,GAAU39C,KAEzB,GAAIzL,EAAKw4G,cAAgB7nG,EAAQ,CAEzB3Q,EAAK83G,aACL93G,EAAKy4G,iBAAiBj8B,YAAYx8E,EAAK83G,YAAa,CAChD33B,YAAY,IAIpB,MAAMs4B,EAAmBz4G,EAAKy4G,iBAAmB1pD,EAAMmI,SAASvmD,GAChE,GAAI8nG,EAAkB,CAGlB,MAAM9B,EAAqB32G,EAAK22G,mBAAqB8B,EAAiBn4B,WAAW3vE,GAC3EmnG,EAAc93G,EAAK83G,YAAcW,EAAiBh4B,cAAck2B,EAAoB,eAEtFA,GAAsBlrG,KAAKsjD,MAAM3rB,QAAQ60E,mBAAmBrrG,MAC5DmiD,EACA/uD,EAAKk4G,uBAAuBO,EAAkB9B,IAK1CmB,GACAW,EAAiB/zD,UAAUozD,EAAa,CACpC33B,YAAY,KAKpBngF,EAAK22G,mBAAqB,KAC1B32G,EAAK83G,YAAc,KAE3B,MAEI93G,EAAK22G,mBAAqB,KAC1B32G,EAAK83G,YAAc,IAE3B,CAEA93G,EAAKw4G,YAAc7nG,EAEnBy4C,EAAMvqD,IAAImB,EAAKu2G,UAAW,CAAE38F,EAAGA,EAAGH,EAAGA,GAAK,CAAEwnE,IAAI,GACpD,EAEAg1B,qBAAsB,SAASj2G,EAAO,CAAC,EAAG4Z,EAAGH,GAEzC,MAAM,MAAE2vC,GAAU39C,MACZ,iBAAEgtG,EAAgB,mBAAE9B,EAAkB,YAAEmB,EAAW,UAAEvB,GAAcv2G,EAEzE,IAAK22G,IAAuBmB,IAAgBW,EAAkB,OAE9DA,EAAiBj8B,YAAYs7B,EAAa,CAAE33B,YAAY,IAGxD,MAAM70E,EAAMmtG,EAAiBz3B,WAAW21B,EAAoB/8F,EAAGH,EAAG2vC,EAAOmtD,GACzEntD,EAAMvqD,IAAI03G,EAAWjrG,EAAK,CAAE21E,IAAI,GACpC,EAEAy3B,qBAAsB,SAAS14G,GAE3BA,EAAKg3B,EAAIvrB,KAAK29C,MAAMxyD,IAAI,KACxB6U,KAAK29C,MAAMkK,UAIX,IAAI5tB,EAAQj6B,KAAKqI,GAAG4xB,MACpB1lC,EAAK4lE,cAAgBlgC,EAAMkgC,cAC3BlgC,EAAMkgC,cAAgB,OAElBn6D,KAAKsjD,MAAM3rB,QAAQu1E,eACnBltG,KAAKmtG,sBAAsB54G,EAEnC,EAEAs2G,oBAAqB,SAASt2G,GAEX,OAAXA,EAAKg3B,IACLvrB,KAAK29C,MAAMvqD,IAAI,IAAKmB,EAAKg3B,EAAG,CAAEiqD,IAAI,IAClCjhF,EAAKg3B,EAAI,MAIbvrB,KAAKqI,GAAG4xB,MAAMkgC,cAAgB5lE,EAAK4lE,cAE/Bn6D,KAAKsjD,MAAM3rB,QAAQu1E,eACnBltG,KAAKotG,wBAAwB74G,EAErC,EAEA84G,8BAA+B,SAASvC,GAGpC,IAKIwC,EALArsG,EAAO,GAEXA,EAAK,GAAK6pG,EACV7pG,EAAK,GAAKjB,KAGV,IAAI8G,EAAI,EACJC,EAAI,EAEU,WAAd+jG,GACAhkG,EAAI,EACJwmG,EAAoB,WAEpBvmG,EAAI,EACJumG,EAAoB,UAGxB,IAAIztG,EAAMG,KAAK29C,MAAMxyD,IAAImiH,GAEzB,GAAIztG,EAAIy1B,GAAI,CACR,IAAIk8C,EAAOvwE,EAAK6F,GAAK9G,KAAKsjD,MAAMoI,gBAAgB7rD,EAAIy1B,IAChD4+C,EAAS1C,EAAKqE,qBAAqBh2E,GACnCq0E,IAAW1C,EAAKnpE,KAAI6rE,OAASzhF,GACjCwO,EAAK6F,EAAI,GAAKotE,CAClB,CAQA,OANA,SAAgC5E,EAAU4E,GAGtC,OAFAjzE,EAAK8F,GAAKuoE,EACVruE,EAAK8F,EAAI,GAAKuoE,EAASjnE,KAAO6rE,OAASzhF,EAAYyhF,EAC5CjzE,CACX,CAGJ,EAEAksG,sBAAuB,SAAS54G,GAE5B,SAASg5G,EAAkB/7B,EAAM0C,GAC7B,IAAI5wB,EAAQkuB,EAAKluB,MAEjB,OADeA,EAAM3rB,QAAQ60E,mBACbrrG,MAAMmiD,EAAOtjD,KAAKysG,uBAAuBj7B,EAAM0C,GACnE,CAEA,IAAI5wB,EAAQtjD,KAAKsjD,MACbr7C,EAAWq7C,EAAM3F,MAAM2oB,WAC3B/xE,EAAKi5G,OAAS,CAAC,EAEf,IAAK,IAAI1mG,EAAI,EAAGkJ,EAAI/H,EAASzW,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAC7C,IAAI0qE,EAAOvpE,EAASnB,GAAG2kD,SAASnI,GAEhC,GAAKkuB,EAAL,CAIA,IAAIi8B,EAAUz8G,MAAM1F,UAAUwP,MAAMtP,KAAKgmF,EAAKnpE,GAAGG,iBAAiB,aAC3B,UAAnCgpE,EAAKnpE,GAAGszB,aAAa,WAErB8xE,EAAQ77G,KAAK4/E,EAAKnpE,IAGtB,IAAIqlG,EAAmBD,EAAQ15G,OAAOw5G,EAAkBx9G,KAAKwE,EAAMi9E,IAEnE,GAAIk8B,EAAiBl8G,OAAS,EAAG,CAE7B,IAAK,IAAIuV,EAAI,EAAGqQ,EAAIs2F,EAAiBl8G,OAAQuV,EAAIqQ,EAAGrQ,IAChDyqE,EAAKv4B,UAAUy0D,EAAiB3mG,GAAI,CAAE4tE,oBAAoB,IAG9DnD,EAAKv4B,UAAU,KAAM,CAAE27B,qBAAqB,IAE5CrgF,EAAKi5G,OAAOh8B,EAAK7zB,MAAMroB,IAAMo4E,CACjC,CAnBA,CAoBJ,CACJ,EAEAN,wBAAyB,SAAS74G,GAM9B,IAJA,IACI+gC,EACAq4E,EAFAC,EAAa5iH,OAAO0F,KAAK6D,EAAKi5G,QAIzB1mG,EAAI,EAAGkJ,EAAI49F,EAAWp8G,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAC/CwuB,EAAKs4E,EAAW9mG,GAChB6mG,EAAgBp5G,EAAKi5G,OAAOl4E,GAE5B,IAAIk8C,EAAOxxE,KAAKsjD,MAAMoI,gBAAgBp2B,GACtC,GAAIk8C,EAAM,CACN,IAAK,IAAIzqE,EAAI,EAAGqQ,EAAIu2F,EAAcn8G,OAAQuV,EAAIqQ,EAAGrQ,IAC7CyqE,EAAKT,YAAY48B,EAAc5mG,GAAI,CAAE4tE,oBAAoB,IAE7DnD,EAAKT,YAAY,KAAM,CAAE6D,qBAAqB,GAClD,CACJ,CAEArgF,EAAKi5G,OAAS,IAClB,EAEAv3B,mBAAoB,SAASp2E,EAAKwU,GAE9BA,IAAQA,EAAM,CAAC,GAIf,IAAI9f,EAAO,CACPmtF,OAAQ,iBACRopB,UAAWjrG,EACXq2E,eAAgB7hE,EAAI6hE,gBAAkB,SACtC+0B,cAAejrG,KAAKH,EAAM,YAAcG,KAAKH,EAAM,QAAUG,KAAKH,EAAM,QAAQwI,GAAK,MACrF0iG,WAAY3oG,GAAMpC,KAAK29C,MAAMxyD,IAAI0U,IACjC4sG,uBAAwBzsG,KAAKqtG,8BAA8BxtG,IAS/D,OANAG,KAAKitG,qBAAqB14G,IAEe,IAArC8f,EAAI21F,+BACJhqG,KAAKs+F,UAAY/pG,GAGdA,CACX,EAIAqmF,QAAS,WACLpI,GAASlnF,UAAUsvF,QAAQz5E,MAAMnB,KAAMpB,WACvCoB,KAAKugG,aACT,EAEAxlB,SAAU,WACNvI,GAASlnF,UAAUyvF,SAAS55E,MAAMnB,KAAMpB,WACxCoB,KAAKy/F,eACT,EAEAnxB,SAAU,WACNkE,GAASlnF,UAAUgjF,SAASntE,MAAMnB,KAAMpB,WACxCoB,KAAKy/F,eACT,GAED,CAEC1hB,MAAO,KAGX/yF,OAAOC,eAAeizG,GAAS5yG,UAAW,aAAc,CAEpDJ,YAAY,EAEZC,IAAK,WACD,IAAIiyF,EAAap9E,KAAKo9E,WACtB,IAAKA,EAAY,CACb,IAAImmB,EAAYvjG,KAAK29C,MAAMhrD,SAC3B,OAAO,IAAImc,GAAKy0F,EAAUp1F,EAAGo1F,EAAUv1F,EAC3C,CACA,IAAI6zF,EAAe7hG,KAAK6hG,aACxB,OAAIzkB,EAAW1E,iBAAiBmpB,GACrB,IAAI/yF,GAAK9O,KAAKwlF,cAElBpI,EAAWpJ,YAAY6tB,GAAgBzkB,EAAW/0E,GAC7D,IAIJrd,OAAOC,eAAeizG,GAAS5yG,UAAW,aAAc,CAEpDJ,YAAY,EAEZC,IAAK,WACD,IAAIoyF,EAAav9E,KAAKu9E,WACtB,IAAKA,EAAY,CACb,IAAIimB,EAAYxjG,KAAK29C,MAAMz4C,SAC3B,OAAO,IAAI4J,GAAK00F,EAAUr1F,EAAGq1F,EAAUx1F,EAC3C,CACA,IAAIuoE,EAAev2E,KAAKu2E,aACxB,OAAIgH,EAAW7E,iBAAiBnC,GACrB,IAAIznE,GAAK9O,KAAK0lF,cAElBnI,EAAWvJ,YAAYuC,GAAgBgH,EAAWl1E,GAC7D,ICltEG,MAAMwlG,GAAc,CACvBC,KAAM,OACNC,MAAO,QACPC,KAAM,OACNC,MAAO,QACPjwB,MAAO,QACP+f,OAAQ,UAGCmQ,GAAa7hC,GAAKxsD,OAAO,CAElCic,QAAS,IACToxC,YAAY,EACZihC,WAAY,KACZ1hC,aAAc,KAEd90C,QAAS,CACLxgC,KAAM,IAGVqjC,UAAW,WACP,OAAO0W,GAAmB,GAAGlxC,KAAK23B,QAAQxgC,aAC9C,EAEA61E,KAAM,WACFhtE,KAAKmuG,WAAa,CAAC,CACvB,EAEA39B,iBAAkB,SAAS1nE,EAAMyiB,GAC7BvrB,KAAKqI,GAAGg0B,aAAavzB,EAAM9I,KAAKouG,YAAY7iF,GAChD,EAEA8iF,WAAY,SAASvlG,GACjB,MAAM,GAAET,GAAOrI,KACX8I,EAAKkD,aAAe3D,GACpBA,EAAGZ,YAAYqB,EAEvB,EAEAslG,YAAa,SAAS7iF,GAClB,MAAM,GAAEljB,EAAE,WAAE8lG,GAAenuG,MAC3BurB,GAAKA,KACCA,EAAI,GACV,IAAI+iF,EAAYH,EAAW5iF,GAC3B,GAAI+iF,EAAW,OAAOA,EACtBA,EAAYH,EAAW5iF,GAAKplB,SAASooG,cAAc,YAAchjF,EAAI,IACrE,IAAIijF,GAAY,IAChB,IAAK,IAAIC,KAAYN,EACjBM,GAAYA,EACRA,EAAWljF,GAAKkjF,EAAWD,IAC3BA,EAAYC,GAIpB,GAAID,KAAc,IAAW,CACzB,MAAME,EAAgBP,EAAWK,GAEjCnmG,EAAGg0B,aAAaiyE,EAAWI,EAAcj+B,YAC7C,MAEIpoE,EAAGg0B,aAAaiyE,EAAWjmG,EAAGqrB,YAElC,OAAO46E,CACX,EAEAK,aAAc,WACV,MAAM,GAAEtmG,EAAE,WAAE8lG,GAAenuG,KAC3B,IAAK,IAAIurB,KAAK4iF,EAAY9lG,EAAG2zB,YAAYmyE,EAAW5iF,IACpDvrB,KAAKmuG,WAAa,CAAC,CACvB,ICpESjpD,GAASgqB,GAAgBrvD,OAAO,CAEzCic,QAAS,OACTtB,UAAW,mBACXkB,WAAY,CACR,iBAAkB,OAClB,KAAQ,QAGZ/D,QAAS,CACL2hC,QAAS,EACT7iD,GAAI,EACJC,GAAI,EACJk4F,iBAAiB,EACjB17E,MAAO,CACH,eAAgB,EAChB,OAAU,YAIlB,WAAA27E,CAAYv/B,EAAUxmE,GAClB,MAAM,QAAE6uB,GAAY33B,MACd,gBAAE4uG,GAAoBj3E,EAC5B,IAAI7gB,EACJ,IACI,MAAM+oF,EAAQ,GAAE/2F,GAEhB,GADAgO,EAAI+oF,EAAM3/D,oBAAoB/nC,OACN,SAApB0nG,EAAM/jE,WAAwB8yE,EAAiB,CAC/C,MAAME,EAAqBh4F,EAAE6/B,OAAO,OAAS,EACzCm4D,EAAqB,IACrBh4F,EAAIA,EAAEs6B,OAAO,EAAG09D,GAExB,CACJ,CAAE,MAAO3sE,GAGL,MAAMujB,EAAW4pB,EAAS6E,oBAAoBrrE,GAC9CgO,EAAI,GAAE0wB,WAAW,GAAO,CAAC,EAAG7P,EAAS+tB,EAASlzC,UAClD,CACA,OAAOsE,CACX,EAEA,mBAAAi4F,CAAoBz/B,GAChBtvE,KAAKi5B,IAAI/D,KAAK,IAAKo6C,EAASjrB,0BAChC,EAEA,aAAA2qD,CAAc1/B,EAAUxmE,GACpB,MAAM,IAAEmwB,EAAG,QAAEtB,GAAY33B,MACnB,QAAEs5D,EAAO,MAAE0W,GAAUr4C,EAC3B,IAAIs3E,EAAkBjvG,KAAK+vE,cAAcT,EAAUxmE,GAEnD,GAAIwwD,EAAS,CACJ0W,GAASlnE,IAASwmE,EAASjnE,IAI5B4wB,EAAI10B,SAER,IAAImhD,EAAW4pB,EAAS6E,oBAAoBrrE,GAC5C,MAAM+tB,EAAK6uB,EAASv3C,EAAKu3C,EAASl1C,MAAQ,EACpCsmB,EAAK4uB,EAAS13C,EAAK03C,EAASj1C,OAAS,EAC3Ci1C,EAAW,GAAEjuB,cAAciuB,EAAUupD,GACrC,MAAMz+F,EAAQzO,KAAKwL,IAAIm4C,EAASl1C,MAAO,GACjCC,EAAS1O,KAAKwL,IAAIm4C,EAASj1C,OAAQ,GACnC2B,GAAM5B,EAAQ8oD,GAAW9oD,EACzB6B,GAAM5B,EAAS6oD,GAAW7oD,EAC1By+F,EAAgB,GAAEn5E,gBAAgB,CACpCp6B,EAAGyW,EACHxW,EAAG,EACHma,EAAG,EACHe,EACA5M,EAAG2sB,EAAKzkB,EAAKykB,EACb1kB,EAAG2kB,EAAKzkB,EAAKykB,IAEjBm4E,EAAkBA,EAAgBn5E,SAASo5E,EAC/C,CACAj2E,EAAI/D,KAAK,CACL,EAAKl1B,KAAK6uG,YAAYv/B,EAAUxmE,GAChC,UAAa,GAAEutB,wBAAwB44E,IAE/C,EAEA,SAAAh2D,CAAUq2B,EAAUxmE,GAChB,MAAM,IAAEmwB,EAAG,QAAEtB,GAAY33B,KACzBi5B,EAAI/D,KAAKyC,EAAQzE,OACbyE,EAAQw3E,kBACRl2E,EAAI/D,KAAK,gBAAiB,sBAE1Bo6C,EAASoJ,iBAAiB5vE,GAC1B9I,KAAK+uG,oBAAoBz/B,GAEzBtvE,KAAKgvG,cAAc1/B,EAAUxmE,EAErC,IC9FEsmG,GAAY,GAYLC,GAAOngC,GAAgBrvD,OAAO,CAEvCic,QAAS,OACTtB,UAAW,iBACXkB,WAAY,CACR,iBAAkB,QAGtB/D,QAAS,CACL2hC,QAAS,EACTg2C,SAAUF,GACVrnD,MAAM,EACN70B,MAAO,CACH,OAAU,UACV,eAAgB,EAChB,iBAAkB,OAClB,kBAAmB,UAI3Bq8E,QAAS,QACTC,UAAW,QAEXC,8BAA+B,CAC3B,eACA,aACA,aACA,YACA,mBACA,SAGJC,+BAAgC,CAC5B,SACA,OACA,eACA,iBACA,mBACA,eACA,eACA,aACA,aACA,SAIJC,kBAAmB,CACf,gBACA,QACA,MACA,OACA,QACA,YAIJC,iBAAkB,CACd,OACA,QACA,YAGJ,kBAAAC,CAAmBvgC,EAAUwgC,GACzB,MAAM,+BACFJ,EAA8B,kBAC9BC,EAAiB,iBACjBC,GACA5vG,KACE+vG,EAAeD,EAAQh0E,UAE7B,IAAK,GAAEtG,qBAAqBs6E,IAAYF,EAAiB52G,SAAS+2G,GAE9D,OADAD,EAAQvrG,UACD,EAGX,GAAIorG,EAAkB32G,SAAS+2G,GAAe,CAE1C,MAAMC,EAAgB1gC,EAASr2C,IAAIyD,QAAQ,IAAIozE,EAAQx6E,MACvD,GAAI06E,EAAe,CACf,MAAQlnG,KAAMmnG,GAAiBD,EAC/B,IAAIn4E,EAAYy3C,EAAS6E,oBAAoB87B,GACzC3gC,EAAS3xB,MAAMgO,cACf9zB,EAAY,GAAEJ,cAAcI,EAAWy3C,EAASS,cAAckgC,KAElE,MAAMz6D,EAAc,GAAE,OAAQ3d,EAAUrlB,WAChCrE,EAAG6M,EAAIhN,EAAGiN,GAAO4c,EAAU3hB,UAC7B,MAAEpJ,EAAK,GAAE+pB,EAAK7b,EAAE,GAAE8b,EAAK7b,GAAO+0F,EAAcj+F,SAC9CjF,GAAO0oC,EAAYzjC,OAAOjF,EAAO+pB,EAAIC,GAEzCg5E,EAAQ1zE,SAAStI,OAAO0hB,EAC5B,CAEA,OADAs6D,EAAQvrG,UACD,CACX,CAMA,OAJAmrG,EAA+B/3G,SAAQikC,IAClB,SAAbA,GAAgD,SAAzBk0E,EAAQ56E,KAAK,SACxC46E,EAAQ70E,WAAWW,EAAS,KAEzB,CACX,EAEA,iBAAAs0E,CAAkBh/B,EAAWi/B,GACzB,MAAM,8BAAEV,GAAkCzvG,KAC1CyvG,EAA8B93G,SAAQikC,IAClCu0E,EAAOl1E,WAAWW,EAAS,GAEnC,EAEA,YAAAw0E,CAAa9gC,EAAUr2C,GACnB,MAAM,QAAEtB,EAAO,kBAAEg4E,GAAsB3vG,MACjC,KAAE+nD,GAASpwB,EACXmE,EAAU7C,EAAI6C,UACpB,IAAIu0E,EACJ,GAAgB,MAAZv0E,EAAiB,CACjB,IAAKisB,EAAM,OAAO,KAClBsoD,EAAWp3E,EAAI72B,QA9H3B,SAA2B62B,EAAKxyB,GAC5B,MAAM6pG,EAAcr3E,EAAI9F,WACxB,KAAOm9E,EAAY9+G,OAAS,GAAG,CAC3B,MAAM++G,EAAaD,EAAY9kE,QAC3B/kC,EAAG8pG,IACHD,EAAY1+G,QAAQ2+G,EAAWp9E,WAEvC,CACJ,CAuHYq9E,CAAkBH,GAAUI,GAAazwG,KAAK6vG,mBAAmBvgC,EAAUmhC,IAC/E,KAAO,CACH,GAAId,EAAkB32G,SAAS8iC,GAAU,OAAO,KAChDu0E,EAAWp3E,EAAI72B,OACnB,CAEA,OADApC,KAAKkwG,kBAAkB5gC,EAAU+gC,GAC1BA,CACX,EAEA,SAAAK,GACI,MAAO,kBAAkB1wG,KAAK+9C,KAClC,EAEA,OAAA4yD,CAAQrhC,EAAUuwB,GAEd,MAAM,QAAE0P,EAAO,UAAEC,EAAS,QAAE73E,GAAY33B,MAClC,QAAEs5D,EAAO,MAAEpmC,GAAUyE,EAErBqmC,EAAc1uD,WAAW,GAAE,KAAK4lB,KAAKhC,GAAOgC,KAAK,iBACjD07E,EAAqC,SAAvB/Q,EAAM3qE,KAAK,QAC/B,IAAI27E,EAAoBvhG,WAAWuwF,EAAM3qE,KAAK,iBAC1C+f,MAAM47D,KAAoBA,EAAoB,GAElD,MAAMC,EAAiBD,EAA8B,EAAVv3C,EAErCy3C,EAAiBD,EAA+B,EAAd9yC,EACxC,IAAIgzC,EAAShxG,KAAKowG,aAAa9gC,EAAUuwB,GACzC,IAAKmR,EAAQ,CACT,MAAMtrD,EAAW4pB,EAAS6E,oBAAoB0rB,EAAM/2F,MAEpD48C,EAASrvC,QAAQqvC,EAASl1C,MAAQ,EAAI,GAAKk1C,EAASj1C,OAAS,EAAI,IACjEugG,EAAU,GAAE,OAAQtrD,EAASlzC,SACjC,CAEA,OADAw+F,EAAO97E,KAAKhC,GACL,GAAE,OAAQ,CACb,GAAMlzB,KAAK0wG,cACZ58E,OAAO,CACNk9E,EAAO5uG,QAAQ8yB,KAAK,CAChB,KAAQ07E,EAAcrB,EAAU,OAChC,OAAUA,EACV,eAAgBwB,IAEpBC,EAAO5uG,QAAQ8yB,KAAK,CAChB,KAAQ07E,EAAcpB,EAAY,OAClC,OAAUA,EACV,eAAgBsB,KAG5B,EAEA,UAAAG,CAAW3tD,GACP,MAAM4tD,EAAW5tD,EAAM3wB,IAAIzpB,eAAelJ,KAAK0wG,aAC3CQ,GACA5tD,EAAMjqB,KAAK2C,YAAYk1E,EAE/B,EAEA,OAAAC,CAAQ7tD,EAAO0tD,GACX1tD,EAAMjqB,KAAK5xB,YAAYupG,EAAOloG,KAClC,EAEA,SAAAmwC,CAAUq2B,EAAUxmE,GAChB,MAAM,QAAE6uB,EAAO,IAAEsB,GAAQj5B,MACnB,QAAEs5D,EAAO,MAAEpmC,EAAK,SAAEo8E,EAAWF,GAAS,MAAEp/B,GAAUr4C,EAClDqhB,EAAS,WAAY9lB,EAASA,EAAc,OAAI,UACjD88C,GAASlnE,IAASwmE,EAASjnE,IAI5B4wB,EAAI10B,SAER,MAAM6sG,EAAkB9hC,EAAS6E,oBAAoBrrE,GAAMuN,QAAQijD,EAAUg2C,GACvEL,EAAkBjvG,KAAK+vE,cAAcT,EAAUxmE,GAC/CkoG,EAAShxG,KAAK2wG,QAAQrhC,EAAU,GAAExmE,IACxC9I,KAAKmxG,QAAQ7hC,EAAShsB,MAAO0tD,GAC7B/3E,EAAI/D,KAAKk8E,EAAgB5+F,UACzBymB,EAAI/D,KAAK,CACL,UAAa,GAAEmB,wBAAwB44E,GACvC,KAAQ,QAAQ+B,EAAO17E,MACvB,KAAQ0jB,GAEhB,EAEA,WAAA+3B,CAAYzB,GACRtvE,KAAKixG,WAAW3hC,EAAShsB,MAC7B,ICvNSxN,GAAUo5B,GAAgBrvD,OAAO,CAE1CuvD,WAAW,EACXC,WAAW,EAEXp2B,UAAW,SAASi4B,EAAWpoE,GAC3B,MAAM,WAAEuoG,EAAa,IAAQrxG,KAAK23B,QAClC7uB,EAAKmxB,MAAM6b,QAAUu7D,CACzB,EAEAtgC,YAAa,SAASG,EAAWpoE,GAC7BA,EAAKmxB,MAAM6b,QAAU,EACzB,ICVEtb,GAAY,GAAwB,eAE7B,GAAW00C,GAAgBrvD,OAAO,CAE3CuvD,WAAW,EACXC,WAAW,EAEX13C,QAAS,CACL6C,cAGJye,UAAW,SAASi4B,EAAWpoE,GAC3B,GAAEA,GAAMmsB,SAASj1B,KAAK23B,QAAQ6C,UAClC,EAEAu2C,YAAa,SAASG,EAAWpoE,GAC7B,GAAEA,GAAMy2B,YAAYv/B,KAAK23B,QAAQ6C,UACrC,GAED,CAECA,eCdE,GAAa,CACf82E,IAAK,MACLC,OAAQ,UAGC7+B,GAAOxD,GAAgBrvD,OAAO,CAEvCic,QAAS,IACTuzC,WAAW,EACXmiC,kBAAmB,WACf,MAAO,CAACxxG,KAAK23B,QAAQiuB,UACzB,EAEA6rD,WAAY,KAEZ,SAAAx4D,CAAUy4D,EAAa5oG,GACnB,MAAMyuD,EAAUm6C,EAAY/zD,OACtB,UAAEiI,EAAS,KAAEpuD,EAAO,GAAE,IAAEm6G,EAAM,EAAC,UAAEv5C,EAAY,GAAWk5C,KAAQtxG,KAAK23B,QAC3E,IAAKiuB,EAAW,MAAM,IAAI58C,MAAM,+BAChC,MAAM4oG,EAAkC,iBAATp6G,EAAqB,CAAEgZ,MAAOhZ,EAAMiZ,OAAQjZ,GAASA,EAC9Eq6G,EAAkBz5C,IAAc,GAAWk5C,IAC3CQ,EAAYD,EAAiBD,EAAephG,MAAQohG,EAAenhG,OACzE,IAAIogD,EAAQ0G,EAAQpsE,IAAIy6D,GACnB50D,MAAMC,QAAQ4/D,KAAQA,EAAQ,IACnC,MAAMkhD,EAAY/xG,KAAKyxG,YAAc,GAC/BO,EAAanhD,EAAMlgE,KAAI,CAAC61C,EAAM90C,IAAU8Q,GAAQuvG,EAAUrgH,GAAQm/D,EAAMn/D,MAC9E,GAAIqgH,EAAUvgH,SAAWq/D,EAAMr/D,QAAUwgH,EAAWr7G,MAAKs7G,IAAcA,IAAY,CAC/E,MAAMC,EAAUlyG,KAAKi5B,IAAI9F,WACnBg/E,EAAWthD,EAAMlgE,KAAI,CAAC61C,EAAM90C,KAC9B,MAAM0gH,EAAU1gH,KAASwgH,EAAWA,EAAQxgH,GAAOoX,KAAO,KAC1D,GAAIkpG,EAAWtgH,GAAQ,OAAO0gH,EAC9B,MAAMC,EAASryG,KAAKsyG,eAAe9rE,EAAMorE,EAAgBQ,GACzD,IAAKC,EAAQ,OAAO,KACpB,KAAMA,aAAkB9tE,YAAa,MAAM,IAAIv7B,MAAM,oCACrDqpG,EAAO5lE,QAAQ/6C,MAAQA,EACvB2gH,EAAO5lE,QAAQmZ,UAAYA,EAC3B,MAAMv0C,EAAS3f,GAASogH,EAAYH,GAKpC,OAJAU,EAAO93E,aAAa,YAAa,EAC3B,aAAalpB,QACb,gBAAgBA,MAEfghG,CAAM,IAEjBryG,KAAKi5B,IAAIH,QAAQhF,OAAOq+E,GACxBnyG,KAAKyxG,WAAa5gD,CACtB,CACA,MAAM0hD,EAAa1hD,EAAMr/D,OACnBA,EAAyB,IAAf+gH,EACV,EACCA,EAAaT,GAAaS,EAAa,GAAKZ,EAC7Ca,EAAW,EACX,CAAEhiG,MAAOhf,EAAQif,OAAQmhG,EAAenhG,QACxC,CAAED,MAAOohG,EAAephG,MAAOC,OAAQjf,GAE7CwO,KAAK49B,SAAS25B,EAASi7C,EAC3B,EAEA,QAAA50E,CAAS25B,EAASi7C,GACd,MAAM,IAAEv5E,EAAG,QAAEtB,GAAY33B,MACnB,OAAE84C,EAAS,EAAC,SAAElb,EAAW,YAAejG,GACxC,MAAEnnB,EAAK,OAAEC,GAAW8mD,EAAQ//D,QAC5B,KAAEwb,EAAI,MAAEE,EAAK,IAAED,EAAG,OAAEE,GAAW8jC,GAAe6B,GAC9C/lC,EAAO,IAAIjE,GAAKkE,EAAMC,EAAKzC,GAASwC,EAAOE,GAAQzC,GAAUwC,EAAME,IACzE,IAAI,EAAEhF,EAAC,EAAEH,GAAMqzD,GAAatuD,EAAM6qB,GAElC,OAAQA,GACJ,KAAK+iC,GAAUS,OACf,KAAKT,GAAUC,IACf,KAAKD,GAAUG,OACX3yD,GAAKqkG,EAAShiG,MAAQ,EACtB,MAEJ,KAAKmwD,GAAUE,MACf,KAAKF,GAAUQ,aACf,KAAKR,GAAUM,UACX9yD,GAAKqkG,EAAShiG,MAKtB,OAAQotB,GACJ,KAAK+iC,GAAUS,OACf,KAAKT,GAAUE,MACf,KAAKF,GAAUI,KACX/yD,GAAKwkG,EAAS/hG,OAAS,EACvB,MAEJ,KAAKkwD,GAAUG,OACf,KAAKH,GAAUQ,aACf,KAAKR,GAAUO,YACXlzD,GAAKwkG,EAAS/hG,OAItBwoB,EAAI/D,KAAK,YAAa,aAAa/mB,MAAMH,KAC7C,GACD,CACC8+E,WAAU,GACVnsB,UAAS,KC1Gb,SAAS8xC,GAAgBjhC,EAAMkhC,EAASC,EAAWt+F,GAE/C,IAAIP,EAAS,UAAWO,EAAOA,EAAIP,MAAQ,GAC3C,OAAO09D,EAAKm2B,gBAAgB7zF,EAChC,CAEA,SAAS8+F,GAAiBphC,EAAMkhC,EAASC,EAAWt+F,GAEhD,IAAI7iB,EAAU,WAAY6iB,EAAOA,EAAI7iB,OAAS,GAC9C,OAAOggF,EAAKxxC,iBAAiBxuC,EACjC,CA4BO,SAASqhH,GAAWpsG,GACvB,OAAO,SAAS+qE,EAAM0C,EAAQ9iE,EAAKiD,GAC/B,GAAIjD,aAAe0hG,QAAS,CACxB,IACIC,EADAC,EAAUhzG,KAAKsjD,MAAMmI,SAASr6C,GAalC,OARQ2hG,EAHJC,EACIA,EAAQt6B,iBAAiBtnE,GAEd6hG,GAAeD,EADV,YAAa3+F,EAAOA,EAAI6+F,QAAU,OAGvCF,EAAQh/B,YAAY5iE,GAAK8E,SAI7B,IAAIvH,GAEZlI,EAAGjb,KAAKwU,KAAMwxE,EAAM0C,EAAQ6+B,EAAU1+F,EACjD,CACA,OAAO5N,EAAGtF,MAAMnB,KAAMpB,UAC1B,CACJ,CAEA,SAASq0G,GAAezhC,EAAM7lF,GAC1B,IAAIwnH,EAAc7jG,WAAW3jB,GAC7B,OAAIkpD,GAAalpD,GACN6lF,EAAKm2B,gBAAgBwL,EAAc,KAEnC3hC,EAAKxxC,iBAAiBmzE,EAErC,CAIO,MAAMC,GAA0BP,IA3DvC,SAAkCrhC,EAAMkhC,EAASK,EAAU1+F,GAEvD,IAAIg/F,EAAS,IACTv7G,EAAO05E,EAAKvtB,gBACZh9B,EAAsBuqD,EAAKttB,4BAC3BovD,EAAe,IAAI1kG,GAAKmkG,EAAS3wG,QAAQiP,OAAO,EAAGgiG,GAASN,EAAS3wG,QAAQiP,OAAO,GAAIgiG,IACxFE,EAAiB,IAAI3kG,GAAKmkG,EAAS3wG,QAAQiP,OAAOgiG,EAAQ,GAAIN,EAAS3wG,QAAQiP,QAAQgiG,EAAQ,IAC/FG,EAAwBF,EAAan/F,UAAUrc,EAAM,CAAEmvB,oBAAqBA,IAC5EwsF,EAA0BF,EAAep/F,UAAUrc,EAAM,CAAEmvB,oBAAqBA,IAChF3Q,EAAgB,GAGpB,OAFIk9F,GAAuBxiH,MAAM1F,UAAUsG,KAAKuP,MAAMmV,EAAek9F,GACjEC,GAAyBziH,MAAM1F,UAAUsG,KAAKuP,MAAMmV,EAAem9F,GACnEn9F,EAAc9kB,OAAS,EAAUuhH,EAASjjG,cAAcwG,GACxD,eAAgBjC,EACT4+F,GAAezhC,EAAMn9D,EAAIq/F,YAE7BC,GAAkBniC,EAAMkhC,EAASK,EAAU1+F,EACtD,IA2Cas/F,GAAoBd,IAzCjC,SAA4BrhC,EAAMkhC,EAASK,EAAUa,GAGjD,OADmBpiC,EAAKq2B,gBAAgBkL,IACd,IAAIpkG,EAElC,ICnCA,SAASklG,GAAYljG,EAAIC,EAAIS,GACzB,GAAI,GAAmBA,GAAS,CAC5B,MAAM,EAAElD,EAAC,EAAEH,GAAMqD,EACjB,GAAI+jB,SAASpnB,GAAI,CACb,MAAMwG,EAAQ,IAAI,GAAO5D,EAAID,IACvB,MAAE/Q,EAAK,IAAEC,GAAQ2U,EAAKS,SAASjH,GACrC4C,EAAKhR,EACL+Q,EAAK9Q,CACT,CACAwR,EAASlD,CACb,CACA,IAAKinB,SAAS/jB,GAAS,OAAOV,EAC9B,IAAInf,EAASmf,EAAGnB,SAASoB,GACzB,OAAe,IAAXS,GAAgB7f,EAAS,EAAUmf,EAChCA,EAAGiB,KAAKhB,GAAK7O,KAAKE,IAAIoP,EAAQ7f,EAAS,GAClD,CAEA,SAAS,GAAO0iF,GAEZ,IAAIhvB,EAASgvB,EAAOv4C,aAAa,gBACjC,OAAe,OAAXupB,EAAwB,EACrB51C,WAAW41C,IAAW,CACjC,CAoDA,SAAS4uD,GAAiBt/F,EAAMg9D,EAAM0C,EAAQ7/D,GAE1C,IAAItB,EAAOy+D,EAAKwC,YAAYE,GACxB7/D,EAAI6wC,QAAQnyC,EAAKsD,QAAQ,GAAO69D,GAAU,GAC9C,IAAI59D,EAAgB9B,EAAKL,UAAUpB,GAInC,OAAO8gG,GAHE,EACHr/F,EAAK5U,MAAMkQ,cAAcwG,GACzB9B,EAAK3U,IACY2U,EAAK5U,MAAOyU,EAAIhD,OAC3C,CAoCA,IAAI0iG,GAAoB,qBACpBC,GAAkB,YA0Ef,MAAM,GA9Hb,SAA+Bx/F,EAAMy/F,EAAOvB,EAASr+F,GACjD,IAAI,OAAEhD,EAAM,YAAE6iG,EAAW,MAAE5rB,GAAUj0E,EAErC,OADIi0E,GA9CR,SAAmB9zE,EAAMriB,EAAMkf,EAAS,GACpC,IAAI2xE,EAAYrnF,EAAGC,EAAGw8D,EACtB,MAAM,MAAEx4D,EAAK,IAAEC,GAAQ2U,EACvB,OAAQriB,GACJ,IAAK,OACD6wF,EAAa,IACbrnF,EAAIkE,EACJjE,EAAIgE,EACJw4D,GAAa,EACb,MACJ,IAAK,QACD4qB,EAAa,IACbrnF,EAAIiE,EACJhE,EAAIiE,EACJu4D,EAAY,EACZ,MACJ,IAAK,MACD4qB,EAAa,IACbrnF,EAAIkE,EACJjE,EAAIgE,EACJw4D,GAAa,EACb,MACJ,IAAK,SACD4qB,EAAa,IACbrnF,EAAIiE,EACJhE,EAAIiE,EACJu4D,EAAY,EACZ,MACJ,QACI,OAEJx4D,EAAMojF,GAAcnjF,EAAImjF,GACxBrnF,EAAEqnF,GAAcpnF,EAAEonF,GAElBpnF,EAAEonF,GAAcrnF,EAAEqnF,GAElB5tD,SAAS/jB,KACT1V,EAAEqnF,IAAe5qB,EAAY/mD,EAC7BzV,EAAEonF,IAAe5qB,EAAY/mD,EAErC,CAMe8iG,CAAU3/F,EAAM8zE,EAAO4rB,GAC3BL,GAAYr/F,EAAK3U,IAAK2U,EAAK5U,MAAOyR,EAC7C,EA2Ha0B,GAAO+gG,GACPM,GA/Gb,SAA+B5/F,EAAMg9D,EAAM0C,EAAQ7/D,GAE/C,IAAIvH,EAAQ0kE,EAAK7zB,MAAM7wC,QACvB,GAAc,IAAVA,EACA,OAAOgnG,GAAiBt/F,EAAMg9D,EAAM0C,EAAQ7/D,GAGhD,IAAIggG,EAAiB7iC,EAAK6C,qBAAqBH,GAC3C7/D,EAAI6wC,QAAQmvD,EAAeh+F,QAAQ,GAAO69D,GAAU,GACxD,IAAIh+D,EAASm+F,EAAen+F,SACxBo+F,EAAiB9/F,EAAKpS,QAAQ2P,OAAOmE,EAAQpJ,GAC7CwJ,EAAgBg+F,EAAe/+F,UAAU,KAAKpB,UAAUkgG,GAI5D,OAAOR,GAHE,EACHS,EAAe10G,MAAMkQ,cAAcwG,GAAevE,OAAOmE,GAASpJ,GAClE0H,EAAK3U,IACY2U,EAAK5U,MAAOyU,EAAIhD,OAC3C,EAgGag0E,GA3Eb,SAA8B7wE,EAAMg9D,EAAM0C,EAAQ7/D,GAE9C,IAAIvL,EAAMyL,EACNhO,EAAW8N,EAAI9N,SACf6iF,EAAS50E,EAAK3U,IAYlB,GATIiJ,EADoB,iBAAbvC,EACAirE,EAAKxuB,SAASz8C,IACD,IAAbA,EACA2tE,EACAljF,MAAMC,QAAQsV,GACd,GAAe2tE,EAAQ3tE,GA9BtC,SAAuB2tE,GACnB,IAAKA,EAAQ,OAAO,KACpB,IAAIprE,EAAOorE,EACX,EAAG,CACC,IAAIp4C,EAAUhzB,EAAKgzB,QACnB,GAAuB,iBAAZA,EAAsB,OAAO,KAExC,GAAgB,OADhBA,EAAUA,EAAQS,eAEdzzB,EAAOA,EAAK26C,sBACT,IAAgB,UAAZ3nB,EAEJ,MADHhzB,EAAOA,EAAKyrG,kBACJ,CAChB,OAASzrG,GACT,OAAOA,CACX,CAkBe0rG,CAActgC,IAGpB,GAAE1+C,qBAAqB1sB,GAAO,CAC/B,GAAIA,IAASorE,IAAW,GAAE1+C,qBAAqB0+C,GAAS,OAAOkV,EAC/DtgF,EAAOorE,CACX,CAEA,IAiBIjiD,EAjBAwiF,EAAajjC,EAAKgH,aAAa1vE,GAC/BsrE,EAAe5C,EAAKzB,cAAcjnE,GAClC4nE,EAAkBc,EAAKb,yBACvBC,EAAeY,EAAKtB,sBACpBwkC,EAAehkC,EAAgB56C,SAAS86C,GAAc96C,SAASs+C,GAC/DugC,EAAcD,EAAa7+E,UAC3B++E,EAAY,GAAE1vE,cAAc1wB,EAAMmgG,GAClCE,EAAWD,EAAUh1G,MAAMwC,QAC3B7N,EAAOi9E,EAAK8G,YAAYxvE,GAE5B,IAAsB,IAAlBuL,EAAIygG,YACCvgH,EAAKy/G,MAAkBz/G,EAAKy/G,IAAmBS,EAAW1hG,QAC/Cxe,EAAKy/G,IACPzjG,cAAcskG,IAAW,OAAOzrB,EAKlD,GAAIqrB,aAAsB,GAAQ,CAC9B,IAAIviG,EAAYmC,EAAInC,WAAa,EAC5B3d,EAAKw/G,MAAoBx/G,EAAKw/G,IAAqBU,EAAWvtF,uBAAuB,CAAEhV,UAAWA,KACvG+f,EAAU,CACN/f,UAAWA,EACX+U,oBAAqB1yB,EAAKw/G,IAElC,EAEwB,IAApB1/F,EAAI0gG,aAAsBH,EAAUr/F,UAAU,MAElDhB,EAAeqgG,EAAUzgG,UAAUsgG,EAAYxiF,IAGvC,GAAEhhC,QAAQsjB,KAAeA,EAAesgG,EAAS/kG,cAAcyE,KAC7C,IAAfF,EAAI2gG,SAGPzgG,EADAkgG,aAAsB,GACPA,EAAWt9F,oBAAoB09F,GACvCJ,aAAsB,GACdA,EAAWv9F,sCAAsC29F,GAEjDJ,EAAWrhG,aAAayhG,EAAU5iF,IAIzD,IAAIshC,EAAK,EAAiB,GAAEtuB,eAAe1wB,EAAcmgG,GAAgBtrB,EACrE6rB,EAAW5gG,EAAIhD,QAAU,EAG7B,OAFIgD,EAAI6wC,SAAQ+vD,GAAY,GAAOnsG,GAAQ,GAEpC+qG,GAAYtgD,EAAI/+C,EAAK5U,MAAOq1G,EACvC,EChMA,SAASC,GAAYvoE,GAEjB,OAAO,SAAS6kC,EAAM0C,EAAQ9iE,EAAKiD,GAE/B,IAAItC,IAAWsC,EAAItC,OACfgB,EAAO,EAAWy+D,EAAK6C,qBAAqBH,GAAU1C,EAAKwC,YAAYE,GACvEkV,EAASr2E,EAAK45B,KAEdz7B,EAAKmD,EAAInD,GACb,GAAIA,EAAI,CACJ,IAAIikG,EAAe,GAAkBjkG,GACrCA,EAAK5B,WAAW4B,GACZkkB,SAASlkB,KACLikG,IACAjkG,GAAM,IACNA,GAAM6B,EAAKvC,OAEf44E,EAAOj7E,GAAK+C,EAEpB,CAEA,IAAIC,EAAKkD,EAAIlD,GACb,GAAIA,EAAI,CACJ,IAAIikG,EAAe,GAAkBjkG,GACrCA,EAAK7B,WAAW6B,GACZikB,SAASjkB,KACLikG,IACAjkG,GAAM,IACNA,GAAM4B,EAAKtC,QAEf24E,EAAOp7E,GAAKmD,EAEpB,CAEA,OAAO,EAAWi4E,EAAOr3E,OAAOy/D,EAAK7zB,MAAMvmB,UAAUlhB,UAAWs7D,EAAK7zB,MAAM7wC,SAAWs8E,CAC1F,CACJ,CAsEO,MAAMlzE,GAASg/F,GAAY,UACrB,GAAMA,GAAY,aAClB,GAASA,GAAY,gBACrB,GAAOA,GAAY,cACnB,GAAQA,GAAY,eACpB76F,GAAU66F,GAAY,UACtB/5F,GAAW+5F,GAAY,YACvBx8F,GAAaw8F,GAAY,cACzBt8F,GAAcs8F,GAAY,UAC1BjvB,GAAgB4sB,IA7E7B,SAAwBrhC,EAAM0C,EAAQ6+B,EAAU1+F,GAE5C,IAAIvH,EAAQ0kE,EAAK7zB,MAAM7wC,QACnBiG,EAAOy+D,EAAKwC,YAAYE,GACxBkV,EAASr2E,EAAKmD,SACdmE,EAAUtH,EAAKtD,SACfmJ,EAAc7F,EAAKuG,SAEnBggD,EAAUjlD,EAAIilD,QAGlB,GAFKlkC,SAASkkC,KAAUA,EAAU,GAE7Bj/C,EAAQrM,EAAIsrD,GAAYy5C,EAAS/kG,GAAK+kG,EAAS/kG,GAAM4K,EAAY5K,EAAIsrD,EAAU,CAChF,IAAInoD,EAAM4hG,EAAS/kG,EAAIo7E,EAAOp7E,EAC9Bo7E,EAAOj7E,GAAgB,IAAVrB,GAAyB,MAAVA,EAAiB,EAAS,EAALqE,EAASpP,KAAKimC,IAAI76B,GAAML,IACzEs8E,EAAOp7E,GAAKmD,CAChB,MAAO,GAAKkJ,EAAQlM,EAAImrD,GAAYy5C,EAAS5kG,GAAK4kG,EAAS5kG,GAAMyK,EAAYzK,EAAImrD,EAAU,CACvF,IAAIpoD,EAAM6hG,EAAS5kG,EAAIi7E,EAAOj7E,EAC9Bi7E,EAAOp7E,GAAgB,KAAVlB,GAA0B,MAAVA,EAAiB,EAAIoE,EAAKnP,KAAKimC,IAAI76B,GAAML,IACtEs8E,EAAOj7E,GAAK+C,CAChB,CAEA,OAAOk4E,CACX,IAwDaisB,GAAUxC,IAtDvB,SAAkBrhC,EAAM0C,EAAQ6+B,EAAU1+F,GAEtC,IACItB,EAAMjG,EAAOoJ,EADbnE,IAAWsC,EAAItC,OAEfA,GACAgB,EAAOy+D,EAAK6C,qBAAqBH,GACjCh+D,EAASs7D,EAAK7zB,MAAMvmB,UAAUlhB,SAC9BpJ,EAAQ0kE,EAAK7zB,MAAM7wC,SAEnBiG,EAAOy+D,EAAKwC,YAAYE,GAG5B,IAMIkV,EANA9vB,EAAUjlD,EAAIilD,QAOlB,OANIlkC,SAASkkC,IAAUvmD,EAAKsD,QAAQijD,GAEhCvnD,GAAQghG,EAAShhG,OAAOmE,EAAQpJ,GAEzBiG,EAAK4I,mBAAmBo3F,IAG/B,IAAK,OACD3pB,EAASr2E,EAAKuH,aACd,MACJ,IAAK,QACD8uE,EAASr2E,EAAK6I,cACd,MACJ,IAAK,MACDwtE,EAASr2E,EAAKkJ,YACd,MACJ,IAAK,SACDmtE,EAASr2E,EAAK8F,eAItB,OAAO,EAAWuwE,EAAOr3E,OAAOmE,GAASpJ,GAASs8E,CACtD,IAoBaksB,GAhBb,SAAsB9jC,EAAMkhC,EAASC,EAAWt+F,EAAKolD,GACjD,OAAO+X,EAAK7zB,MAAMmO,0BAA0B9rD,KAAK29C,MAAO8b,GAASpoD,OAAOgD,EAAInD,GAAImD,EAAIlD,GACxF,EChGaokG,GAAYrH,GAAWruF,OAAO,CAEvCoa,MAAO,CACH,iBAAkB,QAGtBu7E,WAAY,KACZC,cAAe,KAEf,IAAAzoC,GACIkhC,GAAW5iH,UAAU0hF,KAAK7rE,MAAMnB,KAAMpB,WACtC,MAAQ+4B,SAAS,MAAE2rB,IAAWtjD,KAC9BA,KAAKw1G,WAAa,KAClBx1G,KAAKy1G,cAAgB,GACrBz1G,KAAKu7C,SAAS+H,EAAO,mBAAoBtjD,KAAK01G,WAClD,EAEA,OAAAC,CAAQC,GACJ51G,KAAKy1G,cAAgBz1G,KAAK61G,gBAAgBD,GAC1C51G,KAAK81G,YACT,EAEA,eAAAD,CAAgBD,GACZ,MAAMG,EAAe,GAOrB,OANIH,IACoB5kH,MAAMC,QAAQ2kH,GAAYA,EAAW,CAACA,GAAY,CAAC,IAC3Dj+G,SAAS6uC,IACjBuvE,EAAankH,QAAQoO,KAAKg2G,uBAAuBxvE,GAAM,IAGxDuvE,CACX,EAEA,UAAAE,GACI,MAAQT,WAAY9yB,GAAS1iF,KACxB0iF,IACLA,EAAK3rE,KAAKxS,SACVvE,KAAKw1G,WAAa,KACtB,EAEA,UAAAM,GAEI,MAAQn+E,SAAS,MAAE2rB,IAAWtjD,MACtBy1G,cAAeM,GAAiB/1G,KAIxC,GAFAA,KAAKi2G,aAEuB,IAAxBF,EAAavkH,OAAc,OAE/B,MAAMwb,EAAWs2C,EAAM3rB,QAAQu+E,cAAgB5yD,EAAM3rB,QAAQ3qB,SAC7D,GAAIA,GAAY,EACZ,OAGJ,MAAMmoD,EAAOn1D,KAAKm2G,eAElBJ,EAAap+G,SAAQ,CAACy+G,EAAkB1kH,KAEpC,MAAM4jC,EAAKt1B,KAAKq2G,cAAc3kH,GACxBimC,EAAUz2B,GAAM,CAAC,EAAGk1G,IACpB,YAAE3gG,EAAc,GAAMkiB,EAI5B,IAAI2+E,EAHJ3+E,EAAQnnB,MAAQxD,EAAWyI,GAAe,EAC1CkiB,EAAQlnB,OAASzD,EAAWyI,GAAe,EAGtC0/C,EAAKohD,MAAMjhF,GAIZghF,EAAWnhD,EAAKhqE,IAAImqC,IAHpBghF,EAAW,GAAE,UAAW,CAAEhhF,GAAIA,EAAIkhF,aAAc,kBAAoB,GAAE7+E,EAAQu5B,SAC9EiE,EAAKv6D,IAAI06B,EAAIghF,IAKb,GAAW3+E,EAAQ8zC,SACnB9zC,EAAQ8zC,OAAO6qC,EAASxtG,KAAK4qB,WAAYiE,EAAS2rB,GAEtDgzD,EAASphF,KAAK,CACV1kB,MAAOmnB,EAAQnnB,MACfC,OAAQknB,EAAQlnB,QAClB,IAGN0kD,EAAKp+C,KAAKqiB,SAASp5B,KAAKqI,IACxBrI,KAAK01G,YACT,EAEA,UAAAA,GAEI,MAAQF,WAAY9yB,EAAM+yB,cAAeM,EAAcp+E,SAAS,MAAE2rB,IAAWtjD,KAC7E,IAAK0iF,EAAM,OACX,MAAQ3rE,KAAM0/F,EAAI,SAAEC,GAAah0B,GAC3B,EAAEv0E,EAAC,EAAEH,EAAC,MAAEwC,EAAK,OAAEC,GAAW6yC,EAAMqzD,UACtCF,EAAKvhF,KAAK,CAAE/mB,IAAGH,IAAGwC,QAAOC,WACzB,IAAK,MAAMmmG,KAAaF,EACHA,EAASE,GACjB1hF,KAAK,CAAE/mB,GAAIA,EAAGH,GAAIA,IAE/B+nG,EAAap+G,SAAQ,CAACggC,EAASjmC,KAC3B,GAAI,GAAWimC,EAAQhlB,QAAS,CAC5B,MAAM2jG,EAAWI,EAAS12G,KAAKq2G,cAAc3kH,IAC7CimC,EAAQhlB,OAAO2jG,EAASxtG,KAAK4qB,WAAYiE,EAAS2rB,EACtD,IAER,EAEA,aAAA+yD,CAAc3kH,GACV,MAAO,WAAWsO,KAAK23B,QAAQ2rB,MAAMvF,OAAOrsD,GAChD,EAEA,YAAAykH,GACI,IAAMX,WAAY9yB,GAAS1iF,KAC3B,GAAI0iF,EAAM,OAAOA,EACjB,MAAMm0B,EAAU,GAAE,QACZC,EAAS,GAAE,MAAO,CAAEtmG,MAAO,OAAQC,OAAQ,QAAU,CAAComG,IAiB5D,OAhBAn0B,EAAO1iF,KAAKw1G,WAAa,CACrBz+F,KAAM+/F,EACNJ,SAAU,CAAC,EACX97G,IAAK,SAAS06B,EAAIyhF,GACd,MAAMC,EAAU,GAAE,OAAQ,CAAExmG,MAAO,OAAQC,OAAQ,OAAQypD,KAAM,QAAQ5kC,OACzEuhF,EAAQ/iF,OAAOijF,GACfD,EAAOhjF,OAAOkjF,GACdh3G,KAAK02G,SAASphF,GAAMyhF,CACxB,EACA5rH,IAAK,SAASmqC,GACV,OAAOt1B,KAAK02G,SAASphF,EACzB,EACAihF,MAAO,SAASjhF,GACZ,YAA6B7iC,IAAtBuN,KAAK02G,SAASphF,EACzB,GAEGotD,CACX,EAEA,sBAAAszB,CAAuB3hG,GAEnB,IAAI1J,EAAY3K,KAAK23B,QAAQ++E,SAC7B,GAAI91G,GAASyT,IAAQrjB,MAAMC,QAAQ0Z,EAAU0J,IACzC,OAAO1J,EAAU0J,GAAK1jB,KAAI,SAAS61C,GAC/B,OAAO,GAAO,CAAC,EAAGA,EACtB,IAGJ,IAAI7O,EAAUtjB,GAAO,CAAEpT,KAAM,CAAC,CAAC,IAC3BhQ,EAAUD,MAAMC,QAAQ0mC,GACxBxgC,EAAOwgC,EAAQxgC,KAMnB,GAJKlG,GAAYkG,GAASwgC,EAAQu5B,SAC9B/5D,EAAO,OAGPA,GAAQnG,MAAMC,QAAQ0Z,EAAUxT,IAAQ,CACxC,IAAIyM,EAAU+G,EAAUxT,GAAMxG,KAAI,SAAS61C,GACvC,OAAO,GAAO,CAAC,EAAGA,EACtB,IAEIvlC,EAAOjQ,MAAMC,QAAQ0mC,EAAQ12B,MAAQ02B,EAAQ12B,KAAO,CAAC02B,EAAQ12B,MAAQ,CAAC,GAE1EJ,GAASI,EAAK,GAAI,GAAKoT,EAAK,SAC5B,IAAK,IAAIvN,EAAI,EAAGA,EAAI7F,EAAKzP,OAAQsV,IACzBlD,EAAQkD,IACR,GAAOlD,EAAQkD,GAAI7F,EAAK6F,IAGhC,OAAOlD,CACX,CAEA,OAAO3S,EAAU0mC,EAAU,CAACA,EAChC,IChIEs/E,GAAe,CACjBC,KAAM,eACNC,OAAQ,sBACRC,MAAO,iBAMLC,GAAoBp0G,IACpBq0G,GAAe,iBAEf,GAAoB9kC,GAASyL,aAE7Bs5B,GAAsB,CACxB,CAAC,GAAkBplC,SAAU,CACzBh7E,KAAM,SACNwgC,QAAS,CACL2hC,QAAS,IAGjB,CAAC,GAAkBgZ,qBAAsB,CACrCn7E,KAAM,WACNwgC,QAAS,CACL6C,UAAW,qBAGnB,CAAC,GAAkB+3C,sBAAuB,CACtCp7E,KAAM,WACNwgC,QAAS,CACL6C,UAAW,oBAKjBg9E,GAAgB,CAAC,CACnBrgH,KAAM02G,GAAYC,MACnB,CACC32G,KAAM02G,GAAYG,MACnB,CACC72G,KAAM02G,GAAYE,OACnB,CACC52G,KAAM02G,GAAY9P,QACnB,CACC5mG,KAAM02G,GAAYI,OACnB,CACC92G,KAAM02G,GAAY7vB,QAGTy5B,GAAQprC,GAAKxsD,OAAO,CAE7B2a,UAAW,QAEX7C,QAAS,CAELnnB,MAAO,IACPC,OAAQ,IACRzD,SAAU,EAGV4oG,UAAU,EAEVM,aAAc,KAId53C,YAAY,EAEZozC,YAAa7yB,GACb9I,SAAUmoB,GACV+L,YAAY,EACZC,WAAW,EACXE,eAAe,EAMfjK,aAAa,EAGbv1B,YAAY,EAGZlvE,MAAO,SAASkK,EAAK4rE,GAGjB,OAAO,CACX,EAEAkmC,aAAcH,GAGdI,oBAAoB,EAGpBC,2BAA2B,EAG3BC,0BAA0B,EAa1BC,mBAAmB,EAKnB5K,eAAe,EAOf6K,YAAa,WAET,MAAM,cAAE5zC,GAAkBnkE,KAAK29C,MAAMxyD,IAAI,SACnC6sH,EAAOvlE,GAAU0xB,EAAe,CAAC,WAAY,SACnD,IAAK6zC,EAAM,MAAM,IAAIhvG,MAAM,sGAC3B,OAAO,IAAIgvG,CACf,EAIAhf,iBAAkB,CAAE7hG,KAAM,UAI1BowG,cAAe,CAAEpwG,KAAM,UAEvBitG,cAAe,CAAEjtG,KAAM,UAEvBgtG,kBAAmB,CAAEhtG,KAAM,mBAE3BwsG,uBAAwB,CAAExsG,KAAM,YAIhCw+E,mBAAoB,KAGpB8M,eAAgB,SAASvR,EAAWgD,EAAQ+jC,GACxC,MAAyC,YAAlC/jC,EAAOv4C,aAAa,SAC/B,EAIA6wE,mBAAoB,SAAS0L,EAAWC,EAAUC,EAAWC,EAAUx4G,EAAKy4G,GACxE,OAAgB,WAARz4G,EAAmBu4G,EAAYF,aAAsBr5B,EACjE,EAMAgE,eAAe,EAGfrC,kBAAmB,SAAS+3B,EAAWC,GAEnC,OAAO,CACX,EAGAv3B,oBAAqB,SAASs3B,GAE1B,OAAO,CACX,EAIAj4B,aAAc,OAKdC,iBAAiB,EAGjB3M,YAAa,CACT6kC,WAAW,GAKfxtC,aAAa,EAKbytC,UAAW,KAGX51B,eAAgB,EAGhB61B,cAAe,EAIftiC,gBAAiB,EAIjBuiC,QAAS3B,GAAaE,OAEtB0B,QAAQ,EAERC,YAAY,EAGZC,aAAc,SAASvnC,EAAM3lB,EAAMu3C,EAAU/uF,EAAKivC,GAMzCuI,GAAQ2lB,EAAK5E,YAAc4E,EAAK3E,cAAiBx4D,EAAI2kG,UAAY3kG,EAAI4kG,SAC1E31D,EAAM41D,4BAA4B1nC,EAAM4xB,EAAU/uF,EACtD,EAGA8kG,gBAAiB,SAAS3nC,EAAM3lB,EAAMvI,GAClC,OAAOA,EAAM81D,yBAAyB5nC,EAAM3lB,EAChD,EAEAwtD,aAAc,KAEdC,YAAa,KAEbC,SAAU,KAIVC,kBAAmB,KAEnBlS,gBAAiB,KAEjBG,mBAAoB,KAEpBgS,qBAAsB,EAEtBC,gBAAiB,EAEjBC,oBAAqB,EAErBlV,yBAA0B,EAE1BmV,UAAU,GAGdrwG,OAAQ,CACJ,SAAY,kBACZ,OAAU,kBACV,YAAe,cACf,UAAa,cACb,WAAc,cACd,UAAa,YACb,SAAY,WACZ,WAAc,aACd,WAAc,aACd,MAAS,aACT,yBAA0B,aAC1B,yBAA0B,aAC1B,0BAA2B,aAC3B,0BAA2B,aAC3B,gCAAiC,wBACjC,mCAAoC,oBACpC,+BAAgC,UAChC,gCAAiC,UACjC,8BAA+B,oBAGnCswG,eAAgB,CACZ,UAAa,cACb,UAAa,cACb,QAAW,YACX,SAAY,YACZ,YAAe,aAOnBj4E,WAAmB,0GAMnBjP,IAAK,KACL4mF,SAAU,KACVlgF,KAAM,KACNygF,MAAO,KACPC,OAAQ,KAGRC,gBAAiB,KAGjBC,yBAA0B,KAE1BC,SAAU,KAEVC,QAAS,KAETC,sBAAuB,CAAC,MAAO,WAAY,WAC3CC,wBAAyB,CAAC,aAG1BC,uBAAwB,CAAC,WAAY,QAAS,SAAU,SAAU,UAGlEC,kBAAmB,CAOf,UAEJC,UAAW,KAKXC,oBAAqB,IAErBztC,KAAM,WAEF,MAAM,QAAEr1C,GAAY33B,KACf23B,EAAQ6hF,oBAET7hF,EAAQ6hF,kBAAqC,oBAAVltD,OAAyB,GAAIA,MAAO,UAAYA,MAAMC,OAAS,MAItG,MAAM5O,EAAQ39C,KAAK29C,MAAQhmB,EAAQgmB,OAAS,IAAI2mB,GAGhDtkE,KAAKm6G,QAAU,CAAC,EAEhBn6G,KAAK06G,eACL16G,KAAKyrE,SACLzrE,KAAK26G,iBACL36G,KAAKqzE,iBAGLrzE,KAAKqxE,OAAS,CAAC,EAGfrxE,KAAK46G,eAAiB,CAClBzxG,MAAO,KACP0xG,OAAQ,IAIZ76G,KAAK86G,WAAWn9D,EAAMjiB,WAAW2iB,MAAMkjB,SAElCvhE,KAAK+6G,YAAc/6G,KAAKm9E,WAAWn9E,KAAKg7G,kBACjD,EAEAC,cAAe,WAGX,OAFIj7G,KAAKk6G,UAAYl6G,KAAKk6G,SAAS5kF,IAAI2e,GAAYj0C,KAAKk6G,SAAS5kF,IAE1Dt1B,KAAKk6G,SAAW,CACnB5kF,GAAI,KACJ4lF,WAAY,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,GACtBC,cAAe,GACfC,YAAa,GACbC,UAAW,CAAC,EACZC,QAAS,CAAC,EACVz/D,MAAO,EACP0/D,WAAW,EACXC,UAAW,KACXj+G,MAAM,EACN0O,UAAU,EACVwvG,MAAM,EAEd,EAEApoC,eAAgB,WACZ,IAAI11B,EAAQ39C,KAAK29C,MACjB39C,KAAKu7C,SAASoC,EAAO,MAAO39C,KAAK07G,aAC5BngE,SAASoC,EAAO,SAAU39C,KAAK27G,eAC/BpgE,SAASoC,EAAO,SAAU39C,KAAK47G,cAC/BrgE,SAASoC,EAAO,QAAS39C,KAAK67G,cAC9BtgE,SAASoC,EAAO,OAAQ39C,KAAK87G,aAC7BvgE,SAASoC,EAAO,aAAc39C,KAAK+7G,kBACxC/7G,KAAKwJ,GAAG,iBAAkBxJ,KAAKg8G,iBAC1BxyG,GAAG,mBAAoBxJ,KAAKi8G,mBAC5BzyG,GAAG,YAAaxJ,KAAK2S,OAC9B,EAEA+oG,YAAa,SAASn9D,EAAMuB,EAAGzrC,GAC3B,IAAIupB,EAAWvpB,EAAIupB,SACf59B,KAAKm9E,YAAcx8E,GAASi9B,GAC5B59B,KAAKk8G,WAAW39D,EAAMlqC,IAElBA,EAAI0xD,cAAgBnoC,GAAU59B,KAAKm8G,OAAO,CAAErxH,IAAK,aACrDkV,KAAKk8G,WAAW39D,EAAMlqC,GACL,IAAbupB,GAAgB59B,KAAKo8G,SAAS,CAAEtxH,IAAK,aAEjD,EAEA6wH,cAAe,SAASp9D,EAAMuB,EAAGzrC,GAC7B,MAAMm9D,EAAOxxE,KAAK0rD,gBAAgBnN,GAC9BizB,GAAMxxE,KAAK4vE,kBAAkB4B,EAAMA,EAAK3E,YAAa2E,EAAK7E,gBAAiBt4D,EACnF,EAEAunG,aAAc,SAASr9D,EAAMlqC,GACzB,GAAIkqC,IAASv+C,KAAK29C,MAAMjiB,WAAW2iB,OAC/BE,EAAKgB,WAAW,MAAQv/C,KAAK23B,QAAQihF,UAAY3B,GAAaE,OAAQ,CACtE,MAAM3lC,EAAOxxE,KAAK0rD,gBAAgBnN,GAC9BizB,GAAMxxE,KAAK4vE,kBAAkB4B,EAAMA,EAAK5E,YAAa4E,EAAK7E,gBAAiBt4D,EACnF,CACJ,EAEAwnG,aAAc,SAASr/G,EAAY6X,GAC/BrU,KAAKq8G,cACLr8G,KAAK86G,WAAWt+G,EAAW+kE,OAAQltD,EACvC,EAEAynG,YAAa,WACL97G,KAAK29C,MAAM8sB,eAAezqE,KAAKo6G,wBACnCp6G,KAAKs8G,WACT,EAEAP,iBAAkB,SAASxnH,GACvB,IAAIyL,KAAK+6G,WAAT,CACA,IAAI5jH,EAAO5C,GAAQA,EAAKu0D,UACpB7B,EAAQjnD,KAAK29C,MACjB,IAAK39C,KAAKm9E,UAAW,CACjB,IAAIo/B,EAAwBv8G,KAAKq6G,wBAC7BkC,EAAsBvjH,SAAS7B,KAAU8vD,EAAMwjB,eAAe8xC,IAC9Dv8G,KAAKw8G,YAAYjoH,EAEzB,CACA,IAAIkoH,EAAsBz8G,KAAKo6G,sBAC3BqC,EAAoBzjH,SAAS7B,KAAU8vD,EAAMwjB,eAAegyC,IAC5Dz8G,KAAKs8G,WAXkB,CAa/B,EAEA5B,aAAc,WAEV,MAAM,QAAE/iF,GAAY33B,MACd,iBACFg5F,EAAgB,cAChBuO,EAAa,uBACb5D,EAAsB,cACtBS,EAAa,kBACbD,EAAiB,aACjBuT,EAAY,kBACZ8B,EAAiB,YACjB5lC,GACAj8C,GAIC6hF,GAAsC,oBAAVltD,OAAyB,GAAIA,MAAO,YACjE30B,EAAQ6hF,kBAAoBltD,MAAMC,QAMjC,GAAWysC,KACZrhE,EAAQqhE,iBAAmB32F,GAAU22F,IAEpC,GAAWuO,KACZ5vE,EAAQ4vE,cAAgBllG,GAAUklG,IAEjC,GAAW5D,KACZhsE,EAAQgsE,uBAAyBthG,GAAUshG,IAE1C,GAAWS,KACZzsE,EAAQysE,cAAgB/hG,GAAU+hG,IAEjC,GAAWD,KACZxsE,EAAQwsE,kBAAoB9hG,GAAU8hG,IAEtC/nG,GAAcw3E,KACdj8C,EAAQi8C,YAAc,GAAO,CAAC,EAAGA,IAEjCx3E,GAAcs7G,KAEd//E,EAAQ+/E,aAAe12G,GAAa,CAAC,EAAG02G,EAAcH,IAE9D,EAEApkF,SAAU,WACN,IAAI7oB,EAAK,GAAEK,UACX,MAAO,CAAC,CACJonC,aAAcznC,EAAGyoB,MACjB+I,QAAS,MACTtB,UAAW0W,GAAmB,oBAC9B3qC,SAAU,aACV0zB,MAAO,CACH2D,SAAU,WACV8+E,MAAO,IAEZ,CACC3qE,aAAcznC,EAAGqoB,IACjBmJ,QAAS,MACTJ,WAAY,CACR,MAAS,OACT,OAAU,OACV,cAAepxB,EAAGwoB,OAEtBvsB,SAAU,MACV0zB,MAAO,CACH2D,SAAU,WACV8+E,MAAO,GAEXvpF,SAAU,CAAC,CAGP2I,QAAS,OACTv1B,SAAU,QACX,CACCu1B,QAAS,IACTtB,UAAW0W,GAAmB,UAC9B3qC,SAAU,YAGtB,EAEA,YAAAo2G,CAAatsC,GACT,OAASA,KAAarwE,KAAKm6G,OAC/B,EAEA,YAAA5pC,CAAaF,GACT,MAAM,QAAE8pC,GAAYn6G,KACpB,GAAIqwE,KAAa8pC,EAAS,OAAOA,EAAQ9pC,GACzC,MAAM,IAAIrnE,MAAM,6BAA6BqnE,KACjD,EAEA,YAAAusC,CAAavsC,GACT,OAAOrwE,KAAKuwE,aAAaF,GAAWhoE,EACxC,EAEAojE,OAAQ,WAEJzrE,KAAKotE,iBACL,MAAM,GAAE/kE,EAAE,WAAEN,EAAU,QAAE4vB,EAAO,WAAEiK,GAAe5hC,MAC1C,IAAE2yB,EAAG,KAAE0G,EAAI,OAAE0gF,GAAWhyG,EAuB9B,OArBAM,EAAG4xB,MAAM2D,SAAW,WACpBjL,EAAIsH,MAAM2/E,SAAWjiF,EAAQiiF,SAAW,UAAY,SAEpD55G,KAAK2yB,IAAMA,EACX3yB,KAAKq5B,KAAOA,EACZr5B,KAAK+5G,OAASA,EAEd/5G,KAAK68G,eAEL,GAAEjpF,SAASjB,GAEX3yB,KAAK88G,cAAcl7E,GAEfjK,EAAQ2mC,YACRt+D,KAAK+8G,eAAeplF,EAAQ2mC,YAG5B3mC,EAAQi+E,UACR51G,KAAK21G,QAAQh+E,EAAQi+E,UAGlB51G,IACX,EAEA88G,cAAe,SAAStwE,GACfA,GACL,GAAExsC,KAAK2yB,KAAKuJ,QAAQ,GAAEyF,eAAe6K,GACzC,EAEA,WAAAwwE,CAAY7lH,GACR,OAAQA,IACC02G,GAAYC,KACN,IAAIyH,GAAU,CAAEp+G,OAAMmsD,MAAOtjD,KAAM02G,SAAU12G,KAAK1N,YAAY2qH,eAE9D,IAAI/O,GAAW,CAAE/2G,QAEpC,EAEA0lH,aAAc,SAAS9C,EAASvC,IAC5Bx3G,KAAKk9G,eAELnD,EAAOpiH,SAAQ,EAAGR,OAAMgmH,aACpB,MAAMC,EAAYp9G,KAAKg9G,YAAY7lH,GACnC6I,KAAK+5G,OAAOtyG,YAAY21G,EAAU/0G,IAClCrI,KAAKm6G,QAAQhjH,GAAQimH,CAAS,IAGlC,MAAMC,EAAiBr9G,KAAKuwE,aAAas9B,GAAYE,OAC/CuP,EAAiBt9G,KAAKuwE,aAAas9B,GAAY7vB,OAC/Cu/B,EAAkBv9G,KAAKuwE,aAAas9B,GAAY9P,QAEtD/9F,KAAK85G,MAAQwD,EAAej1G,GAC5BrI,KAAKq+C,MAAQr+C,KAAKu5G,SAAW8D,EAAeh1G,GAE5Cg1G,EAAepkF,IAAIhE,SAASic,GAAmB,aAC/CqsE,EAAgBtkF,IAAIhE,SAASic,GAAmB,aAChDmsE,EAAeh1G,GAAG4xB,MAAMujF,iBAAmB,OAC3CH,EAAeh1G,GAAG4xB,MAAMwjF,WAAa,OACrCF,EAAgBl1G,GAAG4xB,MAAMujF,iBAAmB,OAC5CD,EAAgBl1G,GAAG4xB,MAAMwjF,WAAa,MAC1C,EAEAP,aAAc,WACV,MAAM,QAAE/C,GAAYn6G,KACpBhV,OAAO0F,KAAKypH,GAASxiH,SAAQR,IACzBgjH,EAAQhjH,GAAMoN,gBACP41G,EAAQhjH,EAAK,GAE5B,EAEAklH,YAAa,WACT,MAAM,QAAElC,GAAYn6G,KACpBhV,OAAO0F,KAAKypH,GAASxiH,SAAQR,IACzBgjH,EAAQhjH,GAAMw3G,cAAc,GAEpC,EAEAh8F,OAAQ,WAMJ,OAJI3S,KAAK09G,aACL19G,KAAK29G,sBAAsB39G,KAAK09G,aAG7B19G,IACX,EAEAuM,MAAO,SAAS6F,EAAIC,EAAI9d,GACpB,MAAM6pC,EAAMp+B,KAAKi2B,SAEjB,YAAWxjC,IAAP2f,EACO,GAAE+xB,cAAc/F,SAGhB3rC,IAAP4f,IACAA,EAAKD,GAETA,EAAKrQ,KAAKwL,IAAI6E,GAAM,EAAGpS,KAAKw6G,WAC5BnoG,EAAKtQ,KAAKwL,IAAI8E,GAAM,EAAGrS,KAAKw6G,WAC5Bp8E,EAAIziC,EAAIyW,EACRgsB,EAAItnB,EAAIzE,EACRrS,KAAKi2B,OAAOmI,EAAK7pC,GACVyL,KACX,EAEA49G,oBAAqB,SAASrxG,EAAOyE,EAAOzc,GACxC,MAAQoH,EAAGyW,EAAI0E,EAAGzE,EAAInI,EAAG2L,EAAI1D,EAAG2D,GAAO9V,KAAKi2B,SAE5C,IADA1pB,EAAQxK,KAAKwL,IAAIhB,GAAS,EAAGvM,KAAKw6G,cACpBpoG,GAAM7F,IAAU8F,EAE1B,OAAOrS,KAEX,MAAMi2B,EAAS,GAAEF,kBACZljB,UACGgD,EAAK7E,EAAM7C,GAAK5B,EAAQ6F,GACxB0D,EAAK9E,EAAMhD,GAAKzB,EAAQ8F,IAE3B9F,MAAMA,EAAOA,GAElB,OADAvM,KAAKi2B,OAAOA,EAAQ1hC,GACbyL,IACX,EAEA6S,UAAW,SAASgD,EAAIC,EAAIvhB,GACxB,MAAM6pC,EAAMp+B,KAAKi2B,SAEjB,YAAWxjC,IAAPojB,EACO,GAAEwuB,kBAAkBjG,IAG/BvoB,IAAOA,EAAK,GACZC,IAAOA,EAAK,GACRsoB,EAAIl0B,IAAM2L,GAAMuoB,EAAIjsB,IAAM2D,IAC9BsoB,EAAIl0B,EAAI2L,EACRuoB,EAAIjsB,EAAI2D,EACR9V,KAAKi2B,OAAOmI,EAAK7pC,IAHwByL,KAK7C,EAEAi2B,OAAQ,SAASmI,EAAK7pC,EAAO,CAAC,GAE1B,IAAIglH,EAAWv5G,KAAK+5G,OAGpB,QAAYtnH,IAAR2rC,EAAmB,CAEnB,IAAIy/E,EAAkBtE,EAAS59E,aAAa,aAe5C,OAbK37B,KAAKi6G,0BAA4B,QAAU4D,EAG5Cz/E,EAAMp+B,KAAKg6G,iBAGX57E,EAAMm7E,EAASuE,SACf99G,KAAKg6G,gBAAkB57E,EACvBp+B,KAAKi6G,yBAA2B4D,GAK7B,GAAE9nF,gBAAgBqI,EAC7B,CAGA,MAAMqI,EAAOzmC,KAAKi2B,SACZmpB,EAAU,GAAErpB,gBAAgBqI,GAC5B2/E,EAAyB/9G,KAAKi6G,yBAC9B+D,EAAY,GAAE3nF,wBAAwB+oB,GAC5C,GAAI4+D,IAAcD,EAGd,OAAO/9G,KAEX,IAAK+9G,GAA0B,GAAE1nF,4BAA8B2nF,EAG3D,OAAOh+G,KAGX,MAAM,EAAErE,EAAC,EAAEmb,EAAC,EAAE5M,EAAC,EAAEiI,GAAMitC,EAiBvB,OAfAm6D,EAASh/E,aAAa,YAAayjF,GACnCh+G,KAAKg6G,gBAAkB56D,EACvBp/C,KAAKi6G,yBAA2BV,EAAS59E,aAAa,aAGlDhgC,IAAM8qC,EAAK9qC,GAAKmb,IAAM2vB,EAAK3vB,GAC3B9W,KAAK28C,QAAQ,QAAShhD,EAAGmb,EAAGviB,GAI5B2V,IAAMu8B,EAAKv8B,GAAKiI,IAAMs0B,EAAKt0B,GAC3BnS,KAAK28C,QAAQ,YAAazyC,EAAGiI,EAAG5d,GAGpCyL,KAAK28C,QAAQ,YAAayC,EAAS7qD,GAC5ByL,IACX,EAEAi+G,aAAc,WAEV,OAAO,GAAEloF,gBAAgB/1B,KAAKq+C,MAAM1oB,eACxC,EAEAujF,4BAA6B,SAAS1nC,EAAM4xB,EAAU/uF,GAClD,GAAIm9D,aAAgBgB,GAGhB,IAFA,IAAI70B,EAAQ6zB,EAAK7zB,MACbipB,EAAQ5mE,KAAK29C,MAAMuJ,kBAAkBvJ,GAChC52C,EAAI,EAAGiJ,EAAI42D,EAAMp1E,OAAQuV,EAAIiJ,EAAGjJ,IAAK,CAC1C,IAAIqgD,EAAOwf,EAAM7/D,GACbgvE,EAAW/1E,KAAK0rD,gBAAgBtE,GACpC,GAAK2uB,EAAL,CACA,IAAImoC,EAAa,CAAC,UACd92D,EAAK4U,kBAAoBre,GAAOugE,EAAWtsH,KAAK,UAChDw1D,EAAKyU,kBAAoBle,GAAOugE,EAAWtsH,KAAK,UACpD,IAAIusH,EAAep8G,KAAKwL,IAAI61F,EAAW,EAAGrtB,EAASpJ,iBACnD3sE,KAAKo+G,mBAAmBroC,EAAUA,EAAS7C,QAAQgrC,GAAaC,EAAc9pG,EALvD,CAM3B,CAER,EAEA+kG,yBAA0B,SAAS5nC,EAAM3lB,GACrC,KAAK2lB,GAAUA,aAAgBgB,IAAW,OAAO,EACjD,IAAI70B,EAAQ6zB,EAAK7zB,MACjB,GAAIA,EAAMgO,YAAa,OAAO,EAC9B,KAAKE,EAAO2lB,EAAK0B,QAAQ,CAAC,SAAU,YAAmB,CACnD,IAAImrC,EAAc,CAAEt/D,QAAQ,GAGxBu/D,EAAa,EACblhC,EAAap9E,KAAK0rD,gBAAgB/N,EAAMke,iBACxCuhB,IAAep9E,KAAK0+F,cAActhB,KAClCkhC,EAAat+G,KAAKq9E,SAASD,EAAYihC,GACvC7sC,EAAK6zB,gBAAgB,WAEzB,IAAIkZ,EAAa,EACbhhC,EAAav9E,KAAK0rD,gBAAgB/N,EAAMqe,iBAK5C,GAJIuhB,IAAev9E,KAAK0+F,cAAcnhB,KAClCghC,EAAav+G,KAAKq9E,SAASE,EAAY8gC,GACvC7sC,EAAK6zB,gBAAgB,WAEN,IAAfiZ,GAAmC,IAAfC,EAEpB,OAAQv+G,KAAKq9E,SAAS7L,EAAM6sC,EAEpC,CACA,OAAO,CACX,EAEAzuC,kBAAmB,SAAS4B,EAAM3lB,EAAMu3C,EAAU/uF,GAC9CA,IAAQA,EAAM,CAAC,GACfrU,KAAKo+G,mBAAmB5sC,EAAM3lB,EAAMu3C,EAAU/uF,GAC9C,IAAI8oE,EAAUn9E,KAAKm9E,UACnB,KAAIn9E,KAAK+6G,YAAe59B,IAAyB,IAAd9oE,EAAIqtB,OACnC1hC,KAAK29C,MAAM8sB,eAAezqE,KAAKq6G,0BAAnC,CACA,IAAImE,EAAQx+G,KAAKw8G,YAAYnoG,GACzB8oE,GAASn9E,KAAKy+G,kBAAkBD,EAAOnqG,EAFwB,CAGvE,EAEA+pG,mBAAoB,SAAS5sC,EAAMr/E,EAAMixG,EAAU/uF,GAC/C,MAAQ6lG,SAAUwE,EAAO,QAAE/mF,GAAY33B,KACnC0+G,EAAQjD,MACJ9jF,EAAQmhF,aACR4F,EAAQjD,MAAO,EACfz7G,KAAKo8G,YAGb,MAAM,YAAEvvC,EAAW,YAAED,EAAW,gBAAED,EAAe,IAAE5uB,GAAQyzB,EAC3D,IAAImtC,EAAkBD,EAAQxD,WAAW9X,GAGzC,GAFKub,IAAiBA,EAAkBD,EAAQxD,WAAW9X,GAAY,CAAC,GAEpEA,EAAWz2B,EAMX,IAAK,IAAI7lE,EAAIs8F,EAAW,EAAGt8F,GAAK6lE,EAAiB7lE,IAAK,CAClD,MAAM83G,EAAsBF,EAAQxD,WAAWp0G,GAC1C83G,GAAyB7gE,KAAO6gE,IACrCD,EAAgB5gE,IAAQ6gE,EAAoB7gE,UACrC6gE,EAAoB7gE,GAC/B,CAEJ,IAAI8gE,EAAcF,EAAgB5gE,IAAQ,EAE1C,IAAK8gE,EAAc1sH,KAAUA,EAAM,OAC9B0sH,GAAaH,EAAQ7iE,QACtB1pD,EAAO06E,GAAegyC,EAAcjyC,EAEpC+xC,EAAgB5gE,IAAQ6uB,EACjBz6E,EAAOy6E,GAAeiyC,EAAchyC,IAE3C8xC,EAAgB5gE,IAAQ8uB,GAE5B8xC,EAAgB5gE,IAAQ5rD,EACxB,MAAM2sH,EAAennF,EAAQohF,aACD,mBAAjB+F,GAA6BA,EAAatzH,KAAKwU,KAAMwxE,EAAMr/E,EAAMixG,EAAU/uF,GAAO,CAAC,EAAGrU,KACrG,EAEA++G,eAAgB,SAASvtC,GACrB,IAAKA,EAAM,OAAO,EAClB,IAAIktC,EAAU1+G,KAAKk6G,SACfn8D,EAAMyzB,EAAKzzB,IACX4gE,EAAkBD,EAAQxD,WAAW1pC,EAAK7E,iBAC1C9gB,EAAO7rD,KAAKg/G,oBAAoBxtC,GAAQmtC,EAAgB5gE,GAE5D,cADO4gE,EAAgB5gE,GAChB8N,CACX,EAEAwxB,SAAU,SAAS7L,EAAMn9D,EAAM,CAAC,GAC5B,MAAMw3C,EAAO7rD,KAAK++G,eAAevtC,GACjC,IAAK3lB,EAAM,OAAO,EAClB,MAAMozD,GAAgB5qG,EAAI0qC,OACtBkgE,GAAcj/G,KAAKk/G,mBAAmB7qG,GAC1C,MAAM8qG,EAAWn/G,KAAKo/G,WAAW5tC,EAAM3lB,EAAMx3C,GAC7C,GAAI4qG,EAAc,CACd,MAAMT,EAAQ,CAAEa,QAAS,EAAGjc,SAAU5xB,EAAK7E,iBAC3C3sE,KAAKy+G,kBAAkBD,EAAOnqG,EAClC,CACA,OAAO8qG,CACX,EAEAC,WAAY,SAAS5tC,EAAM3lB,EAAMx3C,GAC7B,IAAKm9D,EAAM,OAAO,EAClB,MAAM,YAAE3E,EAAW,YAAED,EAAW,UAAEE,EAAS,MAAEnvB,GAAU6zB,EACvD,GAAIA,aAAgBgB,GAAU,CAC1B,GAAI3mB,EAAOghB,EAEP,OADA7sE,KAAKs/G,WAAW3hE,GACT,EAEX,GAAIkO,EAAO+gB,EAAa,CACpB,MAAM2yC,KAAqB1zD,EAAOihB,GAC9ByyC,IACA1zD,GAAQihB,GAEZ9sE,KAAKw/G,WAAWhuC,EAAM+tC,GACtB1zD,GAAQ+gB,CACZ,CACJ,CACA,OAAK/gB,EACE2lB,EAAKzD,cAAcliB,EAAMx3C,GAAO,CAAC,GADtB,CAEtB,EAEAorG,YAAa,SAAS9hE,EAAOtpC,GACzB,IAAIm9D,EAAOxxE,KAAK0rD,gBAAgB/N,GAChC,OAAK6zB,GACLxxE,KAAKq9E,SAAS7L,EAAMn9D,GACbm9D,GAFW,IAGtB,EAEAkuC,sBAAuB,SAASluC,GAC5B,IAAIzzB,EAAMyzB,EAAKzzB,IACX2gE,EAAU1+G,KAAKk6G,SACnB,GAAIn8D,KAAO2gE,EAAQrD,UAAW,OAAO,EACrC,IAAIxvD,EAAO6yD,EAAQrD,UAAUt9D,IAAQyzB,EAAK5E,YAG1C,OAFA8xC,EAAQvD,cAAcvpH,KAAKmsD,UACpB2gE,EAAQpD,QAAQv9D,GAChB8N,CACX,EAEAmzD,oBAAqB,SAASxtC,GAC1B,IAAIzzB,EAAMyzB,EAAKzzB,IACX2gE,EAAU1+G,KAAKk6G,SACnB,GAAIn8D,KAAO2gE,EAAQpD,QAAS,OAAO,EACnCoD,EAAQpD,QAAQv9D,IAAO,EACvB2gE,EAAQtD,YAAYxpH,KAAKmsD,GACzB,IAAI8N,EAAO6yD,EAAQrD,UAAUt9D,IAAQ,EAErC,cADO2gE,EAAQrD,UAAUt9D,GAClB8N,CACX,EAEA6yC,cAAe,SAASltB,GACpB,QAAKA,GACKA,EAAKzzB,OACD/9C,KAAKk6G,SACIoB,OAC3B,EAEAqE,UAAW,SAAStrG,GAChB,IAAIurG,EAAa/+G,GAAS,CAAC,EAAGwT,EAAK,CAAEklG,SAAU,OAC/Cv5G,KAAK6/G,cAAcD,GACnB5/G,KAAKw8G,YAAYoD,EACrB,EAGApD,YAAa,SAASnoG,GAElB,IAAIyrG,EADJ9/G,KAAKk/G,mBAAmB7qG,GAExB,IAAI0rG,EAAc,EACdC,EAAa,EACb5c,EAAWkU,GACf,GACI0I,IACAF,EAAa9/G,KAAKigH,iBAAiB5rG,GACnC0rG,GAAeD,EAAWT,QAC1Bjc,EAAWrhG,KAAKE,IAAI69G,EAAW1c,SAAUA,UACnC0c,EAAWhnF,OACrB,MAAM0lF,EAAQ,CAAEa,QAASU,EAAar1C,QAASs1C,EAAY5c,YAE3D,OADApjG,KAAKy+G,kBAAkBD,EAAOnqG,GACvBmqG,CACX,EAEA0B,oBAAqB,WACjB,MAAMhF,EAAal7G,KAAKk6G,SAASgB,WAC3BiF,EAAkBn1H,OAAO0F,KAAKwqH,GACpC,IAAIp0G,EAAIq5G,EAAgB3uH,OACxB,KAAOsV,EAAI,GAAKA,KAEZ,IAAK,IAAIs5G,KAAQlF,EAAWiF,EAAgBr5G,IAAK,OAAO,EAE5D,OAAO,CACX,EAEAk0G,iBAAkB,SAAS3mG,EAAK9f,GAC5B8f,IAAQA,EAAM,CAAC,GACf9f,IAASA,EAAO,CAAE8rH,UAAW,EAAGjd,SAAUkU,KAC1C,MAAQ4C,SAAUwE,EAAO,QAAE/mF,GAAY33B,KACjCs1B,EAAKopF,EAAQppF,GACnB,GAAIA,EAAI,CACJ2e,GAAY3e,GACW,IAAnB/gC,EAAK8rH,WAAmBrgH,KAAKkgH,uBAC7BlgH,KAAKk/G,mBAAmB7qG,GAE5B,MAAMmqG,EAAQx+G,KAAKigH,iBAAiB5rG,GAC9BurG,EAAa/+G,GAAS,CAAC,EAAGwT,EAAK,CACjCisG,eAj9BS,IAi9B0B9B,EAAMlD,QACzCiF,iBAl9BS,IAk9B4B/B,EAAMnD,YAEzCmF,EAAaxgH,KAAK6/G,cAAcD,GAChCa,EAAeD,EAAWnF,UAC1BqF,EAAaF,EAAWlF,QAC9B,IAAI+E,EAAY9rH,EAAK8rH,UACrB,MAAMM,EAAQjC,EAAQ7iE,MAClB2iE,EAAMa,QAAU,GAEhBgB,GAAa7B,EAAMa,QAAUb,EAAMnD,UACnCmD,EAAM6B,UAAYA,EAClB9rH,EAAK6uG,SAAWrhG,KAAKE,IAAIu8G,EAAMpb,SAAU7uG,EAAK6uG,UAC1Cob,EAAM1lF,OAAwB,IAAf4nF,GACflC,EAAMnD,WAAaoF,EACnBjC,EAAMlD,SAAWoF,EACjBlC,EAAMpb,SAAW7uG,EAAK6uG,SACtBpjG,KAAKy+G,kBAAkBD,EAAOnqG,GAC9B9f,EAAK8rH,UAAY,EACjB9rH,EAAK6uG,SAAWkU,GAChBoH,EAAQ7iE,MAAQ,GAEhBtnD,EAAK8rH,UAAYA,GAGhB3B,EAAQjD,MACL9jF,EAAQmhF,aACR94G,KAAKm8G,SACLuC,EAAQjD,MAAO,EACfz7G,KAAK28C,QAAQ,cAAetoC,IAKxC,MAAMusG,EAAavsG,EAAI02C,SAKvB,GAJI41D,GAA+B,mBAAfC,GAChBA,EAAWp1H,KAAKwU,KAAMw+G,EAAM1lF,MAAOunF,EAAWM,EAAOnC,EAAOx+G,MAG5D0+G,EAAQppF,KAAOA,EAAI,MAC3B,CACA,GAAIopF,EAAQzyG,SACR,MAAM,IAAIjD,MAAM,8DAEpB01G,EAAQppF,GAAK+d,GAAUrzC,KAAKg7G,iBAAkBh7G,KAAMqU,EAAK9f,EAC7D,EAEA2qH,mBAAoB,SAAS7qG,EAAM,CAAC,GAChC,IAAIwsG,EAAWxsG,EAAIglG,aACK,mBAAbwH,IACPA,EAAW7gH,KAAK23B,QAAQ0hF,aACA,mBAAbwH,IAEfA,EAASr1H,KAAKwU,KAAMqU,EAAKrU,KAC7B,EAEAy+G,kBAAmB,SAASD,EAAOnqG,EAAM,CAAC,GACtC,IAAIysG,EAAUzsG,EAAIilG,YACK,mBAAZwH,IACPA,EAAU9gH,KAAK23B,QAAQ2hF,aAEJ,mBAAZwH,GACPA,EAAQt1H,KAAKwU,KAAMw+G,EAAOnqG,EAAKrU,MAEnCA,KAAK28C,QAAQ,cAAe6hE,EAAOnqG,EACvC,EAEA4rG,iBAAkB,SAAS5rG,GACvBA,IAAQA,EAAM,CAAC,GACf,IAAI0sG,EAAY1sG,EAAI0sG,WAAa1J,GAC7BqH,EAAU1+G,KAAKk6G,SACf6F,EAAc,EACdiB,EAAgB,EAChBP,EAAe,EACfC,EAAa,EACbO,EAAc3J,GACdx+E,GAAQ,EACRnB,EAAU33B,KAAK23B,QACfujF,EAAawD,EAAQxD,WACrBgG,EAAa,aAAc7sG,EAAMA,EAAIklG,SAAW5hF,EAAQ4hF,SAClC,mBAAf2H,IAA2BA,EAAa,MACnD,IAAIC,EAAiBxpF,EAAQwhF,gBACC,mBAAnBgI,IAA+BA,EAAiB,MAC3D,IAAIhB,EAAkBn1H,OAAO0F,KAAKwqH,GAClCkG,EAAM,IAAK,IAAIt6G,EAAI,EAAGkJ,EAAImwG,EAAgB3uH,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAC1D,IAAIs8F,GAAY+c,EAAgBr5G,GAC5B63G,EAAkBzD,EAAW9X,GACjC,IAAK,IAAIrlD,KAAO4gE,EAAiB,CAC7B,GAAIoB,GAAegB,EAAW,CAC1BjoF,GAAQ,EACR,MAAMsoF,CACV,CACA,IAAI5vC,EAAOpF,GAAMruB,GACjB,GAAKyzB,EAAL,CAKA,IAAI6vC,EAAc1C,EAAgB5gE,GAClC,KAAKsjE,EAAc7vC,EAAK3E,aAAoB,CAExC,IAAIy0C,EAAavjE,KAAO2gE,EAAQrD,UAChC,GAAI7pC,EAAK9E,YAAcw0C,IAAeA,EAAW11H,KAAKwU,KAAMwxE,GAAO8vC,EAAYthH,MAAO,CAE7EshH,IACDthH,KAAK0/G,sBAAsBluC,GAC3BxxE,KAAKuhH,WAAW/vC,IAEpBktC,EAAQrD,UAAUt9D,IAAQsjE,SACnB1C,EAAgB5gE,GACvB0iE,IACA,QACJ,CAEIa,IACAD,GAAe7vC,EAAK5E,YACpB8zC,KAEJW,GAAerhH,KAAKg/G,oBAAoBxtC,EAC5C,CACA,IAAIgwC,EAAexhH,KAAKo/G,WAAW5tC,EAAM6vC,EAAahtG,GAClDmtG,EAAe,IAEf7C,EAAgB5gE,GAAOyjE,GAClBL,IAAmBA,EAAe31H,KAAKwU,KAAMwxE,EAAMgwC,EAAcxhH,OAAS2+G,EAAgB5gE,KAC3FijE,IACAloF,GAAQ,IAIZmoF,EAAc7d,IAAU6d,EAAc7d,GAC1C2c,WACOpB,EAAgB5gE,GAnCvB,aAFW4gE,EAAgB5gE,EAsC/B,CACJ,CACA,MAAO,CACHqlD,SAAU6d,EACV5B,QAASU,EACT0B,UAAWT,EACX3F,UAAWoF,EACXnF,QAASoF,EACT5nF,MAAOA,EAEf,EAEA4oF,kBAAmB,WACf,MAAMhD,EAAU1+G,KAAKk6G,SACfiB,EAAgBnwH,OAAO0F,KAAKguH,EAAQrD,WACpCrrG,EAAImrG,EAAc3pH,OAClBmwH,EAAiB,IAAI3wH,MAAMgf,GACjC,IAAK,IAAIlJ,EAAI,EAAGA,EAAIkJ,EAAGlJ,IACnB66G,EAAe76G,GAAKslE,GAAM+uC,EAAcr0G,IAE5C,OAAO66G,CACX,EAEAC,gBAAiB,WACb,MAAMlD,EAAU1+G,KAAKk6G,SACfkB,EAAcpwH,OAAO0F,KAAKguH,EAAQpD,SAClCtrG,EAAIorG,EAAY5pH,OAChBqwH,EAAe,IAAI7wH,MAAMgf,GAC/B,IAAK,IAAIlJ,EAAI,EAAGA,EAAIkJ,EAAGlJ,IACnB+6G,EAAa/6G,GAAKslE,GAAMgvC,EAAYt0G,IAExC,OAAO+6G,CACX,EAEAC,oBAAqB,SAASZ,EAAY7sG,GACtCA,IAAQA,EAAO,CAAC,GAChB,IAAIqsG,EAAa,EACS,mBAAfQ,IAA2BA,EAAa,MAKnD,IAJA,IAAIH,GAAY,mBAAoB1sG,EAAMA,EAAIisG,eAAiBr9G,KAC3Dy7G,EAAU1+G,KAAKk6G,SACfiB,EAAgBuD,EAAQvD,cACxBE,EAAYqD,EAAQrD,UACfv0G,EAAI,EAAGkJ,EAAIjO,KAAKE,IAAIk5G,EAAc3pH,OAAQuvH,GAAYj6G,EAAIkJ,EAAGlJ,IAAK,CACvE,IAAIi3C,EAAMo9D,EAAcr0G,GACxB,GAAMi3C,KAAOs9D,EAAb,CACA,IAAI7pC,EAAOpF,GAAMruB,GACjB,GAAKyzB,EACL,GAAIA,EAAK9E,YAAcw0C,IAAeA,EAAW11H,KAAKwU,KAAMwxE,GAAM,EAAOxxE,MAErEm7G,EAAcvpH,KAAKmsD,OAFvB,CAKA2iE,IACA,IAAI70D,EAAO7rD,KAAKg/G,oBAAoBxtC,GAChC3lB,GAAM7rD,KAAKo+G,mBAAmB5sC,EAAM3lB,EAAM2lB,EAAK7E,gBAAiB,CAAEqsC,UAAU,GAHhF,CAPiC,CAWrC,CAGA,OADAmC,EAAc36G,OAAO,EAAGsG,GACjB45G,CACX,EAEAqB,kBAAmB,SAASb,EAAY7sG,GACpCA,IAAQA,EAAM,CAAC,GACf,IAAIosG,EAAe,EACnB,GAA0B,mBAAfS,EAA2B,OAAOT,EAK7C,IAJA,IAAIM,GAAY,qBAAsB1sG,EAAMA,EAAIksG,iBAAmBt9G,KAC/Dy7G,EAAU1+G,KAAKk6G,SACfkB,EAAcsD,EAAQtD,YACtBE,EAAUoD,EAAQpD,QACbx0G,EAAI,EAAGkJ,EAAIjO,KAAKE,IAAIm5G,EAAY5pH,OAAQuvH,GAAYj6G,EAAIkJ,EAAGlJ,IAAK,CACrE,IAAIi3C,EAAMq9D,EAAYt0G,GACtB,GAAMi3C,KAAOu9D,EAAb,CACA,IAAI9pC,EAAOpF,GAAMruB,GACZyzB,IACAA,EAAK9E,aAAcw0C,EAAW11H,KAAKwU,KAAMwxE,GAAM,EAAMxxE,OAK1DygH,IACWzgH,KAAK0/G,sBAAsBluC,IAC5BxxE,KAAKuhH,WAAW/vC,IALtB4pC,EAAYxpH,KAAKmsD,GALU,CAWnC,CAGA,OADAq9D,EAAY56G,OAAO,EAAGsG,GACf25G,CACX,EAEAnjC,oBAAqB,SAAShO,EAAUj7D,EAAM,CAAC,GAC3C,IAAI6sG,EAAa,aAAc7sG,EAAMA,EAAIklG,SAAWv5G,KAAK23B,QAAQ4hF,SACvC,mBAAf2H,IAA2BA,EAAa,MACnD,MAAMxC,EAAU1+G,KAAKk6G,UACf,QAAEoB,EAAO,UAAED,GAAcqD,EACzBsD,GAAW1yC,EAAS5C,aAAew0C,GAAcA,EAAW11H,KAAKwU,KAAMsvE,GAAU,EAAOtvE,MAE9F,IAAIiiH,GAAc,EACd90C,GAAY,EAEhB,GAAImC,EAASvxB,OAAOu9D,IAAY0G,EAAS,CACxBhiH,KAAK0/G,sBAAsBpwC,IAC9BtvE,KAAKuhH,WAAWjyC,GAC1B,MAAMxoE,EAAI43G,EAAQtD,YAAYniH,QAAQq2E,EAASvxB,KAC/C2gE,EAAQtD,YAAY56G,OAAOsG,EAAG,GAC9Bm7G,GAAc,CAClB,CAEA,IAAKA,GAAe3yC,EAASvxB,OAAOs9D,GAAa2G,EAAS,CACtD,MAAMl7G,EAAI43G,EAAQvD,cAAcliH,QAAQq2E,EAASvxB,KACjD2gE,EAAQvD,cAAc36G,OAAOsG,EAAG,GAChC,IAAI+kD,EAAO7rD,KAAKg/G,oBAAoB1vC,GAChCzjB,GAAM7rD,KAAKo+G,mBAAmB9uC,EAAUzjB,EAAMyjB,EAAS3C,gBAAiB,CAAEqsC,UAAU,IACxF7rC,GAAY,CAChB,CAEA,MAAO,CACHmuC,QAASnuC,EAAY,EAAI,EACzBkuC,UAAW4G,EAAc,EAAI,EAErC,EAEApC,cAAe,SAASxrG,GACpB,IAAIurG,EAAa/+G,GAAS,CAAC,EAAGwT,EAAK,CAC/BisG,eAAgBr9G,IAChBs9G,iBAAkBt9G,MAElBi+G,EAAa,aAActB,EAAaA,EAAWrG,SAAWv5G,KAAK23B,QAAQ4hF,SAC3E2I,EAAiBliH,KAAK+hH,kBAAkBb,EAAYtB,GACxD,GAAIsC,EAAiB,EAAG,CAEpB,IAAI/G,EAAgBn7G,KAAKk6G,SAASiB,cAClCyE,EAAWU,eAAiBv+G,KAAKE,IAAIk5G,EAAc3pH,OAAS0wH,EAAgBtC,EAAWU,eAC3F,CAEA,MAAO,CACHhF,QAFet7G,KAAK8hH,oBAAoBZ,EAAYtB,GAGpDvE,UAAW6G,EAEnB,EAEA/F,OAAQ,SAAS9nG,GACbA,IAAQA,EAAM,CAAC,GACf,IAAIqqG,EAAU1+G,KAAKk6G,SACfpvH,EAAMupB,EAAIvpB,IACViwH,EAAW/6G,KAAK23B,QAAQkhF,OACxB2C,EAAYkD,EAAQlD,UACxB,GAAI1wH,GAAOA,IAAQ0wH,EAAY,CAE3B,GAAIT,GAAYS,EAAW,OAC3BkD,EAAQlD,UAAY1wH,EACpB4zH,EAAQnD,UAAYR,CACxB,CACA/6G,KAAK23B,QAAQkhF,QAAS,EACtB,IAAIvjF,EAAKopF,EAAQppF,GACjBopF,EAAQppF,GAAK,KACTt1B,KAAKm9E,WAAa7nD,GAAI2e,GAAY3e,EAC1C,EAEA8mF,SAAU,SAAS/nG,GACfA,IAAQA,EAAM,CAAC,GACf,IAAIqqG,EAAU1+G,KAAKk6G,SACfpvH,EAAMupB,EAAIvpB,IACV0wH,EAAYkD,EAAQlD,UAEpB1wH,GAAO0wH,GAAa1wH,IAAQ0wH,IAChCkD,EAAQlD,UAAY,KAEhB1wH,GAAOA,IAAQ0wH,GAAakD,EAAQnD,YACpCv7G,KAAKm9E,WACLn9E,KAAKm8G,SACLn8G,KAAKg7G,iBAAiB3mG,IAEtBrU,KAAKw8G,YAAYnoG,GAErBrU,KAAK23B,QAAQkhF,OAAS6F,EAAQnD,WAAY,EACtCmD,EAAQnhH,OACRyC,KAAKs8G,YACLoC,EAAQnhH,MAAO,IAEvB,EAEA4/E,QAAS,WACL,QAASn9E,KAAK23B,QAAQ+J,KAC1B,EAEAq5E,SAAU,WACN,QAAS/6G,KAAK23B,QAAQkhF,MAC1B,EAEAsJ,eAAgB,WACZ,OAAOniH,KAAK23B,QAAQihF,UAAY3B,GAAaG,KACjD,EAEA9oC,SAAU,WAENtuE,KAAKm8G,SACLn8G,KAAKk6G,SAASjuG,UAAW,EAEzBjM,KAAKk9G,eACLl9G,KAAKoiH,aACT,EAEAC,gBAAiB,WAEb,IAAI1qF,EAAU33B,KAAK23B,QACfhgB,EAAIggB,EAAQnnB,MACZoH,EAAI+f,EAAQlnB,OAGhB,OAFK9P,GAASgX,KAAIA,EAAI3X,KAAKqI,GAAGkvB,aACzB52B,GAASiX,KAAIA,EAAI5X,KAAKqI,GAAGmvB,cACvB,CAAEhnB,MAAOmH,EAAGlH,OAAQmH,EAC/B,EAEA0qG,cAAe,SAAS9xG,EAAOC,EAAQlc,EAAO,CAAC,GAC3C,MAAM,QAAEojC,GAAY33B,MACZwQ,MAAO+xG,EAAc9xG,OAAQ+xG,GAAkB7qF,EACvD,IAAIhgB,OAAellB,IAAV+d,EAAuB+xG,EAAe/xG,EAC3CoH,OAAgBnlB,IAAXge,EAAwB+xG,EAAgB/xG,EACjD,GAAI8xG,IAAiB5qG,GAAK6qG,IAAkB5qG,EAAG,OAC/C+f,EAAQnnB,MAAQmH,EAChBggB,EAAQlnB,OAASmH,EACjB5X,KAAK26G,iBACL,MAAM8H,EAAeziH,KAAKqiH,kBAC1BriH,KAAK28C,QAAQ,SAAU8lE,EAAajyG,MAAOiyG,EAAahyG,OAAQlc,EACpE,EAEAomH,eAAgB,WACZ,MAAM,QAAEhjF,GAAY33B,KACpB,IAAI2X,EAAIggB,EAAQnnB,MACZoH,EAAI+f,EAAQlnB,OACZ9P,GAASgX,KAAIA,EAAI,GAAG5V,KAAKsK,MAAMsL,QAC/BhX,GAASiX,KAAIA,EAAI,GAAG7V,KAAKsK,MAAMuL,QACnC5X,KAAK0tC,IAAIlB,IAAI,CACTh8B,MAAc,OAANmH,EAAc,GAAKA,EAC3BlH,OAAe,OAANmH,EAAc,GAAKA,GAEpC,EAIA8qG,aAAc,SAASC,EAAWC,EAAYtpD,EAASjlD,GAI/CA,EAFAniB,GAASywH,GAEHA,EAGA,GAAO,CAAEA,YAAWC,aAAYtpD,WAAWjlD,GAGrD,MAAM,EAAElG,EAAC,EAAEH,EAAC,MAAEwC,EAAK,OAAEC,GAAWzQ,KAAK6iH,oBAAoBxuG,IACnD,GAAEjC,EAAE,GAAEC,GAAOrS,KAAKuM,QAKxB,OAHAvM,KAAK6S,WAAW1E,EAAIiE,GAAKpE,EAAIqE,EAAIgC,GACjCrU,KAAKsiH,cAAc9xG,EAAQ4B,EAAI3B,EAAS4B,EAAIgC,GAErC,IAAIvF,GAAKX,EAAGH,EAAGwC,EAAOC,EACjC,EAEAoyG,oBAAqB,SAASxuG,EAAM,CAAC,GAIjC,MAAMsuG,EAAYtuG,EAAIsuG,WAAa,EAC7BC,EAAavuG,EAAIuuG,YAAc,EAC/BtpD,EAAUriB,GAAe5iC,EAAIilD,SAAW,GAExCwpD,EAAW/gH,KAAKwL,IAAI8G,EAAIyuG,UAAY,EAAGH,GACvCI,EAAYhhH,KAAKwL,IAAI8G,EAAI0uG,WAAa,EAAGH,GACzCI,EAAW3uG,EAAI2uG,UAAY/nH,OAAOqxG,UAClC2W,EAAY5uG,EAAI4uG,WAAahoH,OAAOqxG,UACpC4W,EAAY7uG,EAAI8uG,eAEhBh6C,EAAQ,gBAAiB90D,EAAO,IAAIvF,GAAKuF,EAAI+uG,aAAepjH,KAAKqjH,eAAehvG,IAChF,GAAEjC,EAAE,GAAEC,GAAOrS,KAAKuM,QACxB48D,EAAKh7D,GAAKiE,EACV+2D,EAAKn7D,GAAKqE,EACV82D,EAAK34D,OAAS4B,EACd+2D,EAAK14D,QAAU4B,EAEf,IAAIixG,EAAYvhH,KAAK2qF,MAAMvjB,EAAK34D,MAAQ24D,EAAKh7D,GAAKw0G,GAC9CY,EAAaxhH,KAAK2qF,MAAMvjB,EAAK14D,OAAS04D,EAAKn7D,GAAK40G,GAC/CvuG,EAAImvG,2BACLF,EAAYvhH,KAAKwL,IAAI+1G,EAAW,GAChCC,EAAaxhH,KAAKwL,IAAIg2G,EAAY,IAEtCD,GAAaX,EACbY,GAAcX,EAEd,IAAI/sG,EAAK,GACU,aAAdqtG,GAA4B/5C,EAAKh7D,EAAI,GAAqB,aAAd+0G,GAA4B/5C,EAAKh7D,GAAK,GAAoB,QAAd+0G,KACzFrtG,EAAK9T,KAAK2qF,MAAMvjB,EAAKh7D,EAAIw0G,GAAaA,EACtC9sG,GAAMyjD,EAAQtmD,KACdswG,GAAaztG,GAGjB,IAAIC,EAAK,EAkBT,OAjBmB,aAAdotG,GAA4B/5C,EAAKn7D,EAAI,GAAqB,aAAdk1G,GAA4B/5C,EAAKn7D,GAAK,GAAoB,QAAdk1G,KACzFptG,EAAK/T,KAAK2qF,MAAMvjB,EAAKn7D,EAAI40G,GAAcA,EACvC9sG,GAAMwjD,EAAQrmD,IACdswG,GAAcztG,GAGlBwtG,GAAahqD,EAAQpmD,MACrBqwG,GAAcjqD,EAAQnmD,OAGtBmwG,EAAYvhH,KAAKwL,IAAI+1G,EAAWR,GAChCS,EAAaxhH,KAAKwL,IAAIg2G,EAAYR,GAGlCO,EAAYvhH,KAAKE,IAAIqhH,EAAWN,GAChCO,EAAaxhH,KAAKE,IAAIshH,EAAYN,GAE3B,IAAIn0G,IAAM+G,EAAKzD,GAAK0D,EAAKzD,EAAIixG,EAAYlxG,EAAImxG,EAAalxG,EACrE,EAEAoxG,sBAAuB,SAASpvG,GAG5B,IAAIqvG,EAAaC,EACjB,GAHAtvG,IAAQA,EAAM,CAAC,GAGX,gBAAiBA,EAAK,CACtB,MAAM+uG,EAAc/uG,EAAI+uG,YACxBM,EAAc1jH,KAAKi0E,iBAAiBmvC,GACpCO,EAAqB,IAAIh1G,GAAMy0G,EACnC,MACIM,EAAc1jH,KAAK4jH,eAAevvG,GAClCsvG,EAAqB3jH,KAAK6jH,kBAAkBH,GAGhD,IAAKA,EAAYlzG,QAAUkzG,EAAYjzG,OAAQ,OAE/C5P,GAASwT,EAAK,CACVilD,QAAS,EACTkF,qBAAqB,EACrBslD,UAAW,KACXC,SAAU,EACVC,SAAU/oH,OAAOqxG,UACjB2X,cAAe,MACfC,gBAAiB,SAQrB,MAAM5qD,EAAUriB,GAAe5iC,EAAIilD,SAE7B6qD,EAAY9vG,EAAI8vG,WAAa9vG,EAAI0vG,SACjCK,EAAY/vG,EAAI+vG,WAAa/vG,EAAI2vG,SACjCK,EAAYhwG,EAAIgwG,WAAahwG,EAAI0vG,SACjCO,EAAYjwG,EAAIiwG,WAAajwG,EAAI2vG,SAEvC,IAAIO,EACJ,GAAIlwG,EAAIkwG,YACJA,EAAclwG,EAAIkwG,gBACf,CACH,MAAMC,EAAmBxkH,KAAK6S,YACxB4vG,EAAeziH,KAAKqiH,kBAC1BkC,EAAc,CACVp2G,EAAGq2G,EAAiB3uG,GACpB7H,EAAGw2G,EAAiB1uG,GACpBtF,MAAOiyG,EAAajyG,MACpBC,OAAQgyG,EAAahyG,OAE7B,CAEA8zG,EAAc,IAAIz1G,GAAKy1G,GAAajpG,cAAc,CAC9CnN,EAAGmrD,EAAQtmD,KACXhF,EAAGsrD,EAAQrmD,IACXzC,OAAQ8oD,EAAQtmD,KAAOsmD,EAAQpmD,MAC/BzC,QAAS6oD,EAAQrmD,IAAMqmD,EAAQnmD,SAGnC,MAAMirB,EAAMp+B,KAAKi2B,UACTt6B,EAAGyW,EAAI0E,EAAGzE,EAAInI,EAAG2L,EAAI1D,GAAUisB,EAEvC,IAAIqmF,EAAQF,EAAY/zG,MAAQkzG,EAAYlzG,MAAQ4B,EAChDsyG,EAAQH,EAAY9zG,OAASizG,EAAYjzG,OAAS4B,EAOtD,GALIgC,EAAImqD,sBACJimD,EAAQC,EAAQ3iH,KAAKE,IAAIwiH,EAAOC,IAIhCrwG,EAAIyvG,UAAW,CAEf,MAAM92G,EAAWqH,EAAIyvG,UAErBW,EAAQz3G,EAAWjL,KAAKC,MAAMyiH,EAAQz3G,GACtC03G,EAAQ13G,EAAWjL,KAAKC,MAAM0iH,EAAQ13G,EAC1C,CAGAy3G,EAAQ1iH,KAAKE,IAAImiH,EAAWriH,KAAKwL,IAAI42G,EAAWM,IAChDC,EAAQ3iH,KAAKE,IAAIqiH,EAAWviH,KAAKwL,IAAI82G,EAAWK,IAEhD,MAAMC,EACCF,EAAQryG,EADTuyG,EAECD,EAAQryG,EAGf,IAAIuyG,EAAQL,EAAYp2G,EAAIw1G,EAAmBx1G,EAAIs2G,EAAQ5uG,EACvDgvG,EAAQN,EAAYv2G,EAAI21G,EAAmB31G,EAAI02G,EAAQ5uG,EAE3D,OAAQzB,EAAI4vG,eACR,IAAK,SACDY,IAAiBN,EAAY9zG,OAASizG,EAAYjzG,OAASk0G,GAAe,EAC1E,MACJ,IAAK,SACDE,GAAiBN,EAAY9zG,OAASizG,EAAYjzG,OAASk0G,EAOnE,OAAQtwG,EAAI6vG,iBACR,IAAK,SACDU,IAAiBL,EAAY/zG,MAAQkzG,EAAYlzG,MAAQm0G,GAAe,EACxE,MACJ,IAAK,QACDC,GAAiBL,EAAY/zG,MAAQkzG,EAAYlzG,MAAQm0G,EAOjEvmF,EAAIziC,EAAI8oH,EACRrmF,EAAItnB,EAAI4tG,EACRtmF,EAAIl0B,EAAI06G,EACRxmF,EAAIjsB,EAAI0yG,EACR7kH,KAAKi2B,OAAOmI,EAAK/pB,EACrB,EAEAywG,kBAAmB,SAASzwG,GACxBrU,KAAKyjH,sBAAsBpvG,EAC/B,EAGAgvG,eAAgB,SAAShvG,GAErB,OAAIA,GAAOA,EAAI0/D,iBACJ/zE,KAAK29C,MAAMvmB,WAAa,IAAItoB,GAGhC,GAAE9O,KAAKq+C,OAAOjnB,SACzB,EAGAwsF,eAAgB,SAASvvG,GAErB,OAAOrU,KAAKi0E,iBAAiBj0E,KAAKqjH,eAAehvG,GACrD,EAKAsiG,QAAS,WAEL,OAAO32G,KAAK+kH,iBAAiB/kH,KAAKqiH,kBACtC,EAEA9/B,kBAAmB,YAAYthF,GAE3B,MAAM,kBAAE62G,GAAsB93G,KAAK23B,QAEnC,IAAIigC,EAeJ,OAZIA,EAFA,GAAWkgD,GAEMA,EAAkB32G,MAAMnB,KAAMiB,IAClB,IAAtB62G,EAEU93G,KAAK22G,UACdmB,EAKS,IAAIhpG,GAAKgpG,GAHT,KAMdlgD,CACX,EAEAotD,mBAAoB,SAASzmE,GAEzB,MAAM,QAAE5mB,GAAY33B,KAEpB,IAAIilH,EAGAC,EAIAv6G,EAAYgtB,EAAQ6hF,kBACpBrnH,EAAOosD,EAAKpzD,IAAI,QAAU,OAC1Bg6H,EAAqB1yE,GAAU9nC,EAAWxY,EAAM,KAqBpD,OAnBIosD,EAAKC,UACLymE,EAAoBttF,EAAQo+C,SAC5BmvC,EAAmBhnB,KAEnB+mB,EAAoBttF,EAAQ+5E,YAC5BwT,EAAmBrmC,IAchB,IAJUomC,EAAkB35H,qBAAqB8/E,GAClD+5C,GAAsBF,EACtBA,EAAkBz5H,KAAKwU,KAAMu+C,IAAS4mE,GAAsBD,GAE7C,CACjBvnE,MAAOY,EACPq1B,YAAaj8C,EAAQi8C,YACrBusB,aAAqC,IAAxBxoE,EAAQwoE,YAAuB0N,GAAY9P,OAASpmE,EAAQwoE,aAEjF,EAEAmf,WAAY,SAAS/gE,GAEjB,MAAM,GAAEjpB,GAAOipB,GACT,OAAE8yB,EAAM,SAAE6oC,GAAal6G,KACvBwxE,EAAOH,EAAO/7C,GACpB,GAAIk8C,EAAM,CACN,IAAI,IAAEzzB,GAAQyzB,EACd,MAAM,QAAE8pC,EAAO,UAAED,GAAcnB,EAC/B1oC,EAAKjtE,gBACE8sE,EAAO/7C,UACPgmF,EAAQv9D,UACRs9D,EAAUt9D,EACrB,CACA,OAAOyzB,CACX,EAEA0qC,WAAY,SAAS39D,EAAMlqC,GAEvB,MAAM,GAAEihB,GAAOipB,EACT6tB,EAAQpsE,KAAKqxE,OACnB,IAAIG,EAAM3lB,EACNl4D,GAAS,EAmBb,OAlBI2hC,KAAM82C,IACNoF,EAAOpF,EAAM92C,GACTk8C,EAAK7zB,QAAUY,GACfsN,EAAO2lB,EAAK5E,YACZj5E,GAAS,GAKTqM,KAAKs/G,WAAW/gE,IAGpB5qD,IACA69E,EAAOpF,EAAM92C,GAAMt1B,KAAKglH,mBAAmBzmE,GAC3CizB,EAAKluB,MAAQtjD,KACb6rD,EAAO7rD,KAAK0/G,sBAAsBluC,GAAQxxE,KAAK8sE,UAAY0E,EAAK0B,QAAQzhF,GAAO+/E,EAAM,cAEzFxxE,KAAK4vE,kBAAkB4B,EAAM3lB,EAAM2lB,EAAK7E,gBAAiBt4D,GAClDm9D,CACX,EAEA4zC,iBAAkB,WAId,OAAO,CACX,EAEAtK,WAAY,SAASz8D,EAAOhqC,GACxBA,IAAQA,EAAM,CAAC,GACfgqC,IAAUA,EAAQ,IAClBr+C,KAAKi7G,gBAELj7G,KAAKoiH,cAEL,MAAMt3H,EAAMkV,KAAK23B,QAAQmhF,WAAa,KAAO,QAC7C94G,KAAKm8G,OAAO,CAAErxH,QACd,IAAK,IAAIgc,EAAI,EAAGkJ,EAAIquC,EAAM7sD,OAAQsV,EAAIkJ,EAAGlJ,IACrC9G,KAAKk8G,WAAW79D,EAAMv3C,GAAIuN,GAE9BrU,KAAKo8G,SAAS,CAAEtxH,QAChBkV,KAAKs8G,WACT,EAEA8F,YAAa,WAEThhH,GAAOpB,KAAKqxE,OAAQ,UAEpBrxE,KAAKqxE,OAAS,CAAC,CACnB,EAEAirC,UAAW,WAEFt8G,KAAKmiH,mBAINniH,KAAK+6G,WAEL/6G,KAAKk6G,SAAS38G,MAAO,EAGzByC,KAAKqlH,iBACT,EAEAA,eAAgB,WAKZ,IAAIC,EAAYt0H,MAAM8W,KAAK9H,KAAKq+C,MAAMt2C,YAAYhU,QAAO+U,GAAQA,EAAK6yB,aAAa,cAC/E0iB,EAAQr+C,KAAK29C,MAAMxyD,IAAI,UvDxvBP,SAAS8c,GAGjC,IAAIs9G,GADJt9G,EAAW,GAAEA,GAAUvF,WACG/R,KAAI,SAAS60H,GAEnC,IAAIx5G,EAAaw5G,EAAYx5G,WAIzBykE,EAAczkE,EAAWqwB,aAAal2B,SAASkvB,eAAe,IAAKmwF,EAAY/0C,aAEnF,OAAO,WAEH,GAAIzkE,IAAehM,KACf,MAAM,IAAIgJ,MAAM,kEAIpBgD,EAAWqwB,aAAar8B,KAAMywE,GAE9BzkE,EAAWgwB,YAAYy0C,EAC3B,CACJ,IAEAxoE,EAAS1K,MuDkuBmB,SAAS5B,EAAGC,GAChC,IAAI6pH,EAAQpnE,EAAMlzD,IAAIwQ,EAAEggC,aAAa,aACjC+pF,EAAQrnE,EAAMlzD,IAAIyQ,EAAE+/B,aAAa,aACjCgqF,EAAKF,EAAM/pF,WAAWnQ,GAAK,EAC3Bq6F,EAAKF,EAAMhqF,WAAWnQ,GAAK,EAC/B,OAAQo6F,IAAOC,EAAM,EAAKD,EAAKC,GAAO,EAAI,CAC9C,IvDvuBJ,IAAK,IAAI9+G,EAAI,EAAGA,EAAIy+G,EAAW/zH,OAAQsV,IACnCy+G,EAAWz+G,GAAGtb,KAAKyc,EAASnB,GAGpC,CuD6tBQ++G,CAAaP,EAOjB,EAEA9F,WAAY,SAAShuC,EAAM+tC,GACvB,MAAMnC,EAAYp9G,KAAKuwE,aAAas9B,GAAYE,QAC1C,GAAE1lG,EAAE,MAAEs1C,GAAU6zB,EACdxxE,KAAK23B,QAAQihF,UACZ3B,GAAaE,OACdiG,EAAU5sC,iBAAiBnoE,EAAIs1C,EAAMxyD,IAAI,MAIzCiyH,EAAU/O,WAAWhmG,GAG7BmpE,EAAKoJ,QAAQ2kC,EACjB,EAEA,UAAAgC,CAAW/vC,GACPA,EAAKvE,UACLuE,EAAKuJ,UACT,EAIAtvB,SAAU,SAAS/d,GAEf,IAAIrlC,EAAKzH,GAAS8sC,GACZ1tC,KAAKq+C,MAAMzhB,cAAc8Q,GACzBA,aAAe,GAAIA,EAAI,GAAKA,EAE9BpY,EAAKt1B,KAAKytE,cAAc,WAAYplE,GACxC,GAAIitB,EAAI,OAAOt1B,KAAKqxE,OAAO/7C,EAG/B,EAGAo2B,gBAAiB,SAASnN,GAEtB,IAAIjpB,EAAM10B,GAAS29C,IAAS59C,GAAS49C,GAASA,EAAQA,GAAQA,EAAKjpB,GAEnE,OAAOt1B,KAAKqxE,OAAO/7C,EACvB,EAGAwwF,mBAAoB,SAASj4G,GAMzB,OAJAA,EAAI,IAAIc,GAAMd,GAEF7N,KAAK29C,MAAM4oB,cAAc51E,IAAIqP,KAAK0rD,gBAAiB1rD,MAElDjM,QAAO,SAASy9E,GACzB,OAAOA,GAAQA,EAAKv4C,IAAI7B,QAAQ,CAAElyB,OAAQlF,KAAKq+C,QAAS9tC,cAAc1C,EAC1E,GAAG7N,KACP,EAGA+lH,gBAAiB,SAAS9vG,EAAM5B,GAE5BA,EAAMxT,GAASwT,GAAO,CAAC,EAAG,CAAEyE,QAAQ,IACpC7C,EAAO,IAAInH,GAAKmH,GAEhB,IAAIm2D,EAAQpsE,KAAK29C,MAAM4oB,cAAc51E,IAAIqP,KAAK0rD,gBAAiB1rD,MAC3D2sC,EAASt4B,EAAIyE,OAAS,eAAiB,YAE3C,OAAOszD,EAAMr4E,QAAO,SAASy9E,GACzB,OAAOA,GAAQv7D,EAAK02B,GAAQ6kC,EAAKv4C,IAAI7B,QAAQ,CAAElyB,OAAQlF,KAAKq+C,QAChE,GAAGr+C,KACP,EAEA,sBAAA8rG,CAAuBka,EAAW3xG,GAC9B,OAAOrU,KAAKimH,mBACRD,GACA,CAACE,EAASC,IAAYnmH,KAAK29C,MAAMurB,mBAAmBg9C,EAASC,IAC7D9xG,EAER,EAEA+xG,oBAAqB,SAASJ,EAAW3xG,GACrC,OAAOrU,KAAKimH,mBACRD,GACA,CAACE,EAASC,IAAYnmH,KAAK29C,MAAM0rB,gBAAgB68C,EAASC,IAC1D9xG,EAER,EAEAgyG,oBAAqB,SAASL,EAAW3xG,GACrC,OAAOrU,KAAKimH,mBACRD,GACA,CAACE,EAASC,IAAYnmH,KAAK29C,MAAM2rB,gBAAgB48C,EAASC,IAC1D9xG,EAER,EAEAiyG,wBAAyB,SAASC,EAAYlyG,GAC1C,OAAOrU,KAAKwmH,oBACRD,GACCL,GAAYlmH,KAAK29C,MAAMurB,mBAAmBg9C,IAC3C7xG,EAER,EAEAoyG,qBAAsB,SAASF,EAAYlyG,GACvC,OAAOrU,KAAKwmH,oBACRD,GACCL,GAAYlmH,KAAK29C,MAAM0rB,gBAAgB68C,IACxC7xG,EAER,EAEAqyG,qBAAsB,SAASH,EAAYlyG,GACvC,OAAOrU,KAAKwmH,oBACRD,GAGCL,GAAYlmH,KAAK29C,MAAM2rB,gBAAgB48C,IACxC7xG,EAER,EAEAsyG,oBAAqB,SAASx9C,EAAMy9C,EAAavyG,EAAM,CAAC,GACpD,MAAM,OACF7gB,EAASwM,KAAKy6G,qBACdpmG,EAGJ,OAD4BuyG,EADP,IAAK93G,GAAKq6D,GAAO9yD,QAAQ7iB,GACQ6gB,GAC3B1jB,KAAI4mE,GAAWv3D,KAAK0rD,gBAAgB6L,IACnE,EAEA0uD,mBAAoB,SAASD,EAAWa,EAAWxyG,EAAM,CAAC,GACtD,MAAM80D,EAAO,IAAIr6D,GAAKk3G,GAMtB,OAL4BhmH,KAAK2mH,oBAAoBx9C,EAAM09C,EAAWxyG,GAC9BtgB,QAAOy9E,KACtCA,GACEA,EAAKqM,SAAS1U,EAAM90D,IAGnC,EAEAmyG,oBAAqB,SAASD,EAAYM,EAAWxyG,EAAM,CAAC,GACxD,MAAM80D,EAAO,IAAIr6D,GAAKy3G,GAMtB,OAL4BvmH,KAAK2mH,oBAAoBx9C,EAAM09C,EAAWxyG,GAC7BtgB,QAAOy9E,KACvCA,GACEA,EAAKsM,UAAUyoC,EAAYlyG,IAG1C,EAEA4mE,YAAa,WAET,OADAj7E,KAAK8mH,mBAAmB,UACjB9mH,IACX,EAEA47E,UAAW,WAEP,OADA57E,KAAK8mH,mBAAmB,QACjB9mH,IACX,EAEA87E,UAAW,WAEP,OADA97E,KAAK8mH,mBAAmB,QACjB9mH,IACX,EAEA8mH,mBAAoB,SAAS39G,KAAUlI,GACd,iBAAVkI,GACXnJ,KAAK28C,QAAQ,cAAexzC,KAAUlI,EAC1C,EAGAskG,aAAc,SAASjwE,GAEnB,OAAOt1B,KAAK29C,MAAMqL,QAAQ1zB,EAC9B,EAEAvoB,WAAY,SAASoB,EAAGH,GAIpB,OAAOhO,KAAK+mH,mBAAmB54G,EAAGH,GAAGjB,WAAW/M,KAAK23B,QAAQ3qB,SACjE,EAEAg6G,kBAAmB,SAAS74G,EAAGH,GAE3B,IAAIi5G,EAAa,IAAIt4G,GAAMR,EAAGH,GAE9B,OADiB,GAAEi3B,eAAegiF,EAAYjnH,KAAKi2B,SAEvD,EAEAg+C,iBAAkB,SAAS9lE,EAAGH,EAAGwC,EAAOC,GAEpC,IAAIy2G,EAAY,IAAIp4G,GAAKX,EAAGH,EAAGwC,EAAOC,GAEtC,OADgB,GAAEgnB,cAAcyvF,EAAWlnH,KAAKi2B,SAEpD,EAEA4tF,kBAAmB,SAAS11G,EAAGH,GAE3B,IAAIm5G,EAAa,IAAIx4G,GAAMR,EAAGH,GAE9B,OADiB,GAAEi3B,eAAekiF,EAAYnnH,KAAKi2B,SAASJ,UAEhE,EAEAkvF,iBAAkB,SAAS52G,EAAGH,EAAGwC,EAAOC,GAEpC,IAAI22G,EAAY,IAAIt4G,GAAKX,EAAGH,EAAGwC,EAAOC,GAEtC,OADgB,GAAEgnB,cAAc2vF,EAAWpnH,KAAKi2B,SAASJ,UAE7D,EAEA81E,mBAAoB,SAASx9F,EAAGH,GAE5B,IAAIi5G,EAAa,IAAIt4G,GAAMR,EAAGH,GAE9B,OADkB,GAAEi3B,eAAegiF,EAAYjnH,KAAKi+G,eAExD,EAEAoJ,kBAAmB,SAASl5G,EAAGH,EAAGwC,EAAOC,GAErC,IAAIy2G,EAAY,IAAIp4G,GAAKX,EAAGH,EAAGwC,EAAOC,GAEtC,OADiB,GAAEgnB,cAAcyvF,EAAWlnH,KAAKi+G,eAErD,EAMA8I,mBAAoB,SAAS54G,EAAGH,GAE5B,IAAIs5G,EAAc,IAAI34G,GAAMR,EAAGH,GAE/B,OADiB,GAAEi3B,eAAeqiF,EAAatnH,KAAKi+G,eAAepoF,UAEvE,EAEA0xF,kBAAmB,SAASp5G,EAAGH,EAAGwC,EAAOC,GAErC,IAAI+2G,EAAa,IAAI14G,GAAKX,EAAGH,EAAGwC,EAAOC,GAEvC,OADgB,GAAEgnB,cAAc+vF,EAAYxnH,KAAKi+G,eAAepoF,UAEpE,EAEA4xF,iBAAkB,SAASt5G,EAAGH,GAE1B,OAAOhO,KAAKgnH,kBAAkB74G,EAAGH,GAAGqD,OAAOrR,KAAK0nH,aACpD,EAEAC,gBAAiB,SAASx5G,EAAGH,EAAGwC,EAAOC,GAEnC,OAAOzQ,KAAKi0E,iBAAiB9lE,EAAGH,EAAGwC,EAAOC,GAAQY,OAAOrR,KAAK0nH,aAClE,EAEAE,iBAAkB,SAASz5G,EAAGH,GAE1B,IACIm5G,EADY,IAAIx4G,GAAMR,EAAGH,GACF7K,WAAWnD,KAAK0nH,cAC3C,OAAO1nH,KAAK6jH,kBAAkBsD,EAClC,EAEAU,gBAAiB,SAAS15G,EAAGH,EAAGwC,EAAOC,GAEnC,IAAIi3G,EAAa1nH,KAAK0nH,aAClBN,EAAY,IAAIt4G,GAAKX,EAAGH,EAAGwC,EAAOC,GAGtC,OAFA22G,EAAUj5G,GAAKu5G,EAAWv5G,EAC1Bi5G,EAAUp5G,GAAK05G,EAAW15G,EACnBhO,KAAK+kH,iBAAiBqC,EACjC,EAEAU,aAAc,WAEV,IAAIN,EAAaxnH,KAAK2yB,IAAIib,wBAC1B,OAAO,IAAIj/B,GAAM64G,EAAWx0G,KAAMw0G,EAAWv0G,IACjD,EAEAy0G,WAAY,WAER,OAAO1nH,KAAK8nH,eAAez2G,OAAOnL,OAAOooC,QAASpoC,OAAOmoC,QAC7D,EAEAo8D,YAAa,SAAS10B,GAElB,KAAMA,aAAoBmoB,IACtB,MAAM,IAAIl1F,MAAM,4BAGpB,IAAIo+C,EAAO2uB,EAASp4B,MAChB8lD,EAAezjG,KAAK23B,QACpBsvB,EAAQjnD,KAAK29C,MACbrzC,EAAK28C,EAAM30D,YAAYq4E,YAE3B,SAAK84B,EAAa74B,aACTtgE,EAAGsgE,WAAWp/E,KAAKwU,KAAMinD,EAAOG,KAGpCq8C,EAAax4B,cAET3gE,EAAG2gE,YAAYz/E,KAAKwU,KAAMinD,EAAOG,IAGJ,mBAA3Bq8C,EAAaiV,YACfjV,EAAaiV,UAAUltH,KAAKwU,KAAM+1E,EAAU/1E,MAIzD,EAEAs1E,eAAgB,SAAShG,EAAU4E,GAE/B,OAAO,GAAWl0E,KAAK23B,QAAQogF,aAEzB/3G,KAAK23B,QAAQogF,YAAYvsH,KAAKwU,KAAMsvE,EAAU4E,GAE9Cl0E,KAAK23B,QAAQogF,YAAY31G,OACnC,EAKA2lH,mBAAoB,SAAS1zG,EAAM,CAAC,GAEhC,IAAM2zG,YAAaC,EAAc,KAAE91H,GAASkiB,EAC5C,MAAM,aAAEqjG,EAAY,qBAAC+B,GAA0Bz5G,KAAK23B,QAWpD,QAAuBllC,IAAnBw1H,EAA8B,CAG9B,IAAKvQ,EAAc,OAAO,EAE1B,GAAIvlH,IACA81H,EAAiBvQ,EAAavlH,IAEP,IAAnB81H,GAA0B,OAAO,EAEpCA,IAEDA,EAAiBvQ,EAAsB,QAE/C,CAMA,IAAKuQ,EAAgB,OAAO,EAGxBrnH,GAASqnH,KACTA,EAAiB,CACb9wH,KAAM8wH,IAId,MAAM9wH,EAAO8wH,EAAe9wH,KACtB6wH,EAAcvO,EAAqBtiH,GAGzC,IAAK6wH,EACD,MAAM,IAAIh/G,MAAM,yBAA2B7R,EAAO,MAEtD,GAAqC,mBAA1B6wH,EAAY/uE,UACnB,MAAM,IAAIjwC,MAAM,iBAAmB7R,EAAO,6CAE9C,GAAuC,mBAA5B6wH,EAAYj3C,YACnB,MAAM,IAAI/nE,MAAM,iBAAmB7R,EAAO,+CAG9C,MAAO,CACH6wH,cACArwF,QAASswF,EAAetwF,SAAW,CAAC,EACpCxgC,OAER,EAEA6kH,gBAAiB,SAAS1sC,EAAU44C,EAAU7zG,GAC1C,MAAM8zG,EAAwBnoH,KAAK+nH,mBAAmB1zG,GACtD,IAAK8zG,EAAuB,OAC5B,MAAM,YAAEH,EAAW,QAAErwF,GAAYwwF,EACjCH,EAAY/uE,UAAUq2B,EAAU44C,EAAUvwF,EAC9C,EAEAskF,kBAAmB,SAAS3sC,EAAU44C,EAAU7zG,GAC5C,MAAM8zG,EAAwBnoH,KAAK+nH,mBAAmB1zG,GACtD,IAAK8zG,EAAuB,OAC5B,MAAM,YAAEH,EAAW,QAAErwF,GAAYwwF,EACjCH,EAAYj3C,YAAYzB,EAAU44C,EAAUvwF,EAChD,EAKA0kD,gBAAiB,SAASz2E,GAEtBA,EAAID,iBAIJC,EAAMmtC,GAAentC,GAErB,IAAI4rE,EAAOxxE,KAAKyrD,SAAS7lD,EAAIV,QAC7B,IAAIlF,KAAKtE,MAAMkK,EAAK4rE,GAApB,CAEA,IAAIy1C,EAAajnH,KAAK+M,WAAWnH,EAAIwzE,QAASxzE,EAAIyzE,SAE9C7H,EACAA,EAAK6K,gBAAgBz2E,EAAKqhH,EAAW94G,EAAG84G,EAAWj5G,GAGnDhO,KAAK28C,QAAQ,wBAAyB/2C,EAAKqhH,EAAW94G,EAAG84G,EAAWj5G,EARvC,CAUrC,EAEAsuE,aAAc,SAAS12E,GAMnB,GAFW5F,KAAK6uE,UAAUjpE,GAEjB4wE,YAAcx2E,KAAK23B,QAAQmrD,eAAgB,CAEhDl9E,EAAMmtC,GAAentC,GAErB,IAAI4rE,EAAOxxE,KAAKyrD,SAAS7lD,EAAIV,QAC7B,GAAIlF,KAAKtE,MAAMkK,EAAK4rE,GAAO,OAE3B,IAAIy1C,EAAajnH,KAAK+M,WAAWnH,EAAIwzE,QAASxzE,EAAIyzE,SAE9C7H,EACAA,EAAK8K,aAAa12E,EAAKqhH,EAAW94G,EAAG84G,EAAWj5G,GAGhDhO,KAAK28C,QAAQ,qBAAsB/2C,EAAKqhH,EAAW94G,EAAG84G,EAAWj5G,EAEzE,CACJ,EAEAuuE,YAAa,SAAS32E,GAEd5F,KAAK23B,QAAQggF,oBAAoB/xG,EAAID,iBAErC3F,KAAKooH,iBACLpoH,KAAKooH,kBAAmB,GAI5BxiH,EAAMmtC,GAAentC,GAErB5F,KAAKqoH,mBAAmBziH,GAC5B,EAEAyiH,mBAAoB,SAASziH,GACzB,IAAI4rE,EAAOxxE,KAAKyrD,SAAS7lD,EAAIV,QAC7B,IAAIlF,KAAKtE,MAAMkK,EAAK4rE,GAApB,CAEA,IAAIy1C,EAAajnH,KAAK+M,WAAWnH,EAAIwzE,QAASxzE,EAAIyzE,SAE9C7H,EACAA,EAAK+K,YAAY32E,EAAKqhH,EAAW94G,EAAG84G,EAAWj5G,GAG/ChO,KAAK28C,QAAQ,oBAAqB/2C,EAAKqhH,EAAW94G,EAAG84G,EAAWj5G,EARnC,CAUrC,EAEAwuE,YAAa,SAAS52E,GAElBA,EAAMmtC,GAAentC,GAErB,MAAM,OAAEV,EAAM,OAAE4G,GAAWlG,EACrB4rE,EAAOxxE,KAAKyrD,SAASvmD,GACrBojH,EAA4B,IAAXx8G,EAEvB,GAAI0lE,EAAM,CAEN,IAAK82C,GAAiBtoH,KAAKtE,MAAMkK,EAAK4rE,GAAO,OAE7C,MAAM+2C,EAAmBvoH,KAAKs6G,uBAAuBthH,SAASkM,EAAO42B,SAEjE97B,KAAK23B,QAAQkgF,2BAA6B0Q,GAI1C3iH,EAAID,iBAGJ4iH,GAGA/2C,EAAK0K,0BAA0Bt2E,GAInC,MAAM4iH,EAAWxoH,KAAKyoH,mBAAmB7iH,EAAK4rE,GAC9C,GAAIg3C,EAAU,CAEV,GAAIA,EAAS/iH,uBAAwB,OAErCG,EAAIrR,KAAOi0H,EAASj0H,IACxB,CAGA,MAAMm0H,EAAaxjH,EAAO+K,QAAQ,YAClC,GAAIy4G,GAAcl3C,EAAKnpE,KAAOqgH,GAAcl3C,EAAKnpE,GAAGE,SAASmgH,GAAa,CACtE,MAAMC,EAAY51E,GAAe,IAAI,GAAEpuC,MAAMiB,EAAIf,cAAe,CAC5DtQ,KAAMqR,EAAIrR,KAEV4Q,cAAeujH,KAOnB,GALA1oH,KAAK+8E,SAAS4rC,GACVA,EAAU7jH,sBACVc,EAAID,iBAGJgjH,EAAUljH,uBAAwB,CAElC,GAAI6iH,EAAe,OAEnB,YADAtoH,KAAK6pG,mBAAmBr4B,EAAMm3C,EAAUp0H,KAE5C,CACAqR,EAAIrR,KAAOo0H,EAAUp0H,IACzB,CACJ,CAEA,GAAI+zH,EAAe,CACftoH,KAAKooH,kBAAmB,EACxB,MAAMQ,EAAiB,IAAI,GAAEjkH,MAAMiB,EAAIf,cAAe,CAAE1S,KAAM,cAAeoC,KAAMqR,EAAIrR,OACvFyL,KAAKqoH,mBAAmBO,EAC5B,KAAO,CACH,MAAM3B,EAAajnH,KAAK+M,WAAWnH,EAAIwzE,QAASxzE,EAAIyzE,SAChD7H,EACAA,EAAKgL,YAAY52E,EAAKqhH,EAAW94G,EAAG84G,EAAWj5G,IAE3ChO,KAAK23B,QAAQigF,2BACbhyG,EAAID,iBAER3F,KAAK28C,QAAQ,oBAAqB/2C,EAAKqhH,EAAW94G,EAAG84G,EAAWj5G,IAGpEhO,KAAK6pG,mBAAmBr4B,EAAM5rE,EAAIrR,KACtC,CAEJ,EAEA6hF,YAAa,SAASxwE,GAGlB,IAAIrR,EAAOyL,KAAK6uE,UAAUjpE,GAY1B,GAXKrR,EAAKiiF,aACNjiF,EAAKiiF,WAAa,EAGlBx2E,KAAK4rE,wBAKUr3E,EAAKiiF,YAENx2E,KAAK23B,QAAQghF,eAA/B,CAEA/yG,EAAMmtC,GAAentC,GAErB,IAAIqhH,EAAajnH,KAAK+M,WAAWnH,EAAIwzE,QAASxzE,EAAIyzE,SAE9C7H,EAAOj9E,EAAK6oF,WACZ5L,EACAA,EAAK4E,YAAYxwE,EAAKqhH,EAAW94G,EAAG84G,EAAWj5G,GAE/ChO,KAAK28C,QAAQ,oBAAqB/2C,EAAKqhH,EAAW94G,EAAG84G,EAAWj5G,GAGpEhO,KAAK6uE,UAAUjpE,EAAKrR,EAbgC,CAcxD,EAEAmiF,UAAW,SAAS9wE,GAEhB5F,KAAKuuE,2BAEL,IAAIs6C,EAAgB91E,GAAentC,GAE/BqhH,EAAajnH,KAAK+M,WAAW87G,EAAczvC,QAASyvC,EAAcxvC,SAElE7H,EAAOxxE,KAAK6uE,UAAUjpE,GAAKw3E,WAC3B5L,EACAA,EAAKkF,UAAUmyC,EAAe5B,EAAW94G,EAAG84G,EAAWj5G,GAEvDhO,KAAK28C,QAAQ,kBAAmBksE,EAAe5B,EAAW94G,EAAG84G,EAAWj5G,GAGvE66G,EAAcpjH,wBACfzF,KAAKs8E,aAAa,IAAI,GAAE33E,MAAMiB,EAAIf,cAAe,CAAE1S,KAAM,QAASoC,KAAMqR,EAAIrR,QAGhFyL,KAAK8rE,gBACT,EAEA2Q,UAAW,SAAS72E,GAEhBA,EAAMmtC,GAAentC,GAErB,IAAI4rE,EAAOxxE,KAAKyrD,SAAS7lD,EAAIV,QAC7B,IAAIlF,KAAKtE,MAAMkK,EAAK4rE,GAEpB,GAAIA,EACAA,EAAKiL,UAAU72E,OAEZ,CACH,GAAI5F,KAAKqI,KAAOzC,EAAIV,OAAQ,OAC5BlF,KAAK28C,QAAQ,kBAAmB/2C,EACpC,CACJ,EAEA82E,SAAU,SAAS92E,GAEfA,EAAMmtC,GAAentC,GAErB,IAAI4rE,EAAOxxE,KAAKyrD,SAAS7lD,EAAIV,QAC7B,IAAIlF,KAAKtE,MAAMkK,EAAK4rE,GAEpB,GAAIA,EACAA,EAAKkL,SAAS92E,OAEX,CACH,GAAI5F,KAAKqI,KAAOzC,EAAIV,OAAQ,OAC5BlF,KAAK28C,QAAQ,iBAAkB/2C,EACnC,CACJ,EAEA+2E,WAAY,SAAS/2E,GAEjBA,EAAMmtC,GAAentC,GAErB,MAAM,OACFV,EAAM,cACNE,EAAa,cACbD,GACAS,EACE4rE,EAAOxxE,KAAKyrD,SAASvmD,GAC3B,GAAIlF,KAAKtE,MAAMkK,EAAK4rE,GAAO,OAC3B,MAAMiK,EAAcz7E,KAAKyrD,SAASrmD,GAClC,GAAIosE,EAAM,CACN,GAAIiK,IAAgBjK,EAEhB,OAGJ,GADAA,EAAKmL,WAAW/2E,GACZ5F,KAAKqI,GAAGE,SAASnD,GAEjB,MAER,CACIq2E,GAKAt2E,IAAkBnF,KAAKqI,IAEvBrI,KAAK28C,QAAQ,mBAAoB/2C,EAEzC,EAEAg3E,WAAY,SAASh3E,GAEjBA,EAAMmtC,GAAentC,GAErB,MAAM,OACFV,EAAM,cACNE,EAAa,cACbD,GACAS,EACE4rE,EAAOxxE,KAAKyrD,SAASvmD,GAC3B,GAAIlF,KAAKtE,MAAMkK,EAAK4rE,GAAO,OAC3B,MAAMiK,EAAcz7E,KAAKyrD,SAASrmD,GAClC,GAAIosE,EAAM,CACN,GAAIiK,IAAgBjK,EAEhB,OAGJ,GADAA,EAAKoL,WAAWh3E,GACZ5F,KAAKqI,GAAGE,SAASnD,GAEjB,MAER,CACIq2E,GAMAt2E,IAAkBnF,KAAKqI,IAEvBrI,KAAK28C,QAAQ,mBAAoB/2C,EAEzC,EAEAkjH,yBrFzYG,SAAkBxnH,EAAMynH,EAAM10G,GAKjC,IAAI20G,EACAC,EACAC,EACAz3H,EACA03H,EACAC,EACAC,EAAiB,EACjBC,GAAU,EACVC,GAAS,EACT5pH,GAAW,EAEf,MAAM6pH,GAAWT,GAAiB,IAATA,GAAc7iH,QAAkD,mBAAjCA,OAAOqtC,sBAW/D,SAASk2E,EAAWC,GAChB,MAAMzoH,EAAO+nH,EACPW,EAAUV,EAKhB,OAHAD,EAAWC,OAAWx2H,EACtB42H,EAAiBK,EACjBj4H,EAAS6P,EAAKH,MAAMwoH,EAAS1oH,GACtBxP,CACX,CAEA,SAASm4H,EAAWC,EAAad,GAC7B,OAAIS,GACAtjH,OAAOkuC,qBAAqB+0E,GACrBjjH,OAAOqtC,sBAAsBs2E,IAEjCt6E,WAAWs6E,EAAad,EACnC,CAuBA,SAASe,EAAaJ,GAClB,MAAMK,EAAoBL,EAAON,EAGjC,YAAyB32H,IAAjB22H,GAA+BW,GAAqBhB,GAAUgB,EAAoB,GACrFR,GAHuBG,EAAOL,GAGGH,CAC1C,CAEA,SAASc,IACL,MAAMN,EAAOpkH,KAAKC,MAClB,GAAIukH,EAAaJ,GACb,OAAOO,EAAaP,GAExBP,EAAUS,EAAWI,EArBzB,SAAuBN,GACnB,MACMQ,EAAsBR,EAAOL,EAC7Bc,EAAcpB,GAFMW,EAAON,GAIjC,OAAOG,EAASxnH,KAAKE,IAAIkoH,EAAajB,EAAUgB,GAAuBC,CAC3E,CAeuCC,CAAcV,GACrD,CAEA,SAASO,EAAaP,GAGlB,OAFAP,OAAU12H,EAENkN,GAAYqpH,EACLS,EAAWC,IAEtBV,EAAWC,OAAWx2H,EACfhB,EACX,CAEA,SAAS44H,KAAappH,GAClB,MAAMyoH,EAAOpkH,KAAKC,MACZ+kH,EAAaR,EAAaJ,GAMhC,GAJAV,EAAW/nH,EACXgoH,EAAWjpH,KACXopH,EAAeM,EAEXY,EAAY,CACZ,QAAgB73H,IAAZ02H,EACA,OAlDZ,SAAqBO,GAGjB,OAFAL,EAAiBK,EACjBP,EAAUS,EAAWI,EAAcjB,GAC5BO,EAAUG,EAAWC,GAAQj4H,CACxC,CA8CmB84H,CAAYnB,GAEvB,GAAIG,EAEA,OADAJ,EAAUS,EAAWI,EAAcjB,GAC5BU,EAAWL,EAE1B,CAIA,YAHgB32H,IAAZ02H,IACAA,EAAUS,EAAWI,EAAcjB,IAEhCt3H,CACX,CAYA,OA3GAs3H,GAAQA,GAAQ,EAEZ72H,GAASmiB,KACTi1G,IAAYj1G,EAAIi1G,QAChBC,EAAS,YAAal1G,EACtB60G,EAAUK,EAASxnH,KAAKwL,KAAK8G,EAAI60G,SAAW,EAAGH,GAAQG,EACvDvpH,EAAW,aAAc0U,IAAQA,EAAI1U,SAAWA,GA2FpD0qH,EAAUG,OAAS,UACC/3H,IAAZ02H,GAvER,SAAqB7zF,GACjB,GAAIk0F,EACA,OAAOtjH,OAAOkuC,qBAAqB9e,GAEvCwa,aAAaxa,EACjB,CAmEQm1F,CAAYtB,GAEhBE,EAAiB,EACjBL,EAAWI,EAAeH,EAAWE,OAAU12H,CAAS,EAE5D43H,EAAUK,MAAQ,SAAkBj4H,IAAZ02H,EAAwB13H,EAASw4H,EAAa3kH,KAAKC,OAC3E8kH,EAAUM,QAAU,SAAkBl4H,IAAZ02H,EAEnBkB,CACX,CqF2Q8BO,EAAS,WAC/B,MAAM,MAAEzhH,EAAK,OAAE0xG,GAAW76G,KAAK46G,eACzBiQ,EAAShQ,EAAO72G,QAAO,CAAC6hB,EAAKglG,KAAWhlG,WvDhkE1BrnB,EuDgkEoCqsH,GA/4E9C,MvDgVWrsH,GuDhVX,OvDgV+BA,GAD9B,IAASA,CuDgkEsD,GAAE,GAEtE+N,EAAQxK,KAAKqN,IAAI,KAAOy7G,IACxB,EAAE18G,EAAC,EAAEH,GAAMhO,KAAK+mH,mBAAmB59G,EAAMiwE,QAASjwE,EAAMkwE,SAC9Dr5E,KAAK28C,QAAQ,cAAexzC,EAAOgF,EAAGH,EAAGzB,GAEzCvM,KAAK46G,eAAiB,CAClBzxG,MAAO,KACP0xG,OAAQ,GAEhB,GAx5EkB,GAw5EA,CAAEqO,QAx5EF,KA05ElBrsC,WAAY,SAASj3E,GAEjBA,EAAMmtC,GAAentC,GAErB,MAAM4rE,EAAOxxE,KAAKyrD,SAAS7lD,EAAIV,QAC/B,GAAIlF,KAAKtE,MAAMkK,EAAK4rE,GAAO,OAE3B,MAAM3sE,EAAgBe,EAAIf,cACpBoiH,EAAajnH,KAAK+M,WAAWlI,EAAcu0E,QAASv0E,EAAcw0E,UAClE,OAAEyxC,EAAM,OAAED,GvD1oEM,SAASjlH,GAMnC,IAAImlH,EAAK,EAAGC,EAAK,EAAGC,EAAK,EAAGC,EAAK,EAuCjC,MApCI,WAAiBtlH,IAAOolH,EAAKplH,EAAIulH,QACjC,eAAiBvlH,IAAOolH,GAAMplH,EAAIwlH,WAAa,KAC/C,gBAAiBxlH,IAAOolH,GAAMplH,EAAIylH,YAAc,KAChD,gBAAiBzlH,IAAOmlH,GAAMnlH,EAAI0lH,YAAc,KAG/C,SAAU1lH,GAAOA,EAAIs6C,OAASt6C,EAAI2lH,kBACnCR,EAAKC,EACLA,EAAK,GAGTC,EAAK,WAAYrlH,EAAMA,EAAIklH,OAlBP,GAkBgBC,EACpCG,EAAK,WAAYtlH,EAAMA,EAAIilH,OAnBP,GAmBgBG,GAE/BC,GAAMC,IAAOtlH,EAAI4lH,YACG,GAAjB5lH,EAAI4lH,WACJP,GAtBY,GAuBZC,GAvBY,KAyBZD,GAxBY,IAyBZC,GAzBY,MA8BD,IAAftlH,EAAIklH,QAA+B,IAAfllH,EAAIilH,QAAgBjlH,EAAI6lH,WAC5CR,EAAKC,EACLA,EAAK,EACLH,EAAKC,EACLA,EAAK,GAILC,IAAOF,IAAMA,EAAME,EAAK,GAAM,EAAI,GAClCC,IAAOF,IAAMA,EAAME,EAAK,GAAM,EAAI,GAE/B,CACHQ,MAASX,EACTY,MAASX,EACTF,OAASG,EACTJ,OAASK,EAEjB,CuDulEmCU,CAAe/mH,GAEpCgnH,EAAgB7rH,KAAKi7C,QAAQ,eAOnC,GAAIr1C,EAAIkmH,SAAWD,GAAiBA,EAAcr6H,OAAS,EAEvDqT,EAAcc,iBACd3F,KAAK46G,eAAezxG,MAAQvD,EAC5B5F,KAAK46G,eAAeC,OAAOjpH,KAAKi5H,GAChC7qH,KAAK8oH,+BACF,CACH,MAAM93E,EAAQjvC,KAAKwL,KAAK,EAAGxL,KAAKE,IAAI,EAAG4C,EAAcumH,aACjD55C,EACAA,EAAKqL,WAAWj3E,EAAKqhH,EAAW94G,EAAG84G,EAAWj5G,EAAGgjC,GAGjDhxC,KAAK28C,QAAQ,mBAAoB/2C,EAAKqhH,EAAW94G,EAAG84G,EAAWj5G,EAAGgjC,GAGtEhxC,KAAK28C,QAAQ,YAAa/2C,EAAKklH,EAAQD,EAC3C,CACJ,EAEA/tC,QAAS,SAASl3E,GAEd,IAAImmH,EAAYnmH,EAAIT,cAChB6mE,EAAY+/C,EAAUpwF,aAAa,SACvC,GAAIqwC,EAAW,CACX,IAAIwF,EAAOxxE,KAAKyrD,SAASsgE,GACzB,GAAIv6C,EAAM,CAGN,GADA5rE,EAAMmtC,GAAentC,GACjB5F,KAAKtE,MAAMkK,EAAK4rE,GAAO,OAE3B,IAAIy1C,EAAajnH,KAAK+M,WAAWnH,EAAIwzE,QAASxzE,EAAIyzE,SAClD7H,EAAKsL,QAAQl3E,EAAKomE,EAAWi7C,EAAW94G,EAAG84G,EAAWj5G,EAC1D,CACJ,CACJ,EAEAg+G,YAAa,SAASpmH,EAAKiE,GAEvB,IAAI6+G,EAAa9iH,EAAIT,cAErB,GADkBujH,EAAW/sF,aAAa,UACzB,CACb,IAAI61C,EAAOxxE,KAAKyrD,SAASi9D,GACzB,GAAIl3C,EAAM,CAEN,GADA5rE,EAAMmtC,GAAentC,GACjB5F,KAAKtE,MAAMkK,EAAK4rE,GAAO,OAC3B,IAAIy1C,EAAajnH,KAAK+M,WAAWnH,EAAIwzE,QAASxzE,EAAIyzE,SAClDxvE,EAAQre,KAAKwU,KAAMwxE,EAAM5rE,EAAK8iH,EAAYzB,EAAW94G,EAAG84G,EAAWj5G,EACvE,CACJ,CACJ,EAEA+uE,SAAU,SAASn3E,GAEf,GAAmB,IAAfA,EAAIkG,OAAc,CAClB9L,KAAKooH,kBAAmB,EACxBpoH,KAAKisH,wBAAyB,EAC9B,MAAMrD,EAAiB,IAAI,GAAEjkH,MAAMiB,EAAIf,cAAe,CAClD1S,KAAM,cACNoC,KAAMqR,EAAIrR,KACV4Q,cAAeS,EAAIT,gBAEvBnF,KAAKksH,yBAAyBtD,GAC1BA,EAAenjH,wBACfG,EAAIC,iBAEZ,MACI7F,KAAKgsH,YAAYpmH,GAAK,SAAS4rE,EAAM5rE,EAAKk6C,EAAG3xC,EAAGH,GAC5CwjE,EAAKuL,SAASn3E,EAAKuI,EAAGH,EAC1B,GAER,EAEAgvE,sBAAuB,SAASp3E,GAE5B5F,KAAKgsH,YAAYpmH,GAAK,SAAS4rE,EAAM5rE,EAAKsuE,EAAQ/lE,EAAGH,GACjDwjE,EAAKwL,sBAAsBp3E,EAAKsuE,EAAQ/lE,EAAGH,EAC/C,GACJ,EAEAivE,kBAAmB,SAASr3E,GACpB5F,KAAK23B,QAAQggF,oBAAoB/xG,EAAID,iBAErC3F,KAAKisH,uBACLjsH,KAAKisH,wBAAyB,EAIlCjsH,KAAKksH,yBAAyBtmH,EAClC,EAEAsmH,yBAA0B,SAAStmH,GAC/B5F,KAAKgsH,YAAYpmH,GAAK,SAAS4rE,EAAM5rE,EAAKsuE,EAAQ/lE,EAAGH,GACjDwjE,EAAKyL,kBAAkBr3E,EAAKsuE,EAAQ/lE,EAAGH,EAC3C,GACJ,EAEAw7F,QAAS,SAAS5jG,GAEd,IAAIgxD,EAAYhxD,EAAIT,cAEhBqsE,EAAOxxE,KAAKyrD,SAASmL,GACzB,IAAK4a,EAAM,OAGX,GADA5rE,EAAMmtC,GAAentC,GACjB5F,KAAKtE,MAAMkK,EAAK4rE,GAAO,OAG3B,MAAMg3C,EAAWxoH,KAAKyoH,mBAAmB7iH,EAAK4rE,EAAM5a,GACpD,GAAI4xD,EAAU,CAEV,GAAIA,EAAS/iH,uBAAwB,OAErCG,EAAIrR,KAAOi0H,EAASj0H,IACxB,CAEA,IAAI0yH,EAAajnH,KAAK+M,WAAWnH,EAAIwzE,QAASxzE,EAAIyzE,SAClD7H,EAAKg4B,QAAQ5jG,EAAKqhH,EAAW94G,EAAG84G,EAAWj5G,EAC/C,EAEA,cAAAm+G,CAAevmH,GACX,MAAMijH,EAAgB91E,GAAentC,IAC/B,EAAEuI,EAAC,EAAEH,GAAMhO,KAAK+M,WAAW87G,EAAczvC,QAASyvC,EAAcxvC,SACtE,MAAO,CAACwvC,EAAe16G,EAAGH,EAC9B,EAEA67F,mBAAoB,SAASr4B,EAAMj9E,GAE/BA,IAASA,EAAO,CAAC,GACjByL,KAAK6uE,UAAU,CAAEt6E,KAAMA,GAAQ,CAAE6oF,WAAY5L,GAAQ,KAAMgF,WAAY,IACvEx2E,KAAK4uE,uBAAuB,KAAMr6E,EACtC,EAIAmH,MAAO,SAASkK,EAAK4rE,GAEjB,GAAiB,cAAb5rE,EAAIzT,MAAuC,IAAfyT,EAAIkG,OAEhC,OAAO,EAGX,GAAI9L,KAAK23B,QAAQj8B,OAASsE,KAAK23B,QAAQj8B,MAAMkK,EAAK4rE,GAC9C,OAAO,EAGX,GAAI5rE,EAAIrR,WAA6B9B,IAArBmT,EAAIrR,KAAK63H,QACrB,OAAOxmH,EAAIrR,KAAK63H,QAGpB,MAAM,OAAElnH,GAAWU,EAEnB,QAAI5F,KAAKu6G,kBAAkBvhH,SAASkM,EAAO42B,YAIvC01C,GAAQA,EAAK7zB,OAAU6zB,EAAK7zB,iBAAiBwI,KAI7CnmD,KAAKqI,KAAOnD,IAAUlF,KAAK2yB,IAAIpqB,SAASrD,EAKhD,EAEAmnH,YAAa,SAASr/G,GAClB,MAAM,QAAE2qB,GAAY33B,KAMpB,OALA23B,EAAQ3qB,SAAWA,EACf2qB,EAAQi+E,WAAaj+E,EAAQu+E,cAE7Bl2G,KAAKuwE,aAAas9B,GAAYC,MAAMgI,aAEjC91G,IACX,EAEA21G,QAAS,SAASC,GAEd,OADA51G,KAAKuwE,aAAas9B,GAAYC,MAAM6H,QAAQC,GACrC51G,IACX,EAEA29G,sBAAuB,SAAStpG,GAI5B,IAAIi4G,GAFJj4G,EAAMA,GAAO,CAAC,GAEeupB,UAAY,SACrC2uF,EAAiBl4G,EAAI7c,MAAQ,YAE7Bg1H,EAAexsH,KAAKuM,QACpBi4G,EAAmBxkH,KAAK6S,YAGxB3gB,GAASo6H,KAGTA,EAFQ9H,EAAiB3uG,GAAM22G,EAAap6G,IAAMk6G,EAAmBn+G,GAAK,GAEjD,OADjBq2G,EAAiB1uG,GAAM02G,EAAan6G,IAAMi6G,EAAmBt+G,GAAK,IACrC,MAIrC9b,GAASq6H,KAETA,GADAA,EAAiB,IAAIz9G,GAAKy9G,GAAgBhgH,MAAMigH,EAAap6G,GAAIo6G,EAAan6G,KAC9C7B,MAAQ,MAAQ+7G,EAAe97G,OAAS,MAG5E,MAAM,WAAE6tD,GAAet+D,KAAK+H,WAC5Bu2D,EAAWrkC,MAAMsyF,eAAiBA,EAClCjuD,EAAWrkC,MAAMqyF,mBAAqBA,CAC1C,EAEAG,oBAAqB,SAASC,EAAKr4G,GAG/B,GAAMq4G,aAAeC,kBAKrB,GAAK3sH,KAAK09G,aAAe19G,KAAK09G,YAAYpoF,KAAOjhB,EAAIihB,GAArD,CAOA,IAAIs3F,EACAL,GAHJl4G,EAAMA,GAAO,CAAC,GAGW7c,KACrBq1H,EAAmBx4G,EAAIy4G,QAAU,YACjCC,EAAoB14G,EAAIyhC,SAAW,EACnCk3E,EAAoBjrH,KAAKoN,IAAIkF,EAAI44G,UAAY,EAC7CC,EAAoBltH,KAAK1N,YAAY66H,mBAAmBxpH,GAAUkpH,IAEtE,GAAI,GAAWK,GAAoB,CAE/BR,EAAIl8G,OAASw8G,EACbN,EAAIj8G,QAAUu8G,EACd,IAAII,EAASF,EAAkBR,EAAKr4G,GACpC,KAAM+4G,aAAkBC,mBACpB,MAAM,IAAIrkH,MAAM,qEAGpB4jH,EAAkBQ,EAAOE,UAAU,aACnCT,EAAmB,SACf36H,GAASq6H,IAETA,EAAe/7G,OAAS48G,EAAO58G,MAAQk8G,EAAIl8G,MAC3C+7G,EAAe97G,QAAU28G,EAAO38G,OAASi8G,EAAIj8G,aACnBhe,IAAnB85H,IAEPl4G,EAAI7c,KAAO,CACPgZ,MAAO48G,EAAO58G,MAAQw8G,EACtBv8G,OAAQ28G,EAAO38G,OAASu8G,GAGpC,MAGIJ,EAAkBF,EAAI9nH,SACCnS,IAAnB85H,IAEAl4G,EAAI7c,KAAO,CACPgZ,MAAOk8G,EAAIl8G,MACXC,OAAQi8G,EAAIj8G,SAKxBzQ,KAAK+H,WAAWu2D,WAAWrkC,MAAM6b,QAAUi3E,EAC3C/sH,KAAK+H,WAAWu2D,WAAWrkC,MAAM4yF,iBAAmBA,EACpD7sH,KAAK+H,WAAWu2D,WAAWrkC,MAAM2yF,gBAAkB,OAAOA,KAE1D5sH,KAAK29G,sBAAsBtpG,EAlD3B,OAPIrU,KAAK+H,WAAWu2D,WAAWrkC,MAAM2yF,gBAAkB,EA0D3D,EAEAW,sBAAuB,SAASv0E,GAE5Bh5C,KAAK0tC,IAAIlB,IAAI,kBAAmBwM,GAAS,GAC7C,EAEA+jE,eAAgB,SAAS1oG,GAMrB,GAJAA,EAAMA,GAAO,CAAC,EAEdrU,KAAKutH,sBAAsBl5G,EAAI2kC,OAE3B3kC,EAAI8pD,MAAO,CACX9pD,EAAMrU,KAAK09G,YAAcr7G,GAAUgS,GACnC3N,GAAK2N,GACL,IAAIq4G,EAAMvmH,SAASkB,cAAc,OACjCqlH,EAAIc,OAASxtH,KAAKysH,oBAAoB18H,KAAKiQ,KAAM0sH,EAAKr4G,GACtDq4G,EAAI9nH,IAAMyP,EAAI8pD,KAClB,MACIn+D,KAAKysH,oBAAoB,MACzBzsH,KAAK09G,YAAc,KAGvB,OAAO19G,IACX,EAEAw9E,iBAAkB,SAAS7xF,GAEvBqU,KAAK23B,QAAQi8C,YAAcjoF,EAE3ByV,GAAOpB,KAAKqxE,OAAQ,mBAAoB1lF,EAC5C,EAKA8hI,UAAW,SAASC,GAEhB,QAAS1tH,KAAK2yB,IAAIzpB,eAAewkH,EACrC,EAEAloE,aAAc,SAASzxD,GAEnB,IAAK7B,GAAS6B,GACV,MAAM,IAAI2oD,UAAU,mEAGxB,IAAIixE,EAAW55H,EAAOuhC,GAClBn+B,EAAOpD,EAAOoD,KASlB,GANKw2H,IACDA,EAAWx2H,EAAO6I,KAAK2yB,IAAI2C,GAAKid,GAAS5L,KAAKC,UAAU7yC,MAKvDiM,KAAKytH,UAAUE,GAAW,CAE3B,IAAIhjH,EAAY,GACZijH,EAAkBjjH,EAAUxT,IAASwT,EAAUxT,GAAMpD,EAAOkN,MAAQ,CAAC,GACzE,IAAK2sH,EACD,MAAM,IAAI5kH,MAAM,uBAAyB7R,GAI7C,IAAI02H,EAAc,GAAO,CACrBC,YAAa,kBACd/5H,EAAOm/B,MAAO,CACboC,GAAIq4F,IAGR,GAAEC,EAAiBC,GAAaz0F,SAASp5B,KAAKq5B,KAClD,CAEA,OAAOs0F,CACX,EAEAroE,eAAgB,SAASyoE,GACrB,IAAK77H,GAAS67H,GACV,MAAM,IAAIrxE,UAAU,qEAExB,MAAM,IAAE/pB,EAAG,KAAE0G,GAASr5B,MAChB,KACF7N,EAAI,GAGJmjC,EAAKnjC,EAAOwgC,EAAI2C,GAAKid,GAAS5L,KAAKC,UAAUmnF,IAAU,MACvDC,EAAK,MACL96F,EAAQ,CAAC,GACT66F,EAGJ,GAAI/tH,KAAKytH,UAAUn4F,GAAK,OAAOA,EAE/B,MAAM24F,EAAWvrH,GAAQsrH,GAAOr9H,KAAI,EAAG0gB,SAAQ2nC,QAAOlD,aAC3C,GAAE,QAAQ5gB,KAAK,CAClB,OAAU7jB,EACV,aAAc2nC,EACd,eAAgB/9C,OAAOm6B,SAAS0gB,GAAWA,EAAU,MAGvDo4E,EAAc,GAAE/7H,EAAM+gC,EAAO+6F,GAGnC,OAFAC,EAAY54F,GAAKA,EACjB44F,EAAY90F,SAASC,GACd/D,CACX,EAEA+vB,cAAe,SAASzhD,GACpB,IAAK1R,GAAS0R,GACV,MAAM,IAAI84C,UAAU,oEAExB,MAAM,IAAE/pB,EAAG,KAAE0G,GAASr5B,MAChB,GAGFs1B,EAAK3C,EAAI2C,GAAKid,GAAS5L,KAAKC,UAAUhjC,IAAS,OAC/CstD,EAAM,MACNh+B,EAAQ,CAAC,GACTtvB,EACJ,IAAKstD,EACD,MAAM,IAAIxU,UAAU,+CAIxB,GAAI18C,KAAKytH,UAAUn4F,GAAK,OAAOA,EAE/B,MAAMyhF,EAAa,GAAE,UAAW,CAC5BP,aAAc,mBAIlB,GAFAO,EAAWzhF,GAAKA,EAChByhF,EAAW7hF,KAAKhC,GACM,iBAAXg+B,EACP6lD,EAAWjjF,OAAO,GAAEo9B,QACjB,CACH,MAAM,SAAExf,GAAaL,GAAa6f,GAClC6lD,EAAWjjF,OAAO4d,EACtB,CAEA,OADAqlE,EAAW39E,SAASC,GACb/D,CACX,EAEAiwB,aAAc,SAASN,GACnB,IAAK/yD,GAAS+yD,GACV,MAAM,IAAIvI,UAAU,0EAExB,MAAM,IAAE/pB,EAAG,KAAE0G,GAASr5B,MAChB,GAGFs1B,EAAK3C,EAAI2C,GAAKid,GAAS5L,KAAKC,UAAUqe,IAAQ,OAG9CiM,EAAM,MAINh+B,EAAQ,CAAC,EAAC,YAEVi7F,EAAc,kBACdlpE,EAGJ,GAAIjlD,KAAKytH,UAAUn4F,GAAK,OAAOA,EAE/B,MAAM84F,EAAY,GAAE,SAAU,CAC1BC,OAAQ,OACRzU,SAAU,UACVuU,YAAaA,IAIjB,IAAIG,EACJ,GAHAF,EAAU94F,GAAKA,EACf84F,EAAUl5F,KAAKhC,GAEXg+B,EAAQ,CACR,IAAIq9D,EACJ,GAAsB,iBAAXr9D,EAGPq9D,EAAY,GAAEr9D,GAGdq9D,EAAav9H,MAAMC,QAAQs9H,GAAaA,EAAY,CAACA,OAClD,CAGH,MAAM,SAAE78E,GAAaL,GAAa6f,GAClCq9D,EAAY,GAAE78E,GAAUve,UAC5B,CAIIm7F,EADAC,EAAU/8H,OAAS,EACA,GAAE,KAAKsiC,OAAOy6F,GAEdA,EAAU,EAErC,KAAO,CAGH,MAAM,KAAEp8H,EAAO,QAAW8yD,EAC1BqpE,EAAmB,GAAEn8H,EACzB,CAIA,MAAMq8H,EAAc,GAAKvpE,EAAQ,OAAQ,KAAM,SAAU,QAAS,eAoBlE,OAnBwBj6D,OAAO0F,KAAK89H,GACpB72H,SAAS7M,IACrB,MAAMa,EAAQ6iI,EAAY1jI,GACpB2jI,EAAcH,EAAiBp5F,KAAKpqC,GACvB,MAAf2jI,EAEAH,EAAiBp5F,KAAKpqC,EAAKa,GAIlB,cADFb,GAGCwjI,EAAiBp5F,KAAKpqC,EAAMa,EAAQ,IAAM8iI,EAGtD,IAEJH,EAAiBl1F,SAASg1F,GAC1BA,EAAUh1F,SAASC,GACZ/D,CACX,EAEAmzF,mBAAoB,SAAS7iH,EAAK4rE,EAAM+C,EAAW/C,EAAKnpE,IAEpD,MAAM0jH,EAAYnmH,EAAIV,OAAO+K,QAAQ,WAErC,GAAI87G,GAAax3C,IAAaw3C,GAAav6C,EAAKnpE,GAAGE,SAASwjH,GAAY,CACpE,MAAMvD,EAAWz1E,GAAe,IAAI,GAAEpuC,MAAMiB,EAAIf,cAAe,CAC3DtQ,KAAMqR,EAAIrR,KAEV4Q,cAAe4mH,KASnB,OANA/rH,KAAK88E,QAAQ0rC,GAETA,EAAS1jH,sBACTc,EAAID,iBAGD6iH,CACX,CAEA,OAAO,IACX,GAED,CAEC5P,QAAS3B,GAETyX,OAAQ7gB,GAERsf,mBAAoB,CAEhBwB,OAAQ,SAASjC,GAIb,IAAIU,EAASjnH,SAASkB,cAAc,UAChCunH,EAAWlC,EAAIl8G,MACfq+G,EAAYnC,EAAIj8G,OAEpB28G,EAAO58G,MAAQ,EAAIo+G,EACnBxB,EAAO38G,OAAS,EAAIo+G,EAEpB,IAAI1zE,EAAMiyE,EAAO0B,WAAW,MAa5B,OAXA3zE,EAAI4zE,UAAUrC,EAAK,EAAG,EAAGkC,EAAUC,GAEnC1zE,EAAI6zE,cAAc,EAAG,EAAG,GAAI,EAAG5B,EAAO58G,MAAO48G,EAAO38G,QACpD0qC,EAAI4zE,UAAUrC,EAAK,EAAG,EAAGkC,EAAUC,GAEnC1zE,EAAI6zE,cAAc,EAAG,EAAG,EAAG,EAAG5B,EAAO58G,MAAO,GAC5C2qC,EAAI4zE,UAAUrC,EAAK,EAAG,EAAGkC,EAAUC,GAEnC1zE,EAAI6zE,aAAa,EAAG,EAAG,GAAI,EAAG,EAAG5B,EAAO38G,QACxC0qC,EAAI4zE,UAAUrC,EAAK,EAAG,EAAGkC,EAAUC,GAE5BzB,CACX,EAEA6B,MAAO,SAASvC,GAIZ,IAAIU,EAASjnH,SAASkB,cAAc,UAChCunH,EAAWlC,EAAIl8G,MACfq+G,EAAYnC,EAAIj8G,OAEpB28G,EAAO58G,MAAmB,EAAXo+G,EACfxB,EAAO38G,OAASo+G,EAEhB,IAAI1zE,EAAMiyE,EAAO0B,WAAW,MAQ5B,OANA3zE,EAAI4zE,UAAUrC,EAAK,EAAG,EAAGkC,EAAUC,GAEnC1zE,EAAItoC,UAAU,EAAI+7G,EAAU,GAC5BzzE,EAAI5uC,OAAO,EAAG,GACd4uC,EAAI4zE,UAAUrC,EAAK,EAAG,EAAGkC,EAAUC,GAE5BzB,CACX,EAEA8B,MAAO,SAASxC,GAIZ,IAAIU,EAASjnH,SAASkB,cAAc,UAChCunH,EAAWlC,EAAIl8G,MACfq+G,EAAYnC,EAAIj8G,OAEpB28G,EAAO58G,MAAQo+G,EACfxB,EAAO38G,OAAqB,EAAZo+G,EAEhB,IAAI1zE,EAAMiyE,EAAO0B,WAAW,MAQ5B,OANA3zE,EAAI4zE,UAAUrC,EAAK,EAAG,EAAGkC,EAAUC,GAEnC1zE,EAAItoC,UAAU,EAAG,EAAIg8G,GACrB1zE,EAAI5uC,MAAM,GAAI,GACd4uC,EAAI4zE,UAAUrC,EAAK,EAAG,EAAGkC,EAAUC,GAE5BzB,CACX,EAEA+B,UAAW,SAASzC,EAAKr4G,GAIrBA,EAAMA,GAAO,CAAC,EAEd,IAAIu6G,EAAWlC,EAAIl8G,MACfq+G,EAAYnC,EAAIj8G,OAEhB28G,EAASjnH,SAASkB,cAAc,UACpC+lH,EAAO58G,MAAmB,EAAXo+G,EACfxB,EAAO38G,OAAqB,EAAZo+G,EAQhB,IANA,IAAI1zE,EAAMiyE,EAAO0B,WAAW,MACxBhiH,EAAQnM,GAAS0T,EAAI+6G,iBAAmB/6G,EAAI+6G,gBAAkB,GAC9D1rC,EAAUv2E,GAAML,GAChBuiH,EAAQjC,EAAO58G,MAAQ,EACvB8+G,EAAQlC,EAAO38G,OAAS,EAEnB3J,EAAI,EAAGA,EAAI,EAAGA,IACnB,IAAK,IAAIC,EAAI,EAAGA,EAAI,EAAGA,KACdD,EAAIC,GAAK,EAAI,IAEdo0C,EAAI6zE,aAAa,EAAG,EAAG,EAAG,GAAI,EAAIloH,EAAI,GAAKuoH,GAAQ,EAAItoH,EAAI,GAAKuoH,GAChEn0E,EAAIppC,OAAO2xE,GACXvoC,EAAI4zE,UAAUrC,GAAMkC,EAAW,GAAIC,EAAY,EAAGD,EAAUC,IAKxE,OAAOzB,CACX,GAGJnQ,aAAc,CACV1rG,IAAK,CAAC,CACFynC,MAAO,UACPu2E,UAAW,EACXr+D,OAAQ,OACRua,OAAQ,SAASpjE,EAAIgM,GACjB,GAAEhM,GAAI6sB,KAAK,CACP1kB,MAAO6D,EAAIk7G,UACX9+G,OAAQ4D,EAAIk7G,UACZr1D,KAAM7lD,EAAI2kC,OAElB,IAEJw2E,SAAU,CAAC,CACPx2E,MAAO,UACPu2E,UAAW,EACXr+D,OAAQ,OACRua,OAAQ,SAASpjE,EAAIgM,GACjB,GAAEhM,GAAI6sB,KAAK,CAAEglC,KAAM7lD,EAAI2kC,OAC3B,EACArmC,OAAQ,SAAStK,EAAIgM,EAAKivC,GACtB,MAAM,GAAElxC,EAAE,GAAEC,GAAOixC,EAAM/2C,QACnBiE,EAAQ4B,GAAM,EAAIiC,EAAIk7G,UAAYl7G,EAAIk7G,UAAYn9G,EAClD3B,EAAS4B,GAAM,EAAIgC,EAAIk7G,UAAYl7G,EAAIk7G,UAAYl9G,EACzD,GAAEhK,GAAI6sB,KAAK,CAAE1kB,QAAOC,UACxB,IAEJg/G,KAAM,CAAC,CACHz2E,MAAO,UACPu2E,UAAW,EACXr+D,OAAQ,OACRua,OAAQ,SAASpjE,EAAIgM,GAEjB,IAAIyC,EACAtG,EAAQ6D,EAAI7D,MACZC,EAAS4D,EAAI5D,OACb8+G,EAAYl7G,EAAIk7G,UAGhBz4G,EADAtG,EAAQ++G,GAAa,GAAK9+G,EAAS8+G,GAAa,EAC5C,CAAC,IAAK/+G,EAAO,EAAG,aAAcC,GAAQ3hB,KAAK,KAE3C,YAGR,GAAEuZ,GAAI6sB,KAAK,CAAE,EAAKpe,EAAGouC,OAAQ7wC,EAAI2kC,MAAO,eAAgB3kC,EAAIk7G,WAChE,IAEJG,WAAY,CAAC,CACT12E,MAAO,UACPu2E,UAAW,EACXr+D,OAAQ,OACRua,OAAQ,SAASpjE,EAAIgM,GAEjB,IAAIyC,EACAtG,EAAQ6D,EAAI7D,MACZC,EAAS4D,EAAI5D,OACb8+G,EAAYl7G,EAAIk7G,UAGhBz4G,EADAtG,EAAQ++G,GAAa,GAAK9+G,EAAS8+G,GAAa,EAC5C,CAAC,IAAK/+G,EAAO,EAAG,aAAcC,GAAQ3hB,KAAK,KAE3C,YAGR,GAAEuZ,GAAI6sB,KAAK,CAAE,EAAKpe,EAAGouC,OAAQ7wC,EAAI2kC,MAAO,eAAgB3kC,EAAIk7G,WAChE,GACD,CACCv2E,MAAO,UACPu2E,UAAW,EACX95G,YAAa,EACby7C,OAAQ,OACRua,OAAQ,SAASpjE,EAAIgM,GAEjB,IAAIyC,EACAtG,EAAQ6D,EAAI7D,MACZC,EAAS4D,EAAI5D,OACb8+G,EAAYl7G,EAAIk7G,UAGhBz4G,EADAtG,EAAQ++G,GAAa,GAAK9+G,EAAS8+G,GAAa,EAC5C,CAAC,IAAK/+G,EAAO,EAAG,aAAcC,GAAQ3hB,KAAK,KAE3C,YAGR,GAAEuZ,GAAI6sB,KAAK,CAAE,EAAKpe,EAAGouC,OAAQ7wC,EAAI2kC,MAAO,eAAgB3kC,EAAIk7G,WAChE,OClrGCI,GAAW,GAAS9vG,OAAO,CACpC1oB,KAAM,KACN2kC,QAAS,IACTtB,UAAW,OACX0yC,YAAY,EACZ0iD,UAAU,EACVC,kBAAkB,EAElB7iD,KAAM,WACF,IAAI71E,EAAO6I,KAAK7I,KACZA,GAAM6I,KAAKi5B,IAAI/D,KAAK,iBAAkB/9B,EAC9C,EAEAqkF,UAAW,SAAShK,EAAM6J,GAOtB,OANAr7E,KAAKy7E,YAAcjK,EACnBxxE,KAAKsjD,MAAQkuB,EAAKluB,MAClBtjD,KAAKw4G,WAAan9B,EAClBr7E,KAAK8vH,oBAAoB9vH,KAAKqI,IAE9BrI,KAAK8rE,iBACE9rE,IACX,EAEA8vH,oBAAqB,SAASznH,GACtBA,GAAIA,EAAGkyB,aAAa,WAAYv6B,KAAKy7E,YAAY99B,MAAMroB,GAC/D,EAEAgmD,QAAS,WACL,OAAOt7E,KAAK7I,IAChB,EAGA44H,iBAAkB,WACd,MAAMhpG,EAAY/mB,KAAKgwH,oBACvBhwH,KAAKqI,GAAG4xB,MAAM8b,QAAUhvB,EAAY,GAAK,OACzC/mB,KAAK4vH,SAAW7oG,CACpB,EAIA,iBAAAipG,GACI,IAAKhwH,KAAKiwH,sBAAuB,OAAO,EACxC,MAAM,WAAEC,GAAelwH,KAAK23B,QAC5B,MAA0B,mBAAfu4F,KACFA,EAAW1kI,KAAKwU,KAAMA,KAAKy7E,YAAaz7E,KACrD,EAEA+7E,KAAM,WACF/7E,KAAK6vH,kBAAmB,EACxB7vH,KAAK+vH,kBACT,EAEAl0C,KAAM,WACF77E,KAAK6vH,kBAAmB,EACxB7vH,KAAK+vH,kBACT,EAGAE,oBAAqB,WACjB,QAASjwH,KAAK6vH,gBAClB,EAKA9oG,UAAW,WACP,QAAS/mB,KAAK4vH,QAClB,EAEAO,MAAO,WACH,IAAIr6E,EAAU91C,KAAK23B,QAAQy4F,aACvBh7F,SAAS0gB,KAAU91C,KAAKqI,GAAG4xB,MAAM6b,QAAUA,GAC/C91C,KAAKw4G,WAAW6X,UAAUrwH,KAC9B,EAEAk5C,KAAM,WACFl5C,KAAKqI,GAAG4xB,MAAM6b,QAAU,GACxB91C,KAAKw4G,WAAW8X,SAAStwH,KAC7B,EAEA2S,OAAQ,WAER,EAEAjX,MAAO,SAASkK,GAEZ,MAAM,MAAE09C,EAAK,YAAEm4B,GAAgBz7E,KAC/B,OAAKsjD,IAAUm4B,GACRn4B,EAAM5nD,MAAMkK,EAAK61E,EAC5B,ICnFJ,IAAI80C,GAAe,GAAS1wG,OAAO,CAC/Bic,QAAS,SACToxC,YAAY,EACZ1yC,UAAW,gBACXjxB,OAAQ,CACJinH,UAAW,gBACXC,WAAY,gBACZC,SAAU,gBACV7/E,OAAQ,iBAEZgpE,eAAgB,CACZ8W,UAAW,gBACXC,UAAW,gBACXC,QAAS,cACTC,SAAU,cACVC,YAAa,eAEjBr1F,WAAY,CACR,EAAK,EACL,KAAQ,UACR,OAAU,UACV,eAAgB,EAChB,OAAU,QAEdkC,SAAU,SAASzvB,EAAGH,GAClB,MAAM,IAAEirB,EAAG,QAAEtB,GAAY33B,MACnB,MAAEuM,GAAUorB,EAClB,IAAI1B,EAAS,GAAEF,kBAAkBljB,UAAU1E,EAAGH,GAC1CzB,IAAO0pB,EAASA,EAAO1pB,MAAMA,IACjC0sB,EAAIjD,UAAUC,EAAQ,CAAEG,UAAU,GACtC,EACA46F,cAAe,SAASprH,GAChB5F,KAAK23B,QAAQj8B,MAAMkK,KACvBA,EAAIC,kBACJD,EAAID,iBACJ3F,KAAK23B,QAAQ2rB,MAAMsoB,mBACnB5rE,KAAK4uE,uBAAuB,KAAMhpE,EAAIrR,MACtCyL,KAAK28C,QAAQ,cAAe38C,KAAM4F,GACtC,EACAqrH,cAAe,SAASrrH,GACpB5F,KAAK28C,QAAQ,WAAY38C,KAAM4F,EACnC,EACAsrH,cAAe,SAAStrH,GACpB5F,KAAK28C,QAAQ,SAAU38C,KAAM4F,EACjC,EACAurH,YAAa,SAASvrH,GAClB5F,KAAK28C,QAAQ,UAAW38C,KAAM4F,GAC9B5F,KAAKuuE,2BACLvuE,KAAK23B,QAAQ2rB,MAAMwoB,gBACvB,IAGG,MAAMslD,GAAWzB,GAAS9vG,OAAO,CACpC1oB,KAAM,WACNwgC,QAAS,CACL05F,YAAad,GACbe,WAAY,GACZC,mBAAmB,EACnBC,cAAc,EAGd3rH,iBAAiB,EACjB0G,MAAO,MAEX4mB,SAAU,CAAC,CACP2I,QAAS,OACTv1B,SAAU,aACVi0B,UAAW,sBACXkB,WAAY,CACR,KAAQ,OACR,OAAU,cACV,eAAgB,GAChB,OAAU,UAGlB+1F,QAAS,KACTC,oBAAqB,KACrBnoH,OAAQ,CACJ,iCAAkC,oBAClC,kCAAmC,qBAEvCooH,WAAY,CACRnB,UAAW,oBACXC,WAAY,qBAEhB3iD,SAAU,WACN,MAAM,aAAE0jD,GAAiBxxH,KAAK23B,QAC9B,GAAI65F,EAAc,CACd,MAAM,oBAAEE,EAAsB,MAASF,EACnCE,EACA1xH,KAAK4xH,mBAAmBF,IAExB1xH,KAAKotE,iBACLptE,KAAKg/F,aAEb,CAGA,OAFAh/F,KAAK6xH,eACL7xH,KAAK8xH,gBACE9xH,IACX,EACA4xH,mBAAoB,SAASrrH,GACzBvG,KAAK+xH,uBACL,MAAM1pH,EAAKrI,KAAKy7E,YAAYz4B,SAASz8C,GAChC8B,GAILA,EAAGi3B,UAAU1kC,IAAI,uBACjBoF,KAAK0xH,oBAAsBrpH,EAC3BrI,KAAKyuE,sBAAsBpmE,EAAIrI,KAAK2xH,aALhC/lG,QAAQC,KAAK,0BAA0BtlB,gBAM/C,EACAwrH,qBAAsB,WAClB,MAAM1pH,EAAKrI,KAAK0xH,oBACXrpH,IACLrI,KAAK2uE,wBAAwBtmE,GAC7BA,EAAGi3B,UAAU/6B,OAAO,uBACpBvE,KAAK0xH,oBAAsB,KAC/B,EACA/+G,OAAQ,WAYJ,OAXkB3S,KAAKy7E,YACI99B,MAAMyd,WACpB5pE,SAAWwO,KAAKyxH,QAAQjgI,OACjCwO,KAAKgyH,iBAELhyH,KAAK6xH,eACL7xH,KAAK8xH,iBAEL9xH,KAAK23B,QAAQ65F,cACbxxH,KAAKg/F,aAEFh/F,IACX,EACA6xH,aAAc,WACV,IAAIJ,EAAUzxH,KAAKyxH,QAGnB,GAFAzxH,KAAKyxH,QAAU,GACfzxH,KAAKg8C,gBACAhrD,MAAMC,QAAQwgI,GACnB,IAAK,IAAI3qH,EAAI,EAAGkJ,EAAIyhH,EAAQjgI,OAAQsV,EAAIkJ,EAAGlJ,IACvC2qH,EAAQ3qH,GAAGvC,QAEnB,EACAutH,cAAe,WAGX,IAFA,IACI12D,EADcp7D,KAAKy7E,YACI99B,MAAMyd,WACxBt0D,EAAI,EAAGkJ,EAAIorD,EAAS5pE,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAC7C,IAAIq0D,EAASC,EAASt0D,GAClBmD,EAAS,IAAKjK,KAAK23B,QAAmB,YAAE,CACxCjmC,MAAOoV,EACPw8C,MAAOtjD,KAAKsjD,MACZ/2C,MAAOvM,KAAK23B,QAAQprB,MACpB7Q,MAAOkK,GAAO5F,KAAKtE,MAAMkK,KAE7BqE,EAAOwhE,SACPxhE,EAAO2zB,SAASu9B,EAAOhtD,EAAGgtD,EAAOntD,GACjChO,KAAK8vH,oBAAoB7lH,EAAO5B,IAChC4B,EAAOgvB,IAAIG,SAASp5B,KAAKqI,IACzBrI,KAAKyxH,QAAQ7/H,KAAKqY,GAClBjK,KAAKiyH,qBAAqBhoH,EAC9B,CACJ,EACA+nH,cAAe,WAGX,IAFA,IACI52D,EADcp7D,KAAKy7E,YACI99B,MAAMyd,WACxBt0D,EAAI,EAAGkJ,EAAIorD,EAAS5pE,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAC7C,IAAIq0D,EAASC,EAASt0D,GAClBmD,EAASjK,KAAKyxH,QAAQ3qH,GAC1B,IAAKmD,EAAQ,OACbA,EAAO2zB,SAASu9B,EAAOhtD,EAAGgtD,EAAOntD,EACrC,CACJ,EACAgxF,WAAY,WACR,GAAIh/F,KAAK0xH,oBAAqB,OAC9B,MAAM1rE,EAAahmD,KAAK+H,WAAWi+C,WAC/BA,GAAYA,EAAWzrB,aAAa,IAAKv6B,KAAKy7E,YAAYp3B,0BAClE,EACA4tE,qBAAsB,SAAShoH,GAC3B,MAAM,eAAEioH,GAAiB,EAAI,aAAEC,GAAe,GAASnyH,KAAK23B,QACxDw6F,IACAnyH,KAAKu7C,SAAStxC,EAAQ,cAAejK,KAAKoyH,oBAC1CpyH,KAAKu7C,SAAStxC,EAAQ,WAAYjK,KAAKqyH,kBACvCryH,KAAKu7C,SAAStxC,EAAQ,UAAWjK,KAAKsyH,kBAEtCJ,GACAlyH,KAAKu7C,SAAStxC,EAAQ,SAAUjK,KAAKuyH,eAE7C,EACAC,kBAAmB,SAAS9gI,GACxB,IAAIqkF,EAAW/1E,KAAKy7E,YAChBrgB,EAAW2a,EAASp4B,MAAMyd,WAC1B30B,EAAQ/0C,EAAQ,EAAK0pE,EAAS1pE,EAAQ,GAAKqkF,EAASyP,aACpD5iF,EAAQlR,EAAQ0pE,EAAS5pE,OAAS,EAAK4pE,EAAS1pE,EAAQ,GAAKqkF,EAAS2P,aAC1E,MAAO,CACHj/C,KAAM,IAAI,GAAQA,GAClB7jC,KAAM,IAAI,GAAQA,GAE1B,EACAwvH,mBAAoB,SAASK,EAAS7sH,GAClC5F,KAAKmwH,QACL,MAAM,YAAE10C,EAAW,QAAE9jD,GAAY33B,KACjCy7E,EAAY99B,MAAM2J,WAAW,cAAe,CAAEkuB,IAAI,EAAMhC,KAAMxzE,KAAK+9C,MAC9DpmB,EAAQ9xB,iBAAiB41E,EAAYzF,qBAAqByF,EAAYn4B,MAAM6oE,eAAevmH,GACpG,EACAysH,iBAAkB,SAASpoH,EAAQrE,GAC/B,MAAM,QAAE+xB,EAAS8jD,YAAa1F,GAAa/1E,KAC3C,IAAItO,EAAQuY,EAAO0tB,QAAQjmC,OACtBghI,EAAiBvkH,EAAGH,GAAK+nE,EAASzyB,MAAM6oE,eAAevmH,GACxDu1D,EAAS,CAAEhtD,IAAGH,KAClBhO,KAAK2yH,WAAWx3D,EAAQzpE,GACxBqkF,EAASp4B,MAAMwd,OAAOzpE,EAAOypE,EAAQ,CAAEqa,IAAI,EAAMhC,KAAMxzE,KAAK+9C,MAC5D9zC,EAAO2zB,SAASu9B,EAAOhtD,EAAGgtD,EAAOntD,GAC5B2pB,EAAQ9xB,iBAAiBkwE,EAASwL,kBAAkBmxC,EAAiBvkH,EAAGH,EACjF,EACAskH,gBAAiB,SAASG,EAAS7sH,GAC/B,MAAM,QAAE+xB,EAAS8jD,YAAa1F,GAAa/1E,KAE3C,GADI23B,EAAQ65F,cAAcxxH,KAAKg/F,aAC1BrnE,EAAQ45F,kBAAb,CAIsBx7C,EAASsrB,8BAA8B,CAAE7rB,IAAI,EAAMhC,KAAMxzE,KAAK+9C,OAC/D/9C,KAAKyrE,SAC1BzrE,KAAKk5C,OACL68B,EAASp4B,MAAMiK,UAAU,cAAe,CAAE4tB,IAAI,EAAMhC,KAAMxzE,KAAK+9C,MAC3D/9C,KAAK6uE,UAAUjpE,GAAKgtH,aACpB78C,EAASp4B,MAAMiK,UAAU,aAAc,CAAE4tB,IAAI,EAAMhC,KAAMxzE,KAAK+9C,MAElE,IAAK8qE,EAAe16G,EAAGH,GAAK+nE,EAASzyB,MAAM6oE,eAAevmH,GACrD+xB,EAAQ9xB,iBAAiBkwE,EAASyL,gBAAgBqnC,EAAe16G,EAAGH,GACzE+nE,EAASmH,gBAAgB2rC,EAVzB,MAFI9yC,EAASmH,gBAAgB,GAAoBt3E,GAarD,EACA+sH,WAAY,SAASx3D,EAAQzpE,GACzB,IAAI4/H,EAAatxH,KAAK23B,QAAQ25F,WAC9B,GAAIA,EAAa,EAAG,CAChB,IAAI/pD,EAAYvnE,KAAKwyH,kBAAkB9gI,GACnC+0C,EAAO8gC,EAAU9gC,KACjB7jC,EAAO2kE,EAAU3kE,KACjBb,KAAKoN,IAAIgsD,EAAOhtD,EAAIs4B,EAAKt4B,GAAKmjH,EAC9Bn2D,EAAOhtD,EAAIs4B,EAAKt4B,EACTpM,KAAKoN,IAAIgsD,EAAOhtD,EAAIvL,EAAKuL,GAAKmjH,IACrCn2D,EAAOhtD,EAAIvL,EAAKuL,GAEhBpM,KAAKoN,IAAIgsD,EAAOntD,EAAIy4B,EAAKz4B,GAAKsjH,EAC9Bn2D,EAAOntD,EAAIu5D,EAAU9gC,KAAKz4B,EACnBjM,KAAKoN,IAAIgsD,EAAOntD,EAAIpL,EAAKoL,GAAKsjH,IACrCn2D,EAAOntD,EAAIpL,EAAKoL,EAExB,CACJ,EACAukH,eAAgB,SAAStoH,EAAQrE,GAC7B,IAAIlU,EAAQuY,EAAO0tB,QAAQjmC,MACvBqkF,EAAW/1E,KAAKy7E,YACpB1F,EAASp4B,MAAM8d,aAAa/pE,EAAO,CAAE8jF,IAAI,IACrCx1E,KAAK23B,QAAQ65F,cAAcxxH,KAAKg/F,aACpCjpB,EAASmH,gBAAgB,GAAoBt3E,GACjD,EACAitH,kBAAmB,SAASjtH,GACxB,IAAI5F,KAAKtE,MAAMkK,GAAf,CACAA,EAAIC,kBACJD,EAAID,iBACJ,IAAI+sH,EAAkB,GAAoB9sH,GACtCu1D,EAASn7D,KAAKsjD,MAAMv2C,WAAW2lH,EAAgBt5C,QAASs5C,EAAgBr5C,SAAS7mE,SACjFipE,EAAcz7E,KAAKy7E,YACvBA,EAAY99B,MAAM2J,WAAW,aAAc,CAAEkuB,IAAI,EAAMhC,KAAMxzE,KAAK+9C,MAClE,IAAIrsD,EAAQ+pF,EAAYirB,eAAevrC,EAAOhtD,EAAGgtD,EAAOntD,GACxDhO,KAAK2yH,WAAWx3D,EAAQzpE,GACxB+pF,EAAY99B,MAAM6d,aAAa9pE,EAAOypE,EAAQ,CAAEqa,IAAI,EAAMhC,KAAMxzE,KAAK+9C,MACrE/9C,KAAK2S,SACL,IAAI1I,EAASjK,KAAKyxH,QAAQ//H,GAC1BsO,KAAK6uE,UAAU6jD,EAAiB,CAAEE,aAAa,IAC/C3oH,EAAO+mH,cAAc0B,EAbM,CAc/B,EACAI,kBAAmB,SAASltH,GACxB5F,KAAKy7E,YAAYS,0BAA0Bt2E,GAC3C5F,KAAK6yH,kBAAkBjtH,EAC3B,EACA0oE,SAAU,WACNtuE,KAAK6xH,eACL7xH,KAAK+xH,sBACT,GACD,CACCxB,aAAcA,KC9RlB,SAASwC,GAAQ38F,EAAU7oB,GAEvB,OAAY,IAARA,EAAkB,KAGLxL,KAAKsK,MAAM+pB,EAAW7oB,EAAM,IADlC,SAEJ,GACX,CAEA,SAASylH,GAAIC,GAET,OAAO,SAASpzH,EAAK2xE,EAAM0C,EAAQ73D,GAE/B,OADUm1D,EAAKkH,iBAAiBxE,GAAWg/C,GAAgBC,IACjDF,EAAUpzH,EAAK2xE,EAAM0C,EAAQ73D,EAC3C,CACJ,CAEA,SAAS82G,GAAiBF,EAAUpzH,EAAK2xE,EAAM0C,EAAQ73D,GAEnD,IAAIvP,EAAQ0kE,EAAK7zB,MAAM7wC,QACnBiG,EAAOy+D,EAAK6C,qBAAqBH,GACjCzkE,EAAS+hE,EAAK7zB,MAAMvmB,UAAUlhB,SAClCmG,EAAOtK,OAAOtC,EAAQ3C,GACtB,IAAIoE,EAAKmL,EAAOlO,EAAI4E,EAAK5E,EACrBgD,EAAKkL,EAAOrO,EAAI+E,EAAK/E,EAgBzB,OAdIilH,IACA/hH,EAAK6hH,GAAQ7hH,EAAI6B,EAAKvC,OACtBW,EAAK4hH,GAAQ5hH,EAAI4B,EAAKtC,SAG1B5Q,EAAIupF,OAAS,CACTjyF,KAAM,UACN8J,KAAM,CACFiQ,GAAIA,EACJC,GAAIA,EACJY,QAAQ,IAITlS,CACX,CAEA,SAASqzH,GAAcD,EAAUpzH,EAAK2xE,EAAMkhC,EAASr2F,GAEjD,IAAI2pC,EAAawrB,EAAKvtB,gBACtB,IAAK+B,EAAY,OAAOnmD,EACxB,IAAIrO,EAASw0D,EAAWzyC,mBAAmB8I,GAC3C,GAAI42G,EAAU,CACV,IAAIG,EAAcptE,EAAWx0D,SAC7BqO,EAAIupF,OAAS,CACTjyF,KAAM,kBACN8J,KAAM,CACF6S,MAAOtiB,EAAS4hI,GAG5B,MACIvzH,EAAIupF,OAAS,CACTjyF,KAAM,mBACN8J,KAAM,CACFzP,OAAQA,IAIpB,OAAOqO,CACX,CAG2BmzH,IAAI,GADxB,MAEMK,GAAcL,IAAI,GChE/B,IAAIM,GAAgB,GAASzzG,OAAO,CAChCic,QAAS,IACToxC,YAAY,EACZ1yC,UAAW,iBACXjxB,OAAQ,CACJinH,UAAW,gBACXC,WAAY,iBAEhB5W,eAAgB,CACZ8W,UAAW,gBACXC,UAAW,gBACXC,QAAS,cACTC,SAAU,cACVC,YAAa,eAEjB59F,SAAU,CAAC,CACP2I,QAAS,OACTv1B,SAAU,OACVm1B,WAAY,CACR,OAAU,UACV,eAAgB,EAChB,KAAQ,OACR,iBAAkB,SAEvB,CACCI,QAAS,OACTv1B,SAAU,SACVm1B,WAAY,CACR,MAAS,GACT,OAAU,EACV,GAAM,GACN,GAAM,EACN,GAAM,EACN,GAAM,EACN,KAAQ,UACR,OAAU,UACV,eAAgB,KAGxBoyC,SAAU,WACN9tE,KAAKotE,gBACT,EACAxvC,SAAU,SAASzvB,EAAGH,EAAGlB,EAAO0kE,GAC5B,MAAM,MAAEjlE,GAAUvM,KAAK23B,QACvB,IAAI1B,EAAS,GAAEF,kBAAkBljB,UAAU1E,EAAGH,GAAG+D,OAAOjF,GACpDP,IAAO0pB,EAASA,EAAO1pB,MAAMA,IAEjC,IAAItC,EAASjK,KAAK+H,WAAWkC,OAC7BA,EAAOswB,aAAa,YAAa,GAAElE,wBAAwBJ,IAC3DhsB,EAAOswB,aAAa,SAAWztB,EAAQ,KAAQ,EAAK,aAAe,cAEnE,IAAIymH,EAAY/hD,EAAKq2B,gBAAgB,IAAI,GAAQ15F,EAAGH,IAChDwG,EAAOxU,KAAK+H,WAAWyM,KAC3BA,EAAK+lB,aAAa,KAAMpsB,GACxBqG,EAAK+lB,aAAa,KAAMvsB,GACxBwG,EAAK+lB,aAAa,KAAMg5F,EAAUplH,GAClCqG,EAAK+lB,aAAa,KAAMg5F,EAAUvlH,EACtC,EACAgjH,cAAe,SAASprH,GAChB5F,KAAK23B,QAAQj8B,MAAMkK,KACvB5F,KAAK28C,QAAQ,eAAgB38C,KAAM4F,GACnCA,EAAIC,kBACJD,EAAID,iBACJ3F,KAAK23B,QAAQ2rB,MAAMsoB,mBACnB5rE,KAAK4uE,uBAAuB,KAAMhpE,EAAIrR,MAC1C,EACA08H,cAAe,SAASrrH,GACpB5F,KAAK28C,QAAQ,WAAY38C,KAAM4F,EACnC,EACAurH,YAAa,SAASvrH,GAClB5F,KAAKuuE,2BACLvuE,KAAK23B,QAAQ2rB,MAAMwoB,iBACnB9rE,KAAK28C,QAAQ,aAAc38C,KAAM4F,EACrC,EACAm2E,KAAM,WACF/7E,KAAKqI,GAAG4xB,MAAM8b,QAAU,EAC5B,EACA8lC,KAAM,WACF77E,KAAKqI,GAAG4xB,MAAM8b,QAAU,MAC5B,IAGG,MAAMy9E,GAAW7D,GAAS9vG,OAAO,CACpC1oB,KAAM,WACN+a,UAAW,GACXylB,QAAS,CACL05F,YAAaiC,GACbG,uBAAwB,GACxBlC,mBAAmB,EACnBnoC,OCxFD,SAAmB/sE,EAAQm1D,EAAM0C,GAWpC,OARU,GAAiC1oF,KACvCwU,KAAKsjD,MACL,CAAC,EACDkuB,EACA0C,EACA73D,EACArc,KAAK29C,OAEEyrC,MACf,ED6EQkoC,WAAY,GACZoC,YAAY,EACZ7tH,iBAAiB,GAErB4rH,QAAS,KACT3jD,SAAU,WACN9tE,KAAK6xH,eACL,IAAIp2C,EAAcz7E,KAAKy7E,YACnBrgB,EAAWqgB,EAAY99B,MAAMyd,WACjCA,EAASn+C,QAAQw+D,EAAY0H,aAC7B/nB,EAASxpE,KAAK6pF,EAAY2H,aAC1B,IAAK,IAAIt8E,EAAI,EAAGkJ,EAAIorD,EAAS5pE,OAAQsV,EAAIkJ,EAAI,EAAGlJ,IAAK,CACjD,IAAIq0D,EAASC,EAASt0D,GAClB6sH,EAAav4D,EAASt0D,EAAI,GAC1BmD,EAASjK,KAAK4zH,aAAaz4D,EAAQw4D,GACvC3zH,KAAK8vH,oBAAoB7lH,EAAO5B,IAChCrI,KAAKyxH,QAAQ7/H,KAAKqY,GAClBA,EAAO0tB,QAAQjmC,MAAQoV,CAC3B,CACA,OAAO9G,IACX,EACA4zH,aAAc,SAASz4D,EAAQw4D,GAC3B,IAAI1pH,EAAS,IAAKjK,KAAK23B,QAAmB,YAAE,CACxC2rB,MAAOtjD,KAAKsjD,MACZ/2C,MAAOvM,KAAK23B,QAAQprB,MACpB7Q,MAAOkK,GAAO5F,KAAKtE,MAAMkK,KAM7B,OAJAqE,EAAOwhE,SACPzrE,KAAK6zH,aAAa5pH,EAAQkxD,EAAQw4D,GAClC1pH,EAAOgvB,IAAIG,SAASp5B,KAAKqI,IACzBrI,KAAKiyH,qBAAqBhoH,GACnBA,CACX,EACA0I,OAAQ,WAEJ,OADA3S,KAAKyrE,SACEzrE,IACX,EACAiyH,qBAAsB,SAAShoH,GAC3BjK,KAAKu7C,SAAStxC,EAAQ,eAAgBjK,KAAK8zH,qBAC3C9zH,KAAKu7C,SAAStxC,EAAQ,WAAYjK,KAAKqyH,kBACvCryH,KAAKu7C,SAAStxC,EAAQ,aAAcjK,KAAK+zH,kBAC7C,EACAlC,aAAc,WACV,IAAIJ,EAAUzxH,KAAKyxH,QAGnB,GAFAzxH,KAAKyxH,QAAU,GACfzxH,KAAKg8C,gBACAhrD,MAAMC,QAAQwgI,GACnB,IAAK,IAAI3qH,EAAI,EAAGkJ,EAAIyhH,EAAQjgI,OAAQsV,EAAIkJ,EAAGlJ,IACvC2qH,EAAQ3qH,GAAGvC,QAEnB,EACAyvH,mBAAoB,SAASroI,GAEzB,IADA,IAAI8lI,EAAUzxH,KAAKyxH,QACV3qH,EAAI,EAAGkJ,EAAIyhH,EAAQjgI,OAAQsV,EAAIkJ,EAAGlJ,IAAK2qH,EAAQ3qH,GAAG6wB,QAAQjmC,OAAS/F,CAChF,EACAsoI,YAAa,SAAS9hI,EAAMi3F,GACxB,IAAI8qC,EAAel0H,KAAKy7E,YAAY99B,MAChCyrC,EACA8qC,EAAa7oI,KAAK,CAAC8G,EAAM,UAAWi3F,EAAQ,CACxCv/B,SAAS,EACT2rB,IAAI,EACJhC,KAAMxzE,KAAK+9C,MAGfm2E,EAAa9pE,WAAW,CAACj4D,EAAM,UAAW,CACtCqjF,IAAI,EACJhC,KAAMxzE,KAAK+9C,KAGvB,EACA21E,WAAY,SAASzpH,EAAQ2zB,EAAUrpC,GAEnC,IAAI7C,EAAQuY,EAAO0tB,QAAQjmC,MAGvB0pE,EAFWp7D,KAAKy7E,YACA99B,MACAyd,WAChBlb,EAAOj2C,EAAO0tB,QAAQuoB,KACtBzZ,EAAO20B,EAAS1pE,EAAQ,IAAM6C,EAAKixF,aACnC5iF,EAAOw4D,EAAS1pE,EAAQ,IAAM6C,EAAKmxF,aACnC4rC,EAAatxH,KAAK23B,QAAQ25F,WAM9B,OALIvvH,KAAKoN,IAAIyuB,EAASsiB,GAAQzZ,EAAKyZ,IAASoxE,EACxC1zF,EAASsiB,GAAQzZ,EAAKyZ,GACfn+C,KAAKoN,IAAIyuB,EAASsiB,GAAQt9C,EAAKs9C,IAASoxE,IAC/C1zF,EAASsiB,GAAQt9C,EAAKs9C,IAEnBtiB,CACX,EAEAy0F,iBAAkB,SAASpoH,EAAQrE,GAE/B,MAAM,QAAE+xB,GAAY33B,KACpB,IAAIzL,EAAOyL,KAAK6uE,UAAUjpE,GACtB61E,EAAcz7E,KAAKy7E,YACnBn4B,EAAQm4B,EAAYn4B,MACpB5xD,EAAQuY,EAAO0tB,QAAQjmC,MAAQ,EAC/BghI,EAAkB,GAAoB9sH,GACtCyW,EAASinC,EAAMv2C,WAAW2lH,EAAgBt5C,QAASs5C,EAAgBr5C,SACnEz7C,EAAW59B,KAAK0zH,WAAWzpH,EAAQoS,EAAOja,QAAS7N,GACnD2rD,EAAOj2C,EAAO0tB,QAAQuoB,KACtB7uC,EAAUrR,KAAK23B,QAAkB,WAAI,EAAKtb,EAAO6jC,GAAQtiB,EAASsiB,GAClEkH,EAAOq0B,EAAY99B,MACnByd,EAAW,GAAehU,EAAKgU,YAC/B6oC,EAAWjkG,KAAK23B,QAAQyxD,OACJ,mBAAb6a,IAAyBA,EAAW,MAE/C,MAAMkwB,EAAclqH,EAAO0tB,QAAQjmC,MAE7B0iI,EAAe,CAAC34C,EAAY0H,YAAY/gF,WAAYg5D,EAAUqgB,EAAY2H,YAAYhhF,SAC5F,IAAIiyH,EAAc,EAGdF,EAAc,GAAK,GAIL,IAAI,GAHPC,EAAaD,EAAc,GAC3BC,EAAaD,IAES1gH,SAAS1C,QAG9B,IAAO,IACfqqD,EAAS56D,OAAO2zH,EAAc,EAAG,EAAG5/H,EAAK+/H,iBAAiBH,EAAc,IACxEE,IACAr0H,KAAKg0H,mBAAmB,IAIhC,IAAI74D,EAASC,EAAS1pE,EAAQ2iI,GAC1BV,EAAav4D,EAAS1pE,EAAQ,EAAI2iI,GAGtC,GAAIF,EAAc,EAAIC,EAAa5iI,QAIjB,IAAI,GAHP4iI,EAAaD,EAAc,GAC3BC,EAAaD,EAAc,IAEL1gH,SAAS1C,QAG9B,IAAO,EAAG,CAClB,MAAMwjH,EAAkD,IAAjChgI,EAAK+/H,iBAAiB9iI,OACvCgjI,EAAaD,EAAiB,EAAIJ,EAClCM,EAAmBlgI,EAAKmgI,qBAAuBH,EAAiB,EAAI,EAC1E,IAAII,EAAa,EAAIN,EACrBj5D,EAAS56D,OAAO2zH,EAAcQ,EAAY,EAAGpgI,EAAK+/H,iBAAiBE,EAAaC,GACpF,CAIJ,IAAIr3C,EAAa3B,EAAY2B,WACzB6F,EAAaxH,EAAYwH,WACzB2xC,GAAqB,EACrBC,GAAqB,EA2BzB,GA1BK15D,EAagB,IAAVzpE,EACHuxF,EAAW1yE,cAAc4qD,IACzBC,EAAS5vB,QACTxrC,KAAKg0H,oBAAoB,GACzBY,GAAqB,IAErBz5D,EAAOjb,GAAQtiB,EAASsiB,GACxB20E,GAAqB,GAGzB15D,EAAOjb,GAAQtiB,EAASsiB,KAtBxBib,EAASsgB,EAAY+J,aAAahzE,UAC3B0tC,GAAQtiB,EAASsiB,GACpB+iC,EAAW1yE,cAAc4qD,IACzBA,EAAOjb,GAAQtiB,EAASsiB,GACxB00E,GAAqB,IAGrBx5D,EAASn+C,QAAQk+C,GACjBn7D,KAAKg0H,mBAAmB,GACxBz/H,EAAKmgI,oBAAqB,EAC1BG,GAAqB,IAezB5wB,GAAY7mB,EAAY,CACxB,GAAIw3C,EAAoB,CACpB,IAAIE,EAAuBvgI,EAAKixF,aAAapjF,QAC7C0yH,EAAqB50E,GAAQtiB,EAASsiB,GACtC,IAAIslC,EAAeye,EAASz4G,KAAKiwF,EAAaq5C,EAAsB13C,EAAY3B,EAAYomB,cAAgBzkB,EAAW/0E,GAAI,SAAUozE,GACrIz7E,KAAKi0H,YAAY,SAAUzuC,EAC/B,CACIqvC,GACA70H,KAAKi0H,YAAY,SAAU1/H,EAAKwgI,gBAExC,CAGA,IAAIx3C,EAAa9B,EAAY8B,WACzB2F,EAAazH,EAAYyH,WACzB8xC,GAAqB,EACrBC,GAAqB,EAuBzB,GAtBKtB,EAUMjiI,IAAU0pE,EAAS5pE,OAAS,EAC/B0xF,EAAW3yE,cAAcojH,IACzBv4D,EAAS76D,MACTy0H,GAAqB,IAErBrB,EAAWzzE,GAAQtiB,EAASsiB,GAC5B+0E,GAAqB,GAGzBtB,EAAWzzE,GAAQtiB,EAASsiB,KAlB5ByzE,EAAal4C,EAAYiK,aAAalzE,UAC3B0tC,GAAQtiB,EAASsiB,GACxBgjC,EAAW3yE,cAAcojH,GACzBqB,GAAqB,GAGrB55D,EAASxpE,KAAK+hI,GACdsB,GAAqB,IAczBhxB,GAAY1mB,EAAY,CACxB,GAAIy3C,EAAoB,CACpB,IAAIE,EAAuB3gI,EAAKmxF,aAAatjF,QAC7C8yH,EAAqBh1E,GAAQtiB,EAASsiB,GACtC,IAAIwlC,EAAeue,EAASz4G,KAAKiwF,EAAay5C,EAAsB33C,EAAY9B,EAAYlF,cAAgBgH,EAAWl1E,GAAI,SAAUozE,GACrIz7E,KAAKi0H,YAAY,SAAUvuC,EAC/B,CACIuvC,GACAj1H,KAAKi0H,YAAY,SAAU1/H,EAAK4gI,gBAExC,CACA,GAAI/5D,EAASzkE,MAAKszC,IAAMA,IAGpB,MAAM,IAAIjhC,MAAM,wCAEpBo+C,EAAKgU,SAASA,EAAU,CAAEoa,IAAI,EAAMhC,KAAMxzE,KAAK+9C,MAC/C/9C,KAAK6zH,aAAa5pH,EAAQkxD,EAAQw4D,EAAYtiH,GACzCsmB,EAAQ9xB,iBAAiB41E,EAAY8F,kBAAkBmxC,EAAiBr2G,EAAOlO,EAAGkO,EAAOrO,EAClG,EACA8lH,oBAAqB,SAAS7pH,EAAQrE,GAClC,MAAM,QAAE+xB,EAAO,QAAE85F,EAASh2C,YAAa1F,GAAa/1E,MAC9C,MAAE29C,EAAK,MAAE2F,GAAUyyB,EACzB,IAAIrkF,EAAQuY,EAAO0tB,QAAQjmC,MAC3B,GAAKV,MAAMC,QAAQwgI,GAAnB,CACA,IAAK,IAAI3qH,EAAI,EAAGkJ,EAAIyhH,EAAQjgI,OAAQsV,EAAIkJ,EAAGlJ,IACnCA,IAAMpV,GAAO+/H,EAAQ3qH,GAAG+0E,OAEhC77E,KAAKmwH,QACLnwH,KAAK6uE,UAAUjpE,EAAK,CAChB4/E,aAAczP,EAASyP,aAAapjF,QACpCsjF,aAAc3P,EAAS2P,aAAatjF,QACpC2yH,gBAAiB,GAAWp3E,EAAMtyD,KAAK,CAAC,SAAU,YAClD8pI,gBAAiB,GAAWx3E,EAAMtyD,KAAK,CAAC,SAAU,YAClDipI,iBAAkB,GAAe32E,EAAMyd,YACvCs5D,oBAAoB,IAExB/2E,EAAM2J,WAAW,eAAgB,CAAEkuB,IAAI,EAAMhC,KAAMxzE,KAAK+9C,MACnDpmB,EAAQ9xB,iBAAiBkwE,EAASC,qBAAqB1yB,EAAM6oE,eAAevmH,GAd9C,CAevC,EACAmuH,kBAAmB,SAAStB,EAAS7sH,GACjC,MAAM,QAAE+xB,EAAS8jD,YAAa1F,GAAY/1E,MACpC,MAAEsjD,EAAK,MAAE3F,GAAUo4B,EACrBp+C,EAAQ45F,mBACRx7C,EAASsrB,8BAA8B,CAAE7rB,IAAI,EAAMhC,KAAMxzE,KAAK+9C,MAElE,MAAM20E,EAAkB,GAAoB9sH,GACtCyW,EAASinC,EAAMv2C,WAAW2lH,EAAgBt5C,QAASs5C,EAAgBr5C,SACzEr5E,KAAKyrE,SACLzrE,KAAKk5C,OACLyE,EAAMiK,UAAU,eAAgB,CAAE4tB,IAAI,EAAMhC,KAAMxzE,KAAK+9C,MAClDpmB,EAAQ9xB,iBAAiBkwE,EAASyL,gBAAgBkxC,EAAiBr2G,EAAOlO,EAAGkO,EAAOrO,GACzF+nE,EAASmH,gBAAgBw1C,EAC7B,EACAmB,aAAc,SAAS5pH,EAAQkxD,EAAQw4D,EAAYtiH,GAC/C,IAAI6lC,EAAWn1C,KAAKoN,IAAIgsD,EAAOhtD,EAAIwlH,EAAWxlH,GAAKnO,KAAKkS,UACpDilC,EAAap1C,KAAKoN,IAAIgsD,EAAOntD,EAAI2lH,EAAW3lH,GAAKhO,KAAKkS,UAC1D,GAAIglC,GAAYC,EAAY,CACxB,IAAIi+E,EAAc,IAAI,GAAOj6D,EAAQw4D,GAErC,GADayB,EAAY5jI,SACZwO,KAAK23B,QAAQ87F,uBACtBxpH,EAAO4xE,WACJ,CACH,IAAIj+C,EAAWw3F,EAAYpgH,WACvBkrC,EAAO,EAAa,IAAM,IAC9BtiB,EAASsiB,IAAS7uC,GAAU,EAC5B,IAAIvE,EAAQsoH,EAAY3hH,SAASb,YAAY,IAAI,GAAQ,EAAG,IAC5D3I,EAAO2zB,SAASA,EAASzvB,EAAGyvB,EAAS5vB,EAAGlB,EAAO9M,KAAKy7E,aACpDxxE,EAAO8xE,OACP9xE,EAAO0tB,QAAQuoB,KAAOA,CAC1B,CACJ,MACIj2C,EAAO4xE,MAEf,EACAvN,SAAU,WACNtuE,KAAK6xH,cACT,GACD,CACCyB,cAAeA,KEjYN+B,GAAY,GAASx1G,OAAO,CACrCic,QAAS,IACTtB,UAAW,QACX0yC,YAAY,EACZ4sC,MAAO,KACPwb,YAAY,EACZ39F,QAAS,CACLmiF,MAAO,KACPr+B,YAAa,KACbtkF,KAAM,MAKVqkF,UAAW,SAAS7jD,GAEhB,IAAImiF,GADJniF,EAAU,GAAY33B,KAAK23B,QAASA,IAChBmiF,MACpB,IAAK9oH,MAAMC,QAAQ6oH,GAAQ,OAAO95G,KAClC,IAAIy7E,EAAc9jD,EAAQ8jD,YAC1B,KAAMA,aAAuBjJ,IAAW,OAAOxyE,KAE/C,IADA,IAAIosE,EAAQpsE,KAAK85G,MAAQ,GAChBhzG,EAAI,EAAGkJ,EAAI8pG,EAAMtoH,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAC1C,IAAI0sE,EAAOsmC,EAAMhzG,GACX0sE,aAAgBm8C,KACtBn8C,EAAKgI,UAAUC,EAAaz7E,MAC5BA,KAAKi5B,IAAInF,OAAO0/C,EAAKnrE,IACrB+jE,EAAMx6E,KAAK4hF,GACf,CAGA,OAFAxzE,KAAKs1H,YAAa,EAClB75C,EAAY9L,cAAc8L,EAAYvI,QAAQ,UACvClzE,IACX,EAEAs7E,QAAS,WACL,OAAOt7E,KAAK23B,QAAQxgC,IACxB,EAEAwb,OAAQ,SAAS0B,GAEbA,IAAQA,EAAM,CAAC,GACf,MAAMylG,EAAQ95G,KAAK85G,MACnB,IAAKA,EAAO,OAAO95G,KACnB,MAAMgQ,EAAI8pG,EAAMtoH,OACV+jI,EAAcv1H,KAAKs1H,WACzB,IAAK,IAAIxuH,EAAI,EAAGA,EAAIkJ,EAAGlJ,IAAK,CACxB,MAAM0sE,EAAOsmC,EAAMhzG,GACnB0sE,EAAKu8C,mBACAv8C,EAAKzsD,aACN/mB,KAAKw1H,mBAAmB1b,EAAOhzG,IAAMuN,EAAIm/D,OAASA,EAAKz1B,KACvDy1B,EAAK7gE,QAEb,CACA,OAAK3S,KAAKs1H,YAActlH,EAAI,IAKvBhQ,KAAKmtE,aACNntE,KAAK6vE,QAEJ0lD,GAEDv1H,KAAKswH,YAPEtwH,IAUf,EAEA,kBAAAw1H,CAAmB1b,EAAOhzG,GAKtB,OAJK9G,KAAKs1H,aAENt1H,KAAKs1H,WAAatkI,MAAM8oH,EAAMtoH,QAAQ0oE,MAAK,MAE1Cl6D,KAAKs1H,WAAWxuH,KAEjBgzG,EAAMhzG,GAAG2kE,SACTzrE,KAAKs1H,WAAWxuH,IAAK,GACd,EAGf,EAEAupH,UAAW,SAASoF,GAEhB,IAAI3b,EAAQ95G,KAAK85G,MACjB,IAAKA,EAAO,OAAO95G,KACnB,IAAK,IAAI8G,EAAI,EAAGkJ,EAAI8pG,EAAMtoH,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAC1C,IAAI0sE,EAAOsmC,EAAMhzG,GACb2uH,IAAgBjiD,EAChBA,EAAKuI,OAELvI,EAAKqI,MAEb,CACA,OAAO77E,IACX,EAEAswH,SAAU,SAASoF,GACf,IAAI5b,EAAQ95G,KAAK85G,MACjB,IAAKA,EAAO,OAAO95G,KACnB,IAAK,IAAI8G,EAAI,EAAGkJ,EAAI8pG,EAAMtoH,OAAQsV,EAAIkJ,EAAGlJ,IAAK,CAC1C,IAAI0sE,EAAOsmC,EAAMhzG,GACb0sE,IAASkiD,GAAgBliD,EAAKy8C,wBAC9Bz8C,EAAKuI,OAEDvI,EAAKzsD,aACL/mB,KAAKw1H,mBAAmB1b,EAAOhzG,IAAM0sE,EAAK7gE,SAGtD,CACA,OAAO3S,IACX,EAEA67E,KAAM,WACF,OAAO77E,KAAKqwH,UAAU,KAC1B,EAEAt0C,KAAM,WAMF,OALA/7E,KAAKswH,SAAS,MAETtwH,KAAKmtE,aACNntE,KAAK6vE,QAEF7vE,IACX,EAEAsuE,SAAU,WACN,IAAIwrC,EAAQ95G,KAAK85G,MACjB,IAAKA,EAAO,OAAO95G,KACnB,IAAK,IAAI8G,EAAI,EAAGkJ,EAAI8pG,EAAMtoH,OAAQsV,EAAIkJ,EAAGlJ,IACrCgzG,EAAMhzG,GAAGvC,SAEbvE,KAAK85G,MAAQ,IACjB,EAEAjqC,MAAO,WACH,MAAM,QAAEl4C,EAAO,GAAEtvB,GAAOrI,MAClB,YAAEy7E,EAAW,MAAEzL,EAAQ69B,GAAY7vB,MAAK,EAAEzyD,GAAMoM,EAQtD,OAPI8jD,IACIzL,EACAyL,EAAYn4B,MAAMitB,aAAaP,GAAOQ,iBAAiBnoE,EAAIkjB,GAE3DkwD,EAAYpzE,GAAGZ,YAAYY,IAG5BrI,IACX,QCxIC21H,GAUAC,GAMAC,GAWAC,GAMAC,2SAjCL,SAAKJ,GACD,uCACA,2CACA,iCACA,mCACA,iDACA,iBACA,oBACH,CARD,CAAKA,KAAAA,GAAS,KAUd,SAAKC,GACD,+BACA,yBACA,8BACH,CAJD,CAAKA,KAAAA,GAAe,KAMpB,SAAKC,GACD,2BACA,qBACA,yBACA,yBACA,+BACA,6BACA,6BACA,oCACH,CATD,CAAKA,KAAAA,GAAQ,KAWb,SAAKC,GACD,eACA,qBACA,oBACH,CAJD,CAAKA,KAAAA,GAAY,KAMjB,SAAKC,GACD,yBACA,+BACA,wBACH,CAJD,CAAKA,KAAAA,GAAW,KAMhB,MAAMC,IACc,GAAAC,aAAuB,UACvB,GAAAC,eAAyB,UACzB,GAAAC,gBAA0B,UAC1B,GAAAC,gBAA0B,UAQ9C,MAAMC,GAA2C,CAC7C,CAAElkI,KAAM,eAAgB6mD,MAAO,WAC/B,CAAE7mD,KAAM,YAAa6mD,MAAO,WAC5B,CAAE7mD,KAAM,cAAe6mD,MAAO,WAC9B,CAAE7mD,KAAM,cAAe6mD,MAAO,SAC9B,CAAE7mD,KAAM,iBAAkB6mD,MAAO,WACjC,CAAE7mD,KAAM,gBAAiB6mD,MAAO,WAChC,CAAE7mD,KAAM,gBAAiB6mD,MAAO,WAChC,CAAE7mD,KAAM,oBAAqB6mD,MAAO,YAGxC,MAAMs9E,WAAa,GAEf,aAAIC,GACA,OAAOv2H,KAAK3U,KAAK,YACrB,CACA,aAAIkrI,CAAU5qI,GACVqU,KAAK3U,KAAK,YAAaM,EAC3B,CAEA,eAAI6qI,GACA,OAAOx2H,KAAK3U,KAAK,cACrB,CACA,eAAImrI,CAAY7qI,GACZqU,KAAK3U,KAAK,cAAeM,EAC7B,CAEO,QAAA8qI,CAASz9E,GACZh5C,KAAKk1B,KAAK,YAAa8jB,EAC3B,CAEA,aAAI09E,GACA,OAAO12H,KAAK3U,KAAK,YACrB,CACA,aAAIqrI,CAAU/qI,GACVqU,KAAKoqD,WAAW,aAChBpqD,KAAK3U,KAAK,YAAaM,EAC3B,CAEO,sBAAAgrI,CAAuBC,GAC1B,OAAQA,GACJ,KAAKd,GAAae,GACd72H,KAAKy2H,SAAST,GAAcC,cAC5B,MACJ,KAAKH,GAAagB,MACd92H,KAAKy2H,SAAST,GAAcE,gBAC5B,MACJ,KAAKJ,GAAaiB,MAGlB,QACI/2H,KAAKy2H,SAAST,GAAcC,cAGxC,CAEO,QAAAe,CAAStmE,GAEZ,GAAIA,EAAMl/D,OAAS,GAAI,CACnB,IAAIylI,EAAa,GACblzH,EAAQ2sD,EAAMpgE,MAAM,KACpB+kB,EAAa,EACjBtR,EAAMpM,SAAQsM,IACNoR,EAAapR,EAAKzS,OAAS,IAC3BylI,GAAc,KAAOhzH,EAAO,IAC5BoR,EAAapR,EAAKzS,SAElBylI,GAAchzH,EAAO,IACrBoR,GAAcpR,EAAKzS,OACvB,IAGJwO,KAAKk1B,KAAK,aAAc+hG,EAAW9+H,OACvC,MACI6H,KAAKk1B,KAAK,aAAcw7B,EAEhC,CAEO,iBAAAwmE,CAAkBxmE,GAErB,GAAIA,EAAMl/D,OAAS,GAAI,CACnB,IAAIylI,EAAa,GACblzH,EAAQ2sD,EAAMpgE,MAAM,KACpB+kB,EAAa,EACjBtR,EAAMpM,SAAQsM,IACNoR,EAAapR,EAAKzS,OAAS,IAC3BylI,GAAc,KAAOhzH,EAAO,IAC5BoR,EAAapR,EAAKzS,SAElBylI,GAAchzH,EAAO,IACrBoR,GAAcpR,EAAKzS,OACvB,IAEJwO,KAAKk1B,KAAK,cAAe+hG,EAAW9+H,OACxC,MACI6H,KAAKk1B,KAAK,cAAew7B,EAEjC,CAEa,eAAAymE,CAAgBC,6CACzB,IACI,MAAMC,EAAW,oBAAoBD,QAE/BE,QAAiBC,MAAMF,GAC7B,IAAKC,EAASE,GACV,MAAM,IAAIxuH,MAAM,uBAAuBsuH,EAASG,UAEpD,MAAMC,QAAmBJ,EAASn/F,OAC5Bw/F,EAAaC,mBAAmBF,GAEtC13H,KAAKk1B,KAAK,CACN2iG,aAAc,CACV,aAAc,2BAA2BF,MAGrD,CAAE,MAAOx1F,GACLvW,QAAQuW,MAAM,sBAAuBA,EACzC,CACJ,IAEa,gBAAA21F,CAAiBpB,6CAC1B9qG,QAAQmsG,MAAM,kBAAmB/3H,KAAK02H,WACtC9qG,QAAQmsG,MAAM,kBAAmBrB,GACjC12H,KAAK02H,UAAYA,CAmDrB,KAkBJ,IAAKsB,IAAL,SAAKA,GACD,yBACA,uCACA,qCACA,iCACA,iCACA,kCACH,CAPD,CAAKA,KAAAA,GAAQ,KASb,MAAMC,GAA+B,CAACD,GAASE,QAASF,GAASG,eAAgBH,GAASI,YAAaJ,GAASK,YAAaL,GAASM,cAE/H,MAAMC,GA0BF,YAAAC,SAEH,OADgB7xF,KAAKC,UAAoB,QAAV,EAAA5mC,KAAKinD,aAAK,eAAEz0C,SAE/C,CAGO,YAAAimH,CAAaC,GAChB9sG,QAAQmsG,MAAM,gBACd/3H,KAAK24H,aAEDD,GACA9sG,QAAQmsG,MAAM,2BACd/3H,KAAKsjD,MAAM3F,MAAM8nB,SAAS9+B,KAAKxoB,MAAMu6G,GAAY,CAAEv0D,cAAenkE,KAAK2K,YAEvE3K,KAAKinD,MAAMsf,cAAc5uE,SAAQ4/D,IAC7B,GAAIA,aAAmB++D,GAAM,CACzB,IAAIplE,EAASqG,EAAQpsE,IAAI,UAEpB6F,MAAMC,QAAQigE,KACfA,EAAS,CAACA,IAId,MAAM0nE,EAAY1nE,EAAOn9D,QAAO8kI,GACH,iBAAlBA,GAA8B,YAAaA,GAA2C,UAA1BA,EAAc/8F,UAAwB+8F,EAActyH,SAASvN,SAAS,kBAG7Iu+D,EAAQnkE,IAAI,SAAUwlI,GAGtB,MAAMrC,EAAYh/D,EAAQg/D,UAM1B,GALIA,EAAU5/H,MAAK2+B,GAAMA,EAAGt8B,SAAS,SACjCu+D,EAAQg/D,UAAYA,EAAU5lI,KAAI2kC,GAAMA,EAAGv9B,QAAQ,IAAK,QAIhC,OAAxBw/D,EAAQpsE,IAAI,UAAqBosE,EAAQpsE,IAAI,WAAY,CACzD,MACM2tI,EAAU,UADGvhE,EAAQpsE,IAAI,cAE/BosE,EAAQnkE,IAAI,UAAW0lI,EAC3B,CACJ,KAIJ94H,KAAKinD,MAAMuf,WAAW7uE,SAAQyvD,gBAG1B,GAAIA,aAAgB2xE,GAChB3xE,EAAK7iD,cAIJ,GAA6B,kBAAzB6iD,EAAK1rB,WAAWvpC,MAAoE,aAAb,QAA3B,EAAqB,QAArB,EAAAi1D,EAAK1rB,WAAWxI,aAAK,eAAE1e,YAAI,eAAE0wC,SAKlF,GAA6B,kBAAzBkC,EAAK1rB,WAAWvpC,OAAuD,QAA3B,EAAqB,QAArB,EAAAi1D,EAAK1rB,WAAWxI,aAAK,eAAE1e,YAAI,eAAE0wC,QAAQ,CACjF,MAAM8zE,EAAY5xE,EAAK1rB,WAAWxI,MAAM1e,KAAK0wC,OACvC+zE,EAAe5C,GAAejuH,MAAK8wH,GAAMA,EAAGlgF,QAAUggF,IAExDC,IACA7xE,EAAK1rB,WAAWsd,MAAQggF,EACxB5xE,EAAK1rB,WAAWvpC,KAAO8mI,EAAa9mI,KAE5C,OAZIi1D,EAAK7iD,QAYT,IAIJvE,KAAKsjD,MAAM/2C,MAAM,EAAG,GACpBvM,KAAKsjD,MAAMmgE,sBAAsB,CAAEQ,cAAe,SAAUC,gBAAiB,SAAUH,SAAU,EAAGC,SAAU,MAE9Gp4F,QAAQmsG,MAAM,sBACd/3H,KAAKsjD,MAAM3F,MAAMz9C,SAErB0rB,QAAQmsG,MAAM,oBAClB,CAKQ,gBAAAoB,CAAiBxtI,GACrBigC,QAAQmsG,MAAM,kBAAoBpsI,GAClCqU,KAAKo5H,WAAaztI,EAAQqsI,GAASqB,cAAgB,IACvD,CAEQ,aAAAC,CAAc1zH,EAAsBuI,EAAWH,SAC/ChO,KAAKu5H,iBACL3tG,QAAQmsG,MAAM,qBACW,QAAzB,EAAA/3H,KAAKw5H,4BAAoB,SAAEj1H,SAGvBxC,KAAKoN,IAAIhB,EAAInO,KAAKu5H,eAAeprH,IAAMnO,KAAKsjD,MAAM3rB,QAAQ3qB,UACvDjL,KAAKoN,IAAInB,EAAIhO,KAAKu5H,eAAevrH,IAAMhO,KAAKsjD,MAAM3rB,QAAQ3qB,WAE7DhN,KAAKw5H,qBAAuB,IAAIC,GAAe,CAC3CjiI,KAAM,CACFgZ,MAAOzO,KAAKoN,IAAIhB,EAAInO,KAAKu5H,eAAeprH,GACxCsC,OAAQ1O,KAAKoN,IAAInB,EAAIhO,KAAKu5H,eAAevrH,IAE7C4vB,SAAU,CACNzvB,EAAGnO,KAAKu5H,eAAeprH,EAAIA,EAAIA,EAAInO,KAAKu5H,eAAeprH,EACvDH,EAAGhO,KAAKu5H,eAAevrH,EAAIA,EAAIA,EAAIhO,KAAKu5H,eAAevrH,KAK/DhO,KAAKinD,MAAMuE,QAAQxrD,KAAKw5H,uBAGpC,CAEc,cAAAE,CAAe/mI,EAAcuS,EAAcy0H,6CAErD,GAAIhnI,EAAO2iC,IAAMpwB,EAAOowB,GAGpB,OAAQqkG,GACJ,KAAK/D,GAAgBgE,YACjB55H,KAAK65H,wBAAwB75H,KAAK85H,mBAAmBnnI,EAAQuS,EAAQ6wH,GAAY6D,WAAY/D,GAASkE,UACtG,MACJ,KAAKnE,GAAgBoE,SACjBh6H,KAAK65H,wBAAwB75H,KAAK85H,mBAAmBnnI,EAAQuS,EAAQ6wH,GAAYiE,QAASnE,GAASoE,YACnG,MACJ,KAAKrE,GAAgBsE,YACjBl6H,KAAK65H,wBAAwB75H,KAAKm6H,sBAAsBj1H,EAAQvS,EAAQkjI,GAASqE,aACjF,MACJ,QACI,MAAM,IAAIlxH,MAAM,gCAGhC,IAEQ,OAAAoxH,CAAQznI,EAA2BuS,EAA2Bm1H,EAAoB3pE,EAAuB4pE,SAC7G,GAAI3nI,EAAO2iC,IAAMpwB,EAAOowB,GAAI,CACxB,IAAIilG,EAEJ,OAAQF,GACJ,KAAKxE,GAAS2E,SACVD,EAAU,IAAK,eACf,MACJ,KAAK1E,GAAS4E,MACVF,EAAU,IAAK,YACf,MACJ,KAAK1E,GAAS6E,QACVH,EAAU,IAAK,cACf,MACJ,KAAK1E,GAASkE,QACVQ,EAAU,IAAK,cACf,MACJ,KAAK1E,GAASqE,WACVK,EAAU,IAAK,iBACf,MACJ,KAAK1E,GAASoE,UACVM,EAAU,IAAK,gBACf,MACJ,KAAK1E,GAAS8E,UACVJ,EAAU,IAAK,gBACf,MACJ,KAAK1E,GAAS+E,cACVL,EAAU,IAAK,oBAInBD,GACAC,EAAQlvI,KAAK,SAAUivI,GAG3BC,EAAQ5nI,OAAOA,GACf4nI,EAAQr1H,OAAOA,GACf,IAAI21H,EAAmBloI,EAAgB4jI,UACnCuE,EAAmB51H,EAAgBqxH,UAElC+D,GAAkC,GAAxBt6H,KAAK65H,kBAEhBS,EAASt6H,KAAK+6H,aAAaC,aAAa,sBAAuBH,EAAiBC,EAAoC,QAAnB,EAAAP,EAAQz/D,SAAS,UAAE,eAAE5nC,MAAMiF,KAAKA,KAAMkiG,GACvIE,EAAQlvI,KAAK,SAAUivI,IAG3Bt6H,KAAKinD,MAAMuE,QAAQ+uE,GAEnBv6H,KAAK+6H,aAAaE,kBAAkB,qBACxC,CACJ,CAGQ,sBAAAC,CAAuBC,EAAwBC,EAAwBf,EAAoB3pE,EAAe4pE,GAC9G,MAAMe,EAAar7H,KAAKinD,MAAMsf,cAAcn+D,MAAKU,GAAQA,aAAgBwtH,IAAQxtH,EAAKytH,UAAUv9H,SAASmiI,KACnGG,EAAat7H,KAAKinD,MAAMsf,cAAcn+D,MAAKU,GAAQA,aAAgBwtH,IAAQxtH,EAAKytH,UAAUv9H,SAASoiI,KAErGC,GAAcC,GACdt7H,KAAKo6H,QAAQiB,EAAYC,EAAYjB,EAAU3pE,EAAO4pE,EAE9D,CAGQ,yBAAAiB,CAA0BJ,EAAwBC,EAAwBf,GAChEr6H,KAAKinD,MAAMuf,WACEzyE,QAAOqzD,IAC9B,MAAMi0E,EAAaj0E,EAAK+U,mBAClBm/D,EAAal0E,EAAKgV,mBAClBy+D,EAAkBQ,EAAW9E,UAC7BuE,EAAkBQ,EAAW/E,UACnC,IAAIiF,EACJ,OAAQnB,GACJ,KAAKxE,GAAS2E,SACVgB,EAAW,eACX,MACJ,KAAK3F,GAAS4E,MACVe,EAAW,YACX,MACJ,KAAK3F,GAAS6E,QACVc,EAAW,cACX,MACJ,KAAK3F,GAASkE,QACVyB,EAAW,cACX,MACJ,KAAK3F,GAASqE,WACVsB,EAAW,iBACX,MACJ,KAAK3F,GAASoE,UACVuB,EAAW,gBACX,MACJ,KAAK3F,GAAS8E,UACVa,EAAW,gBACX,MACJ,KAAK3F,GAAS+E,cACVY,EAAW,oBAInB,OAAOX,EAAgB7hI,SAASmiI,IAAmBL,EAAgB9hI,SAASoiI,IAAmBh0E,EAAK1rB,WAAWvpC,OAASqpI,CAAQ,IAGvH7jI,SAAQyvD,IACjBA,EAAK7iD,QAAQ,IAGjBvE,KAAK+6H,aAAaE,kBAAkB,qBACxC,CAGQ,kBAAAQ,CAAmBnB,GACvB,MACMoB,EADQ17H,KAAKinD,MAAMuf,WACGzyE,QAAOqzD,GAAQA,EAAK/7D,KAAK,YAAcivI,IAC/DoB,IACAA,EAAc/jI,SAAQyvD,GAAQA,EAAK7iD,WACnCvE,KAAK+6H,aAAaE,kBAAkB,sBAE5C,CAGQ,2BAAAU,CAA4BtB,EAAkBtzG,GAClD,IAAI9e,EACJA,EAAWjI,KAAKinD,MAAMqf,WAAWvyE,QAAOwqD,UACpC,OAA2B,QAApB,EAAAA,EAAK7iB,WAAWvpC,YAAI,eAAE+R,cAAcnM,QAAQ,OAAQ,OAAQsiI,EAASn2H,cAAcnM,QAAQ,OAAQ,GAAG,IAGjHkQ,EAAStQ,SAAQ4/D,IAEbA,EAAQriC,KAAK,eAAgBnO,EAAY,QAAU,QACnD,MAAM2qF,EAAc1xG,KAAKsjD,MAAMoI,gBAAgB6L,GAE3Cm6C,GACiBA,EAAYrpG,GAAGG,iBAAiB,KACxC7Q,SAASmoB,IACdA,EAAMya,aAAa,UAAWxT,EAAY,QAAU,OAAO,IAI/DwwC,aAAmB,KACnBA,EAAQriC,KAAK,eAAgBnO,EAAY,QAAU,QACnDwwC,EAAQ7G,MAAM,EAAG,CACbx9B,MAAO,CACHiF,KAAM,CAAE4d,QAAShvB,EAAY,QAAU,QACvC9Q,KAAM,CAAE8/B,QAAShvB,EAAY,QAAU,WAGnD,IAIJ/mB,KAAK+6H,aAAaE,kBAAkB,qBACxC,CAEQ,QAAAW,CAASr9E,EAAsBpwC,EAAWH,SAE1C6tH,EAAO11H,SAASkB,cAAc,OAClCw0H,EAAKrhG,UAAY,mBAGjBqhG,EAAK5hG,MAAMhnB,IAAMjF,EAAI,KACrB6tH,EAAK5hG,MAAMjnB,KAAO7E,EAAI,KAGtB,IAAIwpB,EAAwB,GAExB4mB,aAAgBu9E,IAAgBv9E,aAAgBw9E,GAChDpkG,EAAU,CAEN,CAAEQ,KAAM,KAAMupD,OAAQ,MACtB,CAAEvpD,KAAM,SAAUupD,OAAQ,KAAQnjC,EAAKh6C,QAAQ,IAE5Cg6C,aAAgBk7E,GACvB9hG,EAAU,CACN,CAAEQ,KAAM,aAAcupD,OAAQ,KAAQ1hF,KAAKg8H,yBAAyBz9E,EAAK,GACzE,CAAEpmB,KAAM,KAAMupD,OAAQ,MACtB,CAAEvpD,KAAM,SAAUupD,OAAQ,KAAQnjC,EAAKh6C,QAAQ,IAE5Cg6C,aAAgB+3E,IACnBt2H,KAAK65H,kBACLliG,EAAU,CACN,CACIQ,KAAM,kBAAmBupD,OAAQ,KACjCu6C,QAAS,CACL,CAAE9jG,KAAM,0BAA2BupD,OAAQ,KAAQ1hF,KAAKk8H,oBAAoB39E,EAAMq3E,GAAgBgE,WAAW,GAC7G,CAAEzhG,KAAM,0BAA2BupD,OAAQ,KAAQ1hF,KAAKk8H,oBAAoB39E,EAAMq3E,GAAgBoE,QAAQ,GAC1G,CAAE7hG,KAAM,oBAAqBupD,OAAQ,KAAQ1hF,KAAKk8H,oBAAoB39E,EAAMq3E,GAAgBsE,WAAW,KAG/G,CAAE/hG,KAAM,sBAAuBupD,OAAQ,KAAQ1hF,KAAKm8H,iBAAiB59E,EAAK,GAC1E,CAAEpmB,KAAM,sBAAuBupD,OAAQ,KAAQ1hF,KAAKo8H,iBAAiB79E,EAAK,IAGxEA,aAAgB89E,KAElB1kG,EAAUA,EAAQhvB,OAAO,CACrB,CACIwvB,KAAM,mBACNupD,OAAQ,KACJ1hF,KAAK+6H,aAAaE,kBAAkB,sBAAuB18E,EAAKg4E,UAAU,GAAIh4E,EAAKm4E,UAAU,KA+BzG/+F,GAzBIA,GADc,QAAd,EAAA4mB,EAAKm4E,iBAAS,eAAEllI,QAAS,EACfmmC,EAAQhvB,OAAO,CACrB,CACIwvB,KAAM,gBAAiBupD,OAAQ,KAC/Bu6C,QAAS19E,EAAKm4E,UAAU/lI,KAAI,CAAC2rI,EAAc5qI,KAChC,CACHymC,KAAMmkG,EACN56C,OAAQ,KAAQ1hF,KAAKu8H,kBAAkBh+E,EAAM+9E,EAAa,SAQhE3kG,EAAQhvB,OAAO,CACrB,CACIwvB,KAAM,gBAAiBupD,OAAQ,IAAM,KACrCu6C,QAAS,CACL,CACI9jG,KAAM,yBAA0BupD,OAAQ,IAAM,WAMhD/4E,OAAO,CACrB,CACIwvB,KAAM,sBACNupD,OAAQ,KACJ1hF,KAAK+6H,aAAaE,kBAAkB,kBAAmB18E,EAAKg4E,UAAU,GAAG,OAMzF5+F,EAAUA,EAAQhvB,OAAO,CACrB,CACIwvB,KAAM,iBAAkBupD,OAAQ,KAC5B1hF,KAAK+6H,aAAaE,kBAAkB,uBAAwB18E,EAAKg4E,UAAU,GAAG,MAKlF3kI,KAAK,CAAEumC,KAAM,KAAMupD,OAAQ,QAGvC/pD,EAAUA,EAAQhvB,OAAO,CACrB,CACIwvB,KAAM,WAAYupD,OAAQ,KAC1Bu6C,QAAS,CACL,CAAE9jG,KAAM,WAAYupD,OAAQ,KAAQ1hF,KAAKw8H,aAAaj+E,EAAMs3E,GAAS2E,SAAS,GAC9E,CAAEriG,KAAM,cAAeupD,OAAQ,KAAQ1hF,KAAKw8H,aAAaj+E,EAAMs3E,GAAS4E,MAAM,GAC9E,CAAEtiG,KAAM,UAAWupD,OAAQ,KAAQ1hF,KAAKw8H,aAAaj+E,EAAMs3E,GAAS6E,QAAQ,GAC5E,CAAEviG,KAAM,UAAWupD,OAAQ,KAAQ1hF,KAAKw8H,aAAaj+E,EAAMs3E,GAASkE,QAAQ,GAC5E,CAAE5hG,KAAM,cAAeupD,OAAQ,KAAQ1hF,KAAKw8H,aAAaj+E,EAAMs3E,GAASqE,WAAW,GACnF,CAAE/hG,KAAM,aAAcupD,OAAQ,KAAQ1hF,KAAKw8H,aAAaj+E,EAAMs3E,GAASoE,UAAU,GACjF,CAAE9hG,KAAM,YAAaupD,OAAQ,KAAQ1hF,KAAKw8H,aAAaj+E,EAAMs3E,GAAS8E,UAAU,KAKxF,CAAExiG,KAAM,KAAMupD,OAAQ,QAGtB1hF,KAAK65H,kBACDt7E,EAAKi4E,cACL7+F,EAAUA,EAAQhvB,OAAO,CACrB,CAAEwvB,KAAM,WAAYupD,OAAQ,KAAQ1hF,KAAKy8H,eAAel+E,EAAK,MAGrE5mB,EAAUA,EAAQhvB,OAAO,CACrB,CAAEwvB,KAAM,cAAeupD,OAAQ,KAAQ1hF,KAAK+6H,aAAaE,kBAAkB,qBAAsB18E,EAAKg4E,UAAWh4E,EAAKrpB,KAAK,cAAc,MAkCjJyC,EAAUA,EAAQhvB,OAAO,CACrB,CAAEwvB,KAAM,aAAcupD,OAAQ,KAAQ1hF,KAAK08H,mBAAmBn+E,EAAK,GACnE,CAAEpmB,KAAM,qBAAsBupD,OAAQ,KAAQ1hF,KAAKg8H,yBAAyBz9E,EAAK,GACjF,CAAEpmB,KAAmC,KAA7BomB,EAAKrpB,KAAK,eAAwB,sBAAwB,uBAAwBwsD,OAAQ,KAAQ1hF,KAAK28H,2BAA2Bp+E,EAAK,GAM/I,CAAEpmB,KAAM,KAAMupD,OAAQ,MACtB,CAAEvpD,KAAM,SAAUupD,OAAQ,KAAQ1hF,KAAK48H,qBAAqBr+E,EAAK,MAG9DA,aAAgB,KACNA,EAAK4d,mBACL5d,EAAK6d,mBAEtBzkC,EAAU,CACN,CAAEQ,KAAM,aAAcupD,OAAQ,KAAQ1hF,KAAK68H,eAAet+E,EAAK,GAC/D,CAAEpmB,KAAM,KAAMupD,OAAQ,MACtB,CAAEvpD,KAAM,cAAeupD,OAAQ,KAAQ1hF,KAAK88H,0BAA0Bv+E,EAAK,KAInF5mB,EAAQhgC,SAAQooD,IACZ,IAAIg9E,EAAa52H,SAASkB,cAAc,OAExC,GAAmB,MAAf04C,EAAO5nB,MAAiC,MAAjB4nB,EAAO2hC,OAG9B,OAFAq7C,EAAWviG,UAAY,gCACvBqhG,EAAKp0H,YAAYs1H,GAIrBA,EAAWviG,UAAY,0BACvB,IAAIwiG,EAAW72H,SAASkB,cAAc,QAItC,GAHA21H,EAASjoG,YAAcgrB,EAAO5nB,KAC9B4kG,EAAWt1H,YAAYu1H,GAEnBj9E,EAAOk8E,QAAS,CAChB,IAAIgB,EAAQ92H,SAASkB,cAAc,QACnC41H,EAAMloG,YAAc,IACpBgoG,EAAWt1H,YAAYw1H,EAC3B,CAEApB,EAAKp0H,YAAYs1H,GAEjBA,EAAWhyH,iBAAiB,SAAS,IAAY,GAAD,gCAC5C,GAAIg1C,EAAOk8E,QAAS,CAEhB,IAAI/6G,EAAS67G,EAAWnvF,wBACpBz/B,EAAI+S,EAAOlO,KAAOkO,EAAO1Q,MACzBxC,EAAIkT,EAAOjO,IACfjT,KAAKk9H,YAAY/uH,EAAGH,EAAG+xC,EAAOk8E,QAClC,YAEUl8E,EAAO2hC,eACP1hF,KAAK24H,YAEnB,KAAE,IAINkD,EAAK5hG,MAAMi2F,WAAa,SACxB/pH,SAASuB,KAAKD,YAAYo0H,GAG1B,IAAIsB,EAAYtB,EAAKuB,UAAYvB,EAAKzuF,aAClCiwF,EAAen3H,OAAOiqC,aAAehqC,SAASC,gBAAgBoxB,aAC9D8lG,EAAmBD,EAAeF,EAEtCvxG,QAAQmsG,MAAM,cAAgBoF,GAC9BvxG,QAAQmsG,MAAM,iBAAmBsF,GACjCzxG,QAAQmsG,MAAM,qBAAuBuF,GAGjCA,EAAmB,IACnBzB,EAAK5hG,MAAMhnB,IAAO4oH,EAAKuB,UAAYvB,EAAKzuF,aAAgB,MAE5DyuF,EAAK5hG,MAAMi2F,WAAa,SAC5B,CAEO,WAAAgN,CAAY/uH,EAAWH,EAAW2pB,GAErC33B,KAAKu9H,gBAGL,IAAI1B,EAAO11H,SAASkB,cAAc,OAClCw0H,EAAKrhG,UAAY,mBACjBqhG,EAAKv8F,UAAU1kC,IAAI,uBAGnBihI,EAAK5hG,MAAMhnB,IAAMjF,EAAI,KACrB6tH,EAAK5hG,MAAMjnB,KAAO7E,EAAI,KAEtB0tH,EAAK5hG,MAAMgpF,UAAY,QACvB4Y,EAAK5hG,MAAMujG,UAAY,SAGvB7lG,EAAQhgC,SAAQooD,IACZ,IAAIg9E,EAAa52H,SAASkB,cAAc,OAExC,GAAmB,MAAf04C,EAAO5nB,MAAiC,MAAjB4nB,EAAO2hC,OAG9B,OAFAq7C,EAAWviG,UAAY,gCACvBqhG,EAAKp0H,YAAYs1H,GAIrBA,EAAWviG,UAAY,0BACvB,IAAIwiG,EAAW72H,SAASkB,cAAc,QACtC21H,EAASjoG,YAAcgrB,EAAO5nB,KAC9B4kG,EAAWt1H,YAAYu1H,GACvBnB,EAAKp0H,YAAYs1H,GAEjBA,EAAWhyH,iBAAiB,SAAS,IAAY,GAAD,gCAC5C,GAAIg1C,EAAOk8E,QAAS,CAEhB,IAAI/6G,EAAS67G,EAAWnvF,wBACpBz/B,EAAI+S,EAAOlO,KAAOkO,EAAO1Q,MACzBxC,EAAIkT,EAAOjO,IACfjT,KAAKk9H,YAAY/uH,EAAGH,EAAG+xC,EAAOk8E,QAClC,YAEUl8E,EAAO2hC,eACP1hF,KAAK24H,YAEnB,KAAE,IAINkD,EAAK5hG,MAAMi2F,WAAa,SACxB/pH,SAASuB,KAAKD,YAAYo0H,GAG1B,IAAIsB,EAAYtB,EAAKuB,UAAYvB,EAAKzuF,aAClCiwF,EAAen3H,OAAOiqC,aAAehqC,SAASC,gBAAgBoxB,aAC9D8lG,EAAmBD,EAAeF,EAEtCvxG,QAAQmsG,MAAM,cAAgBoF,GAC9BvxG,QAAQmsG,MAAM,iBAAmBsF,GACjCzxG,QAAQmsG,MAAM,qBAAuBuF,GAGjCA,EAAmB,IACnBzB,EAAK5hG,MAAMhnB,IAAO4oH,EAAKuB,UAAYvB,EAAKzuF,aAAgB,MAI5D,IAAIqwF,EAAW5B,EAAK6B,WAAa7B,EAAK9uF,aACpB7mC,OAAOgqC,YAAc/pC,SAASC,gBAAgBmxB,aAC5BkmG,EAId,IAClB5B,EAAK5hG,MAAMjnB,KAAQ6oH,EAAK6B,WAAa7B,EAAK9uF,YAAe,MAG7D8uF,EAAK5hG,MAAMi2F,WAAa,SAC5B,CAEO,UAAAyI,GAEa3nI,MAAM8W,KAAK3B,SAASw3H,uBAAuB,qBAGjDhmI,SAAQkkI,IACdA,EAAKt3H,QAAQ,GAErB,CAEO,aAAAg5H,GAEgBvsI,MAAM8W,KAAK3B,SAASw3H,uBAAuB,wBAGjDhmI,SAAQkkI,IACjBA,EAAKt3H,QAAQ,GAErB,CAEQ,mBAAA23H,CAAoBv/D,EAAqBg9D,GAG7C35H,KAAKo5H,WAAapB,GAASG,eAG3Bn4H,KAAK49H,gBAAkBjhE,EACvB38D,KAAK69H,wBAA0BlE,EAG/Bh9D,EAAcznC,KAAK,cAAe,CAAE/9B,KAAM,YAAa8J,KAAM,CAAE+3C,MAAO,SAAUxoC,MAAO,EAAGslC,QAAS,IAAMoD,KAAM,KAC/Gl5C,KAAK24H,YACT,CAEQ,YAAA6D,CAAa7/D,EAAqB09D,GAEtCr6H,KAAKo5H,WAAapB,GAASE,QAG3Bl4H,KAAK49H,gBAAkBjhE,EACvB38D,KAAK89H,iBAAmBzD,EAGxB19D,EAAcznC,KAAK,cAAe,CAAE/9B,KAAM,YAAa8J,KAAM,CAAE+3C,MAAO,SAAUxoC,MAAO,EAAGslC,QAAS,IAAMoD,KAAM,KAC/Gl5C,KAAK24H,YACT,CAEQ,gBAAAyD,CAAiBz/D,GAErB38D,KAAKo5H,WAAapB,GAASI,YAG3Bp4H,KAAK49H,gBAAkBjhE,EAGvBA,EAAcznC,KAAK,cAAe,CAAE/9B,KAAM,YAAa8J,KAAM,CAAE+3C,MAAO,SAAUxoC,MAAO,EAAGslC,QAAS,IAAMoD,KAAM,KAC/Gl5C,KAAK24H,YACT,CAEQ,gBAAAwD,CAAiBx/D,GAErB38D,KAAKo5H,WAAapB,GAASK,YAG3Br4H,KAAK49H,gBAAkBjhE,EAGvBA,EAAcznC,KAAK,cAAe,CAAE/9B,KAAM,YAAa8J,KAAM,CAAE+3C,MAAO,SAAUxoC,MAAO,EAAGslC,QAAS,IAAMoD,KAAM,KAC/Gl5C,KAAK24H,YACT,CAEQ,iBAAA4D,CAAkB5/D,EAAqB2/D,GAE3Ct8H,KAAKo5H,WAAapB,GAASM,aAG3Bt4H,KAAK49H,gBAAkBjhE,EACvB38D,KAAK+9H,mBAAqBzB,EAG1B3/D,EAAcznC,KAAK,cAAe,CAAE/9B,KAAM,YAAa8J,KAAM,CAAE+3C,MAAO,SAAUxoC,MAAO,EAAGslC,QAAS,IAAMoD,KAAM,KAC/Gl5C,KAAK24H,YACT,CAEc,kBAAAmB,CAAmBnnI,EAAcuS,EAAc84H,EAA0B3D,qDAC/EQ,EAAkC,QAAhB,EAAAloI,EAAO4jI,iBAAS,QAAI,GACtCuE,EAAkC,QAAhB,EAAA51H,EAAOqxH,iBAAS,QAAI,GACtC0H,EAActrI,EAAOuiC,KAAK,cAC1BgpG,EAAch5H,EAAOgwB,KAAK,cAE1BipG,EAAeH,IAAgBjI,GAAY6D,iBACnC55H,KAAK+6H,aAAaE,kBAAkB,wBAAyBJ,EAAiBC,EAAiBmD,EAAaC,SAC5Gl+H,KAAK+6H,aAAaE,kBAAkB,wBAAyBJ,EAAiBC,EAAiBmD,EAAaC,GAGxH,GAAIC,EAAc,CACd,MAAM7D,EAAS6D,EAAa5pI,KAAK,GAAG+gC,GAGpCt1B,KAAKo6H,QAAQl1H,EAAQvS,EAAQ0nI,EAAU,KAAMC,GAE7Ct6H,KAAKo6H,QAAQznI,EAAQuS,EAAQ2wH,GAAS6E,QAAS,KAAMJ,EACzD,CACJ,IAEc,qBAAAH,CAAsBxnI,EAAcuS,EAAcm1H,qDACxDQ,EAAkC,QAAhB,EAAAloI,EAAO4jI,iBAAS,QAAI,GACtCuE,EAAkC,QAAhB,EAAA51H,EAAOqxH,iBAAS,QAAI,GACtC0H,EAActrI,EAAOuiC,KAAK,cAC1BgpG,EAAch5H,EAAOgwB,KAAK,cAE1BipG,QAAqBn+H,KAAK+6H,aAAaE,kBAAkB,4BAA6BJ,EAAiBC,EAAiBmD,EAAaC,GAGzI,GAAIC,EAAc,CACd,MAAM7D,EAAS6D,EAAa5pI,KAAK,GAAG+gC,GAGpCt1B,KAAKo6H,QAAQl1H,EAAQvS,EAAQ0nI,EAAU,KAAMC,GAE7Ct6H,KAAKo6H,QAAQznI,EAAQuS,EAAQ2wH,GAAS6E,QAAS,KAAMJ,EACzD,CACJ,IAEc,cAAAmC,CAAe3zH,6CACzB,IAAIs1H,EAAWt1H,EAAKytH,UAAU,SAExBv2H,KAAK+6H,aAAaE,kBAAkB,kBAAmBmD,EACjE,IAEa,aAAAC,6CACTzyG,QAAQmsG,MAAM,iBAEd,IAAIuG,EAA+B,GACnCt+H,KAAKinD,MAAMsf,cAAc5uE,SAAQmR,IACzBA,aAAgBwtH,IAChBgI,EAAmB1sI,QAAQkX,EAAKytH,UACpC,IAGJ,IAAIgI,QAAqCv+H,KAAK+6H,aAAaE,kBAAkB,yBAA0BqD,GACvG,GAAe,MAAXC,EAAiB,CACjB,IAAIpwH,EAAKnO,KAAKw+H,UAAUzxF,YAAc,EAAuB,GAAjBwxF,EAAQ/sI,OAChDwc,EAAKhO,KAAKw+H,UAAUpxF,aAAe,EAAuB,GAAjBmxF,EAAQ/sI,OACrDo6B,QAAQmsG,MAAMwG,GAEdA,EAAQ5mI,SAAQlG,IAEZ,IAAIgtI,EAAmBz+H,KAAK0+H,iBAAiBjtI,EAAO2iB,OAGpDqqH,EAAWlI,UAAY9kI,EAAO8kI,UAG9BkI,EAAWzH,SAASvlI,EAAOi/D,OAG3B+tE,EAAW9H,uBAAuBllI,EAAOmlI,cAEzC6H,EAAW7gG,SAASzvB,EAAGH,GACvBywH,EAAWtmE,OAAO,IAAK,KACvBn4D,KAAKinD,MAAMuE,QAAQizE,GAGfhtI,EAAOilI,WAAajlI,EAAOilI,UAAUllI,OAAS,GAC9CitI,EAAW3G,iBAAiBrmI,EAAOilI,WAGvCvoH,GAAQ,GACRH,GAAQ,EAAE,UAGRhO,KAAK+6H,aAAaE,kBAAkB,qBAC9C,CACJ,IAEa,iBAAA0D,6CACT/yG,QAAQmsG,MAAM,qBAEd,IAAIuG,EAA+B,GACnCt+H,KAAKinD,MAAMsf,cAAc5uE,SAAQmR,IACzBA,aAAgBwtH,IAChBgI,EAAmB1sI,QAAQkX,EAAKytH,UACpC,IAGJ,IAAIgI,QAAqCv+H,KAAK+6H,aAAaE,kBAAkB,iCAAkCqD,GAC/G,GAAe,MAAXC,EAAiB,CACjB,IAAIpwH,EAAKnO,KAAKw+H,UAAUzxF,YAAc,EAAuB,GAAjBwxF,EAAQ/sI,OAChDwc,EAAKhO,KAAKw+H,UAAUpxF,aAAe,EAAuB,GAAjBmxF,EAAQ/sI,OACrDo6B,QAAQmsG,MAAMwG,GAEdA,EAAQ5mI,SAAQlG,IAEZ,IAAIgtI,EAAmBz+H,KAAK0+H,iBAAiBjtI,EAAO2iB,OAEpDqqH,EAAWlI,UAAY9kI,EAAO8kI,UAG9BkI,EAAWzH,SAASvlI,EAAOi/D,OAG3B+tE,EAAW9H,uBAAuBllI,EAAOmlI,cAEzC6H,EAAW7gG,SAASzvB,EAAGH,GACvBywH,EAAWtmE,OAAO,IAAK,KACvBn4D,KAAKinD,MAAMuE,QAAQizE,GAEnBtwH,GAAQ,GACRH,GAAQ,EAAE,UAGRhO,KAAK+6H,aAAaE,kBAAkB,qBAC9C,CACJ,IA6Ba,qBAAA2D,CAAsBR,EAAkBS,6CACjD,IAAIC,EAAa9+H,KAAKinD,MAAMsf,cAAcn+D,MAAK8B,GAAKA,aAAaosH,IAAQpsH,EAAEqsH,UAAUv9H,SAASolI,KAC9FxyG,QAAQmzG,IAAID,EAAYD,GACxBC,SAAAA,EAAYhH,iBAAiB+G,EACjC,IAGa,4BAAAG,CAA6BrnG,6CAOtC,GANA/L,QAAQmsG,MAAMpgG,GAGA33B,KAAKinD,MAAMsf,cAAcn+D,MAAK8B,GAAKA,aAAaosH,IAC1DpsH,EAAEqsH,UAAUxiI,QAAOuhC,GAAMqC,EAAQ4+F,UAAUv9H,SAASs8B,KAAK9jC,OAAS,IAGlEo6B,QAAQmsG,MAAM,yDADlB,CAKA,IAAI0G,EAAmBz+H,KAAK0+H,iBAAiB/mG,EAAQvjB,OAGrDqqH,EAAWlI,UAAY5+F,EAAQ4+F,UAG/BkI,EAAWzH,SAASr/F,EAAQ+4B,OAG5B+tE,EAAW9H,uBAAuBh/F,EAAQi/F,cAG1C6H,EAAWjI,YAAc7+F,EAAQ6+F,YAGjC,IAAI54F,EAAW,CAAC59B,KAAKw+H,UAAUzxF,YAAc,EAAG/sC,KAAKw+H,UAAUpxF,aAAe,GAC9ExhB,QAAQmsG,MAAMn6F,GAGd,EAAG,CACC,IAAIqhG,EAA6Bj/H,KAAKinD,MAAMsf,cAAcn+D,MAAK8B,GAAKA,aAAaosH,IAC7EpsH,EAAE0zB,WAAWzvB,IAAMyvB,EAAS,IAC5B1zB,EAAE0zB,WAAW5vB,IAAM4vB,EAAS,KAE5BqhG,IACArzG,QAAQmsG,MAAM,uBACdn6F,EAAS,GAAKA,EAAS,GAAK,GAC5BA,EAAS,GAAKA,EAAS,GAAK,GAE5BhS,QAAQmsG,MAAMn6F,IAElBhS,QAAQmsG,MAAM,yBAClB,OACOkH,GAEPR,EAAW7gG,SAASA,EAAS,GAAIA,EAAS,IAC1C6gG,EAAWtmE,OAAO,IAAK,KAGnBxgC,EAAQ++F,WAAa/+F,EAAQ++F,UAAUllI,OAAS,UAC1CitI,EAAW3G,iBAAiBngG,EAAQ++F,YAG9C12H,KAAKinD,MAAMuE,QAAQizE,SACbz+H,KAAK+6H,aAAaE,kBAAkB,qBA9C1C,CAiDJ,IAGa,2BAAAiE,CAA4Bd,EAAkBzmG,6CACvD,IAAI4/B,EAAUv3D,KAAKinD,MAAMsf,cAAcn+D,MAAK8B,GAAKA,aAAaosH,IACpC,GAAtBpsH,EAAEqsH,UAAU/kI,QAAe0Y,EAAEqsH,UAAU,IAAM6H,IAEjD,GAAI7mE,EAAS,CACT,IAAIknE,EAAmBz+H,KAAK0+H,iBAAiB/mG,EAAQvjB,OAGrDqqH,EAAWlI,UAAY5+F,EAAQ4+F,UAG/BkI,EAAWzH,SAASr/F,EAAQ+4B,OAG5B+tE,EAAW9H,uBAAuBh/F,EAAQi/F,cAE1C6H,EAAW7gG,SAAS25B,EAAQ77B,WAAWkC,SAASzvB,EAAGopD,EAAQ77B,WAAWkC,SAAS5vB,GAC/EywH,EAAWtmE,OAAO,IAAK,KACvBn4D,KAAKinD,MAAMuE,QAAQizE,GAGf9mG,EAAQ++F,WAAa/+F,EAAQ++F,UAAUllI,OAAS,GAChDitI,EAAW3G,iBAAiBngG,EAAQ++F,WAI5B12H,KAAKinD,MAAMC,kBAAkBqQ,GACnC5/D,SAAQyvD,IACNA,EAAKj8D,IAAI,UAAUmqC,KAAOiiC,EAAQjiC,IAClC8xB,EAAKz0D,OAAO8rI,GAEZr3E,EAAKj8D,IAAI,UAAUmqC,KAAOiiC,EAAQjiC,IAClC8xB,EAAKliD,OAAOu5H,EAChB,IAIJlnE,EAAQhzD,eACFvE,KAAK+6H,aAAaE,kBAAkB,qBAC9C,CACJ,IAEc,oBAAA2B,CAAqBrlE,mDAC/B,GAAIv3D,KAAK65H,iBAAmBtiE,aAAmB++D,GAAM,CACjD,IAAIC,EAA6B,QAAjB,EAAAh/D,EAAQg/D,iBAAS,QAAI,GACjC7lE,EAAQ6G,EAAQriC,KAAK,qBAENl1B,KAAK+6H,aAAaE,kBAAkB,8BAA+B1E,EAAW7lE,KAE7F6G,EAAQhzD,QAEhB,MAEIgzD,EAAQhzD,eAENvE,KAAK+6H,aAAaE,kBAAkB,qBAC9C,IAEc,yBAAA6B,CAA0B11E,qDACpC,GAAIpnD,KAAK65H,gBAAiB,CACtB,IAAIwB,EAAaj0E,EAAK+U,mBAClBm/D,EAAal0E,EAAKgV,mBAClBy+D,EAAsC,QAApB,EAAAQ,EAAW9E,iBAAS,QAAI,GAC1CuE,EAAsC,QAApB,EAAAQ,EAAW/E,iBAAS,QAAI,GAC1C+D,EAASlzE,EAAK/7D,KAAK,iBAEJ2U,KAAK+6H,aAAaE,kBAAkB,oCAAqCJ,EAAiBC,EAAiBR,MAQ1HlzE,EAAK7iD,eACCvE,KAAK+6H,aAAaE,kBAAkB,sBAElD,MAEI7zE,EAAK7iD,eACCvE,KAAK+6H,aAAaE,kBAAkB,qBAElD,IAGa,0BAAAkE,CAA2Bf,6CACpC,IAAI7mE,EAAUv3D,KAAKinD,MAAMsf,cAAcn+D,MAAK8B,GAAKA,aAAaosH,IACpC,GAAtBpsH,EAAEqsH,UAAU/kI,QAAe0Y,EAAEqsH,UAAU,IAAM6H,IAE7C7mE,IACAA,EAAQhzD,eACFvE,KAAK+6H,aAAaE,kBAAkB,sBAElD,IAEa,uBAAAmE,CAAwBhB,EAAkB9B,6CACnD,IAAI/kE,EAAUv3D,KAAKinD,MAAMsf,cAAcn+D,MAAK8B,GAAKA,aAAaosH,IACpC,GAAtBpsH,EAAEqsH,UAAU/kI,QAAe0Y,EAAEqsH,UAAU,IAAM6H,IAE7C7mE,IACAA,EAAQm/D,UAAU9kI,KAAK0qI,GACvBt8H,KAAK4+H,sBAAsBR,EAAU7mE,EAAQm/D,WAErD,IAEa,4BAAA2I,CAA6BjB,EAAkB9B,6CACxD,IAAI/kE,EAAUv3D,KAAKinD,MAAMsf,cAAcn+D,MAAK8B,GAAKA,aAAaosH,IACpC,GAAtBpsH,EAAEqsH,UAAU/kI,QAAe0Y,EAAEqsH,UAAU,IAAM6H,IAEjD,GAAI7mE,EAAS,CACT,IAAI+nE,EAAmB/nE,EAAQm/D,UAAU3iI,QAAOoe,GAAKA,IAAMmqH,IAC3Dt8H,KAAK4+H,sBAAsBR,EAAUkB,EACzC,CACJ,IAEa,wBAAAC,CAAyBpE,EAAwBC,EAAwBkB,6CAClFt8H,KAAKq/H,6BAA6BjE,EAAgBkB,GAClDt8H,KAAKo/H,wBAAwBjE,EAAgBmB,EACjD,IAEO,aAAAkD,SACHx/H,KAAKo5H,WAAa,KAEdp5H,KAAK49H,kBACL59H,KAAK49H,gBAAgB1oG,KAAK,cAAe,MACzCl1B,KAAK49H,gBAAkB,MAG3B59H,KAAK89H,iBAAmB,KACxB99H,KAAK69H,wBAA0B,KAE/B79H,KAAKu5H,eAAiB,KACG,QAAzB,EAAAv5H,KAAKw5H,4BAAoB,SAAEj1H,SAE3BvE,KAAKinD,MAAMsf,cAAc5uE,SAAQ4/D,IACzBA,aAAmB++D,IACnB/+D,EAAQriC,KAAK,cAAe,KAChC,GAER,CAEc,wBAAA8mG,CAAyBzkE,6CAEnC,IAAIkoE,EAAUloE,EAAQriC,KAAK,cAEvBwqG,QAAgB1/H,KAAK+6H,aAAaE,kBAAkB,mBAAoBwE,GAC5E7zG,QAAQmsG,MAAM,YAAc2H,GAGb,MAAXA,GACAnoE,EAAQy/D,SAAS0I,EAEzB,IAEc,0BAAA/C,CAA2BplE,6CAErC,IAAIkoE,EAAUloE,EAAQriC,KAAK,eAEvBwqG,QAAgB1/H,KAAK+6H,aAAaE,kBAAkB,mBAAoBwE,GAC5E7zG,QAAQmsG,MAAM,YAAc2H,GAGb,MAAXA,GACAnoE,EAAQ2/D,kBAAkBwI,EAElC,IAEc,kBAAAC,CAAmBpoE,EAAe+kE,6CAE5C,IAEI,GAAqB,SAAjBA,EAEA,YADA/kE,EAAQriC,KAAK,0BAA2B,IAI5C,MAAMmiG,EAAW,oBAAoBiF,QAC/BhF,QAAiBC,MAAMF,GAE7B,IAAKC,EAASE,GACV,MAAM,IAAIxuH,MAAM,sCAAsCsuH,EAASG,UAEnE,MAAMC,QAAmBJ,EAASn/F,OAE5BynG,EAAoBhI,mBAAmBF,GAEzCngE,EAAQriC,KAAK,gBACbqiC,EAAQriC,KAAK,CACT2iG,aAAc,CACV,aAAc,mCAAmC+H,IACjDpvH,MAAO,GACPC,OAAQ,GACRovH,KAAM,MACNC,KAAM,SAIdvoE,EAAQ4/D,gBAAgBmF,EAEhC,CAAE,MAAOn6F,GACLvW,QAAQuW,MAAM,gCAAiCA,EACnD,CACJ,IAGc,cAAA06F,CAAez1E,mDAErBq4E,EAA0B,QAAhB,EAAAr4E,EAAK0T,SAAS,UAAE,eAAE5nC,MAAMiF,KAAKA,KAGvCunG,QAAgB1/H,KAAK+6H,aAAaE,kBAAkB,mBAAoBwE,GAI7D,MAAXC,GACAt4E,EAAKsJ,MAAM,EAAG,CACVx9B,MAAO,CACHiF,KAAM,CACFA,KAAMunG,KAK1B,IAEc,kBAAAhD,CAAmBnlE,6CAE7B,IAAIwoE,EAAWxoE,EAAQriC,KAAK,aAExB8jB,QAAch5C,KAAK+6H,aAAaE,kBAAkB,sBAAuB8E,GAGzE/mF,GACAue,EAAQriC,KAAK,YAAa8jB,EAElC,IAEQ,gBAAA0lF,CAAiBsB,GACrB,OAAQA,GACJ,KAAKrK,GAAUsK,eACX,OAAO,IAAIA,GAEf,KAAKtK,GAAUuK,iBACX,OAAO,IAAIA,GAEf,KAAKvK,GAAUwK,YACX,OAAO,IAAIA,GAEf,KAAKxK,GAAUyK,aACX,OAAO,IAAIA,GAEf,KAAKzK,GAAU0K,oBACX,OAAO,IAAIC,GAEf,KAAK3K,GAAU4K,IACX,OAAO,IAAIC,GAEf,KAAK7K,GAAU8K,MACX,OAAO,IAAIpE,GAEf,QACI,OAAO,IAAI4D,GAGvB,CAEA,WAAA3tI,CAAYqlC,GArrCK,KAAAhtB,UAAY,EAQrB,KAAAyuH,WAA8B,KAE9B,KAAA0E,iBAAoC,KAEpC,KAAAD,wBAAkD,KAElD,KAAAD,gBAA4C,KAC5C,KAAA8C,6BAAuC,EAEvC,KAAA3C,mBAAoC,KAEpC,KAAAxE,eAAkD,KAClD,KAAAC,qBAA8C,KAE9C,KAAAmH,iBAAoD,KAgqCxD3gI,KAAKinD,MAAQ,IAAI,GAAgB,CAAC,EAAG,CAAEkd,cAAenkE,KAAK2K,YAE3D3K,KAAKinD,MAAMz9C,GAAG,qBAAsB+0C,IAAD,IAInCv+C,KAAKsjD,MAAQ,IAAI,GAAgB,CAC7Bj7C,GAAIsvB,EAAQ6mG,UACZ7gF,MAAO39C,KAAKinD,MACZz2C,MAAO,KACPC,OAAQ,KACRzD,SAAU,GACV4oG,SAAU,CACNz+G,KAAM,MAAO8J,KAAM,CAAE+3C,MAAO,UAEhC46B,YAAa,CACTgtD,UAAU,EACVnoB,WAAW,GAEfxO,YAAY,EACZ9J,aAAa,EACbwY,cAAe,EACfb,mBAAmB,EACnB0B,kBAAmBx5G,KAAK2K,YAG5B3K,KAAK+6H,aAAepjG,EAAQojG,aAC5B/6H,KAAK65H,gBAAkBliG,EAAQkiG,gBAC/B75H,KAAKw+H,UAAY7mG,EAAQ6mG,UAEzB5yG,QAAQmsG,MAAM,oBAAsBpgG,EAAQkiG,iBAE5C,IAAIgH,EAAe,IAAI,GAAyB,CAC5CvP,WAAY,GACZzrH,iBAAiB,IAGjBi7H,EAAe,IAAI,GAAyB,CAC5CxP,WAAY,GACZzrH,iBAAiB,IAGjBw1E,EAAY,IAAI,GAAoB,CACpCy+B,MAAO,CACH+mB,EACAC,KAIR9gI,KAAKsjD,MAAM95C,GAAG,mBAAmB,SAAUusE,GACvCA,EAASwF,SAASF,EACtB,IAEAr7E,KAAKsjD,MAAM95C,GAAG,mBAAmB,KAC7BxJ,KAAKsjD,MAAM23B,aAAa,IAG5Bj7E,KAAKsjD,MAAM95C,GAAG,CACV,qBAAsB,CAAC8lE,EAAU1pE,KAGzB0pE,EAAS3xB,iBAAiB24E,IACvBt2H,KAAK49H,iBACL59H,KAAK49H,gBAAgBtoG,IAAMg6C,EAAS3xB,MAAMroB,IAC1Ct1B,KAAKo5H,cAAcnB,KAGhB3oD,EAAS3xB,iBAAiBuiF,IAAqBlgI,KAAKo5H,YAAcpB,GAASE,SAI7E,GAA4Bt9H,IAAI00E,EAAU,OAAQ,0BAA2B,CAAE90C,UAAW,gBAC1Fx6B,KAAK0gI,6BAA8B,GAJnCpxD,EAAS3xB,MAAMzoB,KAAK,cAAe,CAAE/9B,KAAM,YAAa8J,KAAM,CAAE+3C,MAAO,SAAUxoC,MAAO,EAAGslC,QAAS,IAAMoD,KAAM,KAMxH,EAEJ,qBAAsB,CAACo2B,EAAU1pE,KAGzB0pE,EAAS3xB,iBAAiB24E,IACvBt2H,KAAK49H,iBACL59H,KAAK49H,gBAAgBtoG,IAAMg6C,EAAS3xB,MAAMroB,IAC1Ct1B,KAAKo5H,cAAcnB,IAEtB3oD,EAAS3xB,MAAMzoB,KAAK,cAAe,MAGvC,GAA4B3wB,OAAO+qE,EAAU,2BAC7CtvE,KAAK0gI,6BAA8B,CAAK,EAE5C,oBAAqB,CAACpxD,EAAU1pE,KAC5BA,EAAIC,kBACJ+lB,QAAQmzG,IAAI,qBAAqB,EAErC,uBAAwB,CAAOzvD,EAAU1pE,EAAKuI,EAAGH,IAAM,GAAD,kDAElD,GADApI,EAAIC,kBACA7F,KAAK0gI,4BAEL,OAGJ90G,QAAQmzG,IAAI,+CAAoE,QAApB,EAAA/+H,KAAK49H,uBAAe,eAAEtoG,KAClFt1B,KAAK24H,aAEL,MAAMphE,EAAU+X,EAAS3xB,MAGzB,GAAI39C,KAAK49H,iBAAmB59H,KAAK49H,iBAAmBrmE,EAAS,CAEzD,GAAIv3D,KAAKo5H,YAAcpB,GAASG,gBAAkBn4H,KAAK49H,2BAA2BtH,IAAQ/+D,aAAmB++D,GAEzGt2H,KAAK05H,eAAe15H,KAAK49H,gBAAiBrmE,EAASv3D,KAAK69H,8BACrD,GAAI79H,KAAKo5H,YAAcpB,GAASE,QAEnCl4H,KAAKo6H,QAAQp6H,KAAK49H,gBAAiBrmE,EAASv3D,KAAK89H,uBAC9C,GAAI99H,KAAKo5H,YAAcpB,GAASI,YAAa,CAEhD,IAAIyC,EAA0D,QAAvC,EAAA76H,KAAK49H,gBAAyBrH,iBAAS,QAAI,GAC9DuE,EAA6C,QAA1B,EAAAvjE,EAAiBg/D,iBAAS,QAAI,GACjD0H,EAAej+H,KAAK49H,gBAAyB1oG,KAAK,cAClDgpG,EAAe3mE,EAAiBriC,KAAK,oBACnCl1B,KAAK+6H,aAAaE,kBAAkB,iCAAkCJ,EAAiBC,EAAiBmD,EAAaC,EAC/H,MAAWl+H,KAAKo5H,YAAcpB,GAASK,aAE/BwC,EAA0D,QAAvC,EAAA76H,KAAK49H,gBAAyBrH,iBAAS,QAAI,GAC9DuE,EAA6C,QAA1B,EAAAvjE,EAAiBg/D,iBAAS,QAAI,GACjD0H,EAAej+H,KAAK49H,gBAAyB1oG,KAAK,cAClDgpG,EAAe3mE,EAAiBriC,KAAK,oBACnCl1B,KAAK+6H,aAAaE,kBAAkB,iCAAkCJ,EAAiBC,EAAiBmD,EAAaC,IACpHl+H,KAAKo5H,YAAcpB,GAASM,eAE/BuC,EAA0D,QAAvC,EAAA76H,KAAK49H,gBAAyBrH,iBAAS,QAAI,GAC9DuE,EAA6C,QAA1B,EAAAvjE,EAAiBg/D,iBAAS,QAAI,GACjD0H,EAAej+H,KAAK49H,gBAAyB1oG,KAAK,cAClDgpG,EAAe3mE,EAAiBriC,KAAK,oBACnCl1B,KAAK+6H,aAAaE,kBAAkB,sBAAuBJ,EAAiBC,EAAiB96H,KAAK+9H,qBAG5G/9H,KAAK+6H,aAAaE,kBAAkB,sBAGpCj7H,KAAKw/H,eACT,MAEIx/H,KAAK47H,SAASrkE,EAAS3xD,EAAIm7H,MAAOn7H,EAAIo7H,MAE9C,IACA,oBAAqB,CAAC1xD,EAAU1pE,KAC5BA,EAAIC,kBACJ+lB,QAAQmzG,IAAI,sBACZ/+H,KAAK24H,aAEL,IAAIvxE,EAAOkoB,EAAS3xB,MACpB39C,KAAK47H,SAASx0E,EAAMxhD,EAAIm7H,MAAOn7H,EAAIo7H,MAAM,EAE7C,sBAAuB,CAAC1xD,EAAU1pE,EAAKuI,EAAGH,KAGtC4d,QAAQmzG,IAAI,wBACZ/+H,KAAK24H,aACL34H,KAAKw/H,eAAe,EAQxB,oBAAqB,CAAC55H,EAAKuI,EAAGH,KAM1B,GAHA4d,QAAQmzG,IAAI,sBACZ/+H,KAAK24H,aAED34H,KAAKo5H,YAAcpB,GAASqB,cAC5Br5H,KAAKu5H,eAAiB,CAAEprH,EAAGA,EAAGH,EAAGA,GACjC4d,QAAQmsG,MAAM,+BAEb,CACD/3H,KAAKw/H,gBAGL,IAAIjzH,EAAQvM,KAAKsjD,MAAM/2C,QACvBvM,KAAK2gI,iBAAmB,CAAExyH,EAAGA,EAAI5B,EAAM6F,GAAIpE,EAAGA,EAAIzB,EAAM8F,GAC5D,GAEJ,kBAAmB,CAAOzM,EAAKuI,EAAGH,IAAM,GAAD,sCAGnC4d,QAAQmzG,IAAI,oBACZ/+H,KAAK24H,aAED34H,KAAKo5H,YAAcpB,GAASqB,eAAiBr5H,KAAKu5H,gBAClDv5H,KAAKu5H,eAAiB,KACG,QAAzB,EAAAv5H,KAAKw5H,4BAAoB,SAAExC,SAAS,sBACpCh3H,KAAKw5H,qBAAuB,WACtBx5H,KAAK+6H,aAAaE,kBAAkB,oBAAoB,IAG9Dj7H,KAAK2gI,iBAAmB,IAEhC,IACA,oBAAqB,CAAC/6H,EAAKuI,EAAGH,KAE1B4d,QAAQmzG,IAAI,sBACR/+H,KAAKo5H,YAAcpB,GAASqB,eAC5Br5H,KAAKs5H,cAAc1zH,EAAKuI,EAAGH,EAC/B,EAEJ,6BAA8B,CAACshE,EAAU1pE,KACrCA,EAAIC,kBACJ+lB,QAAQmzG,IAAI,+BACZ/+H,KAAK24H,aACL34H,KAAKg8H,yBAAyB1sD,EAAS3xB,MAAM,IASrD39C,KAAKw+H,UAAUzzH,iBAAiB,aAAcnF,IACtC5F,KAAK2gI,kBACL3gI,KAAKsjD,MAAMzwC,UACPjN,EAAI6gF,QAAUzmF,KAAK2gI,iBAAiBxyH,EACpCvI,EAAI8gF,QAAU1mF,KAAK2gI,iBAAiB3yH,EAC5C,IAKJhO,KAAKsjD,MAAM95C,GAAG,oBAAoB,CAAC5D,EAAKuI,EAAGH,EAAGgjC,KAC1CprC,EAAID,iBACJ,MAAMs7H,EAAWjhI,KAAKsjD,MAAM/2C,QAAQ6F,GAC9B8uH,EAAWD,EAAW,GAAMjwF,EAAQiwF,EAEtCC,EAAW,IAAOA,EAAW,IAC7BlhI,KAAKsjD,MAAM/2C,MAAM20H,EAAUA,GAC3BlhI,KAAKsjD,MAAMzwC,WAAW1E,EAAI+yH,EAAWt7H,EAAI6gF,SAAUz4E,EAAIkzH,EAAWt7H,EAAI8gF,SAC1E,IAIJxgF,OAAO6E,iBAAiB,UAAU,KAC9B6gB,QAAQmzG,IAAI,iBACZ,IAAIvS,EAAexsH,KAAKsjD,MAAM/2C,QAC9BvM,KAAKsjD,MAAMmgE,sBAAsB,CAAEQ,cAAe,SAAUC,gBAAiB,SAAUH,SAAUyI,EAAap6G,GAAI4xG,SAAUwI,EAAap6G,IAAK,GAEtJ,CAEO,OAAA+uH,GACHnhI,KAAK24H,YACT,EAGG,SAASyI,GAAiBzpG,GAC7B,OAAO,IAAI4gG,GAAW5gG,EAC1B,CAEO,MAAM0pG,GAKT,WAAA/uI,CAAYqlC,GAJK,KAAAhtB,UAAY,EAKzB3K,KAAKinD,MAAQ,IAAI,GAAgB,CAAC,EAAG,CAAEkd,cAAenkE,KAAK2K,YAE3D3K,KAAKsjD,MAAQ,IAAI,GAAgB,CAC7Bj7C,GAAIsvB,EAAQ6mG,UACZ7gF,MAAO39C,KAAKinD,MACZz2C,MAAOmnB,EAAQ6mG,UAAUzxF,YACzBt8B,OAAQknB,EAAQ6mG,UAAUpxF,aAC1BwmC,aAAa,EACb4lC,kBAAmBx5G,KAAK2K,YAG5B3K,KAAKsjD,MAAM3F,MAAM8nB,SAAS9+B,KAAKxoB,MAAMwZ,EAAQ+gG,WAAY,CAAEv0D,cAAenkE,KAAK2K,YAC/E3K,KAAKsjD,MAAMmgE,sBAAsB,CAAEQ,cAAe,SAAUC,gBAAiB,SAAUF,SAAU,GACrG,EAGG,SAASsd,GAAkB3pG,GAC9B,IAEI,OADkBgP,KAAKxoB,MAAMwZ,EAAQ+gG,WAC9B,IAAI2I,GAAY1pG,EAC3B,CAAE,MAAOwK,GACLvW,QAAQuW,MAAM,qBAAsBA,GACpCvW,QAAQuW,MAAM,WAAYxK,EAC9B,CACJ,CAIO,MAAMmkG,WAAqBxF,GAC9B,QAAAz1H,GACI,MAAO,CACH1O,KAAM,eACNwgC,IAAK,GACLO,MAAO,CACHxrB,KAAM,CACFwyD,KAAM,QACNhV,OAAQ,QACR8Y,YAAa,EACbxtD,MAAO,UACPC,OAAQ,UACRgG,GAAI,GACJC,GAAI,GACJ6qH,MAAO,wBAEX7wE,MAAO,CAKH1C,WAAY,SACZv1B,mBAAoB,SACpBtqB,EAAG,cACHH,EAAG,cACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,+BAGd+4B,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,QAEd,CACIu1B,QAAS,OACTv1B,SAAU,UAGtB,EAEJvb,OAAOgP,OAAO,EAAc,CAAE8hI,kBAEvB,MAAMC,WAAwBzF,GACjC,QAAAz1H,GACI,MAAO,CACH1O,KAAM,kBACN2mI,QAAS,8BACT5lG,MAAO,CACHxrB,KAAM,CACFwyD,KAAM,OACNhV,OAAQ,QACR8Y,YAAa,EACbxtD,MAAO,UACPC,OAAQ,UACRgG,GAAI,cACJC,GAAI,cACJmgB,GAAI,cACJC,GAAI,cACJyqG,MAAO,wBAEX7wE,MAAO,CACH1C,WAAY,SACZv1B,mBAAoB,SACpBtqB,EAAG,cACHH,EAAG,cACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,oCAGd+4B,OAAQ,CAAC,CACLp1B,QAAS,UACTv1B,SAAU,QAEd,CACIu1B,QAAS,OACTv1B,SAAU,UAGtB,EAEJvb,OAAOgP,OAAO,EAAc,CAAE+hI,qBAGvB,MAAMkE,WAAuB3J,GAChC,QAAAz1H,GACI,MAAO,CACH1O,KAAM,iBACN2mI,QAAS,yBACT5lG,MAAO,CACHxrB,KAAM,CACFwyD,KAAM,UACNhV,OAAQ,QACR8Y,YAAa,EACbxtD,MAAO,UACPC,OAAQ,UACRgG,GAAI,GACJC,GAAI,IAERg6C,MAAO,CACH1C,WAAY,SACZv1B,mBAAoB,SACpBtqB,EAAG,cACHH,EAAG,cACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,eAEVupG,OAAQ,CACJ1zE,WAAY,SACZv1B,mBAAoB,SACpBtqB,EAAG,cACHH,EAAG,eACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZrpG,KAAM,KAGd+4B,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,QACX,CACCu1B,QAAS,OACTv1B,SAAU,SACX,CACCu1B,QAAS,OACTv1B,SAAU,WAGtB,EAEJvb,OAAOgP,OAAO,EAAc,CAAEimI,oBAGvB,MAAMC,WAAyB5J,GAClC,QAAAz1H,GACI,MAAO,CACH1O,KAAM,mBACN2mI,QAAS,8BACT5lG,MAAO,CACHxrB,KAAM,CACFwyD,KAAM,OACNhV,OAAQ,QACR8Y,YAAa,EACbxtD,MAAO,UACPC,OAAQ,UACRgG,GAAI,cACJC,GAAI,cACJmgB,GAAI,cACJC,GAAI,eAER45B,MAAO,CACH1C,WAAY,SACZv1B,mBAAoB,SACpBtqB,EAAG,cACHH,EAAG,cACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,eAEVupG,OAAQ,CACJ1zE,WAAY,SACZv1B,mBAAoB,SACpBtqB,EAAG,cACHH,EAAG,eACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZrpG,KAAM,KAGd+4B,OAAQ,CAAC,CACLp1B,QAAS,UACTv1B,SAAU,QACX,CACCu1B,QAAS,OACTv1B,SAAU,SACX,CACCu1B,QAAS,OACTv1B,SAAU,WAGtB,CAEA,sBAAAowH,CAAuBC,GAEnB52H,KAAKy2H,SAAST,GAAcI,gBAChC,EAEJprI,OAAOgP,OAAO,EAAc,CAAEkmI,sBAGvB,MAAMC,WAAoB7J,GAC7B,QAAAz1H,GACI,MAAO,CACH1O,KAAM,cACN2mI,QAAS,yBACT5lG,MAAO,CACHxrB,KAAM,CACFwyD,KAAM,UACNhV,OAAQ,QACR8Y,YAAa,EACbxtD,MAAO,UACPC,OAAQ,UACRV,OAAQ,2CAEZ2gD,MAAO,CACH1C,WAAY,SACZv1B,mBAAoB,SACpBqnG,KAAM,IACN3xH,EAAG,cACHH,EAAG,cACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,eAEVupG,OAAQ,CACJ1zE,WAAY,SACZv1B,mBAAoB,SACpBqnG,KAAM,IACN3xH,EAAG,cACHH,EAAG,eACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZrpG,KAAM,KAGd+4B,OAAQ,CAAC,CACLp1B,QAAS,UACTv1B,SAAU,QACX,CACCu1B,QAAS,OACTv1B,SAAU,SACX,CACCu1B,QAAS,OACTv1B,SAAU,WAGtB,EAEJvb,OAAOgP,OAAO,EAAc,CAAEmmI,iBAIvB,MAAMC,WAAqB9J,GAC9B,QAAAz1H,GACI,MAAO,CACH1O,KAAM,eACN2mI,QAAS,0BACT5lG,MAAO,CACHxrB,KAAM,CACFwyD,KAAM,UACNhV,OAAQ,QACR8Y,YAAa,EACbxtD,MAAO,UACPC,OAAQ,UACRqG,EAAG,iGAEP45C,MAAO,CACH1C,WAAY,SACZv1B,mBAAoB,SACpBtqB,EAAG,cACHH,EAAG,cACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,eAEVupG,OAAQ,CACJ1zE,WAAY,SACZv1B,mBAAoB,SACpBtqB,EAAG,cACHH,EAAG,eACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZrpG,KAAM,KAGd+4B,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,QACX,CACCu1B,QAAS,OACTv1B,SAAU,SACX,CACCu1B,QAAS,OACTv1B,SAAU,WAGtB,EAEJvb,OAAOgP,OAAO,EAAc,CAAEomI,kBAGvB,MAAME,WAAsBhK,GAC/B,QAAAz1H,GACI,MAAO,CACH1O,KAAM,gBACN2mI,QAAS,2BACT5lG,MAAO,CACHxrB,KAAM,CACFwyD,KAAM,UACNhV,OAAQ,QACR8Y,YAAa,EACbxtD,MAAO,UACPC,OAAQ,UACRulB,UAAW,kCACXlf,EAAG,iGAEP45C,MAAO,CACH1C,WAAY,SACZv1B,mBAAoB,SACpBtqB,EAAG,cACHH,EAAG,cACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,eAEVupG,OAAQ,CACJ1zE,WAAY,SACZv1B,mBAAoB,SACpBtqB,EAAG,cACHH,EAAG,eACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZrpG,KAAM,KAGd+4B,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,QACX,CACCu1B,QAAS,OACTv1B,SAAU,SACX,CACCu1B,QAAS,OACTv1B,SAAU,WAGtB,EAEJvb,OAAOgP,OAAO,EAAc,CAAEsmI,mBAGvB,MAAME,WAAoBlK,GAC7B,QAAAz1H,GACI,MAAO,CACH1O,KAAM,cACN2mI,QAAS,yBACT5lG,MAAO,CACHxrB,KAAM,CACFwyD,KAAM,UACNhV,OAAQ,QACR8Y,YAAa,EACbxtD,MAAO,UACPC,OAAQ,UACRgG,GAAI,GACJC,GAAI,IAERirH,MAAO,CACHznE,KAAM,cACNhV,OAAQ,QACR8Y,YAAa,EACbvnD,GAAI,cACJC,GAAI,cACJmgB,GAAI,cACJC,GAAI,eAER45B,MAAO,CACH1C,WAAY,SACZv1B,mBAAoB,SACpBtqB,EAAG,cACHH,EAAG,cACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,eAEVupG,OAAQ,CACJ1zE,WAAY,SACZv1B,mBAAoB,SACpBtqB,EAAG,cACHH,EAAG,eACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZrpG,KAAM,KAGd+4B,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,QACX,CACCu1B,QAAS,UACTv1B,SAAU,SACX,CACCu1B,QAAS,OACTv1B,SAAU,SACX,CACCu1B,QAAS,OACTv1B,SAAU,WAGtB,EAEJvb,OAAOgP,OAAO,EAAc,CAAEwmI,iBAGvB,MAAMnE,WAAoB/F,GAC7B,QAAAz1H,GACI,MAAO,CACH1O,KAAM,cACN2mI,QAAS,yBACT5lG,MAAO,CACHxrB,KAAM,CACFwyD,KAAM,UACNhV,OAAQ,QACR8Y,YAAa,EACbxtD,MAAO,UACPC,OAAQ,UACRgG,GAAI,GACJC,GAAI,GACJvI,GAAI,EACJH,GAAI,GAER2zH,MAAO,CACHznE,KAAM,UACNhV,OAAQ,QACR8Y,YAAa,EACbxtD,MAAO,UACPC,OAAQ,UACRgG,GAAI,GACJC,GAAI,GACJvI,EAAG,EACHH,EAAG,GAEP0iD,MAAO,CACH1C,WAAY,SACZv1B,mBAAoB,SACpBtqB,EAAG,cACHH,EAAG,cACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,IAEVupG,OAAQ,CACJ1zE,WAAY,SACZv1B,mBAAoB,SACpBtqB,EAAG,cACHH,EAAG,eACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZrpG,KAAM,KAGd+4B,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,SAEd,CACIu1B,QAAS,OACTv1B,SAAU,QAEd,CACIu1B,QAAS,OACTv1B,SAAU,SAEd,CACIu1B,QAAS,OACTv1B,SAAU,WAGtB,CAEA,QAAAkwH,CAASz9E,GACLh5C,KAAKk1B,KAAK,YAAa8jB,GACvBh5C,KAAKk1B,KAAK,aAAc8jB,EAC5B,CAEA,sBAAA29E,CAAuBC,GACnB,OAAQA,GACJ,KAAKd,GAAae,GACd72H,KAAKy2H,SAAST,GAAcC,cAC5B,MACJ,KAAKH,GAAagB,MACd92H,KAAKy2H,SAAST,GAAcE,gBAC5B,MACJ,KAAKJ,GAAaiB,MACd/2H,KAAKk1B,KAAK,YAAa8gG,GAAcC,cACrCj2H,KAAKk1B,KAAK,aAAc8gG,GAAcE,gBACtC,MACJ,QACIl2H,KAAKy2H,SAAST,GAAcC,cAGxC,EAEJjrI,OAAOgP,OAAO,EAAc,CAAEqiI,iBAGvB,MAAM5C,WAAuB,GAChC,QAAA54H,GACI,MAAO,CACH1O,KAAM,iBACN+gC,MAAO,CACHxrB,KAAM,CACFwyD,KAAM,OACNhV,OAAQ,QACR8Y,YAAa,EACbxtD,MAAO,UACPC,OAAQ,WAEZ,mBAAoB,CAChBW,IAAK,QACL8oD,KAAM,QACNhV,OAAQ,UACR8Y,YAAa,EACbxtD,MAAO,aACPC,OAAQ,aACRtC,EAAG,YACHH,EAAG,YACHyI,GAAI,EACJC,GAAI,GAERg6C,MAAO,CACH1C,WAAY,SACZv1B,mBAAoB,MACpBtqB,EAAG,cACHH,EAAG,KACHksD,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,GACN4lC,OAAQ,OACR50D,MAAO,+BAGf+nD,OAAQ,CAAC,CACLp1B,QAAS,OACTv1B,SAAU,QAEd,CACIu1B,QAAS,OACTv1B,SAAU,oBACX,CACCu1B,QAAS,OACTv1B,SAAU,UAGtB,CAEO,QAAAywH,CAAStmE,GACZ1wD,KAAKk1B,KAAK,aAAcw7B,EAC5B,EAGJ1lE,OAAOgP,OAAO,EAAc,CAAEy/H,oBAEvB,MAAMmI,WAAqB,GAC9B,QAAA/gI,GACI,OAAO,GAAwB,CAC3B1O,KAAM,eACN6mD,MAAO,UACP9lB,MAAO,CACH1e,KAAM,CACF0wC,OAAQ,UACR8Y,YAAa,EACbqC,aAAc,CACVvpD,EAAG,wBAIfgkD,OAAQ,CAAC,CACL5nC,MAAO,CACHjd,KAAM,CACF7E,IAAK,OACLZ,MAAO,aACPC,OAAQ,aACRtC,EAAG,YACHH,EAAG,YACHk3C,OAAQ,UACR6Y,OAAQ,WAEZ5lC,KAAM,CACF61B,WAAY,SACZv1B,mBAAoB,SACpByhC,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,gBAInB,GAA2B7sC,UAAUuV,SAC5C,EAGG,MAAMghI,WAAkB,GAC3B,QAAAhhI,GACI,OAAO,GAAwB,CAC3B1O,KAAM,YACN6mD,MAAO,UACP8oF,QAAQ,EACR5uG,MAAO,CACH1e,KAAM,CACF0wC,OAAQ,UACR8Y,YAAa,EACb+jE,gBAAiB,OACjB1hE,aAAc,CACVvpD,EAAG,wBAIfgkD,OAAQ,CAAC,CACL5nC,MAAO,CACHjd,KAAM,CACF7E,IAAK,OACLZ,MAAO,aACPC,OAAQ,aACRtC,EAAG,YACHH,EAAG,YACHk3C,OAAQ,UACR6Y,OAAQ,WAEZ5lC,KAAM,CACF61B,WAAY,SACZv1B,mBAAoB,SACpByhC,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,mBAInB,GAA2B7sC,UAAUuV,SAC5C,EAGG,MAAMmhI,WAAoB,GAC7B,QAAAnhI,GACI,OAAO,GAAwB,CAC3B1O,KAAM,cACN6mD,MAAO,UACP8oF,QAAQ,EACR5uG,MAAO,CACH1e,KAAM,CACF0wC,OAAQ,UACR8Y,YAAa,EACb+jE,gBAAiB,OACjB1hE,aAAc,CACVvpD,EAAG,wBAIfgkD,OAAQ,CAAC,CACL5nC,MAAO,CACHjd,KAAM,CACF7E,IAAK,OACLZ,MAAO,aACPC,OAAQ,aACRtC,EAAG,YACHH,EAAG,YACHk3C,OAAQ,UACR6Y,OAAQ,WAEZ5lC,KAAM,CACF61B,WAAY,SACZv1B,mBAAoB,SACpByhC,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,eAInB,GAA2B7sC,UAAUuV,SAC5C,EAsKJ,MAAMk4H,WAA0B,GAC5B,QAAAl4H,GACI,OAAO,GAAwB,CAC3B1O,KAAM,oBACN6mD,MAAO,UACP8oF,QAAQ,EACR5uG,MAAO,CACH1e,KAAM,CACF0wC,OAAQ,UACR8Y,YAAa,EACb+jE,gBAAiB,OACjB1hE,aAAc,CACVvpD,EAAG,wBAIfgkD,OAAQ,CAAC,CACL5nC,MAAO,CACHjd,KAAM,CACF7E,IAAK,OACLZ,MAAO,aACPC,OAAQ,aACRtC,EAAG,YACHH,EAAG,YACHk3C,OAAQ,UACR6Y,OAAQ,WAEZ5lC,KAAM,CACF61B,WAAY,SACZv1B,mBAAoB,SACpByhC,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,qBAInB,GAA2B7sC,UAAUuV,SAC5C,EAGJ7V,OAAOgP,OAAO,EAAc,CAAE4nI,gBAAcC,aAAWG,eAAaC,YA7MpE,cAA0B,GACtB,QAAAphI,GACI,OAAO,GAAwB,CAC3B1O,KAAM,cACN6mD,MAAO,QACP9lB,MAAO,CACH1e,KAAM,CACF0wC,OAAQ,QACR8Y,YAAa,EACbqC,aAAc,CACVvpD,EAAG,wBAIfgkD,OAAQ,CAAC,CACL5nC,MAAO,CACHjd,KAAM,CACF7E,IAAK,OACLZ,MAAO,aACPC,OAAQ,aACRtC,EAAG,YACHH,EAAG,YACHk3C,OAAQ,UACR6Y,OAAQ,WAEZ5lC,KAAM,CACF61B,WAAY,SACZv1B,mBAAoB,SACpByhC,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,eAInB,GAA2B7sC,UAAUuV,SAC5C,GAwK6EqhI,eArKjF,cAA6B,GACzB,QAAArhI,GACI,OAAO,GAAwB,CAC3B1O,KAAM,iBACN6mD,MAAO,UACP9lB,MAAO,CACH1e,KAAM,CACF0wC,OAAQ,UACR8Y,YAAa,EACbqC,aAAc,CACVvpD,EAAG,wBAIfgkD,OAAQ,CAAC,CACL5nC,MAAO,CACHjd,KAAM,CACF7E,IAAK,OACLZ,MAAO,aACPC,OAAQ,aACRtC,EAAG,YACHH,EAAG,YACHk3C,OAAQ,UACR6Y,OAAQ,WAEZ5lC,KAAM,CACF61B,WAAY,SACZv1B,mBAAoB,SACpByhC,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,mBAInB,GAA2B7sC,UAAUuV,SAC5C,GAgI6FshI,cA7HjG,cAA4B,GACxB,QAAAthI,GACI,OAAO,GAAwB,CAC3B1O,KAAM,gBACN6mD,MAAO,UACP9lB,MAAO,CACH1e,KAAM,CACF0wC,OAAQ,UACR8Y,YAAa,EACbqC,aAAc,CACVvpD,EAAG,wBAIfgkD,OAAQ,CAAC,CACL5nC,MAAO,CACHjd,KAAM,CACF7E,IAAK,OACLZ,MAAO,aACPC,OAAQ,aACRtC,EAAG,YACHH,EAAG,YACHk3C,OAAQ,UACR6Y,OAAQ,WAEZ5lC,KAAM,CACF61B,WAAY,SACZv1B,mBAAoB,SACpByhC,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,kBAInB,GAA2B7sC,UAAUuV,SAC5C,GAwF4GuhI,cArFhH,cAA4B,GACxB,QAAAvhI,GACI,OAAO,GAAwB,CAC3B1O,KAAM,gBACN6mD,MAAO,UACP9lB,MAAO,CACH1e,KAAM,CACF0wC,OAAQ,UACR8Y,YAAa,EACbqC,aAAc,CACVvpD,EAAG,sBAEP2pD,aAAc,CACV3pD,EAAG,wBAIfgkD,OAAQ,CAAC,CACL5nC,MAAO,CACHjd,KAAM,CACF7E,IAAK,OACLZ,MAAO,aACPC,OAAQ,aACRtC,EAAG,YACHH,EAAG,YACHk3C,OAAQ,UACR6Y,OAAQ,WAEZ5lC,KAAM,CACF61B,WAAY,SACZv1B,mBAAoB,SACpByhC,KAAM,QACNvlC,SAAU,GACV6sG,WAAY,0BACZC,WAAY,OACZtpG,KAAM,iBAInB,GAA2B7sC,UAAUuV,SAC5C,GA6C2Hk4H","sources":["webpack://vca/webpack/bootstrap","webpack://vca/webpack/runtime/define property getters","webpack://vca/webpack/runtime/hasOwnProperty shorthand","webpack://vca/webpack/runtime/make namespace object","webpack://vca/./node_modules/@joint/core/src/util/utilHelpers.mjs","webpack://vca/./node_modules/@joint/core/src/mvc/Data.mjs","webpack://vca/./node_modules/@joint/core/src/mvc/Dom/vars.mjs","webpack://vca/./node_modules/@joint/core/src/mvc/Dom/Event.mjs","webpack://vca/./node_modules/@joint/core/src/mvc/Dom/Dom.mjs","webpack://vca/./node_modules/@joint/core/src/g/geometry.helpers.mjs","webpack://vca/./node_modules/@joint/core/src/g/line.bearing.mjs","webpack://vca/./node_modules/@joint/core/src/g/line.squaredLength.mjs","webpack://vca/./node_modules/@joint/core/src/g/line.length.mjs","webpack://vca/./node_modules/@joint/core/src/g/types.mjs","webpack://vca/./node_modules/@joint/core/src/g/point.mjs","webpack://vca/./node_modules/@joint/core/src/g/line.mjs","webpack://vca/./node_modules/@joint/core/src/g/ellipse.mjs","webpack://vca/./node_modules/@joint/core/src/g/rect.mjs","webpack://vca/./node_modules/@joint/core/src/g/points.mjs","webpack://vca/./node_modules/@joint/core/src/g/polyline.mjs","webpack://vca/./node_modules/@joint/core/src/g/curve.mjs","webpack://vca/./node_modules/@joint/core/src/g/extend.mjs","webpack://vca/./node_modules/@joint/core/src/g/path.mjs","webpack://vca/./node_modules/@joint/core/src/g/bezier.mjs","webpack://vca/./node_modules/@joint/core/src/g/polygon.mjs","webpack://vca/./node_modules/@joint/core/src/g/intersection.mjs","webpack://vca/./node_modules/@joint/core/src/g/index.mjs","webpack://vca/./node_modules/@joint/core/src/V/index.mjs","webpack://vca/./node_modules/@joint/core/src/mvc/Dom/methods.mjs","webpack://vca/./node_modules/@joint/core/src/mvc/Dom/animations.mjs","webpack://vca/./node_modules/@joint/core/src/mvc/Dom/props.mjs","webpack://vca/./node_modules/@joint/core/src/config/index.mjs","webpack://vca/./node_modules/@joint/core/src/mvc/Dom/events.mjs","webpack://vca/./node_modules/@joint/core/src/mvc/Dom/index.mjs","webpack://vca/./node_modules/@joint/core/src/util/util.mjs","webpack://vca/./node_modules/@joint/core/src/mvc/Events.mjs","webpack://vca/./node_modules/@joint/core/src/mvc/mvcUtils.mjs","webpack://vca/./node_modules/@joint/core/src/mvc/Model.mjs","webpack://vca/./node_modules/@joint/core/src/util/cloneCells.mjs","webpack://vca/./node_modules/@joint/core/src/dia/attributes/props.mjs","webpack://vca/./node_modules/@joint/core/src/dia/attributes/legacy.mjs","webpack://vca/./node_modules/@joint/core/src/util/calc.mjs","webpack://vca/./node_modules/@joint/core/src/dia/attributes/text.mjs","webpack://vca/./node_modules/@joint/core/src/dia/attributes/connection.mjs","webpack://vca/./node_modules/@joint/core/src/dia/attributes/shape.mjs","webpack://vca/./node_modules/@joint/core/src/dia/attributes/defs.mjs","webpack://vca/./node_modules/@joint/core/src/dia/attributes/offset.mjs","webpack://vca/./node_modules/@joint/core/src/dia/attributes/index.mjs","webpack://vca/./node_modules/@joint/core/src/dia/Cell.mjs","webpack://vca/./node_modules/@joint/core/src/layout/ports/port.mjs","webpack://vca/./node_modules/@joint/core/src/layout/ports/portLabel.mjs","webpack://vca/./node_modules/@joint/core/src/dia/ports.mjs","webpack://vca/./node_modules/@joint/core/src/dia/Element.mjs","webpack://vca/./node_modules/@joint/core/src/dia/Link.mjs","webpack://vca/./node_modules/@joint/core/src/env/index.mjs","webpack://vca/./node_modules/@joint/core/src/shapes/standard.mjs","webpack://vca/./node_modules/@joint/core/src/util/getRectPoint.mjs","webpack://vca/./node_modules/@joint/core/src/mvc/Collection.mjs","webpack://vca/./node_modules/@joint/core/src/util/wrappers.mjs","webpack://vca/./node_modules/@joint/core/src/dia/Graph.mjs","webpack://vca/./node_modules/@joint/core/src/mvc/ViewBase.mjs","webpack://vca/./node_modules/@joint/core/src/mvc/View.mjs","webpack://vca/./node_modules/@joint/core/src/dia/HighlighterView.mjs","webpack://vca/./node_modules/@joint/core/src/dia/attributes/eval.mjs","webpack://vca/./node_modules/@joint/core/src/dia/CellView.mjs","webpack://vca/./node_modules/@joint/core/src/dia/ElementView.mjs","webpack://vca/./node_modules/@joint/core/src/routers/normal.mjs","webpack://vca/./node_modules/@joint/core/src/routers/oneSide.mjs","webpack://vca/./node_modules/@joint/core/src/routers/orthogonal.mjs","webpack://vca/./node_modules/@joint/core/src/routers/manhattan.mjs","webpack://vca/./node_modules/@joint/core/src/routers/metro.mjs","webpack://vca/./node_modules/@joint/core/src/routers/rightAngle.mjs","webpack://vca/./node_modules/@joint/core/src/connectors/straight.mjs","webpack://vca/./node_modules/@joint/core/src/connectors/jumpover.mjs","webpack://vca/./node_modules/@joint/core/src/connectors/normal.mjs","webpack://vca/./node_modules/@joint/core/src/connectors/rounded.mjs","webpack://vca/./node_modules/@joint/core/src/connectors/smooth.mjs","webpack://vca/./node_modules/@joint/core/src/connectors/curve.mjs","webpack://vca/./node_modules/@joint/core/src/dia/LinkView.mjs","webpack://vca/./node_modules/@joint/core/src/dia/PaperLayer.mjs","webpack://vca/./node_modules/@joint/core/src/highlighters/stroke.mjs","webpack://vca/./node_modules/@joint/core/src/highlighters/mask.mjs","webpack://vca/./node_modules/@joint/core/src/highlighters/opacity.mjs","webpack://vca/./node_modules/@joint/core/src/highlighters/addClass.mjs","webpack://vca/./node_modules/@joint/core/src/highlighters/list.mjs","webpack://vca/./node_modules/@joint/core/src/linkAnchors/index.mjs","webpack://vca/./node_modules/@joint/core/src/connectionPoints/index.mjs","webpack://vca/./node_modules/@joint/core/src/anchors/index.mjs","webpack://vca/./node_modules/@joint/core/src/dia/layers/GridLayer.mjs","webpack://vca/./node_modules/@joint/core/src/dia/Paper.mjs","webpack://vca/./node_modules/@joint/core/src/dia/ToolView.mjs","webpack://vca/./node_modules/@joint/core/src/linkTools/Vertices.mjs","webpack://vca/./node_modules/@joint/core/src/connectionStrategies/index.mjs","webpack://vca/./node_modules/@joint/core/src/linkTools/Segments.mjs","webpack://vca/./node_modules/@joint/core/src/cellTools/helpers.mjs","webpack://vca/./node_modules/@joint/core/src/dia/ToolsView.mjs","webpack://vca/./src/flows.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// code is inspired by https://github.com/lodash/lodash\n\n/* eslint-disable no-case-declarations */\n// -- helper constants\nconst argsTag = '[object Arguments]';\nconst arrayTag = '[object Array]';\nconst boolTag = '[object Boolean]';\nconst dateTag = '[object Date]';\nconst errorTag = '[object Error]';\nconst funcTag = '[object Function]';\nconst mapTag = '[object Map]';\nconst numberTag = '[object Number]';\nconst nullTag = '[object Null]';\nconst objectTag = '[object Object]';\nconst regexpTag = '[object RegExp]';\nconst setTag = '[object Set]';\nconst stringTag = '[object String]';\nconst symbolTag = '[object Symbol]';\nconst undefinedTag = '[object Undefined]';\nconst weakMapTag = '[object WeakMap]';\nconst arrayBufferTag = '[object ArrayBuffer]';\nconst dataViewTag = '[object DataView]';\nconst float32Tag = '[object Float32Array]';\nconst float64Tag = '[object Float64Array]';\nconst int8Tag = '[object Int8Array]';\nconst int16Tag = '[object Int16Array]';\nconst int32Tag = '[object Int32Array]';\nconst uint8Tag = '[object Uint8Array]';\nconst uint8ClampedTag = '[object Uint8ClampedArray]';\nconst uint16Tag = '[object Uint16Array]';\nconst uint32Tag = '[object Uint32Array]';\n\nconst CLONEABLE_TAGS = {\n    [argsTag]: true,\n    [arrayTag]: true,\n    [arrayBufferTag]: true,\n    [dataViewTag]: true,\n    [boolTag]: true,\n    [dateTag]: true,\n    [float32Tag]: true,\n    [float64Tag]: true,\n    [int8Tag]: true,\n    [int16Tag]: true,\n    [int32Tag]: true,\n    [mapTag]: true,\n    [numberTag]: true,\n    [objectTag]: true,\n    [regexpTag]: true,\n    [setTag]: true,\n    [stringTag]: true,\n    [symbolTag]: true,\n    [uint8Tag]: true,\n    [uint8ClampedTag]: true,\n    [uint16Tag]: true,\n    [uint32Tag]: true,\n    [errorTag]: false,\n    [funcTag]: false,\n    [weakMapTag]: false,\n};\n\n/** Used to compose unicode character classes. */\nconst rsAstralRange = '\\\\ud800-\\\\udfff';\nconst rsComboMarksRange = '\\\\u0300-\\\\u036f';\nconst reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f';\nconst rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff';\nconst rsComboMarksExtendedRange = '\\\\u1ab0-\\\\u1aff';\nconst rsComboMarksSupplementRange = '\\\\u1dc0-\\\\u1dff';\nconst rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange + rsComboMarksExtendedRange + rsComboMarksSupplementRange;\nconst rsDingbatRange = '\\\\u2700-\\\\u27bf';\nconst rsLowerRange = 'a-z\\\\xdf-\\\\xf6\\\\xf8-\\\\xff';\nconst rsMathOpRange = '\\\\xac\\\\xb1\\\\xd7\\\\xf7';\nconst rsNonCharRange = '\\\\x00-\\\\x2f\\\\x3a-\\\\x40\\\\x5b-\\\\x60\\\\x7b-\\\\xbf';\nconst rsPunctuationRange = '\\\\u2000-\\\\u206f';\nconst rsSpaceRange = ' \\\\t\\\\x0b\\\\f\\\\xa0\\\\ufeff\\\\n\\\\r\\\\u2028\\\\u2029\\\\u1680\\\\u180e\\\\u2000\\\\u2001\\\\u2002\\\\u2003\\\\u2004\\\\u2005\\\\u2006\\\\u2007\\\\u2008\\\\u2009\\\\u200a\\\\u202f\\\\u205f\\\\u3000';\nconst rsUpperRange = 'A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde';\nconst rsVarRange = '\\\\ufe0e\\\\ufe0f';\nconst rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;\n\n/** Used to compose unicode capture groups. */\nconst rsApos = '[\\'\\u2019]';\nconst rsBreak = `[${rsBreakRange}]`;\nconst rsCombo = `[${rsComboRange}]`;\nconst rsDigit = '\\\\d';\nconst rsDingbat = `[${rsDingbatRange}]`;\nconst rsLower = `[${rsLowerRange}]`;\nconst rsMisc = `[^${rsAstralRange}${rsBreakRange + rsDigit + rsDingbatRange + rsLowerRange + rsUpperRange}]`;\nconst rsFitz = '\\\\ud83c[\\\\udffb-\\\\udfff]';\nconst rsModifier = `(?:${rsCombo}|${rsFitz})`;\nconst rsNonAstral = `[^${rsAstralRange}]`;\nconst rsRegional = '(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}';\nconst rsSurrPair = '[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]';\nconst rsUpper = `[${rsUpperRange}]`;\nconst rsZWJ = '\\\\u200d';\n\n/** Used to compose unicode regexes. */\nconst rsMiscLower = `(?:${rsLower}|${rsMisc})`;\nconst rsMiscUpper = `(?:${rsUpper}|${rsMisc})`;\nconst rsOptContrLower = `(?:${rsApos}(?:d|ll|m|re|s|t|ve))?`;\nconst rsOptContrUpper = `(?:${rsApos}(?:D|LL|M|RE|S|T|VE))?`;\nconst reOptMod = `${rsModifier}?`;\nconst rsOptVar = `[${rsVarRange}]?`;\nconst rsOptJoin = `(?:${rsZWJ}(?:${[rsNonAstral, rsRegional, rsSurrPair].join('|')})${rsOptVar + reOptMod})*`;\nconst rsOrdLower = '\\\\d*(?:1st|2nd|3rd|(?![123])\\\\dth)(?=\\\\b|[A-Z_])';\nconst rsOrdUpper = '\\\\d*(?:1ST|2ND|3RD|(?![123])\\\\dTH)(?=\\\\b|[a-z_])';\nconst rsSeq = rsOptVar + reOptMod + rsOptJoin;\nconst rsEmoji = `(?:${[rsDingbat, rsRegional, rsSurrPair].join('|')})${rsSeq}`;\n\nconst reUnicodeWords = RegExp([\n    `${rsUpper}?${rsLower}+${rsOptContrLower}(?=${[rsBreak, rsUpper, '$'].join('|')})`,\n    `${rsMiscUpper}+${rsOptContrUpper}(?=${[rsBreak, rsUpper + rsMiscLower, '$'].join('|')})`,\n    `${rsUpper}?${rsMiscLower}+${rsOptContrLower}`,\n    `${rsUpper}+${rsOptContrUpper}`,\n    rsOrdUpper,\n    rsOrdLower,\n    `${rsDigit}+`,\n    rsEmoji\n].join('|'), 'g');\n\nconst LARGE_ARRAY_SIZE = 200;\nconst HASH_UNDEFINED = '__hash_undefined__';\n\n// Used to match `toStringTag` values of typed arrays\nconst reTypedTag = /^\\[object (?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)Array\\]$/;\n\n// Used to compose unicode capture groups\nconst rsAstral = `[${rsAstralRange}]`;\n\n// Used to compose unicode regexes\nconst rsNonAstralCombo = `${rsNonAstral}${rsCombo}?`;\nconst rsSymbol = `(?:${[rsNonAstralCombo, rsCombo, rsRegional, rsSurrPair, rsAstral].join('|')})`;\n\n// Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode)\nconst reUnicode = RegExp(`${rsFitz}(?=${rsFitz})|${rsSymbol + rsSeq}`, 'g');\n\nconst reIsDeepProp = /\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\\\]|\\\\.)*?\\1)\\]/;\nconst reIsPlainProp = /^\\w*$/;\n\nconst charCodeOfDot = '.'.charCodeAt(0);\nconst reEscapeChar = /\\\\(\\\\)?/g;\nconst rePropName = RegExp(\n    // Match anything that isn't a dot or bracket.\n    '[^.[\\\\]]+' + '|' +\n  // Or match property names within brackets.\n  '\\\\[(?:' +\n    // Match a non-string expression.\n    '([^\"\\'][^[]*)' + '|' +\n    // Or match strings (supports escaping characters).\n    '([\"\\'])((?:(?!\\\\2)[^\\\\\\\\]|\\\\\\\\.)*?)\\\\2' +\n  ')\\\\]'+ '|' +\n  // Or match \"\" as the space between consecutive dots or empty brackets.\n  '(?=(?:\\\\.|\\\\[\\\\])(?:\\\\.|\\\\[\\\\]|$))'\n    , 'g');\nconst reIsUint = /^(?:0|[1-9]\\d*)$/;\n\nconst hasUnicodeWord = RegExp.prototype.test.bind(\n    /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/\n);\n\nconst MAX_ARRAY_INDEX = 4294967295 - 1;\n\n/** Used to match words composed of alphanumeric characters. */\n// eslint-disable-next-line no-control-regex\nconst reAsciiWord = /[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\x7f]+/g;\n\n\n\n// -- helper functions\nconst hasUnicode = (string) => {\n    return reUnicode.test(string);\n};\n\nconst unicodeToArray = (string) => {\n    return string.match(reUnicode) || [];\n};\n\nconst asciiToArray = (string) => {\n    return string.split('');\n};\n\nconst stringToArray = (string) => {\n    return hasUnicode(string) ? unicodeToArray(string) : asciiToArray(string);\n};\n\nconst values = (object) => {\n    if (object == null) {\n        return [];\n    }\n\n    return keys(object).map((key) => object[key]);\n};\n\nconst keys = (object) => {\n    return isArrayLike(object) ? arrayLikeKeys(object) : Object.keys(Object(object));\n};\n\nconst baseKeys = (object) => {\n    if (!isPrototype(object)) {\n        return Object.keys(object);\n    }\n    var result = [];\n    for (var key in Object(object)) {\n        if (hasOwnProperty.call(object, key) && key != 'constructor') {\n            result.push(key);\n        }\n    }\n\n    return result;\n};\n\nconst arrayLikeKeys = (value, inherited) => {\n    const isArr = Array.isArray(value);\n    const isArg = !isArr && isObjectLike(value) && getTag(value) === argsTag;\n    const isType = !isArr && !isArg && isTypedArray(value);\n    const skipIndexes = isArr || isArg || isType;\n    const length = value.length;\n    const result = new Array(skipIndexes ? length : 0);\n    let index = skipIndexes ? -1 : length;\n    while (++index < length) {\n        result[index] = `${index}`;\n    }\n    for (const key in value) {\n        if ((inherited || hasOwnProperty.call(value, key)) &&\n            !(skipIndexes && (\n                // Safari 9 has enumerable `arguments.length` in strict mode.\n                key === 'length' ||\n                // Skip index properties.\n                isIndex(key, length)\n            ))\n        ) {\n            result.push(key);\n        }\n    }\n    return result;\n};\n\nconst assocIndexOf = (array, key) => {\n    let { length } = array;\n    while (length--) {\n        if (eq(array[length][0], key)) {\n            return length;\n        }\n    }\n    return -1;\n};\n\nconst eq = (value, other) => {\n    return value === other || (value !== value && other !== other);\n};\n\nconst isObjectLike = (value) => {\n    return value != null && typeof value == 'object';\n};\n\nconst isIterateeCall = (value, index, object) => {\n    if (!isObject(object)) {\n        return false;\n    }\n    const type = typeof index;\n\n    const isPossibleIteratee = type == 'number' ?\n        (isArrayLike(object) && index > -1 && index < object.length) :\n        (type == 'string' && index in object);\n\n    if (isPossibleIteratee) {\n        return eq(object[index], value);\n    }\n    return false;\n};\n\nconst isSet = (value) => {\n    return isObjectLike(value) && getTag(value) == setTag;\n};\n\nconst isMap = (value) => {\n    return isObjectLike(value) && getTag(value) == mapTag;\n};\n\nconst isPrototype = (value) => {\n    const Ctor = value && value.constructor;\n    const proto = (typeof Ctor === 'function' && Ctor.prototype) || Object.prototype;\n\n    return value === proto;\n};\n\nconst assignValue = (object, key, value) => {\n    const objValue = object[key];\n    if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n        (value === undefined && !(key in object))) {\n        object[key] = value;\n    }\n};\n\nconst copyObject = (source, props, object) => {\n    let index = -1;\n    const length = props.length;\n\n    while (++index < length) {\n        const key = props[index];\n        assignValue(object, key, source[key]);\n    }\n    return object;\n};\n\nconst isArrayLike = (value) => {\n    return value != null && typeof value !== 'function' && typeof value.length === 'number' &&\n        value.length > -1 && value.length % 1 === 0;\n};\n\nconst isSymbol = (value) => {\n    return typeof value == 'symbol' ||\n        (isObjectLike(value) && getTag(value) === symbolTag);\n};\n\nconst initCloneArray = (array) => {\n    const length = array.length;\n    let result = new array.constructor(length);\n\n    if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {\n        result.index = array.index;\n        result.input = array.input;\n    }\n\n    return result;\n};\n\nconst copyArray = (source, array) => {\n    let index = -1;\n    const length = source.length;\n\n    array || (array = new Array(length));\n    while (++index < length) {\n        array[index] = source[index];\n    }\n    return array;\n};\n\nconst getTag = (value) => {\n    if (value == null) {\n        return value === undefined ? undefinedTag : nullTag;\n    }\n\n    return Object.prototype.toString.call(value);\n};\n\nconst cloneArrayBuffer = (arrayBuffer) => {\n    const result = new arrayBuffer.constructor(arrayBuffer.byteLength);\n    new Uint8Array(result).set(new Uint8Array(arrayBuffer));\n    return result;\n};\n\nconst cloneTypedArray = (typedArray, isDeep) => {\n    const buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;\n    return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);\n};\n\nconst cloneRegExp = (regexp) =>{\n    const result = new regexp.constructor(regexp.source, /\\w*$/.exec(regexp));\n    result.lastIndex = regexp.lastIndex;\n    return result;\n};\n\nconst initCloneObject = (object) => {\n    return (typeof object.constructor == 'function' && !isPrototype(object))\n        ? Object.create(Object.getPrototypeOf(object))\n        : {};\n};\n\nconst getSymbols = (object) => {\n    if (object == null) {\n        return [];\n    }\n\n    object = Object(object);\n    const symbols = Object.getOwnPropertySymbols(object);\n\n    return symbols.filter((symbol) => propertyIsEnumerable.call(object, symbol));\n};\n\nconst copySymbols = (source, object) => {\n    return copyObject(source, getSymbols(source), object);\n};\n\nfunction cloneDataView(dataView, isDeep) {\n    const buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;\n    return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);\n}\n\nconst initCloneByTag = (object, tag, isDeep) => {\n    const Constructor = object.constructor;\n    switch(tag) {\n        case arrayBufferTag:\n            return cloneArrayBuffer(object, isDeep);\n        case boolTag:\n        case dateTag:\n            return new Constructor(+object);\n        case dataViewTag:\n            return cloneDataView(object, isDeep);\n        case float32Tag:\n        case float64Tag:\n        case int8Tag:\n        case int16Tag:\n        case int32Tag:\n        case uint8Tag:\n        case uint8ClampedTag:\n        case uint16Tag:\n        case uint32Tag:\n            return cloneTypedArray(object, isDeep);\n        case mapTag:\n            return new Constructor(object);\n        case numberTag:\n        case stringTag:\n            return new Constructor(object);\n        case regexpTag:\n            return cloneRegExp(object);\n        case setTag:\n            return new Constructor;\n        case symbolTag:\n            return Symbol.prototype.valueOf ? Object(Symbol.prototype.valueOf.call(object)) : {};\n    }\n};\n\nconst isTypedArray = (value) => {\n    return isObjectLike(value) && reTypedTag.test(getTag(value));\n};\n\nconst getAllKeys = (object) => {\n    const result = Object.keys(object);\n    if(!Array.isArray(object) && object != null) {\n        result.push(...getSymbols(Object(object)));\n    }\n\n    return result;\n};\n\nconst getSymbolsIn = (object) => {\n    const result = [];\n    while (object) {\n        result.push(...getSymbols(object));\n        object = Object.getPrototypeOf(Object(object));\n    }\n\n    return result;\n};\n\nconst getAllKeysIn = (object) => {\n    const result = [];\n\n    for (const key in object) {\n        result.push(key);\n    }\n\n    if (!Array.isArray(object)) {\n        result.push(...getSymbolsIn(object));\n    }\n\n    return result;\n};\n\nconst getMapData = ({ __data__ }, key) => {\n    const data = __data__;\n    return isKeyable(key)\n        ? data[typeof key === 'string' ? 'string' : 'hash']\n        : data.map;\n};\n\nconst equalObjects = (object, other, equalFunc, stack) => {\n    const objProps = getAllKeys(object);\n    const objLength = objProps.length;\n    const othProps = getAllKeys(other);\n    const othLength = othProps.length;\n\n    if (objLength != othLength) {\n        return false;\n    }\n    let key;\n    let index = objLength;\n    while (index--) {\n        key = objProps[index];\n        if (!(hasOwnProperty.call(other, key))) {\n            return false;\n        }\n    }\n\n    const objStacked = stack.get(object);\n    const othStacked = stack.get(other);\n    if (objStacked && othStacked) {\n        return objStacked == other && othStacked == object;\n    }\n    let result = true;\n    stack.set(object, other);\n    stack.set(other, object);\n\n    let compared;\n    let skipCtor;\n\n    while (++index < objLength) {\n        key = objProps[index];\n        const objValue = object[key];\n        const othValue = other[key];\n\n        if (!(compared === undefined\n            ? (objValue === othValue || equalFunc(objValue, othValue, stack))\n            : compared\n        )) {\n            result = false;\n            break;\n        }\n        skipCtor || (skipCtor = key == 'constructor');\n    }\n\n    if (result && !skipCtor) {\n        const objCtor = object.constructor;\n        const othCtor = other.constructor;\n\n        if (objCtor != othCtor &&\n        ('constructor' in object && 'constructor' in other) &&\n        !(typeof objCtor === 'function' && objCtor instanceof objCtor &&\n            typeof othCtor === 'function' && othCtor instanceof othCtor)) {\n            result = false;\n        }\n    }\n    stack['delete'](object);\n    stack['delete'](other);\n    return result;\n};\n\nconst baseIsEqual = (value, other, stack) => {\n    if (value === other) {\n        return true;\n    }\n    if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {\n        return value !== value && other !== other;\n    }\n\n    return baseIsEqualDeep(value, other, baseIsEqual, stack);\n};\n\nconst baseIsEqualDeep = (object, other, equalFunc, stack) => {\n    let objIsArr = Array.isArray(object);\n    const othIsArr = Array.isArray(other);\n    let objTag = objIsArr ? arrayTag : getTag(object);\n    let othTag = othIsArr ? arrayTag : getTag(other);\n\n    objTag = objTag == argsTag ? objectTag : objTag;\n    othTag = othTag == argsTag ? objectTag : othTag;\n\n    let objIsObj = objTag == objectTag;\n    const othIsObj = othTag == objectTag;\n    const isSameTag = objTag == othTag;\n\n    if (isSameTag && !objIsObj) {\n        stack || (stack = new Stack);\n        return (objIsArr || isTypedArray(object))\n            ? equalArrays(object, other, false, equalFunc, stack)\n            : equalByTag(object, other, objTag, equalFunc, stack);\n    }\n\n    const objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__');\n    const othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');\n\n    if (objIsWrapped || othIsWrapped) {\n        const objUnwrapped = objIsWrapped ? object.value() : object;\n        const othUnwrapped = othIsWrapped ? other.value() : other;\n\n        stack || (stack = new Stack);\n        return equalFunc(objUnwrapped, othUnwrapped, stack);\n    }\n\n    if (!isSameTag) {\n        return false;\n    }\n\n    stack || (stack = new Stack);\n    return equalObjects(object, other, equalFunc, stack);\n};\n\nconst equalArrays = (array, other, compareUnordered, equalFunc, stack) => {\n    const isPartial = false;\n    const arrLength = array.length;\n    const othLength = other.length;\n\n    if (arrLength != othLength && !(isPartial && othLength > arrLength)) {\n        return false;\n    }\n    // Assume cyclic values are equal.\n    const arrStacked = stack.get(array);\n    const othStacked = stack.get(other);\n    if (arrStacked && othStacked) {\n        return arrStacked == other && othStacked == array;\n    }\n    let index = -1;\n    let result = true;\n    const seen = compareUnordered ? new SetCache : undefined;\n\n    stack.set(array, other);\n    stack.set(other, array);\n\n    while (++index < arrLength) {\n        let compared;\n        const arrValue = array[index];\n        const othValue = other[index];\n\n        if (compared !== undefined) {\n            if (compared) {\n                continue;\n            }\n            result = false;\n            break;\n        }\n\n        if (seen) {\n            if (!some(other, (othValue, othIndex) => {\n                if (!cacheHas(seen, othIndex) &&\n            (arrValue === othValue || equalFunc(arrValue, othValue, stack))) {\n                    return seen.push(othIndex);\n                }\n            })) {\n                result = false;\n                break;\n            }\n        } else if (!(\n            arrValue === othValue ||\n            equalFunc(arrValue, othValue, stack)\n        )) {\n            result = false;\n            break;\n        }\n    }\n    stack['delete'](array);\n    stack['delete'](other);\n    return result;\n};\n\nconst some = (array, predicate) => {\n    let index = -1;\n    const length = array == null ? 0 : array.length;\n\n    while (++index < length) {\n        if (predicate(array[index], index, array)) {\n            return true;\n        }\n    }\n    return false;\n};\n\nconst cacheHas = (cache, key) => {\n    return cache.has(key);\n};\n\nconst compareArrayBufferTag = (object, other, equalFunc, stack) => {\n    if ((object.byteLength != other.byteLength) ||\n                !equalFunc(new Uint8Array(object), new Uint8Array(other), stack)) {\n        return false;\n    }\n    return true;\n};\n\nconst equalByTag = (object, other, tag, equalFunc, stack) => {\n\n    switch (tag) {\n        case dataViewTag:\n            if ((object.byteLength != other.byteLength) ||\n                (object.byteOffset != other.byteOffset)) {\n                return false;\n            }\n            object = object.buffer;\n            other = other.buffer;\n            return compareArrayBufferTag(object, other, equalFunc, stack);\n        case arrayBufferTag:\n            return compareArrayBufferTag(object, other, equalFunc, stack);\n        case boolTag:\n        case dateTag:\n        case numberTag:\n            return eq(+object, +other);\n        case errorTag:\n            return object.name == other.name && object.message == other.message;\n        case regexpTag:\n        case stringTag:\n            return object == `${other}`;\n        case mapTag:\n            // This use of 'var' is intentional. Don't remove if replacing all instances.\n            var convert = mapToArray;\n        // Intentional fallthrough\n        // eslint-disable-next-line no-fallthrough\n        case setTag:\n            convert || (convert = setToArray);\n\n            if (object.size != other.size) {\n                return false;\n            }\n            // Assume cyclic values are equal.\n            const stacked = stack.get(object);\n            if (stacked) {\n                return stacked == other;\n            }\n\n            // Recursively compare objects (susceptible to call stack limits).\n            stack.set(object, other);\n            const result = equalArrays(convert(object), convert(other), true, equalFunc, stack);\n            stack['delete'](object);\n            return result;\n        case symbolTag:\n            return Symbol.prototype.valueOf.call(object) == Symbol.prototype.valueOf.call(other);\n    }\n\n    return false;\n};\n\nconst mapToArray = (map) => {\n    let index = -1;\n    let result = Array(map.size);\n\n    map.forEach((value, key) => {\n        result[++index] = [key, value];\n    });\n    return result;\n};\n\nconst setToArray = (set) => {\n    let index = -1;\n    const result = new Array(set.size);\n\n    set.forEach((value) => {\n        result[++index] = value;\n    });\n    return result;\n};\n\nconst isKey = (value, object) => {\n    if (Array.isArray(value)) {\n        return false;\n    }\n    const type = typeof value;\n    if (type === 'number' || type === 'boolean' || value == null || isSymbol(value)) {\n        return true;\n    }\n    return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||\n    (object != null && value in Object(object));\n};\n\nconst stringToPath = (string) => {\n    const result = [];\n    if (string.charCodeAt(0) === charCodeOfDot) {\n        result.push('');\n    }\n    string.replace(rePropName, (match, expression, quote, subString) => {\n        let key = match;\n        if (quote) {\n            key = subString.replace(reEscapeChar, '$1');\n        }\n        else if (expression) {\n            key = expression.trim();\n        }\n        result.push(key);\n    });\n    return result;\n};\n\nconst castPath = (path, object) => {\n    if (Array.isArray(path)) {\n        return path;\n    }\n\n    return isKey(path, object) ? [path] : stringToPath(`${path}`);\n};\n\nconst get = (object, path) => {\n    path = castPath(path, object);\n\n    let index = 0;\n    const length = path.length;\n\n    while (object != null && index < length) {\n        object = object[toKey(path[index])];\n        index++;\n    }\n\n    return (index && index == length) ? object : undefined;\n};\n\nfunction compareAscending(value, other) {\n    if (value !== other) {\n        const valIsDefined = value !== undefined;\n        const valIsNull = value === null;\n        const valIsReflexive = value === value;\n        const valIsSymbol = isSymbol(value);\n\n        const othIsDefined = other !== undefined;\n        const othIsNull = other === null;\n        const othIsReflexive = other === other;\n        const othIsSymbol = isSymbol(other);\n\n        if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||\n            (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||\n            (valIsNull && othIsDefined && othIsReflexive) ||\n            (!valIsDefined && othIsReflexive) ||\n            !valIsReflexive) {\n            return 1;\n        }\n        if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||\n            (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||\n            (othIsNull && valIsDefined && valIsReflexive) ||\n            (!othIsDefined && valIsReflexive) ||\n            !othIsReflexive) {\n            return -1;\n        }\n    }\n    return 0;\n}\n\nfunction compareMultiple(object, other, orders) {\n    let index = -1;\n    const objCriteria = object.criteria;\n    const othCriteria = other.criteria;\n    const length = objCriteria.length;\n    const ordersLength = orders.length;\n\n    while (++index < length) {\n        const order = index < ordersLength ? orders[index] : null;\n        const cmpFn = (order && typeof order === 'function') ? order : compareAscending;\n        const result = cmpFn(objCriteria[index], othCriteria[index]);\n        if (result) {\n            if (order && typeof order !== 'function') {\n                return result * (order == 'desc' ? -1 : 1);\n            }\n            return result;\n        }\n    }\n\n    return object.index - other.index;\n}\n\nconst diff = (array, values) => {\n    let includes = (array, value) => {\n        const length = array == null ? 0 : array.length;\n        return !!length && array.indexOf(value) > -1;\n    };\n    let isCommon = true;\n    const result = [];\n    const valuesLength = values.length;\n\n    if (!array.length) {\n        return result;\n    }\n\n    if (values.length >= LARGE_ARRAY_SIZE) {\n        includes = (cache, key) => cache.has(key);\n        isCommon = false;\n        values = new SetCache(values);\n    }\n\n    outer:\n    for (let key in array) {\n        let value = array[key];\n        const computed = value;\n\n        value = (value !== 0) ? value : 0;\n        if (isCommon && computed === computed) {\n            let valuesIndex = valuesLength;\n            while (valuesIndex--) {\n                if (values[valuesIndex] === computed) {\n                    continue outer;\n                }\n            }\n            result.push(value);\n        }\n        else if (!includes(values, computed)) {\n            result.push(value);\n        }\n    }\n\n    return result;\n};\n\nconst intersect = (arrays) => {\n    const includes = (array, value) => {\n        const length = array == null ? 0 : array.length;\n        return !!length && array.indexOf(value) > -1;\n    };\n    const cacheHas = (cache, key) => cache.has(key);\n    const length = arrays[0].length;\n    const othLength = arrays.length;\n    const caches = new Array(othLength);\n    const result = [];\n\n    let array;\n    let maxLength = Infinity;\n    let othIndex = othLength;\n\n    while (othIndex--) {\n        array = arrays[othIndex];\n\n        maxLength = Math.min(array.length, maxLength);\n        caches[othIndex] = length >= 120 && array.length >= 120\n            ? new SetCache(othIndex && array)\n            : undefined;\n    }\n    array = arrays[0];\n\n    let index = -1;\n    const seen = caches[0];\n\n    outer:\n    while (++index < length && result.length < maxLength) {\n        let value = array[index];\n        const computed = value;\n\n        value = (value !== 0) ? value : 0;\n        if (!(seen\n            ? cacheHas(seen, computed)\n            : includes(result, computed)\n        )) {\n            othIndex = othLength;\n            while (--othIndex) {\n                const cache = caches[othIndex];\n                if (!(cache\n                    ? cacheHas(cache, computed)\n                    : includes(arrays[othIndex], computed))\n                ) {\n                    continue outer;\n                }\n            }\n            if (seen) {\n                seen.push(computed);\n            }\n            result.push(value);\n        }\n    }\n    return result;\n};\n\nconst toKey = (value) => {\n    if (typeof value === 'string' || isSymbol(value)) {\n        return value;\n    }\n    const result = `${value}`;\n    return (result == '0' && (1 / value) == -Infinity) ? '-0' : result;\n};\n\nconst baseClone = (value, isDeep = false, isFlat = false, isFull = true, customizer, key, object, stack) => {\n    let result;\n\n    if (customizer) {\n        result = object ? customizer(value, key, object, stack) : customizer(value);\n    }\n\n    if (result !== undefined) {\n        return result;\n    }\n\n    if (!isObject(value)) {\n        return value;\n    }\n\n    const isArr = Array.isArray(value);\n    const tag = getTag(value);\n\n    if (isArr) {\n        result = initCloneArray(value);\n\n        if (!isDeep) {\n            return copyArray(value, result);\n        }\n    } else {\n        const isFunc = typeof value === 'function';\n\n        if (tag === objectTag || tag === argsTag || (isFunc && !object)) {\n            result = (isFlat || isFunc) ? {} : initCloneObject(value);\n            if (!isDeep) {\n                return isFlat ?\n                    copySymbolsIn(value, copyObject(value, Object.keys(value), result)) :\n                    copySymbols(value, Object.assign(result, value));\n            }\n        } else {\n            if (isFunc || !CLONEABLE_TAGS[tag]) {\n                return object ? value : {};\n            }\n            result = initCloneByTag(value, tag, isDeep);\n        }\n    }\n\n    stack || (stack = new Stack);\n    const stacked = stack.get(value);\n\n    if (stacked) {\n        return stacked;\n    }\n\n    stack.set(value, result);\n\n    if (isMap(value)) {\n        value.forEach((subValue, key) => {\n            result.set(key, baseClone(subValue, isDeep, isFlat, isFull, customizer, key, value, stack));\n        });\n\n        return result;\n    }\n\n    if (isSet(value)) {\n        value.forEach(subValue => {\n            result.add(baseClone(subValue, isDeep, isFlat, isFull, customizer, subValue, value, stack));\n        });\n\n        return result;\n    }\n\n    if(isTypedArray(value)) {\n        return result;\n    }\n\n    const keysFunc = isFull\n        ? (isFlat ? getAllKeysIn : getAllKeys)\n        : (isFlat ? keysIn : keys);\n\n    const props =  isArr ? undefined : keysFunc(value);\n\n    (props || value).forEach((subValue, key) => {\n        if (props) {\n            key = subValue;\n            subValue = value[key];\n        }\n\n        assignValue(result, key, baseClone(subValue, isDeep, isFlat, isFull, customizer, key, value, stack));\n    });\n\n    return result;\n};\n\nconst copySymbolsIn = (source, object) => {\n    return copyObject(source, getSymbolsIn(source), object);\n};\n\nconst parent = (object, path) => {\n    return path.length < 2 ? object : get(object, path.slice(0, -1));\n};\n\nconst set = (object, path, value) => {\n    if (!isObject(object)) {\n        return object;\n    }\n    path = castPath(path, object);\n\n    const length = path.length;\n    const lastIndex = length - 1;\n\n    let index = -1;\n    let nested = object;\n\n    while (nested != null && ++index < length) {\n        const key = toKey(path[index]);\n        let newValue = value;\n\n        if (index != lastIndex) {\n            const objValue = nested[key];\n            newValue = undefined;\n            if (newValue === undefined) {\n                newValue = isObject(objValue)\n                    ? objValue\n                    : (isIndex(path[index + 1]) ? [] : {});\n            }\n        }\n        assignValue(nested, key, newValue);\n        nested = nested[key];\n    }\n    return object;\n};\n\nconst isIndex = (value, length) => {\n    const type = typeof value;\n    length = length == null ? Number.MAX_SAFE_INTEGER : length;\n\n    return !!length &&\n    (type === 'number' ||\n        (type !== 'symbol' && reIsUint.test(value))) &&\n        (value > -1 && value % 1 == 0 && value < length);\n};\n\nconst unset = (object, path) => {\n    path = castPath(path, object);\n    object = parent(object, path);\n    const lastSegment = path[path.length - 1];\n    return object == null || delete object[toKey(lastSegment)];\n};\n\nconst isKeyable = (value) => {\n    const type = typeof value;\n    return (type === 'string' || type === 'number' || type === 'symbol' || type === 'boolean')\n        ? (value !== '__proto__')\n        : (value === null);\n};\n\nconst keysIn = (object) => {\n    const result = [];\n    for (const key in object) {\n        result.push(key);\n    }\n    return result;\n};\n\nconst toPlainObject = (value) => {\n    value = Object(value);\n    const result = {};\n    for (const key in value) {\n        result[key] = value[key];\n    }\n    return result;\n};\n\nconst safeGet = (object, key) => {\n    if (key === 'constructor' && typeof object[key] === 'function') {\n        return;\n    }\n\n    if (key == '__proto__') {\n        return;\n    }\n\n    return object[key];\n};\n\nfunction createAssigner(assigner, isMerge = false) {\n    return (object, ...sources) => {\n        let index = -1;\n        let length = sources.length;\n        let customizer = length > 1 ? sources[length - 1] : undefined;\n        const guard = length > 2 ? sources[2] : undefined;\n\n        customizer = (assigner.length > 3 && typeof customizer === 'function')\n            ? (length--, customizer)\n            : isMerge ? (a, b) => {\n                if (Array.isArray(a) && !Array.isArray(b)) {\n                    return b;\n                }\n            } : undefined;\n\n        if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n            customizer = length < 3 ? undefined : customizer;\n            length = 1;\n        }\n        object = Object(object);\n        while (++index < length) {\n            const source = sources[index];\n            if (source) {\n                assigner(object, source, index, customizer);\n            }\n        }\n        return object;\n    };\n}\n\nconst baseMerge = (object, source, srcIndex, customizer, stack) => {\n    if (object === source) {\n        return;\n    }\n\n    forIn(source, (srcValue, key) => {\n        if (isObject(srcValue)) {\n            stack || (stack = new Stack);\n            baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);\n        } else {\n            let newValue = customizer\n                ? customizer(object[key], srcValue, `${key}`, object, source, stack)\n                : undefined;\n\n            if (newValue === undefined) {\n                newValue = srcValue;\n            }\n\n            assignMergeValue(object, key, newValue);\n        }\n    }, keysIn);\n};\n\nconst baseMergeDeep = (object, source, key, srcIndex, mergeFunc, customizer, stack) => {\n    const objValue = safeGet(object, key);\n    const srcValue = safeGet(source, key);\n    const stacked = stack.get(srcValue);\n\n    if (stacked) {\n        assignMergeValue(object, key, stacked);\n        return;\n    }\n\n    let newValue = customizer\n        ? customizer(objValue, srcValue, `${key}`, object, source, stack)\n        : undefined;\n\n    let isCommon = newValue === undefined;\n\n    if (isCommon) {\n        const isArr = Array.isArray(srcValue);\n        const isTyped = !isArr && isTypedArray(srcValue);\n\n        newValue = srcValue;\n        if (isArr || isTyped) {\n            if (Array.isArray(objValue)) {\n                newValue = objValue;\n            }\n            else if (isObjectLike(objValue) && isArrayLike(objValue)) {\n                newValue = copyArray(objValue);\n            }\n            else if (isTyped) {\n                isCommon = false;\n                newValue = cloneTypedArray(srcValue, true);\n            }\n            else {\n                newValue = [];\n            }\n        }\n        else if (isPlainObject(srcValue) || isArguments(srcValue)) {\n            newValue = objValue;\n            if (isArguments(objValue)) {\n                newValue = toPlainObject(objValue);\n            }\n            else if (typeof objValue === 'function' || !isObject(objValue)) {\n                newValue = initCloneObject(srcValue);\n            }\n        }\n        else {\n            isCommon = false;\n        }\n    }\n    if (isCommon) {\n    // Recursively merge objects and arrays (susceptible to call stack limits).\n        stack.set(srcValue, newValue);\n        mergeFunc(newValue, srcValue, srcIndex, customizer, stack);\n        stack['delete'](srcValue);\n    }\n    assignMergeValue(object, key, newValue);\n};\n\nconst assignMergeValue = (object, key, value) => {\n    if ((value !== undefined && !eq(object[key], value)) ||\n        (value === undefined && !(key in object))) {\n        assignValue(object, key, value);\n    }\n};\n\nfunction baseFor(object, iteratee, keysFunc) {\n    const iterable = Object(object);\n    const props = keysFunc(object);\n    let { length } = props;\n    let index = -1;\n\n    while (length--) {\n        const key = props[++index];\n        if (iteratee(iterable[key], key, iterable) === false) {\n            break;\n        }\n    }\n    return object;\n}\n\nconst baseForOwn = (object, iteratee) => {\n    return object && baseFor(object, iteratee, keys);\n};\n\nconst baseEach = (collection, iteratee) => {\n    if (collection == null) {\n        return collection;\n    }\n    if (!isArrayLike(collection)) {\n        return baseForOwn(collection, iteratee);\n    }\n    const length = collection.length;\n    const iterable = Object(collection);\n    let index = -1;\n\n    while (++index < length) {\n        if (iteratee(iterable[index], index, iterable) === false) {\n            break;\n        }\n    }\n    return collection;\n};\n\nfunction last(array) {\n    const length = array == null ? 0 : array.length;\n    return length ? array[length - 1] : undefined;\n}\n\nconst createSet = (Set && (1 / setToArray(new Set([undefined,-0]))[1]) == 1 / 0)\n    ? (values) => new Set(values)\n    : () => {};\n\nfunction customDefaultsMerge(objValue, srcValue, key, object, source, stack) {\n    if (isObject(objValue) && isObject(srcValue)) {\n    // Recursively merge objects and arrays (susceptible to call stack limits).\n        stack.set(srcValue, objValue);\n        baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack);\n        stack['delete'](srcValue);\n    }\n    return objValue;\n}\n\nfunction baseOrderBy(collection, iteratees, orders) {\n    if (iteratees.length) {\n        iteratees = iteratees.map((iteratee) => {\n            if (Array.isArray(iteratee)) {\n                return (value) => get(value, iteratee.length === 1 ? iteratee[0] : iteratee);\n            }\n\n            return iteratee;\n        });\n    } else {\n        iteratees = [(value) => value];\n    }\n\n    let criteriaIndex = -1;\n    let eachIndex = -1;\n\n    const result = isArrayLike(collection) ? new Array(collection.length) : [];\n\n    baseEach(collection, (value) => {\n        const criteria = iteratees.map((iteratee) => iteratee(value));\n\n        result[++eachIndex] = {\n            criteria,\n            index: ++criteriaIndex,\n            value\n        };\n    });\n\n    return baseSortBy(result, (object, other) => compareMultiple(object, other, orders));\n}\n\nfunction baseSortBy(array, comparer) {\n    let { length } = array;\n\n    array.sort(comparer);\n    while (length--) {\n        array[length] = array[length].value;\n    }\n    return array;\n}\n\nfunction isStrictComparable(value) {\n    return value === value && !isObject(value);\n}\n\nfunction matchesStrictComparable(key, srcValue) {\n    return (object) => {\n        if (object == null) {\n            return false;\n        }\n        return object[key] === srcValue &&\n            (srcValue !== undefined || (key in Object(object)));\n    };\n}\n\nfunction hasIn(object, path) {\n    return object != null && hasPath(object, path, baseHasIn);\n}\n\nfunction baseMatchesProperty(path, srcValue) {\n    if (isKey(path) && isStrictComparable(srcValue)) {\n        return matchesStrictComparable(toKey(path), srcValue);\n    }\n    return (object) => {\n        const objValue = get(object, path);\n        return (objValue === undefined && objValue === srcValue)\n            ? hasIn(object, path)\n            : baseIsEqual(srcValue, objValue);\n    };\n}\n\nfunction baseMatches(source) {\n    const matchData = getMatchData(source);\n    if (matchData.length === 1 && matchData[0][2]) {\n        return matchesStrictComparable(matchData[0][0], matchData[0][1]);\n    }\n    return (object) => object === source || baseIsMatch(object, source, matchData);\n}\n\nfunction getMatchData(object) {\n    const result = keys(object);\n    let length = result.length;\n\n    while (length--) {\n        const key = result[length];\n        const value = object[key];\n        result[length] = [key, value, isStrictComparable(value)];\n    }\n    return result;\n}\n\nfunction baseIsMatch(object, source, matchData, customizer) {\n    let index = matchData.length;\n    const length = index;\n    const noCustomizer = !customizer;\n\n    if (object == null) {\n        return !length;\n    }\n    let data;\n    let result;\n    object = Object(object);\n    while (index--) {\n        data = matchData[index];\n        if ((noCustomizer && data[2])\n            ? data[1] !== object[data[0]]\n            : !(data[0] in object)\n        ) {\n            return false;\n        }\n    }\n    while (++index < length) {\n        data = matchData[index];\n        const key = data[0];\n        const objValue = object[key];\n        const srcValue = data[1];\n\n        if (noCustomizer && data[2]) {\n            if (objValue === undefined && !(key in object)) {\n                return false;\n            }\n        } else {\n            const stack = new Stack;\n            if (customizer) {\n                result = customizer(objValue, srcValue, key, object, source, stack);\n            }\n            if (!(result === undefined\n                ? baseIsEqual(srcValue, objValue, stack)\n                : result\n            )) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\nfunction property(path) {\n    return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);\n}\n\nfunction baseProperty(key) {\n    return (object) => object == null ? undefined : object[key];\n}\n\nfunction basePropertyDeep(path) {\n    return (object) => get(object, path);\n}\n\nfunction baseIteratee(value) {\n    if (typeof value == 'function') {\n        return value;\n    }\n    if (value == null) {\n        return (val) => val;\n    }\n    if (typeof value == 'object') {\n        return Array.isArray(value)\n            ? baseMatchesProperty(value[0], value[1])\n            : baseMatches(value);\n    }\n    return property(value);\n}\n\nfunction getIteratee() {\n    const result = baseIteratee;\n    return arguments.length ? result(arguments[0], arguments[1]) : result;\n}\n\nconst arrayReduce = (array, iteratee, accumulator, initAccum) => {\n    let index = -1;\n    const length = array == null ? 0 : array.length;\n\n    if (initAccum && length) {\n        accumulator = array[++index];\n    }\n    while (++index < length) {\n        accumulator = iteratee(accumulator, array[index], index, array);\n    }\n    return accumulator;\n};\n\nconst baseReduce = (collection, iteratee, accumulator, initAccum, eachFunc) => {\n    eachFunc(collection, (value, index, collection) => {\n        accumulator = initAccum\n            ? (initAccum = false, value)\n            : iteratee(accumulator, value, index, collection);\n    });\n    return accumulator;\n};\n\nfunction reduce(collection, iteratee, accumulator) {\n    const func = Array.isArray(collection) ? arrayReduce : baseReduce;\n    const initAccum = arguments.length < 3;\n    return func(collection, iteratee, accumulator, initAccum, baseEach);\n}\n\nconst isFlattenable = (value) => {\n    return Array.isArray(value) || isArguments(value) ||\n    !!(value && value[Symbol.isConcatSpreadable]);\n};\n\nfunction baseFlatten(array, depth, predicate, isStrict, result) {\n    let index = -1;\n    const length = array.length;\n\n    predicate || (predicate = isFlattenable);\n    result || (result = []);\n\n    while (++index < length) {\n        var value = array[index];\n        if (depth > 0 && predicate(value)) {\n            if (depth > 1) {\n                // Recursively flatten arrays (susceptible to call stack limits).\n                baseFlatten(value, depth - 1, predicate, isStrict, result);\n            } else {\n                result.push(...value);\n            }\n        } else if (!isStrict) {\n            result[result.length] = value;\n        }\n    }\n    return result;\n}\n\nconst isArguments = (value) => {\n    return isObjectLike(value) && getTag(value) == '[object Arguments]';\n};\n\nconst basePick = (object, paths) => {\n    return basePickBy(object, paths, (value, path) => hasIn(object, path));\n};\n\nconst basePickBy = (object, paths, predicate) => {\n    let index = -1;\n    const length = paths.length;\n    const result = {};\n\n    while (++index < length) {\n        const path = paths[index];\n        const value = get(object, path);\n        if (predicate(value, path)) {\n            set(result, castPath(path, object), value);\n        }\n    }\n    return result;\n};\n\nconst isLength = (value) => {\n    return typeof value == 'number' &&\n        value > -1 && value % 1 == 0 && value <= Number.MAX_SAFE_INTEGER;\n};\n\nconst baseHasIn = (object, key) =>{\n    return object != null && key in Object(object);\n};\n\nconst hasPath = (object, path, hasFunc) => {\n    path = castPath(path, object);\n\n    var index = -1,\n        length = path.length,\n        result = false;\n\n    while (++index < length) {\n        var key = toKey(path[index]);\n        if (!(result = object != null && hasFunc(object, key))) {\n            break;\n        }\n        object = object[key];\n    }\n    if (result || ++index != length) {\n        return result;\n    }\n    length = object == null ? 0 : object.length;\n    return !!length && isLength(length) && isIndex(key, length) &&\n        (Array.isArray(object) || isArguments(object));\n};\n\nconst asciiWords = (string) => {\n    return string.match(reAsciiWord);\n};\n\nconst unicodeWords = (string) => {\n    return string.match(reUnicodeWords);\n};\n\nconst words = (string, pattern) => {\n    if (pattern === undefined) {\n        const result = hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);\n        return result || [];\n    }\n    return string.match(pattern) || [];\n};\n\nconst castSlice = (array, start, end) => {\n    const { length } = array;\n    end = end === undefined ? length : end;\n    return (!start && end >= length) ? array : array.slice(start, end);\n};\n\nconst upperFirst = createCaseFirst('toUpperCase');\n\nfunction createCaseFirst(methodName) {\n    return (string) => {\n        if (!string) {\n            return '';\n        }\n\n        const strSymbols = hasUnicode(string)\n            ? stringToArray(string)\n            : undefined;\n\n        const chr = strSymbols\n            ? strSymbols[0]\n            : string[0];\n\n        const trailing = strSymbols\n            ? castSlice(strSymbols, 1).join('')\n            : string.slice(1);\n\n        return chr[methodName]() + trailing;\n    };\n}\n\nexport function matches(source) {\n    return baseMatches(baseClone(source, true));\n}\n\n// -- helper classes\nclass Stack {\n    constructor(entries) {\n        const data = this.__data__ = new ListCache(entries);\n        this.size = data.size;\n    }\n\n    clear() {\n        this.__data__ = new ListCache;\n        this.size = 0;\n    }\n\n    delete(key) {\n        const data = this.__data__;\n        const result = data['delete'](key);\n\n        this.size = data.size;\n        return result;\n    }\n\n    get(key) {\n        return this.__data__.get(key);\n    }\n\n    has(key) {\n        return this.__data__.has(key);\n    }\n\n    set(key, value) {\n        let data = this.__data__;\n        if (data instanceof ListCache) {\n            const pairs = data.__data__;\n            if (pairs.length < LARGE_ARRAY_SIZE - 1) {\n                pairs.push([key, value]);\n                this.size = ++data.size;\n                return this;\n            }\n            data = this.__data__ = new MapCache(pairs);\n        }\n        data.set(key, value);\n        this.size = data.size;\n        return this;\n    }\n}\n\nclass ListCache {\n    constructor(entries) {\n        let index = -1;\n        const length = entries == null ? 0 : entries.length;\n\n        this.clear();\n        while (++index < length) {\n            const entry = entries[index];\n            this.set(entry[0], entry[1]);\n        }\n    }\n\n    clear() {\n        this.__data__ = [];\n        this.size = 0;\n    }\n\n    delete(key) {\n        const data = this.__data__;\n        const index = assocIndexOf(data, key);\n\n        if (index < 0) {\n            return false;\n        }\n        const lastIndex = data.length - 1;\n        if (index == lastIndex) {\n            data.pop();\n        } else {\n            data.splice(index, 1);\n        }\n        --this.size;\n        return true;\n    }\n\n    get(key) {\n        const data = this.__data__;\n        const index = assocIndexOf(data, key);\n        return index < 0 ? undefined : data[index][1];\n    }\n\n    has(key) {\n        return assocIndexOf(this.__data__, key) > -1;\n    }\n\n    set(key, value) {\n        const data = this.__data__;\n        const index = assocIndexOf(data, key);\n\n        if (index < 0) {\n            ++this.size;\n            data.push([key, value]);\n        } else {\n            data[index][1] = value;\n        }\n        return this;\n    }\n}\n\nclass MapCache {\n    constructor(entries) {\n        let index = -1;\n        const length = entries == null ? 0 : entries.length;\n\n        this.clear();\n        while (++index < length) {\n            const entry = entries[index];\n            this.set(entry[0], entry[1]);\n        }\n    }\n\n    clear() {\n        this.size = 0;\n        this.__data__ = {\n            'hash': new Hash,\n            'map': new Map,\n            'string': new Hash\n        };\n    }\n\n    delete(key) {\n        const result = getMapData(this, key)['delete'](key);\n        this.size -= result ? 1 : 0;\n        return result;\n    }\n\n    get(key) {\n        return getMapData(this, key).get(key);\n    }\n\n    has(key) {\n        return getMapData(this, key).has(key);\n    }\n\n    set(key, value) {\n        const data = getMapData(this, key);\n        const size = data.size;\n\n        data.set(key, value);\n        this.size += data.size == size ? 0 : 1;\n        return this;\n    }\n}\n\nclass Hash {\n    constructor(entries) {\n        let index = -1;\n        const length = entries == null ? 0 : entries.length;\n\n        this.clear();\n        while (++index < length) {\n            const entry = entries[index];\n            this.set(entry[0], entry[1]);\n        }\n    }\n\n    clear() {\n        this.__data__ = Object.create(null);\n        this.size = 0;\n    }\n\n    delete(key) {\n        const result = this.has(key) && delete this.__data__[key];\n        this.size -= result ? 1 : 0;\n        return result;\n    }\n\n    get(key) {\n        const data = this.__data__;\n        const result = data[key];\n        return result === HASH_UNDEFINED ? undefined : result;\n    }\n\n    has(key) {\n        const data = this.__data__;\n        return data[key] !== undefined;\n    }\n\n    set(key, value) {\n        const data = this.__data__;\n        this.size += this.has(key) ? 0 : 1;\n        data[key] = value === undefined ? HASH_UNDEFINED : value;\n        return this;\n    }\n}\n\nclass SetCache {\n    constructor(values) {\n        let index = -1;\n        const length = values == null ? 0 : values.length;\n\n        this.__data__ = new MapCache;\n        while (++index < length) {\n            this.add(values[index]);\n        }\n    }\n\n    add(value) {\n        this.__data__.set(value, HASH_UNDEFINED);\n        return this;\n    }\n\n    has(value) {\n        return this.__data__.has(value);\n    }\n}\n\nSetCache.prototype.push = SetCache.prototype.add;\n\n// -- top level functions\n\nexport const isBoolean = function(value) {\n    var toString = Object.prototype.toString;\n    return value === true || value === false || (!!value && typeof value === 'object' && toString.call(value) === boolTag);\n};\n\nexport const isObject = function(value) {\n    return !!value && (typeof value === 'object' || typeof value === 'function');\n};\n\nexport const isNumber = function(value) {\n    var toString = Object.prototype.toString;\n    return typeof value === 'number' || (!!value && typeof value === 'object' && toString.call(value) === numberTag);\n};\n\nexport const isString = function(value) {\n    var toString = Object.prototype.toString;\n    return typeof value === 'string' || (!!value && typeof value === 'object' && toString.call(value) === stringTag);\n};\n\nexport const assign = createAssigner((object, source) => {\n    if (isPrototype(source) || isArrayLike(source)) {\n        copyObject(source, keys(source), object);\n        return;\n    }\n    for (var key in source) {\n        if (hasOwnProperty.call(source, key)) {\n            assignValue(object, key, source[key]);\n        }\n    }\n});\n\nexport const mixin = assign;\n\nexport const deepMixin = mixin;\n\nexport const supplement = (object, ...sources) => {\n    let index = -1;\n    let length = sources.length;\n    const guard = length > 2 ? sources[2] : undefined;\n\n    if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n        length = 1;\n    }\n\n    while (++index < length) {\n        const source = sources[index];\n\n        if (source == null) {\n            continue;\n        }\n\n        const props = Object.keys(source);\n        const propsLength = props.length;\n        let propsIndex = -1;\n\n        while (++propsIndex < propsLength) {\n            const key = props[propsIndex];\n            const value = object[key];\n\n            if (value === undefined ||\n                (eq(value, Object.prototype[key]) && !hasOwnProperty.call(object, key))) {\n                object[key] = source[key];\n            }\n        }\n    }\n\n    return object;\n};\n\nexport const defaults = supplement;\n\nexport const deepSupplement = function defaultsDeep(...args) {\n    args.push(undefined, customDefaultsMerge);\n    return merge.apply(undefined, args);\n};\n\nexport const defaultsDeep = deepSupplement;\n\n// _.invokeMap\nexport const invoke = (collection, path, ...args) => {\n    let index = -1;\n    const isFunc = typeof path === 'function';\n    const result = isArrayLike(collection) ? new Array(collection.length) : [];\n\n    baseEach(collection, (value) => {\n        result[++index] = isFunc ? path.apply(value, args) : invokeProperty(value, path, ...args);\n    });\n\n    return result;\n};\n\n// _.invoke\nexport const invokeProperty = (object, path, ...args) => {\n    path = castPath(path, object);\n    object = parent(object, path);\n    const func = object == null ? object : object[toKey(last(path))];\n    return func == null ? undefined : func.apply(object, args);\n};\n\nexport const sortedIndex = (array, value, iteratee) => {\n    let low = 0;\n    let high = array == null ? 0 : array.length;\n    if (high == 0) {\n        return 0;\n    }\n\n    iteratee = getIteratee(iteratee, 2);\n    value = iteratee(value);\n\n    const valIsNaN = value !== value;\n    const valIsNull = value === null;\n    const valIsSymbol = isSymbol(value);\n    const valIsUndefined = value === undefined;\n\n    while (low < high) {\n        let setLow;\n        const mid = Math.floor((low + high) / 2);\n        const computed = iteratee(array[mid]);\n        const othIsDefined = computed !== undefined;\n        const othIsNull = computed === null;\n        const othIsReflexive = computed === computed;\n        const othIsSymbol = isSymbol(computed);\n\n        if (valIsNaN) {\n            setLow = othIsReflexive;\n        } else if (valIsUndefined) {\n            setLow = othIsReflexive &&othIsDefined;\n        } else if (valIsNull) {\n            setLow = othIsReflexive && othIsDefined && !othIsNull;\n        } else if (valIsSymbol) {\n            setLow = othIsReflexive && othIsDefined && !othIsNull && !othIsSymbol;\n        } else if (othIsNull || othIsSymbol) {\n            setLow = false;\n        } else {\n            setLow = computed < value;\n        }\n        if (setLow) {\n            low = mid + 1;\n        } else {\n            high = mid;\n        }\n    }\n    return Math.min(high, MAX_ARRAY_INDEX);\n};\n\nexport const uniq = (array, iteratee) => {\n    let index = -1;\n    let includes = (array, value) => {\n        const length = array == null ? 0 : array.length;\n        return !!length && array.indexOf(value) > -1;\n    };\n    iteratee = getIteratee(iteratee, 2);\n    let isCommon = true;\n\n    const { length } = array;\n    const result = [];\n    let seen = result;\n\n    if (length >= LARGE_ARRAY_SIZE) {\n        const set = iteratee ? null : createSet(array);\n        if (set) {\n            return setToArray(set);\n        }\n        isCommon = false;\n        includes = (cache, key) => cache.has(key);\n        seen = new SetCache;\n    } else {\n        seen = iteratee ? [] : result;\n    }\n    outer:\n    while (++index < length) {\n        let value = array[index];\n        const computed = iteratee ? iteratee(value) : value;\n\n        value = (value !== 0) ? value : 0;\n        if (isCommon && computed === computed) {\n            let seenIndex = seen.length;\n            while (seenIndex--) {\n                if (seen[seenIndex] === computed) {\n                    continue outer;\n                }\n            }\n            if (iteratee) {\n                seen.push(computed);\n            }\n            result.push(value);\n        }\n        else if (!includes(seen, computed)) {\n            if (seen !== result) {\n                seen.push(computed);\n            }\n            result.push(value);\n        }\n    }\n    return result;\n};\n\nexport const clone = (value) => baseClone(value);\n\nexport const cloneDeep = (value) => baseClone(value, true);\n\nexport const isEmpty = (value) => {\n    if (value == null) {\n        return true;\n    }\n    if (isArrayLike(value) &&\n        (Array.isArray(value) || typeof value === 'string' || typeof value.splice === 'function' ||\n            isTypedArray(value) || isArguments(value))) {\n        return !value.length;\n    }\n    const tag = getTag(value);\n    if (tag == '[object Map]' || tag == '[object Set]') {\n        return !value.size;\n    }\n    if (isPrototype(value)) {\n        return !baseKeys(value).length;\n    }\n    for (const key in value) {\n        if (hasOwnProperty.call(value, key)) {\n            return false;\n        }\n    }\n    return true;\n};\nexport const isEqual = (object, other) => baseIsEqual(object, other);\n\nexport const isFunction = (value) => typeof value === 'function';\n\nexport const isPlainObject = (value) => {\n    if (!isObjectLike(value) || getTag(value) != '[object Object]') {\n        return false;\n    }\n    if (Object.getPrototypeOf(value) === null) {\n        return true;\n    }\n    let proto = value;\n    while (Object.getPrototypeOf(proto) !== null) {\n        proto = Object.getPrototypeOf(proto);\n    }\n    return Object.getPrototypeOf(value) === proto;\n};\n\nexport const toArray = (value) => {\n    if (!value) {\n        return [];\n    }\n\n    if (isArrayLike(value)) {\n        return isString(value) ? stringToArray(value) : copyArray(value);\n    }\n\n    if (Symbol.iterator && Symbol.iterator in Object(value)) {\n        const iterator = value[Symbol.iterator]();\n        let data;\n        const result = [];\n\n        while (!(data = iterator.next()).done) {\n            result.push(data.value);\n        }\n        return result;\n    }\n\n    const tag = getTag(value);\n    const func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);\n\n    return func(value);\n};\n\nexport function debounce(func, wait, opt) {\n    if (typeof func !== 'function') {\n        throw new TypeError('Expected a function');\n    }\n\n    let lastArgs;\n    let lastThis;\n    let maxWait;\n    let result;\n    let timerId;\n    let lastCallTime;\n    let lastInvokeTime = 0;\n    let leading = false;\n    let maxing = false;\n    let trailing = true;\n\n    const useRaf = (!wait && wait !== 0 && window && typeof window.requestAnimationFrame === 'function');\n\n    wait = +wait || 0;\n\n    if (isObject(opt)) {\n        leading = !!opt.leading;\n        maxing = 'maxWait' in opt;\n        maxWait = maxing ? Math.max(+opt.maxWait || 0, wait) : maxWait;\n        trailing = 'trailing' in opt ? !!opt.trailing : trailing;\n    }\n\n    function invokeFunc(time) {\n        const args = lastArgs;\n        const thisArg = lastThis;\n\n        lastArgs = lastThis = undefined;\n        lastInvokeTime = time;\n        result = func.apply(thisArg, args);\n        return result;\n    }\n\n    function startTimer(pendingFunc, wait) {\n        if (useRaf) {\n            window.cancelAnimationFrame(timerId);\n            return window.requestAnimationFrame(pendingFunc);\n        }\n        return setTimeout(pendingFunc, wait);\n    }\n\n    function cancelTimer(id) {\n        if (useRaf) {\n            return window.cancelAnimationFrame(id);\n        }\n        clearTimeout(id);\n    }\n\n    function leadingEdge(time) {\n        lastInvokeTime = time;\n        timerId = startTimer(timerExpired, wait);\n        return leading ? invokeFunc(time) : result;\n    }\n\n    function remainingWait(time) {\n        const timeSinceLastCall = time - lastCallTime;\n        const timeSinceLastInvoke = time - lastInvokeTime;\n        const timeWaiting = wait - timeSinceLastCall;\n\n        return maxing ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;\n    }\n\n    function shouldInvoke(time) {\n        const timeSinceLastCall = time - lastCallTime;\n        const timeSinceLastInvoke = time - lastInvokeTime;\n\n        return (lastCallTime === undefined || (timeSinceLastCall >= wait) || (timeSinceLastCall < 0) ||\n            (maxing && timeSinceLastInvoke >= maxWait));\n    }\n\n    function timerExpired() {\n        const time = Date.now();\n        if (shouldInvoke(time)) {\n            return trailingEdge(time);\n        }\n        timerId = startTimer(timerExpired, remainingWait(time));\n    }\n\n    function trailingEdge(time) {\n        timerId = undefined;\n\n        if (trailing && lastArgs) {\n            return invokeFunc(time);\n        }\n        lastArgs = lastThis = undefined;\n        return result;\n    }\n\n    function debounced(...args) {\n        const time = Date.now();\n        const isInvoking = shouldInvoke(time);\n\n        lastArgs = args;\n        lastThis = this;\n        lastCallTime = time;\n\n        if (isInvoking) {\n            if (timerId === undefined) {\n                return leadingEdge(lastCallTime);\n            }\n            if (maxing) {\n                timerId = startTimer(timerExpired, wait);\n                return invokeFunc(lastCallTime);\n            }\n        }\n        if (timerId === undefined) {\n            timerId = startTimer(timerExpired, wait);\n        }\n        return result;\n    }\n\n    debounced.cancel = () => {\n        if (timerId !== undefined) {\n            cancelTimer(timerId);\n        }\n        lastInvokeTime = 0;\n        lastArgs = lastCallTime = lastThis = timerId = undefined;\n    };\n    debounced.flush = () => timerId === undefined ? result : trailingEdge(Date.now());\n    debounced.pending = () => timerId !== undefined;\n\n    return debounced;\n}\n\nexport const groupBy = (collection, iteratee) => {\n    iteratee = getIteratee(iteratee, 2);\n\n    return reduce(collection, (result, value, key) => {\n        key = iteratee(value);\n        if (hasOwnProperty.call(result, key)) {\n            result[key].push(value);\n        } else {\n            assignValue(result, key, [value]);\n        }\n        return result;\n    }, {});\n};\n\nexport const sortBy = (collection, iteratees = []) => {\n    if (collection == null) {\n        return [];\n    }\n\n    const length = iteratees.length;\n    if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {\n        iteratees = [];\n    } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {\n        iteratees = [iteratees[0]];\n    }\n\n    if (!Array.isArray(iteratees)) {\n        iteratees = [getIteratee(iteratees, 2)];\n    }\n\n    return baseOrderBy(collection, iteratees.flat(1), []);\n};\n\nexport const flattenDeep = (array) => {\n    const length = array == null ? 0 : array.length;\n    return length ? baseFlatten(array, Infinity) : [];\n};\n\nexport const without = (array, ...values) => isArrayLike(array) ? diff(array, values) : [];\n\nexport const difference = (array, ...values) =>\n    isObjectLike(array) && isArrayLike(array) ?\n        diff(array, values.flat(1)) : [];\n\nexport const intersection = (...arrays) => {\n    const mapped = arrays.map((array) =>\n        isObjectLike(array) && isArrayLike(array) ?\n            array : []\n    );\n\n    return mapped.length && mapped[0] === arrays[0] ?\n        intersect(mapped) : [];\n};\n\nexport const union = (...arrays) => {\n    const array = arrays.flat(1);\n    return uniq(array);\n};\n\nexport const has = (object, key) => {\n    if (object == null) {\n        return false;\n    }\n\n    if (typeof key === 'string') {\n        key = key.split('.');\n    }\n\n    let index = -1;\n    let value = object;\n\n    while (++index < key.length) {\n        if (!value || !hasOwnProperty.call(value, key[index])) {\n            return false;\n        }\n        value = value[key[index]];\n    }\n\n    return true;\n};\n\nexport const result = (object, path, defaultValue) => {\n    path = castPath(path, object);\n\n    let index = -1;\n    let length = path.length;\n\n    if (!length) {\n        length = 1;\n        object = undefined;\n    }\n    while (++index < length) {\n        let value = object == null ? undefined : object[toKey(path[index])];\n        if (value === undefined) {\n            index = length;\n            value = defaultValue;\n        }\n        object = typeof value === 'function' ? value.call(object) : value;\n    }\n    return object;\n};\n\nexport const omit = (object, ...paths) => {\n    let result = {};\n    if (object == null) {\n        return result;\n    }\n    let isDeep = false;\n    paths = paths.flat(1).map((path) => {\n        path = castPath(path, object);\n        isDeep || (isDeep = path.length > 1);\n        return path;\n    });\n    copyObject(object, getAllKeysIn(object), result);\n    if (isDeep) {\n        result = baseClone(result, true, true, true, (value) => isPlainObject(value) ? undefined : value);\n    }\n    let length = paths.length;\n    while (length--) {\n        unset(result, paths[length]);\n    }\n    return result;\n};\n\nexport const pick = (object, ...paths) => {\n    return object == null ? {} : basePick(object, paths.flat(Infinity));\n};\n\nexport const bindAll = (object, ...methodNames) => {\n    methodNames.flat(1).forEach((key) => {\n        key = toKey(key);\n        assignValue(object, key, object[key].bind(object));\n    });\n    return object;\n};\n\nexport const forIn = (object, iteratee = (value) => value) => {\n    let index = -1;\n    const iterable = Object(object);\n    const props = isArrayLike(object) ? arrayLikeKeys(object, true) : keysIn(object);\n    let length = props.length;\n\n    while(length--) {\n        const key = props[++index];\n        if (iteratee(iterable[key], key, iterable) === false) {\n            break;\n        }\n    }\n};\n\nexport const camelCase = (string = '') => (\n    words(`${string}`.replace(/['\\u2019]/g, ''))\n        .reduce((result, word, index) => {\n            word = word.toLowerCase();\n            return result + (index ? upperFirst(word) : word);\n        }, '')\n);\n\nlet idCounter = 0;\n\nexport const uniqueId = (prefix = '') => {\n    const id = ++idCounter;\n    return `${prefix}` + id;\n};\n\nexport const merge = createAssigner((object, source, srcIndex, customizer) => {\n    baseMerge(object, source, srcIndex, customizer);\n}, true);\n","class Data {\n\n    constructor() {\n        this.map = new WeakMap();\n    }\n\n    has(obj, key) {\n        if (key === undefined) return this.map.has(obj);\n        return key in this.map.get(obj);\n    }\n\n    create(obj) {\n        if (!this.has(obj)) this.map.set(obj, Object.create(null));\n        return this.get(obj);\n    }\n\n    get(obj, key) {\n        if (!this.has(obj)) return undefined;\n        const data = this.map.get(obj);\n        if (key === undefined) return data;\n        return data[key];\n    }\n\n    set(obj, key, value) {\n        if (key === undefined) return;\n        const data = this.create(obj);\n        if (typeof key === 'string') {\n            data[key] = value;\n        } else {\n            Object.assign(data, key);\n        }\n    }\n\n    remove(obj, key) {\n        if (!this.has(obj)) return;\n        if (key === undefined) {\n            this.map.delete(obj);\n        } else {\n            const data = this.map.get(obj);\n            delete data[key];\n        }\n    }\n}\n\nexport default Data;\n\n","import Data from '../Data.mjs';\n\nexport const dataPriv = new Data();\n\nexport const dataUser = new Data();\n","export const Event = function(src, props) {\n    // Allow instantiation without the 'new' keyword\n    if (!(this instanceof Event)) {\n        return new Event(src, props);\n    }\n\n    // Event object\n    if (src && src.type) {\n        this.originalEvent = src;\n        this.type = src.type;\n\n        // Events bubbling up the document may have been marked as prevented\n        // by a handler lower down the tree; reflect the correct value.\n        this.isDefaultPrevented = src.defaultPrevented\n            ? returnTrue\n            : returnFalse;\n\n        // Create target properties\n        this.target = src.target;\n        this.currentTarget = src.currentTarget;\n        this.relatedTarget = src.relatedTarget;\n\n        // Event type\n    } else {\n        this.type = src;\n    }\n\n    // Put explicitly provided properties onto the event object\n    if (props) {\n        Object.assign(this, props);\n    }\n\n    // Create a timestamp if incoming event doesn't have one\n    this.timeStamp = (src && src.timeStamp) || Date.now();\n\n    // Mark it as fixed\n    this.envelope = true;\n};\n\n// $.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\nEvent.prototype = {\n    constructor: Event,\n    isDefaultPrevented: returnFalse,\n    isPropagationStopped: returnFalse,\n    isImmediatePropagationStopped: returnFalse,\n    preventDefault: function() {\n        const evt = this.originalEvent;\n        this.isDefaultPrevented = returnTrue;\n        if (evt) {\n            evt.preventDefault();\n        }\n    },\n    stopPropagation: function() {\n        const evt = this.originalEvent;\n        this.isPropagationStopped = returnTrue;\n        if (evt) {\n            evt.stopPropagation();\n        }\n    },\n    stopImmediatePropagation: function() {\n        const evt = this.originalEvent;\n        this.isImmediatePropagationStopped = returnTrue;\n        if (evt) {\n            evt.stopImmediatePropagation();\n        }\n        this.stopPropagation();\n    },\n};\n\n// Includes all common event props including KeyEvent and MouseEvent specific props\n[\n    'altKey',\n    'bubbles',\n    'cancelable',\n    'changedTouches',\n    'ctrlKey',\n    'detail',\n    'eventPhase',\n    'metaKey',\n    'pageX',\n    'pageY',\n    'shiftKey',\n    'view',\n    'char',\n    'code',\n    'charCode',\n    'key',\n    'keyCode',\n    'button',\n    'buttons',\n    'clientX',\n    'clientY',\n    'offsetX',\n    'offsetY',\n    'pointerId',\n    'pointerType',\n    'screenX',\n    'screenY',\n    'targetTouches',\n    'toElement',\n    'touches',\n    'which',\n].forEach((name) => addProp(name));\n\nfunction addProp(name) {\n    Object.defineProperty(Event.prototype, name, {\n        enumerable: true,\n        configurable: true,\n        get: function() {\n            return this.originalEvent ? this.originalEvent[name] : undefined;\n        },\n        set: function(value) {\n            Object.defineProperty(this, name, {\n                enumerable: true,\n                configurable: true,\n                writable: true,\n                value: value,\n            });\n        },\n    });\n}\n\nfunction returnTrue() {\n    return true;\n}\n\nfunction returnFalse() {\n    return false;\n}\n","\n/*!\n * jQuery JavaScript Library v4.0.0-pre+c98597ea.dirty\n * https://jquery.com/\n *\n * Copyright OpenJS Foundation and other contributors\n * Released under the MIT license\n * https://jquery.org/license\n *\n * Date: 2023-11-24T14:04Z\n */\n\nimport { uniq, isEmpty } from '../../util/utilHelpers.mjs';\nimport { dataPriv, dataUser } from './vars.mjs';\nimport { Event } from './Event.mjs';\n\nconst document = (typeof window !== 'undefined') ? window.document : null;\nconst documentElement = document && document.documentElement;\n\nconst rTypeNamespace = /^([^.]*)(?:\\.(.+)|)/;\n\n// Only count HTML whitespace\n// Other whitespace should count in values\n// https://infra.spec.whatwg.org/#ascii-whitespace\nconst rNotHtmlWhite = /[^\\x20\\t\\r\\n\\f]+/g;\n\n// Define a local copy of $\nconst $ = function(selector) {\n    // The $ object is actually just the init constructor 'enhanced'\n    // Need init if $ is called (just allow error to be thrown if not included)\n    return new $.Dom(selector);\n};\n\n$.fn = $.prototype = {\n    constructor: $,\n    // The default length of a $ object is 0\n    length: 0,\n};\n\n// A global GUID counter for objects\n$.guid = 1;\n\n// User data storage\n$.data = dataUser;\n\n$.merge = function(first, second) {\n    let len = +second.length;\n    let i = first.length;\n    for (let j = 0; j < len; j++) {\n        first[i++] = second[j];\n    }\n    first.length = i;\n    return first;\n};\n\n$.parseHTML = function(string) {\n    // Inline events will not execute when the HTML is parsed; this includes, for example, sending GET requests for images.\n    const context = document.implementation.createHTMLDocument();\n    // Set the base href for the created document so any parsed elements with URLs\n    // are based on the document's URL\n    const base = context.createElement('base');\n    base.href = document.location.href;\n    context.head.appendChild(base);\n\n    context.body.innerHTML = string;\n    // remove scripts\n    const scripts = context.getElementsByTagName('script');\n    for (let i = 0; i < scripts.length; i++) {\n        scripts[i].remove();\n    }\n    return Array.from(context.body.childNodes);\n};\n\nif (typeof Symbol === 'function') {\n    $.fn[Symbol.iterator] = Array.prototype[Symbol.iterator];\n}\n\n$.fn.toArray = function() {\n    return Array.from(this);\n};\n\n// Take an array of elements and push it onto the stack\n// (returning the new matched element set)\n$.fn.pushStack = function(elements) {\n    // Build a new $ matched element set\n    const ret = $.merge(this.constructor(), elements);\n    // Add the old object onto the stack (as a reference)\n    ret.prevObject = this;\n    // Return the newly-formed element set\n    return ret;\n};\n\n$.fn.find = function(selector) {\n    const [el] = this;\n    const ret = this.pushStack([]);\n    if (!el) return ret;\n    // Early return if context is not an element, document or document fragment\n    const { nodeType } = el;\n    if (nodeType !== 1 && nodeType !== 9 && nodeType !== 11) {\n        return ret;\n    }\n    if (typeof selector !== 'string') {\n        if (el !== selector && el.contains(selector)) {\n            $.merge(ret, [selector]);\n        }\n    } else {\n        $.merge(ret, el.querySelectorAll(selector));\n    }\n    return ret;\n};\n\n$.fn.add = function(selector, context) {\n    const newElements = $(selector, context).toArray();\n    const prevElements = this.toArray();\n    const ret = this.pushStack([]);\n    $.merge(ret, uniq(prevElements.concat(newElements)));\n    return ret;\n};\n\n$.fn.addBack = function() {\n    return this.add(this.prevObject);\n};\n\n$.fn.filter = function(selector) {\n    const matches = [];\n    for (let i = 0; i < this.length; i++) {\n        const node = this[i];\n        if (!node.matches(selector)) continue;\n        matches.push(node);\n    }\n    return this.pushStack(matches);\n};\n\n// A simple way to check for HTML strings\n// Prioritize #id over <tag> to avoid XSS via location.hash (trac-9521)\n// Strict HTML recognition (trac-11290: must start with <)\n// Shortcut simple #id case for speed\nconst rQuickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]+))$/;\n\nfunction isObviousHtml(input) {\n    return (\n        input[0] === '<' && input[input.length - 1] === '>' && input.length >= 3\n    );\n}\n\nconst Dom = function(selector) {\n    if (!selector) {\n        // HANDLE: $(\"\"), $(null), $(undefined), $(false)\n        return this;\n    }\n    if (typeof selector === 'function') {\n        // HANDLE: $(function)\n        // Shortcut for document ready\n        throw new Error('function not supported');\n    }\n    if (arguments.length > 1) {\n        throw new Error('selector with context not supported');\n    }\n    if (selector.nodeType) {\n        // HANDLE: $(DOMElement)\n        this[0] = selector;\n        this.length = 1;\n        return this;\n    }\n    let match;\n    if (isObviousHtml(selector + '')) {\n        // Handle obvious HTML strings\n        // Assume that strings that start and end with <> are HTML and skip\n        // the regex check. This also handles browser-supported HTML wrappers\n        // like TrustedHTML.\n        match = [null, selector, null];\n    } else if (typeof selector === 'string') {\n        // Handle HTML strings or selectors\n        match = rQuickExpr.exec(selector);\n    } else {\n        // Array-like\n        return $.merge(this, selector);\n    }\n    if (!match || !match[1]) {\n        // HANDLE: $(expr)\n        return $root.find(selector);\n    }\n    // Match html or make sure no context is specified for #id\n    // Note: match[1] may be a string or a TrustedHTML wrapper\n    if (match[1]) {\n        // HANDLE: $(html) -> $(array)\n        $.merge(this, $.parseHTML(match[1]));\n        return this;\n    }\n    // HANDLE: $(#id)\n    const el = document.getElementById(match[2]);\n    if (el) {\n        // Inject the element directly into the $ object\n        this[0] = el;\n        this.length = 1;\n    }\n    return this;\n};\n\n$.Dom = Dom;\n\n// Give the init function the $ prototype for later instantiation\nDom.prototype = $.fn;\n\n// Events\n\n$.Event = Event;\n\n$.event = {\n    special: Object.create(null),\n};\n\n$.event.has = function(elem, eventType) {\n    const events = dataPriv.get(elem, 'events');\n    if (!events) return false;\n    if (!eventType) return true;\n    return Array.isArray(events[eventType]) && events[eventType].length > 0;\n};\n\n$.event.on = function(elem, types, selector, data, fn, one) {\n\n    // Types can be a map of types/handlers\n    if (typeof types === 'object') {\n        // ( types-Object, selector, data )\n        if (typeof selector !== 'string') {\n            // ( types-Object, data )\n            data = data || selector;\n            selector = undefined;\n        }\n        for (let type in types) {\n            $.event.on(elem, type, selector, data, types[type], one);\n        }\n        return elem;\n    }\n\n    if (data == null && fn == null) {\n        // ( types, fn )\n        fn = selector;\n        data = selector = undefined;\n    } else if (fn == null) {\n        if (typeof selector === 'string') {\n            // ( types, selector, fn )\n            fn = data;\n            data = undefined;\n        } else {\n            // ( types, data, fn )\n            fn = data;\n            data = selector;\n            selector = undefined;\n        }\n    }\n    if (!fn) {\n        return elem;\n    }\n    if (one === 1) {\n        const origFn = fn;\n        fn = function(event) {\n            // Can use an empty set, since event contains the info\n            $().off(event);\n            return origFn.apply(this, arguments);\n        };\n\n        // Use same guid so caller can remove using origFn\n        fn.guid = origFn.guid || (origFn.guid = $.guid++);\n    }\n    for (let i = 0; i < elem.length; i++) {\n        $.event.add(elem[i], types, fn, data, selector);\n    }\n};\n\n$.event.add = function(elem, types, handler, data, selector) {\n    // Only attach events to objects for which we can store data\n    if (typeof elem != 'object') {\n        return;\n    }\n\n    const elemData = dataPriv.create(elem);\n\n    // Caller can pass in an object of custom data in lieu of the handler\n    let handleObjIn;\n    if (handler.handler) {\n        handleObjIn = handler;\n        handler = handleObjIn.handler;\n        selector = handleObjIn.selector;\n    }\n\n    // Ensure that invalid selectors throw exceptions at attach time\n    // Evaluate against documentElement in case elem is a non-element node (e.g., document)\n    if (selector) {\n        documentElement.matches(selector);\n    }\n\n    // Make sure that the handler has a unique ID, used to find/remove it later\n    if (!handler.guid) {\n        handler.guid = $.guid++;\n    }\n\n    // Init the element's event structure and main handler, if this is the first\n    let events;\n    if (!(events = elemData.events)) {\n        events = elemData.events = Object.create(null);\n    }\n    let eventHandle;\n    if (!(eventHandle = elemData.handle)) {\n        eventHandle = elemData.handle = function(e) {\n            // Discard the second event of a $.event.trigger() and\n            // when an event is called after a page has unloaded\n            return (typeof $ !== 'undefined')\n                ? $.event.dispatch.apply(elem, arguments)\n                : undefined;\n        };\n    }\n\n    // Handle multiple events separated by a space\n    const typesArr = (types || '').match(rNotHtmlWhite) || [''];\n    let i = typesArr.length;\n    while (i--) {\n        const [, origType, ns = ''] = rTypeNamespace.exec(typesArr[i]);\n        // There *must* be a type, no attaching namespace-only handlers\n        if (!origType) {\n            continue;\n        }\n\n        const namespaces = ns.split('.').sort();\n        // If event changes its type, use the special event handlers for the changed type\n        let special = $.event.special[origType];\n        // If selector defined, determine special event api type, otherwise given type\n        const type = (special && (selector ? special.delegateType : special.bindType)) || origType;\n        // Update special based on newly reset type\n        special = $.event.special[type];\n        // handleObj is passed to all event handlers\n        const handleObj = Object.assign(\n            {\n                type: type,\n                origType: origType,\n                data: data,\n                handler: handler,\n                guid: handler.guid,\n                selector: selector,\n                namespace: namespaces.join('.'),\n            },\n            handleObjIn\n        );\n\n        let handlers;\n        // Init the event handler queue if we're the first\n        if (!(handlers = events[type])) {\n            handlers = events[type] = [];\n            handlers.delegateCount = 0;\n\n            // Only use addEventListener if the special events handler returns false\n            if (\n                !special || !special.setup ||\n                    special.setup.call(elem, data, namespaces, eventHandle) === false\n            ) {\n                if (elem.addEventListener) {\n                    elem.addEventListener(type, eventHandle);\n                }\n            }\n        }\n\n        if (special && special.add) {\n            special.add.call(elem, handleObj);\n            if (!handleObj.handler.guid) {\n                handleObj.handler.guid = handler.guid;\n            }\n        }\n\n        // Add to the element's handler list, delegates in front\n        if (selector) {\n            handlers.splice(handlers.delegateCount++, 0, handleObj);\n        } else {\n            handlers.push(handleObj);\n        }\n    }\n};\n\n// Detach an event or set of events from an element\n$.event.remove = function(elem, types, handler, selector, mappedTypes) {\n\n    const elemData = dataPriv.get(elem);\n    if (!elemData || !elemData.events) return;\n    const events = elemData.events;\n\n    // Once for each type.namespace in types; type may be omitted\n    const typesArr = (types || '').match(rNotHtmlWhite) || [''];\n    let i = typesArr.length;\n    while (i--) {\n        const [, origType, ns = ''] = rTypeNamespace.exec(typesArr[i]);\n        // Unbind all events (on this namespace, if provided) for the element\n        if (!origType) {\n            for (const type in events) {\n                $.event.remove(\n                    elem,\n                    type + typesArr[i],\n                    handler,\n                    selector,\n                    true\n                );\n            }\n            continue;\n        }\n\n        const special = $.event.special[origType];\n        const type = (special && (selector ? special.delegateType : special.bindType)) || origType;\n        const handlers = events[type];\n        if (!handlers || handlers.length === 0) continue;\n\n        const namespaces = ns.split('.').sort();\n        const rNamespace = ns\n            ? new RegExp('(^|\\\\.)' + namespaces.join('\\\\.(?:.*\\\\.|)') + '(\\\\.|$)')\n            : null;\n\n        // Remove matching events\n        const origCount = handlers.length;\n        let j = origCount;\n        while (j--) {\n            const handleObj = handlers[j];\n\n            if (\n                (mappedTypes || origType === handleObj.origType) &&\n                    (!handler || handler.guid === handleObj.guid) &&\n                    (!rNamespace || rNamespace.test(handleObj.namespace)) &&\n                    (!selector ||\n                        selector === handleObj.selector ||\n                        (selector === '**' && handleObj.selector))\n            ) {\n                handlers.splice(j, 1);\n                if (handleObj.selector) {\n                    handlers.delegateCount--;\n                }\n                if (special && special.remove) {\n                    special.remove.call(elem, handleObj);\n                }\n            }\n        }\n\n        // Remove generic event handler if we removed something and no more handlers exist\n        // (avoids potential for endless recursion during removal of special event handlers)\n        if (origCount && handlers.length === 0) {\n            if (\n                !special || !special.teardown ||\n                    special.teardown.call(elem, namespaces, elemData.handle) === false\n            ) {\n                // This \"if\" is needed for plain objects\n                if (elem.removeEventListener) {\n                    elem.removeEventListener(type, elemData.handle);\n                }\n            }\n            delete events[type];\n        }\n    }\n\n    // Remove data if it's no longer used\n    if (isEmpty(events)) {\n        dataPriv.remove(elem, 'handle');\n        dataPriv.remove(elem, 'events');\n    }\n};\n\n$.event.dispatch = function(nativeEvent) {\n\n    const elem = this;\n    // Make a writable $.Event from the native event object\n    const event = $.event.fix(nativeEvent);\n    event.delegateTarget = elem;\n    // Use the fix-ed $.Event rather than the (read-only) native event\n    const args = Array.from(arguments);\n    args[0] = event;\n\n    const eventsData = dataPriv.get(elem, 'events');\n    const handlers = (eventsData && eventsData[event.type]) || [];\n    const special = $.event.special[event.type];\n\n    // Call the preDispatch hook for the mapped type, and let it bail if desired\n    if (special && special.preDispatch) {\n        if (special.preDispatch.call(elem, event) === false) return;\n    }\n\n    // Determine handlers\n    const handlerQueue = $.event.handlers.call(elem, event, handlers);\n\n    // Run delegates first; they may want to stop propagation beneath us\n    let i = 0;\n    let matched;\n    while ((matched = handlerQueue[i++]) && !event.isPropagationStopped()) {\n        event.currentTarget = matched.elem;\n        let j = 0;\n        let handleObj;\n        while (\n            (handleObj = matched.handlers[j++]) &&\n                !event.isImmediatePropagationStopped()\n        ) {\n\n            event.handleObj = handleObj;\n            event.data = handleObj.data;\n\n            const origSpecial = $.event.special[handleObj.origType];\n            let handler;\n            if (origSpecial && origSpecial.handle) {\n                handler = origSpecial.handle;\n            } else {\n                handler = handleObj.handler;\n            }\n\n            const ret = handler.apply(matched.elem, args);\n            if (ret !== undefined) {\n                if ((event.result = ret) === false) {\n                    event.preventDefault();\n                    event.stopPropagation();\n                }\n            }\n        }\n    }\n\n    // Call the postDispatch hook for the mapped type\n    if (special && special.postDispatch) {\n        special.postDispatch.call(elem, event);\n    }\n\n    return event.result;\n};\n\n$.event.handlers = function(event, handlers) {\n\n    const delegateCount = handlers.delegateCount;\n    const handlerQueue = [];\n\n    // Find delegate handlers\n    if (\n        delegateCount &&\n            // Support: Firefox <=42 - 66+\n            // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)\n            // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click\n            // Support: IE 11+\n            // ...but not arrow key \"clicks\" of radio inputs, which can have `button` -1 (gh-2343)\n            !(event.type === 'click' && event.button >= 1)\n    ) {\n        for (let cur = event.target; cur !== this; cur = cur.parentNode || this) {\n            // Don't check non-elements (trac-13208)\n            // Don't process clicks on disabled elements (trac-6911, trac-8165, trac-11382, trac-11764)\n            if (\n                cur.nodeType === 1 &&\n                    !(event.type === 'click' && cur.disabled === true)\n            ) {\n                const matchedHandlers = [];\n                const matchedSelectors = {};\n                for (let i = 0; i < delegateCount; i++) {\n                    const handleObj = handlers[i];\n                    // Don't conflict with Object.prototype properties (trac-13203)\n                    const sel = handleObj.selector + ' ';\n                    if (matchedSelectors[sel] === undefined) {\n                        matchedSelectors[sel] = cur.matches(sel);\n                    }\n                    if (matchedSelectors[sel]) {\n                        matchedHandlers.push(handleObj);\n                    }\n                }\n                if (matchedHandlers.length) {\n                    handlerQueue.push({\n                        elem: cur,\n                        handlers: matchedHandlers,\n                    });\n                }\n            }\n        }\n    }\n\n    // Add the remaining (directly-bound) handlers\n    if (delegateCount < handlers.length) {\n        handlerQueue.push({\n            elem: this,\n            handlers: handlers.slice(delegateCount),\n        });\n    }\n\n    return handlerQueue;\n};\n\n$.event.fix = function(originalEvent) {\n    return originalEvent.envelope ? originalEvent : new Event(originalEvent);\n};\n\n// A central reference to the root $(document)\nconst $root = $(document);\n\nexport { $ as default };\n","// Declare shorthands to the most used math functions.\nconst {\n    round,\n    floor,\n    PI\n} = Math;\n\nexport const scale = {\n\n    // Return the `value` from the `domain` interval scaled to the `range` interval.\n    linear: function(domain, range, value) {\n\n        var domainSpan = domain[1] - domain[0];\n        var rangeSpan = range[1] - range[0];\n        return (((value - domain[0]) / domainSpan) * rangeSpan + range[0]) || 0;\n    }\n};\n\nexport const normalizeAngle = function(angle) {\n\n    return (angle % 360) + (angle < 0 ? 360 : 0);\n};\n\nexport const snapToGrid = function(value, gridSize) {\n\n    return gridSize * round(value / gridSize);\n};\n\nexport const toDeg = function(rad) {\n\n    return (180 * rad / PI) % 360;\n};\n\nexport const toRad = function(deg, over360) {\n\n    over360 = over360 || false;\n    deg = over360 ? deg : (deg % 360);\n    return deg * PI / 180;\n};\n\n// Return a random integer from the interval [min,max], inclusive.\nexport const random = function(min, max) {\n\n    if (max === undefined) {\n        // use first argument as max, min is 0\n        max = (min === undefined) ? 1 : min;\n        min = 0;\n\n    } else if (max < min) {\n        // switch max and min\n        const temp = min;\n        min = max;\n        max = temp;\n    }\n\n    return floor((Math.random() * (max - min + 1)) + min);\n};\n\n","// @return the bearing (cardinal direction) of the line. For example N, W, or SE.\n// @returns {String} One of the following bearings : NE, E, SE, S, SW, W, NW, N.\nimport { toDeg, toRad } from './geometry.helpers.mjs';\n\nconst {\n    cos,\n    sin,\n    atan2\n} = Math;\n\nexport const bearing = function(p, q) {\n\n    var lat1 = toRad(p.y);\n    var lat2 = toRad(q.y);\n    var lon1 = p.x;\n    var lon2 = q.x;\n    var dLon = toRad(lon2 - lon1);\n    var y = sin(dLon) * cos(lat2);\n    var x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);\n    var brng = toDeg(atan2(y, x));\n\n    var bearings = ['NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N'];\n\n    var index = brng - 22.5;\n    if (index < 0)\n        index += 360;\n    index = parseInt(index / 45);\n\n    return bearings[index];\n};\n","// @return {integer} length without sqrt\n// @note for applications where the exact length is not necessary (e.g. compare only)\nexport const squaredLength = function(start, end) {\n\n    var x0 = start.x;\n    var y0 = start.y;\n    var x1 = end.x;\n    var y1 = end.y;\n    return (x0 -= x1) * x0 + (y0 -= y1) * y0;\n};\n","import { squaredLength } from './line.squaredLength.mjs';\n\nexport const length = function(start, end) {\n    return Math.sqrt(squaredLength(start, end));\n};\n","export const types = {\n    Point: 1,\n    Line: 2,\n    Ellipse: 3,\n    Rect: 4,\n    Polyline: 5,\n    Polygon: 6,\n    Curve: 7,\n    Path: 8\n};\n","/*\n    Point is the most basic object consisting of x/y coordinate.\n\n    Possible instantiations are:\n    * `Point(10, 20)`\n    * `new Point(10, 20)`\n    * `Point('10 20')`\n    * `Point(Point(10, 20))`\n*/\nimport { normalizeAngle, random, snapToGrid, toDeg, toRad } from './geometry.helpers.mjs';\nimport { bearing } from './line.bearing.mjs';\nimport { squaredLength } from './line.squaredLength.mjs';\nimport { length } from './line.length.mjs';\nimport { types } from './types.mjs';\n\nconst {\n    abs,\n    cos,\n    sin,\n    sqrt,\n    min,\n    max,\n    atan2,\n    round,\n    pow,\n    PI\n} = Math;\n\nexport const Point = function(x, y) {\n\n    if (!(this instanceof Point)) {\n        return new Point(x, y);\n    }\n\n    if (typeof x === 'string') {\n        var xy = x.split(x.indexOf('@') === -1 ? ' ' : '@');\n        x = parseFloat(xy[0]);\n        y = parseFloat(xy[1]);\n\n    } else if (Object(x) === x) {\n        y = x.y;\n        x = x.x;\n    }\n\n    this.x = x === undefined ? 0 : x;\n    this.y = y === undefined ? 0 : y;\n};\n\n// Alternative constructor, from polar coordinates.\n// @param {number} Distance.\n// @param {number} Angle in radians.\n// @param {point} [optional] Origin.\nPoint.fromPolar = function(distance, angle, origin) {\n\n    origin = new Point(origin);\n    var x = abs(distance * cos(angle));\n    var y = abs(distance * sin(angle));\n    var deg = normalizeAngle(toDeg(angle));\n\n    if (deg < 90) {\n        y = -y;\n\n    } else if (deg < 180) {\n        x = -x;\n        y = -y;\n\n    } else if (deg < 270) {\n        x = -x;\n    }\n\n    return new Point(origin.x + x, origin.y + y);\n};\n\n// Create a point with random coordinates that fall into the range `[x1, x2]` and `[y1, y2]`.\nPoint.random = function(x1, x2, y1, y2) {\n\n    return new Point(random(x1, x2), random(y1, y2));\n};\n\nPoint.prototype = {\n\n    type: types.Point,\n\n    chooseClosest: function(points) {\n\n        var n = points.length;\n        if (n === 1) return new Point(points[0]);\n        var closest = null;\n        var minSqrDistance = Infinity;\n        for (var i = 0; i < n; i++) {\n            var p = new Point(points[i]);\n            var sqrDistance = this.squaredDistance(p);\n            if (sqrDistance < minSqrDistance) {\n                closest = p;\n                minSqrDistance = sqrDistance;\n            }\n        }\n        return closest;\n    },\n\n    // If point lies outside rectangle `r`, return the nearest point on the boundary of rect `r`,\n    // otherwise return point itself.\n    // (see Squeak Smalltalk, Point>>adhereTo:)\n    adhereToRect: function(r) {\n\n        if (r.containsPoint(this)) {\n            return this;\n        }\n\n        this.x = min(max(this.x, r.x), r.x + r.width);\n        this.y = min(max(this.y, r.y), r.y + r.height);\n        return this;\n    },\n\n    // Compute the angle between vector from me to p1 and the vector from me to p2.\n    // ordering of points p1 and p2 is important!\n    // theta function's angle convention:\n    // returns angles between 0 and 180 when the angle is counterclockwise\n    // returns angles between 180 and 360 to convert clockwise angles into counterclockwise ones\n    // returns NaN if any of the points p1, p2 is coincident with this point\n    angleBetween: function(p1, p2) {\n\n        var angleBetween = (this.equals(p1) || this.equals(p2)) ? NaN : (this.theta(p2) - this.theta(p1));\n\n        if (angleBetween < 0) {\n            angleBetween += 360; // correction to keep angleBetween between 0 and 360\n        }\n\n        return angleBetween;\n    },\n\n    // Return the bearing between me and the given point.\n    bearing: function(point) {\n        return bearing(this, point);\n    },\n\n    // Returns change in angle from my previous position (-dx, -dy) to my new position\n    // relative to ref point.\n    changeInAngle: function(dx, dy, ref) {\n\n        // Revert the translation and measure the change in angle around x-axis.\n        return this.clone().offset(-dx, -dy).theta(ref) - this.theta(ref);\n    },\n\n    clone: function() {\n\n        return new Point(this);\n    },\n\n    // Returns the cross product of this point relative to two other points\n    // this point is the common point\n    // point p1 lies on the first vector, point p2 lies on the second vector\n    // watch out for the ordering of points p1 and p2!\n    // positive result indicates a clockwise (\"right\") turn from first to second vector\n    // negative result indicates a counterclockwise (\"left\") turn from first to second vector\n    // zero indicates that the first and second vector are collinear\n    // note that the above directions are reversed from the usual answer on the Internet\n    // that is because we are in a left-handed coord system (because the y-axis points downward)\n    cross: function(p1, p2) {\n\n        return (p1 && p2) ? (((p2.x - this.x) * (p1.y - this.y)) - ((p2.y - this.y) * (p1.x - this.x))) : NaN;\n    },\n\n    difference: function(dx, dy) {\n\n        if ((Object(dx) === dx)) {\n            dy = dx.y;\n            dx = dx.x;\n        }\n\n        return new Point(this.x - (dx || 0), this.y - (dy || 0));\n    },\n\n    // Returns distance between me and point `p`.\n    distance: function(p) {\n        return length(this, p);\n    },\n\n    // Returns the dot product of this point with given other point\n    dot: function(p) {\n\n        return p ? (this.x * p.x + this.y * p.y) : NaN;\n    },\n\n    equals: function(p) {\n\n        return !!p &&\n            this.x === p.x &&\n            this.y === p.y;\n    },\n\n    // Linear interpolation\n    lerp: function(p, t) {\n\n        var x = this.x;\n        var y = this.y;\n        return new Point((1 - t) * x + t * p.x, (1 - t) * y + t * p.y);\n    },\n\n    magnitude: function() {\n\n        return sqrt((this.x * this.x) + (this.y * this.y)) || 0.01;\n    },\n\n    // Returns a manhattan (taxi-cab) distance between me and point `p`.\n    manhattanDistance: function(p) {\n\n        return abs(p.x - this.x) + abs(p.y - this.y);\n    },\n\n    // Move point on line starting from ref ending at me by\n    // distance distance.\n    move: function(ref, distance) {\n\n        var theta = toRad((new Point(ref)).theta(this));\n        var offset = this.offset(cos(theta) * distance, -sin(theta) * distance);\n        return offset;\n    },\n\n    // Scales x and y such that the distance between the point and the origin (0,0) is equal to the given length.\n    normalize: function(length) {\n\n        var scale = (length || 1) / this.magnitude();\n        return this.scale(scale, scale);\n    },\n\n    // Offset me by the specified amount.\n    offset: function(dx, dy) {\n\n        if ((Object(dx) === dx)) {\n            dy = dx.y;\n            dx = dx.x;\n        }\n\n        this.x += dx || 0;\n        this.y += dy || 0;\n        return this;\n    },\n\n    // Returns a point that is the reflection of me with\n    // the center of inversion in ref point.\n    reflection: function(ref) {\n\n        return (new Point(ref)).move(this, this.distance(ref));\n    },\n\n    // Rotate point by angle around origin.\n    // Angle is flipped because this is a left-handed coord system (y-axis points downward).\n    rotate: function(origin, angle) {\n\n        if (angle === 0) return this;\n\n        origin = origin || new Point(0, 0);\n\n        angle = toRad(normalizeAngle(-angle));\n        var cosAngle = cos(angle);\n        var sinAngle = sin(angle);\n\n        var x = (cosAngle * (this.x - origin.x)) - (sinAngle * (this.y - origin.y)) + origin.x;\n        var y = (sinAngle * (this.x - origin.x)) + (cosAngle * (this.y - origin.y)) + origin.y;\n\n        this.x = x;\n        this.y = y;\n        return this;\n    },\n\n    round: function(precision) {\n\n        let f = 1; // case 0\n        if (precision) {\n            switch (precision) {\n                case 1: f = 10; break;\n                case 2: f = 100; break;\n                case 3: f = 1000; break;\n                default: f = pow(10, precision); break;\n            }\n        }\n\n        this.x = round(this.x * f) / f;\n        this.y = round(this.y * f) / f;\n        return this;\n    },\n\n    // Scale point with origin.\n    scale: function(sx, sy, origin) {\n\n        origin = (origin && new Point(origin)) || new Point(0, 0);\n        this.x = origin.x + sx * (this.x - origin.x);\n        this.y = origin.y + sy * (this.y - origin.y);\n        return this;\n    },\n\n    snapToGrid: function(gx, gy) {\n\n        this.x = snapToGrid(this.x, gx);\n        this.y = snapToGrid(this.y, gy || gx);\n        return this;\n    },\n\n    squaredDistance: function(p) {\n        return squaredLength(this, p);\n    },\n\n    // Compute the angle between me and `p` and the x axis.\n    // (cartesian-to-polar coordinates conversion)\n    // Return theta angle in degrees.\n    theta: function(p) {\n\n        p = new Point(p);\n\n        // Invert the y-axis.\n        var y = -(p.y - this.y);\n        var x = p.x - this.x;\n        var rad = atan2(y, x); // defined for all 0 corner cases\n\n        // Correction for III. and IV. quadrant.\n        if (rad < 0) {\n            rad = 2 * PI + rad;\n        }\n\n        return 180 * rad / PI;\n    },\n\n    toJSON: function() {\n\n        return { x: this.x, y: this.y };\n    },\n\n    // Converts rectangular to polar coordinates.\n    // An origin can be specified, otherwise it's 0@0.\n    toPolar: function(o) {\n\n        o = (o && new Point(o)) || new Point(0, 0);\n        var x = this.x;\n        var y = this.y;\n        this.x = sqrt((x - o.x) * (x - o.x) + (y - o.y) * (y - o.y)); // r\n        this.y = toRad(o.theta(new Point(x, y)));\n        return this;\n    },\n\n    toString: function() {\n\n        return this.x + '@' + this.y;\n    },\n\n    serialize: function() {\n\n        return this.x + ',' + this.y;\n    },\n\n    update: function(x, y) {\n\n        if ((Object(x) === x)) {\n            y = x.y;\n            x = x.x;\n        }\n\n        this.x = x || 0;\n        this.y = y || 0;\n        return this;\n    },\n\n    // Compute the angle between the vector from 0,0 to me and the vector from 0,0 to p.\n    // Returns NaN if p is at 0,0.\n    vectorAngle: function(p) {\n\n        var zero = new Point(0, 0);\n        return zero.angleBetween(this, p);\n    }\n};\n\nPoint.prototype.translate = Point.prototype.offset;\n\n// For backwards compatibility:\nexport const point = Point;\n","import { Point } from './point.mjs';\nimport { Rect } from './rect.mjs';\nimport { bearing } from './line.bearing.mjs';\nimport { squaredLength } from './line.squaredLength.mjs';\nimport { length } from './line.length.mjs';\nimport { types } from './types.mjs';\n\nconst {\n    max,\n    min\n} = Math;\n\nexport const Line = function(p1, p2) {\n\n    if (!(this instanceof Line)) {\n        return new Line(p1, p2);\n    }\n\n    if (p1 instanceof Line) {\n        return new Line(p1.start, p1.end);\n    }\n\n    this.start = new Point(p1);\n    this.end = new Point(p2);\n};\n\nLine.prototype = {\n\n    type: types.Line,\n\n    // @returns the angle of incline of the line.\n    angle: function() {\n\n        var horizontalPoint = new Point(this.start.x + 1, this.start.y);\n        return this.start.angleBetween(this.end, horizontalPoint);\n    },\n\n    bbox: function() {\n\n        var left = min(this.start.x, this.end.x);\n        var top = min(this.start.y, this.end.y);\n        var right = max(this.start.x, this.end.x);\n        var bottom = max(this.start.y, this.end.y);\n\n        return new Rect(left, top, (right - left), (bottom - top));\n    },\n\n    // @return the bearing (cardinal direction) of the line. For example N, W, or SE.\n    // @returns {String} One of the following bearings : NE, E, SE, S, SW, W, NW, N.\n    bearing: function() {\n        return bearing(this.start, this.end);\n    },\n\n    clone: function() {\n\n        return new Line(this.start, this.end);\n    },\n\n    // @return {point} the closest point on the line to point `p`\n    closestPoint: function(p) {\n\n        return this.pointAt(this.closestPointNormalizedLength(p));\n    },\n\n    closestPointLength: function(p) {\n\n        return this.closestPointNormalizedLength(p) * this.length();\n    },\n\n    // @return {number} the normalized length of the closest point on the line to point `p`\n    closestPointNormalizedLength: function(p) {\n\n        var product = this.vector().dot((new Line(this.start, p)).vector());\n        var cpNormalizedLength = min(1, max(0, product / this.squaredLength()));\n\n        // cpNormalizedLength returns `NaN` if this line has zero length\n        // we can work with that - if `NaN`, return 0\n        if (cpNormalizedLength !== cpNormalizedLength) return 0; // condition evaluates to `true` if and only if cpNormalizedLength is `NaN`\n        // (`NaN` is the only value that is not equal to itself)\n\n        return cpNormalizedLength;\n    },\n\n    closestPointTangent: function(p) {\n\n        return this.tangentAt(this.closestPointNormalizedLength(p));\n    },\n\n    // Returns `true` if the point lies on the line.\n    containsPoint: function(p) {\n\n        var start = this.start;\n        var end = this.end;\n\n        if (start.cross(p, end) !== 0) return false;\n        // else: cross product of 0 indicates that this line and the vector to `p` are collinear\n\n        var length = this.length();\n        if ((new Line(start, p)).length() > length) return false;\n        if ((new Line(p, end)).length() > length) return false;\n        // else: `p` lies between start and end of the line\n\n        return true;\n    },\n\n    // Divides the line into two at requested `ratio` between 0 and 1.\n    divideAt: function(ratio) {\n\n        var dividerPoint = this.pointAt(ratio);\n\n        // return array with two lines\n        return [\n            new Line(this.start, dividerPoint),\n            new Line(dividerPoint, this.end)\n        ];\n    },\n\n    // Divides the line into two at requested `length`.\n    divideAtLength: function(length) {\n\n        var dividerPoint = this.pointAtLength(length);\n\n        // return array with two new lines\n        return [\n            new Line(this.start, dividerPoint),\n            new Line(dividerPoint, this.end)\n        ];\n    },\n\n    equals: function(l) {\n\n        return !!l &&\n            this.start.x === l.start.x &&\n            this.start.y === l.start.y &&\n            this.end.x === l.end.x &&\n            this.end.y === l.end.y;\n    },\n\n    // @return {point} Point where I'm intersecting a line.\n    // @return [point] Points where I'm intersecting a rectangle.\n    // @see Squeak Smalltalk, LineSegment>>intersectionWith:\n    intersect: function(shape, opt) {\n\n        if (shape && shape.intersectionWithLine) {\n            var intersection = shape.intersectionWithLine(this, opt);\n\n            // Backwards compatibility\n            if (intersection && (shape instanceof Line)) {\n                intersection = intersection[0];\n            }\n\n            return intersection;\n        }\n\n        return null;\n    },\n\n    intersectionWithLine: function(line) {\n\n        var pt1Dir = new Point(this.end.x - this.start.x, this.end.y - this.start.y);\n        var pt2Dir = new Point(line.end.x - line.start.x, line.end.y - line.start.y);\n        var det = (pt1Dir.x * pt2Dir.y) - (pt1Dir.y * pt2Dir.x);\n        var deltaPt = new Point(line.start.x - this.start.x, line.start.y - this.start.y);\n        var alpha = (deltaPt.x * pt2Dir.y) - (deltaPt.y * pt2Dir.x);\n        var beta = (deltaPt.x * pt1Dir.y) - (deltaPt.y * pt1Dir.x);\n\n        if (det === 0 || alpha * det < 0 || beta * det < 0) {\n            // No intersection found.\n            return null;\n        }\n\n        if (det > 0) {\n            if (alpha > det || beta > det) {\n                return null;\n            }\n\n        } else {\n            if (alpha < det || beta < det) {\n                return null;\n            }\n        }\n\n        return [new Point(\n            this.start.x + (alpha * pt1Dir.x / det),\n            this.start.y + (alpha * pt1Dir.y / det)\n        )];\n    },\n\n    isDifferentiable: function() {\n\n        return !this.start.equals(this.end);\n    },\n\n    // @return {double} length of the line\n    length: function() {\n        return length(this.start, this.end);\n    },\n\n    // @return {point} my midpoint\n    midpoint: function() {\n\n        return new Point(\n            (this.start.x + this.end.x) / 2,\n            (this.start.y + this.end.y) / 2\n        );\n    },\n\n    parallel: function(distance) {\n        const l = this.clone();\n        if (!this.isDifferentiable()) return l;\n        const { start, end } = l;\n        const eRef = start.clone().rotate(end, 270);\n        const sRef = end.clone().rotate(start, 90);\n        start.move(sRef, distance);\n        end.move(eRef, distance);\n        return l;\n    },\n\n    // @return {point} my point at 't' <0,1>\n    pointAt: function(t) {\n\n        var start = this.start;\n        var end = this.end;\n\n        if (t <= 0) return start.clone();\n        if (t >= 1) return end.clone();\n\n        return start.lerp(end, t);\n    },\n\n    pointAtLength: function(length) {\n\n        var start = this.start;\n        var end = this.end;\n\n        var fromStart = true;\n        if (length < 0) {\n            fromStart = false; // negative lengths mean start calculation from end point\n            length = -length; // absolute value\n        }\n\n        var lineLength = this.length();\n        if (length >= lineLength) return (fromStart ? end.clone() : start.clone());\n\n        return this.pointAt((fromStart ? (length) : (lineLength - length)) / lineLength);\n    },\n\n    // @return {number} the offset of the point `p` from the line. + if the point `p` is on the right side of the line, - if on the left and 0 if on the line.\n    pointOffset: function(p) {\n\n        // Find the sign of the determinant of vectors (start,end), where p is the query point.\n        p = new Point(p);\n        var start = this.start;\n        var end = this.end;\n        var determinant = ((end.x - start.x) * (p.y - start.y) - (end.y - start.y) * (p.x - start.x));\n\n        return determinant / this.length();\n    },\n\n    rotate: function(origin, angle) {\n\n        this.start.rotate(origin, angle);\n        this.end.rotate(origin, angle);\n        return this;\n    },\n\n    round: function(precision) {\n\n        this.start.round(precision);\n        this.end.round(precision);\n        return this;\n    },\n\n    scale: function(sx, sy, origin) {\n\n        this.start.scale(sx, sy, origin);\n        this.end.scale(sx, sy, origin);\n        return this;\n    },\n\n    // @return {number} scale the line so that it has the requested length\n    setLength: function(length) {\n\n        var currentLength = this.length();\n        if (!currentLength) return this;\n\n        var scaleFactor = length / currentLength;\n        return this.scale(scaleFactor, scaleFactor, this.start);\n    },\n\n    // @return {integer} length without sqrt\n    // @note for applications where the exact length is not necessary (e.g. compare only)\n    squaredLength: function() {\n        return squaredLength(this.start, this.end);\n    },\n\n    tangentAt: function(t) {\n\n        if (!this.isDifferentiable()) return null;\n\n        var start = this.start;\n        var end = this.end;\n\n        var tangentStart = this.pointAt(t); // constrains `t` between 0 and 1\n\n        var tangentLine = new Line(start, end);\n        tangentLine.translate(tangentStart.x - start.x, tangentStart.y - start.y); // move so that tangent line starts at the point requested\n\n        return tangentLine;\n    },\n\n    tangentAtLength: function(length) {\n\n        if (!this.isDifferentiable()) return null;\n\n        var start = this.start;\n        var end = this.end;\n\n        var tangentStart = this.pointAtLength(length);\n\n        var tangentLine = new Line(start, end);\n        tangentLine.translate(tangentStart.x - start.x, tangentStart.y - start.y); // move so that tangent line starts at the point requested\n\n        return tangentLine;\n    },\n\n    toString: function() {\n\n        return this.start.toString() + ' ' + this.end.toString();\n    },\n\n    serialize: function() {\n\n        return this.start.serialize() + ' ' + this.end.serialize();\n    },\n\n    translate: function(tx, ty) {\n\n        this.start.translate(tx, ty);\n        this.end.translate(tx, ty);\n        return this;\n    },\n\n    // @return vector {point} of the line\n    vector: function() {\n\n        return new Point(this.end.x - this.start.x, this.end.y - this.start.y);\n    }\n};\n\n// For backwards compatibility:\nLine.prototype.intersection = Line.prototype.intersect;\n\n\n// For backwards compatibility:\nexport const line = Line;\n","import { Rect } from './rect.mjs';\nimport { Point } from './point.mjs';\nimport { types } from './types.mjs';\n\nconst {\n    sqrt,\n    round,\n    pow\n} = Math;\n\nexport const Ellipse = function(c, a, b) {\n\n    if (!(this instanceof Ellipse)) {\n        return new Ellipse(c, a, b);\n    }\n\n    if (c instanceof Ellipse) {\n        return new Ellipse(new Point(c.x, c.y), c.a, c.b);\n    }\n\n    c = new Point(c);\n    this.x = c.x;\n    this.y = c.y;\n    this.a = a;\n    this.b = b;\n};\n\nEllipse.fromRect = function(rect) {\n\n    rect = new Rect(rect);\n    return new Ellipse(rect.center(), rect.width / 2, rect.height / 2);\n};\n\nEllipse.prototype = {\n\n    type: types.Ellipse,\n\n    bbox: function() {\n\n        return new Rect(this.x - this.a, this.y - this.b, 2 * this.a, 2 * this.b);\n    },\n\n    /**\n     * @returns {g.Point}\n     */\n    center: function() {\n\n        return new Point(this.x, this.y);\n    },\n\n    clone: function() {\n\n        return new Ellipse(this);\n    },\n\n    /**\n     * @param {g.Point} p\n     * @returns {boolean}\n     */\n    containsPoint: function(p) {\n\n        return this.normalizedDistance(p) <= 1;\n    },\n\n    equals: function(ellipse) {\n\n        return !!ellipse &&\n            ellipse.x === this.x &&\n            ellipse.y === this.y &&\n            ellipse.a === this.a &&\n            ellipse.b === this.b;\n    },\n\n    // inflate by dx and dy\n    // @param dx {delta_x} representing additional size to x\n    // @param dy {delta_y} representing additional size to y -\n    // dy param is not required -> in that case y is sized by dx\n    inflate: function(dx, dy) {\n        if (dx === undefined) {\n            dx = 0;\n        }\n\n        if (dy === undefined) {\n            dy = dx;\n        }\n\n        this.a += 2 * dx;\n        this.b += 2 * dy;\n\n        return this;\n    },\n\n    intersectionWithLine: function(line) {\n\n        var intersections = [];\n        var a1 = line.start;\n        var a2 = line.end;\n        var rx = this.a;\n        var ry = this.b;\n        var dir = line.vector();\n        var diff = a1.difference(new Point(this));\n        var mDir = new Point(dir.x / (rx * rx), dir.y / (ry * ry));\n        var mDiff = new Point(diff.x / (rx * rx), diff.y / (ry * ry));\n\n        var a = dir.dot(mDir);\n        var b = dir.dot(mDiff);\n        var c = diff.dot(mDiff) - 1.0;\n        var d = b * b - a * c;\n\n        if (d < 0) {\n            return null;\n        } else if (d > 0) {\n            var root = sqrt(d);\n            var ta = (-b - root) / a;\n            var tb = (-b + root) / a;\n\n            if ((ta < 0 || 1 < ta) && (tb < 0 || 1 < tb)) {\n                // if ((ta < 0 && tb < 0) || (ta > 1 && tb > 1)) outside else inside\n                return null;\n            } else {\n                if (0 <= ta && ta <= 1) intersections.push(a1.lerp(a2, ta));\n                if (0 <= tb && tb <= 1) intersections.push(a1.lerp(a2, tb));\n            }\n        } else {\n            var t = -b / a;\n            if (0 <= t && t <= 1) {\n                intersections.push(a1.lerp(a2, t));\n            } else {\n                // outside\n                return null;\n            }\n        }\n\n        return intersections;\n    },\n\n    // Find point on me where line from my center to\n    // point p intersects my boundary.\n    // @param {number} angle If angle is specified, intersection with rotated ellipse is computed.\n    intersectionWithLineFromCenterToPoint: function(p, angle) {\n\n        p = new Point(p);\n\n        if (angle) p.rotate(new Point(this.x, this.y), angle);\n\n        var dx = p.x - this.x;\n        var dy = p.y - this.y;\n        var result;\n\n        if (dx === 0) {\n            result = this.bbox().pointNearestToPoint(p);\n            if (angle) return result.rotate(new Point(this.x, this.y), -angle);\n            return result;\n        }\n\n        var m = dy / dx;\n        var mSquared = m * m;\n        var aSquared = this.a * this.a;\n        var bSquared = this.b * this.b;\n\n        var x = sqrt(1 / ((1 / aSquared) + (mSquared / bSquared)));\n        x = dx < 0 ? -x : x;\n\n        var y = m * x;\n        result = new Point(this.x + x, this.y + y);\n\n        if (angle) return result.rotate(new Point(this.x, this.y), -angle);\n        return result;\n    },\n\n    /**\n     * @param {g.Point} point\n     * @returns {number} result < 1 - inside ellipse, result == 1 - on ellipse boundary, result > 1 - outside\n     */\n    normalizedDistance: function(point) {\n\n        var x0 = point.x;\n        var y0 = point.y;\n        var a = this.a;\n        var b = this.b;\n        var x = this.x;\n        var y = this.y;\n\n        return ((x0 - x) * (x0 - x)) / (a * a) + ((y0 - y) * (y0 - y)) / (b * b);\n    },\n\n    round: function(precision) {\n\n        let f = 1; // case 0\n        if (precision) {\n            switch (precision) {\n                case 1: f = 10; break;\n                case 2: f = 100; break;\n                case 3: f = 1000; break;\n                default: f = pow(10, precision); break;\n            }\n        }\n\n        this.x = round(this.x * f) / f;\n        this.y = round(this.y * f) / f;\n        this.a = round(this.a * f) / f;\n        this.b = round(this.b * f) / f;\n        return this;\n    },\n\n    /** Compute angle between tangent and x axis\n     * @param {g.Point} p Point of tangency, it has to be on ellipse boundaries.\n     * @returns {number} angle between tangent and x axis\n     */\n    tangentTheta: function(p) {\n\n        var refPointDelta = 30;\n        var x0 = p.x;\n        var y0 = p.y;\n        var a = this.a;\n        var b = this.b;\n        var center = this.bbox().center();\n        var m = center.x;\n        var n = center.y;\n\n        var q1 = x0 > center.x + a / 2;\n        var q3 = x0 < center.x - a / 2;\n\n        var y, x;\n        if (q1 || q3) {\n            y = x0 > center.x ? y0 - refPointDelta : y0 + refPointDelta;\n            x = (a * a / (x0 - m)) - (a * a * (y0 - n) * (y - n)) / (b * b * (x0 - m)) + m;\n\n        } else {\n            x = y0 > center.y ? x0 + refPointDelta : x0 - refPointDelta;\n            y = (b * b / (y0 - n)) - (b * b * (x0 - m) * (x - m)) / (a * a * (y0 - n)) + n;\n        }\n\n        return (new Point(x, y)).theta(p);\n\n    },\n\n    toString: function() {\n\n        return (new Point(this.x, this.y)).toString() + ' ' + this.a + ' ' + this.b;\n    }\n};\n\n// For backwards compatibility:\nexport const ellipse = Ellipse;\n","import { toRad } from './geometry.helpers.mjs';\nimport { Line } from './line.mjs';\nimport { Point } from './point.mjs';\nimport { Ellipse } from './ellipse.mjs';\nimport { types } from './types.mjs';\n\nconst {\n    abs,\n    cos,\n    sin,\n    min,\n    max,\n    round,\n    pow\n} = Math;\n\nexport const Rect = function(x, y, w, h) {\n\n    if (!(this instanceof Rect)) {\n        return new Rect(x, y, w, h);\n    }\n\n    if ((Object(x) === x)) {\n        y = x.y;\n        w = x.width;\n        h = x.height;\n        x = x.x;\n    }\n\n    this.x = x === undefined ? 0 : x;\n    this.y = y === undefined ? 0 : y;\n    this.width = w === undefined ? 0 : w;\n    this.height = h === undefined ? 0 : h;\n};\n\nRect.fromEllipse = function(e) {\n\n    e = new Ellipse(e);\n    return new Rect(e.x - e.a, e.y - e.b, 2 * e.a, 2 * e.b);\n};\n\nRect.fromPointUnion = function(...points) {\n\n    if (points.length === 0) return null;\n\n    const p = new Point();\n    let minX, minY, maxX, maxY;\n    minX = minY = Infinity;\n    maxX = maxY = -Infinity;\n\n    for (let i = 0; i < points.length; i++) {\n        p.update(points[i]);\n        const x = p.x;\n        const y = p.y;\n\n        if (x < minX) minX = x;\n        if (x > maxX) maxX = x;\n        if (y < minY) minY = y;\n        if (y > maxY) maxY = y;\n    }\n\n    return new Rect(minX, minY, maxX - minX, maxY - minY);\n};\n\nRect.fromRectUnion = function(...rects) {\n\n    if (rects.length === 0) return null;\n\n    const r = new Rect();\n    let minX, minY, maxX, maxY;\n    minX = minY = Infinity;\n    maxX = maxY = -Infinity;\n\n    for (let i = 0; i < rects.length; i++) {\n        r.update(rects[i]);\n        const x = r.x;\n        const y = r.y;\n        const mX = x + r.width;\n        const mY = y + r.height;\n\n        if (x < minX) minX = x;\n        if (mX > maxX) maxX = mX;\n        if (y < minY) minY = y;\n        if (mY > maxY) maxY = mY;\n    }\n\n    return new Rect(minX, minY, maxX - minX, maxY - minY);\n};\n\nRect.prototype = {\n\n    type: types.Rect,\n\n    // Find my bounding box when I'm rotated with the center of rotation in the center of me.\n    // @return r {rectangle} representing a bounding box\n    bbox: function(angle) {\n        return this.clone().rotateAroundCenter(angle);\n    },\n\n    rotateAroundCenter: function(angle) {\n        if (!angle) return this;\n        const { width, height } = this;\n        const theta = toRad(angle);\n        const st = abs(sin(theta));\n        const ct = abs(cos(theta));\n        const w = width * ct + height * st;\n        const h = width * st + height * ct;\n        this.x += (width - w) / 2;\n        this.y += (height - h) / 2;\n        this.width = w;\n        this.height = h;\n        return this;\n    },\n\n    bottomLeft: function() {\n\n        return new Point(this.x, this.y + this.height);\n    },\n\n    bottomLine: function() {\n\n        return new Line(this.bottomLeft(), this.bottomRight());\n    },\n\n    bottomMiddle: function() {\n\n        return new Point(this.x + this.width / 2, this.y + this.height);\n    },\n\n    center: function() {\n\n        return new Point(this.x + this.width / 2, this.y + this.height / 2);\n    },\n\n    clone: function() {\n\n        return new Rect(this);\n    },\n\n    // @return {bool} true if point p is inside me.\n    // @param {bool} strict If true, the point has to be strictly inside (not on the border).\n    containsPoint: function(p, opt) {\n        let x, y;\n        if (!p || (typeof p === 'string')) {\n            // Backwards compatibility: if the point is not provided,\n            // the point is considered to be the origin [0, 0].\n            ({ x, y } = new Point(p));\n        } else {\n            // Do not create a new Point object if the point is already a Point-like object.\n            ({ x = 0, y = 0 } = p);\n        }\n        return opt && opt.strict\n            ? (x > this.x && x < this.x + this.width && y > this.y && y < this.y + this.height)\n            : x >= this.x && x <= this.x + this.width && y >= this.y && y <= this.y + this.height;\n    },\n\n    // @return {bool} true if rectangle `r` is inside me.\n    containsRect: function(r) {\n\n        var r0 = new Rect(this).normalize();\n        var r1 = new Rect(r).normalize();\n        var w0 = r0.width;\n        var h0 = r0.height;\n        var w1 = r1.width;\n        var h1 = r1.height;\n\n        if (!w0 || !h0 || !w1 || !h1) {\n            // At least one of the dimensions is 0\n            return false;\n        }\n\n        var x0 = r0.x;\n        var y0 = r0.y;\n        var x1 = r1.x;\n        var y1 = r1.y;\n\n        w1 += x1;\n        w0 += x0;\n        h1 += y1;\n        h0 += y0;\n\n        return x0 <= x1 && w1 <= w0 && y0 <= y1 && h1 <= h0;\n    },\n\n    corner: function() {\n\n        return new Point(this.x + this.width, this.y + this.height);\n    },\n\n    // @return {boolean} true if rectangles are equal.\n    equals: function(r) {\n\n        var mr = (new Rect(this)).normalize();\n        var nr = (new Rect(r)).normalize();\n        return mr.x === nr.x && mr.y === nr.y && mr.width === nr.width && mr.height === nr.height;\n    },\n\n    // inflate by dx and dy, recompute origin [x, y]\n    // @param dx {delta_x} representing additional size to x\n    // @param dy {delta_y} representing additional size to y -\n    // dy param is not required -> in that case y is sized by dx\n    inflate: function(dx, dy) {\n\n        if (dx === undefined) {\n            dx = 0;\n        }\n\n        if (dy === undefined) {\n            dy = dx;\n        }\n\n        this.x -= dx;\n        this.y -= dy;\n        this.width += 2 * dx;\n        this.height += 2 * dy;\n\n        return this;\n    },\n\n    // @return {rect} if rectangles intersect, {null} if not.\n    intersect: function(r) {\n\n        var myOrigin = this.origin();\n        var myCorner = this.corner();\n        var rOrigin = r.origin();\n        var rCorner = r.corner();\n\n        // No intersection found\n        if (rCorner.x <= myOrigin.x ||\n            rCorner.y <= myOrigin.y ||\n            rOrigin.x >= myCorner.x ||\n            rOrigin.y >= myCorner.y) return null;\n\n        var x = max(myOrigin.x, rOrigin.x);\n        var y = max(myOrigin.y, rOrigin.y);\n\n        return new Rect(x, y, min(myCorner.x, rCorner.x) - x, min(myCorner.y, rCorner.y) - y);\n    },\n\n    intersectionWithLine: function(line) {\n\n        var r = this;\n        var rectLines = [r.topLine(), r.rightLine(), r.bottomLine(), r.leftLine()];\n        var points = [];\n        var dedupeArr = [];\n        var pt, i;\n\n        var n = rectLines.length;\n        for (i = 0; i < n; i++) {\n\n            pt = line.intersect(rectLines[i]);\n            if (pt !== null && dedupeArr.indexOf(pt.toString()) < 0) {\n                points.push(pt);\n                dedupeArr.push(pt.toString());\n            }\n        }\n\n        return points.length > 0 ? points : null;\n    },\n\n    // Find point on my boundary where line starting\n    // from my center ending in point p intersects me.\n    // @param {number} angle If angle is specified, intersection with rotated rectangle is computed.\n    intersectionWithLineFromCenterToPoint: function(p, angle) {\n\n        p = new Point(p);\n        var center = new Point(this.x + this.width / 2, this.y + this.height / 2);\n        var result;\n\n        if (angle) p.rotate(center, angle);\n\n        // (clockwise, starting from the top side)\n        var sides = [\n            this.topLine(),\n            this.rightLine(),\n            this.bottomLine(),\n            this.leftLine()\n        ];\n        var connector = new Line(center, p);\n\n        for (var i = sides.length - 1; i >= 0; --i) {\n            var intersection = sides[i].intersection(connector);\n            if (intersection !== null) {\n                result = intersection;\n                break;\n            }\n        }\n        if (result && angle) result.rotate(center, -angle);\n        return result;\n    },\n\n    leftLine: function() {\n\n        return new Line(this.topLeft(), this.bottomLeft());\n    },\n\n    leftMiddle: function() {\n\n        return new Point(this.x, this.y + this.height / 2);\n    },\n\n    maxRectScaleToFit: function(rect, origin) {\n\n        rect = new Rect(rect);\n        origin || (origin = rect.center());\n\n        var sx1, sx2, sx3, sx4, sy1, sy2, sy3, sy4;\n        var ox = origin.x;\n        var oy = origin.y;\n\n        // Here we find the maximal possible scale for all corner points (for x and y axis) of the rectangle,\n        // so when the scale is applied the point is still inside the rectangle.\n\n        sx1 = sx2 = sx3 = sx4 = sy1 = sy2 = sy3 = sy4 = Infinity;\n\n        // Top Left\n        var p1 = rect.topLeft();\n        if (p1.x < ox) {\n            sx1 = (this.x - ox) / (p1.x - ox);\n        }\n        if (p1.y < oy) {\n            sy1 = (this.y - oy) / (p1.y - oy);\n        }\n        // Bottom Right\n        var p2 = rect.bottomRight();\n        if (p2.x > ox) {\n            sx2 = (this.x + this.width - ox) / (p2.x - ox);\n        }\n        if (p2.y > oy) {\n            sy2 = (this.y + this.height - oy) / (p2.y - oy);\n        }\n        // Top Right\n        var p3 = rect.topRight();\n        if (p3.x > ox) {\n            sx3 = (this.x + this.width - ox) / (p3.x - ox);\n        }\n        if (p3.y < oy) {\n            sy3 = (this.y - oy) / (p3.y - oy);\n        }\n        // Bottom Left\n        var p4 = rect.bottomLeft();\n        if (p4.x < ox) {\n            sx4 = (this.x - ox) / (p4.x - ox);\n        }\n        if (p4.y > oy) {\n            sy4 = (this.y + this.height - oy) / (p4.y - oy);\n        }\n\n        return {\n            sx: min(sx1, sx2, sx3, sx4),\n            sy: min(sy1, sy2, sy3, sy4)\n        };\n    },\n\n    maxRectUniformScaleToFit: function(rect, origin) {\n\n        var scale = this.maxRectScaleToFit(rect, origin);\n        return min(scale.sx, scale.sy);\n    },\n\n    // Move and expand me.\n    // @param r {rectangle} representing deltas\n    moveAndExpand: function(r) {\n\n        this.x += r.x || 0;\n        this.y += r.y || 0;\n        this.width += r.width || 0;\n        this.height += r.height || 0;\n        return this;\n    },\n\n    // Normalize the rectangle; i.e., make it so that it has a non-negative width and height.\n    // If width < 0 the function swaps the left and right corners,\n    // and it swaps the top and bottom corners if height < 0\n    // like in http://qt-project.org/doc/qt-4.8/qrectf.html#normalized\n    normalize: function() {\n\n        var newx = this.x;\n        var newy = this.y;\n        var newwidth = this.width;\n        var newheight = this.height;\n        if (this.width < 0) {\n            newx = this.x + this.width;\n            newwidth = -this.width;\n        }\n        if (this.height < 0) {\n            newy = this.y + this.height;\n            newheight = -this.height;\n        }\n        this.x = newx;\n        this.y = newy;\n        this.width = newwidth;\n        this.height = newheight;\n        return this;\n    },\n\n    // Offset me by the specified amount.\n    offset: function(dx, dy) {\n\n        // pretend that this is a point and call offset()\n        // rewrites x and y according to dx and dy\n        return Point.prototype.offset.call(this, dx, dy);\n    },\n\n    origin: function() {\n\n        return new Point(this.x, this.y);\n    },\n\n    // @return {point} a point on my boundary nearest to the given point.\n    // @see Squeak Smalltalk, Rectangle>>pointNearestTo:\n    pointNearestToPoint: function(point) {\n\n        point = new Point(point);\n        if (this.containsPoint(point)) {\n            var side = this.sideNearestToPoint(point);\n            switch (side) {\n                case 'right':\n                    return new Point(this.x + this.width, point.y);\n                case 'left':\n                    return new Point(this.x, point.y);\n                case 'bottom':\n                    return new Point(point.x, this.y + this.height);\n                case 'top':\n                    return new Point(point.x, this.y);\n            }\n        }\n        return point.adhereToRect(this);\n    },\n\n    rightLine: function() {\n\n        return new Line(this.topRight(), this.bottomRight());\n    },\n\n    rightMiddle: function() {\n\n        return new Point(this.x + this.width, this.y + this.height / 2);\n    },\n\n    round: function(precision) {\n\n        let f = 1; // case 0\n        if (precision) {\n            switch (precision) {\n                case 1: f = 10; break;\n                case 2: f = 100; break;\n                case 3: f = 1000; break;\n                default: f = pow(10, precision); break;\n            }\n        }\n\n        this.x = round(this.x * f) / f;\n        this.y = round(this.y * f) / f;\n        this.width = round(this.width * f) / f;\n        this.height = round(this.height * f) / f;\n        return this;\n    },\n\n    // Scale rectangle with origin.\n    scale: function(sx, sy, origin) {\n\n        origin = this.origin().scale(sx, sy, origin);\n        this.x = origin.x;\n        this.y = origin.y;\n        this.width *= sx;\n        this.height *= sy;\n        return this;\n    },\n\n    // @return {string} (left|right|top|bottom) side which is nearest to point\n    // @see Squeak Smalltalk, Rectangle>>sideNearestTo:\n    sideNearestToPoint: function(point) {\n\n        point = new Point(point);\n        var distToLeft = point.x - this.x;\n        var distToRight = (this.x + this.width) - point.x;\n        var distToTop = point.y - this.y;\n        var distToBottom = (this.y + this.height) - point.y;\n        var closest = distToLeft;\n        var side = 'left';\n\n        if (distToRight < closest) {\n            closest = distToRight;\n            side = 'right';\n        }\n        if (distToTop < closest) {\n            closest = distToTop;\n            side = 'top';\n        }\n        if (distToBottom < closest) {\n            // closest = distToBottom;\n            side = 'bottom';\n        }\n        return side;\n    },\n\n    snapToGrid: function(gx, gy) {\n\n        var origin = this.origin().snapToGrid(gx, gy);\n        var corner = this.corner().snapToGrid(gx, gy);\n        this.x = origin.x;\n        this.y = origin.y;\n        this.width = corner.x - origin.x;\n        this.height = corner.y - origin.y;\n        return this;\n    },\n\n    toJSON: function() {\n\n        return { x: this.x, y: this.y, width: this.width, height: this.height };\n    },\n\n    topLine: function() {\n\n        return new Line(this.topLeft(), this.topRight());\n    },\n\n    topMiddle: function() {\n\n        return new Point(this.x + this.width / 2, this.y);\n    },\n\n    topRight: function() {\n\n        return new Point(this.x + this.width, this.y);\n    },\n\n    toString: function() {\n\n        return this.origin().toString() + ' ' + this.corner().toString();\n    },\n\n    // @return {rect} representing the union of both rectangles.\n    union: function(rect) {\n\n        return Rect.fromRectUnion(this, rect);\n    },\n\n    update: function(x, y, w, h) {\n\n        if ((Object(x) === x)) {\n            y = x.y;\n            w = x.width;\n            h = x.height;\n            x = x.x;\n        }\n\n        this.x = x || 0;\n        this.y = y || 0;\n        this.width = w || 0;\n        this.height = h || 0;\n        return this;\n    }\n};\n\nRect.prototype.bottomRight = Rect.prototype.corner;\n\nRect.prototype.topLeft = Rect.prototype.origin;\n\nRect.prototype.translate = Rect.prototype.offset;\n\n// For backwards compatibility:\nexport const rect = Rect;\n","export function parsePoints(svgString) {\n\n    // Step 1: Discard surrounding spaces\n    const trimmedString = svgString.trim();\n    if (trimmedString === '') return [];\n\n    const points = [];\n\n    // Step 2: Split at commas (+ their surrounding spaces) or at multiple spaces\n    // ReDoS mitigation: Have an anchor at the beginning of each alternation\n    // Note: This doesn't simplify double (or more) commas - causes empty coords\n    // This regex is used by `split()`, so it doesn't need to use /g\n    const coords = trimmedString.split(/\\b\\s*,\\s*|,\\s*|\\s+/);\n\n    const numCoords = coords.length;\n    for (let i = 0; i < numCoords; i += 2) {\n        // Step 3: Convert each coord to number\n        // Note: If the coord cannot be converted to a number, it will be `NaN`\n        // Note: If the coord is empty (\"\", e.g. from \",,\" input), it will be `0`\n        // Note: If we end up with an odd number of coords, the last point's second coord will be `NaN`\n        points.push({ x: +coords[i], y: +coords[i + 1] });\n    }\n    return points;\n}\n\nexport function clonePoints(points) {\n    const numPoints = points.length;\n    if (numPoints === 0) return [];\n    const newPoints = [];\n    for (let i = 0; i < numPoints; i++) {\n        const point = points[i].clone();\n        newPoints.push(point);\n    }\n    return newPoints;\n}\n\n// Returns a convex-hull polyline from this polyline.\n// Implements the Graham scan (https://en.wikipedia.org/wiki/Graham_scan).\n// Output polyline starts at the first element of the original polyline that is on the hull, then continues clockwise.\n// Minimal polyline is found (only vertices of the hull are reported, no collinear points).\nexport function convexHull(points) {\n\n    const { abs } = Math;\n\n    var i;\n    var n;\n\n    var numPoints = points.length;\n    if (numPoints === 0) return []; // if points array is empty\n\n    // step 1: find the starting point - point with the lowest y (if equality, highest x)\n    var startPoint;\n    for (i = 0; i < numPoints; i++) {\n        if (startPoint === undefined) {\n            // if this is the first point we see, set it as start point\n            startPoint = points[i];\n\n        } else if (points[i].y < startPoint.y) {\n            // start point should have lowest y from all points\n            startPoint = points[i];\n\n        } else if ((points[i].y === startPoint.y) && (points[i].x > startPoint.x)) {\n            // if two points have the lowest y, choose the one that has highest x\n            // there are no points to the right of startPoint - no ambiguity about theta 0\n            // if there are several coincident start point candidates, first one is reported\n            startPoint = points[i];\n        }\n    }\n\n    // step 2: sort the list of points\n    // sorting by angle between line from startPoint to point and the x-axis (theta)\n\n    // step 2a: create the point records = [point, originalIndex, angle]\n    var sortedPointRecords = [];\n    for (i = 0; i < numPoints; i++) {\n\n        var angle = startPoint.theta(points[i]);\n        if (angle === 0) {\n            angle = 360; // give highest angle to start point\n            // the start point will end up at end of sorted list\n            // the start point will end up at beginning of hull points list\n        }\n\n        var entry = [points[i], i, angle];\n        sortedPointRecords.push(entry);\n    }\n\n    // step 2b: sort the list in place\n    sortedPointRecords.sort(function(record1, record2) {\n        // returning a negative number here sorts record1 before record2\n        // if first angle is smaller than second, first angle should come before second\n\n        var sortOutput = record1[2] - record2[2];  // negative if first angle smaller\n        if (sortOutput === 0) {\n            // if the two angles are equal, sort by originalIndex\n            sortOutput = record2[1] - record1[1]; // negative if first index larger\n            // coincident points will be sorted in reverse-numerical order\n            // so the coincident points with lower original index will be considered first\n        }\n\n        return sortOutput;\n    });\n\n    // step 2c: duplicate start record from the top of the stack to the bottom of the stack\n    if (sortedPointRecords.length > 2) {\n        var startPointRecord = sortedPointRecords[sortedPointRecords.length - 1];\n        sortedPointRecords.unshift(startPointRecord);\n    }\n\n    // step 3a: go through sorted points in order and find those with right turns\n    // we want to get our results in clockwise order\n    var insidePoints = {}; // dictionary of points with left turns - cannot be on the hull\n    var hullPointRecords = []; // stack of records with right turns - hull point candidates\n\n    var currentPointRecord;\n    var currentPoint;\n    var lastHullPointRecord;\n    var lastHullPoint;\n    var secondLastHullPointRecord;\n    var secondLastHullPoint;\n    while (sortedPointRecords.length !== 0) {\n\n        currentPointRecord = sortedPointRecords.pop();\n        currentPoint = currentPointRecord[0];\n\n        // check if point has already been discarded\n        // keys for insidePoints are stored in the form 'point.x@point.y@@originalIndex'\n        if (insidePoints.hasOwnProperty(currentPointRecord[0] + '@@' + currentPointRecord[1])) {\n            // this point had an incorrect turn at some previous iteration of this loop\n            // this disqualifies it from possibly being on the hull\n            continue;\n        }\n\n        var correctTurnFound = false;\n        while (!correctTurnFound) {\n\n            if (hullPointRecords.length < 2) {\n                // not enough points for comparison, just add current point\n                hullPointRecords.push(currentPointRecord);\n                correctTurnFound = true;\n\n            } else {\n                lastHullPointRecord = hullPointRecords.pop();\n                lastHullPoint = lastHullPointRecord[0];\n                secondLastHullPointRecord = hullPointRecords.pop();\n                secondLastHullPoint = secondLastHullPointRecord[0];\n\n                var crossProduct = secondLastHullPoint.cross(lastHullPoint, currentPoint);\n\n                if (crossProduct < 0) {\n                    // found a right turn\n                    hullPointRecords.push(secondLastHullPointRecord);\n                    hullPointRecords.push(lastHullPointRecord);\n                    hullPointRecords.push(currentPointRecord);\n                    correctTurnFound = true;\n\n                } else if (crossProduct === 0) {\n                    // the three points are collinear\n                    // three options:\n                    // there may be a 180 or 0 degree angle at lastHullPoint\n                    // or two of the three points are coincident\n                    var THRESHOLD = 1e-10; // we have to take rounding errors into account\n                    var angleBetween = lastHullPoint.angleBetween(secondLastHullPoint, currentPoint);\n                    if (abs(angleBetween - 180) < THRESHOLD) { // rounding around 180 to 180\n                        // if the cross product is 0 because the angle is 180 degrees\n                        // discard last hull point (add to insidePoints)\n                        //insidePoints.unshift(lastHullPoint);\n                        insidePoints[lastHullPointRecord[0] + '@@' + lastHullPointRecord[1]] = lastHullPoint;\n                        // reenter second-to-last hull point (will be last at next iter)\n                        hullPointRecords.push(secondLastHullPointRecord);\n                        // do not do anything with current point\n                        // correct turn not found\n\n                    } else if (lastHullPoint.equals(currentPoint) || secondLastHullPoint.equals(lastHullPoint)) {\n                        // if the cross product is 0 because two points are the same\n                        // discard last hull point (add to insidePoints)\n                        //insidePoints.unshift(lastHullPoint);\n                        insidePoints[lastHullPointRecord[0] + '@@' + lastHullPointRecord[1]] = lastHullPoint;\n                        // reenter second-to-last hull point (will be last at next iter)\n                        hullPointRecords.push(secondLastHullPointRecord);\n                        // do not do anything with current point\n                        // correct turn not found\n\n                    } else if (abs(((angleBetween + 1) % 360) - 1) < THRESHOLD) { // rounding around 0 and 360 to 0\n                        // if the cross product is 0 because the angle is 0 degrees\n                        // remove last hull point from hull BUT do not discard it\n                        // reenter second-to-last hull point (will be last at next iter)\n                        hullPointRecords.push(secondLastHullPointRecord);\n                        // put last hull point back into the sorted point records list\n                        sortedPointRecords.push(lastHullPointRecord);\n                        // we are switching the order of the 0deg and 180deg points\n                        // correct turn not found\n                    }\n\n                } else {\n                    // found a left turn\n                    // discard last hull point (add to insidePoints)\n                    //insidePoints.unshift(lastHullPoint);\n                    insidePoints[lastHullPointRecord[0] + '@@' + lastHullPointRecord[1]] = lastHullPoint;\n                    // reenter second-to-last hull point (will be last at next iter of loop)\n                    hullPointRecords.push(secondLastHullPointRecord);\n                    // do not do anything with current point\n                    // correct turn not found\n                }\n            }\n        }\n    }\n    // at this point, hullPointRecords contains the output points in clockwise order\n    // the points start with lowest-y,highest-x startPoint, and end at the same point\n\n    // step 3b: remove duplicated startPointRecord from the end of the array\n    if (hullPointRecords.length > 2) {\n        hullPointRecords.pop();\n    }\n\n    // step 4: find the lowest originalIndex record and put it at the beginning of hull\n    var lowestHullIndex; // the lowest originalIndex on the hull\n    var indexOfLowestHullIndexRecord = -1; // the index of the record with lowestHullIndex\n    n = hullPointRecords.length;\n    for (i = 0; i < n; i++) {\n\n        var currentHullIndex = hullPointRecords[i][1];\n\n        if (lowestHullIndex === undefined || currentHullIndex < lowestHullIndex) {\n            lowestHullIndex = currentHullIndex;\n            indexOfLowestHullIndexRecord = i;\n        }\n    }\n\n    var hullPointRecordsReordered = [];\n    if (indexOfLowestHullIndexRecord > 0) {\n        var newFirstChunk = hullPointRecords.slice(indexOfLowestHullIndexRecord);\n        var newSecondChunk = hullPointRecords.slice(0, indexOfLowestHullIndexRecord);\n        hullPointRecordsReordered = newFirstChunk.concat(newSecondChunk);\n\n    } else {\n        hullPointRecordsReordered = hullPointRecords;\n    }\n\n    var hullPoints = [];\n    n = hullPointRecordsReordered.length;\n    for (i = 0; i < n; i++) {\n        hullPoints.push(hullPointRecordsReordered[i][0]);\n    }\n\n    return hullPoints;\n}\n","import { Rect } from './rect.mjs';\nimport { Point } from './point.mjs';\nimport { Line } from './line.mjs';\nimport { types } from './types.mjs';\nimport { clonePoints, parsePoints, convexHull } from './points.mjs';\n\n\nexport const Polyline = function(points) {\n\n    if (!(this instanceof Polyline)) {\n        return new Polyline(points);\n    }\n\n    if (typeof points === 'string') {\n        return new Polyline.parse(points);\n    }\n\n    this.points = (Array.isArray(points) ? points.map(Point) : []);\n};\n\nPolyline.parse = function(svgString) {\n    return new Polyline(parsePoints(svgString));\n};\n\nPolyline.fromRect = function(rect) {\n    return new Polyline([\n        rect.topLeft(),\n        rect.topRight(),\n        rect.bottomRight(),\n        rect.bottomLeft(),\n        rect.topLeft(),\n    ]);\n};\n\nPolyline.prototype = {\n\n    type: types.Polyline,\n\n    bbox: function() {\n\n        var x1 = Infinity;\n        var x2 = -Infinity;\n        var y1 = Infinity;\n        var y2 = -Infinity;\n\n        var points = this.points;\n        var numPoints = points.length;\n        if (numPoints === 0) return null; // if points array is empty\n\n        for (var i = 0; i < numPoints; i++) {\n\n            var point = points[i];\n            var x = point.x;\n            var y = point.y;\n\n            if (x < x1) x1 = x;\n            if (x > x2) x2 = x;\n            if (y < y1) y1 = y;\n            if (y > y2) y2 = y;\n        }\n\n        return new Rect(x1, y1, x2 - x1, y2 - y1);\n    },\n\n    clone: function() {\n        return new Polyline(clonePoints(this.points));\n    },\n\n    closestPoint: function(p) {\n\n        var cpLength = this.closestPointLength(p);\n\n        return this.pointAtLength(cpLength);\n    },\n\n    closestPointLength: function(p) {\n\n        var points = this.lengthPoints();\n        var numPoints = points.length;\n        if (numPoints === 0) return 0; // if points array is empty\n        if (numPoints === 1) return 0; // if there is only one point\n\n        var cpLength;\n        var minSqrDistance = Infinity;\n        var length = 0;\n        var n = numPoints - 1;\n        for (var i = 0; i < n; i++) {\n\n            var line = new Line(points[i], points[i + 1]);\n            var lineLength = line.length();\n\n            var cpNormalizedLength = line.closestPointNormalizedLength(p);\n            var cp = line.pointAt(cpNormalizedLength);\n\n            var sqrDistance = cp.squaredDistance(p);\n            if (sqrDistance < minSqrDistance) {\n                minSqrDistance = sqrDistance;\n                cpLength = length + (cpNormalizedLength * lineLength);\n            }\n\n            length += lineLength;\n        }\n\n        return cpLength;\n    },\n\n    closestPointNormalizedLength: function(p) {\n\n        var cpLength = this.closestPointLength(p);\n        if (cpLength === 0) return 0; // shortcut\n\n        var length = this.length();\n        if (length === 0) return 0; // prevents division by zero\n\n        return cpLength / length;\n    },\n\n    closestPointTangent: function(p) {\n\n        var cpLength = this.closestPointLength(p);\n\n        return this.tangentAtLength(cpLength);\n    },\n\n    // Returns `true` if the area surrounded by the polyline contains the point `p`.\n    // Implements the even-odd SVG algorithm (self-intersections are \"outside\").\n    // (Uses horizontal rays to the right of `p` to look for intersections.)\n    // Closes open polylines (always imagines a final closing segment).\n    containsPoint: function(p) {\n\n        var points = this.points;\n        var numPoints = points.length;\n        if (numPoints === 0) return false; // shortcut (this polyline has no points)\n\n        var x = p.x;\n        var y = p.y;\n\n        // initialize a final closing segment by creating one from last-first points on polyline\n        var startIndex = numPoints - 1; // start of current polyline segment\n        var endIndex = 0; // end of current polyline segment\n        var numIntersections = 0;\n        var segment = new Line();\n        var ray = new Line();\n        var rayEnd = new Point();\n        for (; endIndex < numPoints; endIndex++) {\n            var start = points[startIndex];\n            var end = points[endIndex];\n            if (p.equals(start)) return true; // shortcut (`p` is a point on polyline)\n            // current polyline segment\n            segment.start = start;\n            segment.end = end;\n            if (segment.containsPoint(p)) return true; // shortcut (`p` lies on a polyline segment)\n\n            // do we have an intersection?\n            if (((y <= start.y) && (y > end.y)) || ((y > start.y) && (y <= end.y))) {\n                // this conditional branch IS NOT entered when `segment` is collinear/coincident with `ray`\n                // (when `y === start.y === end.y`)\n                // this conditional branch IS entered when `segment` touches `ray` at only one point\n                // (e.g. when `y === start.y !== end.y`)\n                // since this branch is entered again for the following segment, the two touches cancel out\n\n                var xDifference = (((start.x - x) > (end.x - x)) ? (start.x - x) : (end.x - x));\n                if (xDifference >= 0) {\n                    // segment lies at least partially to the right of `p`\n                    rayEnd.x = x + xDifference;\n                    rayEnd.y = y; // right\n                    ray.start = p;\n                    ray.end = rayEnd;\n                    if (segment.intersect(ray)) {\n                        // an intersection was detected to the right of `p`\n                        numIntersections++;\n                    }\n                } // else: `segment` lies completely to the left of `p` (i.e. no intersection to the right)\n            }\n\n            // move to check the next polyline segment\n            startIndex = endIndex;\n        }\n\n        // returns `true` for odd numbers of intersections (even-odd algorithm)\n        return ((numIntersections % 2) === 1);\n    },\n\n    close: function() {\n        const { start, end, points } = this;\n        if (start && end && !start.equals(end)) {\n            points.push(start.clone());\n        }\n        return this;\n    },\n\n    lengthPoints: function() {\n        return this.points;\n    },\n\n    convexHull: function() {\n        return new Polyline(convexHull(this.points));\n    },\n\n    // Checks whether two polylines are exactly the same.\n    // If `p` is undefined or null, returns false.\n    equals: function(p) {\n\n        if (!p) return false;\n\n        var points = this.points;\n        var otherPoints = p.points;\n\n        var numPoints = points.length;\n        if (otherPoints.length !== numPoints) return false; // if the two polylines have different number of points, they cannot be equal\n\n        for (var i = 0; i < numPoints; i++) {\n\n            var point = points[i];\n            var otherPoint = p.points[i];\n\n            // as soon as an inequality is found in points, return false\n            if (!point.equals(otherPoint)) return false;\n        }\n\n        // if no inequality found in points, return true\n        return true;\n    },\n\n    intersectionWithLine: function(l) {\n        var line = new Line(l);\n        var intersections = [];\n        var points = this.lengthPoints();\n        var l2 = new Line();\n        for (var i = 0, n = points.length - 1; i < n; i++) {\n            l2.start = points[i];\n            l2.end = points[i + 1];\n            var int = line.intersectionWithLine(l2);\n            if (int) intersections.push(int[0]);\n        }\n        return (intersections.length > 0) ? intersections : null;\n    },\n\n    isDifferentiable: function() {\n\n        var points = this.points;\n        var numPoints = points.length;\n        if (numPoints === 0) return false;\n\n        var line = new Line();\n        var n = numPoints - 1;\n        for (var i = 0; i < n; i++) {\n            line.start = points[i];\n            line.end = points[i + 1];\n            // as soon as a differentiable line is found between two points, return true\n            if (line.isDifferentiable()) return true;\n        }\n\n        // if no differentiable line is found between pairs of points, return false\n        return false;\n    },\n\n    length: function() {\n\n        var points = this.lengthPoints();\n        var numPoints = points.length;\n        if (numPoints === 0) return 0; // if points array is empty\n\n        var length = 0;\n        var n = numPoints - 1;\n        for (var i = 0; i < n; i++) {\n            length += points[i].distance(points[i + 1]);\n        }\n\n        return length;\n    },\n\n    pointAt: function(ratio) {\n\n        var points = this.lengthPoints();\n        var numPoints = points.length;\n        if (numPoints === 0) return null; // if points array is empty\n        if (numPoints === 1) return points[0].clone(); // if there is only one point\n\n        if (ratio <= 0) return points[0].clone();\n        if (ratio >= 1) return points[numPoints - 1].clone();\n\n        var polylineLength = this.length();\n        var length = polylineLength * ratio;\n\n        return this.pointAtLength(length);\n    },\n\n    pointAtLength: function(length) {\n\n        var points = this.lengthPoints();\n        var numPoints = points.length;\n        if (numPoints === 0) return null; // if points array is empty\n        if (numPoints === 1) return points[0].clone(); // if there is only one point\n\n        var fromStart = true;\n        if (length < 0) {\n            fromStart = false; // negative lengths mean start calculation from end point\n            length = -length; // absolute value\n        }\n\n        var l = 0;\n        var n = numPoints - 1;\n        for (var i = 0; i < n; i++) {\n            var index = (fromStart ? i : (n - 1 - i));\n\n            var a = points[index];\n            var b = points[index + 1];\n            var line = new Line(a, b);\n            var d = a.distance(b);\n\n            if (length <= (l + d)) {\n                return line.pointAtLength((fromStart ? 1 : -1) * (length - l));\n            }\n\n            l += d;\n        }\n\n        // if length requested is higher than the length of the polyline, return last endpoint\n        var lastPoint = (fromStart ? points[numPoints - 1] : points[0]);\n        return lastPoint.clone();\n    },\n\n    round: function(precision) {\n\n        var points = this.points;\n        var numPoints = points.length;\n\n        for (var i = 0; i < numPoints; i++) {\n            points[i].round(precision);\n        }\n\n        return this;\n    },\n\n    scale: function(sx, sy, origin) {\n\n        var points = this.points;\n        var numPoints = points.length;\n\n        for (var i = 0; i < numPoints; i++) {\n            points[i].scale(sx, sy, origin);\n        }\n\n        return this;\n    },\n\n    simplify: function(opt = {}) {\n\n        const points = this.points;\n        if (points.length < 3) return this; // we need at least 3 points\n\n        // TODO: we may also accept startIndex and endIndex to specify where to start and end simplification\n\n        // Due to the nature of the algorithm, we do not use 0 as the default value for `threshold`\n        // because of the rounding errors that can occur when comparing distances.\n        const threshold = opt.threshold || 1e-10; // = max distance of middle point from chord to be simplified\n\n        // start at the beginning of the polyline and go forward\n        let currentIndex = 0;\n        // we need at least one intermediate point (3 points) in every iteration\n        // as soon as that stops being true, we know we reached the end of the polyline\n        while (points[currentIndex + 2]) {\n            const firstIndex = currentIndex;\n            const middleIndex = (currentIndex + 1);\n            const lastIndex = (currentIndex + 2);\n\n            const firstPoint = points[firstIndex];\n            const middlePoint = points[middleIndex];\n            const lastPoint = points[lastIndex];\n\n            const chord = new Line(firstPoint, lastPoint); // = connection between first and last point\n            const closestPoint = chord.closestPoint(middlePoint); // = closest point on chord from middle point\n            const closestPointDistance = closestPoint.distance(middlePoint);\n            if (closestPointDistance <= threshold) {\n                // middle point is close enough to the chord = simplify\n                // 1) remove middle point:\n                points.splice(middleIndex, 1);\n                // 2) in next iteration, investigate the newly-created triplet of points\n                //    - do not change `currentIndex`\n                //    = (first point stays, point after removed point becomes middle point)\n            } else {\n                // middle point is far from the chord\n                // 1) preserve middle point\n                // 2) in next iteration, move `currentIndex` by one step:\n                currentIndex += 1;\n                //    = (point after first point becomes first point)\n            }\n        }\n\n        // `points` array was modified in-place\n        return this;\n    },\n\n    tangentAt: function(ratio) {\n\n        var points = this.lengthPoints();\n        var numPoints = points.length;\n        if (numPoints === 0) return null; // if points array is empty\n        if (numPoints === 1) return null; // if there is only one point\n\n        if (ratio < 0) ratio = 0;\n        if (ratio > 1) ratio = 1;\n\n        var polylineLength = this.length();\n        var length = polylineLength * ratio;\n\n        return this.tangentAtLength(length);\n    },\n\n    tangentAtLength: function(length) {\n\n        var points = this.lengthPoints();\n        var numPoints = points.length;\n        if (numPoints === 0) return null; // if points array is empty\n        if (numPoints === 1) return null; // if there is only one point\n\n        var fromStart = true;\n        if (length < 0) {\n            fromStart = false; // negative lengths mean start calculation from end point\n            length = -length; // absolute value\n        }\n\n        var lastValidLine; // differentiable (with a tangent)\n        var l = 0; // length so far\n        var n = numPoints - 1;\n        for (var i = 0; i < n; i++) {\n            var index = (fromStart ? i : (n - 1 - i));\n\n            var a = points[index];\n            var b = points[index + 1];\n            var line = new Line(a, b);\n            var d = a.distance(b);\n\n            if (line.isDifferentiable()) { // has a tangent line (line length is not 0)\n                if (length <= (l + d)) {\n                    return line.tangentAtLength((fromStart ? 1 : -1) * (length - l));\n                }\n\n                lastValidLine = line;\n            }\n\n            l += d;\n        }\n\n        // if length requested is higher than the length of the polyline, return last valid endpoint\n        if (lastValidLine) {\n            var ratio = (fromStart ? 1 : 0);\n            return lastValidLine.tangentAt(ratio);\n        }\n\n        // if no valid line, return null\n        return null;\n    },\n\n    toString: function() {\n\n        return this.points + '';\n    },\n\n    translate: function(tx, ty) {\n\n        var points = this.points;\n        var numPoints = points.length;\n\n        for (var i = 0; i < numPoints; i++) {\n            points[i].translate(tx, ty);\n        }\n\n        return this;\n    },\n\n    // Return svgString that can be used to recreate this line.\n    serialize: function() {\n\n        var points = this.points;\n        var numPoints = points.length;\n        if (numPoints === 0) return ''; // if points array is empty\n\n        var output = '';\n        for (var i = 0; i < numPoints; i++) {\n\n            var point = points[i];\n            output += point.x + ',' + point.y + ' ';\n        }\n\n        return output.trim();\n    }\n};\n\nObject.defineProperty(Polyline.prototype, 'start', {\n    // Getter for the first point of the polyline.\n\n    configurable: true,\n\n    enumerable: true,\n\n    get: function() {\n\n        var points = this.points;\n        var numPoints = points.length;\n        if (numPoints === 0) return null; // if points array is empty\n\n        return this.points[0];\n    },\n});\n\nObject.defineProperty(Polyline.prototype, 'end', {\n    // Getter for the last point of the polyline.\n\n    configurable: true,\n\n    enumerable: true,\n\n    get: function() {\n\n        var points = this.points;\n        var numPoints = points.length;\n        if (numPoints === 0) return null; // if points array is empty\n\n        return this.points[numPoints - 1];\n    },\n});\n","import { Point } from './point.mjs';\nimport { Rect } from './rect.mjs';\nimport { Line } from './line.mjs';\nimport { Polyline } from './polyline.mjs';\nimport { types } from './types.mjs';\n\nconst {\n    abs,\n    sqrt,\n    min,\n    max,\n    pow\n} = Math;\n\nexport const Curve = function(p1, p2, p3, p4) {\n\n    if (!(this instanceof Curve)) {\n        return new Curve(p1, p2, p3, p4);\n    }\n\n    if (p1 instanceof Curve) {\n        return new Curve(p1.start, p1.controlPoint1, p1.controlPoint2, p1.end);\n    }\n\n    this.start = new Point(p1);\n    this.controlPoint1 = new Point(p2);\n    this.controlPoint2 = new Point(p3);\n    this.end = new Point(p4);\n};\n\n// Curve passing through points.\n// Ported from C# implementation by Oleg V. Polikarpotchkin and Peter Lee (http://www.codeproject.com/KB/graphics/BezierSpline.aspx).\n// @param {array} points Array of points through which the smooth line will go.\n// @return {array} curves.\nCurve.throughPoints = (function() {\n\n    // Get open-ended Bezier Spline Control Points.\n    // @param knots Input Knot Bezier spline points (At least two points!).\n    // @param firstControlPoints Output First Control points. Array of knots.length - 1 length.\n    // @param secondControlPoints Output Second Control points. Array of knots.length - 1 length.\n    function getCurveControlPoints(knots) {\n\n        var firstControlPoints = [];\n        var secondControlPoints = [];\n        var n = knots.length - 1;\n        var i;\n\n        // Special case: Bezier curve should be a straight line.\n        if (n == 1) {\n            // 3P1 = 2P0 + P3\n            firstControlPoints[0] = new Point(\n                (2 * knots[0].x + knots[1].x) / 3,\n                (2 * knots[0].y + knots[1].y) / 3\n            );\n\n            // P2 = 2P1 – P0\n            secondControlPoints[0] = new Point(\n                2 * firstControlPoints[0].x - knots[0].x,\n                2 * firstControlPoints[0].y - knots[0].y\n            );\n\n            return [firstControlPoints, secondControlPoints];\n        }\n\n        // Calculate first Bezier control points.\n        // Right hand side vector.\n        var rhs = [];\n\n        // Set right hand side X values.\n        for (i = 1; i < n - 1; i++) {\n            rhs[i] = 4 * knots[i].x + 2 * knots[i + 1].x;\n        }\n\n        rhs[0] = knots[0].x + 2 * knots[1].x;\n        rhs[n - 1] = (8 * knots[n - 1].x + knots[n].x) / 2.0;\n\n        // Get first control points X-values.\n        var x = getFirstControlPoints(rhs);\n\n        // Set right hand side Y values.\n        for (i = 1; i < n - 1; ++i) {\n            rhs[i] = 4 * knots[i].y + 2 * knots[i + 1].y;\n        }\n\n        rhs[0] = knots[0].y + 2 * knots[1].y;\n        rhs[n - 1] = (8 * knots[n - 1].y + knots[n].y) / 2.0;\n\n        // Get first control points Y-values.\n        var y = getFirstControlPoints(rhs);\n\n        // Fill output arrays.\n        for (i = 0; i < n; i++) {\n            // First control point.\n            firstControlPoints.push(new Point(x[i], y[i]));\n\n            // Second control point.\n            if (i < n - 1) {\n                secondControlPoints.push(new Point(\n                    2 * knots [i + 1].x - x[i + 1],\n                    2 * knots[i + 1].y - y[i + 1]\n                ));\n\n            } else {\n                secondControlPoints.push(new Point(\n                    (knots[n].x + x[n - 1]) / 2,\n                    (knots[n].y + y[n - 1]) / 2\n                ));\n            }\n        }\n\n        return [firstControlPoints, secondControlPoints];\n    }\n\n    // Solves a tridiagonal system for one of coordinates (x or y) of first Bezier control points.\n    // @param rhs Right hand side vector.\n    // @return Solution vector.\n    function getFirstControlPoints(rhs) {\n\n        var n = rhs.length;\n        // `x` is a solution vector.\n        var x = [];\n        var tmp = [];\n        var b = 2.0;\n\n        x[0] = rhs[0] / b;\n\n        // Decomposition and forward substitution.\n        for (var i = 1; i < n; i++) {\n            tmp[i] = 1 / b;\n            b = (i < n - 1 ? 4.0 : 3.5) - tmp[i];\n            x[i] = (rhs[i] - x[i - 1]) / b;\n        }\n\n        for (i = 1; i < n; i++) {\n            // Backsubstitution.\n            x[n - i - 1] -= tmp[n - i] * x[n - i];\n        }\n\n        return x;\n    }\n\n    return function(points) {\n\n        if (!points || (Array.isArray(points) && points.length < 2)) {\n            throw new Error('At least 2 points are required');\n        }\n\n        var controlPoints = getCurveControlPoints(points);\n\n        var curves = [];\n        var n = controlPoints[0].length;\n        for (var i = 0; i < n; i++) {\n\n            var controlPoint1 = new Point(controlPoints[0][i].x, controlPoints[0][i].y);\n            var controlPoint2 = new Point(controlPoints[1][i].x, controlPoints[1][i].y);\n\n            curves.push(new Curve(points[i], controlPoint1, controlPoint2, points[i + 1]));\n        }\n\n        return curves;\n    };\n})();\n\nCurve.prototype = {\n\n    type: types.Curve,\n\n    // Returns a bbox that tightly envelops the curve.\n    bbox: function() {\n\n        var start = this.start;\n        var controlPoint1 = this.controlPoint1;\n        var controlPoint2 = this.controlPoint2;\n        var end = this.end;\n\n        var x0 = start.x;\n        var y0 = start.y;\n        var x1 = controlPoint1.x;\n        var y1 = controlPoint1.y;\n        var x2 = controlPoint2.x;\n        var y2 = controlPoint2.y;\n        var x3 = end.x;\n        var y3 = end.y;\n\n        var points = new Array(); // local extremes\n        var tvalues = new Array(); // t values of local extremes\n        var bounds = [new Array(), new Array()];\n\n        var a, b, c, t;\n        var t1, t2;\n        var b2ac, sqrtb2ac;\n\n        for (var i = 0; i < 2; ++i) {\n\n            if (i === 0) {\n                b = 6 * x0 - 12 * x1 + 6 * x2;\n                a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;\n                c = 3 * x1 - 3 * x0;\n\n            } else {\n                b = 6 * y0 - 12 * y1 + 6 * y2;\n                a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;\n                c = 3 * y1 - 3 * y0;\n            }\n\n            if (abs(a) < 1e-12) { // Numerical robustness\n                if (abs(b) < 1e-12) { // Numerical robustness\n                    continue;\n                }\n\n                t = -c / b;\n                if ((0 < t) && (t < 1)) tvalues.push(t);\n\n                continue;\n            }\n\n            b2ac = b * b - 4 * c * a;\n            sqrtb2ac = sqrt(b2ac);\n\n            if (b2ac < 0) continue;\n\n            t1 = (-b + sqrtb2ac) / (2 * a);\n            if ((0 < t1) && (t1 < 1)) tvalues.push(t1);\n\n            t2 = (-b - sqrtb2ac) / (2 * a);\n            if ((0 < t2) && (t2 < 1)) tvalues.push(t2);\n        }\n\n        var j = tvalues.length;\n        var jlen = j;\n        var mt;\n        var x, y;\n\n        while (j--) {\n            t = tvalues[j];\n            mt = 1 - t;\n\n            x = (mt * mt * mt * x0) + (3 * mt * mt * t * x1) + (3 * mt * t * t * x2) + (t * t * t * x3);\n            bounds[0][j] = x;\n\n            y = (mt * mt * mt * y0) + (3 * mt * mt * t * y1) + (3 * mt * t * t * y2) + (t * t * t * y3);\n            bounds[1][j] = y;\n\n            points[j] = { X: x, Y: y };\n        }\n\n        tvalues[jlen] = 0;\n        tvalues[jlen + 1] = 1;\n\n        points[jlen] = { X: x0, Y: y0 };\n        points[jlen + 1] = { X: x3, Y: y3 };\n\n        bounds[0][jlen] = x0;\n        bounds[1][jlen] = y0;\n\n        bounds[0][jlen + 1] = x3;\n        bounds[1][jlen + 1] = y3;\n\n        tvalues.length = jlen + 2;\n        bounds[0].length = jlen + 2;\n        bounds[1].length = jlen + 2;\n        points.length = jlen + 2;\n\n        var left = min.apply(null, bounds[0]);\n        var top = min.apply(null, bounds[1]);\n        var right = max.apply(null, bounds[0]);\n        var bottom = max.apply(null, bounds[1]);\n\n        return new Rect(left, top, (right - left), (bottom - top));\n    },\n\n    clone: function() {\n\n        return new Curve(this.start, this.controlPoint1, this.controlPoint2, this.end);\n    },\n\n    // Returns the point on the curve closest to point `p`\n    closestPoint: function(p, opt) {\n\n        return this.pointAtT(this.closestPointT(p, opt));\n    },\n\n    closestPointLength: function(p, opt) {\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var subdivisions = (opt.subdivisions === undefined) ? this.getSubdivisions({ precision: precision }) : opt.subdivisions;\n        var localOpt = { precision: precision, subdivisions: subdivisions };\n\n        return this.lengthAtT(this.closestPointT(p, localOpt), localOpt);\n    },\n\n    closestPointNormalizedLength: function(p, opt) {\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var subdivisions = (opt.subdivisions === undefined) ? this.getSubdivisions({ precision: precision }) : opt.subdivisions;\n        var localOpt = { precision: precision, subdivisions: subdivisions };\n\n        var cpLength = this.closestPointLength(p, localOpt);\n        if (!cpLength) return 0;\n\n        var length = this.length(localOpt);\n        if (length === 0) return 0;\n\n        return cpLength / length;\n    },\n\n    // Returns `t` of the point on the curve closest to point `p`\n    closestPointT: function(p, opt) {\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var subdivisions = (opt.subdivisions === undefined) ? this.getSubdivisions({ precision: precision }) : opt.subdivisions;\n        // does not use localOpt\n\n        // identify the subdivision that contains the point:\n        var investigatedSubdivision;\n        var investigatedSubdivisionStartT; // assume that subdivisions are evenly spaced\n        var investigatedSubdivisionEndT;\n        var distFromStart; // distance of point from start of baseline\n        var distFromEnd; // distance of point from end of baseline\n        var chordLength; // distance between start and end of the subdivision\n        var minSumDist; // lowest observed sum of the two distances\n        var n = subdivisions.length;\n        var subdivisionSize = (n ? (1 / n) : 0);\n        for (var i = 0; i < n; i++) {\n\n            var currentSubdivision = subdivisions[i];\n\n            var startDist = currentSubdivision.start.distance(p);\n            var endDist = currentSubdivision.end.distance(p);\n            var sumDist = startDist + endDist;\n\n            // check that the point is closest to current subdivision and not any other\n            if (!minSumDist || (sumDist < minSumDist)) {\n                investigatedSubdivision = currentSubdivision;\n\n                investigatedSubdivisionStartT = i * subdivisionSize;\n                investigatedSubdivisionEndT = (i + 1) * subdivisionSize;\n\n                distFromStart = startDist;\n                distFromEnd = endDist;\n\n                chordLength = currentSubdivision.start.distance(currentSubdivision.end);\n\n                minSumDist = sumDist;\n            }\n        }\n\n        var precisionRatio = pow(10, -precision);\n\n        // recursively divide investigated subdivision:\n        // until distance between baselinePoint and closest path endpoint is within 10^(-precision)\n        // then return the closest endpoint of that final subdivision\n        while (true) {\n\n            // check if we have reached at least one required observed precision\n            // - calculated as: the difference in distances from point to start and end divided by the distance\n            // - note that this function is not monotonic = it doesn't converge stably but has \"teeth\"\n            // - the function decreases while one of the endpoints is fixed but \"jumps\" whenever we switch\n            // - this criterion works well for points lying far away from the curve\n            var startPrecisionRatio = (distFromStart ? (abs(distFromStart - distFromEnd) / distFromStart) : 0);\n            var endPrecisionRatio = (distFromEnd ? (abs(distFromStart - distFromEnd) / distFromEnd) : 0);\n            var hasRequiredPrecision = ((startPrecisionRatio < precisionRatio) || (endPrecisionRatio < precisionRatio));\n\n            // check if we have reached at least one required minimal distance\n            // - calculated as: the subdivision chord length multiplied by precisionRatio\n            // - calculation is relative so it will work for arbitrarily large/small curves and their subdivisions\n            // - this is a backup criterion that works well for points lying \"almost at\" the curve\n            var hasMinimalStartDistance = (distFromStart ? (distFromStart < (chordLength * precisionRatio)) : true);\n            var hasMinimalEndDistance = (distFromEnd ? (distFromEnd < (chordLength * precisionRatio)) : true);\n            var hasMinimalDistance = (hasMinimalStartDistance || hasMinimalEndDistance);\n\n            // do we stop now?\n            if (hasRequiredPrecision || hasMinimalDistance) {\n                return ((distFromStart <= distFromEnd) ? investigatedSubdivisionStartT : investigatedSubdivisionEndT);\n            }\n\n            // otherwise, set up for next iteration\n            var divided = investigatedSubdivision.divide(0.5);\n            subdivisionSize /= 2;\n\n            var startDist1 = divided[0].start.distance(p);\n            var endDist1 = divided[0].end.distance(p);\n            var sumDist1 = startDist1 + endDist1;\n\n            var startDist2 = divided[1].start.distance(p);\n            var endDist2 = divided[1].end.distance(p);\n            var sumDist2 = startDist2 + endDist2;\n\n            if (sumDist1 <= sumDist2) {\n                investigatedSubdivision = divided[0];\n\n                investigatedSubdivisionEndT -= subdivisionSize; // subdivisionSize was already halved\n\n                distFromStart = startDist1;\n                distFromEnd = endDist1;\n\n            } else {\n                investigatedSubdivision = divided[1];\n\n                investigatedSubdivisionStartT += subdivisionSize; // subdivisionSize was already halved\n\n                distFromStart = startDist2;\n                distFromEnd = endDist2;\n            }\n        }\n    },\n\n    closestPointTangent: function(p, opt) {\n\n        return this.tangentAtT(this.closestPointT(p, opt));\n    },\n\n    // Returns `true` if the area surrounded by the curve contains the point `p`.\n    // Implements the even-odd algorithm (self-intersections are \"outside\").\n    // Closes open curves (always imagines a closing segment).\n    // Precision may be adjusted by passing an `opt` object.\n    containsPoint: function(p, opt) {\n\n        var polyline = this.toPolyline(opt);\n        return polyline.containsPoint(p);\n    },\n\n    // Divides the curve into two at requested `ratio` between 0 and 1 with precision better than `opt.precision`; optionally using `opt.subdivisions` provided.\n    // For a function that uses `t`, use Curve.divideAtT().\n    divideAt: function(ratio, opt) {\n\n        if (ratio <= 0) return this.divideAtT(0);\n        if (ratio >= 1) return this.divideAtT(1);\n\n        var t = this.tAt(ratio, opt);\n\n        return this.divideAtT(t);\n    },\n\n    // Divides the curve into two at requested `length` with precision better than requested `opt.precision`; optionally using `opt.subdivisions` provided.\n    divideAtLength: function(length, opt) {\n\n        var t = this.tAtLength(length, opt);\n\n        return this.divideAtT(t);\n    },\n\n    // Divides the curve into two at point defined by `t` between 0 and 1.\n    // Using de Casteljau's algorithm (http://math.stackexchange.com/a/317867).\n    // Additional resource: https://pomax.github.io/bezierinfo/#decasteljau\n    divideAtT: function(t) {\n\n        var start = this.start;\n        var controlPoint1 = this.controlPoint1;\n        var controlPoint2 = this.controlPoint2;\n        var end = this.end;\n\n        // shortcuts for `t` values that are out of range\n        if (t <= 0) {\n            return [\n                new Curve(start, start, start, start),\n                new Curve(start, controlPoint1, controlPoint2, end)\n            ];\n        }\n\n        if (t >= 1) {\n            return [\n                new Curve(start, controlPoint1, controlPoint2, end),\n                new Curve(end, end, end, end)\n            ];\n        }\n\n        var dividerPoints = this.getSkeletonPoints(t);\n\n        var startControl1 = dividerPoints.startControlPoint1;\n        var startControl2 = dividerPoints.startControlPoint2;\n        var divider = dividerPoints.divider;\n        var dividerControl1 = dividerPoints.dividerControlPoint1;\n        var dividerControl2 = dividerPoints.dividerControlPoint2;\n\n        // return array with two new curves\n        return [\n            new Curve(start, startControl1, startControl2, divider),\n            new Curve(divider, dividerControl1, dividerControl2, end)\n        ];\n    },\n\n    // Returns the distance between the curve's start and end points.\n    endpointDistance: function() {\n\n        return this.start.distance(this.end);\n    },\n\n    // Checks whether two curves are exactly the same.\n    equals: function(c) {\n\n        return !!c &&\n            this.start.x === c.start.x &&\n            this.start.y === c.start.y &&\n            this.controlPoint1.x === c.controlPoint1.x &&\n            this.controlPoint1.y === c.controlPoint1.y &&\n            this.controlPoint2.x === c.controlPoint2.x &&\n            this.controlPoint2.y === c.controlPoint2.y &&\n            this.end.x === c.end.x &&\n            this.end.y === c.end.y;\n    },\n\n    // Returns five helper points necessary for curve division.\n    getSkeletonPoints: function(t) {\n\n        var start = this.start;\n        var control1 = this.controlPoint1;\n        var control2 = this.controlPoint2;\n        var end = this.end;\n\n        // shortcuts for `t` values that are out of range\n        if (t <= 0) {\n            return {\n                startControlPoint1: start.clone(),\n                startControlPoint2: start.clone(),\n                divider: start.clone(),\n                dividerControlPoint1: control1.clone(),\n                dividerControlPoint2: control2.clone()\n            };\n        }\n\n        if (t >= 1) {\n            return {\n                startControlPoint1: control1.clone(),\n                startControlPoint2: control2.clone(),\n                divider: end.clone(),\n                dividerControlPoint1: end.clone(),\n                dividerControlPoint2: end.clone()\n            };\n        }\n\n        var midpoint1 = (new Line(start, control1)).pointAt(t);\n        var midpoint2 = (new Line(control1, control2)).pointAt(t);\n        var midpoint3 = (new Line(control2, end)).pointAt(t);\n\n        var subControl1 = (new Line(midpoint1, midpoint2)).pointAt(t);\n        var subControl2 = (new Line(midpoint2, midpoint3)).pointAt(t);\n\n        var divider = (new Line(subControl1, subControl2)).pointAt(t);\n\n        var output = {\n            startControlPoint1: midpoint1,\n            startControlPoint2: subControl1,\n            divider: divider,\n            dividerControlPoint1: subControl2,\n            dividerControlPoint2: midpoint3\n        };\n\n        return output;\n    },\n\n    // Returns a list of curves whose flattened length is better than `opt.precision`.\n    // That is, observed difference in length between recursions is less than 10^(-3) = 0.001 = 0.1%\n    // (Observed difference is not real precision, but close enough as long as special cases are covered)\n    // As a rule of thumb, increasing `precision` by 1 requires 2 more iterations (= levels of division operations)\n    // - Precision 0 (endpointDistance) - 0 iterations => total of 2^0 - 1 = 0 operations (1 subdivision)\n    // - Precision 1 (<10% error) - 2 iterations => total of 2^2 - 1 = 3 operations (4 subdivisions)\n    // - Precision 2 (<1% error) - 4 iterations => total of 2^4 - 1 = 15 operations requires 4 division operations on all elements (15 operations total) (16 subdivisions)\n    // - Precision 3 (<0.1% error) - 6 iterations => total of 2^6 - 1 = 63 operations - acceptable when drawing (64 subdivisions)\n    // - Precision 4 (<0.01% error) - 8 iterations => total of 2^8 - 1 = 255 operations - high resolution, can be used to interpolate `t` (256 subdivisions)\n    // (Variation of 1 recursion worse or better is possible depending on the curve, doubling/halving the number of operations accordingly)\n    getSubdivisions: function(opt) {\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        // not using opt.subdivisions\n        // not using localOpt\n\n        var start = this.start;\n        var control1 = this.controlPoint1;\n        var control2 = this.controlPoint2;\n        var end = this.end;\n\n        var subdivisions = [new Curve(start, control1, control2, end)];\n        if (precision === 0) return subdivisions;\n\n        // special case #1: point-like curves\n        // - no need to calculate subdivisions, they would all be identical\n        var isPoint = !this.isDifferentiable();\n        if (isPoint) return subdivisions;\n\n        var previousLength = this.endpointDistance();\n\n        var precisionRatio = pow(10, -precision);\n\n        // special case #2: sine-like curves may have the same observed length in iteration 0 and 1 - skip iteration 1\n        // - not a problem for further iterations because cubic curves cannot have more than two local extrema\n        // - (i.e. cubic curves cannot intersect the baseline more than once)\n        // - therefore starting from iteration = 2 ensures that subsequent iterations do not produce sampling with equal length\n        // - (unless it's a straight-line curve, see below)\n        var minIterations = 2; // = 2*1\n\n        // special case #3: straight-line curves have the same observed length in all iterations\n        // - this causes observed precision ratio to always be 0 (= lower than `precisionRatio`, which is our exit condition)\n        // - we enforce the expected number of iterations = 2 * precision\n        var isLine = ((control1.cross(start, end) === 0) && (control2.cross(start, end) === 0));\n        if (isLine) {\n            minIterations = (2 * precision);\n        }\n\n        // recursively divide curve at `t = 0.5`\n        // until we reach `minIterations`\n        // and until the difference between observed length at subsequent iterations is lower than `precision`\n        var iteration = 0;\n        while (true) {\n            iteration += 1;\n\n            // divide all subdivisions\n            var newSubdivisions = [];\n            var numSubdivisions = subdivisions.length;\n            for (var i = 0; i < numSubdivisions; i++) {\n\n                var currentSubdivision = subdivisions[i];\n                var divided = currentSubdivision.divide(0.5); // dividing at t = 0.5 (not at middle length!)\n                newSubdivisions.push(divided[0], divided[1]);\n            }\n\n            // measure new length\n            var length = 0;\n            var numNewSubdivisions = newSubdivisions.length;\n            for (var j = 0; j < numNewSubdivisions; j++) {\n\n                var currentNewSubdivision = newSubdivisions[j];\n                length += currentNewSubdivision.endpointDistance();\n            }\n\n            // check if we have reached minimum number of iterations\n            if (iteration >= minIterations) {\n\n                // check if we have reached required observed precision\n                var observedPrecisionRatio = ((length !== 0) ? ((length - previousLength) / length) : 0);\n                if (observedPrecisionRatio < precisionRatio) {\n                    return newSubdivisions;\n                }\n            }\n\n            // otherwise, set up for next iteration\n            subdivisions = newSubdivisions;\n            previousLength = length;\n        }\n    },\n\n    isDifferentiable: function() {\n\n        var start = this.start;\n        var control1 = this.controlPoint1;\n        var control2 = this.controlPoint2;\n        var end = this.end;\n\n        return !(start.equals(control1) && control1.equals(control2) && control2.equals(end));\n    },\n\n    // Returns flattened length of the curve with precision better than `opt.precision`; or using `opt.subdivisions` provided.\n    length: function(opt) {\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision; // opt.precision only used in getSubdivisions() call\n        var subdivisions = (opt.subdivisions === undefined) ? this.getSubdivisions({ precision: precision }) : opt.subdivisions;\n        // not using localOpt\n\n        var length = 0;\n        var n = subdivisions.length;\n        for (var i = 0; i < n; i++) {\n\n            var currentSubdivision = subdivisions[i];\n            length += currentSubdivision.endpointDistance();\n        }\n\n        return length;\n    },\n\n    // Returns distance along the curve up to `t` with precision better than requested `opt.precision`. (Not using `opt.subdivisions`.)\n    lengthAtT: function(t, opt) {\n\n        if (t <= 0) return 0;\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        // not using opt.subdivisions\n        // not using localOpt\n\n        var subCurve = this.divide(t)[0];\n        var subCurveLength = subCurve.length({ precision: precision });\n\n        return subCurveLength;\n    },\n\n    // Returns point at requested `ratio` between 0 and 1 with precision better than `opt.precision`; optionally using `opt.subdivisions` provided.\n    // Mirrors Line.pointAt() function.\n    // For a function that tracks `t`, use Curve.pointAtT().\n    pointAt: function(ratio, opt) {\n\n        if (ratio <= 0) return this.start.clone();\n        if (ratio >= 1) return this.end.clone();\n\n        var t = this.tAt(ratio, opt);\n\n        return this.pointAtT(t);\n    },\n\n    // Returns point at requested `length` with precision better than requested `opt.precision`; optionally using `opt.subdivisions` provided.\n    pointAtLength: function(length, opt) {\n\n        var t = this.tAtLength(length, opt);\n\n        return this.pointAtT(t);\n    },\n\n    // Returns the point at provided `t` between 0 and 1.\n    // `t` does not track distance along curve as it does in Line objects.\n    // Non-linear relationship, speeds up and slows down as curve warps!\n    // For linear length-based solution, use Curve.pointAt().\n    pointAtT: function(t) {\n\n        if (t <= 0) return this.start.clone();\n        if (t >= 1) return this.end.clone();\n\n        return this.getSkeletonPoints(t).divider;\n    },\n\n    // Default precision\n    PRECISION: 3,\n\n    round: function(precision) {\n\n        this.start.round(precision);\n        this.controlPoint1.round(precision);\n        this.controlPoint2.round(precision);\n        this.end.round(precision);\n        return this;\n    },\n\n    scale: function(sx, sy, origin) {\n\n        this.start.scale(sx, sy, origin);\n        this.controlPoint1.scale(sx, sy, origin);\n        this.controlPoint2.scale(sx, sy, origin);\n        this.end.scale(sx, sy, origin);\n        return this;\n    },\n\n    // Returns a tangent line at requested `ratio` with precision better than requested `opt.precision`; or using `opt.subdivisions` provided.\n    tangentAt: function(ratio, opt) {\n\n        if (!this.isDifferentiable()) return null;\n\n        if (ratio < 0) ratio = 0;\n        else if (ratio > 1) ratio = 1;\n\n        var t = this.tAt(ratio, opt);\n\n        return this.tangentAtT(t);\n    },\n\n    // Returns a tangent line at requested `length` with precision better than requested `opt.precision`; or using `opt.subdivisions` provided.\n    tangentAtLength: function(length, opt) {\n\n        if (!this.isDifferentiable()) return null;\n\n        var t = this.tAtLength(length, opt);\n\n        return this.tangentAtT(t);\n    },\n\n    // Returns a tangent line at requested `t`.\n    tangentAtT: function(t) {\n\n        if (!this.isDifferentiable()) return null;\n\n        if (t < 0) t = 0;\n        else if (t > 1) t = 1;\n\n        var skeletonPoints = this.getSkeletonPoints(t);\n\n        var p1 = skeletonPoints.startControlPoint2;\n        var p2 = skeletonPoints.dividerControlPoint1;\n\n        var tangentStart = skeletonPoints.divider;\n\n        var tangentLine = new Line(p1, p2);\n        tangentLine.translate(tangentStart.x - p1.x, tangentStart.y - p1.y); // move so that tangent line starts at the point requested\n\n        return tangentLine;\n    },\n\n    // Returns `t` at requested `ratio` with precision better than requested `opt.precision`; optionally using `opt.subdivisions` provided.\n    tAt: function(ratio, opt) {\n\n        if (ratio <= 0) return 0;\n        if (ratio >= 1) return 1;\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var subdivisions = (opt.subdivisions === undefined) ? this.getSubdivisions({ precision: precision }) : opt.subdivisions;\n        var localOpt = { precision: precision, subdivisions: subdivisions };\n\n        var curveLength = this.length(localOpt);\n        var length = curveLength * ratio;\n\n        return this.tAtLength(length, localOpt);\n    },\n\n    // Returns `t` at requested `length` with precision better than requested `opt.precision`; optionally using `opt.subdivisions` provided.\n    // Uses `precision` to approximate length within `precision` (always underestimates)\n    // Then uses a binary search to find the `t` of a subdivision endpoint that is close (within `precision`) to the `length`, if the curve was as long as approximated\n    // As a rule of thumb, increasing `precision` by 1 causes the algorithm to go 2^(precision - 1) deeper\n    // - Precision 0 (chooses one of the two endpoints) - 0 levels\n    // - Precision 1 (chooses one of 5 points, <10% error) - 1 level\n    // - Precision 2 (<1% error) - 3 levels\n    // - Precision 3 (<0.1% error) - 7 levels\n    // - Precision 4 (<0.01% error) - 15 levels\n    tAtLength: function(length, opt) {\n\n        var fromStart = true;\n        if (length < 0) {\n            fromStart = false; // negative lengths mean start calculation from end point\n            length = -length; // absolute value\n        }\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var subdivisions = (opt.subdivisions === undefined) ? this.getSubdivisions({ precision: precision }) : opt.subdivisions;\n        var localOpt = { precision: precision, subdivisions: subdivisions };\n\n        // identify the subdivision that contains the point at requested `length`:\n        var investigatedSubdivision;\n        var investigatedSubdivisionStartT; // assume that subdivisions are evenly spaced\n        var investigatedSubdivisionEndT;\n        //var baseline; // straightened version of subdivision to investigate\n        //var baselinePoint; // point on the baseline that is the requested distance away from start\n        var baselinePointDistFromStart; // distance of baselinePoint from start of baseline\n        var baselinePointDistFromEnd; // distance of baselinePoint from end of baseline\n        var l = 0; // length so far\n        var n = subdivisions.length;\n        var subdivisionSize = 1 / n;\n        for (var i = 0; i < n; i++) {\n            var index = (fromStart ? i : (n - 1 - i));\n\n            var currentSubdivision = subdivisions[i];\n            var d = currentSubdivision.endpointDistance(); // length of current subdivision\n\n            if (length <= (l + d)) {\n                investigatedSubdivision = currentSubdivision;\n\n                investigatedSubdivisionStartT = index * subdivisionSize;\n                investigatedSubdivisionEndT = (index + 1) * subdivisionSize;\n\n                baselinePointDistFromStart = (fromStart ? (length - l) : ((d + l) - length));\n                baselinePointDistFromEnd = (fromStart ? ((d + l) - length) : (length - l));\n\n                break;\n            }\n\n            l += d;\n        }\n\n        if (!investigatedSubdivision) return (fromStart ? 1 : 0); // length requested is out of range - return maximum t\n        // note that precision affects what length is recorded\n        // (imprecise measurements underestimate length by up to 10^(-precision) of the precise length)\n        // e.g. at precision 1, the length may be underestimated by up to 10% and cause this function to return 1\n\n        var curveLength = this.length(localOpt);\n\n        var precisionRatio = pow(10, -precision);\n\n        // recursively divide investigated subdivision:\n        // until distance between baselinePoint and closest path endpoint is within 10^(-precision)\n        // then return the closest endpoint of that final subdivision\n        while (true) {\n\n            // check if we have reached required observed precision\n            var observedPrecisionRatio;\n\n            observedPrecisionRatio = ((curveLength !== 0) ? (baselinePointDistFromStart / curveLength) : 0);\n            if (observedPrecisionRatio < precisionRatio) return investigatedSubdivisionStartT;\n            observedPrecisionRatio = ((curveLength !== 0) ? (baselinePointDistFromEnd / curveLength) : 0);\n            if (observedPrecisionRatio < precisionRatio) return investigatedSubdivisionEndT;\n\n            // otherwise, set up for next iteration\n            var newBaselinePointDistFromStart;\n            var newBaselinePointDistFromEnd;\n\n            var divided = investigatedSubdivision.divide(0.5);\n            subdivisionSize /= 2;\n\n            var baseline1Length = divided[0].endpointDistance();\n            var baseline2Length = divided[1].endpointDistance();\n\n            if (baselinePointDistFromStart <= baseline1Length) { // point at requested length is inside divided[0]\n                investigatedSubdivision = divided[0];\n\n                investigatedSubdivisionEndT -= subdivisionSize; // sudivisionSize was already halved\n\n                newBaselinePointDistFromStart = baselinePointDistFromStart;\n                newBaselinePointDistFromEnd = baseline1Length - newBaselinePointDistFromStart;\n\n            } else { // point at requested length is inside divided[1]\n                investigatedSubdivision = divided[1];\n\n                investigatedSubdivisionStartT += subdivisionSize; // subdivisionSize was already halved\n\n                newBaselinePointDistFromStart = baselinePointDistFromStart - baseline1Length;\n                newBaselinePointDistFromEnd = baseline2Length - newBaselinePointDistFromStart;\n            }\n\n            baselinePointDistFromStart = newBaselinePointDistFromStart;\n            baselinePointDistFromEnd = newBaselinePointDistFromEnd;\n        }\n    },\n\n    // Returns an array of points that represents the curve when flattened, up to `opt.precision`; or using `opt.subdivisions` provided.\n    // Flattened length is no more than 10^(-precision) away from real curve length.\n    toPoints: function(opt) {\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision; // opt.precision only used in getSubdivisions() call\n        var subdivisions = (opt.subdivisions === undefined) ? this.getSubdivisions({ precision: precision }) : opt.subdivisions;\n        // not using localOpt\n\n        var points = [subdivisions[0].start.clone()];\n        var n = subdivisions.length;\n        for (var i = 0; i < n; i++) {\n\n            var currentSubdivision = subdivisions[i];\n            points.push(currentSubdivision.end.clone());\n        }\n\n        return points;\n    },\n\n    // Returns a polyline that represents the curve when flattened, up to `opt.precision`; or using `opt.subdivisions` provided.\n    // Flattened length is no more than 10^(-precision) away from real curve length.\n    toPolyline: function(opt) {\n\n        return new Polyline(this.toPoints(opt));\n    },\n\n    toString: function() {\n\n        return this.start + ' ' + this.controlPoint1 + ' ' + this.controlPoint2 + ' ' + this.end;\n    },\n\n    translate: function(tx, ty) {\n\n        this.start.translate(tx, ty);\n        this.controlPoint1.translate(tx, ty);\n        this.controlPoint2.translate(tx, ty);\n        this.end.translate(tx, ty);\n        return this;\n    }\n};\n\nCurve.prototype.divide = Curve.prototype.divideAtT;\n","// Local helper function.\n// Add properties from arguments on top of properties from `obj`.\n// This allows for rudimentary inheritance.\n// - The `obj` argument acts as parent.\n// - This function creates a new object that inherits all `obj` properties and adds/replaces those that are present in arguments.\n// - A high-level example: calling `extend(Vehicle, Car)` would be akin to declaring `class Car extends Vehicle`.\nexport function extend(obj) {\n    // In JavaScript, the combination of a constructor function (e.g. `g.Line = function(...) {...}`) and prototype (e.g. `g.Line.prototype = {...}) is akin to a C++ class.\n    // - When inheritance is not necessary, we can leave it at that. (This would be akin to calling extend with only `obj`.)\n    // - But, what if we wanted the `g.Line` quasiclass to inherit from another quasiclass (let's call it `g.GeometryObject`) in JavaScript?\n    // - First, realize that both of those quasiclasses would still have their own separate constructor function.\n    // - So what we are actually saying is that we want the `g.Line` prototype to inherit from `g.GeometryObject` prototype.\n    // - This method provides a way to do exactly that.\n    // - It copies parent prototype's properties, then adds extra ones from child prototype/overrides parent prototype properties with child prototype properties.\n    // - Therefore, to continue with the example above:\n    //   - `g.Line.prototype = extend(g.GeometryObject.prototype, linePrototype)`\n    //   - Where `linePrototype` is a properties object that looks just like `g.Line.prototype` does right now.\n    //   - Then, `g.Line` would allow the programmer to access to all methods currently in `g.Line.Prototype`, plus any non-overridden methods from `g.GeometryObject.prototype`.\n    //   - In that aspect, `g.GeometryObject` would then act like the parent of `g.Line`.\n    // - Multiple inheritance is also possible, if multiple arguments are provided.\n    // - What if we wanted to add another level of abstraction between `g.GeometryObject` and `g.Line` (let's call it `g.LinearObject`)?\n    //   - `g.Line.prototype = extend(g.GeometryObject.prototype, g.LinearObject.prototype, linePrototype)`\n    //   - The ancestors are applied in order of appearance.\n    //   - That means that `g.Line` would have inherited from `g.LinearObject` that would have inherited from `g.GeometryObject`.\n    //   - Any number of ancestors may be provided.\n    // - Note that neither `obj` nor any of the arguments need to actually be prototypes of any JavaScript quasiclass, that was just a simplified explanation.\n    // - We can create a new object composed from the properties of any number of other objects (since they do not have a constructor, we can think of those as interfaces).\n    //   - `extend({ a: 1, b: 2 }, { b: 10, c: 20 }, { c: 100, d: 200 })` gives `{ a: 1, b: 10, c: 100, d: 200 }`.\n    //   - Basically, with this function, we can emulate the `extends` keyword as well as the `implements` keyword.\n    // - Therefore, both of the following are valid:\n    //   - `Lineto.prototype = extend(Line.prototype, segmentPrototype, linetoPrototype)`\n    //   - `Moveto.prototype = extend(segmentPrototype, movetoPrototype)`\n\n    var i;\n    var n;\n\n    var args = [];\n    n = arguments.length;\n    for (i = 1; i < n; i++) { // skip over obj\n        args.push(arguments[i]);\n    }\n\n    if (!obj) throw new Error('Missing a parent object.');\n    var child = Object.create(obj);\n\n    n = args.length;\n    for (i = 0; i < n; i++) {\n\n        var src = args[i];\n\n        var inheritedProperty;\n        var key;\n        for (key in src) {\n\n            if (src.hasOwnProperty(key)) {\n                delete child[key]; // delete property inherited from parent\n                inheritedProperty = Object.getOwnPropertyDescriptor(src, key); // get new definition of property from src\n                Object.defineProperty(child, key, inheritedProperty); // re-add property with new definition (includes getter/setter methods)\n            }\n        }\n    }\n\n    return child;\n}\n","// Accepts path data string, array of segments, array of Curves and/or Lines, or a Polyline.\n// Path created is not guaranteed to be a valid (serializable) path (might not start with an M).\nimport { Polyline } from './polyline.mjs';\nimport { Rect } from './rect.mjs';\nimport { Point } from './point.mjs';\nimport { Line } from './line.mjs';\nimport { Curve } from './curve.mjs';\nimport { types } from './types.mjs';\nimport { extend } from './extend.mjs';\nexport const Path = function(arg) {\n\n    if (!(this instanceof Path)) {\n        return new Path(arg);\n    }\n\n    if (typeof arg === 'string') { // create from a path data string\n        return new Path.parse(arg);\n    }\n\n    this.segments = [];\n\n    var i;\n    var n;\n\n    if (!arg) {\n        // don't do anything\n\n    } else if (Array.isArray(arg) && arg.length !== 0) { // if arg is a non-empty array\n        // flatten one level deep\n        // so we can chain arbitrary Path.createSegment results\n        arg = arg.reduce(function(acc, val) {\n            return acc.concat(val);\n        }, []);\n\n        n = arg.length;\n        if (arg[0].isSegment) { // create from an array of segments\n            for (i = 0; i < n; i++) {\n\n                var segment = arg[i];\n\n                this.appendSegment(segment);\n            }\n\n        } else { // create from an array of Curves and/or Lines\n            var previousObj = null;\n            for (i = 0; i < n; i++) {\n\n                var obj = arg[i];\n\n                if (!((obj instanceof Line) || (obj instanceof Curve))) {\n                    throw new Error('Cannot construct a path segment from the provided object.');\n                }\n\n                if (i === 0) this.appendSegment(Path.createSegment('M', obj.start));\n\n                // if objects do not link up, moveto segments are inserted to cover the gaps\n                if (previousObj && !previousObj.end.equals(obj.start)) this.appendSegment(Path.createSegment('M', obj.start));\n\n                if (obj instanceof Line) {\n                    this.appendSegment(Path.createSegment('L', obj.end));\n\n                } else if (obj instanceof Curve) {\n                    this.appendSegment(Path.createSegment('C', obj.controlPoint1, obj.controlPoint2, obj.end));\n                }\n\n                previousObj = obj;\n            }\n        }\n\n    } else if (arg.isSegment) { // create from a single segment\n        this.appendSegment(arg);\n\n    } else if (arg instanceof Line) { // create from a single Line\n        this.appendSegment(Path.createSegment('M', arg.start));\n        this.appendSegment(Path.createSegment('L', arg.end));\n\n    } else if (arg instanceof Curve) { // create from a single Curve\n        this.appendSegment(Path.createSegment('M', arg.start));\n        this.appendSegment(Path.createSegment('C', arg.controlPoint1, arg.controlPoint2, arg.end));\n\n    } else if (arg instanceof Polyline) { // create from a Polyline\n        if (!(arg.points && (arg.points.length !== 0))) return; // if Polyline has no points, leave Path empty\n\n        n = arg.points.length;\n        for (i = 0; i < n; i++) {\n\n            var point = arg.points[i];\n\n            if (i === 0) this.appendSegment(Path.createSegment('M', point));\n            else this.appendSegment(Path.createSegment('L', point));\n        }\n\n    } else { // unknown object\n        throw new Error('Cannot construct a path from the provided object.');\n    }\n};\n\n// More permissive than V.normalizePathData and Path.prototype.serialize.\n// Allows path data strings that do not start with a Moveto command (unlike SVG specification).\n// Does not require spaces between elements; commas are allowed, separators may be omitted when unambiguous (e.g. 'ZM10,10', 'L1.6.8', 'M100-200').\n// Allows for command argument chaining.\n// Throws an error if wrong number of arguments is provided with a command.\n// Throws an error if an unrecognized path command is provided (according to Path.segmentTypes). Only a subset of SVG commands is currently supported (L, C, M, Z).\nPath.parse = function(pathData) {\n\n    if (!pathData) return new Path();\n\n    var path = new Path();\n\n    var commandRe = /(?:[a-zA-Z] *)(?:(?:-?\\d+(?:\\.\\d+)?(?:e[-+]?\\d+)? *,? *)|(?:-?\\.\\d+ *,? *))+|(?:[a-zA-Z] *)(?! |\\d|-|\\.)/g;\n    var commands = pathData.match(commandRe);\n\n    var numCommands = commands.length;\n    for (var i = 0; i < numCommands; i++) {\n\n        var command = commands[i];\n        var argRe = /(?:[a-zA-Z])|(?:(?:-?\\d+(?:\\.\\d+)?(?:e[-+]?\\d+)?))|(?:(?:-?\\.\\d+))/g;\n        var args = command.match(argRe);\n\n        var segment = Path.createSegment.apply(this, args); // args = [type, coordinate1, coordinate2...]\n        path.appendSegment(segment);\n    }\n\n    return path;\n};\n\n// Create a segment or an array of segments.\n// Accepts unlimited points/coords arguments after `type`.\nPath.createSegment = function(type) {\n\n    if (!type) throw new Error('Type must be provided.');\n\n    var segmentConstructor = Path.segmentTypes[type];\n    if (!segmentConstructor) throw new Error(type + ' is not a recognized path segment type.');\n\n    var args = [];\n    var n = arguments.length;\n    for (var i = 1; i < n; i++) { // do not add first element (`type`) to args array\n        args.push(arguments[i]);\n    }\n\n    return applyToNew(segmentConstructor, args);\n};\n\nPath.prototype = {\n\n    type: types.Path,\n\n    // Accepts one segment or an array of segments as argument.\n    // Throws an error if argument is not a segment or an array of segments.\n    appendSegment: function(arg) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        // works even if path has no segments\n\n        var currentSegment;\n\n        var previousSegment = ((numSegments !== 0) ? segments[numSegments - 1] : null); // if we are appending to an empty path, previousSegment is null\n        var nextSegment = null;\n\n        if (!Array.isArray(arg)) { // arg is a segment\n            if (!arg || !arg.isSegment) throw new Error('Segment required.');\n\n            currentSegment = this.prepareSegment(arg, previousSegment, nextSegment);\n            segments.push(currentSegment);\n\n        } else { // arg is an array of segments\n            // flatten one level deep\n            // so we can chain arbitrary Path.createSegment results\n            arg = arg.reduce(function(acc, val) {\n                return acc.concat(val);\n            }, []);\n\n            if (!arg[0].isSegment) throw new Error('Segments required.');\n\n            var n = arg.length;\n            for (var i = 0; i < n; i++) {\n\n                var currentArg = arg[i];\n                currentSegment = this.prepareSegment(currentArg, previousSegment, nextSegment);\n                segments.push(currentSegment);\n                previousSegment = currentSegment;\n            }\n        }\n    },\n\n    // Returns the bbox of the path.\n    // If path has no segments, returns null.\n    // If path has only invisible segments, returns bbox of the end point of last segment.\n    bbox: function() {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return null; // if segments is an empty array\n\n        var bbox;\n        for (var i = 0; i < numSegments; i++) {\n\n            var segment = segments[i];\n            if (segment.isVisible) {\n                var segmentBBox = segment.bbox();\n                bbox = bbox ? bbox.union(segmentBBox) : segmentBBox;\n            }\n        }\n\n        if (bbox) return bbox;\n\n        // if the path has only invisible elements, return end point of last segment\n        var lastSegment = segments[numSegments - 1];\n        return new Rect(lastSegment.end.x, lastSegment.end.y, 0, 0);\n    },\n\n    // Returns a new path that is a clone of this path.\n    clone: function() {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        // works even if path has no segments\n\n        var path = new Path();\n        for (var i = 0; i < numSegments; i++) {\n\n            var segment = segments[i].clone();\n            path.appendSegment(segment);\n        }\n\n        return path;\n    },\n\n    closestPoint: function(p, opt) {\n\n        var t = this.closestPointT(p, opt);\n        if (!t) return null;\n\n        return this.pointAtT(t);\n    },\n\n    closestPointLength: function(p, opt) {\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var segmentSubdivisions = (opt.segmentSubdivisions === undefined) ? this.getSegmentSubdivisions({ precision: precision }) : opt.segmentSubdivisions;\n        var localOpt = { precision: precision, segmentSubdivisions: segmentSubdivisions };\n\n        var t = this.closestPointT(p, localOpt);\n        if (!t) return 0;\n\n        return this.lengthAtT(t, localOpt);\n    },\n\n    closestPointNormalizedLength: function(p, opt) {\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var segmentSubdivisions = (opt.segmentSubdivisions === undefined) ? this.getSegmentSubdivisions({ precision: precision }) : opt.segmentSubdivisions;\n        var localOpt = { precision: precision, segmentSubdivisions: segmentSubdivisions };\n\n        var cpLength = this.closestPointLength(p, localOpt);\n        if (cpLength === 0) return 0; // shortcut\n\n        var length = this.length(localOpt);\n        if (length === 0) return 0; // prevents division by zero\n\n        return cpLength / length;\n    },\n\n    // Private function.\n    closestPointT: function(p, opt) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return null; // if segments is an empty array\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var segmentSubdivisions = (opt.segmentSubdivisions === undefined) ? this.getSegmentSubdivisions({ precision: precision }) : opt.segmentSubdivisions;\n        // not using localOpt\n\n        var closestPointT;\n        var minSquaredDistance = Infinity;\n        for (var i = 0; i < numSegments; i++) {\n\n            var segment = segments[i];\n            var subdivisions = segmentSubdivisions[i];\n\n            if (segment.isVisible) {\n                var segmentClosestPointT = segment.closestPointT(p, {\n                    precision: precision,\n                    subdivisions: subdivisions\n                });\n                var segmentClosestPoint = segment.pointAtT(segmentClosestPointT);\n                var squaredDistance = (new Line(segmentClosestPoint, p)).squaredLength();\n\n                if (squaredDistance < minSquaredDistance) {\n                    closestPointT = { segmentIndex: i, value: segmentClosestPointT };\n                    minSquaredDistance = squaredDistance;\n                }\n            }\n        }\n\n        if (closestPointT) return closestPointT;\n\n        // if no visible segment, return end of last segment\n        return { segmentIndex: numSegments - 1, value: 1 };\n    },\n\n    closestPointTangent: function(p, opt) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return null; // if segments is an empty array\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var segmentSubdivisions = (opt.segmentSubdivisions === undefined) ? this.getSegmentSubdivisions({ precision: precision }) : opt.segmentSubdivisions;\n        // not using localOpt\n\n        var closestPointTangent;\n        var minSquaredDistance = Infinity;\n        for (var i = 0; i < numSegments; i++) {\n\n            var segment = segments[i];\n            var subdivisions = segmentSubdivisions[i];\n\n            if (segment.isDifferentiable()) {\n                var segmentClosestPointT = segment.closestPointT(p, {\n                    precision: precision,\n                    subdivisions: subdivisions\n                });\n                var segmentClosestPoint = segment.pointAtT(segmentClosestPointT);\n                var squaredDistance = (new Line(segmentClosestPoint, p)).squaredLength();\n\n                if (squaredDistance < minSquaredDistance) {\n                    closestPointTangent = segment.tangentAtT(segmentClosestPointT);\n                    minSquaredDistance = squaredDistance;\n                }\n            }\n        }\n\n        if (closestPointTangent) return closestPointTangent;\n\n        // if no valid segment, return null\n        return null;\n    },\n\n    // Returns `true` if the area surrounded by the path contains the point `p`.\n    // Implements the even-odd algorithm (self-intersections are \"outside\").\n    // Closes open paths (always imagines a final closing segment).\n    // Precision may be adjusted by passing an `opt` object.\n    containsPoint: function(p, opt) {\n\n        var polylines = this.toPolylines(opt);\n        if (!polylines) return false; // shortcut (this path has no polylines)\n\n        var numPolylines = polylines.length;\n\n        // how many component polylines does `p` lie within?\n        var numIntersections = 0;\n        for (var i = 0; i < numPolylines; i++) {\n            var polyline = polylines[i];\n            if (polyline.containsPoint(p)) {\n                // `p` lies within this polyline\n                numIntersections++;\n            }\n        }\n\n        // returns `true` for odd numbers of intersections (even-odd algorithm)\n        return ((numIntersections % 2) === 1);\n    },\n\n    // Divides the path into two at requested `ratio` between 0 and 1 with precision better than `opt.precision`; optionally using `opt.subdivisions` provided.\n    divideAt: function(ratio, opt) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return null; // if segments is an empty array\n\n        if (ratio < 0) ratio = 0;\n        if (ratio > 1) ratio = 1;\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var segmentSubdivisions = (opt.segmentSubdivisions === undefined) ? this.getSegmentSubdivisions({ precision: precision }) : opt.segmentSubdivisions;\n        var localOpt = { precision: precision, segmentSubdivisions: segmentSubdivisions };\n\n        var pathLength = this.length(localOpt);\n        var length = pathLength * ratio;\n\n        return this.divideAtLength(length, localOpt);\n    },\n\n    // Divides the path into two at requested `length` with precision better than requested `opt.precision`; optionally using `opt.subdivisions` provided.\n    divideAtLength: function(length, opt) {\n\n        var numSegments = this.segments.length;\n        if (numSegments === 0) return null; // if segments is an empty array\n\n        var fromStart = true;\n        if (length < 0) {\n            fromStart = false; // negative lengths mean start calculation from end point\n            length = -length; // absolute value\n        }\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var segmentSubdivisions = (opt.segmentSubdivisions === undefined) ? this.getSegmentSubdivisions({ precision: precision }) : opt.segmentSubdivisions;\n        // not using localOpt\n\n        var i;\n        var segment;\n\n        // identify the segment to divide:\n\n        var l = 0; // length so far\n        var divided;\n        var dividedSegmentIndex;\n        var lastValidSegment; // visible AND differentiable\n        var lastValidSegmentIndex;\n        var t;\n        for (i = 0; i < numSegments; i++) {\n            var index = (fromStart ? i : (numSegments - 1 - i));\n\n            segment = this.getSegment(index);\n            var subdivisions = segmentSubdivisions[index];\n            var d = segment.length({ precision: precision, subdivisions: subdivisions });\n\n            if (segment.isDifferentiable()) { // segment is not just a point\n                lastValidSegment = segment;\n                lastValidSegmentIndex = index;\n\n                if (length <= (l + d)) {\n                    dividedSegmentIndex = index;\n                    divided = segment.divideAtLength(((fromStart ? 1 : -1) * (length - l)), {\n                        precision: precision,\n                        subdivisions: subdivisions\n                    });\n                    break;\n                }\n            }\n\n            l += d;\n        }\n\n        if (!lastValidSegment) { // no valid segment found\n            return null;\n        }\n\n        // else: the path contains at least one valid segment\n\n        if (!divided) { // the desired length is greater than the length of the path\n            dividedSegmentIndex = lastValidSegmentIndex;\n            t = (fromStart ? 1 : 0);\n            divided = lastValidSegment.divideAtT(t);\n        }\n\n        // create a copy of this path and replace the identified segment with its two divided parts:\n\n        var pathCopy = this.clone();\n        pathCopy.replaceSegment(dividedSegmentIndex, divided);\n\n        var divisionStartIndex = dividedSegmentIndex;\n        var divisionMidIndex = dividedSegmentIndex + 1;\n        var divisionEndIndex = dividedSegmentIndex + 2;\n\n        // do not insert the part if it looks like a point\n        if (!divided[0].isDifferentiable()) {\n            pathCopy.removeSegment(divisionStartIndex);\n            divisionMidIndex -= 1;\n            divisionEndIndex -= 1;\n        }\n\n        // insert a Moveto segment to ensure secondPath will be valid:\n        var movetoEnd = pathCopy.getSegment(divisionMidIndex).start;\n        pathCopy.insertSegment(divisionMidIndex, Path.createSegment('M', movetoEnd));\n        divisionEndIndex += 1;\n\n        // do not insert the part if it looks like a point\n        if (!divided[1].isDifferentiable()) {\n            pathCopy.removeSegment(divisionEndIndex - 1);\n            divisionEndIndex -= 1;\n        }\n\n        // ensure that Closepath segments in secondPath will be assigned correct subpathStartSegment:\n\n        var secondPathSegmentIndexConversion = divisionEndIndex - divisionStartIndex - 1;\n        for (i = divisionEndIndex; i < pathCopy.segments.length; i++) {\n\n            var originalSegment = this.getSegment(i - secondPathSegmentIndexConversion);\n            segment = pathCopy.getSegment(i);\n\n            if ((segment.type === 'Z') && !originalSegment.subpathStartSegment.end.equals(segment.subpathStartSegment.end)) {\n                // pathCopy segment's subpathStartSegment is different from original segment's one\n                // convert this Closepath segment to a Lineto and replace it in pathCopy\n                var convertedSegment = Path.createSegment('L', originalSegment.end);\n                pathCopy.replaceSegment(i, convertedSegment);\n            }\n        }\n\n        // distribute pathCopy segments into two paths and return those:\n\n        var firstPath = new Path(pathCopy.segments.slice(0, divisionMidIndex));\n        var secondPath = new Path(pathCopy.segments.slice(divisionMidIndex));\n\n        return [firstPath, secondPath];\n    },\n\n    // Checks whether two paths are exactly the same.\n    // If `p` is undefined or null, returns false.\n    equals: function(p) {\n\n        if (!p) return false;\n\n        var segments = this.segments;\n        var otherSegments = p.segments;\n\n        var numSegments = segments.length;\n        if (otherSegments.length !== numSegments) return false; // if the two paths have different number of segments, they cannot be equal\n\n        for (var i = 0; i < numSegments; i++) {\n\n            var segment = segments[i];\n            var otherSegment = otherSegments[i];\n\n            // as soon as an inequality is found in segments, return false\n            if ((segment.type !== otherSegment.type) || (!segment.equals(otherSegment))) return false;\n        }\n\n        // if no inequality found in segments, return true\n        return true;\n    },\n\n    // Accepts negative indices.\n    // Throws an error if path has no segments.\n    // Throws an error if index is out of range.\n    getSegment: function(index) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) throw new Error('Path has no segments.');\n\n        if (index < 0) index = numSegments + index; // convert negative indices to positive\n        if (index >= numSegments || index < 0) throw new Error('Index out of range.');\n\n        return segments[index];\n    },\n\n    // Returns an array of segment subdivisions, with precision better than requested `opt.precision`.\n    getSegmentSubdivisions: function(opt) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        // works even if path has no segments\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        // not using opt.segmentSubdivisions\n        // not using localOpt\n\n        var segmentSubdivisions = [];\n        for (var i = 0; i < numSegments; i++) {\n\n            var segment = segments[i];\n            var subdivisions = segment.getSubdivisions({ precision: precision });\n            segmentSubdivisions.push(subdivisions);\n        }\n\n        return segmentSubdivisions;\n    },\n\n    // Returns an array of subpaths of this path.\n    // Invalid paths are validated first.\n    // Returns `[]` if path has no segments.\n    getSubpaths: function() {\n\n        const validatedPath = this.clone().validate();\n\n        const segments = validatedPath.segments;\n        const numSegments = segments.length;\n\n        const subpaths = [];\n        for (let i = 0; i < numSegments; i++) {\n\n            const segment = segments[i];\n            if (segment.isSubpathStart) {\n                // we encountered a subpath start segment\n                // create a new path for segment, and push it to list of subpaths\n                subpaths.push(new Path(segment));\n\n            } else {\n                // append current segment to the last subpath\n                subpaths[subpaths.length - 1].appendSegment(segment);\n            }\n        }\n\n        return subpaths;\n    },\n\n    // Insert `arg` at given `index`.\n    // `index = 0` means insert at the beginning.\n    // `index = segments.length` means insert at the end.\n    // Accepts negative indices, from `-1` to `-(segments.length + 1)`.\n    // Accepts one segment or an array of segments as argument.\n    // Throws an error if index is out of range.\n    // Throws an error if argument is not a segment or an array of segments.\n    insertSegment: function(index, arg) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        // works even if path has no segments\n\n        // note that these are incremented compared to getSegments()\n        // we can insert after last element (note that this changes the meaning of index -1)\n        if (index < 0) index = numSegments + index + 1; // convert negative indices to positive\n        if (index > numSegments || index < 0) throw new Error('Index out of range.');\n\n        var currentSegment;\n\n        var previousSegment = null;\n        var nextSegment = null;\n\n        if (numSegments !== 0) {\n            if (index >= 1) {\n                previousSegment = segments[index - 1];\n                nextSegment = previousSegment.nextSegment; // if we are inserting at end, nextSegment is null\n\n            } else { // if index === 0\n                // previousSegment is null\n                nextSegment = segments[0];\n            }\n        }\n\n        if (!Array.isArray(arg)) {\n            if (!arg || !arg.isSegment) throw new Error('Segment required.');\n\n            currentSegment = this.prepareSegment(arg, previousSegment, nextSegment);\n            segments.splice(index, 0, currentSegment);\n\n        } else {\n            // flatten one level deep\n            // so we can chain arbitrary Path.createSegment results\n            arg = arg.reduce(function(acc, val) {\n                return acc.concat(val);\n            }, []);\n\n            if (!arg[0].isSegment) throw new Error('Segments required.');\n\n            var n = arg.length;\n            for (var i = 0; i < n; i++) {\n\n                var currentArg = arg[i];\n                currentSegment = this.prepareSegment(currentArg, previousSegment, nextSegment);\n                segments.splice((index + i), 0, currentSegment); // incrementing index to insert subsequent segments after inserted segments\n                previousSegment = currentSegment;\n            }\n        }\n    },\n\n    intersectionWithLine: function(line, opt) {\n\n        var intersection = null;\n        var polylines = this.toPolylines(opt);\n        if (!polylines) return null;\n        for (var i = 0, n = polylines.length; i < n; i++) {\n            var polyline = polylines[i];\n            var polylineIntersection = line.intersect(polyline);\n            if (polylineIntersection) {\n                intersection || (intersection = []);\n                if (Array.isArray(polylineIntersection)) {\n                    Array.prototype.push.apply(intersection, polylineIntersection);\n                } else {\n                    intersection.push(polylineIntersection);\n                }\n            }\n        }\n\n        return intersection;\n    },\n\n    isDifferentiable: function() {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n\n        for (var i = 0; i < numSegments; i++) {\n\n            var segment = segments[i];\n            // as soon as a differentiable segment is found in segments, return true\n            if (segment.isDifferentiable()) return true;\n        }\n\n        // if no differentiable segment is found in segments, return false\n        return false;\n    },\n\n    // Checks whether current path segments are valid.\n    // Note that d is allowed to be empty - should disable rendering of the path.\n    isValid: function() {\n\n        var segments = this.segments;\n        var isValid = (segments.length === 0) || (segments[0].type === 'M'); // either empty or first segment is a Moveto\n        return isValid;\n    },\n\n    // Returns length of the path, with precision better than requested `opt.precision`; or using `opt.segmentSubdivisions` provided.\n    // If path has no segments, returns 0.\n    length: function(opt) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return 0; // if segments is an empty array\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision; // opt.precision only used in getSegmentSubdivisions() call\n        var segmentSubdivisions = (opt.segmentSubdivisions === undefined) ? this.getSegmentSubdivisions({ precision: precision }) : opt.segmentSubdivisions;\n        // not using localOpt\n\n        var length = 0;\n        for (var i = 0; i < numSegments; i++) {\n\n            var segment = segments[i];\n            var subdivisions = segmentSubdivisions[i];\n            length += segment.length({ subdivisions: subdivisions });\n        }\n\n        return length;\n    },\n\n    // Private function.\n    lengthAtT: function(t, opt) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return 0; // if segments is an empty array\n\n        var segmentIndex = t.segmentIndex;\n        if (segmentIndex < 0) return 0; // regardless of t.value\n\n        var tValue = t.value;\n        if (segmentIndex >= numSegments) {\n            segmentIndex = numSegments - 1;\n            tValue = 1;\n        } else if (tValue < 0) tValue = 0;\n        else if (tValue > 1) tValue = 1;\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var segmentSubdivisions = (opt.segmentSubdivisions === undefined) ? this.getSegmentSubdivisions({ precision: precision }) : opt.segmentSubdivisions;\n        // not using localOpt\n\n        var subdivisions;\n        var length = 0;\n        for (var i = 0; i < segmentIndex; i++) {\n\n            var segment = segments[i];\n            subdivisions = segmentSubdivisions[i];\n            length += segment.length({ precisison: precision, subdivisions: subdivisions });\n        }\n\n        segment = segments[segmentIndex];\n        subdivisions = segmentSubdivisions[segmentIndex];\n        length += segment.lengthAtT(tValue, { precisison: precision, subdivisions: subdivisions });\n\n        return length;\n    },\n\n    // Returns point at requested `ratio` between 0 and 1, with precision better than requested `opt.precision`; optionally using `opt.segmentSubdivisions` provided.\n    pointAt: function(ratio, opt) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return null; // if segments is an empty array\n\n        if (ratio <= 0) return this.start.clone();\n        if (ratio >= 1) return this.end.clone();\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var segmentSubdivisions = (opt.segmentSubdivisions === undefined) ? this.getSegmentSubdivisions({ precision: precision }) : opt.segmentSubdivisions;\n        var localOpt = { precision: precision, segmentSubdivisions: segmentSubdivisions };\n\n        var pathLength = this.length(localOpt);\n        var length = pathLength * ratio;\n\n        return this.pointAtLength(length, localOpt);\n    },\n\n    // Returns point at requested `length`, with precision better than requested `opt.precision`; optionally using `opt.segmentSubdivisions` provided.\n    // Accepts negative length.\n    pointAtLength: function(length, opt) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return null; // if segments is an empty array\n\n        if (length === 0) return this.start.clone();\n\n        var fromStart = true;\n        if (length < 0) {\n            fromStart = false; // negative lengths mean start calculation from end point\n            length = -length; // absolute value\n        }\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var segmentSubdivisions = (opt.segmentSubdivisions === undefined) ? this.getSegmentSubdivisions({ precision: precision }) : opt.segmentSubdivisions;\n        // not using localOpt\n\n        var lastVisibleSegment;\n        var l = 0; // length so far\n        for (var i = 0; i < numSegments; i++) {\n            var index = (fromStart ? i : (numSegments - 1 - i));\n\n            var segment = segments[index];\n            var subdivisions = segmentSubdivisions[index];\n            var d = segment.length({ precision: precision, subdivisions: subdivisions });\n\n            if (segment.isVisible) {\n                if (length <= (l + d)) {\n                    return segment.pointAtLength(((fromStart ? 1 : -1) * (length - l)), {\n                        precision: precision,\n                        subdivisions: subdivisions\n                    });\n                }\n\n                lastVisibleSegment = segment;\n            }\n\n            l += d;\n        }\n\n        // if length requested is higher than the length of the path, return last visible segment endpoint\n        if (lastVisibleSegment) return (fromStart ? lastVisibleSegment.end : lastVisibleSegment.start);\n\n        // if no visible segment, return last segment end point (no matter if fromStart or no)\n        var lastSegment = segments[numSegments - 1];\n        return lastSegment.end.clone();\n    },\n\n    // Private function.\n    pointAtT: function(t) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return null; // if segments is an empty array\n\n        var segmentIndex = t.segmentIndex;\n        if (segmentIndex < 0) return segments[0].pointAtT(0);\n        if (segmentIndex >= numSegments) return segments[numSegments - 1].pointAtT(1);\n\n        var tValue = t.value;\n        if (tValue < 0) tValue = 0;\n        else if (tValue > 1) tValue = 1;\n\n        return segments[segmentIndex].pointAtT(tValue);\n    },\n\n    // Default precision\n    PRECISION: 3,\n\n    // Helper method for adding segments.\n    prepareSegment: function(segment, previousSegment, nextSegment) {\n\n        // insert after previous segment and before previous segment's next segment\n        segment.previousSegment = previousSegment;\n        segment.nextSegment = nextSegment;\n        if (previousSegment) previousSegment.nextSegment = segment;\n        if (nextSegment) nextSegment.previousSegment = segment;\n\n        var updateSubpathStart = segment;\n        if (segment.isSubpathStart) {\n            segment.subpathStartSegment = segment; // assign self as subpath start segment\n            updateSubpathStart = nextSegment; // start updating from next segment\n        }\n\n        // assign previous segment's subpath start (or self if it is a subpath start) to subsequent segments\n        if (updateSubpathStart) this.updateSubpathStartSegment(updateSubpathStart);\n\n        return segment;\n    },\n\n    // Remove the segment at `index`.\n    // Accepts negative indices, from `-1` to `-segments.length`.\n    // Throws an error if path has no segments.\n    // Throws an error if index is out of range.\n    removeSegment: function(index) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) throw new Error('Path has no segments.');\n\n        if (index < 0) index = numSegments + index; // convert negative indices to positive\n        if (index >= numSegments || index < 0) throw new Error('Index out of range.');\n\n        var removedSegment = segments.splice(index, 1)[0];\n        var previousSegment = removedSegment.previousSegment;\n        var nextSegment = removedSegment.nextSegment;\n\n        // link the previous and next segments together (if present)\n        if (previousSegment) previousSegment.nextSegment = nextSegment; // may be null\n        if (nextSegment) nextSegment.previousSegment = previousSegment; // may be null\n\n        // if removed segment used to start a subpath, update all subsequent segments until another subpath start segment is reached\n        if (removedSegment.isSubpathStart && nextSegment) this.updateSubpathStartSegment(nextSegment);\n    },\n\n    // Replace the segment at `index` with `arg`.\n    // Accepts negative indices, from `-1` to `-segments.length`.\n    // Accepts one segment or an array of segments as argument.\n    // Throws an error if path has no segments.\n    // Throws an error if index is out of range.\n    // Throws an error if argument is not a segment or an array of segments.\n    replaceSegment: function(index, arg) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) throw new Error('Path has no segments.');\n\n        if (index < 0) index = numSegments + index; // convert negative indices to positive\n        if (index >= numSegments || index < 0) throw new Error('Index out of range.');\n\n        var currentSegment;\n\n        var replacedSegment = segments[index];\n        var previousSegment = replacedSegment.previousSegment;\n        var nextSegment = replacedSegment.nextSegment;\n\n        var updateSubpathStart = replacedSegment.isSubpathStart; // boolean: is an update of subpath starts necessary?\n\n        if (!Array.isArray(arg)) {\n            if (!arg || !arg.isSegment) throw new Error('Segment required.');\n\n            currentSegment = this.prepareSegment(arg, previousSegment, nextSegment);\n            segments.splice(index, 1, currentSegment); // directly replace\n\n            if (updateSubpathStart && currentSegment.isSubpathStart) updateSubpathStart = false; // already updated by `prepareSegment`\n\n        } else {\n            // flatten one level deep\n            // so we can chain arbitrary Path.createSegment results\n            arg = arg.reduce(function(acc, val) {\n                return acc.concat(val);\n            }, []);\n\n            if (!arg[0].isSegment) throw new Error('Segments required.');\n\n            segments.splice(index, 1);\n\n            var n = arg.length;\n            for (var i = 0; i < n; i++) {\n\n                var currentArg = arg[i];\n                currentSegment = this.prepareSegment(currentArg, previousSegment, nextSegment);\n                segments.splice((index + i), 0, currentSegment); // incrementing index to insert subsequent segments after inserted segments\n                previousSegment = currentSegment;\n\n                if (updateSubpathStart && currentSegment.isSubpathStart) updateSubpathStart = false; // already updated by `prepareSegment`\n            }\n        }\n\n        // if replaced segment used to start a subpath and no new subpath start was added, update all subsequent segments until another subpath start segment is reached\n        if (updateSubpathStart && nextSegment) this.updateSubpathStartSegment(nextSegment);\n    },\n\n    round: function(precision) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n\n        for (var i = 0; i < numSegments; i++) {\n\n            var segment = segments[i];\n            segment.round(precision);\n        }\n\n        return this;\n    },\n\n    scale: function(sx, sy, origin) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n\n        for (var i = 0; i < numSegments; i++) {\n\n            var segment = segments[i];\n            segment.scale(sx, sy, origin);\n        }\n\n        return this;\n    },\n\n    segmentAt: function(ratio, opt) {\n\n        var index = this.segmentIndexAt(ratio, opt);\n        if (!index) return null;\n\n        return this.getSegment(index);\n    },\n\n    // Accepts negative length.\n    segmentAtLength: function(length, opt) {\n\n        var index = this.segmentIndexAtLength(length, opt);\n        if (!index) return null;\n\n        return this.getSegment(index);\n    },\n\n    segmentIndexAt: function(ratio, opt) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return null; // if segments is an empty array\n\n        if (ratio < 0) ratio = 0;\n        if (ratio > 1) ratio = 1;\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var segmentSubdivisions = (opt.segmentSubdivisions === undefined) ? this.getSegmentSubdivisions({ precision: precision }) : opt.segmentSubdivisions;\n        var localOpt = { precision: precision, segmentSubdivisions: segmentSubdivisions };\n\n        var pathLength = this.length(localOpt);\n        var length = pathLength * ratio;\n\n        return this.segmentIndexAtLength(length, localOpt);\n    },\n\n    // Accepts negative length.\n    segmentIndexAtLength: function(length, opt) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return null; // if segments is an empty array\n\n        var fromStart = true;\n        if (length < 0) {\n            fromStart = false; // negative lengths mean start calculation from end point\n            length = -length; // absolute value\n        }\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var segmentSubdivisions = (opt.segmentSubdivisions === undefined) ? this.getSegmentSubdivisions({ precision: precision }) : opt.segmentSubdivisions;\n        // not using localOpt\n\n        var lastVisibleSegmentIndex = null;\n        var l = 0; // length so far\n        for (var i = 0; i < numSegments; i++) {\n            var index = (fromStart ? i : (numSegments - 1 - i));\n\n            var segment = segments[index];\n            var subdivisions = segmentSubdivisions[index];\n            var d = segment.length({ precision: precision, subdivisions: subdivisions });\n\n            if (segment.isVisible) {\n                if (length <= (l + d)) return index;\n                lastVisibleSegmentIndex = index;\n            }\n\n            l += d;\n        }\n\n        // if length requested is higher than the length of the path, return last visible segment index\n        // if no visible segment, return null\n        return lastVisibleSegmentIndex;\n    },\n\n    // Returns a string that can be used to reconstruct the path.\n    // Additional error checking compared to toString (must start with M segment).\n    serialize: function() {\n\n        if (!this.isValid()) throw new Error('Invalid path segments.');\n\n        return this.toString();\n    },\n\n    // Returns tangent line at requested `ratio` between 0 and 1, with precision better than requested `opt.precision`; optionally using `opt.segmentSubdivisions` provided.\n    tangentAt: function(ratio, opt) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return null; // if segments is an empty array\n\n        if (ratio < 0) ratio = 0;\n        if (ratio > 1) ratio = 1;\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var segmentSubdivisions = (opt.segmentSubdivisions === undefined) ? this.getSegmentSubdivisions({ precision: precision }) : opt.segmentSubdivisions;\n        var localOpt = { precision: precision, segmentSubdivisions: segmentSubdivisions };\n\n        var pathLength = this.length(localOpt);\n        var length = pathLength * ratio;\n\n        return this.tangentAtLength(length, localOpt);\n    },\n\n    // Returns tangent line at requested `length`, with precision better than requested `opt.precision`; optionally using `opt.segmentSubdivisions` provided.\n    // Accepts negative length.\n    tangentAtLength: function(length, opt) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return null; // if segments is an empty array\n\n        var fromStart = true;\n        if (length < 0) {\n            fromStart = false; // negative lengths mean start calculation from end point\n            length = -length; // absolute value\n        }\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var segmentSubdivisions = (opt.segmentSubdivisions === undefined) ? this.getSegmentSubdivisions({ precision: precision }) : opt.segmentSubdivisions;\n        // not using localOpt\n\n        var lastValidSegment; // visible AND differentiable (with a tangent)\n        var l = 0; // length so far\n        for (var i = 0; i < numSegments; i++) {\n            var index = (fromStart ? i : (numSegments - 1 - i));\n\n            var segment = segments[index];\n            var subdivisions = segmentSubdivisions[index];\n            var d = segment.length({ precision: precision, subdivisions: subdivisions });\n\n            if (segment.isDifferentiable()) {\n                if (length <= (l + d)) {\n                    return segment.tangentAtLength(((fromStart ? 1 : -1) * (length - l)), {\n                        precision: precision,\n                        subdivisions: subdivisions\n                    });\n                }\n\n                lastValidSegment = segment;\n            }\n\n            l += d;\n        }\n\n        // if length requested is higher than the length of the path, return tangent of endpoint of last valid segment\n        if (lastValidSegment) {\n            var t = (fromStart ? 1 : 0);\n            return lastValidSegment.tangentAtT(t);\n        }\n\n        // if no valid segment, return null\n        return null;\n    },\n\n    // Private function.\n    tangentAtT: function(t) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return null; // if segments is an empty array\n\n        var segmentIndex = t.segmentIndex;\n        if (segmentIndex < 0) return segments[0].tangentAtT(0);\n        if (segmentIndex >= numSegments) return segments[numSegments - 1].tangentAtT(1);\n\n        var tValue = t.value;\n        if (tValue < 0) tValue = 0;\n        else if (tValue > 1) tValue = 1;\n\n        return segments[segmentIndex].tangentAtT(tValue);\n    },\n\n    toPoints: function(opt) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return null; // if segments is an empty array\n\n        opt = opt || {};\n        var precision = (opt.precision === undefined) ? this.PRECISION : opt.precision;\n        var segmentSubdivisions = (opt.segmentSubdivisions === undefined) ? this.getSegmentSubdivisions({ precision: precision }) : opt.segmentSubdivisions;\n\n        var points = [];\n        var partialPoints = [];\n        for (var i = 0; i < numSegments; i++) {\n            var segment = segments[i];\n            if (segment.isVisible) {\n                var currentSegmentSubdivisions = segmentSubdivisions[i];\n                if (currentSegmentSubdivisions.length > 0) {\n                    var subdivisionPoints = currentSegmentSubdivisions.map(function(curve) {\n                        return curve.start;\n                    });\n                    Array.prototype.push.apply(partialPoints, subdivisionPoints);\n                } else {\n                    partialPoints.push(segment.start);\n                }\n            } else if (partialPoints.length > 0) {\n                partialPoints.push(segments[i - 1].end);\n                points.push(partialPoints);\n                partialPoints = [];\n            }\n        }\n\n        if (partialPoints.length > 0) {\n            partialPoints.push(this.end);\n            points.push(partialPoints);\n        }\n        return points;\n    },\n\n    toPolylines: function(opt) {\n\n        var polylines = [];\n        var points = this.toPoints(opt);\n        if (!points) return null;\n        for (var i = 0, n = points.length; i < n; i++) {\n            polylines.push(new Polyline(points[i]));\n        }\n\n        return polylines;\n    },\n\n    toString: function() {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n\n        var pathData = '';\n        for (var i = 0; i < numSegments; i++) {\n\n            var segment = segments[i];\n            pathData += segment.serialize() + ' ';\n        }\n\n        return pathData.trim();\n    },\n\n    translate: function(tx, ty) {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n\n        for (var i = 0; i < numSegments; i++) {\n\n            var segment = segments[i];\n            segment.translate(tx, ty);\n        }\n\n        return this;\n    },\n\n    // Helper method for updating subpath start of segments, starting with the one provided.\n    updateSubpathStartSegment: function(segment) {\n\n        var previousSegment = segment.previousSegment; // may be null\n        while (segment && !segment.isSubpathStart) {\n\n            // assign previous segment's subpath start segment to this segment\n            if (previousSegment) segment.subpathStartSegment = previousSegment.subpathStartSegment; // may be null\n            else segment.subpathStartSegment = null; // if segment had no previous segment, assign null - creates an invalid path!\n\n            previousSegment = segment;\n            segment = segment.nextSegment; // move on to the segment after etc.\n        }\n    },\n\n    // If the path is not valid, insert M 0 0 at the beginning.\n    // Path with no segments is considered valid, so nothing is inserted.\n    validate: function() {\n\n        if (!this.isValid()) this.insertSegment(0, Path.createSegment('M', 0, 0));\n        return this;\n    }\n};\n\nObject.defineProperty(Path.prototype, 'start', {\n    // Getter for the first visible endpoint of the path.\n\n    configurable: true,\n\n    enumerable: true,\n\n    get: function() {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return null;\n\n        for (var i = 0; i < numSegments; i++) {\n\n            var segment = segments[i];\n            if (segment.isVisible) return segment.start;\n        }\n\n        // if no visible segment, return last segment end point\n        return segments[numSegments - 1].end;\n    }\n});\n\nObject.defineProperty(Path.prototype, 'end', {\n    // Getter for the last visible endpoint of the path.\n\n    configurable: true,\n\n    enumerable: true,\n\n    get: function() {\n\n        var segments = this.segments;\n        var numSegments = segments.length;\n        if (numSegments === 0) return null;\n\n        for (var i = numSegments - 1; i >= 0; i--) {\n\n            var segment = segments[i];\n            if (segment.isVisible) return segment.end;\n        }\n\n        // if no visible segment, return last segment end point\n        return segments[numSegments - 1].end;\n    }\n});\n\n\n// Local helper function.\n// Use an array of arguments to call a constructor (function called with `new`).\n// Adapted from https://stackoverflow.com/a/8843181/2263595\n// It is not necessary to use this function if the arguments can be passed separately (i.e. if the number of arguments is limited).\n// - If that is the case, use `new constructor(arg1, arg2)`, for example.\n// It is not necessary to use this function if the function that needs an array of arguments is not supposed to be used as a constructor.\n// - If that is the case, use `f.apply(thisArg, [arg1, arg2...])`, for example.\nfunction applyToNew(constructor, argsArray) {\n    // The `new` keyword can only be applied to functions that take a limited number of arguments.\n    // - We can fake that with .bind().\n    // - It calls a function (`constructor`, here) with the arguments that were provided to it - effectively transforming an unlimited number of arguments into limited.\n    // - So `new (constructor.bind(thisArg, arg1, arg2...))`\n    // - `thisArg` can be anything (e.g. null) because `new` keyword resets context to the constructor object.\n    // We need to pass in a variable number of arguments to the bind() call.\n    // - We can use .apply().\n    // - So `new (constructor.bind.apply(constructor, [thisArg, arg1, arg2...]))`\n    // - `thisArg` can still be anything because `new` overwrites it.\n    // Finally, to make sure that constructor.bind overwriting is not a problem, we switch to `Function.prototype.bind`.\n    // - So, the final version is `new (Function.prototype.bind.apply(constructor, [thisArg, arg1, arg2...]))`\n\n    // The function expects `argsArray[0]` to be `thisArg`.\n    // - This means that whatever is sent as the first element will be ignored.\n    // - The constructor will only see arguments starting from argsArray[1].\n    // - So, a new dummy element is inserted at the start of the array.\n    argsArray.unshift(null);\n\n    return new (Function.prototype.bind.apply(constructor, argsArray));\n}\n\n// Path segment interface:\nvar segmentPrototype = {\n\n    // virtual\n    bbox: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // virtual\n    clone: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // virtual\n    closestPoint: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // virtual\n    closestPointLength: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // virtual\n    closestPointNormalizedLength: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // Redirect calls to closestPointNormalizedLength() function if closestPointT() is not defined for segment.\n    closestPointT: function(p) {\n\n        if (this.closestPointNormalizedLength) return this.closestPointNormalizedLength(p);\n\n        throw new Error('Neither closestPointT() nor closestPointNormalizedLength() function is implemented.');\n    },\n\n    // virtual\n    closestPointTangent: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // virtual\n    divideAt: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // virtual\n    divideAtLength: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // Redirect calls to divideAt() function if divideAtT() is not defined for segment.\n    divideAtT: function(t) {\n\n        if (this.divideAt) return this.divideAt(t);\n\n        throw new Error('Neither divideAtT() nor divideAt() function is implemented.');\n    },\n\n    // virtual\n    equals: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // virtual\n    getSubdivisions: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // virtual\n    isDifferentiable: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    isSegment: true,\n\n    isSubpathStart: false, // true for Moveto segments\n\n    isVisible: true, // false for Moveto segments\n\n    // virtual\n    length: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // Return a fraction of result of length() function if lengthAtT() is not defined for segment.\n    lengthAtT: function(t) {\n\n        if (t <= 0) return 0;\n\n        var length = this.length();\n\n        if (t >= 1) return length;\n\n        return length * t;\n    },\n\n    nextSegment: null, // needed for subpath start segment updating\n\n    // virtual\n    pointAt: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // virtual\n    pointAtLength: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // Redirect calls to pointAt() function if pointAtT() is not defined for segment.\n    pointAtT: function(t) {\n\n        if (this.pointAt) return this.pointAt(t);\n\n        throw new Error('Neither pointAtT() nor pointAt() function is implemented.');\n    },\n\n    previousSegment: null, // needed to get segment start property\n\n    // virtual\n    round: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    subpathStartSegment: null, // needed to get Closepath segment end property\n\n    // virtual\n    scale: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // virtual\n    serialize: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // virtual\n    tangentAt: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // virtual\n    tangentAtLength: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // Redirect calls to tangentAt() function if tangentAtT() is not defined for segment.\n    tangentAtT: function(t) {\n\n        if (this.tangentAt) return this.tangentAt(t);\n\n        throw new Error('Neither tangentAtT() nor tangentAt() function is implemented.');\n    },\n\n    // virtual\n    toString: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    },\n\n    // virtual\n    translate: function() {\n\n        throw new Error('Declaration missing for virtual function.');\n    }\n};\n\n// usually directly assigned\n// getter for Closepath\nObject.defineProperty(segmentPrototype, 'end', {\n\n    configurable: true,\n\n    enumerable: true,\n\n    writable: true\n});\n\n// always a getter\n// always throws error for Moveto\nObject.defineProperty(segmentPrototype, 'start', {\n    // get a reference to the end point of previous segment\n\n    configurable: true,\n\n    enumerable: true,\n\n    get: function() {\n\n        if (!this.previousSegment) throw new Error('Missing previous segment. (This segment cannot be the first segment of a path; OR segment has not yet been added to a path.)');\n\n        return this.previousSegment.end;\n    }\n});\n\n// virtual\nObject.defineProperty(segmentPrototype, 'type', {\n\n    configurable: true,\n\n    enumerable: true,\n\n    get: function() {\n\n        throw new Error('Bad segment declaration. No type specified.');\n    }\n});\n\n// Path segment implementations:\nvar Lineto = function() {\n\n    var args = [];\n    var n = arguments.length;\n    for (var i = 0; i < n; i++) {\n        args.push(arguments[i]);\n    }\n\n    if (!(this instanceof Lineto)) { // switching context of `this` to Lineto when called without `new`\n        return applyToNew(Lineto, args);\n    }\n\n    if (n === 0) {\n        throw new Error('Lineto constructor expects a line, 1 point, or 2 coordinates (none provided).');\n    }\n\n    var outputArray;\n\n    if (args[0] instanceof Line) { // lines provided\n        if (n === 1) {\n            this.end = args[0].end.clone();\n            return this;\n\n        } else {\n            throw new Error('Lineto constructor expects a line, 1 point, or 2 coordinates (' + n + ' lines provided).');\n        }\n\n    } else if (typeof args[0] === 'string' || typeof args[0] === 'number') { // coordinates provided\n        if (n === 2) {\n            this.end = new Point(+args[0], +args[1]);\n            return this;\n\n        } else if (n < 2) {\n            throw new Error('Lineto constructor expects a line, 1 point, or 2 coordinates (' + n + ' coordinates provided).');\n\n        } else { // this is a poly-line segment\n            var segmentCoords;\n            outputArray = [];\n            for (i = 0; i < n; i += 2) { // coords come in groups of two\n\n                segmentCoords = args.slice(i, i + 2); // will send one coord if args.length not divisible by 2\n                outputArray.push(applyToNew(Lineto, segmentCoords));\n            }\n            return outputArray;\n        }\n\n    } else { // points provided (needs to be last to also cover plain objects with x and y)\n        if (n === 1) {\n            this.end = new Point(args[0]);\n            return this;\n\n        } else { // this is a poly-line segment\n            var segmentPoint;\n            outputArray = [];\n            for (i = 0; i < n; i += 1) {\n\n                segmentPoint = args[i];\n                outputArray.push(new Lineto(segmentPoint));\n            }\n            return outputArray;\n        }\n    }\n};\n\nvar linetoPrototype = {\n\n    clone: function() {\n\n        return new Lineto(this.end);\n    },\n\n    divideAt: function(ratio) {\n\n        var line = new Line(this.start, this.end);\n        var divided = line.divideAt(ratio);\n        return [\n            new Lineto(divided[0]),\n            new Lineto(divided[1])\n        ];\n    },\n\n    divideAtLength: function(length) {\n\n        var line = new Line(this.start, this.end);\n        var divided = line.divideAtLength(length);\n        return [\n            new Lineto(divided[0]),\n            new Lineto(divided[1])\n        ];\n    },\n\n    getSubdivisions: function() {\n\n        return [];\n    },\n\n    isDifferentiable: function() {\n\n        if (!this.previousSegment) return false;\n\n        return !this.start.equals(this.end);\n    },\n\n    round: function(precision) {\n\n        this.end.round(precision);\n        return this;\n    },\n\n    scale: function(sx, sy, origin) {\n\n        this.end.scale(sx, sy, origin);\n        return this;\n    },\n\n    serialize: function() {\n\n        var end = this.end;\n        return this.type + ' ' + end.x + ' ' + end.y;\n    },\n\n    toString: function() {\n\n        return this.type + ' ' + this.start + ' ' + this.end;\n    },\n\n    translate: function(tx, ty) {\n\n        this.end.translate(tx, ty);\n        return this;\n    }\n};\n\nObject.defineProperty(linetoPrototype, 'type', {\n\n    configurable: true,\n\n    enumerable: true,\n\n    value: 'L'\n});\n\nLineto.prototype = extend(segmentPrototype, Line.prototype, linetoPrototype);\n\nvar Curveto = function() {\n\n    var args = [];\n    var n = arguments.length;\n    for (var i = 0; i < n; i++) {\n        args.push(arguments[i]);\n    }\n\n    if (!(this instanceof Curveto)) { // switching context of `this` to Curveto when called without `new`\n        return applyToNew(Curveto, args);\n    }\n\n    if (n === 0) {\n        throw new Error('Curveto constructor expects a curve, 3 points, or 6 coordinates (none provided).');\n    }\n\n    var outputArray;\n\n    if (args[0] instanceof Curve) { // curves provided\n        if (n === 1) {\n            this.controlPoint1 = args[0].controlPoint1.clone();\n            this.controlPoint2 = args[0].controlPoint2.clone();\n            this.end = args[0].end.clone();\n            return this;\n\n        } else {\n            throw new Error('Curveto constructor expects a curve, 3 points, or 6 coordinates (' + n + ' curves provided).');\n        }\n\n    } else if (typeof args[0] === 'string' || typeof args[0] === 'number') { // coordinates provided\n        if (n === 6) {\n            this.controlPoint1 = new Point(+args[0], +args[1]);\n            this.controlPoint2 = new Point(+args[2], +args[3]);\n            this.end = new Point(+args[4], +args[5]);\n            return this;\n\n        } else if (n < 6) {\n            throw new Error('Curveto constructor expects a curve, 3 points, or 6 coordinates (' + n + ' coordinates provided).');\n\n        } else { // this is a poly-bezier segment\n            var segmentCoords;\n            outputArray = [];\n            for (i = 0; i < n; i += 6) { // coords come in groups of six\n\n                segmentCoords = args.slice(i, i + 6); // will send fewer than six coords if args.length not divisible by 6\n                outputArray.push(applyToNew(Curveto, segmentCoords));\n            }\n            return outputArray;\n        }\n\n    } else { // points provided (needs to be last to also cover plain objects with x and y)\n        if (n === 3) {\n            this.controlPoint1 = new Point(args[0]);\n            this.controlPoint2 = new Point(args[1]);\n            this.end = new Point(args[2]);\n            return this;\n\n        } else if (n < 3) {\n            throw new Error('Curveto constructor expects a curve, 3 points, or 6 coordinates (' + n + ' points provided).');\n\n        } else { // this is a poly-bezier segment\n            var segmentPoints;\n            outputArray = [];\n            for (i = 0; i < n; i += 3) { // points come in groups of three\n\n                segmentPoints = args.slice(i, i + 3); // will send fewer than three points if args.length is not divisible by 3\n                outputArray.push(applyToNew(Curveto, segmentPoints));\n            }\n            return outputArray;\n        }\n    }\n};\n\nvar curvetoPrototype = {\n\n    clone: function() {\n\n        return new Curveto(this.controlPoint1, this.controlPoint2, this.end);\n    },\n\n    divideAt: function(ratio, opt) {\n\n        var curve = new Curve(this.start, this.controlPoint1, this.controlPoint2, this.end);\n        var divided = curve.divideAt(ratio, opt);\n        return [\n            new Curveto(divided[0]),\n            new Curveto(divided[1])\n        ];\n    },\n\n    divideAtLength: function(length, opt) {\n\n        var curve = new Curve(this.start, this.controlPoint1, this.controlPoint2, this.end);\n        var divided = curve.divideAtLength(length, opt);\n        return [\n            new Curveto(divided[0]),\n            new Curveto(divided[1])\n        ];\n    },\n\n    divideAtT: function(t) {\n\n        var curve = new Curve(this.start, this.controlPoint1, this.controlPoint2, this.end);\n        var divided = curve.divideAtT(t);\n        return [\n            new Curveto(divided[0]),\n            new Curveto(divided[1])\n        ];\n    },\n\n    isDifferentiable: function() {\n\n        if (!this.previousSegment) return false;\n\n        var start = this.start;\n        var control1 = this.controlPoint1;\n        var control2 = this.controlPoint2;\n        var end = this.end;\n\n        return !(start.equals(control1) && control1.equals(control2) && control2.equals(end));\n    },\n\n    round: function(precision) {\n\n        this.controlPoint1.round(precision);\n        this.controlPoint2.round(precision);\n        this.end.round(precision);\n        return this;\n    },\n\n    scale: function(sx, sy, origin) {\n\n        this.controlPoint1.scale(sx, sy, origin);\n        this.controlPoint2.scale(sx, sy, origin);\n        this.end.scale(sx, sy, origin);\n        return this;\n    },\n\n    serialize: function() {\n\n        var c1 = this.controlPoint1;\n        var c2 = this.controlPoint2;\n        var end = this.end;\n        return this.type + ' ' + c1.x + ' ' + c1.y + ' ' + c2.x + ' ' + c2.y + ' ' + end.x + ' ' + end.y;\n    },\n\n    toString: function() {\n\n        return this.type + ' ' + this.start + ' ' + this.controlPoint1 + ' ' + this.controlPoint2 + ' ' + this.end;\n    },\n\n    translate: function(tx, ty) {\n\n        this.controlPoint1.translate(tx, ty);\n        this.controlPoint2.translate(tx, ty);\n        this.end.translate(tx, ty);\n        return this;\n    }\n};\n\nObject.defineProperty(curvetoPrototype, 'type', {\n\n    configurable: true,\n\n    enumerable: true,\n\n    value: 'C'\n});\n\nCurveto.prototype = extend(segmentPrototype, Curve.prototype, curvetoPrototype);\n\nvar Moveto = function() {\n\n    var args = [];\n    var n = arguments.length;\n    for (var i = 0; i < n; i++) {\n        args.push(arguments[i]);\n    }\n\n    if (!(this instanceof Moveto)) { // switching context of `this` to Moveto when called without `new`\n        return applyToNew(Moveto, args);\n    }\n\n    if (n === 0) {\n        throw new Error('Moveto constructor expects a line, a curve, 1 point, or 2 coordinates (none provided).');\n    }\n\n    var outputArray;\n\n    if (args[0] instanceof Line) { // lines provided\n        if (n === 1) {\n            this.end = args[0].end.clone();\n            return this;\n\n        } else {\n            throw new Error('Moveto constructor expects a line, a curve, 1 point, or 2 coordinates (' + n + ' lines provided).');\n        }\n\n    } else if (args[0] instanceof Curve) { // curves provided\n        if (n === 1) {\n            this.end = args[0].end.clone();\n            return this;\n\n        } else {\n            throw new Error('Moveto constructor expects a line, a curve, 1 point, or 2 coordinates (' + n + ' curves provided).');\n        }\n\n    } else if (typeof args[0] === 'string' || typeof args[0] === 'number') { // coordinates provided\n        if (n === 2) {\n            this.end = new Point(+args[0], +args[1]);\n            return this;\n\n        } else if (n < 2) {\n            throw new Error('Moveto constructor expects a line, a curve, 1 point, or 2 coordinates (' + n + ' coordinates provided).');\n\n        } else { // this is a moveto-with-subsequent-poly-line segment\n            var segmentCoords;\n            outputArray = [];\n            for (i = 0; i < n; i += 2) { // coords come in groups of two\n\n                segmentCoords = args.slice(i, i + 2); // will send one coord if args.length not divisible by 2\n                if (i === 0) outputArray.push(applyToNew(Moveto, segmentCoords));\n                else outputArray.push(applyToNew(Lineto, segmentCoords));\n            }\n            return outputArray;\n        }\n\n    } else { // points provided (needs to be last to also cover plain objects with x and y)\n        if (n === 1) {\n            this.end = new Point(args[0]);\n            return this;\n\n        } else { // this is a moveto-with-subsequent-poly-line segment\n            var segmentPoint;\n            outputArray = [];\n            for (i = 0; i < n; i += 1) { // points come one by one\n\n                segmentPoint = args[i];\n                if (i === 0) outputArray.push(new Moveto(segmentPoint));\n                else outputArray.push(new Lineto(segmentPoint));\n            }\n            return outputArray;\n        }\n    }\n};\n\nvar movetoPrototype = {\n\n    bbox: function() {\n\n        return null;\n    },\n\n    clone: function() {\n\n        return new Moveto(this.end);\n    },\n\n    closestPoint: function() {\n\n        return this.end.clone();\n    },\n\n    closestPointNormalizedLength: function() {\n\n        return 0;\n    },\n\n    closestPointLength: function() {\n\n        return 0;\n    },\n\n    closestPointT: function() {\n\n        return 1;\n    },\n\n    closestPointTangent: function() {\n\n        return null;\n    },\n\n    divideAt: function() {\n\n        return [\n            this.clone(),\n            this.clone()\n        ];\n    },\n\n    divideAtLength: function() {\n\n        return [\n            this.clone(),\n            this.clone()\n        ];\n    },\n\n    equals: function(m) {\n\n        return this.end.equals(m.end);\n    },\n\n    getSubdivisions: function() {\n\n        return [];\n    },\n\n    isDifferentiable: function() {\n\n        return false;\n    },\n\n    isSubpathStart: true,\n\n    isVisible: false,\n\n    length: function() {\n\n        return 0;\n    },\n\n    lengthAtT: function() {\n\n        return 0;\n    },\n\n    pointAt: function() {\n\n        return this.end.clone();\n    },\n\n    pointAtLength: function() {\n\n        return this.end.clone();\n    },\n\n    pointAtT: function() {\n\n        return this.end.clone();\n    },\n\n    round: function(precision) {\n\n        this.end.round(precision);\n        return this;\n    },\n\n    scale: function(sx, sy, origin) {\n\n        this.end.scale(sx, sy, origin);\n        return this;\n    },\n\n    serialize: function() {\n\n        var end = this.end;\n        return this.type + ' ' + end.x + ' ' + end.y;\n    },\n\n    tangentAt: function() {\n\n        return null;\n    },\n\n    tangentAtLength: function() {\n\n        return null;\n    },\n\n    tangentAtT: function() {\n\n        return null;\n    },\n\n    toString: function() {\n\n        return this.type + ' ' + this.end;\n    },\n\n    translate: function(tx, ty) {\n\n        this.end.translate(tx, ty);\n        return this;\n    }\n};\n\nObject.defineProperty(movetoPrototype, 'start', {\n\n    configurable: true,\n\n    enumerable: true,\n\n    get: function() {\n\n        throw new Error('Illegal access. Moveto segments should not need a start property.');\n    }\n});\n\nObject.defineProperty(movetoPrototype, 'type', {\n\n    configurable: true,\n\n    enumerable: true,\n\n    value: 'M'\n});\n\nMoveto.prototype = extend(segmentPrototype, movetoPrototype); // does not inherit from any other geometry object\n\nvar Closepath = function() {\n\n    var args = [];\n    var n = arguments.length;\n    for (var i = 0; i < n; i++) {\n        args.push(arguments[i]);\n    }\n\n    if (!(this instanceof Closepath)) { // switching context of `this` to Closepath when called without `new`\n        return applyToNew(Closepath, args);\n    }\n\n    if (n > 0) {\n        throw new Error('Closepath constructor expects no arguments.');\n    }\n\n    return this;\n};\n\nvar closepathPrototype = {\n\n    clone: function() {\n\n        return new Closepath();\n    },\n\n    divideAt: function(ratio) {\n\n        var line = new Line(this.start, this.end);\n        var divided = line.divideAt(ratio);\n        return [\n            // if we didn't actually cut into the segment, first divided part can stay as Z\n            (divided[1].isDifferentiable() ? new Lineto(divided[0]) : this.clone()),\n            new Lineto(divided[1])\n        ];\n    },\n\n    divideAtLength: function(length) {\n\n        var line = new Line(this.start, this.end);\n        var divided = line.divideAtLength(length);\n        return [\n            // if we didn't actually cut into the segment, first divided part can stay as Z\n            (divided[1].isDifferentiable() ? new Lineto(divided[0]) : this.clone()),\n            new Lineto(divided[1])\n        ];\n    },\n\n    getSubdivisions: function() {\n\n        return [];\n    },\n\n    isDifferentiable: function() {\n\n        if (!this.previousSegment || !this.subpathStartSegment) return false;\n\n        return !this.start.equals(this.end);\n    },\n\n    round: function() {\n\n        return this;\n    },\n\n    scale: function() {\n\n        return this;\n    },\n\n    serialize: function() {\n\n        return this.type;\n    },\n\n    toString: function() {\n\n        return this.type + ' ' + this.start + ' ' + this.end;\n    },\n\n    translate: function() {\n\n        return this;\n    }\n};\n\nObject.defineProperty(closepathPrototype, 'end', {\n    // get a reference to the end point of subpath start segment\n\n    configurable: true,\n\n    enumerable: true,\n\n    get: function() {\n\n        if (!this.subpathStartSegment) throw new Error('Missing subpath start segment. (This segment needs a subpath start segment (e.g. Moveto); OR segment has not yet been added to a path.)');\n\n        return this.subpathStartSegment.end;\n    }\n});\n\nObject.defineProperty(closepathPrototype, 'type', {\n\n    configurable: true,\n\n    enumerable: true,\n\n    value: 'Z'\n});\n\nClosepath.prototype = extend(segmentPrototype, Line.prototype, closepathPrototype);\n\nvar segmentTypes = Path.segmentTypes = {\n    L: Lineto,\n    C: Curveto,\n    M: Moveto,\n    Z: Closepath,\n    z: Closepath\n};\n\nPath.regexSupportedData = new RegExp('^[\\\\s\\\\d' + Object.keys(segmentTypes).join('') + ',.]*$');\n\nPath.isDataSupported = function(data) {\n\n    if (typeof data !== 'string') return false;\n    return this.regexSupportedData.test(data);\n};\n","import { Path } from './path.mjs';\nimport { Curve } from './curve.mjs';\nimport { Point } from './point.mjs';\n\nexport const bezier = {\n\n    // Cubic Bezier curve path through points.\n    // @deprecated\n    // @param {array} points Array of points through which the smooth line will go.\n    // @return {array} SVG Path commands as an array\n    curveThroughPoints: function(points) {\n\n        console.warn('deprecated');\n\n        return new Path(Curve.throughPoints(points)).serialize();\n    },\n\n    // Get open-ended Bezier Spline Control Points.\n    // @deprecated\n    // @param knots Input Knot Bezier spline points (At least two points!).\n    // @param firstControlPoints Output First Control points. Array of knots.length - 1 length.\n    // @param secondControlPoints Output Second Control points. Array of knots.length - 1 length.\n    getCurveControlPoints: function(knots) {\n\n        console.warn('deprecated');\n\n        var firstControlPoints = [];\n        var secondControlPoints = [];\n        var n = knots.length - 1;\n        var i;\n\n        // Special case: Bezier curve should be a straight line.\n        if (n == 1) {\n            // 3P1 = 2P0 + P3\n            firstControlPoints[0] = new Point(\n                (2 * knots[0].x + knots[1].x) / 3,\n                (2 * knots[0].y + knots[1].y) / 3\n            );\n\n            // P2 = 2P1 – P0\n            secondControlPoints[0] = new Point(\n                2 * firstControlPoints[0].x - knots[0].x,\n                2 * firstControlPoints[0].y - knots[0].y\n            );\n\n            return [firstControlPoints, secondControlPoints];\n        }\n\n        // Calculate first Bezier control points.\n        // Right hand side vector.\n        var rhs = [];\n\n        // Set right hand side X values.\n        for (i = 1; i < n - 1; i++) {\n            rhs[i] = 4 * knots[i].x + 2 * knots[i + 1].x;\n        }\n\n        rhs[0] = knots[0].x + 2 * knots[1].x;\n        rhs[n - 1] = (8 * knots[n - 1].x + knots[n].x) / 2.0;\n\n        // Get first control points X-values.\n        var x = this.getFirstControlPoints(rhs);\n\n        // Set right hand side Y values.\n        for (i = 1; i < n - 1; ++i) {\n            rhs[i] = 4 * knots[i].y + 2 * knots[i + 1].y;\n        }\n\n        rhs[0] = knots[0].y + 2 * knots[1].y;\n        rhs[n - 1] = (8 * knots[n - 1].y + knots[n].y) / 2.0;\n\n        // Get first control points Y-values.\n        var y = this.getFirstControlPoints(rhs);\n\n        // Fill output arrays.\n        for (i = 0; i < n; i++) {\n            // First control point.\n            firstControlPoints.push(new Point(x[i], y[i]));\n\n            // Second control point.\n            if (i < n - 1) {\n                secondControlPoints.push(new Point(\n                    2 * knots [i + 1].x - x[i + 1],\n                    2 * knots[i + 1].y - y[i + 1]\n                ));\n\n            } else {\n                secondControlPoints.push(new Point(\n                    (knots[n].x + x[n - 1]) / 2,\n                    (knots[n].y + y[n - 1]) / 2)\n                );\n            }\n        }\n\n        return [firstControlPoints, secondControlPoints];\n    },\n\n    // Divide a Bezier curve into two at point defined by value 't' <0,1>.\n    // Using deCasteljau algorithm. http://math.stackexchange.com/a/317867\n    // @deprecated\n    // @param control points (start, control start, control end, end)\n    // @return a function that accepts t and returns 2 curves.\n    getCurveDivider: function(p0, p1, p2, p3) {\n\n        console.warn('deprecated');\n\n        var curve = new Curve(p0, p1, p2, p3);\n\n        return function divideCurve(t) {\n\n            var divided = curve.divide(t);\n\n            return [{\n                p0: divided[0].start,\n                p1: divided[0].controlPoint1,\n                p2: divided[0].controlPoint2,\n                p3: divided[0].end\n            }, {\n                p0: divided[1].start,\n                p1: divided[1].controlPoint1,\n                p2: divided[1].controlPoint2,\n                p3: divided[1].end\n            }];\n        };\n    },\n\n    // Solves a tridiagonal system for one of coordinates (x or y) of first Bezier control points.\n    // @deprecated\n    // @param rhs Right hand side vector.\n    // @return Solution vector.\n    getFirstControlPoints: function(rhs) {\n\n        console.warn('deprecated');\n\n        var n = rhs.length;\n        // `x` is a solution vector.\n        var x = [];\n        var tmp = [];\n        var b = 2.0;\n\n        x[0] = rhs[0] / b;\n\n        // Decomposition and forward substitution.\n        for (var i = 1; i < n; i++) {\n            tmp[i] = 1 / b;\n            b = (i < n - 1 ? 4.0 : 3.5) - tmp[i];\n            x[i] = (rhs[i] - x[i - 1]) / b;\n        }\n\n        for (i = 1; i < n; i++) {\n            // Backsubstitution.\n            x[n - i - 1] -= tmp[n - i] * x[n - i];\n        }\n\n        return x;\n    },\n\n    // Solves an inversion problem -- Given the (x, y) coordinates of a point which lies on\n    // a parametric curve x = x(t)/w(t), y = y(t)/w(t), find the parameter value t\n    // which corresponds to that point.\n    // @deprecated\n    // @param control points (start, control start, control end, end)\n    // @return a function that accepts a point and returns t.\n    getInversionSolver: function(p0, p1, p2, p3) {\n\n        console.warn('deprecated');\n\n        var curve = new Curve(p0, p1, p2, p3);\n\n        return function solveInversion(p) {\n\n            return curve.closestPointT(p);\n        };\n    }\n};\n","import { Point } from './point.mjs';\nimport { Polyline } from './polyline.mjs';\nimport { extend } from './extend.mjs';\nimport { types } from './types.mjs';\nimport { clonePoints, parsePoints, convexHull } from './points.mjs';\n\nexport const Polygon = function(points) {\n\n    if (!(this instanceof Polygon)) {\n        return new Polygon(points);\n    }\n\n    if (typeof points === 'string') {\n        return new Polygon.parse(points);\n    }\n\n    this.points = (Array.isArray(points) ? points.map(Point) : []);\n};\n\nPolygon.parse = function(svgString) {\n    return new Polygon(parsePoints(svgString));\n};\n\nPolygon.fromRect = function(rect) {\n    return new Polygon([\n        rect.topLeft(),\n        rect.topRight(),\n        rect.bottomRight(),\n        rect.bottomLeft()\n    ]);\n};\n\nPolygon.prototype = extend(Polyline.prototype, {\n\n    type: types.Polygon,\n\n    clone: function() {\n        return new Polygon(clonePoints(this.points));\n    },\n\n    convexHull: function() {\n        return new Polygon(convexHull(this.points));\n    },\n\n    lengthPoints: function() {\n        const { start, end, points } = this;\n        if (points.length <= 1 || start.equals(end)) return points;\n        return [...points, start.clone()];\n    }\n\n});\n","import { Line } from './line.mjs';\nimport { Polygon } from './polygon.mjs';\nimport { Rect } from './rect.mjs';\nimport { types } from './types.mjs';\n\nexport function exists(shape1, shape2, shape1opt, shape2opt) {\n    switch (shape1.type) {\n        case types.Line: {\n            switch (shape2.type) {\n                case types.Line: {\n                    return lineWithLine(shape1, shape2);\n                }\n            }\n            break;\n        }\n        case types.Ellipse: {\n            switch (shape2.type) {\n                case types.Line: {\n                    return ellipseWithLine(shape1, shape2);\n                }\n                case types.Ellipse: {\n                    return ellipseWithEllipse(shape1, shape2);\n                }\n            }\n            break;\n        }\n        case types.Rect: {\n            switch (shape2.type) {\n                case types.Line: {\n                    return rectWithLine(shape1, shape2);\n                }\n                case types.Ellipse: {\n                    return rectWithEllipse(shape1, shape2);\n                }\n                case types.Rect: {\n                    return rectWithRect(shape1, shape2);\n                }\n            }\n            break;\n        }\n        case types.Polyline: {\n            switch (shape2.type) {\n                case types.Line: {\n                    return polylineWithLine(shape1, shape2);\n                }\n                case types.Ellipse: {\n                    return polylineWithEllipse(shape1, shape2);\n                }\n                case types.Rect: {\n                    return polylineWithRect(shape1, shape2);\n                }\n                case types.Polyline: {\n                    return polylineWithPolyline(shape1, shape2);\n                }\n            }\n            break;\n        }\n        case types.Polygon: {\n            switch (shape2.type) {\n                case types.Line: {\n                    return polygonWithLine(shape1, shape2);\n                }\n                case types.Ellipse: {\n                    return polygonWithEllipse(shape1, shape2);\n                }\n                case types.Rect: {\n                    return polygonWithRect(shape1, shape2);\n                }\n                case types.Polyline: {\n                    return polygonWithPolyline(shape1, shape2);\n                }\n                case types.Polygon: {\n                    return polygonWithPolygon(shape1, shape2);\n                }\n            }\n            break;\n        }\n        case types.Path: {\n            switch (shape2.type) {\n                case types.Line: {\n                    return pathWithLine(shape1, shape2, shape1opt);\n                }\n                case types.Ellipse: {\n                    return pathWithEllipse(shape1, shape2, shape1opt);\n                }\n                case types.Rect: {\n                    return pathWithRect(shape1, shape2, shape1opt);\n                }\n                case types.Polyline: {\n                    return pathWithPolyline(shape1, shape2, shape1opt);\n                }\n                case types.Polygon: {\n                    return pathWithPolygon(shape1, shape2, shape1opt);\n                }\n                case types.Path: {\n                    return pathWithPath(shape1, shape2, shape1opt, shape2opt);\n                }\n            }\n            break;\n        }\n    }\n    // None of the cases above\n    switch (shape2.type) {\n        case types.Ellipse:\n        case types.Rect:\n        case types.Polyline:\n        case types.Polygon:\n        case types.Path: {\n            return exists(shape2, shape1, shape2opt, shape1opt);\n        }\n        default: {\n            throw Error(`The intersection for ${shape1} and ${shape2} could not be found.`);\n        }\n    }\n}\n\n/* Line */\n\nexport function lineWithLine(line1, line2) {\n    const x1 = line1.start.x;\n    const y1 = line1.start.y;\n    const x2 = line1.end.x;\n    const y2 = line1.end.y;\n    const x3 = line2.start.x;\n    const y3 = line2.start.y;\n    const x4 = line2.end.x;\n    const y4 = line2.end.y;\n    const s1x = x2 - x1;\n    const s1y = y2 - y1;\n    const s2x = x4 - x3;\n    const s2y = y4 - y3;\n    const s3x = x1 - x3;\n    const s3y = y1 - y3;\n    const p = s1x * s2y - s2x * s1y;\n    const s = (s1x * s3y - s1y * s3x) / p;\n    const t = (s2x * s3y - s2y * s3x) / p;\n    return s >= 0 && s <= 1 && t >= 0 && t <= 1;\n}\n\n/* Ellipse */\n\nexport function ellipseWithLine(ellipse, line) {\n    const rex = ellipse.a;\n    const rey = ellipse.b;\n    const xe = ellipse.x;\n    const ye = ellipse.y;\n    const x1 = line.start.x - xe;\n    const x2 = line.end.x - xe;\n    const y1 = line.start.y - ye;\n    const y2 = line.end.y - ye;\n    const rex_2 = rex * rex;\n    const rey_2 = rey * rey;\n    const dx = x2 - x1;\n    const dy = y2 - y1;\n    const A = dx * dx / rex_2 + dy * dy / rey_2;\n    const B = 2 * x1 * dx / rex_2 + 2 * y1 * dy / rey_2;\n    const C = x1 * x1 / rex_2 + y1 * y1 / rey_2 - 1;\n    const D = B * B - 4 * A * C;\n    if (D === 0) {\n        const t = -B / 2 / A;\n        return t >= 0 && t <= 1;\n    } else if (D > 0) {\n        const sqrt = Math.sqrt(D);\n        const t1 = (-B + sqrt) / 2 / A;\n        const t2 = (-B - sqrt) / 2 / A;\n        return (t1 >= 0 && t1 <= 1) || (t2 >= 0 && t2 <= 1);\n    }\n    return false;\n}\n\nexport function ellipseWithEllipse(ellipse1, ellipse2) {\n    return _ellipsesIntersection(ellipse1, 0, ellipse2, 0);\n}\n\n/* Rect */\n\nexport function rectWithLine(rect, line) {\n    const { start, end } = line;\n    const { x, y, width, height } = rect;\n    if (\n        (start.x > x + width && end.x > x + width)\n        || (start.x < x && end.x < x)\n        || (start.y > y + height && end.y > y + height)\n        || (start.y < y && end.y < y)\n    ) {\n        return false;\n    }\n    if (rect.containsPoint(line.start) || rect.containsPoint(line.end)) {\n        return true;\n    }\n    return lineWithLine(rect.topLine(), line)\n        || lineWithLine(rect.rightLine(), line)\n        || lineWithLine(rect.bottomLine(), line)\n        || lineWithLine(rect.leftLine(), line);\n}\n\nexport function rectWithEllipse(rect, ellipse) {\n    if (!rectWithRect(rect, Rect.fromEllipse(ellipse))) return false;\n    return polygonWithEllipse(Polygon.fromRect(rect), ellipse);\n}\n\nexport function rectWithRect(rect1, rect2) {\n    return rect1.x < rect2.x + rect2.width\n        && rect1.x + rect1.width > rect2.x\n        && rect1.y < rect2.y + rect2.height\n        && rect1.y + rect1.height > rect2.y;\n}\n\n/* Polyline */\n\nexport function polylineWithLine(polyline, line) {\n    return _polylineWithLine(polyline, line, { interior: false });\n}\n\nexport function polylineWithEllipse(polyline, ellipse) {\n    return _polylineWithEllipse(polyline, ellipse, { interior: false });\n}\n\nexport function polylineWithRect(polyline, rect) {\n    return _polylineWithRect(polyline, rect, { interior: false });\n}\n\nexport function polylineWithPolyline(polyline1, polyline2) {\n    return _polylineWithPolyline(polyline1, polyline2, { interior: false });\n}\n\n/* Polygon */\n\nexport function polygonWithLine(polygon, line) {\n    return _polylineWithLine(polygon, line, { interior: true });\n}\n\nexport function polygonWithEllipse(polygon, ellipse) {\n    return _polylineWithEllipse(polygon, ellipse, { interior: true });\n}\n\nexport function polygonWithRect(polygon, rect) {\n    return _polylineWithRect(polygon, rect, { interior: true });\n}\n\nexport function polygonWithPolyline(polygon, polyline) {\n    return _polylineWithPolyline(polygon, polyline, { interior: true });\n}\n\nexport function polygonWithPolygon(polygon1, polygon2) {\n    return _polylineWithPolygon(polygon1, polygon2, { interior: true });\n}\n\n/* Path */\n\nexport function pathWithLine(path, line, pathOpt) {\n    return path.getSubpaths().some(subpath => {\n        const [polyline] = subpath.toPolylines(pathOpt);\n        const { type } = subpath.getSegment(-1);\n        if (type === 'Z') {\n            return polygonWithLine(polyline, line);\n        } else {\n            return polylineWithLine(polyline, line);\n        }\n    });\n}\n\nexport function pathWithEllipse(path, ellipse, pathOpt) {\n    return path.getSubpaths().some(subpath => {\n        const [polyline] = subpath.toPolylines(pathOpt);\n        const { type } = subpath.getSegment(-1);\n        if (type === 'Z') {\n            return polygonWithEllipse(polyline, ellipse);\n        } else {\n            return polylineWithEllipse(polyline, ellipse);\n        }\n    });\n}\n\nexport function pathWithRect(path, rect, pathOpt) {\n    return pathWithPolygon(path, Polygon.fromRect(rect), pathOpt);\n}\n\nexport function pathWithPolyline(path, polyline, pathOpt) {\n    return _pathWithPolyline(path, polyline, pathOpt, { interior: false });\n}\n\nexport function pathWithPolygon(path, polygon, pathOpt) {\n    return _pathWithPolyline(path, polygon, pathOpt, { interior: true });\n}\n\nexport function pathWithPath(path1, path2, pathOpt1, pathOpt2) {\n    return path1.getSubpaths().some(subpath => {\n        const [polyline1] = subpath.toPolylines(pathOpt1);\n        const { type } = subpath.getSegment(-1);\n        if (type === 'Z') {\n            return pathWithPolygon(path2, polyline1, pathOpt2);\n        } else {\n            return pathWithPolyline(path2, polyline1, pathOpt2);\n        }\n    });\n}\n\nfunction _polylineWithLine(polyline, line, opt = {}) {\n    const { interior = false } = opt;\n    let thisPoints;\n    if (interior) {\n        if (polyline.containsPoint(line.start)) {\n            // If any point of the polyline lies inside this polygon (interior = true)\n            // there is an intersection (we've chosen the start point)\n            return true;\n        }\n        const { start, end, points } = polyline;\n        thisPoints = end.equals(start) ? points : [...points, start];\n    } else {\n        thisPoints = polyline.points;\n    }\n    const { length } = thisPoints;\n    const segment = new Line();\n    for (let i = 0; i < length - 1; i++) {\n        segment.start = thisPoints[i];\n        segment.end = thisPoints[i + 1];\n        if (lineWithLine(line, segment)) {\n            return true;\n        }\n    }\n    return false;\n}\n\nfunction _polylineWithEllipse(polyline, ellipse, opt = {}) {\n    const { start, end, points } = polyline;\n    if (ellipse.containsPoint(start)) {\n        return true;\n    }\n    let thisPoints;\n    const { interior = false } = opt;\n    if (interior) {\n        if (polyline.containsPoint(ellipse.center())) {\n            // If any point of the ellipse lies inside this polygon (interior = true)\n            // there is an intersection (we've chosen the center point)\n            return true;\n        }\n        thisPoints = end.equals(start) ? points : [...points, start];\n    } else {\n        thisPoints = points;\n    }\n\n    const { length } = thisPoints;\n    const segment = new Line();\n    for (let i = 0; i < length - 1; i++) {\n        segment.start = thisPoints[i];\n        segment.end = thisPoints[i + 1];\n        if (ellipseWithLine(ellipse, segment)) {\n            return true;\n        }\n    }\n    return false;\n}\n\nfunction _polylineWithRect(polyline, rect, opt) {\n    const polygon = Polygon.fromRect(rect);\n    return _polylineWithPolygon(polyline, polygon, opt);\n}\n\nfunction _pathWithPolyline(path, polyline1, pathOpt, opt) {\n    return path.getSubpaths().some(subpath => {\n        const [polyline2] = subpath.toPolylines(pathOpt);\n        const { type } = subpath.getSegment(-1);\n        if (type === 'Z') {\n            return _polylineWithPolygon(polyline1, polyline2, opt);\n        } else {\n            return _polylineWithPolyline(polyline1, polyline2, opt);\n        }\n    });\n}\n\nfunction _polylineWithPolyline(polyline1, polyline2, opt = {}) {\n    const { interior = false } = opt;\n    let thisPolyline;\n    if (interior) {\n        const { start } = polyline2;\n        if (polyline1.containsPoint(start)) {\n            // If any point of the polyline lies inside this polygon (interior = true)\n            // there is an intersection (we've chosen the start point)\n            return true;\n        }\n        thisPolyline = polyline1.clone().close();\n    } else {\n        thisPolyline = polyline1;\n    }\n    const otherPoints = polyline2.points;\n    const { length } = otherPoints;\n    const segment = new Line();\n    for (let i = 0; i < length - 1; i++) {\n        segment.start = otherPoints[i];\n        segment.end = otherPoints[i + 1];\n        if (polylineWithLine(thisPolyline, segment)) {\n            return true;\n        }\n    }\n    return false;\n}\n\nfunction _polylineWithPolygon(polyline, polygon, opt) {\n    return polygon.containsPoint(polyline.start) || _polylineWithPolyline(polyline, polygon.clone().close(), opt);\n}\n\nfunction _ellipsesIntersection(e1, w1, e2, w2) {\n    const { cos, sin } = Math;\n    const sinW1 = sin(w1);\n    const cosW1 = cos(w1);\n    const sinW2 = sin(w2);\n    const cosW2 = cos(w2);\n    const sinW1s = sinW1 * sinW1;\n    const cosW1s = cosW1 * cosW1;\n    const sinCos1 = sinW1 * cosW1;\n    const sinW2s = sinW2 * sinW2;\n    const cosW2s = cosW2 * cosW2;\n    const sinCos2 = sinW2 * cosW2;\n    const a1s = e1.a * e1.a;\n    const b1s = e1.b * e1.b;\n    const a2s = e2.a * e2.a;\n    const b2s = e2.b * e2.b;\n    const A1 = a1s * sinW1s + b1s * cosW1s;\n    const A2 = a2s * sinW2s + b2s * cosW2s;\n    const B1 = a1s * cosW1s + b1s * sinW1s;\n    const B2 = a2s * cosW2s + b2s * sinW2s;\n    let C1 = 2 * (b1s - a1s) * sinCos1;\n    let C2 = 2 * (b2s - a2s) * sinCos2;\n    let D1 = (-2 * A1 * e1.x - C1 * e1.y);\n    let D2 = (-2 * A2 * e2.x - C2 * e2.y);\n    let E1 = (-C1 * e1.x - 2 * B1 * e1.y);\n    let E2 = (-C2 * e2.x - 2 * B2 * e2.y);\n    const F1 = A1 * e1.x * e1.x + B1 * e1.y * e1.y + C1 * e1.x * e1.y - a1s * b1s;\n    const F2 = A2 * e2.x * e2.x + B2 * e2.y * e2.y + C2 * e2.x * e2.y - a2s * b2s;\n\n    C1 = C1 / 2;\n    C2 = C2 / 2;\n    D1 = D1 / 2;\n    D2 = D2 / 2;\n    E1 = E1 / 2;\n    E2 = E2 / 2;\n\n    const l3 = det3([\n        [A1, C1, D1],\n        [C1, B1, E1],\n        [D1, E1, F1]\n    ]);\n    const l0 = det3([\n        [A2, C2, D2],\n        [C2, B2, E2],\n        [D2, E2, F2]\n    ]);\n    const l2 = 0.33333333 * (det3([\n        [A2, C1, D1],\n        [C2, B1, E1],\n        [D2, E1, F1]\n    ]) + det3([\n        [A1, C2, D1],\n        [C1, B2, E1],\n        [D1, E2, F1]\n    ]) + det3([\n        [A1, C1, D2],\n        [C1, B1, E2],\n        [D1, E1, F2]\n    ]));\n    const l1 = 0.33333333 * (det3([\n        [A1, C2, D2],\n        [C1, B2, E2],\n        [D1, E2, F2]\n    ]) + det3([\n        [A2, C1, D2],\n        [C2, B1, E2],\n        [D2, E1, F2]\n    ]) + det3([\n        [A2, C2, D1],\n        [C2, B2, E1],\n        [D2, E2, F1]\n    ]));\n\n    const delta1 = det2([\n        [l3, l2],\n        [l2, l1]\n    ]);\n    const delta2 = det2([\n        [l3, l1],\n        [l2, l0]\n    ]);\n    const delta3 = det2([\n        [l2, l1],\n        [l1, l0]\n    ]);\n\n    const dP = det2([\n        [2 * delta1, delta2],\n        [delta2, 2 * delta3]\n    ]);\n\n    if (dP > 0 && (l1 > 0 || l2 > 0)) {\n        return false;\n    }\n    return true;\n}\n\nfunction det2(m) {\n    return m[0][0] * m[1][1] - m[0][1] * m[1][0];\n}\n\nfunction det3(m) {\n    return m[0][0] * m[1][1] * m[2][2] -\n        m[0][0] * m[1][2] * m[2][1] -\n        m[0][1] * m[1][0] * m[2][2] +\n        m[0][1] * m[1][2] * m[2][0] +\n        m[0][2] * m[1][0] * m[2][1] -\n        m[0][2] * m[1][1] * m[2][0];\n}\n","// Geometry library.\n// -----------------\n\nexport * from './geometry.helpers.mjs';\nexport * from './bezier.mjs';\nexport * from './curve.mjs';\nexport * from './ellipse.mjs';\nexport * from './line.mjs';\nexport * from './path.mjs';\nexport * from './point.mjs';\nexport * from './polyline.mjs';\nexport * from './polygon.mjs';\nexport * from './rect.mjs';\nexport * from './types.mjs';\n\nimport * as _intersection from './intersection.mjs';\nexport const intersection = _intersection;\n","// Vectorizer.\n// -----------\n\n// A tiny library for making your life easier when dealing with SVG.\n// The only Vectorizer dependency is the Geometry library.\n\nimport * as g from '../g/index.mjs';\n\nconst V = (function() {\n\n    var hasSvg = typeof window === 'object' && !!window.SVGAngle;\n\n    // SVG support is required.\n    if (!hasSvg) {\n\n        // Return a function that throws an error when it is used.\n        return function() {\n            throw new Error('SVG is required to use Vectorizer.');\n        };\n    }\n\n    // XML namespaces.\n    var ns = {\n        svg: 'http://www.w3.org/2000/svg',\n        xmlns: 'http://www.w3.org/2000/xmlns/',\n        xml: 'http://www.w3.org/XML/1998/namespace',\n        xlink: 'http://www.w3.org/1999/xlink',\n        xhtml: 'http://www.w3.org/1999/xhtml'\n    };\n\n    var SVGVersion = '1.1';\n\n    // Declare shorthands to the most used math functions.\n    var math = Math;\n    var PI = math.PI;\n    var atan2 = math.atan2;\n    var sqrt = math.sqrt;\n    var min = math.min;\n    var max = math.max;\n    var cos = math.cos;\n    var sin = math.sin;\n\n    var V = function(el, attrs, children) {\n\n        // This allows using V() without the new keyword.\n        if (!(this instanceof V)) {\n            return V.apply(Object.create(V.prototype), arguments);\n        }\n\n        if (!el) return;\n\n        if (V.isV(el)) {\n            el = el.node;\n        }\n\n        attrs = attrs || {};\n\n        if (V.isString(el)) {\n\n            el = el.trim();\n\n            if (el.toLowerCase() === 'svg') {\n\n                // Create a new SVG canvas.\n                el = V.createSvgDocument();\n\n            } else if (el[0] === '<') {\n\n                // Create element from an SVG string.\n                // Allows constructs of type: `document.appendChild(V('<rect></rect>').node)`.\n\n                var svgDoc = V.createSvgDocument(el);\n\n                // Note that `V()` might also return an array should the SVG string passed as\n                // the first argument contain more than one root element.\n                if (svgDoc.childNodes.length > 1) {\n\n                    // Map child nodes to `V`s.\n                    var arrayOfVels = [];\n                    var i, len;\n\n                    for (i = 0, len = svgDoc.childNodes.length; i < len; i++) {\n\n                        var childNode = svgDoc.childNodes[i];\n                        arrayOfVels.push(new V(document.importNode(childNode, true)));\n                    }\n\n                    return arrayOfVels;\n                }\n\n                el = document.importNode(svgDoc.firstChild, true);\n\n            } else {\n\n                el = document.createElementNS(ns.svg, el);\n            }\n\n            V.ensureId(el);\n        }\n\n        this.node = el;\n\n        this.setAttributes(attrs);\n\n        if (children) {\n            this.append(children);\n        }\n\n        return this;\n    };\n\n    var VPrototype = V.prototype;\n\n    Object.defineProperty(VPrototype, 'id', {\n        enumerable: true,\n        get: function() {\n            return this.node.id;\n        },\n        set: function(id) {\n            this.node.id = id;\n        }\n    });\n\n    /**\n     * @param {SVGGElement} toElem\n     * @returns {SVGMatrix}\n     */\n    VPrototype.getTransformToElement = function(target) {\n        var node = this.node;\n        if (V.isSVGGraphicsElement(target) && V.isSVGGraphicsElement(node)) {\n            var targetCTM = V.toNode(target).getScreenCTM();\n            var nodeCTM = node.getScreenCTM();\n            if (targetCTM && nodeCTM) {\n                return targetCTM.inverse().multiply(nodeCTM);\n            }\n        }\n        // Could not get actual transformation matrix\n        return V.createSVGMatrix();\n    };\n\n    /**\n     * @param {SVGMatrix} matrix\n     * @param {Object=} opt\n     * @returns {Vectorizer|SVGMatrix} Setter / Getter\n     */\n    VPrototype.transform = function(matrix, opt) {\n\n        var node = this.node;\n        if (V.isUndefined(matrix)) {\n            return V.transformStringToMatrix(this.attr('transform'));\n        }\n\n        if (opt && opt.absolute) {\n            return this.attr('transform', V.matrixToTransformString(matrix));\n        }\n\n        var svgTransform = V.createSVGTransform(matrix);\n        node.transform.baseVal.appendItem(svgTransform);\n        return this;\n    };\n\n    VPrototype.translate = function(tx, ty, opt) {\n\n        opt = opt || {};\n        ty = ty || 0;\n\n        var transformAttr = this.attr('transform') || '';\n        var transform = V.parseTransformString(transformAttr);\n        transformAttr = transform.value;\n        // Is it a getter?\n        if (V.isUndefined(tx)) {\n            return transform.translate;\n        }\n\n        transformAttr = transformAttr.replace(/translate\\([^)]*\\)/g, '').trim();\n\n        var newTx = opt.absolute ? tx : transform.translate.tx + tx;\n        var newTy = opt.absolute ? ty : transform.translate.ty + ty;\n        var newTranslate = 'translate(' + newTx + ',' + newTy + ')';\n\n        // Note that `translate()` is always the first transformation. This is\n        // usually the desired case.\n        this.attr('transform', (newTranslate + ' ' + transformAttr).trim());\n        return this;\n    };\n\n    VPrototype.rotate = function(angle, cx, cy, opt) {\n\n        opt = opt || {};\n\n        var transformAttr = this.attr('transform') || '';\n        var transform = V.parseTransformString(transformAttr);\n        transformAttr = transform.value;\n\n        // Is it a getter?\n        if (V.isUndefined(angle)) {\n            return transform.rotate;\n        }\n\n        transformAttr = transformAttr.replace(/rotate\\([^)]*\\)/g, '').trim();\n\n        angle %= 360;\n\n        var newAngle = opt.absolute ? angle : transform.rotate.angle + angle;\n        var newOrigin = (cx !== undefined && cy !== undefined) ? ',' + cx + ',' + cy : '';\n        var newRotate = 'rotate(' + newAngle + newOrigin + ')';\n\n        this.attr('transform', (transformAttr + ' ' + newRotate).trim());\n        return this;\n    };\n\n    // Note that `scale` as the only transformation does not combine with previous values.\n    VPrototype.scale = function(sx, sy) {\n\n        sy = V.isUndefined(sy) ? sx : sy;\n\n        var transformAttr = this.attr('transform') || '';\n        var transform = V.parseTransformString(transformAttr);\n        transformAttr = transform.value;\n\n        // Is it a getter?\n        if (V.isUndefined(sx)) {\n            return transform.scale;\n        }\n\n        transformAttr = transformAttr.replace(/scale\\([^)]*\\)/g, '').trim();\n\n        var newScale = 'scale(' + sx + ',' + sy + ')';\n\n        this.attr('transform', (transformAttr + ' ' + newScale).trim());\n        return this;\n    };\n\n    // Get SVGRect that contains coordinates and dimension of the real bounding box,\n    // i.e. after transformations are applied.\n    // If `target` is specified, bounding box will be computed relatively to `target` element.\n    VPrototype.bbox = function(withoutTransformations, target) {\n\n        var box;\n        var node = this.node;\n        var ownerSVGElement = node.ownerSVGElement;\n\n        // If the element is not in the live DOM, it does not have a bounding box defined and\n        // so fall back to 'zero' dimension element.\n        if (!ownerSVGElement) {\n            return new g.Rect(0, 0, 0, 0);\n        }\n\n        try {\n\n            box = node.getBBox();\n\n        } catch (e) {\n\n            // Fallback for IE.\n            box = {\n                x: node.clientLeft,\n                y: node.clientTop,\n                width: node.clientWidth,\n                height: node.clientHeight\n            };\n        }\n\n        if (withoutTransformations) {\n            return new g.Rect(box);\n        }\n\n        var matrix = this.getTransformToElement(target || ownerSVGElement);\n\n        return V.transformRect(box, matrix);\n    };\n\n    // Returns an SVGRect that contains coordinates and dimensions of the real bounding box,\n    // i.e. after transformations are applied.\n    // Fixes a browser implementation bug that returns incorrect bounding boxes for groups of svg elements.\n    // Takes an (Object) `opt` argument (optional) with the following attributes:\n    // (Object) `target` (optional): if not undefined, transform bounding boxes relative to `target`; if undefined, transform relative to this\n    // (Boolean) `recursive` (optional): if true, recursively enter all groups and get a union of element bounding boxes (svg bbox fix); if false or undefined, return result of native function this.node.getBBox();\n    VPrototype.getBBox = function(opt) {\n\n        var options = {};\n\n        var outputBBox;\n        var node = this.node;\n        var ownerSVGElement = node.ownerSVGElement;\n\n        // If the element is not in the live DOM, it does not have a bounding box defined and\n        // so fall back to 'zero' dimension element.\n        // If the element is not an SVGGraphicsElement, we could not measure the bounding box either\n        if (!ownerSVGElement || !V.isSVGGraphicsElement(node)) {\n            return new g.Rect(0, 0, 0, 0);\n        }\n\n        if (opt) {\n            if (opt.target) { // check if target exists\n                options.target = V.toNode(opt.target); // works for V objects, jquery objects, and node objects\n            }\n            if (opt.recursive) {\n                options.recursive = opt.recursive;\n            }\n        }\n\n        if (!options.recursive) {\n            try {\n                outputBBox = node.getBBox();\n            } catch (e) {\n                // Fallback for IE.\n                outputBBox = {\n                    x: node.clientLeft,\n                    y: node.clientTop,\n                    width: node.clientWidth,\n                    height: node.clientHeight\n                };\n            }\n\n            if (!options.target) {\n                // transform like this (that is, not at all)\n                return new g.Rect(outputBBox);\n            } else {\n                // transform like target\n                var matrix = this.getTransformToElement(options.target);\n                return V.transformRect(outputBBox, matrix);\n            }\n        } else { // if we want to calculate the bbox recursively\n            // browsers report correct bbox around svg elements (one that envelops the path lines tightly)\n            // but some browsers fail to report the same bbox when the elements are in a group (returning a looser bbox that also includes control points, like node.getClientRect())\n            // this happens even if we wrap a single svg element into a group!\n            // this option setting makes the function recursively enter all the groups from this and deeper, get bboxes of the elements inside, then return a union of those bboxes\n\n            var children = this.children();\n            var n = children.length;\n\n            if (n === 0) {\n                return this.getBBox({ target: options.target, recursive: false });\n            }\n\n            // recursion's initial pass-through setting:\n            // recursive passes-through just keep the target as whatever was set up here during the initial pass-through\n            if (!options.target) {\n                // transform children/descendants like this (their parent/ancestor)\n                options.target = this;\n            } // else transform children/descendants like target\n\n            for (var i = 0; i < n; i++) {\n                var currentChild = children[i];\n\n                var childBBox;\n\n                // if currentChild is not a group element, get its bbox with a nonrecursive call\n                if (currentChild.children().length === 0) {\n                    childBBox = currentChild.getBBox({ target: options.target, recursive: false });\n                } else {\n                    // if currentChild is a group element (determined by checking the number of children), enter it with a recursive call\n                    childBBox = currentChild.getBBox({ target: options.target, recursive: true });\n                }\n\n                if (!outputBBox) {\n                    // if this is the first iteration\n                    outputBBox = childBBox;\n                } else {\n                    // make a new bounding box rectangle that contains this child's bounding box and previous bounding box\n                    outputBBox = outputBBox.union(childBBox);\n                }\n            }\n\n            return outputBBox;\n        }\n    };\n\n    // Text() helpers\n\n    function createTextPathNode(attrs, vel) {\n        attrs || (attrs = {});\n        var textPathElement = V('textPath');\n        var d = attrs.d;\n        if (d && attrs['xlink:href'] === undefined) {\n            // If `opt.attrs` is a plain string, consider it to be directly the\n            // SVG path data for the text to go along (this is a shortcut).\n            // Otherwise if it is an object and contains the `d` property, then this is our path.\n            // Wrap the text in the SVG <textPath> element that points\n            // to a path defined by `opt.attrs` inside the `<defs>` element.\n            var linkedPath = V('path').attr('d', d).appendTo(vel.defs());\n            textPathElement.attr('xlink:href', '#' + linkedPath.id);\n        }\n        if (V.isObject(attrs)) {\n            // Set attributes on the `<textPath>`. The most important one\n            // is the `xlink:href` that points to our newly created `<path/>` element in `<defs/>`.\n            // Note that we also allow the following construct:\n            // `t.text('my text', { textPath: { 'xlink:href': '#my-other-path' } })`.\n            // In other words, one can completely skip the auto-creation of the path\n            // and use any other arbitrary path that is in the document.\n            textPathElement.attr(attrs);\n        }\n        return textPathElement.node;\n    }\n\n    function annotateTextLine(lineNode, lineAnnotations, opt) {\n        opt || (opt = {});\n        var includeAnnotationIndices = opt.includeAnnotationIndices;\n        var eol = opt.eol;\n        var lineHeight = opt.lineHeight;\n        var baseSize = opt.baseSize;\n        var maxFontSize = 0;\n        var fontMetrics = {};\n        var lastJ = lineAnnotations.length - 1;\n        for (var j = 0; j <= lastJ; j++) {\n            var annotation = lineAnnotations[j];\n            var fontSize = null;\n            if (V.isObject(annotation)) {\n                var annotationAttrs = annotation.attrs;\n                var vTSpan = V('tspan', annotationAttrs);\n                var tspanNode = vTSpan.node;\n                var t = annotation.t;\n                if (eol && j === lastJ) t += eol;\n                tspanNode.textContent = t;\n                // Per annotation className\n                var annotationClass = annotationAttrs['class'];\n                if (annotationClass) vTSpan.addClass(annotationClass);\n                // If `opt.includeAnnotationIndices` is `true`,\n                // set the list of indices of all the applied annotations\n                // in the `annotations` attribute. This list is a comma\n                // separated list of indices.\n                if (includeAnnotationIndices) vTSpan.attr('annotations', annotation.annotations);\n                // Check for max font size\n                fontSize = parseFloat(annotationAttrs['font-size']);\n                if (!isFinite(fontSize)) fontSize = baseSize;\n                if (fontSize && fontSize > maxFontSize) maxFontSize = fontSize;\n            } else {\n                if (eol && j === lastJ) annotation += eol;\n                tspanNode = document.createTextNode(annotation || ' ');\n                if (baseSize && baseSize > maxFontSize) maxFontSize = baseSize;\n            }\n            lineNode.appendChild(tspanNode);\n        }\n\n        if (maxFontSize) fontMetrics.maxFontSize = maxFontSize;\n        if (lineHeight) {\n            fontMetrics.lineHeight = lineHeight;\n        } else if (maxFontSize) {\n            fontMetrics.lineHeight = (maxFontSize * 1.2);\n        }\n        return fontMetrics;\n    }\n\n    var emRegex = /em$/;\n\n    function convertEmToPx(em, fontSize) {\n        var numerical = parseFloat(em);\n        if (emRegex.test(em)) return numerical * fontSize;\n        return numerical;\n    }\n\n    function calculateDY(alignment, linesMetrics, baseSizePx, lineHeight) {\n        if (!Array.isArray(linesMetrics)) return 0;\n        var n = linesMetrics.length;\n        if (!n) return 0;\n        var lineMetrics = linesMetrics[0];\n        var flMaxFont = convertEmToPx(lineMetrics.maxFontSize, baseSizePx) || baseSizePx;\n        var rLineHeights = 0;\n        var lineHeightPx = convertEmToPx(lineHeight, baseSizePx);\n        for (var i = 1; i < n; i++) {\n            lineMetrics = linesMetrics[i];\n            var iLineHeight = convertEmToPx(lineMetrics.lineHeight, baseSizePx) || lineHeightPx;\n            rLineHeights += iLineHeight;\n        }\n        var llMaxFont = convertEmToPx(lineMetrics.maxFontSize, baseSizePx) || baseSizePx;\n        var dy;\n        switch (alignment) {\n            case 'middle':\n                dy = (flMaxFont / 2) - (0.15 * llMaxFont) - (rLineHeights / 2);\n                break;\n            case 'bottom':\n                dy = -(0.25 * llMaxFont) - rLineHeights;\n                break;\n            default:\n            case 'top':\n                dy = (0.8 * flMaxFont);\n                break;\n        }\n        return dy;\n    }\n\n    VPrototype.text = function(content, opt) {\n\n        if (content && typeof content !== 'string') throw new Error('Vectorizer: text() expects the first argument to be a string.');\n\n        // Replace all spaces with the Unicode No-break space (http://www.fileformat.info/info/unicode/char/a0/index.htm).\n        // IE would otherwise collapse all spaces into one.\n        content = V.sanitizeText(content);\n        opt || (opt = {});\n        // Should we allow the text to be selected?\n        var displayEmpty = opt.displayEmpty;\n        // End of Line character\n        var eol = opt.eol;\n        // Text along path\n        var textPath = opt.textPath;\n        // Vertical shift\n        var verticalAnchor = opt.textVerticalAnchor;\n        var namedVerticalAnchor = (verticalAnchor === 'middle' || verticalAnchor === 'bottom' || verticalAnchor === 'top');\n        // Horizontal shift applied to all the lines but the first.\n        var x = opt.x;\n        if (x === undefined) x = this.attr('x') || 0;\n        // Annotations\n        var iai = opt.includeAnnotationIndices;\n        var annotations = opt.annotations;\n        if (annotations && !V.isArray(annotations)) annotations = [annotations];\n        // Shift all the <tspan> but first by one line (`1em`)\n        var defaultLineHeight = opt.lineHeight;\n        var autoLineHeight = (defaultLineHeight === 'auto');\n        var lineHeight = (autoLineHeight) ? '1.5em' : (defaultLineHeight || '1em');\n        // Clearing the element\n        this.empty();\n        this.attr({\n            // Preserve spaces. In other words, we do not want consecutive spaces to get collapsed to one.\n            'xml:space': 'preserve',\n            // An empty text gets rendered into the DOM in webkit-based browsers.\n            // In order to unify this behaviour across all browsers\n            // we rather hide the text element when it's empty.\n            'display': (content || displayEmpty) ? null : 'none'\n        });\n\n        // Set default font-size if none\n        var fontSize = parseFloat(this.attr('font-size'));\n        if (!fontSize) {\n            fontSize = 16;\n            if (namedVerticalAnchor || annotations) this.attr('font-size', fontSize);\n        }\n\n        var doc = document;\n        var containerNode;\n        if (textPath) {\n            // Now all the `<tspan>`s will be inside the `<textPath>`.\n            if (typeof textPath === 'string') textPath = { d: textPath };\n            containerNode = createTextPathNode(textPath, this);\n        } else {\n            containerNode = doc.createDocumentFragment();\n        }\n        var offset = 0;\n        var lines = content.split('\\n');\n        var linesMetrics = [];\n        var annotatedY;\n        for (var i = 0, lastI = lines.length - 1; i <= lastI; i++) {\n            var dy = lineHeight;\n            var lineClassName = 'v-line';\n            var lineNode = doc.createElementNS(ns.svg, 'tspan');\n            var line = lines[i];\n            var lineMetrics;\n            if (line) {\n                if (annotations) {\n                    // Find the *compacted* annotations for this line.\n                    var lineAnnotations = V.annotateString(line, annotations, {\n                        offset: -offset,\n                        includeAnnotationIndices: iai\n                    });\n                    lineMetrics = annotateTextLine(lineNode, lineAnnotations, {\n                        includeAnnotationIndices: iai,\n                        eol: (i !== lastI && eol),\n                        lineHeight: (autoLineHeight) ? null : lineHeight,\n                        baseSize: fontSize\n                    });\n                    // Get the line height based on the biggest font size in the annotations for this line.\n                    var iLineHeight = lineMetrics.lineHeight;\n                    if (iLineHeight && autoLineHeight && i !== 0) dy = iLineHeight;\n                    if (i === 0) annotatedY = lineMetrics.maxFontSize * 0.8;\n                } else {\n                    if (eol && i !== lastI) line += eol;\n                    lineNode.textContent = line;\n                }\n            } else {\n                // Make sure the textContent is never empty. If it is, add a dummy\n                // character and make it invisible, making the following lines correctly\n                // relatively positioned. `dy=1em` won't work with empty lines otherwise.\n                lineNode.textContent = '-';\n                lineClassName += ' v-empty-line';\n                // 'opacity' needs to be specified with fill, stroke. Opacity without specification\n                // is not applied in Firefox\n                var lineNodeStyle = lineNode.style;\n                lineNodeStyle.fillOpacity = 0;\n                lineNodeStyle.strokeOpacity = 0;\n                if (annotations) {\n                    // Empty line with annotations.\n                    lineMetrics = {};\n                    lineAnnotations = V.findAnnotationsAtIndex(annotations, offset);\n                    let lineFontSize = fontSize;\n                    // Check if any of the annotations overrides the font size.\n                    for (let j = lineAnnotations.length; j > 0; j--) {\n                        const attrs = lineAnnotations[j - 1].attrs;\n                        if (!attrs || !('font-size' in attrs)) continue;\n                        const fs = parseFloat(attrs['font-size']);\n                        if (isFinite(fs)) {\n                            lineFontSize = fs;\n                            break;\n                        }\n                    }\n                    if (autoLineHeight) {\n                        if (i > 0) {\n                            dy = lineFontSize * 1.2;\n                        } else {\n                            annotatedY = lineFontSize * 0.8;\n                        }\n                    }\n                    // The font size is important for the native selection box height.\n                    lineNode.setAttribute('font-size', lineFontSize);\n                    lineMetrics.maxFontSize = lineFontSize;\n                }\n            }\n            if (lineMetrics) linesMetrics.push(lineMetrics);\n            if (i > 0) lineNode.setAttribute('dy', dy);\n            // Firefox requires 'x' to be set on the first line when inside a text path\n            if (i > 0 || textPath) lineNode.setAttribute('x', x);\n            lineNode.className.baseVal = lineClassName;\n            containerNode.appendChild(lineNode);\n            offset += line.length + 1;      // + 1 = newline character.\n        }\n        // Y Alignment calculation\n        if (namedVerticalAnchor) {\n            if (annotations) {\n                dy = calculateDY(verticalAnchor, linesMetrics, fontSize, lineHeight);\n            } else if (verticalAnchor === 'top') {\n                // A shortcut for top alignment. It does not depend on font-size nor line-height\n                dy = '0.8em';\n            } else {\n                var rh; // remaining height\n                if (lastI > 0) {\n                    rh = parseFloat(lineHeight) || 1;\n                    rh *= lastI;\n                    if (!emRegex.test(lineHeight)) rh /= fontSize;\n                } else {\n                    // Single-line text\n                    rh = 0;\n                }\n                switch (verticalAnchor) {\n                    case 'middle':\n                        dy = (0.3 - (rh / 2)) + 'em';\n                        break;\n                    case 'bottom':\n                        dy = (-rh - 0.3) + 'em';\n                        break;\n                }\n            }\n        } else {\n            if (verticalAnchor === 0) {\n                dy = '0em';\n            } else if (verticalAnchor) {\n                dy = verticalAnchor;\n            } else {\n                // No vertical anchor is defined\n                dy = 0;\n                // Backwards compatibility - we change the `y` attribute instead of `dy`.\n                if (this.attr('y') === null) this.attr('y', annotatedY || '0.8em');\n            }\n        }\n        containerNode.firstChild.setAttribute('dy', dy);\n        // Appending lines to the element.\n        this.append(containerNode);\n        return this;\n    };\n\n    /**\n     * @public\n     * @param {string} name\n     * @returns {Vectorizer}\n     */\n    VPrototype.removeAttr = function(name) {\n\n        const trueName = attributeNames[name];\n\n        const { ns, local } = V.qualifyAttr(trueName);\n        const el = this.node;\n\n        if (ns) {\n            if (el.hasAttributeNS(ns, local)) {\n                el.removeAttributeNS(ns, local);\n            }\n        } else if (el.hasAttribute(trueName)) {\n            el.removeAttribute(trueName);\n        }\n        return this;\n    };\n\n    VPrototype.attr = function(name, value) {\n\n        if (V.isUndefined(name)) {\n\n            // Return all attributes.\n            var attributes = this.node.attributes;\n            var attrs = {};\n\n            for (var i = 0; i < attributes.length; i++) {\n                attrs[attributes[i].name] = attributes[i].value;\n            }\n\n            return attrs;\n        }\n\n        if (V.isString(name) && V.isUndefined(value)) {\n            return this.node.getAttribute(attributeNames[name]);\n        }\n\n        if (typeof name === 'object') {\n\n            for (var attrName in name) {\n                if (name.hasOwnProperty(attrName)) {\n                    this.setAttribute(attrName, name[attrName]);\n                }\n            }\n\n        } else {\n\n            this.setAttribute(name, value);\n        }\n\n        return this;\n    };\n\n    VPrototype.normalizePath = function() {\n\n        var tagName = this.tagName();\n        if (tagName === 'PATH') {\n            this.attr('d', V.normalizePathData(this.attr('d')));\n        }\n\n        return this;\n    };\n\n    VPrototype.remove = function() {\n\n        if (this.node.parentNode) {\n            this.node.parentNode.removeChild(this.node);\n        }\n\n        return this;\n    };\n\n    VPrototype.empty = function() {\n\n        while (this.node.firstChild) {\n            this.node.removeChild(this.node.firstChild);\n        }\n\n        return this;\n    };\n\n    /**\n     * @private\n     * @param {object} attrs\n     * @returns {Vectorizer}\n     */\n    VPrototype.setAttributes = function(attrs) {\n\n        for (var key in attrs) {\n            if (attrs.hasOwnProperty(key)) {\n                this.setAttribute(key, attrs[key]);\n            }\n        }\n\n        return this;\n    };\n\n    VPrototype.append = function(els) {\n\n        if (!V.isArray(els)) {\n            els = [els];\n        }\n\n        for (var i = 0, len = els.length; i < len; i++) {\n            this.node.appendChild(V.toNode(els[i])); // lgtm [js/xss-through-dom]\n        }\n\n        return this;\n    };\n\n    VPrototype.prepend = function(els) {\n\n        var child = this.node.firstChild;\n        return child ? V(child).before(els) : this.append(els);\n    };\n\n    VPrototype.before = function(els) {\n\n        var node = this.node;\n        var parent = node.parentNode;\n\n        if (parent) {\n\n            if (!V.isArray(els)) {\n                els = [els];\n            }\n\n            for (var i = 0, len = els.length; i < len; i++) {\n                parent.insertBefore(V.toNode(els[i]), node);\n            }\n        }\n\n        return this;\n    };\n\n    VPrototype.appendTo = function(node) {\n        V.toNode(node).appendChild(this.node); // lgtm [js/xss-through-dom]\n        return this;\n    };\n\n    VPrototype.svg = function() {\n\n        return this.node instanceof window.SVGSVGElement ? this : V(this.node.ownerSVGElement);\n    };\n\n    VPrototype.tagName = function() {\n\n        return this.node.tagName.toUpperCase();\n    };\n\n    VPrototype.defs = function() {\n        var context = this.svg() || this;\n        var defsNode = context.node.getElementsByTagName('defs')[0];\n        if (defsNode) return V(defsNode);\n        return V('defs').appendTo(context);\n    };\n\n    VPrototype.clone = function() {\n\n        var clone = V(this.node.cloneNode(true/* deep */));\n        // Note that clone inherits also ID. Therefore, we need to change it here.\n        clone.node.id = V.uniqueId();\n        return clone;\n    };\n\n    VPrototype.findOne = function(selector) {\n\n        var found = this.node.querySelector(selector);\n        return found ? V(found) : undefined;\n    };\n\n    VPrototype.find = function(selector) {\n\n        var vels = [];\n        var nodes = this.node.querySelectorAll(selector);\n\n        if (nodes) {\n\n            // Map DOM elements to `V`s.\n            for (var i = 0; i < nodes.length; i++) {\n                vels.push(V(nodes[i]));\n            }\n        }\n\n        return vels;\n    };\n\n    // Returns an array of V elements made from children of this.node.\n    VPrototype.children = function() {\n\n        var children = this.node.childNodes;\n\n        var outputArray = [];\n        for (var i = 0; i < children.length; i++) {\n            var currentChild = children[i];\n            if (currentChild.nodeType === 1) {\n                outputArray.push(V(children[i]));\n            }\n        }\n        return outputArray;\n    };\n\n    // Returns the V element from parentNode of this.node.\n    VPrototype.parent = function() {\n        return V(this.node.parentNode) || null;\n    },\n\n    // Find an index of an element inside its container.\n    VPrototype.index = function() {\n\n        var index = 0;\n        var node = this.node.previousSibling;\n\n        while (node) {\n            // nodeType 1 for ELEMENT_NODE\n            if (node.nodeType === 1) index++;\n            node = node.previousSibling;\n        }\n\n        return index;\n    };\n\n    VPrototype.findParentByClass = function(className, terminator) {\n\n        var ownerSVGElement = this.node.ownerSVGElement;\n        var node = this.node.parentNode;\n\n        while (node && node !== terminator && node !== ownerSVGElement) {\n\n            var vel = V(node);\n            if (vel.hasClass(className)) {\n                return vel;\n            }\n\n            node = node.parentNode;\n        }\n\n        return null;\n    };\n\n    // https://jsperf.com/get-common-parent\n    VPrototype.contains = function(el) {\n\n        var a = this.node;\n        var b = V.toNode(el);\n        var bup = b && b.parentNode;\n\n        return (a === bup) || !!(bup && bup.nodeType === 1 && (a.compareDocumentPosition(bup) & 16));\n    };\n\n    // Convert global point into the coordinate space of this element.\n    VPrototype.toLocalPoint = function(x, y) {\n\n        var svg = this.svg().node;\n\n        var p = svg.createSVGPoint();\n        p.x = x;\n        p.y = y;\n\n        try {\n\n            var globalPoint = p.matrixTransform(svg.getScreenCTM().inverse());\n            var globalToLocalMatrix = this.getTransformToElement(svg).inverse();\n\n        } catch (e) {\n            // IE9 throws an exception in odd cases. (`Unexpected call to method or property access`)\n            // We have to make do with the original coordianates.\n            return p;\n        }\n\n        return globalPoint.matrixTransform(globalToLocalMatrix);\n    };\n\n    VPrototype.translateCenterToPoint = function(p) {\n\n        var bbox = this.getBBox({ target: this.svg() });\n        var center = bbox.center();\n\n        this.translate(p.x - center.x, p.y - center.y);\n        return this;\n    };\n\n    // Efficiently auto-orient an element. This basically implements the orient=auto attribute\n    // of markers. The easiest way of understanding on what this does is to imagine the element is an\n    // arrowhead. Calling this method on the arrowhead makes it point to the `position` point while\n    // being auto-oriented (properly rotated) towards the `reference` point.\n    // `target` is the element relative to which the transformations are applied. Usually a viewport.\n    VPrototype.translateAndAutoOrient = function(position, reference, target) {\n\n        position = new g.Point(position);\n        reference =  new g.Point(reference);\n        target || (target = this.svg());\n\n        // Clean-up previously set transformations except the scale. If we didn't clean up the\n        // previous transformations then they'd add up with the old ones. Scale is an exception as\n        // it doesn't add up, consider: `this.scale(2).scale(2).scale(2)`. The result is that the\n        // element is scaled by the factor 2, not 8.\n        var scale = this.scale();\n        this.attr('transform', '');\n        var bbox = this.getBBox({ target: target }).scale(scale.sx, scale.sy);\n\n        // 1. Translate to origin.\n        var translateToOrigin = V.createSVGTransform();\n        translateToOrigin.setTranslate(-bbox.x - bbox.width / 2, -bbox.y - bbox.height / 2);\n\n        // 2. Rotate around origin.\n        var rotateAroundOrigin = V.createSVGTransform();\n        var angle = position.angleBetween(reference, position.clone().offset(1, 0));\n        if (angle) rotateAroundOrigin.setRotate(angle, 0, 0);\n\n        // 3. Translate to the `position` + the offset (half my width) towards the `reference` point.\n        var translateFromOrigin = V.createSVGTransform();\n        var finalPosition = position.clone().move(reference, bbox.width / 2);\n        translateFromOrigin.setTranslate(2 * position.x - finalPosition.x, 2 * position.y - finalPosition.y);\n\n        // 4. Get the current transformation matrix of this node\n        var ctm = this.getTransformToElement(target);\n\n        // 5. Apply transformations and the scale\n        var transform = V.createSVGTransform();\n        transform.setMatrix(\n            translateFromOrigin.matrix.multiply(\n                rotateAroundOrigin.matrix.multiply(\n                    translateToOrigin.matrix.multiply(\n                        ctm.scale(scale.sx, scale.sy)))));\n\n        this.attr('transform', V.matrixToTransformString(transform.matrix));\n\n        return this;\n    };\n\n    VPrototype.animateAlongPath = function(attrs, path) {\n\n        path = V.toNode(path);\n\n        var id = V.ensureId(path);\n        var animateMotion = V('animateMotion', attrs);\n        var mpath = V('mpath', { 'xlink:href': '#' + id });\n\n        animateMotion.append(mpath);\n\n        this.append(animateMotion);\n        try {\n            animateMotion.node.beginElement();\n        } catch (e) {\n            // Fallback for IE 9.\n            // Run the animation programmatically if FakeSmile (`http://leunen.me/fakesmile/`) present\n            if (document.documentElement.getAttribute('smiling') === 'fake') {\n                /* global getTargets:true, Animator:true, animators:true id2anim:true */\n                // Register the animation. (See `https://answers.launchpad.net/smil/+question/203333`)\n                var animation = animateMotion.node;\n                animation.animators = [];\n\n                var animationID = animation.getAttribute('id');\n                if (animationID) id2anim[animationID] = animation;\n\n                var targets = getTargets(animation);\n                for (var i = 0, len = targets.length; i < len; i++) {\n                    var target = targets[i];\n                    var animator = new Animator(animation, target, i);\n                    animators.push(animator);\n                    animation.animators[i] = animator;\n                    animator.register();\n                }\n            }\n        }\n        return this;\n    };\n\n\n    // Split a string into an array of tokens.\n    // https://infra.spec.whatwg.org/#ascii-whitespace\n    const noHTMLWhitespaceRegex = /[^\\x20\\t\\r\\n\\f]+/g;\n    function getTokenList(str) {\n        if (!V.isString(str)) return [];\n        return str.trim().match(noHTMLWhitespaceRegex) || [];\n    }\n\n    VPrototype.hasClass = function(className) {\n        if (!V.isString(className)) return false;\n        return this.node.classList.contains(className.trim());\n    };\n\n    VPrototype.addClass = function(className) {\n        this.node.classList.add(...getTokenList(className));\n        return this;\n    };\n\n    VPrototype.removeClass = function(className) {\n        this.node.classList.remove(...getTokenList(className));\n        return this;\n    };\n\n    VPrototype.toggleClass = function(className, toAdd) {\n        const tokens = getTokenList(className);\n        for (let i = 0; i < tokens.length; i++) {\n            this.node.classList.toggle(tokens[i], toAdd);\n        }\n        return this;\n    };\n\n    // Interpolate path by discrete points. The precision of the sampling\n    // is controlled by `interval`. In other words, `sample()` will generate\n    // a point on the path starting at the beginning of the path going to the end\n    // every `interval` pixels.\n    // The sampler can be very useful for e.g. finding intersection between two\n    // paths (finding the two closest points from two samples).\n    VPrototype.sample = function(interval) {\n\n        interval = interval || 1;\n        var node = this.node;\n        var length = node.getTotalLength();\n        var samples = [];\n        var distance = 0;\n        var sample;\n        while (distance < length) {\n            sample = node.getPointAtLength(distance);\n            samples.push({ x: sample.x, y: sample.y, distance: distance });\n            distance += interval;\n        }\n        return samples;\n    };\n\n    VPrototype.convertToPath = function() {\n\n        var path = V('path');\n        path.attr(this.attr());\n        var d = this.convertToPathData();\n        if (d) {\n            path.attr('d', d);\n        }\n        return path;\n    };\n\n    VPrototype.convertToPathData = function() {\n\n        var tagName = this.tagName();\n\n        switch (tagName) {\n            case 'PATH':\n                return this.attr('d');\n            case 'LINE':\n                return V.convertLineToPathData(this.node);\n            case 'POLYGON':\n                return V.convertPolygonToPathData(this.node);\n            case 'POLYLINE':\n                return V.convertPolylineToPathData(this.node);\n            case 'ELLIPSE':\n                return V.convertEllipseToPathData(this.node);\n            case 'CIRCLE':\n                return V.convertCircleToPathData(this.node);\n            case 'RECT':\n                return V.convertRectToPathData(this.node);\n        }\n\n        throw new Error(tagName + ' cannot be converted to PATH.');\n    };\n\n    V.prototype.toGeometryShape = function() {\n        var x, y, width, height, cx, cy, r, rx, ry, points, d, x1, x2, y1, y2;\n        switch (this.tagName()) {\n\n            case 'RECT':\n                x = parseFloat(this.attr('x')) || 0;\n                y = parseFloat(this.attr('y')) || 0;\n                width = parseFloat(this.attr('width')) || 0;\n                height = parseFloat(this.attr('height')) || 0;\n                return new g.Rect(x, y, width, height);\n\n            case 'CIRCLE':\n                cx = parseFloat(this.attr('cx')) || 0;\n                cy = parseFloat(this.attr('cy')) || 0;\n                r = parseFloat(this.attr('r')) || 0;\n                return new g.Ellipse({ x: cx, y: cy }, r, r);\n\n            case 'ELLIPSE':\n                cx = parseFloat(this.attr('cx')) || 0;\n                cy = parseFloat(this.attr('cy')) || 0;\n                rx = parseFloat(this.attr('rx')) || 0;\n                ry = parseFloat(this.attr('ry')) || 0;\n                return new g.Ellipse({ x: cx, y: cy }, rx, ry);\n\n            case 'POLYLINE':\n                points = V.getPointsFromSvgNode(this);\n                return new g.Polyline(points);\n\n            case 'POLYGON':\n                points = V.getPointsFromSvgNode(this);\n                if (points.length > 1) points.push(points[0]);\n                return new g.Polyline(points);\n\n            case 'PATH':\n                d = this.attr('d');\n                if (!g.Path.isDataSupported(d)) d = V.normalizePathData(d);\n                return new g.Path(d);\n\n            case 'LINE':\n                x1 = parseFloat(this.attr('x1')) || 0;\n                y1 = parseFloat(this.attr('y1')) || 0;\n                x2 = parseFloat(this.attr('x2')) || 0;\n                y2 = parseFloat(this.attr('y2')) || 0;\n                return new g.Line({ x: x1, y: y1 }, { x: x2, y: y2 });\n        }\n\n        // Anything else is a rectangle\n        return this.getBBox();\n    };\n\n    // Find the intersection of a line starting in the center\n    // of the SVG `node` ending in the point `ref`.\n    // `target` is an SVG element to which `node`s transformations are relative to.\n    // Note that `ref` point must be in the coordinate system of the `target` for this function to work properly.\n    // Returns a point in the `target` coordinate system (the same system as `ref` is in) if\n    // an intersection is found. Returns `undefined` otherwise.\n    VPrototype.findIntersection = function(ref, target) {\n\n        var svg = this.svg().node;\n        target = target || svg;\n        var bbox = this.getBBox({ target: target });\n        var center = bbox.center();\n\n        if (!bbox.intersectionWithLineFromCenterToPoint(ref)) return undefined;\n\n        var spot;\n        var tagName = this.tagName();\n\n        // Little speed up optimization for `<rect>` element. We do not do conversion\n        // to path element and sampling but directly calculate the intersection through\n        // a transformed geometrical rectangle.\n        if (tagName === 'RECT') {\n\n            var gRect = new g.Rect(\n                parseFloat(this.attr('x') || 0),\n                parseFloat(this.attr('y') || 0),\n                parseFloat(this.attr('width')),\n                parseFloat(this.attr('height'))\n            );\n            // Get the rect transformation matrix with regards to the SVG document.\n            var rectMatrix = this.getTransformToElement(target);\n            // Decompose the matrix to find the rotation angle.\n            var rectMatrixComponents = V.decomposeMatrix(rectMatrix);\n            // Now we want to rotate the rectangle back so that we\n            // can use `intersectionWithLineFromCenterToPoint()` passing the angle as the second argument.\n            var resetRotation = svg.createSVGTransform();\n            resetRotation.setRotate(-rectMatrixComponents.rotation, center.x, center.y);\n            var rect = V.transformRect(gRect, resetRotation.matrix.multiply(rectMatrix));\n            spot = (new g.Rect(rect)).intersectionWithLineFromCenterToPoint(ref, rectMatrixComponents.rotation);\n\n        } else if (tagName === 'PATH' || tagName === 'POLYGON' || tagName === 'POLYLINE' || tagName === 'CIRCLE' || tagName === 'ELLIPSE') {\n\n            var pathNode = (tagName === 'PATH') ? this : this.convertToPath();\n            var samples = pathNode.sample();\n            var minDistance = Infinity;\n            var closestSamples = [];\n\n            var i, sample, gp, centerDistance, refDistance, distance;\n\n            for (i = 0; i < samples.length; i++) {\n\n                sample = samples[i];\n                // Convert the sample point in the local coordinate system to the global coordinate system.\n                gp = V.createSVGPoint(sample.x, sample.y);\n                gp = gp.matrixTransform(this.getTransformToElement(target));\n                sample = new g.Point(gp);\n                centerDistance = sample.distance(center);\n                // Penalize a higher distance to the reference point by 10%.\n                // This gives better results. This is due to\n                // inaccuracies introduced by rounding errors and getPointAtLength() returns.\n                refDistance = sample.distance(ref) * 1.1;\n                distance = centerDistance + refDistance;\n\n                if (distance < minDistance) {\n                    minDistance = distance;\n                    closestSamples = [{ sample: sample, refDistance: refDistance }];\n                } else if (distance < minDistance + 1) {\n                    closestSamples.push({ sample: sample, refDistance: refDistance });\n                }\n            }\n\n            closestSamples.sort(function(a, b) {\n                return a.refDistance - b.refDistance;\n            });\n\n            if (closestSamples[0]) {\n                spot = closestSamples[0].sample;\n            }\n        }\n\n        return spot;\n    };\n\n    /**\n     * @private\n     * @param {string} name\n     * @param {string} value\n     * @returns {Vectorizer}\n     */\n    VPrototype.setAttribute = function(name, value) {\n\n        const el = this.node;\n\n        if (value === null) {\n            this.removeAttr(name);\n            return this;\n        }\n\n        const trueName = attributeNames[name];\n\n        const { ns } = V.qualifyAttr(trueName);\n        if (ns) {\n            // Attribute names can be namespaced. E.g. `image` elements\n            // have a `xlink:href` attribute to set the source of the image.\n            el.setAttributeNS(ns, trueName, value);\n        } else if (trueName === 'id') {\n            el.id = value;\n        } else {\n            el.setAttribute(trueName, value);\n        }\n\n        return this;\n    };\n\n    // Create an SVG document element.\n    // If `content` is passed, it will be used as the SVG content of the `<svg>` root element.\n    V.createSvgDocument = function(content) {\n\n        if (content) {\n            const XMLString = `<svg xmlns=\"${ns.svg}\" xmlns:xlink=\"${ns.xlink}\" version=\"${SVGVersion}\">${content}</svg>`;\n            const { documentElement } = V.parseXML(XMLString, { async: false });\n            return documentElement;\n        }\n\n        const svg = document.createElementNS(ns.svg, 'svg');\n        svg.setAttributeNS(ns.xmlns, 'xmlns:xlink', ns.xlink);\n        svg.setAttribute('version', SVGVersion);\n        return svg;\n    };\n\n    V.createSVGStyle = function(stylesheet) {\n        const { node } = V('style', { type: 'text/css' }, [\n            V.createCDATASection(stylesheet)\n        ]);\n        return node;\n    },\n\n    V.createCDATASection = function(data = '') {\n        const xml = document.implementation.createDocument(null, 'xml', null);\n        return xml.createCDATASection(data);\n    };\n\n    V.idCounter = 0;\n\n    // A function returning a unique identifier for this client session with every call.\n    V.uniqueId = function() {\n\n        return 'v-' + (++V.idCounter);\n    };\n\n    V.toNode = function(el) {\n\n        return V.isV(el) ? el.node : (el.nodeName && el || el[0]);\n    };\n\n    V.ensureId = function(node) {\n\n        node = V.toNode(node);\n        return node.id || (node.id = V.uniqueId());\n    };\n\n    // Replace all spaces with the Unicode No-break space (http://www.fileformat.info/info/unicode/char/a0/index.htm).\n    // IE would otherwise collapse all spaces into one. This is used in the text() method but it is\n    // also exposed so that the programmer can use it in case he needs to. This is useful e.g. in tests\n    // when you want to compare the actual DOM text content without having to add the unicode character in\n    // the place of all spaces.\n    V.sanitizeText = function(text) {\n\n        return (text || '').replace(/ /g, '\\u00A0');\n    };\n\n    V.isUndefined = function(value) {\n\n        return typeof value === 'undefined';\n    };\n\n    V.isString = function(value) {\n\n        return typeof value === 'string';\n    };\n\n    V.isObject = function(value) {\n\n        return value && (typeof value === 'object');\n    };\n\n    V.isArray = Array.isArray;\n\n    V.parseXML = function(data, opt) {\n\n        opt = opt || {};\n\n        var xml;\n\n        try {\n            var parser = new DOMParser();\n\n            if (!V.isUndefined(opt.async)) {\n                parser.async = opt.async;\n            }\n\n            xml = parser.parseFromString(data, 'text/xml');\n        } catch (error) {\n            xml = undefined;\n        }\n\n        if (!xml || xml.getElementsByTagName('parsererror').length) {\n            throw new Error('Invalid XML: ' + data);\n        }\n\n        return xml;\n    };\n\n    // Create an empty object which does not inherit any properties from `Object.prototype`.\n    // This is useful when we want to use an object as a dictionary without having to\n    // worry about inherited properties such as `toString`, `valueOf` etc.\n    const _attributeNames = Object.create(null);\n\n    // List of attributes for which not to split camel case words.\n    // It contains known SVG attribute names and may be extended with user-defined attribute names.\n    [\n        'baseFrequency',\n        'baseProfile',\n        'clipPathUnits',\n        'contentScriptType',\n        'contentStyleType',\n        'diffuseConstant',\n        'edgeMode',\n        'externalResourcesRequired',\n        'filterRes', // deprecated\n        'filterUnits',\n        'gradientTransform',\n        'gradientUnits',\n        'kernelMatrix',\n        'kernelUnitLength',\n        'keyPoints',\n        'lengthAdjust',\n        'limitingConeAngle',\n        'markerHeight',\n        'markerUnits',\n        'markerWidth',\n        'maskContentUnits',\n        'maskUnits',\n        'numOctaves',\n        'pathLength',\n        'patternContentUnits',\n        'patternTransform',\n        'patternUnits',\n        'pointsAtX',\n        'pointsAtY',\n        'pointsAtZ',\n        'preserveAlpha',\n        'preserveAspectRatio',\n        'primitiveUnits',\n        'refX',\n        'refY',\n        'requiredExtensions',\n        'requiredFeatures',\n        'specularConstant',\n        'specularExponent',\n        'spreadMethod',\n        'startOffset',\n        'stdDeviation',\n        'stitchTiles',\n        'surfaceScale',\n        'systemLanguage',\n        'tableValues',\n        'targetX',\n        'targetY',\n        'textLength',\n        'viewBox',\n        'viewTarget', // deprecated\n        'xChannelSelector',\n        'yChannelSelector',\n        'zoomAndPan' // deprecated\n    ].forEach((name) => _attributeNames[name] = name);\n\n    _attributeNames['xlinkShow'] = 'xlink:show';\n    _attributeNames['xlinkRole'] = 'xlink:role';\n    _attributeNames['xlinkActuate'] = 'xlink:actuate';\n    _attributeNames['xlinkHref'] = 'xlink:href';\n    _attributeNames['xlinkType'] = 'xlink:type';\n    _attributeNames['xlinkTitle'] = 'xlink:title';\n    _attributeNames['xmlBase'] = 'xml:base';\n    _attributeNames['xmlLang'] = 'xml:lang';\n    _attributeNames['xmlSpace'] = 'xml:space';\n\n    const attributeNames = new Proxy(_attributeNames, {\n        get(cache, name) {\n            // The cache is a dictionary of attribute names. See `_attributeNames` above.\n            // If the attribute name is not in the cache, it means that it is not\n            // a camel-case attribute name. In that case, we need to convert\n            // the attribute name to dash-separated words.\n            if (!V.supportCamelCaseAttributes) return name;\n            if (name in cache) {\n                return cache[name];\n            }\n            // Convert camel case to dash-separated words.\n            return (cache[name] = name.replace(/[A-Z]/g, '-$&').toLowerCase());\n        }\n    });\n\n    // Dictionary of attribute names\n    Object.defineProperty(V, 'attributeNames', {\n        enumerable: true,\n        value: attributeNames,\n        writable: false,\n    });\n\n    // Should camel case attributes be supported?\n    Object.defineProperty(V, 'supportCamelCaseAttributes', {\n        enumerable: true,\n        value: true,\n        writable: true,\n    });\n\n    /**\n     * @param {string} name\n     * @returns {{ns: string|null, local: string}} namespace and attribute name\n     */\n    V.qualifyAttr = function(name) {\n\n        if (name.indexOf(':') !== -1) {\n            var combinedKey = name.split(':');\n            return {\n                ns: ns[combinedKey[0]],\n                local: combinedKey[1]\n            };\n        }\n\n        return {\n            ns: null,\n            local: name\n        };\n    };\n\n    // Note: This regex allows multiple commas as separator which is incorrect in SVG\n    // This regex is used by `split()`, so it doesn't need to use /g\n    V.transformSeparatorRegex = /[ ,]+/;\n    // Note: All following regexes are more restrictive than SVG specification\n    // ReDoS mitigation: Use an anchor at the beginning of the match\n    // ReDoS mitigation: Avoid backtracking (uses `[^()]+` instead of `.*?`)\n    // ReDoS mitigation: Don't match initial `(` inside repeated part\n    // The following regex needs to use /g (= cannot use capturing groups)\n    V.transformRegex = /\\b\\w+\\([^()]+\\)/g;\n    // The following regexes need to use capturing groups (= cannot use /g)\n    V.transformFunctionRegex = /\\b(\\w+)\\(([^()]+)\\)/;\n    V.transformTranslateRegex = /\\btranslate\\(([^()]+)\\)/;\n    V.transformRotateRegex = /\\brotate\\(([^()]+)\\)/;\n    V.transformScaleRegex = /\\bscale\\(([^()]+)\\)/;\n\n    V.transformStringToMatrix = function(transform) {\n\n        // Initialize result matrix as identity matrix\n        let transformationMatrix = V.createSVGMatrix();\n\n        // Note: Multiple transform functions are allowed in `transform` string\n        // `match()` returns `null` if none found\n        const transformMatches = transform && transform.match(V.transformRegex);\n        if (!transformMatches) {\n            // Return identity matrix\n            return transformationMatrix;\n        }\n\n        const numMatches = transformMatches.length;\n        for (let i = 0; i < numMatches; i++) {\n\n            const transformMatch = transformMatches[i];\n            // Use same regex as above, but with capturing groups\n            // `match()` returns values of capturing groups as `[1]`, `[2]`\n            const transformFunctionMatch = transformMatch.match(V.transformFunctionRegex);\n            if (transformFunctionMatch) {\n\n                let sx, sy, tx, ty, angle;\n                let ctm = V.createSVGMatrix();\n                const transformFunction = transformFunctionMatch[1].toLowerCase();\n                const args = transformFunctionMatch[2].split(V.transformSeparatorRegex);\n                switch (transformFunction) {\n\n                    case 'scale':\n                        sx = parseFloat(args[0]);\n                        sy = (args[1] === undefined) ? sx : parseFloat(args[1]);\n                        ctm = ctm.scaleNonUniform(sx, sy);\n                        break;\n\n                    case 'translate':\n                        tx = parseFloat(args[0]);\n                        ty = parseFloat(args[1]);\n                        ctm = ctm.translate(tx, ty);\n                        break;\n\n                    case 'rotate':\n                        angle = parseFloat(args[0]);\n                        tx = parseFloat(args[1]) || 0;\n                        ty = parseFloat(args[2]) || 0;\n                        if (tx !== 0 || ty !== 0) {\n                            ctm = ctm.translate(tx, ty).rotate(angle).translate(-tx, -ty);\n                        } else {\n                            ctm = ctm.rotate(angle);\n                        }\n                        break;\n\n                    case 'skewx':\n                        angle = parseFloat(args[0]);\n                        ctm = ctm.skewX(angle);\n                        break;\n\n                    case 'skewy':\n                        angle = parseFloat(args[0]);\n                        ctm = ctm.skewY(angle);\n                        break;\n\n                    case 'matrix':\n                        ctm.a = parseFloat(args[0]);\n                        ctm.b = parseFloat(args[1]);\n                        ctm.c = parseFloat(args[2]);\n                        ctm.d = parseFloat(args[3]);\n                        ctm.e = parseFloat(args[4]);\n                        ctm.f = parseFloat(args[5]);\n                        break;\n\n                    default:\n                        continue;\n                }\n\n                // Multiply current transformation into result matrix\n                transformationMatrix = transformationMatrix.multiply(ctm);\n            }\n\n        }\n        return transformationMatrix;\n    };\n\n    V.matrixToTransformString = function(matrix) {\n        matrix || (matrix = true);\n\n        return 'matrix(' +\n            (matrix.a !== undefined ? matrix.a : 1) + ',' +\n            (matrix.b !== undefined ? matrix.b : 0) + ',' +\n            (matrix.c !== undefined ? matrix.c : 0) + ',' +\n            (matrix.d !== undefined ? matrix.d : 1) + ',' +\n            (matrix.e !== undefined ? matrix.e : 0) + ',' +\n            (matrix.f !== undefined ? matrix.f : 0) +\n            ')';\n    };\n\n    V.parseTransformString = function(transform) {\n\n        var translate, rotate, scale;\n\n        if (transform) {\n\n            var separator = V.transformSeparatorRegex;\n\n            // Special handling for `transform` with one or more matrix functions\n            if (transform.trim().indexOf('matrix') >= 0) {\n\n                // Convert EVERYTHING in `transform` string to a matrix\n                // Will combine ALL matrixes * ALL translates * ALL scales * ALL rotates\n                // Note: In non-matrix case, we only take first one of each (if any)\n                var matrix = V.transformStringToMatrix(transform);\n                var decomposedMatrix = V.decomposeMatrix(matrix);\n\n                // Extract `translate`, `scale`, `rotate` from matrix\n                translate = [decomposedMatrix.translateX, decomposedMatrix.translateY];\n                scale = [decomposedMatrix.scaleX, decomposedMatrix.scaleY];\n                rotate = [decomposedMatrix.rotation];\n\n                // Rewrite `transform` string in `translate scale rotate` format\n                var transformations = [];\n                if (translate[0] !== 0 || translate[1] !== 0) {\n                    transformations.push('translate(' + translate + ')');\n                }\n                if (scale[0] !== 1 || scale[1] !== 1) {\n                    transformations.push('scale(' + scale + ')');\n                }\n                if (rotate[0] !== 0) {\n                    transformations.push('rotate(' + rotate + ')');\n                }\n                transform = transformations.join(' ');\n\n            } else {\n\n                // Extract `translate`, `rotate`, `scale` functions from `transform` string\n                // Note: We only detect the first match of each (if any)\n                // `match()` returns value of capturing group as `[1]`\n                const translateMatch = transform.match(V.transformTranslateRegex);\n                if (translateMatch) {\n                    translate = translateMatch[1].split(separator);\n                }\n                const rotateMatch = transform.match(V.transformRotateRegex);\n                if (rotateMatch) {\n                    rotate = rotateMatch[1].split(separator);\n                }\n                const scaleMatch = transform.match(V.transformScaleRegex);\n                if (scaleMatch) {\n                    scale = scaleMatch[1].split(separator);\n                }\n            }\n        }\n\n        var sx = (scale && scale[0]) ? parseFloat(scale[0]) : 1;\n\n        return {\n            value: transform,\n            translate: {\n                tx: (translate && translate[0]) ? parseInt(translate[0], 10) : 0,\n                ty: (translate && translate[1]) ? parseInt(translate[1], 10) : 0\n            },\n            rotate: {\n                angle: (rotate && rotate[0]) ? parseInt(rotate[0], 10) : 0,\n                cx: (rotate && rotate[1]) ? parseInt(rotate[1], 10) : undefined,\n                cy: (rotate && rotate[2]) ? parseInt(rotate[2], 10) : undefined\n            },\n            scale: {\n                sx: sx,\n                sy: (scale && scale[1]) ? parseFloat(scale[1]) : sx\n            }\n        };\n    };\n\n    V.deltaTransformPoint = function(matrix, point) {\n\n        var dx = point.x * matrix.a + point.y * matrix.c + 0;\n        var dy = point.x * matrix.b + point.y * matrix.d + 0;\n        return { x: dx, y: dy };\n    };\n\n    V.decomposeMatrix = function(matrix) {\n\n        // @see https://gist.github.com/2052247\n\n        // calculate delta transform point\n        var px = V.deltaTransformPoint(matrix, { x: 0, y: 1 });\n        var py = V.deltaTransformPoint(matrix, { x: 1, y: 0 });\n\n        // calculate skew\n        var skewX = ((180 / PI) * atan2(px.y, px.x) - 90);\n        var skewY = ((180 / PI) * atan2(py.y, py.x));\n\n        return {\n\n            translateX: matrix.e,\n            translateY: matrix.f,\n            scaleX: sqrt(matrix.a * matrix.a + matrix.b * matrix.b),\n            scaleY: sqrt(matrix.c * matrix.c + matrix.d * matrix.d),\n            skewX: skewX,\n            skewY: skewY,\n            rotation: skewX // rotation is the same as skew x\n        };\n    };\n\n    // Return the `scale` transformation from the following equation:\n    // `translate(tx, ty) . rotate(angle) . scale(sx, sy) === matrix(a,b,c,d,e,f)`\n    V.matrixToScale = function(matrix) {\n\n        var a, b, c, d;\n        if (matrix) {\n            a = V.isUndefined(matrix.a) ? 1 : matrix.a;\n            d = V.isUndefined(matrix.d) ? 1 : matrix.d;\n            b = matrix.b;\n            c = matrix.c;\n        } else {\n            a = d = 1;\n        }\n        return {\n            sx: b ? sqrt(a * a + b * b) : a,\n            sy: c ? sqrt(c * c + d * d) : d\n        };\n    };\n\n    // Return the `rotate` transformation from the following equation:\n    // `translate(tx, ty) . rotate(angle) . scale(sx, sy) === matrix(a,b,c,d,e,f)`\n    V.matrixToRotate = function(matrix) {\n\n        var p = { x: 0, y: 1 };\n        if (matrix) {\n            p = V.deltaTransformPoint(matrix, p);\n        }\n\n        return {\n            angle: g.normalizeAngle(g.toDeg(atan2(p.y, p.x)) - 90)\n        };\n    };\n\n    // Return the `translate` transformation from the following equation:\n    // `translate(tx, ty) . rotate(angle) . scale(sx, sy) === matrix(a,b,c,d,e,f)`\n    V.matrixToTranslate = function(matrix) {\n\n        return {\n            tx: (matrix && matrix.e) || 0,\n            ty: (matrix && matrix.f) || 0\n        };\n    };\n\n    V.isV = function(object) {\n\n        return object instanceof V;\n    };\n\n    // For backwards compatibility:\n    V.isVElement = V.isV;\n\n    // Element implements `getBBox()`, `getCTM()` and `getScreenCTM()`\n    // https://developer.mozilla.org/en-US/docs/Web/API/SVGGraphicsElement\n    V.isSVGGraphicsElement = function(node) {\n        if (!node) return false;\n        node = V.toNode(node);\n        // IE/Edge does not implement SVGGraphicsElement interface, thus check for `getScreenCTM` below\n        return node instanceof SVGElement && typeof node.getScreenCTM === 'function';\n    };\n\n    var svgDocument = V('svg').node;\n\n    V.createSVGMatrix = function(matrix) {\n\n        var svgMatrix = svgDocument.createSVGMatrix();\n        for (var component in matrix) {\n            svgMatrix[component] = matrix[component];\n        }\n\n        return svgMatrix;\n    };\n\n    V.createSVGTransform = function(matrix) {\n\n        if (!V.isUndefined(matrix)) {\n\n            if (!(matrix instanceof SVGMatrix)) {\n                matrix = V.createSVGMatrix(matrix);\n            }\n\n            return svgDocument.createSVGTransformFromMatrix(matrix);\n        }\n\n        return svgDocument.createSVGTransform();\n    };\n\n    V.createSVGPoint = function(x, y) {\n\n        var p = svgDocument.createSVGPoint();\n        p.x = x;\n        p.y = y;\n        return p;\n    };\n\n    V.transformRect = function(r, matrix) {\n\n        var p = svgDocument.createSVGPoint();\n\n        p.x = r.x;\n        p.y = r.y;\n        var corner1 = p.matrixTransform(matrix);\n\n        p.x = r.x + r.width;\n        p.y = r.y;\n        var corner2 = p.matrixTransform(matrix);\n\n        p.x = r.x + r.width;\n        p.y = r.y + r.height;\n        var corner3 = p.matrixTransform(matrix);\n\n        p.x = r.x;\n        p.y = r.y + r.height;\n        var corner4 = p.matrixTransform(matrix);\n\n        var minX = min(corner1.x, corner2.x, corner3.x, corner4.x);\n        var maxX = max(corner1.x, corner2.x, corner3.x, corner4.x);\n        var minY = min(corner1.y, corner2.y, corner3.y, corner4.y);\n        var maxY = max(corner1.y, corner2.y, corner3.y, corner4.y);\n\n        return new g.Rect(minX, minY, maxX - minX, maxY - minY);\n    };\n\n    V.transformPoint = function(p, matrix) {\n\n        return new g.Point(V.createSVGPoint(p.x, p.y).matrixTransform(matrix));\n    };\n\n    V.transformLine = function(l, matrix) {\n\n        return new g.Line(\n            V.transformPoint(l.start, matrix),\n            V.transformPoint(l.end, matrix)\n        );\n    };\n\n    V.transformPolyline = function(p, matrix) {\n\n        var inPoints = (p instanceof g.Polyline) ? p.points : p;\n        if (!V.isArray(inPoints)) inPoints = [];\n        var outPoints = [];\n        for (var i = 0, n = inPoints.length; i < n; i++) outPoints[i] = V.transformPoint(inPoints[i], matrix);\n        return new g.Polyline(outPoints);\n    };\n\n    // Convert a style represented as string (e.g. `'fill=\"blue\"; stroke=\"red\"'`) to\n    // an object (`{ fill: 'blue', stroke: 'red' }`).\n    V.styleToObject = function(styleString) {\n        var ret = {};\n        var styles = styleString.split(';');\n        for (var i = 0; i < styles.length; i++) {\n            var style = styles[i];\n            var pair = style.split('=');\n            ret[pair[0].trim()] = pair[1].trim();\n        }\n        return ret;\n    };\n\n    // Inspired by d3.js https://github.com/mbostock/d3/blob/master/src/svg/arc.js\n    V.createSlicePathData = function(innerRadius, outerRadius, startAngle, endAngle) {\n\n        var svgArcMax = 2 * PI - 1e-6;\n        var r0 = innerRadius;\n        var r1 = outerRadius;\n        var a0 = startAngle;\n        var a1 = endAngle;\n        var da = (a1 < a0 && (da = a0, a0 = a1, a1 = da), a1 - a0);\n        var df = da < PI ? '0' : '1';\n        var c0 = cos(a0);\n        var s0 = sin(a0);\n        var c1 = cos(a1);\n        var s1 = sin(a1);\n\n        return (da >= svgArcMax)\n            ? (r0\n                ? 'M0,' + r1\n                + 'A' + r1 + ',' + r1 + ' 0 1,1 0,' + (-r1)\n                + 'A' + r1 + ',' + r1 + ' 0 1,1 0,' + r1\n                + 'M0,' + r0\n                + 'A' + r0 + ',' + r0 + ' 0 1,0 0,' + (-r0)\n                + 'A' + r0 + ',' + r0 + ' 0 1,0 0,' + r0\n                + 'Z'\n                : 'M0,' + r1\n                + 'A' + r1 + ',' + r1 + ' 0 1,1 0,' + (-r1)\n                + 'A' + r1 + ',' + r1 + ' 0 1,1 0,' + r1\n                + 'Z')\n            : (r0\n                ? 'M' + r1 * c0 + ',' + r1 * s0\n                + 'A' + r1 + ',' + r1 + ' 0 ' + df + ',1 ' + r1 * c1 + ',' + r1 * s1\n                + 'L' + r0 * c1 + ',' + r0 * s1\n                + 'A' + r0 + ',' + r0 + ' 0 ' + df + ',0 ' + r0 * c0 + ',' + r0 * s0\n                + 'Z'\n                : 'M' + r1 * c0 + ',' + r1 * s0\n                + 'A' + r1 + ',' + r1 + ' 0 ' + df + ',1 ' + r1 * c1 + ',' + r1 * s1\n                + 'L0,0'\n                + 'Z');\n    };\n\n    // Merge attributes from object `b` with attributes in object `a`.\n    // Note that this modifies the object `a`.\n    // Also important to note that attributes are merged but CSS classes are concatenated.\n    V.mergeAttrs = function(a, b) {\n\n        for (var attr in b) {\n\n            if (attr === 'class') {\n                // Concatenate classes.\n                a[attr] = a[attr] ? a[attr] + ' ' + b[attr] : b[attr];\n            } else if (attr === 'style') {\n                // `style` attribute can be an object.\n                if (V.isObject(a[attr]) && V.isObject(b[attr])) {\n                    // `style` stored in `a` is an object.\n                    a[attr] = V.mergeAttrs(a[attr], b[attr]);\n                } else if (V.isObject(a[attr])) {\n                    // `style` in `a` is an object but it's a string in `b`.\n                    // Convert the style represented as a string to an object in `b`.\n                    a[attr] = V.mergeAttrs(a[attr], V.styleToObject(b[attr]));\n                } else if (V.isObject(b[attr])) {\n                    // `style` in `a` is a string, in `b` it's an object.\n                    a[attr] = V.mergeAttrs(V.styleToObject(a[attr]), b[attr]);\n                } else {\n                    // Both styles are strings.\n                    a[attr] = V.mergeAttrs(V.styleToObject(a[attr]), V.styleToObject(b[attr]));\n                }\n            } else {\n                a[attr] = b[attr];\n            }\n        }\n\n        return a;\n    };\n\n    V.annotateString = function(t, annotations, opt) {\n\n        annotations = annotations || [];\n        opt = opt || {};\n\n        var offset = opt.offset || 0;\n        var compacted = [];\n        var batch;\n        var ret = [];\n        var item;\n        var prev;\n\n        for (var i = 0; i < t.length; i++) {\n\n            item = ret[i] = t[i];\n\n            for (var j = 0; j < annotations.length; j++) {\n\n                var annotation = annotations[j];\n                var start = annotation.start + offset;\n                var end = annotation.end + offset;\n\n                if (i >= start && i < end) {\n                    // Annotation applies.\n                    if (V.isObject(item)) {\n                        // There is more than one annotation to be applied => Merge attributes.\n                        item.attrs = V.mergeAttrs(V.mergeAttrs({}, item.attrs), annotation.attrs);\n                    } else {\n                        item = ret[i] = { t: t[i], attrs: annotation.attrs };\n                    }\n                    if (opt.includeAnnotationIndices) {\n                        (item.annotations || (item.annotations = [])).push(j);\n                    }\n                }\n            }\n\n            prev = ret[i - 1];\n\n            if (!prev) {\n\n                batch = item;\n\n            } else if (V.isObject(item) && V.isObject(prev)) {\n                // Both previous item and the current one are annotations. If the attributes\n                // didn't change, merge the text.\n                if (JSON.stringify(item.attrs) === JSON.stringify(prev.attrs)) {\n                    batch.t += item.t;\n                } else {\n                    compacted.push(batch);\n                    batch = item;\n                }\n\n            } else if (V.isObject(item)) {\n                // Previous item was a string, current item is an annotation.\n                compacted.push(batch);\n                batch = item;\n\n            } else if (V.isObject(prev)) {\n                // Previous item was an annotation, current item is a string.\n                compacted.push(batch);\n                batch = item;\n\n            } else {\n                // Both previous and current item are strings.\n                batch = (batch || '') + item;\n            }\n        }\n\n        if (batch) {\n            compacted.push(batch);\n        }\n\n        return compacted;\n    };\n\n    V.findAnnotationsAtIndex = function(annotations, index) {\n\n        var found = [];\n\n        if (annotations) {\n\n            annotations.forEach(function(annotation) {\n\n                if (annotation.start < index && index <= annotation.end) {\n                    found.push(annotation);\n                }\n            });\n        }\n\n        return found;\n    };\n\n    V.findAnnotationsBetweenIndexes = function(annotations, start, end) {\n\n        var found = [];\n\n        if (annotations) {\n\n            annotations.forEach(function(annotation) {\n\n                if ((start >= annotation.start && start < annotation.end) || (end > annotation.start && end <= annotation.end) || (annotation.start >= start && annotation.end < end)) {\n                    found.push(annotation);\n                }\n            });\n        }\n\n        return found;\n    };\n\n    // Shift all the text annotations after character `index` by `offset` positions.\n    V.shiftAnnotations = function(annotations, index, offset) {\n\n        if (annotations) {\n\n            annotations.forEach(function(annotation) {\n\n                if (annotation.start < index && annotation.end >= index) {\n                    annotation.end += offset;\n                } else if (annotation.start >= index) {\n                    annotation.start += offset;\n                    annotation.end += offset;\n                }\n            });\n        }\n\n        return annotations;\n    };\n\n    V.convertLineToPathData = function(line) {\n\n        line = V(line);\n        var d = [\n            'M', line.attr('x1'), line.attr('y1'),\n            'L', line.attr('x2'), line.attr('y2')\n        ].join(' ');\n        return d;\n    };\n\n    V.convertPolygonToPathData = function(polygon) {\n\n        var points = V.getPointsFromSvgNode(polygon);\n        if (points.length === 0) return null;\n\n        return V.svgPointsToPath(points) + ' Z';\n    };\n\n    V.convertPolylineToPathData = function(polyline) {\n\n        var points = V.getPointsFromSvgNode(polyline);\n        if (points.length === 0) return null;\n\n        return V.svgPointsToPath(points);\n    };\n\n    V.svgPointsToPath = function(points) {\n\n        for (var i = 0, n = points.length; i < n; i++) {\n            points[i] = points[i].x + ' ' + points[i].y;\n        }\n\n        return 'M ' + points.join(' L');\n    };\n\n    V.getPointsFromSvgNode = function(node) {\n\n        node = V.toNode(node);\n        var points = [];\n        var nodePoints = node.points;\n        if (nodePoints) {\n            for (var i = 0, n = nodePoints.numberOfItems; i < n; i++) {\n                points.push(nodePoints.getItem(i));\n            }\n        }\n\n        return points;\n    };\n\n    V.KAPPA = 0.551784;\n\n    V.convertCircleToPathData = function(circle) {\n\n        circle = V(circle);\n        var cx = parseFloat(circle.attr('cx')) || 0;\n        var cy = parseFloat(circle.attr('cy')) || 0;\n        var r = parseFloat(circle.attr('r'));\n        var cd = r * V.KAPPA; // Control distance.\n\n        var d = [\n            'M', cx, cy - r,    // Move to the first point.\n            'C', cx + cd, cy - r, cx + r, cy - cd, cx + r, cy, // I. Quadrant.\n            'C', cx + r, cy + cd, cx + cd, cy + r, cx, cy + r, // II. Quadrant.\n            'C', cx - cd, cy + r, cx - r, cy + cd, cx - r, cy, // III. Quadrant.\n            'C', cx - r, cy - cd, cx - cd, cy - r, cx, cy - r, // IV. Quadrant.\n            'Z'\n        ].join(' ');\n        return d;\n    };\n\n    V.convertEllipseToPathData = function(ellipse) {\n\n        ellipse = V(ellipse);\n        var cx = parseFloat(ellipse.attr('cx')) || 0;\n        var cy = parseFloat(ellipse.attr('cy')) || 0;\n        var rx = parseFloat(ellipse.attr('rx'));\n        var ry = parseFloat(ellipse.attr('ry')) || rx;\n        var cdx = rx * V.KAPPA; // Control distance x.\n        var cdy = ry * V.KAPPA; // Control distance y.\n\n        var d = [\n            'M', cx, cy - ry,    // Move to the first point.\n            'C', cx + cdx, cy - ry, cx + rx, cy - cdy, cx + rx, cy, // I. Quadrant.\n            'C', cx + rx, cy + cdy, cx + cdx, cy + ry, cx, cy + ry, // II. Quadrant.\n            'C', cx - cdx, cy + ry, cx - rx, cy + cdy, cx - rx, cy, // III. Quadrant.\n            'C', cx - rx, cy - cdy, cx - cdx, cy - ry, cx, cy - ry, // IV. Quadrant.\n            'Z'\n        ].join(' ');\n        return d;\n    };\n\n    V.convertRectToPathData = function(rect) {\n\n        rect = V(rect);\n\n        return V.rectToPath({\n            x: parseFloat(rect.attr('x')) || 0,\n            y: parseFloat(rect.attr('y')) || 0,\n            width: parseFloat(rect.attr('width')) || 0,\n            height: parseFloat(rect.attr('height')) || 0,\n            rx: parseFloat(rect.attr('rx')) || 0,\n            ry: parseFloat(rect.attr('ry')) || 0\n        });\n    };\n\n    // Convert a rectangle to SVG path commands. `r` is an object of the form:\n    // `{ x: [number], y: [number], width: [number], height: [number], top-ry: [number], top-ry: [number], bottom-rx: [number], bottom-ry: [number] }`,\n    // where `x, y, width, height` are the usual rectangle attributes and [top-/bottom-]rx/ry allows for\n    // specifying radius of the rectangle for all its sides (as opposed to the built-in SVG rectangle\n    // that has only `rx` and `ry` attributes).\n    V.rectToPath = function(r) {\n\n        var d;\n        var x = r.x;\n        var y = r.y;\n        var width = r.width;\n        var height = r.height;\n        var topRx = min(r.rx || r['top-rx'] || 0, width / 2);\n        var bottomRx = min(r.rx || r['bottom-rx'] || 0, width / 2);\n        var topRy = min(r.ry || r['top-ry'] || 0, height / 2);\n        var bottomRy = min(r.ry || r['bottom-ry'] || 0, height / 2);\n\n        if (topRx || bottomRx || topRy || bottomRy) {\n            d = [\n                'M', x, y + topRy,\n                'v', height - topRy - bottomRy,\n                'a', bottomRx, bottomRy, 0, 0, 0, bottomRx, bottomRy,\n                'h', width - 2 * bottomRx,\n                'a', bottomRx, bottomRy, 0, 0, 0, bottomRx, -bottomRy,\n                'v', -(height - bottomRy - topRy),\n                'a', topRx, topRy, 0, 0, 0, -topRx, -topRy,\n                'h', -(width - 2 * topRx),\n                'a', topRx, topRy, 0, 0, 0, -topRx, topRy,\n                'Z'\n            ];\n        } else {\n            d = [\n                'M', x, y,\n                'H', x + width,\n                'V', y + height,\n                'H', x,\n                'V', y,\n                'Z'\n            ];\n        }\n\n        return d.join(' ');\n    };\n\n    // Take a path data string\n    // Return a normalized path data string\n    // If data cannot be parsed, return 'M 0 0'\n    // Highly inspired by Raphael Library (www.raphael.com)\n    V.normalizePathData = (function() {\n\n        var spaces = '\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029';\n        var pathCommand = new RegExp('([a-z])[' + spaces + ',]*((-?\\\\d*\\\\.?\\\\d*(?:e[\\\\-+]?\\\\d+)?[' + spaces + ']*,?[' + spaces + ']*)+)', 'ig');\n        var pathValues = new RegExp('(-?\\\\d*\\\\.?\\\\d*(?:e[\\\\-+]?\\\\d+)?)[' + spaces + ']*,?[' + spaces + ']*', 'ig');\n\n        var math = Math;\n        var PI = math.PI;\n        var sin = math.sin;\n        var cos = math.cos;\n        var tan = math.tan;\n        var asin = math.asin;\n        var sqrt = math.sqrt;\n        var abs = math.abs;\n\n        function q2c(x1, y1, ax, ay, x2, y2) {\n\n            var _13 = 1 / 3;\n            var _23 = 2 / 3;\n            return [(_13 * x1) + (_23 * ax), (_13 * y1) + (_23 * ay), (_13 * x2) + (_23 * ax), (_13 * y2) + (_23 * ay), x2, y2];\n        }\n\n        function rotate(x, y, rad) {\n\n            var X = (x * cos(rad)) - (y * sin(rad));\n            var Y = (x * sin(rad)) + (y * cos(rad));\n            return { x: X, y: Y };\n        }\n\n        function a2c(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {\n            // for more information of where this math came from visit:\n            // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes\n            var _120 = (PI * 120) / 180;\n            var rad = (PI / 180) * (+angle || 0);\n            var res = [];\n            var xy;\n\n            if (!recursive) {\n                xy = rotate(x1, y1, -rad);\n                x1 = xy.x;\n                y1 = xy.y;\n\n                xy = rotate(x2, y2, -rad);\n                x2 = xy.x;\n                y2 = xy.y;\n\n                var x = (x1 - x2) / 2;\n                var y = (y1 - y2) / 2;\n                var h = ((x * x) / (rx * rx)) + ((y * y) / (ry * ry));\n\n                if (h > 1) {\n                    h = sqrt(h);\n                    rx = h * rx;\n                    ry = h * ry;\n                }\n\n                var rx2 = rx * rx;\n                var ry2 = ry * ry;\n\n                var k = ((large_arc_flag == sweep_flag) ? -1 : 1) * sqrt(abs(((rx2 * ry2) - (rx2 * y * y) - (ry2 * x * x)) / ((rx2 * y * y) + (ry2 * x * x))));\n                if (!Number.isFinite(k)) {\n                    // Arc is a single point\n                    return [x1, y1, x2, y2, x2, y2];\n                }\n\n                var cx = ((k * rx * y) / ry) + ((x1 + x2) / 2);\n                var cy = ((k * -ry * x) / rx) + ((y1 + y2) / 2);\n\n                var f1 = asin(((y1 - cy) / ry).toFixed(9));\n                var f2 = asin(((y2 - cy) / ry).toFixed(9));\n\n                f1 = ((x1 < cx) ? (PI - f1) : f1);\n                f2 = ((x2 < cx) ? (PI - f2) : f2);\n\n                if (f1 < 0) f1 = (PI * 2) + f1;\n                if (f2 < 0) f2 = (PI * 2) + f2;\n\n                if (sweep_flag && (f1 > f2)) f1 = f1 - (PI * 2);\n                if (!sweep_flag && (f2 > f1)) f2 = f2 - (PI * 2);\n\n            } else {\n                f1 = recursive[0];\n                f2 = recursive[1];\n                cx = recursive[2];\n                cy = recursive[3];\n            }\n\n            var df = f2 - f1;\n            if (abs(df) > _120) {\n                var f2old = f2;\n                var x2old = x2;\n                var y2old = y2;\n                f2 = f1 + (_120 * ((sweep_flag && (f2 > f1)) ? 1 : -1));\n                x2 = cx + (rx * cos(f2));\n                y2 = cy + (ry * sin(f2));\n                res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);\n            }\n\n            df = f2 - f1;\n\n            var c1 = cos(f1);\n            var s1 = sin(f1);\n            var c2 = cos(f2);\n            var s2 = sin(f2);\n            var t = tan(df / 4);\n            var hx = (4 / 3) * (rx * t);\n            var hy = (4 / 3) * (ry * t);\n            var m1 = [x1, y1];\n            var m2 = [x1 + (hx * s1), y1 - (hy * c1)];\n            var m3 = [x2 + (hx * s2), y2 - (hy * c2)];\n            var m4 = [x2, y2];\n\n            m2[0] = (2 * m1[0]) - m2[0];\n            m2[1] = (2 * m1[1]) - m2[1];\n\n            if (recursive) {\n                return [m2, m3, m4].concat(res);\n            } else {\n                res = [m2, m3, m4].concat(res).join().split(',');\n                var newres = [];\n                var ii = res.length;\n                for (var i = 0; i < ii; i++) {\n                    newres[i] = (i % 2) ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;\n                }\n                return newres;\n            }\n        }\n\n        function parsePathString(pathString) {\n\n            if (!pathString) return null;\n\n            var paramCounts = { a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0 };\n            var data = [];\n\n            String(pathString).replace(pathCommand, function(a, b, c) {\n\n                var params = [];\n                var name = b.toLowerCase();\n                c.replace(pathValues, function(a, b) {\n                    if (b) params.push(+b);\n                });\n\n                if ((name === 'm') && (params.length > 2)) {\n                    data.push([b].concat(params.splice(0, 2)));\n                    name = 'l';\n                    b = ((b === 'm') ? 'l' : 'L');\n                }\n\n                while (params.length >= paramCounts[name]) {\n                    data.push([b].concat(params.splice(0, paramCounts[name])));\n                    if (!paramCounts[name]) break;\n                }\n            });\n\n            return data;\n        }\n\n        function pathToAbsolute(pathArray) {\n\n            if (!Array.isArray(pathArray) || !Array.isArray(pathArray && pathArray[0])) { // rough assumption\n                pathArray = parsePathString(pathArray);\n            }\n\n            // if invalid string, return 'M 0 0'\n            if (!pathArray || !pathArray.length) return [['M', 0, 0]];\n\n            var res = [];\n            var x = 0;\n            var y = 0;\n            var mx = 0;\n            var my = 0;\n            var start = 0;\n            var pa0;\n\n            var ii = pathArray.length;\n            for (var i = start; i < ii; i++) {\n\n                var r = [];\n                res.push(r);\n\n                var pa = pathArray[i];\n                pa0 = pa[0];\n\n                if (pa0 != pa0.toUpperCase()) {\n                    r[0] = pa0.toUpperCase();\n\n                    var jj;\n                    var j;\n                    switch (r[0]) {\n                        case 'A':\n                            r[1] = pa[1];\n                            r[2] = pa[2];\n                            r[3] = pa[3];\n                            r[4] = pa[4];\n                            r[5] = pa[5];\n                            r[6] = +pa[6] + x;\n                            r[7] = +pa[7] + y;\n                            break;\n\n                        case 'V':\n                            r[1] = +pa[1] + y;\n                            break;\n\n                        case 'H':\n                            r[1] = +pa[1] + x;\n                            break;\n\n                        case 'M':\n                            mx = +pa[1] + x;\n                            my = +pa[2] + y;\n\n                            jj = pa.length;\n                            for (j = 1; j < jj; j++) {\n                                r[j] = +pa[j] + ((j % 2) ? x : y);\n                            }\n                            break;\n\n                        default:\n                            jj = pa.length;\n                            for (j = 1; j < jj; j++) {\n                                r[j] = +pa[j] + ((j % 2) ? x : y);\n                            }\n                            break;\n                    }\n                } else {\n                    var kk = pa.length;\n                    for (var k = 0; k < kk; k++) {\n                        r[k] = pa[k];\n                    }\n                }\n\n                switch (r[0]) {\n                    case 'Z':\n                        x = +mx;\n                        y = +my;\n                        break;\n\n                    case 'H':\n                        x = r[1];\n                        break;\n\n                    case 'V':\n                        y = r[1];\n                        break;\n\n                    case 'M':\n                        mx = r[r.length - 2];\n                        my = r[r.length - 1];\n                        x = r[r.length - 2];\n                        y = r[r.length - 1];\n                        break;\n\n                    default:\n                        x = r[r.length - 2];\n                        y = r[r.length - 1];\n                        break;\n                }\n            }\n\n            return res;\n        }\n\n        function normalize(path) {\n\n            var p = pathToAbsolute(path);\n            var attrs = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null };\n\n            function processPath(path, d, pcom) {\n\n                var nx, ny;\n\n                if (!path) return ['C', d.x, d.y, d.x, d.y, d.x, d.y];\n\n                if (!(path[0] in { T: 1, Q: 1 })) {\n                    d.qx = null;\n                    d.qy = null;\n                }\n\n                switch (path[0]) {\n                    case 'M':\n                        d.X = path[1];\n                        d.Y = path[2];\n                        break;\n\n                    case 'A':\n                        if (parseFloat(path[1]) === 0 || parseFloat(path[2]) === 0) {\n                            // https://www.w3.org/TR/SVG/paths.html#ArcOutOfRangeParameters\n                            // \"If either rx or ry is 0, then this arc is treated as a\n                            // straight line segment (a \"lineto\") joining the endpoints.\"\n                            path = ['L', path[6], path[7]];\n                        } else {\n                            path = ['C'].concat(a2c.apply(0, [d.x, d.y].concat(path.slice(1))));\n                        }\n                        break;\n\n                    case 'S':\n                        if (pcom === 'C' || pcom === 'S') { // In 'S' case we have to take into account, if the previous command is C/S.\n                            nx = (d.x * 2) - d.bx;          // And reflect the previous\n                            ny = (d.y * 2) - d.by;          // command's control point relative to the current point.\n                        } else {                            // or some else or nothing\n                            nx = d.x;\n                            ny = d.y;\n                        }\n                        path = ['C', nx, ny].concat(path.slice(1));\n                        break;\n\n                    case 'T':\n                        if (pcom === 'Q' || pcom === 'T') { // In 'T' case we have to take into account, if the previous command is Q/T.\n                            d.qx = (d.x * 2) - d.qx;        // And make a reflection similar\n                            d.qy = (d.y * 2) - d.qy;        // to case 'S'.\n                        } else {                            // or something else or nothing\n                            d.qx = d.x;\n                            d.qy = d.y;\n                        }\n                        path = ['C'].concat(q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));\n                        break;\n\n                    case 'Q':\n                        d.qx = path[1];\n                        d.qy = path[2];\n                        path = ['C'].concat(q2c(d.x, d.y, path[1], path[2], path[3], path[4]));\n                        break;\n\n                    case 'H':\n                        path = ['L'].concat(path[1], d.y);\n                        break;\n\n                    case 'V':\n                        path = ['L'].concat(d.x, path[1]);\n                        break;\n\n                    case 'L':\n                        break;\n\n                    case 'Z':\n                        break;\n                }\n\n                return path;\n            }\n\n            function fixArc(pp, i) {\n\n                if (pp[i].length > 7) {\n\n                    pp[i].shift();\n                    var pi = pp[i];\n\n                    while (pi.length) {\n                        pcoms[i] = 'A'; // if created multiple 'C's, their original seg is saved\n                        pp.splice(i++, 0, ['C'].concat(pi.splice(0, 6)));\n                    }\n\n                    pp.splice(i, 1);\n                    ii = p.length;\n                }\n            }\n\n            var pcoms = []; // path commands of original path p\n            var pfirst = ''; // temporary holder for original path command\n            var pcom = ''; // holder for previous path command of original path\n\n            var ii = p.length;\n            for (var i = 0; i < ii; i++) {\n                if (p[i]) pfirst = p[i][0]; // save current path command\n\n                if (pfirst !== 'C') { // C is not saved yet, because it may be result of conversion\n                    pcoms[i] = pfirst; // Save current path command\n                    if (i > 0) pcom = pcoms[i - 1]; // Get previous path command pcom\n                }\n\n                p[i] = processPath(p[i], attrs, pcom); // Previous path command is inputted to processPath\n\n                if (pcoms[i] !== 'A' && pfirst === 'C') pcoms[i] = 'C'; // 'A' is the only command\n                // which may produce multiple 'C's\n                // so we have to make sure that 'C' is also 'C' in original path\n\n                fixArc(p, i); // fixArc adds also the right amount of 'A's to pcoms\n\n                var seg = p[i];\n                var seglen = seg.length;\n\n                attrs.x = seg[seglen - 2];\n                attrs.y = seg[seglen - 1];\n\n                attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x;\n                attrs.by = parseFloat(seg[seglen - 3]) || attrs.y;\n            }\n\n            // make sure normalized path data string starts with an M segment\n            if (!p[0][0] || p[0][0] !== 'M') {\n                p.unshift(['M', 0, 0]);\n            }\n\n            return p;\n        }\n\n        return function(pathData) {\n            return normalize(pathData).join(',').split(',').join(' ');\n        };\n    })();\n\n    V.namespace = ns;\n\n    V.g = g;\n\n    return V;\n\n})();\n\nexport default V;\n","import { camelCase } from '../../util/utilHelpers.mjs';\nimport $ from './Dom.mjs';\nimport V from '../../V/index.mjs';\nimport { dataPriv, dataUser } from './vars.mjs';\n\n// Manipulation\n\nfunction cleanNodesData(nodes) {\n    let i = nodes.length;\n    while (i--) cleanNodeData(nodes[i]);\n}\n\nfunction cleanNodeData(node) {\n    $.event.remove(node);\n    dataPriv.remove(node);\n    dataUser.remove(node);\n}\n\nfunction removeNodes(nodes) {\n    for (let i = 0; i < nodes.length; i++) {\n        const node = nodes[i];\n        if (node.parentNode) {\n            node.parentNode.removeChild(node);\n        }\n    }\n}\n\nexport function remove() {\n    for (let i = 0; i < this.length; i++) {\n        const node = this[i];\n        cleanNodeData(node);\n        cleanNodesData(node.getElementsByTagName('*'));\n    }\n    removeNodes(this);\n    return this;\n}\n\nexport function detach() {\n    removeNodes(this);\n    return this;\n}\n\nexport function empty() {\n    for (let i = 0; i < this.length; i++) {\n        const node = this[i];\n        if (node.nodeType === 1) {\n            cleanNodesData(node.getElementsByTagName('*'));\n            // Remove any remaining nodes\n            node.textContent = '';\n        }\n    }\n    return this;\n}\n\nexport function clone() {\n    const clones = [];\n    for (let i = 0; i < this.length; i++) {\n        clones.push(this[i].cloneNode(true));\n    }\n    return this.pushStack(clones);\n}\n\nexport function html(html) {\n    const [el] = this;\n    if (!el) return null;\n    if (arguments.length === 0) return el.innerHTML;\n    if (html === undefined) return this; // do nothing\n    cleanNodesData(dataPriv, el.getElementsByTagName('*'));\n    if (typeof html === 'string' || typeof html === 'number') {\n        el.innerHTML = html;\n    } else {\n        el.innerHTML = '';\n        return this.append(html);\n    }\n    return this;\n}\n\nexport function append(...nodes) {\n    const [parent] = this;\n    if (!parent) return this;\n    nodes.forEach((node) => {\n        if (!node) return;\n        if (typeof node === 'string') {\n            parent.append(...$.parseHTML(node));\n        } else if (node.toString() === '[object Object]') {\n            // $ object\n            this.append(...Array.from(node));\n        } else if (Array.isArray(node)) {\n            this.append(...node);\n        } else {\n            // DOM node\n            parent.appendChild(node);\n        }\n    });\n    return this;\n}\n\nexport function prepend(...nodes) {\n    const [parent] = this;\n    if (!parent) return this;\n    nodes.forEach((node) => {\n        if (!node) return;\n        if (typeof node === 'string') {\n            parent.prepend(...$.parseHTML(node));\n        } else if (node.toString() === '[object Object]') {\n            // $ object\n            this.prepend(...Array.from(node));\n        } else if (Array.isArray(node)) {\n            this.prepend(...node);\n        } else {\n            // DOM node\n            parent.insertBefore(node, parent.firstChild);\n        }\n    });\n    return this;\n}\n\nexport function appendTo(parent) {\n    $(parent).append(this);\n    return this;\n}\n\nexport function prependTo(parent) {\n    $(parent).prepend(this);\n    return this;\n}\n\n// Styles and attributes\n\nconst requireUnits = {};\n[\n    'width', 'height', 'top', 'bottom', 'left', 'right',\n    'padding', 'paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight',\n    'margin', 'marginTop', 'marginBottom', 'marginLeft', 'marginRight',\n].forEach((cssProp) => {\n    requireUnits[cssProp] = true;\n});\n\nfunction setCSSProperty(el, name, value) {\n    if (typeof value === 'number' && requireUnits[camelCase(name)]) {\n        value += 'px';\n    }\n    el.style[name] = value;\n}\n\nexport function css(name, value) {\n    let styles;\n    if (typeof name === 'string') {\n        if (value === undefined) {\n            const [el] = this;\n            if (!el) return null;\n            return el.style[name];\n        } else {\n            styles = { [name]: value };\n        }\n    } else if (!name) {\n        throw new Error('no styles provided');\n    } else {\n        styles = name;\n    }\n    for (let style in styles) {\n        if (styles.hasOwnProperty(style)) {\n            for (let i = 0; i < this.length; i++) {\n                setCSSProperty(this[i], style, styles[style]);\n            }\n        }\n    }\n    return this;\n}\n\nexport function data(name, value) {\n    if (arguments.length < 2) {\n        const [el] = this;\n        if (!el) return null;\n        if (name === undefined) {\n            return el.dataset;\n        }\n        return el.dataset[name];\n    }\n    for (let i = 0; i < this.length; i++) {\n        this[i].dataset[name] = value;\n    }\n    return this;\n}\n\n// Classes\n\nfunction setNodesClass(method, nodes, args) {\n    for (let i = 0; i < nodes.length; i++) {\n        const node = nodes[i];\n        V.prototype[method].apply({ node }, args);\n    }\n}\n\nexport function removeClass() {\n    setNodesClass('removeClass', this, arguments);\n    return this;\n}\n\nexport function addClass() {\n    setNodesClass('addClass', this, arguments);\n    return this;\n}\n\nexport function toggleClass() {\n    setNodesClass('toggleClass', this, arguments);\n    return this;\n}\n\nexport function hasClass() {\n    const [node] = this;\n    if (!node) return false;\n    return V.prototype.hasClass.apply({ node }, arguments);\n}\n\n// Traversing\n\nexport function children(selector) {\n    const matches = [];\n    for(let i = 0; i < this.length; i++) {\n        const node = this[i];\n        let children = Array.from(node.children);\n        if (typeof selector === 'string') {\n            children = children.filter(child => child.matches(selector));\n        }\n        matches.push(...children);\n    }\n    return this.pushStack(matches);\n}\n\nexport function closest(selector) {\n    const closest = [];\n    for (let i = 0; i < this.length; i++) {\n        const el = this[i];\n        if (typeof selector === 'string') {\n            const closestEl = el.closest(selector);\n            if (closestEl) {\n                closest.push(closestEl);\n            }\n        } else {\n            const [ancestorEl] = $(selector);\n            if (ancestorEl && ancestorEl.contains(el)) {\n                closest.push(ancestorEl);\n            }\n        }\n    }\n    return this.pushStack(closest);\n}\n\n// Events\n\nexport function on(types, selector, data, fn) {\n    $.event.on(this, types, selector, data, fn);\n    return this;\n}\n\nexport function one(types, selector, data, fn) {\n    $.event.on(this, types, selector, data, fn, 1);\n    return this;\n}\n\nexport function off(types, selector, fn) {\n    if (types && types.preventDefault && types.handleObj) {\n        // ( event )  dispatched $.Event\n        const handleObj = types.handleObj;\n        $(types.delegateTarget).off(\n            handleObj.namespace\n                ? handleObj.origType + '.' + handleObj.namespace\n                : handleObj.origType,\n            handleObj.selector,\n            handleObj.handler\n        );\n        return this;\n    }\n    if (typeof types === 'object') {\n        // ( types-object [, selector] )\n        for (let type in types) {\n            this.off(type, selector, types[type]);\n        }\n        return this;\n    }\n    if (selector === false || typeof selector === 'function') {\n        // ( types [, fn] )\n        fn = selector;\n        selector = undefined;\n    }\n    for (let i = 0; i < this.length; i++) {\n        $.event.remove(this[i], types, fn, selector);\n    }\n    return this;\n}\n\n// Measurements\n\nexport function width() {\n    const [el] = this;\n    if (el === window) return el.document.documentElement.clientWidth;\n    else if (!el) return undefined;\n    const styles = window.getComputedStyle(el);\n    const height = el.offsetWidth;\n    const borderTopWidth = parseFloat(styles.borderTopWidth);\n    const borderBottomWidth = parseFloat(styles.borderBottomWidth);\n    const paddingTop = parseFloat(styles.paddingTop);\n    const paddingBottom = parseFloat(styles.paddingBottom);\n    return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;\n}\n\nexport function height() {\n    const [el] = this;\n    if (el === window) return el.document.documentElement.clientHeight;\n    if (!el) return undefined;\n    const styles = window.getComputedStyle(el);\n    const width = el.offsetHeight;\n    const borderLeftWidth = parseFloat(styles.borderLeftWidth);\n    const borderRightWidth = parseFloat(styles.borderRightWidth);\n    const paddingLeft = parseFloat(styles.paddingLeft);\n    const paddingRight = parseFloat(styles.paddingRight);\n    return width - borderLeftWidth - borderRightWidth - paddingLeft - paddingRight;\n}\n\nexport function position() {\n    const [el] = this;\n    if (!el) return;\n    let $el = $(el);\n    let offsetParent;\n    let offset;\n    let doc;\n    let parentOffset = { top: 0, left: 0 };\n    // position:fixed elements are offset from the viewport, which itself always has zero offset\n    if ($el.css('position') === 'fixed') {\n        // Assume position:fixed implies availability of getBoundingClientRect\n        offset = el.getBoundingClientRect();\n    } else {\n        offset = $el.offset();\n        // Account for the *real* offset parent, which can be the document or its root element\n        // when a statically positioned element is identified\n        doc = el.ownerDocument;\n        offsetParent = el.offsetParent || doc.documentElement;\n        const $parentOffset = $(offsetParent);\n        const parentOffsetElementPosition = $parentOffset.css('position') || 'static';\n        while ( offsetParent && (offsetParent === doc.body || offsetParent === doc.documentElement) && parentOffsetElementPosition === 'static') {\n            offsetParent = offsetParent.parentNode;\n        }\n        if (offsetParent && offsetParent !== el && offsetParent.nodeType === 1) {\n            // Incorporate borders into its offset, since they are outside its content origin\n            const offsetParentStyles = window.getComputedStyle(offsetParent);\n            const borderTopWidth = parseFloat(offsetParentStyles.borderTopWidth) || 0;\n            const borderLeftWidth = parseFloat(offsetParentStyles.borderLeftWidth) || 0;\n            parentOffset = $parentOffset.offset();\n            parentOffset.top += borderTopWidth;\n            parentOffset.left += borderLeftWidth;\n        }\n    }\n    const marginTop = parseFloat(window.getComputedStyle(el).marginTop) || 0;\n    const marginLeft = parseFloat(window.getComputedStyle(el).marginLeft) || 0;\n    // Subtract parent offsets and element margins\n    return {\n        top: offset.top - parentOffset.top - marginTop,\n        left: offset.left - parentOffset.left - marginLeft\n    };\n}\n\nexport function offset(coordinates) {\n    const [el] = this;\n    //  Getter\n    if (coordinates === undefined) {\n        if (!el) return null;\n        if (!el.getClientRects().length) {\n            return { top: 0, left: 0 };\n        }\n        const rect = el.getBoundingClientRect();\n        return {\n            top: rect.top + window.scrollY,\n            left: rect.left + window.scrollX\n        };\n    }\n    // Setter\n    if (!el) return this;\n    const currentStyle = window.getComputedStyle(el);\n    if (currentStyle.position === 'static') {\n        this.css('position', 'relative');\n    }\n    const currentOffset = this.offset();\n    const topDifference = coordinates.top - currentOffset.top;\n    const leftDifference = coordinates.left - currentOffset.left;\n    this.css({\n        top: (parseFloat(currentStyle.top) || 0) + topDifference + 'px',\n        left: (parseFloat(currentStyle.left) || 0) + leftDifference + 'px'\n    });\n    return this;\n}\n\n","import $ from './Dom.mjs';\nimport { dataPriv } from './vars.mjs';\n\nconst animationKey = 'animationFrameId';\nconst cssReset = {};\n\ncssReset['transition-property'] =\ncssReset['transition-duration'] =\ncssReset['transition-delay'] =\ncssReset['transition-timing-function'] =\ncssReset['animation-name'] =\ncssReset['animation-duration'] =\ncssReset['animation-delay'] =\ncssReset['animation-timing-function'] = '';\n\nexport function animate(properties, opt = {}) {\n    this.stop();\n    for (let i = 0; i < this.length; i++) {\n        animateNode(this[i], properties, opt);\n    }\n    return this;\n}\n\nfunction animateNode(el, properties, opt = {}) {\n\n    let {\n        duration = 400,\n        easing = 'ease-in-out',\n        delay = 0,\n        complete\n    } = opt;\n\n    const delayId = setTimeout(function() {\n\n        const $el = $(el);\n        let fired = false;\n        let endEvent = 'transitionend';\n\n        // Convert milliseconds to seconds for CSS\n        duration = duration / 1000;\n        delay = delay / 1000;\n\n        // Set up CSS values for transition or keyframe animation\n        const cssValues = {};\n        if (typeof properties === 'string') {\n            // Keyframe animation\n            cssValues['animation-name'] = properties;\n            cssValues['animation-duration'] = duration + 's';\n            cssValues['animation-delay'] = delay + 's';\n            cssValues['animation-timing-function'] = easing;\n            endEvent = 'animationend';\n        } else {\n            // CSS transitions\n            const transitionProperties = [];\n            for (var key in properties) {\n                if (properties.hasOwnProperty(key)) {\n                    cssValues[key] = properties[key];\n                    transitionProperties.push(key);\n                }\n            }\n\n            if (duration > 0) {\n                cssValues['transition-property'] = transitionProperties.join(', ');\n                cssValues['transition-duration'] = duration + 's';\n                cssValues['transition-delay'] = delay + 's';\n                cssValues['transition-timing-function'] = easing;\n            }\n        }\n\n        const wrappedCallback = function(event){\n            if (event) {\n                if (event.target !== event.currentTarget) return; // makes sure the event didn't bubble from \"below\"\n                event.target.removeEventListener(endEvent, wrappedCallback);\n            } else {\n                el.removeEventListener(endEvent, wrappedCallback); // triggered by setTimeout\n            }\n            fired = true;\n            $el.css(cssReset);\n            complete && complete.call(el);\n        };\n\n        if (duration > 0){\n            el.addEventListener(endEvent, wrappedCallback);\n            // transitionEnd is not always firing on older Android phones\n            // so make sure it gets fired\n            const callbackId = setTimeout(function() {\n                if (fired) return;\n                wrappedCallback(null);\n            }, ((duration + delay) * 1000) + 25);\n\n            dataPriv.set(el, animationKey, {\n                id: callbackId,\n                stop: () => {\n                    clearTimeout(callbackId);\n                    el.removeEventListener(endEvent, wrappedCallback);\n                }\n            });\n        }\n\n        $el.css(cssValues);\n\n        if (duration <= 0) {\n            wrappedCallback(null);\n        }\n    });\n\n    dataPriv.set(el, animationKey, {\n        stop: () => clearTimeout(delayId)\n    });\n}\n\nexport function stop() {\n    for (let i = 0; i < this.length; i++) {\n        const el = this[i];\n        const animation = dataPriv.get(el, animationKey);\n        if (!animation) continue;\n        animation.stop();\n        dataPriv.remove(el, animationKey);\n    }\n    this.css(cssReset);\n    return this;\n}\n","const propertySetters = {\n    outerWidth: 'offsetWidth',\n    outerHeight: 'offsetHeight',\n    innerWidth: 'clientWidth',\n    innerHeight: 'clientHeight',\n    scrollLeft: 'scrollLeft',\n    scrollTop: 'scrollTop',\n    val: 'value',\n    text: 'textContent',\n};\n\nconst propertiesMap = {\n    disabled: 'disabled',\n    value: 'value',\n    text: 'textContent',\n};\n\nfunction prop(name, value) {\n    if (!name) throw new Error('no property provided');\n    if (arguments.length === 1) {\n        const [el] = this;\n        if (!el) return null;\n        return el[name];\n    }\n    if (value === undefined) return this;\n    for (let i = 0; i < this.length; i++) {\n        this[i][name] = value;\n    }\n    return this;\n}\n\nfunction attr(name, value) {\n    let attributes;\n    if (typeof name === 'string') {\n        if (value === undefined) {\n            const [el] = this;\n            if (!el) return null;\n            return el.getAttribute(name);\n        } else {\n            attributes = { [name]: value };\n        }\n    } else if (!name) {\n        throw new Error('no attributes provided');\n    } else {\n        attributes = name;\n    }\n    for (let attr in attributes) {\n        if (attributes.hasOwnProperty(attr)) {\n            const value = attributes[attr];\n            if (propertiesMap[attr]) {\n                this.prop(propertiesMap[attr], value);\n                continue;\n            }\n            for (let i = 0; i < this.length; i++) {\n                if (value === null) {\n                    this[i].removeAttribute(attr);\n                } else {\n                    this[i].setAttribute(attr, value);\n                }\n            }\n        }\n    }\n    return this;\n}\n\nconst methods = {\n    prop,\n    attr\n};\n\nObject.keys(propertySetters).forEach(methodName => {\n    methods[methodName] = function(...args) {\n        return this.prop(propertySetters[methodName], ...args);\n    };\n});\n\nexport default methods;\n","export const config = {\n    // When set to `true` the cell selectors could be defined as CSS selectors.\n    // If not, only JSON Markup selectors are taken into account.\n    useCSSSelectors: false,\n    // The class name prefix config is for advanced use only.\n    // Be aware that if you change the prefix, the JointJS CSS will no longer function properly.\n    classNamePrefix: 'joint-',\n    defaultTheme: 'default',\n    // The maximum delay required for two consecutive touchend events to be interpreted\n    // as a double-tap.\n    doubleTapInterval: 300\n};\n","// TODO: should not read config outside the mvc package\nimport { config } from '../../config/index.mjs';\nimport $ from './Dom.mjs';\n\n\n// Special events\n\nconst special = Object.create(null);\n\nexport default special;\n\nspecial.load = {\n    // Prevent triggered image.load events from bubbling to window.load\n    noBubble: true,\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// so that event delegation works in $.\n// Do the same for pointerenter/pointerleave and pointerover/pointerout\n[\n    ['mouseenter', 'mouseover'],\n    ['mouseleave', 'mouseout'],\n    ['pointerenter', 'pointerover'],\n    ['pointerleave', 'pointerout'],\n].forEach(([orig, fix]) => {\n    special[orig] = {\n        delegateType: fix,\n        bindType: fix,\n        handle: function(event) {\n            const target = this;\n            const related = event.relatedTarget;\n            const handleObj = event.handleObj;\n            let ret;\n            // For mouseenter/leave call the handler if related is outside the target.\n            // NB: No relatedTarget if the mouse left/entered the browser window\n            if (!related || !target.contains(related)) {\n                event.type = handleObj.origType;\n                ret = handleObj.handler.apply(target, arguments);\n                event.type = fix;\n            }\n            return ret;\n        },\n    };\n});\n\n\n// Gestures\n\nconst maxDelay = config.doubleTapInterval;\nconst minDelay = 30;\n\nspecial.dbltap = {\n    bindType: 'touchend',\n    delegateType: 'touchend',\n    handle: function(event, ...args) {\n        const { handleObj, target } = event;\n        const targetData = $.data.create(target);\n        const now = new Date().getTime();\n        const delta = 'lastTouch' in targetData ? now - targetData.lastTouch : 0;\n        if (delta < maxDelay && delta > minDelay) {\n            targetData.lastTouch = null;\n            event.type = handleObj.origType;\n            // let $ handle the triggering of \"dbltap\" event handlers\n            handleObj.handler.call(this, event, ...args);\n        } else {\n            targetData.lastTouch = now;\n        }\n    }\n};\n","import { default as $ } from './Dom.mjs';\nimport * as methods from './methods.mjs';\nimport * as animations from './animations.mjs';\nimport { default as props } from './props.mjs';\nimport { default as special } from './events.mjs';\n\nObject.assign($.fn, methods);\nObject.assign($.fn, animations);\nObject.assign($.fn, props);\nObject.assign($.event.special, special);\n\nexport default $;\n\n","import $ from '../mvc/Dom/index.mjs';\nimport V from '../V/index.mjs';\nimport { config } from '../config/index.mjs';\nimport {\n    isBoolean,\n    isObject,\n    isNumber,\n    isString,\n    mixin,\n    deepMixin,\n    supplement,\n    defaults,\n    defaultsDeep,\n    deepSupplement,\n    assign,\n    invoke,\n    invokeProperty,\n    sortedIndex,\n    uniq,\n    clone,\n    cloneDeep,\n    isEmpty,\n    isEqual,\n    isFunction,\n    isPlainObject,\n    toArray,\n    debounce,\n    groupBy,\n    sortBy,\n    flattenDeep,\n    without,\n    difference,\n    intersection,\n    union,\n    has,\n    result,\n    omit,\n    pick,\n    bindAll,\n    forIn,\n    camelCase,\n    uniqueId,\n    merge\n} from './utilHelpers.mjs';\n\nexport const addClassNamePrefix = function(className) {\n\n    if (!className) return className;\n\n    return className.toString().split(' ').map(function(_className) {\n\n        if (_className.substr(0, config.classNamePrefix.length) !== config.classNamePrefix) {\n            _className = config.classNamePrefix + _className;\n        }\n\n        return _className;\n\n    }).join(' ');\n};\n\nexport const removeClassNamePrefix = function(className) {\n\n    if (!className) return className;\n\n    return className.toString().split(' ').map(function(_className) {\n\n        if (_className.substr(0, config.classNamePrefix.length) === config.classNamePrefix) {\n            _className = _className.substr(config.classNamePrefix.length);\n        }\n\n        return _className;\n\n    }).join(' ');\n};\n\nexport const parseDOMJSON = function(json, namespace) {\n\n    const selectors = {};\n    const groupSelectors = {};\n    const svgNamespace = V.namespace.svg;\n\n    const ns = namespace || svgNamespace;\n    const fragment = document.createDocumentFragment();\n\n    const parseNode = function(siblingsDef, parentNode, ns) {\n        for (let i = 0; i < siblingsDef.length; i++) {\n            const nodeDef = siblingsDef[i];\n\n            // Text node\n            if (typeof nodeDef === 'string') {\n                const textNode = document.createTextNode(nodeDef);\n                parentNode.appendChild(textNode);\n                continue;\n            }\n\n            // TagName\n            if (!nodeDef.hasOwnProperty('tagName')) throw new Error('json-dom-parser: missing tagName');\n            const tagName = nodeDef.tagName;\n\n            let node;\n\n            // Namespace URI\n            if (nodeDef.hasOwnProperty('namespaceURI')) ns = nodeDef.namespaceURI;\n            node = document.createElementNS(ns, tagName);\n            const svg = (ns === svgNamespace);\n\n            const wrapperNode = (svg) ? V(node) : $(node);\n            // Attributes\n            const attributes = nodeDef.attributes;\n            if (attributes) wrapperNode.attr(attributes);\n            // Style\n            const style = nodeDef.style;\n            if (style) $(node).css(style);\n            // ClassName\n            if (nodeDef.hasOwnProperty('className')) {\n                const className = nodeDef.className;\n                if (svg) {\n                    node.className.baseVal = className;\n                } else {\n                    node.className = className;\n                }\n            }\n            // TextContent\n            if (nodeDef.hasOwnProperty('textContent')) {\n                node.textContent = nodeDef.textContent;\n            }\n            // Selector\n            if (nodeDef.hasOwnProperty('selector')) {\n                const nodeSelector = nodeDef.selector;\n                if (selectors[nodeSelector]) throw new Error('json-dom-parser: selector must be unique');\n                selectors[nodeSelector] = node;\n                wrapperNode.attr('joint-selector', nodeSelector);\n            }\n            // Groups\n            if (nodeDef.hasOwnProperty('groupSelector')) {\n                let nodeGroups = nodeDef.groupSelector;\n                if (!Array.isArray(nodeGroups)) nodeGroups = [nodeGroups];\n                for (let j = 0; j < nodeGroups.length; j++) {\n                    const nodeGroup = nodeGroups[j];\n                    let group = groupSelectors[nodeGroup];\n                    if (!group) group = groupSelectors[nodeGroup] = [];\n                    group.push(node);\n                }\n            }\n\n            parentNode.appendChild(node);\n\n            // Children\n            const childrenDef = nodeDef.children;\n            if (Array.isArray(childrenDef)) {\n                parseNode(childrenDef, node, ns);\n            }\n        }\n    };\n    parseNode(json, fragment, ns);\n    return {\n        fragment: fragment,\n        selectors: selectors,\n        groupSelectors: groupSelectors\n    };\n};\n\n// Return a simple hash code from a string. See http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/.\nexport const hashCode = function(str) {\n\n    let hash = 0;\n    if (str.length === 0) return hash;\n    for (let i = 0; i < str.length; i++) {\n        const c = str.charCodeAt(i);\n        hash = ((hash << 5) - hash) + c;\n        hash = hash & hash; // Convert to 32bit integer\n    }\n    return hash;\n};\n\nexport const getByPath = function(obj, path, delimiter) {\n\n    var keys = Array.isArray(path) ? path : path.split(delimiter || '/');\n    var key;\n    var i = 0;\n    var length = keys.length;\n    while (i < length) {\n        key = keys[i++];\n        if (Object(obj) === obj && key in obj) {\n            obj = obj[key];\n        } else {\n            return undefined;\n        }\n    }\n    return obj;\n};\n\nconst isGetSafe = function(obj, key) {\n    // Prevent prototype pollution\n    // https://snyk.io/vuln/SNYK-JS-JSON8MERGEPATCH-1038399\n    if (typeof key !== 'string' && typeof key !== 'number') {\n        key = String(key);\n    }\n    if (key === 'constructor' && typeof obj[key] === 'function') {\n        return false;\n    }\n    if (key === '__proto__') {\n        return false;\n    }\n    return true;\n};\n\nexport const setByPath = function(obj, path, value, delimiter) {\n\n    const keys = Array.isArray(path) ? path : path.split(delimiter || '/');\n    const last = keys.length - 1;\n    let diver = obj;\n    let i = 0;\n\n    for (; i < last; i++) {\n        const key = keys[i];\n        if (!isGetSafe(diver, key)) return obj;\n        const value = diver[key];\n        // diver creates an empty object if there is no nested object under such a key.\n        // This means that one can populate an empty nested object with setByPath().\n        diver = value || (diver[key] = {});\n    }\n\n    diver[keys[last]] = value;\n\n    return obj;\n};\n\nexport const unsetByPath = function(obj, path, delimiter) {\n\n    const keys = Array.isArray(path) ? path : path.split(delimiter || '/');\n    const last = keys.length - 1;\n    let diver = obj;\n    let i = 0;\n\n    for (; i < last; i++) {\n        const key = keys[i];\n        if (!isGetSafe(diver, key)) return obj;\n        const value = diver[key];\n        if (!value) return obj;\n        diver = value;\n    }\n\n    delete diver[keys[last]];\n\n    return obj;\n};\n\nexport const flattenObject = function(obj, delim, stop) {\n\n    delim = delim || '/';\n    var ret = {};\n\n    for (var key in obj) {\n\n        if (!obj.hasOwnProperty(key)) continue;\n\n        var shouldGoDeeper = typeof obj[key] === 'object';\n        if (shouldGoDeeper && stop && stop(obj[key])) {\n            shouldGoDeeper = false;\n        }\n\n        if (shouldGoDeeper) {\n\n            var flatObject = flattenObject(obj[key], delim, stop);\n\n            for (var flatKey in flatObject) {\n                if (!flatObject.hasOwnProperty(flatKey)) continue;\n                ret[key + delim + flatKey] = flatObject[flatKey];\n            }\n\n        } else {\n\n            ret[key] = obj[key];\n        }\n    }\n\n    return ret;\n};\n\nexport const uuid = function() {\n\n    // credit: http://stackoverflow.com/posts/2117523/revisions\n\n    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n        var r = (Math.random() * 16) | 0;\n        var v = (c === 'x') ? r : (r & 0x3 | 0x8);\n        return v.toString(16);\n    });\n};\n\n// Generates global unique id and stores it as a property of the object, if provided.\nexport const guid = function(obj) {\n\n    guid.id = guid.id || 1;\n\n    if (obj === undefined) {\n        return 'j_' + guid.id++;\n    }\n\n    obj.id = (obj.id === undefined ? 'j_' + guid.id++ : obj.id);\n    return obj.id;\n};\n\nexport const toKebabCase = function(string) {\n\n    return string.replace(/[A-Z]/g, '-$&').toLowerCase();\n};\n\nexport const normalizeEvent = function(evt) {\n\n    if (evt.normalized) return evt;\n\n    const { originalEvent, target } = evt;\n\n    // If the event is a touch event, normalize it to a mouse event.\n    const touch = originalEvent && originalEvent.changedTouches && originalEvent.changedTouches[0];\n    if (touch) {\n        for (let property in touch) {\n            // copy all the properties from the first touch that are not\n            // defined on TouchEvent (clientX, clientY, pageX, pageY, screenX, screenY, identifier, ...)\n            if (evt[property] === undefined) {\n                evt[property] = touch[property];\n            }\n        }\n    }\n    // IE: evt.target could be set to SVGElementInstance for SVGUseElement\n    if (target) {\n        const useElement = target.correspondingUseElement;\n        if (useElement) evt.target = useElement;\n    }\n\n    evt.normalized = true;\n\n    return evt;\n};\n\nexport const normalizeWheel = function(evt) {\n    // Sane values derived empirically\n    const PIXEL_STEP  = 10;\n    const LINE_HEIGHT = 40;\n    const PAGE_HEIGHT = 800;\n\n    let sX = 0, sY = 0, pX = 0, pY = 0;\n\n    // Legacy\n    if ('detail'      in evt) { sY = evt.detail; }\n    if ('wheelDelta'  in evt) { sY = -evt.wheelDelta / 120; }\n    if ('wheelDeltaY' in evt) { sY = -evt.wheelDeltaY / 120; }\n    if ('wheelDeltaX' in evt) { sX = -evt.wheelDeltaX / 120; }\n\n    // side scrolling on FF with DOMMouseScroll\n    if ( 'axis' in evt && evt.axis === evt.HORIZONTAL_AXIS ) {\n        sX = sY;\n        sY = 0;\n    }\n\n    pX = 'deltaX' in evt ? evt.deltaX : sX * PIXEL_STEP;\n    pY = 'deltaY' in evt ? evt.deltaY : sY * PIXEL_STEP;\n\n    if ((pX || pY) && evt.deltaMode) {\n        if (evt.deltaMode == 1) {\n            pX *= LINE_HEIGHT;\n            pY *= LINE_HEIGHT;\n        } else {\n            pX *= PAGE_HEIGHT;\n            pY *= PAGE_HEIGHT;\n        }\n    }\n\n    // macOS switches deltaX and deltaY automatically when scrolling with shift key, so this is needed in other cases\n    if (evt.deltaX === 0 && evt.deltaY !== 0 && evt.shiftKey) {\n        pX = pY;\n        pY = 0;\n        sX = sY;\n        sY = 0;\n    }\n\n    // Fall-back if spin cannot be determined\n    if (pX && !sX) { sX = (pX < 1) ? -1 : 1; }\n    if (pY && !sY) { sY = (pY < 1) ? -1 : 1; }\n\n    return {\n        spinX  : sX,\n        spinY  : sY,\n        deltaX : pX,\n        deltaY : pY,\n    };\n};\n\nexport const cap = function(val, max) {\n    return val > max ? max : val < -max ? -max : val;\n};\n\nexport const nextFrame = (function() {\n\n    var raf;\n\n    if (typeof window !== 'undefined') {\n\n        raf = window.requestAnimationFrame ||\n            window.webkitRequestAnimationFrame ||\n            window.mozRequestAnimationFrame ||\n            window.oRequestAnimationFrame ||\n            window.msRequestAnimationFrame;\n    }\n\n    if (!raf) {\n\n        var lastTime = 0;\n\n        raf = function(callback) {\n\n            var currTime = new Date().getTime();\n            var timeToCall = Math.max(0, 16 - (currTime - lastTime));\n            var id = setTimeout(function() {\n                callback(currTime + timeToCall);\n            }, timeToCall);\n\n            lastTime = currTime + timeToCall;\n\n            return id;\n        };\n    }\n\n    return function(callback, context, ...rest) {\n        return (context !== undefined)\n            ? raf(callback.bind(context, ...rest))\n            : raf(callback);\n    };\n\n})();\n\nexport const cancelFrame = (function() {\n\n    var caf;\n    var client = typeof window != 'undefined';\n\n    if (client) {\n\n        caf = window.cancelAnimationFrame ||\n            window.webkitCancelAnimationFrame ||\n            window.webkitCancelRequestAnimationFrame ||\n            window.msCancelAnimationFrame ||\n            window.msCancelRequestAnimationFrame ||\n            window.oCancelAnimationFrame ||\n            window.oCancelRequestAnimationFrame ||\n            window.mozCancelAnimationFrame ||\n            window.mozCancelRequestAnimationFrame;\n    }\n\n    caf = caf || clearTimeout;\n\n    return client ? caf.bind(window) : caf;\n\n})();\n\nexport const isPercentage = function(val) {\n\n    return isString(val) && val.slice(-1) === '%';\n};\n\nexport const parseCssNumeric = function(val, restrictUnits) {\n\n    function getUnit(validUnitExp) {\n\n        // one or more numbers, followed by\n        // any number of (\n        //  `.`, followed by\n        //  one or more numbers\n        // ), followed by\n        // `validUnitExp`, followed by\n        // end of string\n        var matches = new RegExp('(?:\\\\d+(?:\\\\.\\\\d+)*)(' + validUnitExp + ')$').exec(val);\n\n        if (!matches) return null;\n        return matches[1];\n    }\n\n    var number = parseFloat(val);\n\n    // if `val` cannot be parsed as a number, return `null`\n    if (Number.isNaN(number)) return null;\n\n    // else: we know `output.value`\n    var output = {};\n    output.value = number;\n\n    // determine the unit\n    var validUnitExp;\n    if (restrictUnits == null) {\n        // no restriction\n        // accept any unit, as well as no unit\n        validUnitExp = '[A-Za-z]*';\n\n    } else if (Array.isArray(restrictUnits)) {\n        // if this is an empty array, top restriction - return `null`\n        if (restrictUnits.length === 0) return null;\n\n        // else: restriction - an array of valid unit strings\n        validUnitExp = restrictUnits.join('|');\n\n    } else if (isString(restrictUnits)) {\n        // restriction - a single valid unit string\n        validUnitExp = restrictUnits;\n    }\n    var unit = getUnit(validUnitExp);\n\n    // if we found no matches for `restrictUnits`, return `null`\n    if (unit === null) return null;\n\n    // else: we know the unit\n    output.unit = unit;\n    return output;\n};\n\nconst NO_SPACE = 0;\n\nfunction splitWordWithEOL(word, eol) {\n    const eolWords = word.split(eol);\n    let n = 1;\n    for (let j = 0, jl = eolWords.length - 1; j < jl; j++) {\n        const replacement = [];\n        if (j > 0 || eolWords[0] !== '') replacement.push(NO_SPACE);\n        replacement.push(eol);\n        if (j < jl - 1 || eolWords[jl] !== '') replacement.push(NO_SPACE);\n        eolWords.splice(n, 0, ...replacement);\n        n += replacement.length + 1;\n    }\n    return eolWords.filter(word => word !== '');\n}\n\n\nfunction getLineHeight(heightValue, textElement) {\n    if (heightValue === null) {\n        // Default 1em lineHeight\n        return textElement.getBBox().height;\n    }\n\n    switch (heightValue.unit) {\n        case 'em':\n            return textElement.getBBox().height * heightValue.value;\n        case 'px':\n        case '':\n            return heightValue.value;\n    }\n}\n\nexport const breakText = function(text, size, styles = {}, opt = {}) {\n\n    var width = size.width;\n    var height = size.height;\n\n    var svgDocument = opt.svgDocument || V('svg').node;\n    var textSpan = V('tspan').node;\n    var textElement = V('text').attr(styles).append(textSpan).node;\n    var textNode = document.createTextNode('');\n\n    // Prevent flickering\n    textElement.style.opacity = 0;\n    // Prevent FF from throwing an uncaught exception when `getBBox()`\n    // called on element that is not in the render tree (is not measurable).\n    // <tspan>.getComputedTextLength() returns always 0 in this case.\n    // Note that the `textElement` resp. `textSpan` can become hidden\n    // when it's appended to the DOM and a `display: none` CSS stylesheet\n    // rule gets applied.\n    textElement.style.display = 'block';\n    textSpan.style.display = 'block';\n\n    textSpan.appendChild(textNode);\n    svgDocument.appendChild(textElement); // lgtm [js/xss-through-dom]\n\n    if (!opt.svgDocument) {\n\n        document.body.appendChild(svgDocument);\n    }\n\n    const preserveSpaces = opt.preserveSpaces;\n    const space = ' ';\n    const separator = (opt.separator || opt.separator === '') ? opt.separator : space;\n    // If separator is a RegExp, we use the space character to join words together again (not ideal)\n    const separatorChar = (typeof separator === 'string') ? separator : space;\n    var eol = opt.eol || '\\n';\n    var hyphen = opt.hyphen ? new RegExp(opt.hyphen) : /[^\\w\\d\\u00C0-\\u1FFF\\u2800-\\uFFFD]/;\n    var maxLineCount = opt.maxLineCount;\n    if (!isNumber(maxLineCount)) maxLineCount = Infinity;\n\n    var words = text.split(separator);\n    var full = [];\n    var lines = [];\n    var p, h;\n    var lineHeight;\n\n    if (preserveSpaces) {\n        V(textSpan).attr('xml:space', 'preserve');\n    }\n\n    for (var i = 0, l = 0, len = words.length; i < len; i++) {\n\n        var word = words[i];\n\n        if (!word && !preserveSpaces) continue;\n        if (typeof word !== 'string') continue;\n\n        var isEol = false;\n        if (eol && word.indexOf(eol) >= 0) {\n            // word contains end-of-line character\n            if (word.length > 1) {\n                // separate word and continue cycle\n                const eolWords = splitWordWithEOL(words[i], eol);\n                words.splice(i, 1, ...eolWords);\n                i--;\n                len = words.length;\n                continue;\n            } else {\n                // creates a new line\n                if (preserveSpaces && typeof words[i - 1] === 'string' ) {\n                    words.splice(i, NO_SPACE, '', NO_SPACE);\n                    len += 2;\n                    i--;\n                    continue;\n                }\n                lines[++l] = (!preserveSpaces || typeof words[i + 1] === 'string') ? '' : undefined;\n                isEol = true;\n            }\n        }\n\n        if (!isEol) {\n\n            let data;\n            if (preserveSpaces) {\n                data = lines[l] !== undefined ? lines[l] + separatorChar + word : word;\n            } else {\n                data = lines[l] ? lines[l] + separatorChar + word : word;\n            }\n\n            textNode.data = data;\n\n            if (textSpan.getComputedTextLength() <= width) {\n\n                // the current line fits\n                lines[l] = data;\n\n                if (p || h) {\n                    // We were partitioning. Put rest of the word onto next line\n                    full[l++] = true;\n\n                    // cancel partitioning and splitting by hyphens\n                    p = 0;\n                    h = 0;\n                }\n\n            } else {\n\n                if (!lines[l] || p) {\n\n                    var partition = !!p;\n\n                    p = word.length - 1;\n\n                    if (partition || !p) {\n\n                        // word has only one character.\n                        if (!p) {\n\n                            if (!lines[l]) {\n\n                                // we won't fit this text within our rect\n                                lines = [];\n\n                                break;\n                            }\n\n                            // partitioning didn't help on the non-empty line\n                            // try again, but this time start with a new line\n\n                            // cancel partitions created\n                            words.splice(i, 2, word + words[i + 1]);\n\n                            // adjust word length\n                            len--;\n\n                            full[l++] = true;\n                            i--;\n\n                            continue;\n                        }\n\n                        // move last letter to the beginning of the next word\n                        words[i] = word.substring(0, p);\n                        const nextWord = words[i + 1];\n                        words[i + 1] = word.substring(p) + (nextWord === undefined || nextWord === NO_SPACE ? '' : nextWord);\n\n                    } else {\n\n                        if (h) {\n                        // cancel splitting and put the words together again\n                            words.splice(i, 2, words[i] + words[i + 1]);\n                            h = 0;\n                        } else {\n                            var hyphenIndex = word.search(hyphen);\n                            if (hyphenIndex > -1 && hyphenIndex !== word.length - 1 && hyphenIndex !== 0) {\n                                h = hyphenIndex + 1;\n                                p = 0;\n                            }\n\n                            // We initiate partitioning or splitting\n                            // split the long word into two words\n                            words.splice(i, 1, word.substring(0, h || p), word.substring(h|| p));\n                            // adjust words length\n                            len++;\n\n                        }\n\n                        if (l && !full[l - 1]) {\n                        // if the previous line is not full, try to fit max part of\n                        // the current word there\n                            l--;\n                        }\n                    }\n\n                    if (!preserveSpaces || lines[l] !== '') {\n                        i--;\n                    }\n\n                    continue;\n                }\n\n                l++;\n                i--;\n            }\n        }\n        var lastL = null;\n\n        if (lines.length > maxLineCount) {\n\n            lastL = maxLineCount - 1;\n\n        } else if (height !== undefined) {\n\n            // if size.height is defined we have to check whether the height of the entire\n            // text exceeds the rect height\n\n            if (lineHeight === undefined && textNode.data !== '') {\n\n                // use the same defaults as in V.prototype.text\n                if (styles.lineHeight === 'auto') {\n                    lineHeight = getLineHeight({ value: 1.5, unit: 'em' }, textElement);\n                } else {\n                    const parsed = parseCssNumeric(styles.lineHeight, ['em', 'px', '']);\n\n                    lineHeight = getLineHeight(parsed, textElement);\n                }\n            }\n\n            if (lineHeight * lines.length > height) {\n                // remove overflowing lines\n                lastL = Math.floor(height / lineHeight) - 1;\n            }\n        }\n\n        if (lastL !== null) {\n\n            lines.splice(lastL + 1);\n\n            // add ellipsis\n            var ellipsis = opt.ellipsis;\n            if (!ellipsis || lastL < 0) break;\n            if (typeof ellipsis !== 'string') ellipsis = '\\u2026';\n\n            var lastLine = lines[lastL];\n            if (!lastLine && !isEol) break;\n            var k = lastLine.length;\n            var lastLineWithOmission, lastChar;\n            do {\n                lastChar = lastLine[k];\n                lastLineWithOmission = lastLine.substring(0, k);\n                if (!lastChar) {\n                    lastLineWithOmission += separatorChar;\n                } else if (lastChar.match(separator)) {\n                    lastLineWithOmission += lastChar;\n                }\n                lastLineWithOmission += ellipsis;\n                textNode.data = lastLineWithOmission;\n                if (textSpan.getComputedTextLength() <= width) {\n                    lines[lastL] = lastLineWithOmission;\n                    break;\n                }\n                k--;\n            } while (k >= 0);\n            break;\n        }\n    }\n\n    if (opt.svgDocument) {\n\n        // svg document was provided, remove the text element only\n        svgDocument.removeChild(textElement);\n\n    } else {\n\n        // clean svg document\n        document.body.removeChild(svgDocument);\n    }\n\n    return lines.join(eol);\n};\n\n// Sanitize HTML\n// Based on https://gist.github.com/ufologist/5a0da51b2b9ef1b861c30254172ac3c9\n// Parses a string into an array of DOM nodes.\n// Then outputs it back as a string.\nexport const sanitizeHTML = function(html) {\n\n    // Ignores tags that are invalid inside a <div> tag (e.g. <body>, <head>)\n    const [outputEl] = $.parseHTML('<div>' + html + '</div>');\n\n    Array.from(outputEl.getElementsByTagName('*')).forEach(function(node) { // for all nodes\n        const names = node.getAttributeNames();\n        names.forEach(function(name) {\n            const value = node.getAttribute(name);\n            // Remove attribute names that start with \"on\" (e.g. onload, onerror...).\n            // Remove attribute values that start with \"javascript:\" pseudo protocol (e.g. `href=\"javascript:alert(1)\"`).\n            if (name.startsWith('on') || value.startsWith('javascript:' || value.startsWith('data:') || value.startsWith('vbscript:'))) {\n                node.removeAttribute(name);\n            }\n        });\n    });\n\n    return outputEl.innerHTML;\n};\n\n// Download `blob` as file with `fileName`.\n// Does not work in IE9.\nexport const downloadBlob = function(blob, fileName) {\n\n    if (window.navigator.msSaveBlob) { // requires IE 10+\n        // pulls up a save dialog\n        window.navigator.msSaveBlob(blob, fileName);\n\n    } else { // other browsers\n        // downloads directly in Chrome and Safari\n\n        // presents a save/open dialog in Firefox\n        // Firefox bug: `from` field in save dialog always shows `from:blob:`\n        // https://bugzilla.mozilla.org/show_bug.cgi?id=1053327\n\n        var url = window.URL.createObjectURL(blob);\n        var link = document.createElement('a');\n\n        link.href = url;\n        link.download = fileName;\n        document.body.appendChild(link);\n\n        link.click();\n\n        document.body.removeChild(link);\n        window.URL.revokeObjectURL(url); // mark the url for garbage collection\n    }\n};\n\n// Download `dataUri` as file with `fileName`.\n// Does not work in IE9.\nexport const downloadDataUri = function(dataUri, fileName) {\n\n    const blob = dataUriToBlob(dataUri);\n    downloadBlob(blob, fileName);\n};\n\n// Convert an uri-encoded data component (possibly also base64-encoded) to a blob.\nexport const dataUriToBlob = function(dataUri) {\n\n    // first, make sure there are no newlines in the data uri\n    dataUri = dataUri.replace(/\\s/g, '');\n    dataUri = decodeURIComponent(dataUri);\n\n    var firstCommaIndex = dataUri.indexOf(','); // split dataUri as `dataTypeString`,`data`\n\n    var dataTypeString = dataUri.slice(0, firstCommaIndex); // e.g. 'data:image/jpeg;base64'\n    var mimeString = dataTypeString.split(':')[1].split(';')[0]; // e.g. 'image/jpeg'\n\n    var data = dataUri.slice(firstCommaIndex + 1);\n    var decodedString;\n    if (dataTypeString.indexOf('base64') >= 0) { // data may be encoded in base64\n        decodedString = atob(data); // decode data\n    } else {\n        // convert the decoded string to UTF-8\n        decodedString = unescape(encodeURIComponent(data));\n    }\n    // write the bytes of the string to a typed array\n    var ia = new Uint8Array(decodedString.length);\n    for (var i = 0; i < decodedString.length; i++) {\n        ia[i] = decodedString.charCodeAt(i);\n    }\n\n    return new Blob([ia], { type: mimeString }); // return the typed array as Blob\n};\n\n// Read an image at `url` and return it as base64-encoded data uri.\n// The mime type of the image is inferred from the `url` file extension.\n// If data uri is provided as `url`, it is returned back unchanged.\n// `callback` is a method with `err` as first argument and `dataUri` as second argument.\n// Works with IE9.\nexport const imageToDataUri = function(url, callback) {\n\n    if (!url || url.substr(0, 'data:'.length) === 'data:') {\n        // No need to convert to data uri if it is already in data uri.\n\n        // This not only convenient but desired. For example,\n        // IE throws a security error if data:image/svg+xml is used to render\n        // an image to the canvas and an attempt is made to read out data uri.\n        // Now if our image is already in data uri, there is no need to render it to the canvas\n        // and so we can bypass this error.\n\n        // Keep the async nature of the function.\n        return setTimeout(function() {\n            callback(null, url);\n        }, 0);\n    }\n\n    // chrome, IE10+\n    var modernHandler = function(xhr, callback) {\n\n        if (xhr.status === 200) {\n\n            var reader = new FileReader();\n\n            reader.onload = function(evt) {\n                var dataUri = evt.target.result;\n                callback(null, dataUri);\n            };\n\n            reader.onerror = function() {\n                callback(new Error('Failed to load image ' + url));\n            };\n\n            reader.readAsDataURL(xhr.response);\n        } else {\n            callback(new Error('Failed to load image ' + url));\n        }\n    };\n\n    var legacyHandler = function(xhr, callback) {\n\n        var Uint8ToString = function(u8a) {\n            var CHUNK_SZ = 0x8000;\n            var c = [];\n            for (var i = 0; i < u8a.length; i += CHUNK_SZ) {\n                c.push(String.fromCharCode.apply(null, u8a.subarray(i, i + CHUNK_SZ)));\n            }\n            return c.join('');\n        };\n\n        if (xhr.status === 200) {\n\n            var bytes = new Uint8Array(xhr.response);\n\n            var suffix = (url.split('.').pop()) || 'png';\n            var map = {\n                'svg': 'svg+xml'\n            };\n            var meta = 'data:image/' + (map[suffix] || suffix) + ';base64,';\n            var b64encoded = meta + btoa(Uint8ToString(bytes));\n            callback(null, b64encoded);\n        } else {\n            callback(new Error('Failed to load image ' + url));\n        }\n    };\n\n    var xhr = new XMLHttpRequest();\n\n    xhr.open('GET', url, true);\n    xhr.addEventListener('error', function() {\n        callback(new Error('Failed to load image ' + url));\n    });\n\n    xhr.responseType = window.FileReader ? 'blob' : 'arraybuffer';\n\n    xhr.addEventListener('load', function() {\n        if (window.FileReader) {\n            modernHandler(xhr, callback);\n        } else {\n            legacyHandler(xhr, callback);\n        }\n    });\n\n    xhr.send();\n};\n\nexport const getElementBBox = function(el) {\n\n    var $el = $(el);\n    if ($el.length === 0) {\n        throw new Error('Element not found');\n    }\n\n    var element = $el[0];\n    var doc = element.ownerDocument;\n    var clientBBox = element.getBoundingClientRect();\n\n    var strokeWidthX = 0;\n    var strokeWidthY = 0;\n\n    // Firefox correction\n    if (element.ownerSVGElement) {\n\n        var vel = V(element);\n        var bbox = vel.getBBox({ target: vel.svg() });\n\n        // if FF getBoundingClientRect includes stroke-width, getBBox doesn't.\n        // To unify this across all browsers we need to adjust the final bBox with `stroke-width` value.\n        strokeWidthX = (clientBBox.width - bbox.width);\n        strokeWidthY = (clientBBox.height - bbox.height);\n    }\n\n    return {\n        x: clientBBox.left + window.pageXOffset - doc.documentElement.offsetLeft + strokeWidthX / 2,\n        y: clientBBox.top + window.pageYOffset - doc.documentElement.offsetTop + strokeWidthY / 2,\n        width: clientBBox.width - strokeWidthX,\n        height: clientBBox.height - strokeWidthY\n    };\n};\n\n\n// Highly inspired by the jquery.sortElements plugin by Padolsey.\n// See http://james.padolsey.com/javascript/sorting-elements-with-jquery/.\nexport const sortElements = function(elements, comparator) {\n\n    elements = $(elements).toArray();\n    var placements = elements.map(function(sortElement) {\n\n        var parentNode = sortElement.parentNode;\n        // Since the element itself will change position, we have\n        // to have some way of storing it's original position in\n        // the DOM. The easiest way is to have a 'flag' node:\n        var nextSibling = parentNode.insertBefore(document.createTextNode(''), sortElement.nextSibling);\n\n        return function() {\n\n            if (parentNode === this) {\n                throw new Error('You can\\'t sort elements if any one is a descendant of another.');\n            }\n\n            // Insert before flag:\n            parentNode.insertBefore(this, nextSibling);\n            // Remove flag:\n            parentNode.removeChild(nextSibling);\n        };\n    });\n\n    elements.sort(comparator);\n    for (var i = 0; i < placements.length; i++) {\n        placements[i].call(elements[i]);\n    }\n    return elements;\n};\n\n// Sets attributes on the given element and its descendants based on the selector.\n// `attrs` object: { [SELECTOR1]: { attrs1 }, [SELECTOR2]: { attrs2}, ... } e.g. { 'input': { color : 'red' }}\nexport const setAttributesBySelector = function(element, attrs) {\n\n    var $element = $(element);\n\n    forIn(attrs, function(attrs, selector) {\n        var $elements = $element.find(selector).addBack().filter(selector);\n        // Make a special case for setting classes.\n        // We do not want to overwrite any existing class.\n        if (has(attrs, 'class')) {\n            $elements.addClass(attrs['class']);\n            attrs = omit(attrs, 'class');\n        }\n        $elements.attr(attrs);\n    });\n};\n\n// Return a new object with all four sides (top, right, bottom, left) in it.\n// Value of each side is taken from the given argument (either number or object).\n// Default value for a side is 0.\n// Examples:\n// normalizeSides(5) --> { top: 5, right: 5, bottom: 5, left: 5 }\n// normalizeSides({ horizontal: 5 }) --> { top: 0, right: 5, bottom: 0, left: 5 }\n// normalizeSides({ left: 5 }) --> { top: 0, right: 0, bottom: 0, left: 5 }\n// normalizeSides({ horizontal: 10, left: 5 }) --> { top: 0, right: 10, bottom: 0, left: 5 }\n// normalizeSides({ horizontal: 0, left: 5 }) --> { top: 0, right: 0, bottom: 0, left: 5 }\nexport const normalizeSides = function(box) {\n\n    if (Object(box) !== box) { // `box` is not an object\n        var val = 0; // `val` left as 0 if `box` cannot be understood as finite number\n        if (isFinite(box)) val = +box; // actually also accepts string numbers (e.g. '100')\n\n        return { top: val, right: val, bottom: val, left: val };\n    }\n\n    // `box` is an object\n    var top, right, bottom, left;\n    top = right = bottom = left = 0;\n\n    if (isFinite(box.vertical)) top = bottom = +box.vertical;\n    if (isFinite(box.horizontal)) right = left = +box.horizontal;\n\n    if (isFinite(box.top)) top = +box.top; // overwrite vertical\n    if (isFinite(box.right)) right = +box.right; // overwrite horizontal\n    if (isFinite(box.bottom)) bottom = +box.bottom; // overwrite vertical\n    if (isFinite(box.left)) left = +box.left; // overwrite horizontal\n\n    return { top: top, right: right, bottom: bottom, left: left };\n};\n\nexport const timing = {\n\n    linear: function(t) {\n        return t;\n    },\n\n    quad: function(t) {\n        return t * t;\n    },\n\n    cubic: function(t) {\n        return t * t * t;\n    },\n\n    inout: function(t) {\n        if (t <= 0) return 0;\n        if (t >= 1) return 1;\n        var t2 = t * t;\n        var t3 = t2 * t;\n        return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);\n    },\n\n    exponential: function(t) {\n        return Math.pow(2, 10 * (t - 1));\n    },\n\n    bounce: function(t) {\n        for (var a = 0, b = 1; 1; a += b, b /= 2) {\n            if (t >= (7 - 4 * a) / 11) {\n                var q = (11 - 6 * a - 11 * t) / 4;\n                return -q * q + b * b;\n            }\n        }\n    },\n\n    reverse: function(f) {\n        return function(t) {\n            return 1 - f(1 - t);\n        };\n    },\n\n    reflect: function(f) {\n        return function(t) {\n            return .5 * (t < .5 ? f(2 * t) : (2 - f(2 - 2 * t)));\n        };\n    },\n\n    clamp: function(f, n, x) {\n        n = n || 0;\n        x = x || 1;\n        return function(t) {\n            var r = f(t);\n            return r < n ? n : r > x ? x : r;\n        };\n    },\n\n    back: function(s) {\n        if (!s) s = 1.70158;\n        return function(t) {\n            return t * t * ((s + 1) * t - s);\n        };\n    },\n\n    elastic: function(x) {\n        if (!x) x = 1.5;\n        return function(t) {\n            return Math.pow(2, 10 * (t - 1)) * Math.cos(20 * Math.PI * x / 3 * t);\n        };\n    }\n};\n\nexport const interpolate = {\n\n    number: function(a, b) {\n        var d = b - a;\n        return function(t) {\n            return a + d * t;\n        };\n    },\n\n    object: function(a, b) {\n        var s = Object.keys(a);\n        return function(t) {\n            var i, p;\n            var r = {};\n            for (i = s.length - 1; i != -1; i--) {\n                p = s[i];\n                r[p] = a[p] + (b[p] - a[p]) * t;\n            }\n            return r;\n        };\n    },\n\n    hexColor: function(a, b) {\n\n        var ca = parseInt(a.slice(1), 16);\n        var cb = parseInt(b.slice(1), 16);\n        var ra = ca & 0x0000ff;\n        var rd = (cb & 0x0000ff) - ra;\n        var ga = ca & 0x00ff00;\n        var gd = (cb & 0x00ff00) - ga;\n        var ba = ca & 0xff0000;\n        var bd = (cb & 0xff0000) - ba;\n\n        return function(t) {\n\n            var r = (ra + rd * t) & 0x000000ff;\n            var g = (ga + gd * t) & 0x0000ff00;\n            var b = (ba + bd * t) & 0x00ff0000;\n\n            return '#' + (1 << 24 | r | g | b).toString(16).slice(1);\n        };\n    },\n\n    unit: function(a, b) {\n\n        var r = /(-?[0-9]*.[0-9]*)(px|em|cm|mm|in|pt|pc|%)/;\n        var ma = r.exec(a);\n        var mb = r.exec(b);\n        var p = mb[1].indexOf('.');\n        var f = p > 0 ? mb[1].length - p - 1 : 0;\n        a = +ma[1];\n        var d = +mb[1] - a;\n        var u = ma[2];\n\n        return function(t) {\n            return (a + d * t).toFixed(f) + u;\n        };\n    }\n};\n\n// SVG filters.\n// (values in parentheses are default values)\nexport const filter = {\n\n    // `color` ... outline color ('blue')\n    // `width`... outline width (1)\n    // `opacity` ... outline opacity (1)\n    // `margin` ... gap between outline and the element (2)\n    outline: function(args) {\n\n        var tpl = '<filter><feFlood flood-color=\"${color}\" flood-opacity=\"${opacity}\" result=\"colored\"/><feMorphology in=\"SourceAlpha\" result=\"morphedOuter\" operator=\"dilate\" radius=\"${outerRadius}\" /><feMorphology in=\"SourceAlpha\" result=\"morphedInner\" operator=\"dilate\" radius=\"${innerRadius}\" /><feComposite result=\"morphedOuterColored\" in=\"colored\" in2=\"morphedOuter\" operator=\"in\"/><feComposite operator=\"xor\" in=\"morphedOuterColored\" in2=\"morphedInner\" result=\"outline\"/><feMerge><feMergeNode in=\"outline\"/><feMergeNode in=\"SourceGraphic\"/></feMerge></filter>';\n\n        var margin = Number.isFinite(args.margin) ? args.margin : 2;\n        var width = Number.isFinite(args.width) ? args.width : 1;\n\n        return template(tpl)({\n            color: args.color || 'blue',\n            opacity: Number.isFinite(args.opacity) ? args.opacity : 1,\n            outerRadius: margin + width,\n            innerRadius: margin\n        });\n    },\n\n    // `color` ... color ('red')\n    // `width`... width (1)\n    // `blur` ... blur (0)\n    // `opacity` ... opacity (1)\n    highlight: function(args) {\n\n        var tpl = '<filter><feFlood flood-color=\"${color}\" flood-opacity=\"${opacity}\" result=\"colored\"/><feMorphology result=\"morphed\" in=\"SourceGraphic\" operator=\"dilate\" radius=\"${width}\"/><feComposite result=\"composed\" in=\"colored\" in2=\"morphed\" operator=\"in\"/><feGaussianBlur result=\"blured\" in=\"composed\" stdDeviation=\"${blur}\"/><feBlend in=\"SourceGraphic\" in2=\"blured\" mode=\"normal\"/></filter>';\n\n        return template(tpl)({\n            color: args.color || 'red',\n            width: Number.isFinite(args.width) ? args.width : 1,\n            blur: Number.isFinite(args.blur) ? args.blur : 0,\n            opacity: Number.isFinite(args.opacity) ? args.opacity : 1\n        });\n    },\n\n    // `x` ... horizontal blur (2)\n    // `y` ... vertical blur (optional)\n    blur: function(args) {\n\n        var x = Number.isFinite(args.x) ? args.x : 2;\n\n        return template('<filter><feGaussianBlur stdDeviation=\"${stdDeviation}\"/></filter>')({\n            stdDeviation: Number.isFinite(args.y) ? [x, args.y] : x\n        });\n    },\n\n    // `dx` ... horizontal shift (0)\n    // `dy` ... vertical shift (0)\n    // `blur` ... blur (4)\n    // `color` ... color ('black')\n    // `opacity` ... opacity (1)\n    dropShadow: function(args) {\n\n        var tpl = 'SVGFEDropShadowElement' in window\n            ? '<filter><feDropShadow stdDeviation=\"${blur}\" dx=\"${dx}\" dy=\"${dy}\" flood-color=\"${color}\" flood-opacity=\"${opacity}\"/></filter>'\n            : '<filter><feGaussianBlur in=\"SourceAlpha\" stdDeviation=\"${blur}\"/><feOffset dx=\"${dx}\" dy=\"${dy}\" result=\"offsetblur\"/><feFlood flood-color=\"${color}\"/><feComposite in2=\"offsetblur\" operator=\"in\"/><feComponentTransfer><feFuncA type=\"linear\" slope=\"${opacity}\"/></feComponentTransfer><feMerge><feMergeNode/><feMergeNode in=\"SourceGraphic\"/></feMerge></filter>';\n\n        return template(tpl)({\n            dx: args.dx || 0,\n            dy: args.dy || 0,\n            opacity: Number.isFinite(args.opacity) ? args.opacity : 1,\n            color: args.color || 'black',\n            blur: Number.isFinite(args.blur) ? args.blur : 4\n        });\n    },\n\n    // `amount` ... the proportion of the conversion (1). A value of 1 (default) is completely grayscale. A value of 0 leaves the input unchanged.\n    grayscale: function(args) {\n\n        var amount = Number.isFinite(args.amount) ? args.amount : 1;\n\n        return template('<filter><feColorMatrix type=\"matrix\" values=\"${a} ${b} ${c} 0 0 ${d} ${e} ${f} 0 0 ${g} ${b} ${h} 0 0 0 0 0 1 0\"/></filter>')({\n            a: 0.2126 + 0.7874 * (1 - amount),\n            b: 0.7152 - 0.7152 * (1 - amount),\n            c: 0.0722 - 0.0722 * (1 - amount),\n            d: 0.2126 - 0.2126 * (1 - amount),\n            e: 0.7152 + 0.2848 * (1 - amount),\n            f: 0.0722 - 0.0722 * (1 - amount),\n            g: 0.2126 - 0.2126 * (1 - amount),\n            h: 0.0722 + 0.9278 * (1 - amount)\n        });\n    },\n\n    // `amount` ... the proportion of the conversion (1). A value of 1 (default) is completely sepia. A value of 0 leaves the input unchanged.\n    sepia: function(args) {\n\n        var amount = Number.isFinite(args.amount) ? args.amount : 1;\n\n        return template('<filter><feColorMatrix type=\"matrix\" values=\"${a} ${b} ${c} 0 0 ${d} ${e} ${f} 0 0 ${g} ${h} ${i} 0 0 0 0 0 1 0\"/></filter>')({\n            a: 0.393 + 0.607 * (1 - amount),\n            b: 0.769 - 0.769 * (1 - amount),\n            c: 0.189 - 0.189 * (1 - amount),\n            d: 0.349 - 0.349 * (1 - amount),\n            e: 0.686 + 0.314 * (1 - amount),\n            f: 0.168 - 0.168 * (1 - amount),\n            g: 0.272 - 0.272 * (1 - amount),\n            h: 0.534 - 0.534 * (1 - amount),\n            i: 0.131 + 0.869 * (1 - amount)\n        });\n    },\n\n    // `amount` ... the proportion of the conversion (1). A value of 0 is completely un-saturated. A value of 1 (default) leaves the input unchanged.\n    saturate: function(args) {\n\n        var amount = Number.isFinite(args.amount) ? args.amount : 1;\n\n        return template('<filter><feColorMatrix type=\"saturate\" values=\"${amount}\"/></filter>')({\n            amount: 1 - amount\n        });\n    },\n\n    // `angle` ...  the number of degrees around the color circle the input samples will be adjusted (0).\n    hueRotate: function(args) {\n\n        return template('<filter><feColorMatrix type=\"hueRotate\" values=\"${angle}\"/></filter>')({\n            angle: args.angle || 0\n        });\n    },\n\n    // `amount` ... the proportion of the conversion (1). A value of 1 (default) is completely inverted. A value of 0 leaves the input unchanged.\n    invert: function(args) {\n\n        var amount = Number.isFinite(args.amount) ? args.amount : 1;\n\n        return template('<filter><feComponentTransfer><feFuncR type=\"table\" tableValues=\"${amount} ${amount2}\"/><feFuncG type=\"table\" tableValues=\"${amount} ${amount2}\"/><feFuncB type=\"table\" tableValues=\"${amount} ${amount2}\"/></feComponentTransfer></filter>')({\n            amount: amount,\n            amount2: 1 - amount\n        });\n    },\n\n    // `amount` ... proportion of the conversion (1). A value of 0 will create an image that is completely black. A value of 1 (default) leaves the input unchanged.\n    brightness: function(args) {\n\n        return template('<filter><feComponentTransfer><feFuncR type=\"linear\" slope=\"${amount}\"/><feFuncG type=\"linear\" slope=\"${amount}\"/><feFuncB type=\"linear\" slope=\"${amount}\"/></feComponentTransfer></filter>')({\n            amount: Number.isFinite(args.amount) ? args.amount : 1\n        });\n    },\n\n    // `amount` ... proportion of the conversion (1). A value of 0 will create an image that is completely black. A value of 1 (default) leaves the input unchanged.\n    contrast: function(args) {\n\n        var amount = Number.isFinite(args.amount) ? args.amount : 1;\n\n        return template('<filter><feComponentTransfer><feFuncR type=\"linear\" slope=\"${amount}\" intercept=\"${amount2}\"/><feFuncG type=\"linear\" slope=\"${amount}\" intercept=\"${amount2}\"/><feFuncB type=\"linear\" slope=\"${amount}\" intercept=\"${amount2}\"/></feComponentTransfer></filter>')({\n            amount: amount,\n            amount2: .5 - amount / 2\n        });\n    }\n};\n\nexport const format = {\n\n    // Formatting numbers via the Python Format Specification Mini-language.\n    // See http://docs.python.org/release/3.1.3/library/string.html#format-specification-mini-language.\n    // Heavilly inspired by the D3.js library implementation.\n    number: function(specifier, value, locale) {\n\n        locale = locale || {\n\n            currency: ['$', ''],\n            decimal: '.',\n            thousands: ',',\n            grouping: [3]\n        };\n\n        // See Python format specification mini-language: http://docs.python.org/release/3.1.3/library/string.html#format-specification-mini-language.\n        // [[fill]align][sign][symbol][0][width][,][.precision][type]\n        var re = /(?:([^{])?([<>=^]))?([+\\- ])?([$#])?(0)?(\\d+)?(,)?(\\.-?\\d+)?([a-z%])?/i;\n\n        var match = re.exec(specifier);\n        var fill = match[1] || ' ';\n        var align = match[2] || '>';\n        var sign = match[3] || '';\n        var symbol = match[4] || '';\n        var zfill = match[5];\n        var width = +match[6];\n        var comma = match[7];\n        var precision = match[8];\n        var type = match[9];\n        var scale = 1;\n        var prefix = '';\n        var suffix = '';\n        var integer = false;\n\n        if (precision) precision = +precision.substring(1);\n\n        if (zfill || fill === '0' && align === '=') {\n            zfill = fill = '0';\n            align = '=';\n            if (comma) width -= Math.floor((width - 1) / 4);\n        }\n\n        switch (type) {\n            case 'n':\n                comma = true;\n                type = 'g';\n                break;\n            case '%':\n                scale = 100;\n                suffix = '%';\n                type = 'f';\n                break;\n            case 'p':\n                scale = 100;\n                suffix = '%';\n                type = 'r';\n                break;\n            case 'b':\n            case 'o':\n            case 'x':\n            case 'X':\n                if (symbol === '#') prefix = '0' + type.toLowerCase();\n                break;\n            case 'c':\n            case 'd':\n                integer = true;\n                precision = 0;\n                break;\n            case 's':\n                scale = -1;\n                type = 'r';\n                break;\n        }\n\n        if (symbol === '$') {\n            prefix = locale.currency[0];\n            suffix = locale.currency[1];\n        }\n\n        // If no precision is specified for `'r'`, fallback to general notation.\n        if (type == 'r' && !precision) type = 'g';\n\n        // Ensure that the requested precision is in the supported range.\n        if (precision != null) {\n            if (type == 'g') precision = Math.max(1, Math.min(21, precision));\n            else if (type == 'e' || type == 'f') precision = Math.max(0, Math.min(20, precision));\n        }\n\n        var zcomma = zfill && comma;\n\n        // Return the empty string for floats formatted as ints.\n        if (integer && (value % 1)) return '';\n\n        // Convert negative to positive, and record the sign prefix.\n        var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, '-') : sign;\n\n        var fullSuffix = suffix;\n\n        // Apply the scale, computing it from the value's exponent for si format.\n        // Preserve the existing suffix, if any, such as the currency symbol.\n        if (scale < 0) {\n            var unit = this.prefix(value, precision);\n            value = unit.scale(value);\n            fullSuffix = unit.symbol + suffix;\n        } else {\n            value *= scale;\n        }\n\n        // Convert to the desired precision.\n        value = this.convert(type, value, precision);\n\n        // Break the value into the integer part (before) and decimal part (after).\n        var i = value.lastIndexOf('.');\n        var before = i < 0 ? value : value.substring(0, i);\n        var after = i < 0 ? '' : locale.decimal + value.substring(i + 1);\n\n        function formatGroup(value) {\n\n            var i = value.length;\n            var t = [];\n            var j = 0;\n            var g = locale.grouping[0];\n            while (i > 0 && g > 0) {\n                t.push(value.substring(i -= g, i + g));\n                g = locale.grouping[j = (j + 1) % locale.grouping.length];\n            }\n            return t.reverse().join(locale.thousands);\n        }\n\n        // If the fill character is not `'0'`, grouping is applied before padding.\n        if (!zfill && comma && locale.grouping) {\n\n            before = formatGroup(before);\n        }\n\n        var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length);\n        var padding = length < width ? new Array(length = width - length + 1).join(fill) : '';\n\n        // If the fill character is `'0'`, grouping is applied after padding.\n        if (zcomma) before = formatGroup(padding + before);\n\n        // Apply prefix.\n        negative += prefix;\n\n        // Rejoin integer and decimal parts.\n        value = before + after;\n\n        return (align === '<' ? negative + value + padding\n            : align === '>' ? padding + negative + value\n                : align === '^' ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length)\n                    : negative + (zcomma ? value : padding + value)) + fullSuffix;\n    },\n\n    // Formatting string via the Python Format string.\n    // See https://docs.python.org/2/library/string.html#format-string-syntax)\n    string: function(formatString, value) {\n\n        var fieldDelimiterIndex;\n        var fieldDelimiter = '{';\n        var endPlaceholder = false;\n        var formattedStringArray = [];\n\n        while ((fieldDelimiterIndex = formatString.indexOf(fieldDelimiter)) !== -1) {\n\n            var pieceFormattedString, formatSpec, fieldName;\n\n            pieceFormattedString = formatString.slice(0, fieldDelimiterIndex);\n\n            if (endPlaceholder) {\n                formatSpec = pieceFormattedString.split(':');\n                fieldName = formatSpec.shift().split('.');\n                pieceFormattedString = value;\n\n                for (var i = 0; i < fieldName.length; i++)\n                    pieceFormattedString = pieceFormattedString[fieldName[i]];\n\n                if (formatSpec.length)\n                    pieceFormattedString = this.number(formatSpec, pieceFormattedString);\n            }\n\n            formattedStringArray.push(pieceFormattedString);\n\n            formatString = formatString.slice(fieldDelimiterIndex + 1);\n            endPlaceholder = !endPlaceholder;\n            fieldDelimiter = (endPlaceholder) ? '}' : '{';\n        }\n        formattedStringArray.push(formatString);\n\n        return formattedStringArray.join('');\n    },\n\n    convert: function(type, value, precision) {\n\n        switch (type) {\n            case 'b':\n                return value.toString(2);\n            case 'c':\n                return String.fromCharCode(value);\n            case 'o':\n                return value.toString(8);\n            case 'x':\n                return value.toString(16);\n            case 'X':\n                return value.toString(16).toUpperCase();\n            case 'g':\n                return value.toPrecision(precision);\n            case 'e':\n                return value.toExponential(precision);\n            case 'f':\n                return value.toFixed(precision);\n            case 'r':\n                return (value = this.round(value, this.precision(value, precision))).toFixed(Math.max(0, Math.min(20, this.precision(value * (1 + 1e-15), precision))));\n            default:\n                return value + '';\n        }\n    },\n\n    round: function(value, precision) {\n\n        return precision\n            ? Math.round(value * (precision = Math.pow(10, precision))) / precision\n            : Math.round(value);\n    },\n\n    precision: function(value, precision) {\n\n        return precision - (value ? Math.ceil(Math.log(value) / Math.LN10) : 1);\n    },\n\n    prefix: function(value, precision) {\n\n        var prefixes = ['y', 'z', 'a', 'f', 'p', 'n', 'µ', 'm', '', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'].map(function(d, i) {\n            var k = Math.pow(10, Math.abs(8 - i) * 3);\n            return {\n                scale: i > 8 ? function(d) {\n                    return d / k;\n                } : function(d) {\n                    return d * k;\n                },\n                symbol: d\n            };\n        });\n\n        var i = 0;\n        if (value) {\n            if (value < 0) value *= -1;\n            if (precision) value = this.round(value, this.precision(value, precision));\n            i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);\n            i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3));\n        }\n        return prefixes[8 + i / 3];\n    }\n};\n\n/*\n    Pre-compile the HTML to be used as a template.\n*/\nexport const template = function(html) {\n\n    /*\n        Must support the variation in templating syntax found here:\n        https://lodash.com/docs#template\n    */\n    var regex = /<%= ([^ ]+) %>|\\$\\{ ?([^{} ]+) ?\\}|\\{\\{([^{} ]+)\\}\\}/g;\n\n    return function(data) {\n\n        data = data || {};\n\n        return html.replace(regex, function(match) {\n\n            var args = Array.from(arguments);\n            var attr = args.slice(1, 4).find(function(_attr) {\n                return !!_attr;\n            });\n\n            var attrArray = attr.split('.');\n            var value = data[attrArray.shift()];\n\n            while (value !== undefined && attrArray.length) {\n                value = value[attrArray.shift()];\n            }\n\n            return value !== undefined ? value : '';\n        });\n    };\n};\n\n/**\n * @param {Element} el Element, which content is intent to display in full-screen mode, 'window.top.document.body' is default.\n */\nexport const toggleFullScreen = function(el) {\n\n    var topDocument = window.top.document;\n    el = el || topDocument.body;\n\n    function prefixedResult(el, prop) {\n\n        var prefixes = ['webkit', 'moz', 'ms', 'o', ''];\n        for (var i = 0; i < prefixes.length; i++) {\n            var prefix = prefixes[i];\n            var propName = prefix ? (prefix + prop) : (prop.substr(0, 1).toLowerCase() + prop.substr(1));\n            if (el[propName] !== undefined) {\n                return isFunction(el[propName]) ? el[propName]() : el[propName];\n            }\n        }\n    }\n\n    if (prefixedResult(topDocument, 'FullscreenElement') || prefixedResult(topDocument, 'FullScreenElement')) {\n        prefixedResult(topDocument, 'ExitFullscreen') || // Spec.\n        prefixedResult(topDocument, 'CancelFullScreen'); // Firefox\n    } else {\n        prefixedResult(el, 'RequestFullscreen') || // Spec.\n        prefixedResult(el, 'RequestFullScreen'); // Firefox\n    }\n};\n\nfunction findDifference(obj, baseObj, currentDepth, maxDepth) {\n\n    if (currentDepth === maxDepth) {\n        return {};\n    }\n\n    const diff = {};\n\n    Object.keys(obj).forEach((key) => {\n\n        const objValue = obj[key];\n        const baseValue = baseObj[key];\n\n        if (!Array.isArray(objValue) && !Array.isArray(baseValue) && isObject(objValue) && isObject(baseValue)) {\n\n            const nestedDepth = currentDepth + 1;\n            const nestedDiff = findDifference(objValue, baseValue, nestedDepth, maxDepth);\n\n            if (Object.keys(nestedDiff).length > 0) {\n                diff[key] = nestedDiff;\n            } else if ((currentDepth === 0 || nestedDepth === maxDepth)) {\n                diff[key] = {};\n            }\n\n        } else if (!isEqual(objValue, baseValue)) {\n            diff[key] = objValue;\n        }\n    });\n\n    return diff;\n}\n\nexport function objectDifference(object, base, opt) {\n\n    const { maxDepth = Number.POSITIVE_INFINITY } = opt || {};\n\n    return findDifference(object, base, 0, maxDepth);\n}\n\nexport {\n    isBoolean,\n    isObject,\n    isNumber,\n    isString,\n    mixin,\n    deepMixin,\n    supplement,\n    defaults,\n    deepSupplement,\n    defaultsDeep,\n    assign,\n    invoke,\n    invokeProperty,\n    sortedIndex,\n    uniq,\n    clone,\n    cloneDeep,\n    isEmpty,\n    isEqual,\n    isFunction,\n    isPlainObject,\n    toArray,\n    debounce,\n    groupBy,\n    sortBy,\n    flattenDeep,\n    without,\n    difference,\n    intersection,\n    union,\n    has,\n    result,\n    omit,\n    pick,\n    bindAll,\n    forIn,\n    camelCase,\n    uniqueId,\n    merge\n};\n\nexport const noop = function() {\n};\n","import {\n    isEmpty,\n    uniqueId \n} from '../util/util.mjs';\n\n// Events\n// ---------------\n\n// A module that can be mixed in to *any object* in order to provide it with\n// a custom event channel. You may bind a callback to an event with `on` or\n// remove with `off`; `trigger`-ing an event fires all callbacks in\n// succession.\n//\n//     const object = {};\n//     assign(object, Events);\n//     object.on('expand', function(){ alert('expanded'); });\n//     object.trigger('expand');\n//\nexport var Events = {};\n\n// Regular expression used to split event strings.\nvar eventSplitter = /\\s+/;\n\n// A private global variable to share between listeners and listenees.\nvar _listening;\n\n// Iterates over the standard `event, callback` (as well as the fancy multiple\n// space-separated events `\"change blur\", callback` and jQuery-style event\n// maps `{event: callback}`).\nvar eventsApi = function(iteratee, events, name, callback, opts) {\n    var i = 0, names;\n    if (name && typeof name === 'object') {\n    // Handle event maps.\n        if (callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback;\n        for (names = Object.keys(name); i < names.length ; i++) {\n            events = eventsApi(iteratee, events, names[i], name[names[i]], opts);\n        }\n    } else if (name && eventSplitter.test(name)) {\n    // Handle space-separated event names by delegating them individually.\n        for (names = name.split(eventSplitter); i < names.length; i++) {\n            events = iteratee(events, names[i], callback, opts);\n        }\n    } else {\n    // Finally, standard events.\n        events = iteratee(events, name, callback, opts);\n    }\n    return events;\n};\n\n// Bind an event to a `callback` function. Passing `\"all\"` will bind\n// the callback to all events fired.\nEvents.on = function(name, callback, context) {\n    this._events = eventsApi(onApi, this._events || {}, name, callback, {\n        context: context,\n        ctx: this,\n        listening: _listening\n    });\n\n    if (_listening) {\n        var listeners = this._listeners || (this._listeners = {});\n        listeners[_listening.id] = _listening;\n        // Allow the listening to use a counter, instead of tracking\n        // callbacks for library interop\n        _listening.interop = false;\n    }\n\n    return this;\n};\n\n// Inversion-of-control versions of `on`. Tell *this* object to listen to\n// an event in another object... keeping track of what it's listening to\n// for easier unbinding later.\nEvents.listenTo = function(obj, name, callback) {\n    if (!obj) return this;\n    var id = obj._listenId || (obj._listenId = uniqueId('l'));\n    var listeningTo = this._listeningTo || (this._listeningTo = {});\n    var listening = _listening = listeningTo[id];\n\n    // This object is not listening to any other events on `obj` yet.\n    // Setup the necessary references to track the listening callbacks.\n    if (!listening) {\n        this._listenId || (this._listenId = uniqueId('l'));\n        listening = _listening = listeningTo[id] = new Listening(this, obj);\n    }\n\n    // Bind callbacks on obj.\n    var error = tryCatchOn(obj, name, callback, this);\n    _listening = void 0;\n\n    if (error) throw error;\n    // If the target obj is not Events, track events manually.\n    if (listening.interop) listening.on(name, callback);\n\n    return this;\n};\n\n// The reducing API that adds a callback to the `events` object.\nvar onApi = function(events, name, callback, options) {\n    if (callback) {\n        var handlers = events[name] || (events[name] = []);\n        var context = options.context, ctx = options.ctx, listening = options.listening;\n        if (listening) listening.count++;\n\n        handlers.push({ callback: callback, context: context, ctx: context || ctx, listening: listening });\n    }\n    return events;\n};\n\n// An try-catch guarded #on function, to prevent poisoning the global\n// `_listening` variable.\nvar tryCatchOn = function(obj, name, callback, context) {\n    try {\n        obj.on(name, callback, context);\n    } catch (e) {\n        return e;\n    }\n};\n\n// Remove one or many callbacks. If `context` is null, removes all\n// callbacks with that function. If `callback` is null, removes all\n// callbacks for the event. If `name` is null, removes all bound\n// callbacks for all events.\nEvents.off = function(name, callback, context) {\n    if (!this._events) return this;\n    this._events = eventsApi(offApi, this._events, name, callback, {\n        context: context,\n        listeners: this._listeners\n    });\n\n    return this;\n};\n\n// Tell this object to stop listening to either specific events ... or\n// to every object it's currently listening to.\nEvents.stopListening = function(obj, name, callback) {\n    var listeningTo = this._listeningTo;\n    if (!listeningTo) return this;\n\n    var ids = obj ? [obj._listenId] : Object.keys(listeningTo);\n    for (var i = 0; i < ids.length; i++) {\n        var listening = listeningTo[ids[i]];\n\n        // If listening doesn't exist, this object is not currently\n        // listening to obj. Break out early.\n        if (!listening) break;\n\n        listening.obj.off(name, callback, this);\n        if (listening.interop) listening.off(name, callback);\n    }\n    if (isEmpty(listeningTo)) this._listeningTo = void 0;\n\n    return this;\n};\n\n// The reducing API that removes a callback from the `events` object.\nvar offApi = function(events, name, callback, options) {\n    if (!events) return;\n\n    var context = options.context, listeners = options.listeners;\n    var i = 0, names;\n\n    // Delete all event listeners and \"drop\" events.\n    if (!name && !context && !callback) {\n        if(listeners != null) {\n            for (names = Object.keys(listeners); i < names.length; i++) {\n                listeners[names[i]].cleanup();\n            }\n        }\n        return;\n    }\n    names = name ? [name] : Object.keys(events);\n    for (; i < names.length; i++) {\n        name = names[i];\n        var handlers = events[name];\n\n        // Bail out if there are no events stored.\n        if (!handlers) break;\n\n        // Find any remaining events.\n        var remaining = [];\n        for (var j = 0; j < handlers.length; j++) {\n            var handler = handlers[j];\n            if (\n                callback && callback !== handler.callback &&\n        callback !== handler.callback._callback ||\n          context && context !== handler.context\n            ) {\n                remaining.push(handler);\n            } else {\n                var listening = handler.listening;\n                if (listening) listening.off(name, callback);\n            }\n        }\n\n        // Replace events if there are any remaining.  Otherwise, clean up.\n        if (remaining.length) {\n            events[name] = remaining;\n        } else {\n            delete events[name];\n        }\n    }\n\n    return events;\n};\n\n// Bind an event to only be triggered a single time. After the first time\n// the callback is invoked, its listener will be removed. If multiple events\n// are passed in using the space-separated syntax, the handler will fire\n// once for each event, not once for a combination of all events.\nEvents.once = function(name, callback, context) {\n// Map the event into a `{event: once}` object.\n    var events = eventsApi(onceMap, {}, name, callback, this.off.bind(this));\n    if (typeof name === 'string' && context == null) callback = void 0;\n    return this.on(events, callback, context);\n};\n\n// Inversion-of-control versions of `once`.\nEvents.listenToOnce = function(obj, name, callback) {\n// Map the event into a `{event: once}` object.\n    var events = eventsApi(onceMap, {}, name, callback, this.stopListening.bind(this, obj));\n    return this.listenTo(obj, events);\n};\n\n// Reduces the event callbacks into a map of `{event: onceWrapper}`.\n// `offer` unbinds the `onceWrapper` after it has been called.\nvar onceMap = function(map, name, callback, offer) {\n    if (callback) {\n        var once = map[name] = onceInvoke(function() {\n            offer(name, once);\n            callback.apply(this, arguments);\n        });\n        once._callback = callback;\n    }\n    return map;\n};\n\n// Creates a function that is restricted to invoking 'func' once.\n// Repeat calls to the function return the value of the first invocation.\nvar onceInvoke = function(func) {\n    var result;\n    if (typeof func != 'function') {\n        throw new TypeError('Expected a function');\n    }\n    var n = 2;\n    return function() {\n        if (--n > 0) {\n            result = func.apply(this, arguments);\n        }\n        if (n <= 1) {\n            func = undefined;\n        }\n        return result;\n    };\n};\n\n// Trigger one or many events, firing all bound callbacks. Callbacks are\n// passed the same arguments as `trigger` is, apart from the event name\n// (unless you're listening on `\"all\"`, which will cause your callback to\n// receive the true name of the event as the first argument).\nEvents.trigger = function(name) {\n    if (!this._events) return this;\n\n    var length = Math.max(0, arguments.length - 1);\n    var args = Array(length);\n    for (var i = 0; i < length; i++) args[i] = arguments[i + 1];\n\n    eventsApi(triggerApi, this._events, name, void 0, args);\n    return this;\n};\n\n// Handles triggering the appropriate event callbacks.\nvar triggerApi = function(objEvents, name, callback, args) {\n    if (objEvents) {\n        var events = objEvents[name];\n        var allEvents = objEvents.all;\n        if (events && allEvents) allEvents = allEvents.slice();\n        if (events) triggerEvents(events, args);\n        if (allEvents) triggerEvents(allEvents, [name].concat(args));\n    }\n    return objEvents;\n};\n\n// A difficult-to-believe, but optimized internal dispatch function for\n// triggering events. Tries to keep the usual cases speedy (most internal\n// events have 3 arguments).\nvar triggerEvents = function(events, args) {\n    var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];\n    switch (args.length) {\n        case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return;\n        case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;\n        case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;\n        case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;\n        default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return;\n    }\n};\n\n// A listening class that tracks and cleans up memory bindings\n// when all callbacks have been offed.\nvar Listening = function(listener, obj) {\n    this.id = listener._listenId;\n    this.listener = listener;\n    this.obj = obj;\n    this.interop = true;\n    this.count = 0;\n    this._events = void 0;\n};\n\nListening.prototype.on = Events.on;\n\n// Offs a callback (or several).\n// Uses an optimized counter if the listenee uses Events.\n// Otherwise, falls back to manual tracking to support events\n// library interop.\nListening.prototype.off = function(name, callback) {\n    var cleanup;\n    if (this.interop) {\n        this._events = eventsApi(offApi, this._events, name, callback, {\n            context: void 0,\n            listeners: void 0\n        });\n        cleanup = !this._events;\n    } else {\n        this.count--;\n        cleanup = this.count === 0;\n    }\n    if (cleanup) this.cleanup();\n};\n\n// Cleans up memory bindings between the listener and the listenee.\nListening.prototype.cleanup = function() {\n    delete this.listener._listeningTo[this.obj._listenId];\n    if (!this.interop) delete this.obj._listeners[this.id];\n};\n\n// Aliases for backwards compatibility.\nEvents.bind   = Events.on;\nEvents.unbind = Events.off;\n","import {\n    assign,\n    forIn,\n    has,\n    isFunction,\n    isObject,\n    isString\n} from '../util/util.mjs';\nimport { matches } from '../util/utilHelpers.mjs';\n\n// Helpers\n// -------\n\n// Helper function to correctly set up the prototype chain for subclasses.\n// Similar to `goog.inherits`, but uses a hash of prototype properties and\n// class properties to be extended.\nexport var extend = function(protoProps, staticProps) {\n    var parent = this;\n    var child;\n\n    // The constructor function for the new subclass is either defined by you\n    // (the \"constructor\" property in your `extend` definition), or defaulted\n    // by us to simply call the parent constructor.\n    if (protoProps && has(protoProps, 'constructor')) {\n        child = protoProps.constructor;\n    } else {\n        child = function(){ return parent.apply(this, arguments); };\n    }\n\n    // Add static properties to the constructor function, if supplied.\n    assign(child, parent, staticProps);\n\n    // Set the prototype chain to inherit from `parent`, without calling\n    // `parent`'s constructor function and add the prototype properties.\n    child.prototype = Object.assign(Object.create(parent.prototype), protoProps);\n    child.prototype.constructor = child;\n\n    // Set a convenience property in case the parent's prototype is needed\n    // later.\n    child.__super__ = parent.prototype;\n\n    return child;\n};\n\n// Proxy class methods to functions, wrapping the model's\n// `attributes` object or collection's `models` array behind the scenes.\n//\n// `Function#apply` can be slow so we use the method's arg count, if we know it.\nvar addMethod = function(base, length, method, attribute) {\n    switch (length) {\n        case 1: return function() {\n            return base[method](this[attribute]);\n        };\n        case 2: return function(value) {\n            return base[method](this[attribute], value);\n        };\n        case 3: return function(iteratee, context) {\n            return base[method](this[attribute], cb(iteratee, this), context);\n        };\n        case 4: return function(iteratee, defaultVal, context) {\n            return base[method](this[attribute], cb(iteratee, this), defaultVal, context);\n        };\n        default: return function() {\n            var args = Array.prototype.slice.call(arguments);\n            args.unshift(this[attribute]);\n            return base[method].apply(base, args);\n        };\n    }\n};\n\nexport var addMethodsUtil = function(Class, base, methods, attribute) {\n    forIn(methods, function(length, method) {\n        if (base[method]) Class.prototype[method] = addMethod(base, length, method, attribute);\n    });\n};\n\n// Support `collection.sortBy('attr')`.\nvar cb = function(iteratee, instance) {\n    if (isFunction(iteratee)) return iteratee;\n    if (isObject(iteratee) && !instance._isModel(iteratee)) return modelMatcher(iteratee);\n    if (isString(iteratee)) return function(model) { return model.get(iteratee); };\n    return iteratee;\n};\n\nvar modelMatcher = function(attrs) {\n    var matcher = matches(attrs);\n    return function(model) {\n        return matcher(model.attributes);\n    };\n};\n","import { Events } from './Events.mjs';\nimport { extend } from './mvcUtils.mjs';\nimport {\n    assign,\n    clone,\n    defaults,\n    has,\n    isEqual,\n    isEmpty,\n    result,\n    uniqueId\n} from '../util/util.mjs';\n\n// Model\n// --------------\n\n// **Models** are the basic data object in the framework --\n// frequently representing a row in a table in a database on your server.\n// A discrete chunk of data and a bunch of useful, related methods for\n// performing computations and transformations on that data.\n\n// Create a new model with the specified attributes. A client id (`cid`)\n// is automatically generated and assigned for you.\n\nexport var Model = function(attributes, options) {\n    var attrs = attributes || {};\n    options || (options = {});\n    this.preinitialize.apply(this, arguments);\n    this.cid = uniqueId(this.cidPrefix);\n    this.attributes = {};\n    if (options.collection) this.collection = options.collection;\n    var attributeDefaults = result(this, 'defaults');\n\n    // Just _.defaults would work fine, but the additional _.extends\n    // is in there for historical reasons. See #3843.\n    attrs = defaults(assign({}, attributeDefaults, attrs), attributeDefaults);\n\n    this.set(attrs, options);\n    this.changed = {};\n    this.initialize.apply(this, arguments);\n};\n\n// Attach all inheritable methods to the Model prototype.\nassign(Model.prototype, Events, {\n\n    // A hash of attributes whose current and previous value differ.\n    changed: null,\n\n    // The value returned during the last failed validation.\n    validationError: null,\n\n    // The default name for the JSON `id` attribute is `\"id\"`. MongoDB and\n    // CouchDB users may want to set this to `\"_id\"`.\n    idAttribute: 'id',\n\n    // The prefix is used to create the client id which is used to identify models locally.\n    // You may want to override this if you're experiencing name clashes with model ids.\n    cidPrefix: 'c',\n\n    // preinitialize is an empty function by default. You can override it with a function\n    // or object.  preinitialize will run before any instantiation logic is run in the Model.\n    preinitialize: function(){},\n\n    // Initialize is an empty function by default. Override it with your own\n    // initialization logic.\n    initialize: function(){},\n\n    // Return a copy of the model's `attributes` object.\n    toJSON: function(options) {\n        return clone(this.attributes);\n    },\n\n    // Get the value of an attribute.\n    get: function(attr) {\n        return this.attributes[attr];\n    },\n\n    // Returns `true` if the attribute contains a value that is not null\n    // or undefined.\n    has: function(attr) {\n        return this.get(attr) != null;\n    },\n\n    // Set a hash of model attributes on the object, firing `\"change\"`. This is\n    // the core primitive operation of a model, updating the data and notifying\n    // anyone who needs to know about the change in state. The heart of the beast.\n    set: function(key, val, options) {\n        if (key == null) return this;\n\n        // Handle both `\"key\", value` and `{key: value}` -style arguments.\n        var attrs;\n        if (typeof key === 'object') {\n            attrs = key;\n            options = val;\n        } else {\n            (attrs = {})[key] = val;\n        }\n\n        options || (options = {});\n\n        // Run validation.\n        if (!this._validate(attrs, options)) return false;\n\n        // Extract attributes and options.\n        var unset      = options.unset;\n        var silent     = options.silent;\n        var changes    = [];\n        var changing   = this._changing;\n        this._changing = true;\n\n        if (!changing) {\n            this._previousAttributes = clone(this.attributes);\n            this.changed = {};\n        }\n\n        var current = this.attributes;\n        var changed = this.changed;\n        var prev    = this._previousAttributes;\n\n        // For each `set` attribute, update or delete the current value.\n        for (var attr in attrs) {\n            val = attrs[attr];\n            if (!isEqual(current[attr], val)) changes.push(attr);\n            if (!isEqual(prev[attr], val)) {\n                changed[attr] = val;\n            } else {\n                delete changed[attr];\n            }\n            unset ? delete current[attr] : current[attr] = val;\n        }\n\n        // Update the `id`.\n        if (this.idAttribute in attrs) {\n            var prevId = this.id;\n            this.id = this.get(this.idAttribute);\n            this.trigger('changeId', this, prevId, options);\n        }\n\n        // Trigger all relevant attribute changes.\n        if (!silent) {\n            if (changes.length) this._pending = options;\n            for (var i = 0; i < changes.length; i++) {\n                this.trigger('change:' + changes[i], this, current[changes[i]], options);\n            }\n        }\n\n        // You might be wondering why there's a `while` loop here. Changes can\n        // be recursively nested within `\"change\"` events.\n        if (changing) return this;\n        if (!silent) {\n            while (this._pending) {\n                options = this._pending;\n                this._pending = false;\n                this.trigger('change', this, options);\n            }\n        }\n        this._pending = false;\n        this._changing = false;\n        return this;\n    },\n\n    // Remove an attribute from the model, firing `\"change\"`. `unset` is a noop\n    // if the attribute doesn't exist.\n    unset: function(attr, options) {\n        return this.set(attr, void 0, assign({}, options, { unset: true }));\n    },\n\n    // Clear all attributes on the model, firing `\"change\"`.\n    clear: function(options) {\n        var attrs = {};\n        for (var key in this.attributes) attrs[key] = void 0;\n        return this.set(attrs, assign({}, options, { unset: true }));\n    },\n\n    // Determine if the model has changed since the last `\"change\"` event.\n    // If you specify an attribute name, determine if that attribute has changed.\n    hasChanged: function(attr) {\n        if (attr == null) return !isEmpty(this.changed);\n        return has(this.changed, attr);\n    },\n\n    // Return an object containing all the attributes that have changed, or\n    // false if there are no changed attributes. Useful for determining what\n    // parts of a view need to be updated and/or what attributes need to be\n    // persisted to the server. Unset attributes will be set to undefined.\n    // You can also pass an attributes object to diff against the model,\n    // determining if there *would be* a change.\n    changedAttributes: function(diff) {\n        if (!diff) return this.hasChanged() ? clone(this.changed) : false;\n        var old = this._changing ? this._previousAttributes : this.attributes;\n        var changed = {};\n        var hasChanged;\n        for (var attr in diff) {\n            var val = diff[attr];\n            if (isEqual(old[attr], val)) continue;\n            changed[attr] = val;\n            hasChanged = true;\n        }\n        return hasChanged ? changed : false;\n    },\n\n    // Get the previous value of an attribute, recorded at the time the last\n    // `\"change\"` event was fired.\n    previous: function(attr) {\n        if (attr == null || !this._previousAttributes) return null;\n        return this._previousAttributes[attr];\n    },\n\n    // Get all of the attributes of the model at the time of the previous\n    // `\"change\"` event.\n    previousAttributes: function() {\n        return clone(this._previousAttributes);\n    },\n\n    // Create a new model with identical attributes to this one.\n    clone: function() {\n        return new this.constructor(this.attributes);\n    },\n\n    // Check if the model is currently in a valid state.\n    isValid: function(options) {\n        return this._validate({}, assign({}, options, { validate: true }));\n    },\n\n    // Run validation against the next complete set of model attributes,\n    // returning `true` if all is well. Otherwise, fire an `\"invalid\"` event.\n    _validate: function(attrs, options) {\n        if (!options.validate || !this.validate) return true;\n        attrs = assign({}, this.attributes, attrs);\n        var error = this.validationError = this.validate(attrs, options) || null;\n        if (!error) return true;\n        this.trigger('invalid', this, error, assign(options, { validationError: error }));\n        return false;\n    }\n\n});\n\n// Set up inheritance for the model.\nModel.extend = extend;\n","import { uniq, toArray, isEmpty } from './util.mjs';\n\n// Clone `cells` returning an object that maps the original cell ID to the clone. The number\n// of clones is exactly the same as the `cells.length`.\n// This function simply clones all the `cells`. However, it also reconstructs\n// all the `source/target` and `parent/embed` references within the `cells`.\n// This is the main difference from the `cell.clone()` method. The\n// `cell.clone()` method works on one single cell only.\n// For example, for a graph: `A --- L ---> B`, `cloneCells([A, L, B])`\n// returns `[A2, L2, B2]` resulting to a graph: `A2 --- L2 ---> B2`, i.e.\n// the source and target of the link `L2` is changed to point to `A2` and `B2`.\nexport function cloneCells(cells) {\n\n    cells = uniq(cells);\n\n    // A map of the form [original cell ID] -> [clone] helping\n    // us to reconstruct references for source/target and parent/embeds.\n    // This is also the returned value.\n    const cloneMap = toArray(cells).reduce(function(map, cell) {\n        map[cell.id] = cell.clone();\n        return map;\n    }, {});\n\n    toArray(cells).forEach(function(cell) {\n\n        const clone = cloneMap[cell.id];\n        // assert(clone exists)\n\n        if (clone.isLink()) {\n            const source = clone.source();\n            const target = clone.target();\n            if (source.id && cloneMap[source.id]) {\n                // Source points to an element and the element is among the clones.\n                // => Update the source of the cloned link.\n                clone.prop('source/id', cloneMap[source.id].id);\n            }\n            if (target.id && cloneMap[target.id]) {\n                // Target points to an element and the element is among the clones.\n                // => Update the target of the cloned link.\n                clone.prop('target/id', cloneMap[target.id].id);\n            }\n        }\n\n        // Find the parent of the original cell\n        const parent = cell.get('parent');\n        if (parent && cloneMap[parent]) {\n            clone.set('parent', cloneMap[parent].id);\n        }\n\n        // Find the embeds of the original cell\n        const embeds = toArray(cell.get('embeds')).reduce(function(newEmbeds, embed) {\n            // Embedded cells that are not being cloned can not be carried\n            // over with other embedded cells.\n            if (cloneMap[embed]) {\n                newEmbeds.push(cloneMap[embed].id);\n            }\n            return newEmbeds;\n        }, []);\n\n        if (!isEmpty(embeds)) {\n            clone.set('embeds', embeds);\n        }\n    });\n\n    return cloneMap;\n}\n\n","import { isPlainObject } from '../../util/util.mjs';\n\nconst validPropertiesList = ['checked', 'selected', 'disabled', 'readOnly', 'contentEditable', 'value', 'indeterminate'];\n\nconst validProperties = validPropertiesList.reduce((acc, key) => {\n    acc[key] = true;\n    return acc;\n}, {});\n\nconst props = {\n    qualify: function(properties) {\n        return isPlainObject(properties);\n    },\n    set: function(properties, _, node) {\n        Object.keys(properties).forEach(function(key) {\n            if (validProperties[key] && key in node) {\n                const value = properties[key];\n                if (node.tagName === 'SELECT' && Array.isArray(value)) {\n                    Array.from(node.options).forEach(function(option, index) {\n                        option.selected = value.includes(option.value);\n                    });\n                } else {\n                    node[key] = value;\n                }\n            }\n        });\n    }\n};\n\nexport default props;\n","import { Point } from '../../g/index.mjs';\nimport { isPercentage } from '../../util/util.mjs';\n\nfunction positionWrapper(axis, dimension, origin) {\n    return function(value, refBBox) {\n        var valuePercentage = isPercentage(value);\n        value = parseFloat(value);\n        if (valuePercentage) {\n            value /= 100;\n        }\n\n        var delta;\n        if (isFinite(value)) {\n            var refOrigin = refBBox[origin]();\n            if (valuePercentage || value > 0 && value < 1) {\n                delta = refOrigin[axis] + refBBox[dimension] * value;\n            } else {\n                delta = refOrigin[axis] + value;\n            }\n        }\n\n        var point = Point();\n        point[axis] = delta || 0;\n        return point;\n    };\n}\n\nfunction setWrapper(attrName, dimension) {\n    return function(value, refBBox) {\n        var isValuePercentage = isPercentage(value);\n        value = parseFloat(value);\n        if (isValuePercentage) {\n            value /= 100;\n        }\n\n        var attrs = {};\n        if (isFinite(value)) {\n            var attrValue = (isValuePercentage || value >= 0 && value <= 1)\n                ? value * refBBox[dimension]\n                : Math.max(value + refBBox[dimension], 0);\n            attrs[attrName] = attrValue;\n        }\n\n        return attrs;\n    };\n}\n\nconst legacyAttributesNS = {\n\n    // if `refX` is in [0, 1] then `refX` is a fraction of bounding box width\n    // if `refX` is < 0 then `refX`'s absolute values is the right coordinate of the bounding box\n    // otherwise, `refX` is the left coordinate of the bounding box\n    'ref-x': {\n        position: positionWrapper('x', 'width', 'origin')\n    },\n\n    'ref-y': {\n        position: positionWrapper('y', 'height', 'origin')\n    },\n\n    // `ref-dx` and `ref-dy` define the offset of the sub-element relative to the right and/or bottom\n    // coordinate of the reference element.\n\n    'ref-dx': {\n        position: positionWrapper('x', 'width', 'corner')\n    },\n\n    'ref-dy': {\n        position: positionWrapper('y', 'height', 'corner')\n    },\n\n    // 'ref-width'/'ref-height' defines the width/height of the sub-element relatively to\n    // the reference element size\n    // val in 0..1         ref-width = 0.75 sets the width to 75% of the ref. el. width\n    // val < 0 || val > 1  ref-height = -20 sets the height to the ref. el. height shorter by 20\n\n    'ref-width': {\n        set: setWrapper('width', 'width')\n    },\n\n    'ref-height': {\n        set: setWrapper('height', 'height')\n    },\n\n    'ref-rx': {\n        set: setWrapper('rx', 'width')\n    },\n\n    'ref-ry': {\n        set: setWrapper('ry', 'height')\n    },\n\n    'ref-cx': {\n        set: setWrapper('cx', 'width')\n    },\n\n    'ref-cy': {\n        set: setWrapper('cy', 'height')\n    },\n\n    'ref-r-inscribed': {\n        set: (function(attrName) {\n            var widthFn = setWrapper(attrName, 'width');\n            var heightFn = setWrapper(attrName, 'height');\n            return function(value, refBBox) {\n                var fn = (refBBox.height > refBBox.width) ? widthFn : heightFn;\n                return fn(value, refBBox);\n            };\n        })('r')\n    },\n\n    'ref-r-circumscribed': {\n        set: function(value, refBBox) {\n            var isValuePercentage = isPercentage(value);\n            value = parseFloat(value);\n            if (isValuePercentage) {\n                value /= 100;\n            }\n\n            var diagonalLength = Math.sqrt((refBBox.height * refBBox.height) + (refBBox.width * refBBox.width));\n\n            var rValue;\n            if (isFinite(value)) {\n                if (isValuePercentage || value >= 0 && value <= 1) rValue = value * diagonalLength;\n                else rValue = Math.max(value + diagonalLength, 0);\n            }\n\n            return { r: rValue };\n        }\n    },\n};\n\n// NOTE: refX & refY are SVG attributes that define the reference point of the marker.\n// That's why we need to define both variants: `refX` and `ref-x` (and `refY` and `ref-y`).\nlegacyAttributesNS['refX'] = legacyAttributesNS['ref-x'];\nlegacyAttributesNS['refY'] = legacyAttributesNS['ref-y'];\n\n// This allows to combine both absolute and relative positioning\n// refX: 50%, refX2: 20\nlegacyAttributesNS['ref-x2'] = legacyAttributesNS['ref-x'];\nlegacyAttributesNS['ref-y2'] = legacyAttributesNS['ref-y'];\nlegacyAttributesNS['ref-width2'] = legacyAttributesNS['ref-width'];\nlegacyAttributesNS['ref-height2'] = legacyAttributesNS['ref-height'];\n\n// Aliases\nlegacyAttributesNS['ref-r'] = legacyAttributesNS['ref-r-inscribed'];\n\nexport default legacyAttributesNS;\n","const props = {\n    x: 'x',\n    y: 'y',\n    width: 'w',\n    height: 'h',\n    minimum: 's',\n    maximum: 'l',\n    diagonal: 'd'\n};\nconst propsList = Object.keys(props).map(key => props[key]).join('');\nconst numberPattern = '[-+]?[0-9]*\\\\.?[0-9]+(?:[eE][-+]?[0-9]+)?';\nconst findSpacesRegex = /\\s/g;\nconst parseFormulaRegExp = new RegExp(`^(${numberPattern}\\\\*)?([${propsList}])(/${numberPattern})?([-+]{1,2}${numberPattern})?$`, 'g');\n\nfunction throwInvalid(expression) {\n    throw new Error(`Invalid calc() expression: ${expression}`);\n}\n\n/*\n* Evaluate the given calc formula.\n* e.g. 'w + 10' in a rect 100x100 -> 110\n*/\nexport function evalCalcFormula(formula, rect) {\n    const match = parseFormulaRegExp.exec(formula.replace(findSpacesRegex, ''));\n    if (!match) throwInvalid(formula);\n    parseFormulaRegExp.lastIndex = 0; // reset regex results for the next run\n    const [,multiply, property, divide, add] = match;\n    const { x, y, width, height } = rect;\n    let value = 0;\n    switch (property) {\n        case props.width: {\n            value = width;\n            break;\n        }\n        case props.height: {\n            value = height;\n            break;\n        }\n        case props.x: {\n            value = x;\n            break;\n        }\n        case props.y: {\n            value = y;\n            break;\n        }\n        case props.minimum: {\n            value = Math.min(height, width);\n            break;\n        }\n        case props.maximum: {\n            value = Math.max(height, width);\n            break;\n        }\n        case props.diagonal: {\n            value = Math.sqrt((height * height) + (width * width));\n            break;\n        }\n    }\n    if (multiply) {\n        // e.g \"2*\"\n        value *= parseFloat(multiply);\n    }\n    if (divide) {\n        // e.g \"/2\"\n        value /= parseFloat(divide.slice(1));\n    }\n    if (add) {\n        value += evalAddExpression(add);\n    }\n    return value;\n}\n\nfunction evalAddExpression(addExpression) {\n    if (!addExpression) return 0;\n    const [sign] = addExpression;\n    switch (sign) {\n        case '+': {\n            return parseFloat(addExpression.substr(1));\n        }\n        case '-': {\n            return -parseFloat(addExpression.substr(1));\n        }\n    }\n    return parseFloat(addExpression);\n}\n\n/*\n* Check if the given value is a calc expression.\n* e.g. 'calc(10 + 100)' -> true\n*/\nexport function isCalcExpression(value) {\n    return typeof value === 'string' && value.includes('calc');\n}\n\nconst calcStart = 'calc(';\nconst calcStartOffset = calcStart.length;\n\n/*\n* Evaluate all calc formulas in the given expression.\n* e.g. 'calc(w + 10)' in rect 100x100 -> '110'\n*/\nexport function evalCalcExpression(expression, rect) {\n    let value = expression;\n    let startSearchIndex = 0;\n    do {\n        let calcIndex = value.indexOf(calcStart, startSearchIndex);\n        if (calcIndex === -1) return value;\n        let calcEndIndex = calcIndex + calcStartOffset;\n        let brackets = 1;\n        findClosingBracket: do {\n            switch (value[calcEndIndex]) {\n                case '(': {\n                    brackets++;\n                    break;\n                }\n                case ')': {\n                    brackets--;\n                    if (brackets === 0) break findClosingBracket;\n                    break;\n                }\n                case undefined: {\n                    // Could not find the closing bracket.\n                    throwInvalid(value);\n                }\n            }\n            calcEndIndex++;\n        } while (true);\n        // Get the calc() expression without nested calcs (recursion)\n        let expression = value.slice(calcIndex + calcStartOffset, calcEndIndex);\n        if (isCalcExpression(expression)) {\n            expression = evalCalcExpression(expression, rect);\n        }\n        // Eval the calc() expression without nested calcs.\n        const calcValue = String(evalCalcFormula(expression, rect));\n        // Replace the calc() expression and continue search\n        value = value.slice(0, calcIndex) + calcValue + value.slice(calcEndIndex + 1);\n        startSearchIndex = calcIndex + calcValue.length;\n    } while (true);\n}\n","import { assign, isPlainObject, isObject, isPercentage, breakText } from '../../util/util.mjs';\nimport { isCalcExpression, evalCalcExpression } from '../../util/calc.mjs';\nimport $ from '../../mvc/Dom/index.mjs';\nimport V from '../../V/index.mjs';\n\nfunction isTextInUse(_value, _node, attrs) {\n    return (attrs.text !== undefined);\n}\n\nconst FONT_ATTRIBUTES = ['font-weight', 'font-family', 'font-size', 'letter-spacing', 'text-transform'];\n\nconst textAttributesNS = {\n\n    'line-height': {\n        qualify: isTextInUse\n    },\n\n    'text-vertical-anchor': {\n        qualify: isTextInUse\n    },\n\n    'text-path': {\n        qualify: isTextInUse\n    },\n\n    'annotations': {\n        qualify: isTextInUse\n    },\n\n    'eol': {\n        qualify: isTextInUse\n    },\n\n    'display-empty': {\n        qualify: isTextInUse\n    },\n\n    'text': {\n        qualify: function(_text, _node, attrs) {\n            const textWrap = attrs['text-wrap'];\n            return !textWrap || !isPlainObject(textWrap);\n        },\n        unset: function(node) {\n            node.textContent = '';\n        },\n        set: function(text, refBBox, node, attrs) {\n            const cacheName = 'joint-text';\n            const cache = $.data.get(node, cacheName);\n            const lineHeight = attrs['line-height'];\n            const textVerticalAnchor = attrs['text-vertical-anchor'];\n            const displayEmpty = attrs['display-empty'];\n            const fontSize = attrs['font-size'];\n            const annotations = attrs.annotations;\n            const eol = attrs.eol;\n            const x = attrs.x;\n            let textPath = attrs['text-path'];\n            // Update the text only if there was a change in the string\n            // or any of its attributes.\n            const textHash = JSON.stringify([text, lineHeight, annotations, textVerticalAnchor, eol, displayEmpty, textPath, x, fontSize]);\n            if (cache === undefined || cache !== textHash) {\n                // Chrome bug:\n                // <tspan> positions defined as `em` are not updated\n                // when container `font-size` change.\n                if (fontSize) node.setAttribute('font-size', fontSize);\n                // Text Along Path Selector\n                if (isObject(textPath)) {\n                    const pathSelector = textPath.selector;\n                    if (typeof pathSelector === 'string') {\n                        const pathNode = this.findNode(pathSelector);\n                        if (pathNode instanceof SVGPathElement) {\n                            textPath = assign({ 'xlink:href': '#' + pathNode.id }, textPath);\n                        }\n                    }\n                }\n                V(node).text('' + text, {\n                    lineHeight,\n                    annotations,\n                    textPath,\n                    x,\n                    textVerticalAnchor,\n                    eol,\n                    displayEmpty\n                });\n                $.data.set(node, cacheName, textHash);\n            }\n        }\n    },\n\n    'text-wrap': {\n        qualify: isPlainObject,\n        set: function(value, refBBox, node, attrs) {\n            var size = {};\n            // option `width`\n            var width = value.width || 0;\n            if (isPercentage(width)) {\n                size.width = refBBox.width * parseFloat(width) / 100;\n            } else if (isCalcExpression(width)) {\n                size.width = Number(evalCalcExpression(width, refBBox));\n            } else {\n                if (value.width === null) {\n                    // breakText() requires width to be specified.\n                    size.width = Infinity;\n                } else if (width <= 0) {\n                    size.width = refBBox.width + width;\n                } else {\n                    size.width = width;\n                }\n            }\n            // option `height`\n            var height = value.height || 0;\n            if (isPercentage(height)) {\n                size.height = refBBox.height * parseFloat(height) / 100;\n            } else if (isCalcExpression(height)) {\n                size.height = Number(evalCalcExpression(height, refBBox));\n            } else {\n                if (value.height === null) {\n                    // if height is not specified breakText() does not\n                    // restrict the height of the text.\n                } else if (height <= 0) {\n                    size.height = refBBox.height + height;\n                } else {\n                    size.height = height;\n                }\n            }\n            // option `text`\n            var wrappedText;\n            var text = value.text;\n            if (text === undefined) text = attrs.text;\n            if (text !== undefined) {\n\n                const breakTextFn = value.breakText || breakText;\n                const computedStyles = getComputedStyle(node);\n                const wrapFontAttributes = {};\n                // The font size attributes must be set on the node\n                // to get the correct text wrapping.\n                // TODO: set the native SVG attributes before special attributes\n                for (let i = 0; i < FONT_ATTRIBUTES.length; i++) {\n                    const name = FONT_ATTRIBUTES[i];\n                    if (name in attrs) {\n                        node.setAttribute(name, attrs[name]);\n                    }\n                    // Note: computedStyles is a live object\n                    // i.e. the properties are evaluated when accessed.\n                    wrapFontAttributes[name] = computedStyles[name];\n                }\n\n                // The `line-height` attribute in SVG is JoinJS specific.\n                // TODO: change the `lineHeight` to breakText option.\n                wrapFontAttributes.lineHeight = attrs['line-height'];\n\n                wrappedText = breakTextFn('' + text, size, wrapFontAttributes, {\n                    // Provide an existing SVG Document here\n                    // instead of creating a temporary one over again.\n                    svgDocument: this.paper.svg,\n                    ellipsis: value.ellipsis,\n                    hyphen: value.hyphen,\n                    separator: value.separator,\n                    maxLineCount: value.maxLineCount,\n                    preserveSpaces: value.preserveSpaces\n                });\n            } else {\n                wrappedText = '';\n            }\n            textAttributesNS.text.set.call(this, wrappedText, refBBox, node, attrs);\n        },\n        // We expose the font attributes list to allow\n        // the user to take other custom font attributes into account\n        // when wrapping the text.\n        FONT_ATTRIBUTES\n    },\n\n    'title': {\n        qualify: function(title, node) {\n            // HTMLElement title is specified via an attribute (i.e. not an element)\n            return node instanceof SVGElement;\n        },\n        unset: function(node) {\n            $.data.remove(node, 'joint-title');\n            const titleNode = node.firstElementChild;\n            if (titleNode) {\n                titleNode.remove();\n            }\n        },\n        set: function(title, refBBox, node) {\n            var cacheName = 'joint-title';\n            var cache = $.data.get(node, cacheName);\n            if (cache === undefined || cache !== title) {\n                $.data.set(node, cacheName, title);\n                if (node.tagName === 'title') {\n                    // The target node is a <title> element.\n                    node.textContent = title;\n                    return;\n                }\n                // Generally <title> element should be the first child element of its parent.\n                var firstChild = node.firstElementChild;\n                if (firstChild && firstChild.tagName === 'title') {\n                    // Update an existing title\n                    firstChild.textContent = title;\n                } else {\n                    // Create a new title\n                    var titleNode = document.createElementNS(node.namespaceURI, 'title');\n                    titleNode.textContent = title;\n                    node.insertBefore(titleNode, firstChild);\n                }\n            }\n        }\n    },\n};\n\nexport default textAttributesNS;\n","import { Point } from '../../g/index.mjs';\n\nfunction atConnectionWrapper(method, opt) {\n    var zeroVector = new Point(1, 0);\n    return function(value) {\n        var p, angle;\n        var tangent = this[method](value);\n        if (tangent) {\n            angle = (opt.rotate) ? tangent.vector().vectorAngle(zeroVector) : 0;\n            p = tangent.start;\n        } else {\n            p = this.path.start;\n            angle = 0;\n        }\n        if (angle === 0) return { transform: 'translate(' + p.x + ',' + p.y + ')' };\n        return { transform: 'translate(' + p.x + ',' + p.y + ') rotate(' + angle + ')' };\n    };\n}\n\nfunction isLinkView() {\n    return this.model.isLink();\n}\n\nconst connectionAttributesNS = {\n\n    'connection': {\n        qualify: isLinkView,\n        unset: 'd',\n        set: function({ stubs = 0 }) {\n            let d;\n            if (isFinite(stubs) && stubs !== 0) {\n                let offset;\n                if (stubs < 0) {\n                    offset = (this.getConnectionLength() + stubs) / 2;\n                } else {\n                    offset = stubs;\n                }\n                const path = this.getConnection();\n                const segmentSubdivisions = this.getConnectionSubdivisions();\n                const sourceParts = path.divideAtLength(offset, { segmentSubdivisions });\n                const targetParts = path.divideAtLength(-offset, { segmentSubdivisions });\n                if (sourceParts && targetParts) {\n                    d = `${sourceParts[0].serialize()} ${targetParts[1].serialize()}`;\n                }\n            }\n\n            return { d: d || this.getSerializedConnection() };\n        }\n    },\n\n    'at-connection-length-keep-gradient': {\n        qualify: isLinkView,\n        unset: 'transform',\n        set: atConnectionWrapper('getTangentAtLength', { rotate: true })\n    },\n\n    'at-connection-length-ignore-gradient': {\n        qualify: isLinkView,\n        unset: 'transform',\n        set: atConnectionWrapper('getTangentAtLength', { rotate: false })\n    },\n\n    'at-connection-ratio-keep-gradient': {\n        qualify: isLinkView,\n        unset: 'transform',\n        set: atConnectionWrapper('getTangentAtRatio', { rotate: true })\n    },\n\n    'at-connection-ratio-ignore-gradient': {\n        qualify: isLinkView,\n        unset: 'transform',\n        set: atConnectionWrapper('getTangentAtRatio', { rotate: false })\n    }\n\n};\n\nconnectionAttributesNS['at-connection-length'] = connectionAttributesNS['at-connection-length-keep-gradient'];\nconnectionAttributesNS['at-connection-ratio'] = connectionAttributesNS['at-connection-ratio-keep-gradient'];\n\nexport default connectionAttributesNS;\n","import { Path, Polyline } from '../../g/index.mjs';\nimport $ from '../../mvc/Dom/index.mjs';\nimport V from '../../V/index.mjs';\n\nfunction shapeWrapper(shapeConstructor, opt) {\n    var cacheName = 'joint-shape';\n    var resetOffset = opt && opt.resetOffset;\n    return function(value, refBBox, node) {\n        var cache = $.data.get(node, cacheName);\n        if (!cache || cache.value !== value) {\n            // only recalculate if value has changed\n            var cachedShape = shapeConstructor(value);\n            cache = {\n                value: value,\n                shape: cachedShape,\n                shapeBBox: cachedShape.bbox()\n            };\n            $.data.set(node, cacheName, cache);\n        }\n\n        var shape = cache.shape.clone();\n        var shapeBBox = cache.shapeBBox.clone();\n        var shapeOrigin = shapeBBox.origin();\n        var refOrigin = refBBox.origin();\n\n        shapeBBox.x = refOrigin.x;\n        shapeBBox.y = refOrigin.y;\n\n        var fitScale = refBBox.maxRectScaleToFit(shapeBBox, refOrigin);\n        // `maxRectScaleToFit` can give Infinity if width or height is 0\n        var sx = (shapeBBox.width === 0 || refBBox.width === 0) ? 1 : fitScale.sx;\n        var sy = (shapeBBox.height === 0 || refBBox.height === 0) ? 1 : fitScale.sy;\n\n        shape.scale(sx, sy, shapeOrigin);\n        if (resetOffset) {\n            shape.translate(-shapeOrigin.x, -shapeOrigin.y);\n        }\n\n        return shape;\n    };\n}\n\n// `d` attribute for SVGPaths\nfunction dWrapper(opt) {\n    function pathConstructor(value) {\n        return new Path(V.normalizePathData(value));\n    }\n\n    var shape = shapeWrapper(pathConstructor, opt);\n    return function(value, refBBox, node) {\n        var path = shape(value, refBBox, node);\n        return {\n            d: path.serialize()\n        };\n    };\n}\n\n// `points` attribute for SVGPolylines and SVGPolygons\nfunction pointsWrapper(opt) {\n    var shape = shapeWrapper(Polyline, opt);\n    return function(value, refBBox, node) {\n        var polyline = shape(value, refBBox, node);\n        return {\n            points: polyline.serialize()\n        };\n    };\n}\n\nconst shapeAttributesNS = {\n\n    'ref-d-reset-offset': {\n        unset: 'd',\n        set: dWrapper({ resetOffset: true })\n    },\n\n    'ref-d-keep-offset': {\n        unset: 'd',\n        set: dWrapper({ resetOffset: false })\n    },\n\n    'ref-points-reset-offset': {\n        unset: 'points',\n        set: pointsWrapper({ resetOffset: true })\n    },\n\n    'ref-points-keep-offset': {\n        unset: 'points',\n        set: pointsWrapper({ resetOffset: false })\n    },\n};\n\n// Aliases\nshapeAttributesNS['ref-d'] = shapeAttributesNS['ref-d-reset-offset'];\nshapeAttributesNS['ref-points'] = shapeAttributesNS['ref-points-reset-offset'];\n\nexport default shapeAttributesNS;\n","import { assign, isPlainObject } from '../../util/util.mjs';\n\nfunction contextMarker(context) {\n    var marker = {};\n    // Stroke\n    // The context 'fill' is disregarded here. The usual case is to use the marker with a connection\n    // (for which 'fill' attribute is set to 'none').\n    var stroke = context.stroke;\n    if (typeof stroke === 'string') {\n        marker['stroke'] = stroke;\n        marker['fill'] = stroke;\n    }\n    // Opacity\n    // Again the context 'fill-opacity' is ignored.\n    var strokeOpacity = context['stroke-opacity'];\n    if (strokeOpacity === undefined) strokeOpacity = context.opacity;\n    if (strokeOpacity !== undefined) {\n        marker['stroke-opacity'] = strokeOpacity;\n        marker['fill-opacity'] = strokeOpacity;\n    }\n    return marker;\n}\n\nfunction setPaintURL(def) {\n    const { paper } = this;\n    const url = (def.type === 'pattern')\n        ? paper.definePattern(def)\n        : paper.defineGradient(def);\n    return `url(#${url})`;\n}\n\nconst defsAttributesNS = {\n\n    'source-marker': {\n        qualify: isPlainObject,\n        unset: 'marker-start',\n        set: function(marker, refBBox, node, attrs) {\n            marker = assign(contextMarker(attrs), marker);\n            return { 'marker-start': 'url(#' + this.paper.defineMarker(marker) + ')' };\n        }\n    },\n\n    'target-marker': {\n        qualify: isPlainObject,\n        unset: 'marker-end',\n        set: function(marker, refBBox, node, attrs) {\n            marker = assign(contextMarker(attrs), { 'transform': 'rotate(180)' }, marker);\n            return { 'marker-end': 'url(#' + this.paper.defineMarker(marker) + ')' };\n        }\n    },\n\n    'vertex-marker': {\n        qualify: isPlainObject,\n        unset: 'marker-mid',\n        set: function(marker, refBBox, node, attrs) {\n            marker = assign(contextMarker(attrs), marker);\n            return { 'marker-mid': 'url(#' + this.paper.defineMarker(marker) + ')' };\n        }\n    },\n\n    'fill': {\n        qualify: isPlainObject,\n        set: setPaintURL\n    },\n\n    'stroke': {\n        qualify: isPlainObject,\n        set: setPaintURL\n    },\n\n    'filter': {\n        qualify: isPlainObject,\n        set: function(filter) {\n            return 'url(#' + this.paper.defineFilter(filter) + ')';\n        }\n    },\n};\n\nexport default defsAttributesNS;\n","\n// Offset attributes require the cell view to be rendered before they can be applied\n// (they must be appended to the DOM).\n\nimport { Point } from '../../g/index.mjs';\nimport { isPercentage } from '../../util/util.mjs';\n\nfunction offsetWrapper(axis, dimension, corner) {\n    return function(value, nodeBBox) {\n        var delta;\n        if (value === 'middle') {\n            delta = nodeBBox[dimension] / 2;\n        } else if (value === corner) {\n            delta = nodeBBox[dimension];\n        } else if (isFinite(value)) {\n            // TODO: or not to do a breaking change?\n            delta = (value > -1 && value < 1) ? (-nodeBBox[dimension] * value) : -value;\n        } else if (isPercentage(value)) {\n            delta = nodeBBox[dimension] * parseFloat(value) / 100;\n        } else {\n            delta = 0;\n        }\n\n        var point = new Point();\n        point[axis] = -(nodeBBox[axis] + delta);\n        return point;\n    };\n}\n\nconst offsetAttributesNS = {\n\n    // `x-alignment` when set to `middle` causes centering of the sub-element around its new x coordinate.\n    // `x-alignment` when set to `right` uses the x coordinate as referenced to the right of the bbox.\n    'x-alignment': {\n        offset: offsetWrapper('x', 'width', 'right')\n    },\n\n    // `y-alignment` when set to `middle` causes centering of the sub-element around its new y coordinate.\n    // `y-alignment` when set to `bottom` uses the y coordinate as referenced to the bottom of the bbox.\n    'y-alignment': {\n        offset: offsetWrapper('y', 'height', 'bottom')\n    },\n\n    'reset-offset': {\n        offset: function(val, nodeBBox) {\n            return (val)\n                ? { x: -nodeBBox.x, y: -nodeBBox.y }\n                : { x: 0, y: 0 };\n        }\n    },\n};\n\nexport default offsetAttributesNS;\n","import { assign, isPlainObject } from '../../util/util.mjs';\nimport $ from '../../mvc/Dom/index.mjs';\nimport V from '../../V/index.mjs';\n\nimport props from './props.mjs';\nimport legacyAttributesNS from './legacy.mjs';\nimport textAttributesNS from './text.mjs';\nimport connectionAttributesNS from './connection.mjs';\nimport shapeAttributesNS from './shape.mjs';\nimport defsAttributesNS from './defs.mjs';\nimport offsetAttributesNS from './offset.mjs';\n\nfunction setIfChangedWrapper(attribute) {\n    return function setIfChanged(value, _, node) {\n        const vel = V(node);\n        if (vel.attr(attribute) === value) return;\n        vel.attr(attribute, value);\n    };\n}\n\nconst attributesNS = {\n\n    'ref': {\n        // We do not set `ref` attribute directly on an element.\n        // The attribute itself does not qualify for relative positioning.\n    },\n\n    'href': {\n        set: setIfChangedWrapper('href')\n    },\n\n    'xlink:href': {\n        set: setIfChangedWrapper('xlink:href')\n    },\n\n    // `port` attribute contains the `id` of the port that the underlying magnet represents.\n    'port': {\n        set: function(port) {\n            return (port === null || port.id === undefined) ? port : port.id;\n        }\n    },\n\n    // `style` attribute is special in the sense that it sets the CSS style of the sub-element.\n    'style': {\n        qualify: isPlainObject,\n        set: function(styles, refBBox, node) {\n            $(node).css(styles);\n        }\n    },\n\n    'html': {\n        unset: function(node) {\n            $(node).empty();\n        },\n        set: function(html, refBBox, node) {\n            $(node).html(html + '');\n        }\n    },\n\n    // Properties setter (set various properties on the node)\n    props,\n};\n\nassign(attributesNS, legacyAttributesNS);\nassign(attributesNS, textAttributesNS);\nassign(attributesNS, connectionAttributesNS);\nassign(attributesNS, shapeAttributesNS);\nassign(attributesNS, defsAttributesNS);\nassign(attributesNS, offsetAttributesNS);\n\nexport const attributes = attributesNS;\n\n","import {\n    uniqueId,\n    union,\n    result,\n    merge,\n    forIn,\n    isObject,\n    isEqual,\n    isString,\n    cloneDeep,\n    omit,\n    uuid,\n    isEmpty,\n    assign,\n    uniq,\n    toArray,\n    setByPath,\n    unsetByPath,\n    getByPath,\n    timing,\n    interpolate,\n    nextFrame,\n    without,\n    cancelFrame,\n    defaultsDeep,\n    has,\n    sortBy,\n    defaults,\n    objectDifference\n} from '../util/util.mjs';\nimport { Model } from '../mvc/Model.mjs';\nimport { cloneCells } from '../util/cloneCells.mjs';\nimport { attributes } from './attributes/index.mjs';\nimport * as g from '../g/index.mjs';\n\n\n// Cell base model.\n// --------------------------\n\nconst attributesMerger = function(a, b) {\n    if (Array.isArray(a)) {\n        return b;\n    }\n};\n\nfunction removeEmptyAttributes(obj) {\n\n    // Remove toplevel empty attributes\n    for (const key in obj) {\n\n        const objValue = obj[key];\n        const isRealObject = isObject(objValue) && !Array.isArray(objValue);\n\n        if (!isRealObject) continue;\n\n        if (isEmpty(objValue)) {\n            delete obj[key];\n        }\n    }\n}\n\nexport const Cell = Model.extend({\n\n    // This is the same as mvc.Model with the only difference that is uses util.merge\n    // instead of just _.extend. The reason is that we want to mixin attributes set in upper classes.\n    constructor: function(attributes, options) {\n\n        var defaults;\n        var attrs = attributes || {};\n        if (typeof this.preinitialize === 'function') {\n            // Check to support an older version\n            this.preinitialize.apply(this, arguments);\n        }\n        this.cid = uniqueId('c');\n        this.attributes = {};\n        if (options && options.collection) this.collection = options.collection;\n        if (options && options.parse) attrs = this.parse(attrs, options) || {};\n        if ((defaults = result(this, 'defaults'))) {\n            //<custom code>\n            // Replaced the call to _.defaults with util.merge.\n            const customizer = (options && options.mergeArrays === true) ? false : attributesMerger;\n            attrs = merge({}, defaults, attrs, customizer);\n            //</custom code>\n        }\n        this.set(attrs, options);\n        this.changed = {};\n        this.initialize.apply(this, arguments);\n    },\n\n    translate: function(dx, dy, opt) {\n\n        throw new Error('Must define a translate() method.');\n    },\n\n    toJSON: function(opt) {\n\n        const { ignoreDefaults, ignoreEmptyAttributes = false } = opt || {};\n        const defaults = result(this.constructor.prototype, 'defaults');\n\n        if (ignoreDefaults === false) {\n            // Return all attributes without omitting the defaults\n            const finalAttributes = cloneDeep(this.attributes);\n\n            if (!ignoreEmptyAttributes) return finalAttributes;\n\n            removeEmptyAttributes(finalAttributes);\n\n            return finalAttributes;\n        }\n\n        let defaultAttributes = {};\n        let attributes = cloneDeep(this.attributes);\n\n        if (ignoreDefaults === true) {\n            // Compare all attributes with the defaults\n            defaultAttributes = defaults;\n        } else {\n            // Compare only the specified attributes with the defaults, use `attrs` as a default if not specified\n            const differentiateKeys = Array.isArray(ignoreDefaults) ? ignoreDefaults : ['attrs'];\n\n            differentiateKeys.forEach((key) => {\n                defaultAttributes[key] = defaults[key] || {};\n            });\n        }\n\n        // Omit `id` and `type` attribute from the defaults since it should be always present\n        const finalAttributes = objectDifference(attributes, omit(defaultAttributes, 'id', 'type'), { maxDepth: 4 });\n\n        if (ignoreEmptyAttributes) {\n            removeEmptyAttributes(finalAttributes);\n        }\n\n        return finalAttributes;\n    },\n\n    initialize: function(options) {\n\n        const idAttribute = this.getIdAttribute();\n        if (!options || options[idAttribute] === undefined) {\n            this.set(idAttribute, this.generateId(), { silent: true });\n        }\n\n        this._transitionIds = {};\n        this._scheduledTransitionIds = {};\n\n        // Collect ports defined in `attrs` and keep collecting whenever `attrs` object changes.\n        this.processPorts();\n        this.on('change:attrs', this.processPorts, this);\n    },\n\n    getIdAttribute: function() {\n        return this.idAttribute || 'id';\n    },\n\n    generateId: function() {\n        return uuid();\n    },\n\n    /**\n     * @deprecated\n     */\n    processPorts: function() {\n\n        // Whenever `attrs` changes, we extract ports from the `attrs` object and store it\n        // in a more accessible way. Also, if any port got removed and there were links that had `target`/`source`\n        // set to that port, we remove those links as well (to follow the same behaviour as\n        // with a removed element).\n\n        var previousPorts = this.ports;\n\n        // Collect ports from the `attrs` object.\n        var ports = {};\n        forIn(this.get('attrs'), function(attrs, selector) {\n\n            if (attrs && attrs.port) {\n\n                // `port` can either be directly an `id` or an object containing an `id` (and potentially other data).\n                if (attrs.port.id !== undefined) {\n                    ports[attrs.port.id] = attrs.port;\n                } else {\n                    ports[attrs.port] = { id: attrs.port };\n                }\n            }\n        });\n\n        // Collect ports that have been removed (compared to the previous ports) - if any.\n        // Use hash table for quick lookup.\n        var removedPorts = {};\n        forIn(previousPorts, function(port, id) {\n\n            if (!ports[id]) removedPorts[id] = true;\n        });\n\n        // Remove all the incoming/outgoing links that have source/target port set to any of the removed ports.\n        if (this.graph && !isEmpty(removedPorts)) {\n\n            var inboundLinks = this.graph.getConnectedLinks(this, { inbound: true });\n            inboundLinks.forEach(function(link) {\n\n                if (removedPorts[link.get('target').port]) link.remove();\n            });\n\n            var outboundLinks = this.graph.getConnectedLinks(this, { outbound: true });\n            outboundLinks.forEach(function(link) {\n\n                if (removedPorts[link.get('source').port]) link.remove();\n            });\n        }\n\n        // Update the `ports` object.\n        this.ports = ports;\n    },\n\n    remove: function(opt = {}) {\n\n        // Store the graph in a variable because `this.graph` won't be accessible\n        // after `this.trigger('remove', ...)` down below.\n        const { graph, collection } = this;\n        if (!graph) {\n            // The collection is a common mvc collection (not the graph collection).\n            if (collection) collection.remove(this, opt);\n            return this;\n        }\n\n        graph.startBatch('remove');\n\n        // First, unembed this cell from its parent cell if there is one.\n        const parentCell = this.getParentCell();\n        if (parentCell) {\n            parentCell.unembed(this, opt);\n        }\n\n        // Remove also all the cells, which were embedded into this cell\n        const embeddedCells = this.getEmbeddedCells();\n        for (let i = 0, n = embeddedCells.length; i < n; i++) {\n            const embed = embeddedCells[i];\n            if (embed) {\n                embed.remove(opt);\n            }\n        }\n\n        this.trigger('remove', this, graph.attributes.cells, opt);\n\n        graph.stopBatch('remove');\n\n        return this;\n    },\n\n    toFront: function(opt) {\n        var graph = this.graph;\n        if (graph) {\n            opt = defaults(opt || {}, { foregroundEmbeds: true });\n\n            let cells;\n            if (opt.deep) {\n                cells = this.getEmbeddedCells({ deep: true, breadthFirst: opt.breadthFirst !== false, sortSiblings: opt.foregroundEmbeds });\n                cells.unshift(this);\n            } else {\n                cells = [this];\n            }\n\n            const sortedCells = opt.foregroundEmbeds ? cells : sortBy(cells, cell => cell.z());\n\n            const maxZ = graph.maxZIndex();\n            let z = maxZ - cells.length + 1;\n\n            const collection = graph.get('cells');\n\n            let shouldUpdate = (collection.toArray().indexOf(sortedCells[0]) !== (collection.length - cells.length));\n            if (!shouldUpdate) {\n                shouldUpdate = sortedCells.some(function(cell, index) {\n                    return cell.z() !== z + index;\n                });\n            }\n\n            if (shouldUpdate) {\n                this.startBatch('to-front');\n\n                z = z + cells.length;\n\n                sortedCells.forEach(function(cell, index) {\n                    cell.set('z', z + index, opt);\n                });\n\n                this.stopBatch('to-front');\n            }\n        }\n\n        return this;\n    },\n\n    toBack: function(opt) {\n        var graph = this.graph;\n        if (graph) {\n            opt = defaults(opt || {}, { foregroundEmbeds: true });\n\n            let cells;\n            if (opt.deep) {\n                cells = this.getEmbeddedCells({ deep: true, breadthFirst: opt.breadthFirst !== false, sortSiblings: opt.foregroundEmbeds });\n                cells.unshift(this);\n            } else {\n                cells = [this];\n            }\n\n            const sortedCells = opt.foregroundEmbeds ? cells : sortBy(cells, cell => cell.z());\n\n            let z = graph.minZIndex();\n\n            var collection = graph.get('cells');\n\n            let shouldUpdate = (collection.toArray().indexOf(sortedCells[0]) !== 0);\n            if (!shouldUpdate) {\n                shouldUpdate = sortedCells.some(function(cell, index) {\n                    return cell.z() !== z + index;\n                });\n            }\n\n            if (shouldUpdate) {\n                this.startBatch('to-back');\n\n                z -= cells.length;\n\n                sortedCells.forEach(function(cell, index) {\n                    cell.set('z', z + index, opt);\n                });\n\n                this.stopBatch('to-back');\n            }\n        }\n\n        return this;\n    },\n\n    parent: function(parent, opt) {\n\n        // getter\n        if (parent === undefined) return this.get('parent');\n        // setter\n        return this.set('parent', parent, opt);\n    },\n\n    embed: function(cell, opt = {}) {\n        const cells = Array.isArray(cell) ? cell : [cell];\n        if (!this.canEmbed(cells)) {\n            throw new Error('Recursive embedding not allowed.');\n        }\n        if (opt.reparent) {\n            const parents = uniq(cells.map(c => c.getParentCell()));\n\n            // Unembed cells from their current parents.\n            parents.forEach((parent) => {\n                // Cell doesn't have to be embedded.\n                if (!parent) return;\n\n                // Pass all the `cells` since the `dia.Cell._unembedCells` method can handle cases\n                // where not all elements of `cells` are embedded in the same parent.\n                parent._unembedCells(cells, opt);\n            });\n\n        } else if (cells.some(c => c.isEmbedded() && this.id !== c.parent())) {\n            throw new Error('Embedding of already embedded cells is not allowed.');\n        }\n        this._embedCells(cells, opt);\n        return this;\n    },\n\n    unembed: function(cell, opt) {\n        const cells = Array.isArray(cell) ? cell : [cell];\n        this._unembedCells(cells, opt);\n        return this;\n    },\n\n    canEmbed: function(cell) {\n        const cells = Array.isArray(cell) ? cell : [cell];\n        return cells.every(c => this !== c && !this.isEmbeddedIn(c));\n    },\n\n    _embedCells: function(cells, opt) {\n        const batchName = 'embed';\n        this.startBatch(batchName);\n        const embeds = assign([], this.get('embeds'));\n        cells.forEach(cell => {\n            // We keep all element ids after link ids.\n            embeds[cell.isLink() ? 'unshift' : 'push'](cell.id);\n            cell.parent(this.id, opt);\n        });\n        this.set('embeds', uniq(embeds), opt);\n        this.stopBatch(batchName);\n    },\n\n    _unembedCells: function(cells, opt) {\n        const batchName = 'unembed';\n        this.startBatch(batchName);\n        cells.forEach(cell => cell.unset('parent', opt));\n        this.set('embeds', without(this.get('embeds'), ...cells.map(cell => cell.id)), opt);\n        this.stopBatch(batchName);\n    },\n\n    getParentCell: function() {\n\n        // unlike link.source/target, cell.parent stores id directly as a string\n        var parentId = this.parent();\n        var graph = this.graph;\n\n        return (parentId && graph && graph.getCell(parentId)) || null;\n    },\n\n    // Return an array of ancestor cells.\n    // The array is ordered from the parent of the cell\n    // to the most distant ancestor.\n    getAncestors: function() {\n\n        var ancestors = [];\n\n        if (!this.graph) {\n            return ancestors;\n        }\n\n        var parentCell = this.getParentCell();\n        while (parentCell) {\n            ancestors.push(parentCell);\n            parentCell = parentCell.getParentCell();\n        }\n\n        return ancestors;\n    },\n\n    getEmbeddedCells: function(opt) {\n\n        opt = opt || {};\n\n        // Cell models can only be retrieved when this element is part of a collection.\n        // There is no way this element knows about other cells otherwise.\n        // This also means that calling e.g. `translate()` on an element with embeds before\n        // adding it to a graph does not translate its embeds.\n        if (!this.graph) {\n            return [];\n        }\n\n        if (opt.deep) {\n            if (opt.breadthFirst) {\n                return this._getEmbeddedCellsBfs(opt.sortSiblings);\n            } else {\n                return this._getEmbeddedCellsDfs(opt.sortSiblings);\n            }\n        }\n\n        const embeddedIds = this.get('embeds');\n        if (isEmpty(embeddedIds)) {\n            return [];\n        }\n\n        let cells = embeddedIds.map(this.graph.getCell, this.graph);\n        if (opt.sortSiblings) {\n            cells = sortBy(cells, cell => cell.z());\n        }\n\n        return cells;\n    },\n\n    _getEmbeddedCellsBfs: function(sortSiblings) {\n        const cells = [];\n\n        const queue = [];\n        queue.push(this);\n\n        while (queue.length > 0) {\n            const current = queue.shift();\n            cells.push(current);\n\n            const embeddedCells = current.getEmbeddedCells({ sortSiblings: sortSiblings });\n\n            queue.push(...embeddedCells);\n        }\n        cells.shift();\n\n        return cells;\n    },\n\n    _getEmbeddedCellsDfs: function(sortSiblings) {\n        const cells = [];\n\n        const stack = [];\n        stack.push(this);\n\n        while (stack.length > 0) {\n            const current = stack.pop();\n            cells.push(current);\n\n            const embeddedCells = current.getEmbeddedCells({ sortSiblings: sortSiblings });\n\n            // When using the stack, cells that are embedded last are processed first.\n            // To maintain the original order, we need to push the cells in reverse order\n            for (let i = embeddedCells.length - 1; i >= 0; --i) {\n                stack.push(embeddedCells[i]);\n            }\n        }\n        cells.shift();\n\n        return cells;\n    },\n\n    isEmbeddedIn: function(cell, opt) {\n\n        var cellId = isString(cell) ? cell : cell.id;\n        var parentId = this.parent();\n\n        opt = assign({ deep: true }, opt);\n\n        // See getEmbeddedCells().\n        if (this.graph && opt.deep) {\n\n            while (parentId) {\n                if (parentId === cellId) {\n                    return true;\n                }\n                parentId = this.graph.getCell(parentId).parent();\n            }\n\n            return false;\n\n        } else {\n\n            // When this cell is not part of a collection check\n            // at least whether it's a direct child of given cell.\n            return parentId === cellId;\n        }\n    },\n\n    // Whether or not the cell is embedded in any other cell.\n    isEmbedded: function() {\n\n        return !!this.parent();\n    },\n\n    // Isolated cloning. Isolated cloning has two versions: shallow and deep (pass `{ deep: true }` in `opt`).\n    // Shallow cloning simply clones the cell and returns a new cell with different ID.\n    // Deep cloning clones the cell and all its embedded cells recursively.\n    clone: function(opt) {\n\n        opt = opt || {};\n\n        if (!opt.deep) {\n            // Shallow cloning.\n\n            var clone = Model.prototype.clone.apply(this, arguments);\n            // We don't want the clone to have the same ID as the original.\n            clone.set(this.getIdAttribute(), this.generateId());\n            // A shallow cloned element does not carry over the original embeds.\n            clone.unset('embeds');\n            // And can not be embedded in any cell\n            // as the clone is not part of the graph.\n            clone.unset('parent');\n\n            return clone;\n\n        } else {\n            // Deep cloning.\n\n            // For a deep clone, simply call `graph.cloneCells()` with the cell and all its embedded cells.\n            return toArray(cloneCells([this].concat(this.getEmbeddedCells({ deep: true }))));\n        }\n    },\n\n    // A convenient way to set nested properties.\n    // This method merges the properties you'd like to set with the ones\n    // stored in the cell and makes sure change events are properly triggered.\n    // You can either set a nested property with one object\n    // or use a property path.\n    // The most simple use case is:\n    // `cell.prop('name/first', 'John')` or\n    // `cell.prop({ name: { first: 'John' } })`.\n    // Nested arrays are supported too:\n    // `cell.prop('series/0/data/0/degree', 50)` or\n    // `cell.prop({ series: [ { data: [ { degree: 50 } ] } ] })`.\n    prop: function(props, value, opt) {\n\n        var delim = '/';\n        var _isString = isString(props);\n\n        if (_isString || Array.isArray(props)) {\n            // Get/set an attribute by a special path syntax that delimits\n            // nested objects by the colon character.\n\n            if (arguments.length > 1) {\n\n                var path;\n                var pathArray;\n\n                if (_isString) {\n                    path = props;\n                    pathArray = path.split('/');\n                } else {\n                    path = props.join(delim);\n                    pathArray = props.slice();\n                }\n\n                var property = pathArray[0];\n                var pathArrayLength = pathArray.length;\n\n                const options = opt || {};\n                options.propertyPath = path;\n                options.propertyValue = value;\n                options.propertyPathArray = pathArray;\n                if (!('rewrite' in options)) {\n                    options.rewrite = false;\n                }\n\n                var update = {};\n                // Initialize the nested object. Sub-objects are either arrays or objects.\n                // An empty array is created if the sub-key is an integer. Otherwise, an empty object is created.\n                // Note that this imposes a limitation on object keys one can use with Inspector.\n                // Pure integer keys will cause issues and are therefore not allowed.\n                var initializer = update;\n                var prevProperty = property;\n\n                for (var i = 1; i < pathArrayLength; i++) {\n                    var pathItem = pathArray[i];\n                    var isArrayIndex = Number.isFinite(_isString ? Number(pathItem) : pathItem);\n                    initializer = initializer[prevProperty] = isArrayIndex ? [] : {};\n                    prevProperty = pathItem;\n                }\n\n                // Fill update with the `value` on `path`.\n                update = setByPath(update, pathArray, value, '/');\n\n                var baseAttributes = merge({}, this.attributes);\n                // if rewrite mode enabled, we replace value referenced by path with\n                // the new one (we don't merge).\n                options.rewrite && unsetByPath(baseAttributes, path, '/');\n\n                // Merge update with the model attributes.\n                var attributes = merge(baseAttributes, update);\n                // Finally, set the property to the updated attributes.\n                return this.set(property, attributes[property], options);\n\n            } else {\n\n                return getByPath(this.attributes, props, delim);\n            }\n        }\n\n        const options = value || {};\n        // Note: '' is not the path to the root. It's a path with an empty string i.e. { '': {}}.\n        options.propertyPath = null;\n        options.propertyValue = props;\n        options.propertyPathArray = [];\n        if (!('rewrite' in options)) {\n            options.rewrite = false;\n        }\n\n        // Create a new object containing only the changed attributes.\n        const changedAttributes = {};\n        for (const key in props) {\n            // Merging the values of changed attributes with the current ones.\n            const { changedValue } = merge({}, { changedValue: this.attributes[key] }, { changedValue: props[key] });\n            changedAttributes[key] = changedValue;\n        }\n\n        return this.set(changedAttributes, options);\n    },\n\n    // A convenient way to unset nested properties\n    removeProp: function(path, opt) {\n\n        opt = opt || {};\n\n        var pathArray = Array.isArray(path) ? path : path.split('/');\n\n        // Once a property is removed from the `attrs` attribute\n        // the cellView will recognize a `dirty` flag and re-render itself\n        // in order to remove the attribute from SVG element.\n        var property = pathArray[0];\n        if (property === 'attrs') opt.dirty = true;\n\n        if (pathArray.length === 1) {\n            // A top level property\n            return this.unset(path, opt);\n        }\n\n        // A nested property\n        var nestedPath = pathArray.slice(1);\n        var propertyValue = this.get(property);\n        if (propertyValue === undefined || propertyValue === null) return this;\n        propertyValue = cloneDeep(propertyValue);\n\n        unsetByPath(propertyValue, nestedPath, '/');\n\n        return this.set(property, propertyValue, opt);\n    },\n\n    // A convenient way to set nested attributes.\n    attr: function(attrs, value, opt) {\n\n        var args = Array.from(arguments);\n        if (args.length === 0) {\n            return this.get('attrs');\n        }\n\n        if (Array.isArray(attrs)) {\n            args[0] = ['attrs'].concat(attrs);\n        } else if (isString(attrs)) {\n            // Get/set an attribute by a special path syntax that delimits\n            // nested objects by the colon character.\n            args[0] = 'attrs/' + attrs;\n\n        } else {\n\n            args[0] = { 'attrs' : attrs };\n        }\n\n        return this.prop.apply(this, args);\n    },\n\n    // A convenient way to unset nested attributes\n    removeAttr: function(path, opt) {\n\n        if (Array.isArray(path)) {\n\n            return this.removeProp(['attrs'].concat(path));\n        }\n\n        return this.removeProp('attrs/' + path, opt);\n    },\n\n    transition: function(path, value, opt, delim) {\n\n        delim = delim || '/';\n\n        var defaults = {\n            duration: 100,\n            delay: 10,\n            timingFunction: timing.linear,\n            valueFunction: interpolate.number\n        };\n\n        opt = assign(defaults, opt);\n\n        var firstFrameTime = 0;\n        var interpolatingFunction;\n\n        var setter = function(runtime) {\n\n            var id, progress, propertyValue;\n\n            firstFrameTime = firstFrameTime || runtime;\n            runtime -= firstFrameTime;\n            progress = runtime / opt.duration;\n\n            if (progress < 1) {\n                this._transitionIds[path] = id = nextFrame(setter);\n            } else {\n                progress = 1;\n                delete this._transitionIds[path];\n            }\n\n            propertyValue = interpolatingFunction(opt.timingFunction(progress));\n\n            opt.transitionId = id;\n\n            this.prop(path, propertyValue, opt);\n\n            if (!id) this.trigger('transition:end', this, path);\n\n        }.bind(this);\n\n        const { _scheduledTransitionIds } = this;\n        let initialId;\n\n        var initiator = (callback) => {\n\n            if (_scheduledTransitionIds[path]) {\n                _scheduledTransitionIds[path] = without(_scheduledTransitionIds[path], initialId);\n                if (_scheduledTransitionIds[path].length === 0) {\n                    delete _scheduledTransitionIds[path];\n                }\n            }\n\n            this.stopPendingTransitions(path, delim);\n\n            interpolatingFunction = opt.valueFunction(getByPath(this.attributes, path, delim), value);\n\n            this._transitionIds[path] = nextFrame(callback);\n\n            this.trigger('transition:start', this, path);\n\n        };\n\n        initialId = setTimeout(initiator, opt.delay, setter);\n\n        _scheduledTransitionIds[path] || (_scheduledTransitionIds[path] = []);\n        _scheduledTransitionIds[path].push(initialId);\n\n        return initialId;\n    },\n\n    getTransitions: function() {\n        return union(\n            Object.keys(this._transitionIds),\n            Object.keys(this._scheduledTransitionIds)\n        );\n    },\n\n    stopScheduledTransitions: function(path, delim = '/') {\n        const { _scheduledTransitionIds = {}} = this;\n        let transitions = Object.keys(_scheduledTransitionIds);\n        if (path) {\n            const pathArray = path.split(delim);\n            transitions = transitions.filter((key) => {\n                return isEqual(pathArray, key.split(delim).slice(0, pathArray.length));\n            });\n        }\n        transitions.forEach((key) => {\n            const transitionIds = _scheduledTransitionIds[key];\n            // stop the initiator\n            transitionIds.forEach(transitionId => clearTimeout(transitionId));\n            delete _scheduledTransitionIds[key];\n            // Note: we could trigger transition:cancel` event here\n        });\n        return this;\n    },\n\n    stopPendingTransitions(path, delim = '/') {\n        const { _transitionIds = {}} = this;\n        let transitions = Object.keys(_transitionIds);\n        if (path) {\n            const pathArray = path.split(delim);\n            transitions = transitions.filter((key) => {\n                return isEqual(pathArray, key.split(delim).slice(0, pathArray.length));\n            });\n        }\n        transitions.forEach((key) => {\n            const transitionId = _transitionIds[key];\n            // stop the setter\n            cancelFrame(transitionId);\n            delete _transitionIds[key];\n            this.trigger('transition:end', this, key);\n        });\n    },\n\n    stopTransitions: function(path, delim = '/') {\n        this.stopScheduledTransitions(path, delim);\n        this.stopPendingTransitions(path, delim);\n        return this;\n    },\n\n    // A shorcut making it easy to create constructs like the following:\n    // `var el = (new joint.shapes.standard.Rectangle()).addTo(graph)`.\n    addTo: function(graph, opt) {\n\n        graph.addCell(this, opt);\n        return this;\n    },\n\n    // A shortcut for an equivalent call: `paper.findViewByModel(cell)`\n    // making it easy to create constructs like the following:\n    // `cell.findView(paper).highlight()`\n    findView: function(paper) {\n\n        return paper.findViewByModel(this);\n    },\n\n    isElement: function() {\n\n        return false;\n    },\n\n    isLink: function() {\n\n        return false;\n    },\n\n    startBatch: function(name, opt) {\n\n        if (this.graph) { this.graph.startBatch(name, assign({}, opt, { cell: this })); }\n        return this;\n    },\n\n    stopBatch: function(name, opt) {\n\n        if (this.graph) { this.graph.stopBatch(name, assign({}, opt, { cell: this })); }\n        return this;\n    },\n\n    getChangeFlag: function(attributes) {\n\n        var flag = 0;\n        if (!attributes) return flag;\n        for (var key in attributes) {\n            if (!attributes.hasOwnProperty(key) || !this.hasChanged(key)) continue;\n            flag |= attributes[key];\n        }\n        return flag;\n    },\n\n    angle: function() {\n\n        // To be overridden.\n        return 0;\n    },\n\n    position: function() {\n\n        // To be overridden.\n        return new g.Point(0, 0);\n    },\n\n    z: function() {\n        return this.get('z') || 0;\n    },\n\n    getPointFromConnectedLink: function() {\n\n        // To be overridden\n        return new g.Point();\n    },\n\n    getBBox: function() {\n\n        // To be overridden\n        return new g.Rect(0, 0, 0, 0);\n    },\n\n    getPointRotatedAroundCenter(angle, x, y) {\n        const point = new g.Point(x, y);\n        if (angle) point.rotate(this.getBBox().center(), angle);\n        return point;\n    },\n\n    getAbsolutePointFromRelative(x, y) {\n        // Rotate the position to take the model angle into account\n        return this.getPointRotatedAroundCenter(\n            -this.angle(),\n            // Transform the relative position to absolute\n            this.position().offset(x, y)\n        );\n    },\n\n    getRelativePointFromAbsolute(x, y) {\n        return this\n            // Rotate the coordinates to mitigate the element's rotation.\n            .getPointRotatedAroundCenter(this.angle(), x, y)\n            // Transform the absolute position into relative\n            .difference(this.position());\n    }\n\n}, {\n\n    getAttributeDefinition: function(attrName) {\n\n        var defNS = this.attributes;\n        var globalDefNS = attributes;\n        return (defNS && defNS[attrName]) || globalDefNS[attrName];\n    },\n\n    define: function(type, defaults, protoProps, staticProps) {\n\n        protoProps = assign({\n            defaults: defaultsDeep({ type: type }, defaults, this.prototype.defaults)\n        }, protoProps);\n\n        var Cell = this.extend(protoProps, staticProps);\n        // es5 backward compatibility\n        /* eslint-disable no-undef */\n        if (typeof joint !== 'undefined' && has(joint, 'shapes')) {\n            setByPath(joint.shapes, type, Cell, '.');\n        }\n        /* eslint-enable no-undef */\n        return Cell;\n    }\n});\n\n","import * as g from '../../g/index.mjs';\nimport * as util from '../../util/index.mjs';\n\nfunction portTransformAttrs(point, angle, opt) {\n\n    var trans = point.toJSON();\n\n    trans.angle = angle || 0;\n\n    return util.defaults({}, opt, trans);\n}\n\nfunction lineLayout(ports, p1, p2, elBBox) {\n    return ports.map(function(port, index, ports) {\n        var p = this.pointAt(((index + 0.5) / ports.length));\n        // `dx`,`dy` per port offset option\n        if (port.dx || port.dy) {\n            p.offset(port.dx || 0, port.dy || 0);\n        }\n        return portTransformAttrs(p.round(), 0, argTransform(elBBox, port));\n    }, g.line(p1, p2));\n}\n\nfunction ellipseLayout(ports, elBBox, startAngle, stepFn) {\n\n    var center = elBBox.center();\n    var ratio = elBBox.width / elBBox.height;\n    var p1 = elBBox.topMiddle();\n\n    var ellipse = g.Ellipse.fromRect(elBBox);\n\n    return ports.map(function(port, index, ports) {\n\n        var angle = startAngle + stepFn(index, ports.length);\n        var p2 = p1.clone()\n            .rotate(center, -angle)\n            .scale(ratio, 1, center);\n\n        var theta = port.compensateRotation ? -ellipse.tangentTheta(p2) : 0;\n\n        // `dx`,`dy` per port offset option\n        if (port.dx || port.dy) {\n            p2.offset(port.dx || 0, port.dy || 0);\n        }\n\n        // `dr` delta radius option\n        if (port.dr) {\n            p2.move(center, port.dr);\n        }\n\n        return portTransformAttrs(p2.round(), theta, argTransform(elBBox, port));\n    });\n}\n\n\nfunction argTransform(bbox, args) {\n    let { x, y, angle } = args;\n    if (util.isPercentage(x)) {\n        x = parseFloat(x) / 100 * bbox.width;\n    } else if (util.isCalcExpression(x)) {\n        x = Number(util.evalCalcExpression(x, bbox));\n    }\n    if (util.isPercentage(y)) {\n        y = parseFloat(y) / 100 * bbox.height;\n    } else if (util.isCalcExpression(y)) {\n        y = Number(util.evalCalcExpression(y, bbox));\n    }\n    return { x, y, angle };\n}\n\n// Creates a point stored in arguments\nfunction argPoint(bbox, args) {\n    const { x, y } = argTransform(bbox, args);\n    return new g.Point(x || 0, y || 0);\n}\n\n\n/**\n * @param {Array<Object>} ports\n * @param {g.Rect} elBBox\n * @param {Object=} opt opt Group options\n * @returns {Array<g.Point>}\n */\nexport const absolute = function(ports, elBBox) {\n    return ports.map(port => {\n        const transformation = argPoint(elBBox, port).round().toJSON();\n        transformation.angle = port.angle || 0;\n        return transformation;\n    });\n};\n\n/**\n * @param {Array<Object>} ports\n * @param {g.Rect} elBBox\n * @param {Object=} opt opt Group options\n * @returns {Array<g.Point>}\n */\nexport const fn = function(ports, elBBox, opt) {\n    return opt.fn(ports, elBBox, opt);\n};\n\n/**\n * @param {Array<Object>} ports\n * @param {g.Rect} elBBox\n * @param {Object=} opt opt Group options\n * @returns {Array<g.Point>}\n */\nexport const line = function(ports, elBBox, opt) {\n\n    var start = argPoint(elBBox, opt.start || elBBox.origin());\n    var end = argPoint(elBBox, opt.end || elBBox.corner());\n\n    return lineLayout(ports, start, end, elBBox);\n};\n\n/**\n * @param {Array<Object>} ports\n * @param {g.Rect} elBBox\n * @param {Object=} opt opt Group options\n * @returns {Array<g.Point>}\n */\nexport const left = function(ports, elBBox, opt) {\n    return lineLayout(ports, elBBox.origin(), elBBox.bottomLeft(), elBBox);\n};\n\n/**\n * @param {Array<Object>} ports\n * @param {g.Rect} elBBox\n * @param {Object=} opt opt Group options\n * @returns {Array<g.Point>}\n */\nexport const right = function(ports, elBBox, opt) {\n    return lineLayout(ports, elBBox.topRight(), elBBox.corner(), elBBox);\n};\n\n/**\n * @param {Array<Object>} ports\n * @param {g.Rect} elBBox\n * @param {Object=} opt opt Group options\n * @returns {Array<g.Point>}\n */\nexport const top = function(ports, elBBox, opt) {\n    return lineLayout(ports, elBBox.origin(), elBBox.topRight(), elBBox);\n};\n\n/**\n * @param {Array<Object>} ports\n * @param {g.Rect} elBBox\n * @param {Object=} opt opt Group options\n * @returns {Array<g.Point>}\n */\nexport const bottom = function(ports, elBBox, opt) {\n    return lineLayout(ports, elBBox.bottomLeft(), elBBox.corner(), elBBox);\n};\n\n/**\n * @param {Array<Object>} ports\n * @param {g.Rect} elBBox\n * @param {Object=} opt Group options\n * @returns {Array<g.Point>}\n */\nexport const ellipseSpread = function(ports, elBBox, opt) {\n\n    var startAngle = opt.startAngle || 0;\n    var stepAngle = opt.step || 360 / ports.length;\n\n    return ellipseLayout(ports, elBBox, startAngle, function(index) {\n        return index * stepAngle;\n    });\n};\n\n/**\n * @param {Array<Object>} ports\n * @param {g.Rect} elBBox\n * @param {Object=} opt Group options\n * @returns {Array<g.Point>}\n */\nexport const ellipse = function(ports, elBBox, opt) {\n\n    var startAngle = opt.startAngle || 0;\n    var stepAngle = opt.step || 20;\n\n    return ellipseLayout(ports, elBBox, startAngle, function(index, count) {\n        return (index + 0.5 - count / 2) * stepAngle;\n    });\n};\n\n","import * as g from '../../g/index.mjs';\nimport * as util from '../../util/index.mjs';\n\nfunction labelAttributes(opt1, opt2) {\n\n    // use value from `opt2` if it is missing in `opt1`\n    // use value from this object if it is missing in `opt2` as well\n    return util.defaultsDeep({}, opt1, opt2, {\n        x: 0,\n        y: 0,\n        angle: 0,\n        attrs: {}\n    });\n}\n\nfunction getBBoxAngles(elBBox) {\n\n    var center = elBBox.center();\n\n    var tl = center.theta(elBBox.origin());\n    var bl = center.theta(elBBox.bottomLeft());\n    var br = center.theta(elBBox.corner());\n    var tr = center.theta(elBBox.topRight());\n\n    return [tl, tr, br, bl];\n}\n\nfunction outsideLayout(portPosition, elBBox, autoOrient, opt) {\n\n    opt = util.defaults({}, opt, { offset: 15 });\n    var angle = elBBox.center().theta(portPosition);\n\n    var tx, ty, y, textAnchor;\n    var offset = opt.offset;\n    var orientAngle = 0;\n\n    const [topLeftAngle, bottomLeftAngle, bottomRightAngle, topRightAngle] = getBBoxAngles(elBBox);\n    if ((angle < bottomLeftAngle) || (angle > bottomRightAngle)) {\n        y = '.3em';\n        tx = offset;\n        ty = 0;\n        textAnchor = 'start';\n    } else if (angle < topLeftAngle) {\n        tx = 0;\n        ty = -offset;\n        if (autoOrient) {\n            orientAngle = -90;\n            textAnchor = 'start';\n            y = '.3em';\n        } else {\n            textAnchor = 'middle';\n            y = '0';\n        }\n    } else if (angle < topRightAngle) {\n        y = '.3em';\n        tx = -offset;\n        ty = 0;\n        textAnchor = 'end';\n    } else {\n        tx = 0;\n        ty = offset;\n        if (autoOrient) {\n            orientAngle = 90;\n            textAnchor = 'start';\n            y = '.3em';\n        } else {\n            textAnchor = 'middle';\n            y = '.6em';\n        }\n    }\n\n    var round = Math.round;\n    return labelAttributes(opt, {\n        x: round(tx),\n        y: round(ty),\n        angle: orientAngle,\n        attrs: { labelText: { y, textAnchor }}\n    });\n}\n\nfunction insideLayout(portPosition, elBBox, autoOrient, opt) {\n\n    opt = util.defaults({}, opt, { offset: 15 });\n    var angle = elBBox.center().theta(portPosition);\n\n    var tx, ty, y, textAnchor;\n    var offset = opt.offset;\n    var orientAngle = 0;\n\n    const [topLeftAngle, bottomLeftAngle, bottomRightAngle, topRightAngle] = getBBoxAngles(elBBox);\n    if ((angle < bottomLeftAngle) || (angle > bottomRightAngle)) {\n        y = '.3em';\n        tx = -offset;\n        ty = 0;\n        textAnchor = 'end';\n    } else if (angle < topLeftAngle) {\n        tx = 0;\n        ty = offset;\n        if (autoOrient) {\n            orientAngle = 90;\n            textAnchor = 'start';\n            y = '.3em';\n        } else {\n            textAnchor = 'middle';\n            y = '.6em';\n        }\n    } else if (angle < topRightAngle) {\n        y = '.3em';\n        tx = offset;\n        ty = 0;\n        textAnchor = 'start';\n    } else {\n        tx = 0;\n        ty = -offset;\n        if (autoOrient) {\n            orientAngle = -90;\n            textAnchor = 'start';\n            y = '.3em';\n        } else {\n            textAnchor = 'middle';\n            y = '0';\n        }\n    }\n\n    var round = Math.round;\n    return labelAttributes(opt, {\n        x: round(tx),\n        y: round(ty),\n        angle: orientAngle,\n        attrs: { labelText: { y, textAnchor }}\n    });\n}\n\nfunction radialLayout(portCenterOffset, autoOrient, opt) {\n\n    opt = util.defaults({}, opt, { offset: 20 });\n\n    var origin = g.point(0, 0);\n    var angle = -portCenterOffset.theta(origin);\n    var orientAngle = angle;\n    var offset = portCenterOffset.clone()\n        .move(origin, opt.offset)\n        .difference(portCenterOffset)\n        .round();\n\n    var y = '.3em';\n    var textAnchor;\n\n    if ((angle + 90) % 180 === 0) {\n        textAnchor = autoOrient ? 'end' : 'middle';\n        if (!autoOrient && angle === -270) {\n            y = '0em';\n        }\n    } else if (angle > -270 && angle < -90) {\n        textAnchor = 'start';\n        orientAngle = angle - 180;\n    } else {\n        textAnchor = 'end';\n    }\n\n    var round = Math.round;\n    return labelAttributes(opt, {\n        x: round(offset.x),\n        y: round(offset.y),\n        angle: ((autoOrient) ? orientAngle : 0),\n        attrs: { labelText: { y, textAnchor }}\n    });\n}\n\nexport const manual = function(_portPosition, _elBBox, opt) {\n    return labelAttributes(opt);\n};\n\nexport const left = function(portPosition, elBBox, opt) {\n    return labelAttributes(opt, {\n        x: -15,\n        attrs: { labelText: { y: '.3em', textAnchor: 'end' }},\n    });\n};\n\nexport const right = function(portPosition, elBBox, opt) {\n    return labelAttributes(opt, {\n        x: 15,\n        attrs: { labelText: { y: '.3em', textAnchor: 'start' }},\n    });\n};\n\nexport const top = function(portPosition, elBBox, opt) {\n    return labelAttributes(opt, {\n        y: -15,\n        attrs: { labelText: { y: '0', textAnchor: 'middle' }},\n    });\n};\n\nexport const bottom = function(portPosition, elBBox, opt) {\n    return labelAttributes(opt, {\n        y: 15,\n        attrs: { labelText: { y: '.6em', textAnchor: 'middle' }},\n    });\n};\n\nexport const outsideOriented = function(portPosition, elBBox, opt) {\n    return outsideLayout(portPosition, elBBox, true, opt);\n};\n\nexport const outside = function(portPosition, elBBox, opt) {\n    return outsideLayout(portPosition, elBBox, false, opt);\n};\n\nexport const insideOriented = function(portPosition, elBBox, opt) {\n    return insideLayout(portPosition, elBBox, true, opt);\n};\n\nexport const inside = function(portPosition, elBBox, opt) {\n    return insideLayout(portPosition, elBBox, false, opt);\n};\n\nexport const radial = function(portPosition, elBBox, opt) {\n    return radialLayout(portPosition.difference(elBBox.center()), false, opt);\n};\n\nexport const radialOriented = function(portPosition, elBBox, opt) {\n    return radialLayout(portPosition.difference(elBBox.center()), true, opt);\n};\n","import * as util from '../util/index.mjs';\nimport V from '../V/index.mjs';\nimport { Rect, Point } from '../g/index.mjs';\nimport * as Port from '../layout/ports/port.mjs';\nimport * as PortLabel from '../layout/ports/portLabel.mjs';\n\nvar PortData = function(data) {\n\n    var clonedData = util.cloneDeep(data) || {};\n    this.ports = [];\n    this.groups = {};\n    this.portLayoutNamespace = Port;\n    this.portLabelLayoutNamespace = PortLabel;\n\n    this._init(clonedData);\n};\n\nPortData.prototype = {\n\n    getPorts: function() {\n        return this.ports;\n    },\n\n    getGroup: function(name) {\n        return this.groups[name] || {};\n    },\n\n    getPortsByGroup: function(groupName) {\n\n        return this.ports.filter(function(port) {\n            return port.group === groupName;\n        });\n    },\n\n    getGroupPortsMetrics: function(groupName, elBBox) {\n\n        var group = this.getGroup(groupName);\n        var ports = this.getPortsByGroup(groupName);\n\n        var groupPosition = group.position || {};\n        var groupPositionName = groupPosition.name;\n        var namespace = this.portLayoutNamespace;\n        if (!namespace[groupPositionName]) {\n            groupPositionName = 'left';\n        }\n\n        var groupArgs = groupPosition.args || {};\n        var portsArgs = ports.map(function(port) {\n            return port && port.position && port.position.args;\n        });\n        var groupPortTransformations = namespace[groupPositionName](portsArgs, elBBox, groupArgs);\n\n        var accumulator = {\n            ports: ports,\n            result: []\n        };\n\n        util.toArray(groupPortTransformations).reduce(function(res, portTransformation, index) {\n            var port = res.ports[index];\n            res.result.push({\n                portId: port.id,\n                portTransformation: portTransformation,\n                labelTransformation: this._getPortLabelLayout(port, Point(portTransformation), elBBox),\n                portAttrs: port.attrs,\n                portSize: port.size,\n                labelSize: port.label.size\n            });\n            return res;\n        }.bind(this), accumulator);\n\n        return accumulator.result;\n    },\n\n    _getPortLabelLayout: function(port, portPosition, elBBox) {\n\n        var namespace = this.portLabelLayoutNamespace;\n        var labelPosition = port.label.position.name || 'left';\n\n        if (namespace[labelPosition]) {\n            return namespace[labelPosition](portPosition, elBBox, port.label.position.args);\n        }\n\n        return null;\n    },\n\n    _init: function(data) {\n\n        // prepare groups\n        if (util.isObject(data.groups)) {\n            var groups = Object.keys(data.groups);\n            for (var i = 0, n = groups.length; i < n; i++) {\n                var key = groups[i];\n                this.groups[key] = this._evaluateGroup(data.groups[key]);\n            }\n        }\n\n        // prepare ports\n        var ports = util.toArray(data.items);\n        for (var j = 0, m = ports.length; j < m; j++) {\n            this.ports.push(this._evaluatePort(ports[j]));\n        }\n    },\n\n    _evaluateGroup: function(group) {\n\n        return util.merge(group, {\n            position: this._getPosition(group.position, true),\n            label: this._getLabel(group, true)\n        });\n    },\n\n    _evaluatePort: function(port) {\n\n        var evaluated = util.assign({}, port);\n\n        var group = this.getGroup(port.group);\n\n        evaluated.markup = evaluated.markup || group.markup;\n        evaluated.attrs = util.merge({}, group.attrs, evaluated.attrs);\n        evaluated.position = this._createPositionNode(group, evaluated);\n        evaluated.label = util.merge({}, group.label, this._getLabel(evaluated));\n        evaluated.z = this._getZIndex(group, evaluated);\n        evaluated.size = util.assign({}, group.size, evaluated.size);\n\n        return evaluated;\n    },\n\n    _getZIndex: function(group, port) {\n\n        if (util.isNumber(port.z)) {\n            return port.z;\n        }\n        if (util.isNumber(group.z) || group.z === 'auto') {\n            return group.z;\n        }\n        return 'auto';\n    },\n\n    _createPositionNode: function(group, port) {\n\n        return util.merge({\n            name: 'left',\n            args: {}\n        }, group.position, { args: port.args });\n    },\n\n    _getPosition: function(position, setDefault) {\n\n        var args = {};\n        var positionName;\n\n        if (util.isFunction(position)) {\n            positionName = 'fn';\n            args.fn = position;\n        } else if (util.isString(position)) {\n            positionName = position;\n        } else if (position === undefined) {\n            positionName = setDefault ? 'left' : null;\n        } else if (Array.isArray(position)) {\n            positionName = 'absolute';\n            args.x = position[0];\n            args.y = position[1];\n        } else if (util.isObject(position)) {\n            positionName = position.name;\n            util.assign(args, position.args);\n        }\n\n        var result = { args: args };\n\n        if (positionName) {\n            result.name = positionName;\n        }\n        return result;\n    },\n\n    _getLabel: function(item, setDefaults) {\n\n        var label = item.label || {};\n\n        var ret = label;\n        ret.position = this._getPosition(label.position, setDefaults);\n\n        return ret;\n    }\n};\n\nexport const elementPortPrototype = {\n\n    _initializePorts: function() {\n\n        this._createPortData();\n        this.on('change:ports', function() {\n\n            this._processRemovedPort();\n            this._createPortData();\n        }, this);\n    },\n\n    /**\n     * remove links tied wiht just removed element\n     * @private\n     */\n    _processRemovedPort: function() {\n\n        var current = this.get('ports') || {};\n        var currentItemsMap = {};\n\n        util.toArray(current.items).forEach(function(item) {\n            currentItemsMap[item.id] = true;\n        });\n\n        var previous = this.previous('ports') || {};\n        var removed = {};\n\n        util.toArray(previous.items).forEach(function(item) {\n            if (!currentItemsMap[item.id]) {\n                removed[item.id] = true;\n            }\n        });\n\n        var graph = this.graph;\n        if (graph && !util.isEmpty(removed)) {\n\n            var inboundLinks = graph.getConnectedLinks(this, { inbound: true });\n            inboundLinks.forEach(function(link) {\n\n                if (removed[link.get('target').port]) link.remove();\n            });\n\n            var outboundLinks = graph.getConnectedLinks(this, { outbound: true });\n            outboundLinks.forEach(function(link) {\n\n                if (removed[link.get('source').port]) link.remove();\n            });\n        }\n    },\n\n    /**\n     * @returns {boolean}\n     */\n    hasPorts: function() {\n\n        var ports = this.prop('ports/items');\n        return Array.isArray(ports) && ports.length > 0;\n    },\n\n    /**\n     * @param {string} id\n     * @returns {boolean}\n     */\n    hasPort: function(id) {\n\n        return this.getPortIndex(id) !== -1;\n    },\n\n    /**\n     * @returns {Array<object>}\n     */\n    getPorts: function() {\n\n        return util.cloneDeep(this.prop('ports/items')) || [];\n    },\n\n    /**\n     * @returns {Array<object>}\n     */\n    getGroupPorts: function(groupName) {\n        const groupPorts = util.toArray(this.prop(['ports','items'])).filter(port => port.group === groupName);\n        return util.cloneDeep(groupPorts);\n    },\n\n    /**\n     * @param {string} id\n     * @returns {object}\n     */\n    getPort: function(id) {\n\n        return util.cloneDeep(util.toArray(this.prop('ports/items')).find(function(port) {\n            return port.id && port.id === id;\n        }));\n    },\n\n    getPortGroupNames: function() {\n        return Object.keys(this._portSettingsData.groups);\n    },\n\n    /**\n     * @param {string} groupName\n     * @returns {Object<portId, {x: number, y: number, angle: number}>}\n     */\n    getPortsPositions: function(groupName) {\n\n        var portsMetrics = this._portSettingsData.getGroupPortsMetrics(groupName, Rect(this.size()));\n\n        return portsMetrics.reduce(function(positions, metrics) {\n            var transformation = metrics.portTransformation;\n            positions[metrics.portId] = {\n                x: transformation.x,\n                y: transformation.y,\n                angle: transformation.angle\n            };\n            return positions;\n        }, {});\n    },\n\n    /**\n     * @param {string|Port} port port id or port\n     * @returns {number} port index\n     */\n    getPortIndex: function(port) {\n\n        var id = util.isObject(port) ? port.id : port;\n\n        if (!this._isValidPortId(id)) {\n            return -1;\n        }\n\n        return util.toArray(this.prop('ports/items')).findIndex(function(item) {\n            return item.id === id;\n        });\n    },\n\n    /**\n     * @param {object} port\n     * @param {object} [opt]\n     * @returns {joint.dia.Element}\n     */\n    addPort: function(port, opt) {\n\n        if (!util.isObject(port) || Array.isArray(port)) {\n            throw new Error('Element: addPort requires an object.');\n        }\n\n        var ports = util.assign([], this.prop('ports/items'));\n        ports.push(port);\n        this.prop('ports/items', ports, opt);\n\n        return this;\n    },\n\n    /**\n     * @param {string|Port|number} before\n     * @param {object} port\n     * @param {object} [opt]\n     * @returns {joint.dia.Element}\n     */\n    insertPort: function(before, port, opt) {\n        const index = (typeof before === 'number') ? before : this.getPortIndex(before);\n\n        if (!util.isObject(port) || Array.isArray(port)) {\n            throw new Error('dia.Element: insertPort requires an object.');\n        }\n\n        const ports = util.assign([], this.prop('ports/items'));\n        ports.splice(index, 0, port);\n        this.prop('ports/items', ports, opt);\n\n        return this;\n    },\n\n    /**\n     * @param {string} portId\n     * @param {string|object=} path\n     * @param {*=} value\n     * @param {object=} opt\n     * @returns {joint.dia.Element}\n     */\n    portProp: function(portId, path, value, opt) {\n\n        var index = this.getPortIndex(portId);\n\n        if (index === -1) {\n            throw new Error('Element: unable to find port with id ' + portId);\n        }\n\n        var args = Array.prototype.slice.call(arguments, 1);\n        if (Array.isArray(path)) {\n            args[0] = ['ports', 'items', index].concat(path);\n        } else if (util.isString(path)) {\n\n            // Get/set an attribute by a special path syntax that delimits\n            // nested objects by the colon character.\n            args[0] = ['ports/items/', index, '/', path].join('');\n\n        } else {\n\n            args = ['ports/items/' + index];\n            if (util.isPlainObject(path)) {\n                args.push(path);\n                args.push(value);\n            }\n        }\n\n        return this.prop.apply(this, args);\n    },\n\n    _validatePorts: function() {\n\n        var portsAttr = this.get('ports') || {};\n\n        var errorMessages = [];\n        portsAttr = portsAttr || {};\n        var ports = util.toArray(portsAttr.items);\n\n        ports.forEach(function(p) {\n\n            if (typeof p !== 'object') {\n                errorMessages.push('Element: invalid port ', p);\n            }\n\n            if (!this._isValidPortId(p.id)) {\n                p.id = this.generatePortId();\n            }\n        }, this);\n\n        if (util.uniq(ports, 'id').length !== ports.length) {\n            errorMessages.push('Element: found id duplicities in ports.');\n        }\n\n        return errorMessages;\n    },\n\n    generatePortId: function() {\n        return this.generateId();\n    },\n\n    /**\n     * @param {string} id port id\n     * @returns {boolean}\n     * @private\n     */\n    _isValidPortId: function(id) {\n\n        return id !== null && id !== undefined && !util.isObject(id);\n    },\n\n    addPorts: function(ports, opt) {\n\n        if (ports.length) {\n            this.prop('ports/items', util.assign([], this.prop('ports/items')).concat(ports), opt);\n        }\n\n        return this;\n    },\n\n    removePort: function(port, opt) {\n        const options = opt || {};\n        const index = this.getPortIndex(port);\n        if (index !== -1) {\n            const ports = util.assign([], this.prop(['ports', 'items']));\n            ports.splice(index, 1);\n            options.rewrite = true;\n            this.startBatch('port-remove');\n            this.prop(['ports', 'items'], ports, options);\n            this.stopBatch('port-remove');\n        }\n        return this;\n    },\n\n    removePorts: function(portsForRemoval, opt) {\n        let options, newPorts;\n        if (Array.isArray(portsForRemoval)) {\n            options = opt || {};\n            if (portsForRemoval.length === 0) return this.this;\n            const currentPorts = util.assign([], this.prop(['ports', 'items']));\n            newPorts = currentPorts.filter(function(cp) {\n                return !portsForRemoval.some(function(rp) {\n                    const rpId = util.isObject(rp) ? rp.id : rp;\n                    return cp.id === rpId;\n                });\n            });\n        } else {\n            options = portsForRemoval || {};\n            newPorts = [];\n        }\n        this.startBatch('port-remove');\n        options.rewrite = true;\n        this.prop(['ports', 'items'], newPorts, options);\n        this.stopBatch('port-remove');\n        return this;\n    },\n\n    /**\n     * @private\n     */\n    _createPortData: function() {\n\n        var err = this._validatePorts();\n\n        if (err.length > 0) {\n            this.set('ports', this.previous('ports'));\n            throw new Error(err.join(' '));\n        }\n\n        var prevPortData;\n\n        if (this._portSettingsData) {\n\n            prevPortData = this._portSettingsData.getPorts();\n        }\n\n        this._portSettingsData = new PortData(this.get('ports'));\n\n        var curPortData = this._portSettingsData.getPorts();\n\n        if (prevPortData) {\n\n            var added = curPortData.filter(function(item) {\n                if (!prevPortData.find(function(prevPort) {\n                    return prevPort.id === item.id;\n                })) {\n                    return item;\n                }\n            });\n\n            var removed = prevPortData.filter(function(item) {\n                if (!curPortData.find(function(curPort) {\n                    return curPort.id === item.id;\n                })) {\n                    return item;\n                }\n            });\n\n            if (removed.length > 0) {\n                this.trigger('ports:remove', this, removed);\n            }\n\n            if (added.length > 0) {\n                this.trigger('ports:add', this, added);\n            }\n        }\n    }\n};\n\nexport const elementViewPortPrototype = {\n\n    portContainerMarkup: 'g',\n    portMarkup: [{\n        tagName: 'circle',\n        selector: 'circle',\n        attributes: {\n            'r': 10,\n            'fill': '#FFFFFF',\n            'stroke': '#000000'\n        }\n    }],\n    portLabelMarkup: [{\n        tagName: 'text',\n        selector: 'text',\n        attributes: {\n            'fill': '#000000'\n        }\n    }],\n    /** @type {Object<string, {portElement: Vectorizer, portLabelElement: Vectorizer}>} */\n    _portElementsCache: null,\n\n    /**\n     * @private\n     */\n    _initializePorts: function() {\n        this._cleanPortsCache();\n    },\n\n    /**\n     * @typedef {Object} Port\n     *\n     * @property {string} id\n     * @property {Object} position\n     * @property {Object} label\n     * @property {Object} attrs\n     * @property {string} markup\n     * @property {string} group\n     */\n\n    /**\n     * @private\n     */\n    _refreshPorts: function() {\n\n        this._removePorts();\n        this._cleanPortsCache();\n        this._renderPorts();\n    },\n\n    _cleanPortsCache: function() {\n        this._portElementsCache = {};\n    },\n\n    /**\n     * @private\n     */\n    _renderPorts: function() {\n\n        // references to rendered elements without z-index\n        var elementReferences = [];\n        var elem = this._getContainerElement();\n\n        for (var i = 0, count = elem.node.childNodes.length; i < count; i++) {\n            elementReferences.push(elem.node.childNodes[i]);\n        }\n\n        var portsGropsByZ = util.groupBy(this.model._portSettingsData.getPorts(), 'z');\n        var withoutZKey = 'auto';\n\n        // render non-z first\n        util.toArray(portsGropsByZ[withoutZKey]).forEach(function(port) {\n            var portElement = this._getPortElement(port);\n            elem.append(portElement);\n            elementReferences.push(portElement);\n        }, this);\n\n        var groupNames = Object.keys(portsGropsByZ);\n        for (var k = 0; k < groupNames.length; k++) {\n            var groupName = groupNames[k];\n            if (groupName !== withoutZKey) {\n                var z = parseInt(groupName, 10);\n                this._appendPorts(portsGropsByZ[groupName], z, elementReferences);\n            }\n        }\n\n        this._updatePorts();\n    },\n\n    /**\n     * @returns {V}\n     * @private\n     */\n    _getContainerElement: function() {\n\n        return this.rotatableNode || this.vel;\n    },\n\n    /**\n     * @param {Array<Port>}ports\n     * @param {number} z\n     * @param refs\n     * @private\n     */\n    _appendPorts: function(ports, z, refs) {\n\n        var containerElement = this._getContainerElement();\n        var portElements = util.toArray(ports).map(this._getPortElement, this);\n\n        if (refs[z] || z < 0) {\n            V(refs[Math.max(z, 0)]).before(portElements);\n        } else {\n            containerElement.append(portElements);\n        }\n    },\n\n    /**\n     * Try to get element from cache,\n     * @param port\n     * @returns {*}\n     * @private\n     */\n    _getPortElement: function(port) {\n\n        if (this._portElementsCache[port.id]) {\n            return this._portElementsCache[port.id].portElement;\n        }\n        return this._createPortElement(port);\n    },\n\n    findPortNodes: function(portId, selector) {\n        const portCache = this._portElementsCache[portId];\n        if (!portCache) return [];\n        if (!selector) return [portCache.portContentElement.node];\n        const portRoot = portCache.portElement.node;\n        const portSelectors = portCache.portSelectors;\n        return this.findBySelector(selector, portRoot, portSelectors);\n    },\n\n    findPortNode: function(portId, selector) {\n        const [node = null] = this.findPortNodes(portId, selector);\n        return node;\n    },\n\n    /**\n     * @private\n     */\n    _updatePorts: function() {\n\n        // layout ports without group\n        this._updatePortGroup(undefined);\n        // layout ports with explicit group\n        var groupsNames = Object.keys(this.model._portSettingsData.groups);\n        groupsNames.forEach(this._updatePortGroup, this);\n    },\n\n    /**\n     * @private\n     */\n    _removePorts: function() {\n        util.invoke(this._portElementsCache, 'portElement.remove');\n    },\n\n    /**\n     * @param {Port} port\n     * @returns {V}\n     * @private\n     */\n    _createPortElement: function(port) {\n\n        let portElement;\n        let labelElement;\n        let labelSelectors;\n        let portSelectors;\n\n        var portContainerElement = V(this.portContainerMarkup).addClass('joint-port');\n\n        var portMarkup = this._getPortMarkup(port);\n        if (Array.isArray(portMarkup)) {\n            var portDoc = this.parseDOMJSON(portMarkup, portContainerElement.node);\n            var portFragment = portDoc.fragment;\n            if (portFragment.childNodes.length > 1) {\n                portElement = V('g').append(portFragment);\n            } else {\n                portElement = V(portFragment.firstChild);\n            }\n            portSelectors = portDoc.selectors;\n        } else {\n            portElement = V(portMarkup);\n            if (Array.isArray(portElement)) {\n                portElement = V('g').append(portElement);\n            }\n        }\n\n        if (!portElement) {\n            throw new Error('ElementView: Invalid port markup.');\n        }\n\n        portElement.attr({\n            'port': port.id,\n            'port-group': port.group\n        });\n\n        // If the port ID is a number, we need to add\n        // extra information to the port element to distinguish\n        // between ports with the same ID but different types.\n        if (util.isNumber(port.id)) {\n            portElement.attr('port-id-type', 'number');\n        }\n\n        const labelMarkupDef = this._getPortLabelMarkup(port.label);\n        if (Array.isArray(labelMarkupDef)) {\n            // JSON Markup\n            const { fragment, selectors } = this.parseDOMJSON(labelMarkupDef, portContainerElement.node);\n            const childCount = fragment.childNodes.length;\n            if (childCount > 0) {\n                labelSelectors = selectors;\n                labelElement = (childCount === 1) ? V(fragment.firstChild) : V('g').append(fragment);\n            }\n        } else {\n            // String Markup\n            labelElement = V(labelMarkupDef);\n            if (Array.isArray(labelElement)) {\n                labelElement = V('g').append(labelElement);\n            }\n        }\n\n        var portContainerSelectors;\n        if (portSelectors && labelSelectors) {\n            for (var key in labelSelectors) {\n                if (portSelectors[key] && key !== this.selector) throw new Error('ElementView: selectors within port must be unique.');\n            }\n            portContainerSelectors = util.assign({}, portSelectors, labelSelectors);\n        } else {\n            portContainerSelectors = portSelectors || labelSelectors || {};\n        }\n\n        // The `portRootSelector` points to the root SVGNode of the port.\n        // Either the implicit wrapping group <g/> in case the port consist of multiple SVGNodes.\n        // Or the single SVGNode of the port.\n        const portRootSelector = 'portRoot';\n        // The `labelRootSelector` points to the root SVGNode of the label.\n        const labelRootSelector = 'labelRoot';\n        // The `labelTextSelector` points to all text SVGNodes of the label.\n        const labelTextSelector = 'labelText';\n\n        if (!(portRootSelector in portContainerSelectors)) {\n            portContainerSelectors[portRootSelector] = portElement.node;\n        }\n\n        if (labelElement) {\n            const labelNode = labelElement.node;\n            if (!(labelRootSelector in portContainerSelectors)) {\n                portContainerSelectors[labelRootSelector] = labelNode;\n            }\n            if (!(labelTextSelector in portContainerSelectors)) {\n                // If the label is a <text> element, we can use it directly.\n                // Otherwise, we need to find the <text> element within the label.\n                const labelTextNode = (labelElement.tagName() === 'TEXT')\n                    ? labelNode\n                    : Array.from(labelNode.querySelectorAll('text'));\n                portContainerSelectors[labelTextSelector] = labelTextNode;\n                if (!labelSelectors) labelSelectors = {};\n                labelSelectors[labelTextSelector] = labelTextNode;\n            }\n        }\n\n        portContainerElement.append(portElement.addClass('joint-port-body'));\n        if (labelElement) {\n            portContainerElement.append(labelElement.addClass('joint-port-label'));\n        }\n\n        this._portElementsCache[port.id] = {\n            portElement: portContainerElement,\n            portLabelElement: labelElement,\n            portSelectors: portContainerSelectors,\n            portLabelSelectors: labelSelectors,\n            portContentElement: portElement,\n            portContentSelectors: portSelectors\n        };\n\n        return portContainerElement;\n    },\n\n    /**\n     * @param {string=} groupName\n     * @private\n     */\n    _updatePortGroup: function(groupName) {\n\n        var elementBBox = Rect(this.model.size());\n        var portsMetrics = this.model._portSettingsData.getGroupPortsMetrics(groupName, elementBBox);\n\n        for (var i = 0, n = portsMetrics.length; i < n; i++) {\n            var metrics = portsMetrics[i];\n            var portId = metrics.portId;\n            var cached = this._portElementsCache[portId] || {};\n            var portTransformation = metrics.portTransformation;\n            var labelTransformation = metrics.labelTransformation;\n            if (labelTransformation && cached.portLabelElement) {\n                this.updateDOMSubtreeAttributes(cached.portLabelElement.node, labelTransformation.attrs, {\n                    rootBBox: new Rect(metrics.labelSize),\n                    selectors: cached.portLabelSelectors\n                });\n                this.applyPortTransform(cached.portLabelElement, labelTransformation, (-portTransformation.angle || 0));\n            }\n            this.updateDOMSubtreeAttributes(cached.portElement.node, metrics.portAttrs, {\n                rootBBox: new Rect(metrics.portSize),\n                selectors: cached.portSelectors\n            });\n            this.applyPortTransform(cached.portElement, portTransformation);\n        }\n    },\n\n    /**\n     * @param {Vectorizer} element\n     * @param {{dx:number, dy:number, angle: number, attrs: Object, x:number: y:number}} transformData\n     * @param {number=} initialAngle\n     * @constructor\n     */\n    applyPortTransform: function(element, transformData, initialAngle) {\n\n        var matrix = V.createSVGMatrix()\n            .rotate(initialAngle || 0)\n            .translate(transformData.x || 0, transformData.y || 0)\n            .rotate(transformData.angle || 0);\n\n        element.transform(matrix, { absolute: true });\n    },\n\n    /**\n     * @param {Port} port\n     * @returns {string}\n     * @private\n     */\n    _getPortMarkup: function(port) {\n\n        return port.markup || this.model.get('portMarkup') || this.model.portMarkup || this.portMarkup;\n    },\n\n    /**\n     * @param {Object} label\n     * @returns {string}\n     * @private\n     */\n    _getPortLabelMarkup: function(label) {\n\n        return label.markup || this.model.get('portLabelMarkup') || this.model.portLabelMarkup || this.portLabelMarkup;\n    }\n};\n\n","import { Cell } from './Cell.mjs';\nimport { Point, toRad, normalizeAngle, Rect } from '../g/index.mjs';\nimport { isNumber, isObject, interpolate, assign, invoke, normalizeSides } from '../util/index.mjs';\nimport { elementPortPrototype } from './ports.mjs';\n\n// Element base model.\n// -----------------------------\n\nexport const Element = Cell.extend({\n\n    defaults: {\n        position: { x: 0, y: 0 },\n        size: { width: 1, height: 1 },\n        angle: 0\n    },\n\n    initialize: function() {\n\n        this._initializePorts();\n        Cell.prototype.initialize.apply(this, arguments);\n    },\n\n    /**\n     * @abstract\n     */\n    _initializePorts: function() {\n        // implemented in ports.js\n    },\n\n    _refreshPorts: function() {\n        // implemented in ports.js\n    },\n\n    isElement: function() {\n\n        return true;\n    },\n\n    position: function(x, y, opt) {\n\n        const isSetter = isNumber(y);\n        opt = (isSetter ? opt : x) || {};\n        const { parentRelative, deep, restrictedArea } = opt;\n\n\n        // option `parentRelative` for setting the position relative to the element's parent.\n        let parentPosition;\n        if (parentRelative) {\n\n            // Getting the parent's position requires the collection.\n            // Cell.parent() holds cell id only.\n            if (!this.graph) throw new Error('Element must be part of a graph.');\n\n            const parent = this.getParentCell();\n            if (parent && !parent.isLink()) {\n                parentPosition = parent.get('position');\n            }\n        }\n\n        if (isSetter) {\n\n            if (parentPosition) {\n                x += parentPosition.x;\n                y += parentPosition.y;\n            }\n\n            if (deep || restrictedArea) {\n                const { x: x0, y: y0 } = this.get('position');\n                this.translate(x - x0, y - y0, opt);\n            } else {\n                this.set('position', { x, y }, opt);\n            }\n\n            return this;\n\n        } else { // Getter returns a geometry point.\n\n            const elementPosition = Point(this.get('position'));\n            return parentRelative\n                ? elementPosition.difference(parentPosition)\n                : elementPosition;\n        }\n    },\n\n    translate: function(tx, ty, opt) {\n\n        tx = tx || 0;\n        ty = ty || 0;\n\n        if (tx === 0 && ty === 0) {\n            // Like nothing has happened.\n            return this;\n        }\n\n        opt = opt || {};\n        // Pass the initiator of the translation.\n        opt.translateBy = opt.translateBy || this.id;\n\n        var position = this.get('position') || { x: 0, y: 0 };\n        var ra = opt.restrictedArea;\n        if (ra && opt.translateBy === this.id) {\n\n            if (typeof ra === 'function') {\n\n                var newPosition = ra.call(this, position.x + tx, position.y + ty, opt);\n\n                tx = newPosition.x - position.x;\n                ty = newPosition.y - position.y;\n\n            } else  {\n                // We are restricting the translation for the element itself only. We get\n                // the bounding box of the element including all its embeds.\n                // All embeds have to be translated the exact same way as the element.\n                var bbox = this.getBBox({ deep: true });\n                //- - - - - - - - - - - - -> ra.x + ra.width\n                // - - - -> position.x      |\n                // -> bbox.x\n                //                ▓▓▓▓▓▓▓   |\n                //         ░░░░░░░▓▓▓▓▓▓▓\n                //         ░░░░░░░░░        |\n                //   ▓▓▓▓▓▓▓▓░░░░░░░\n                //   ▓▓▓▓▓▓▓▓               |\n                //   <-dx->                     | restricted area right border\n                //         <-width->        |   ░ translated element\n                //   <- - bbox.width - ->       ▓ embedded element\n                var dx = position.x - bbox.x;\n                var dy = position.y - bbox.y;\n                // Find the maximal/minimal coordinates that the element can be translated\n                // while complies the restrictions.\n                var x = Math.max(ra.x + dx, Math.min(ra.x + ra.width + dx - bbox.width, position.x + tx));\n                var y = Math.max(ra.y + dy, Math.min(ra.y + ra.height + dy - bbox.height, position.y + ty));\n                // recalculate the translation taking the restrictions into account.\n                tx = x - position.x;\n                ty = y - position.y;\n            }\n        }\n\n        var translatedPosition = {\n            x: position.x + tx,\n            y: position.y + ty\n        };\n\n        // To find out by how much an element was translated in event 'change:position' handlers.\n        opt.tx = tx;\n        opt.ty = ty;\n\n        if (opt.transition) {\n\n            if (!isObject(opt.transition)) opt.transition = {};\n\n            this.transition('position', translatedPosition, assign({}, opt.transition, {\n                valueFunction: interpolate.object\n            }));\n\n            // Recursively call `translate()` on all the embeds cells.\n            invoke(this.getEmbeddedCells(), 'translate', tx, ty, opt);\n\n        } else {\n\n            this.startBatch('translate', opt);\n            this.set('position', translatedPosition, opt);\n            invoke(this.getEmbeddedCells(), 'translate', tx, ty, opt);\n            this.stopBatch('translate', opt);\n        }\n\n        return this;\n    },\n\n    size: function(width, height, opt) {\n\n        var currentSize = this.get('size');\n        // Getter\n        // () signature\n        if (width === undefined) {\n            return {\n                width: currentSize.width,\n                height: currentSize.height\n            };\n        }\n        // Setter\n        // (size, opt) signature\n        if (isObject(width)) {\n            opt = height;\n            height = isNumber(width.height) ? width.height : currentSize.height;\n            width = isNumber(width.width) ? width.width : currentSize.width;\n        }\n\n        return this.resize(width, height, opt);\n    },\n\n    resize: function(width, height, opt) {\n\n        opt = opt || {};\n\n        this.startBatch('resize', opt);\n\n        if (opt.direction) {\n\n            var currentSize = this.get('size');\n\n            switch (opt.direction) {\n\n                case 'left':\n                case 'right':\n                    // Don't change height when resizing horizontally.\n                    height = currentSize.height;\n                    break;\n\n                case 'top':\n                case 'bottom':\n                    // Don't change width when resizing vertically.\n                    width = currentSize.width;\n                    break;\n            }\n\n            // Get the angle and clamp its value between 0 and 360 degrees.\n            var angle = normalizeAngle(this.get('angle') || 0);\n\n            // This is a rectangle in size of the un-rotated element.\n            var bbox = this.getBBox();\n\n            var origin;\n\n            if (angle) {\n\n                var quadrant = {\n                    'top-right': 0,\n                    'right': 0,\n                    'top-left': 1,\n                    'top': 1,\n                    'bottom-left': 2,\n                    'left': 2,\n                    'bottom-right': 3,\n                    'bottom': 3\n                }[opt.direction];\n\n                if (opt.absolute) {\n\n                    // We are taking the element's rotation into account\n                    quadrant += Math.floor((angle + 45) / 90);\n                    quadrant %= 4;\n                }\n\n                // Pick the corner point on the element, which meant to stay on its place before and\n                // after the rotation.\n                var fixedPoint = bbox[['bottomLeft', 'corner', 'topRight', 'origin'][quadrant]]();\n\n                // Find  an image of the previous indent point. This is the position, where is the\n                // point actually located on the screen.\n                var imageFixedPoint = Point(fixedPoint).rotate(bbox.center(), -angle);\n\n                // Every point on the element rotates around a circle with the centre of rotation\n                // in the middle of the element while the whole element is being rotated. That means\n                // that the distance from a point in the corner of the element (supposed its always rect) to\n                // the center of the element doesn't change during the rotation and therefore it equals\n                // to a distance on un-rotated element.\n                // We can find the distance as DISTANCE = (ELEMENTWIDTH/2)^2 + (ELEMENTHEIGHT/2)^2)^0.5.\n                var radius = Math.sqrt((width * width) + (height * height)) / 2;\n\n                // Now we are looking for an angle between x-axis and the line starting at image of fixed point\n                // and ending at the center of the element. We call this angle `alpha`.\n\n                // The image of a fixed point is located in n-th quadrant. For each quadrant passed\n                // going anti-clockwise we have to add 90 degrees. Note that the first quadrant has index 0.\n                //\n                // 3 | 2\n                // --c-- Quadrant positions around the element's center `c`\n                // 0 | 1\n                //\n                var alpha = quadrant * Math.PI / 2;\n\n                // Add an angle between the beginning of the current quadrant (line parallel with x-axis or y-axis\n                // going through the center of the element) and line crossing the indent of the fixed point and the center\n                // of the element. This is the angle we need but on the un-rotated element.\n                alpha += Math.atan(quadrant % 2 == 0 ? height / width : width / height);\n\n                // Lastly we have to deduct the original angle the element was rotated by and that's it.\n                alpha -= toRad(angle);\n\n                // With this angle and distance we can easily calculate the centre of the un-rotated element.\n                // Note that fromPolar constructor accepts an angle in radians.\n                var center = Point.fromPolar(radius, alpha, imageFixedPoint);\n\n                // The top left corner on the un-rotated element has to be half a width on the left\n                // and half a height to the top from the center. This will be the origin of rectangle\n                // we were looking for.\n                origin = Point(center).offset(width / -2, height / -2);\n\n            } else {\n                // calculation for the origin Point when there is no rotation of the element\n                origin = bbox.topLeft();\n\n                switch (opt.direction) {\n                    case 'top':\n                    case 'top-right':\n                        origin.offset(0, bbox.height - height);\n                        break;\n                    case 'left':\n                    case 'bottom-left':\n                        origin.offset(bbox.width -width, 0);\n                        break;\n                    case 'top-left':\n                        origin.offset(bbox.width - width, bbox.height - height);\n                        break;\n                }\n            }\n\n            // Resize the element (before re-positioning it).\n            this.set('size', { width: width, height: height }, opt);\n\n            // Finally, re-position the element.\n            this.position(origin.x, origin.y, opt);\n\n        } else {\n\n            // Resize the element.\n            this.set('size', { width: width, height: height }, opt);\n        }\n\n        this.stopBatch('resize', opt);\n\n        return this;\n    },\n\n    scale: function(sx, sy, origin, opt) {\n\n        var scaledBBox = this.getBBox().scale(sx, sy, origin);\n        this.startBatch('scale', opt);\n        this.position(scaledBBox.x, scaledBBox.y, opt);\n        this.resize(scaledBBox.width, scaledBBox.height, opt);\n        this.stopBatch('scale');\n        return this;\n    },\n\n    fitEmbeds: function(opt) {\n\n        return this.fitToChildren(opt);\n    },\n\n    fitToChildren: function(opt = {}) {\n\n        // Getting the children's size and position requires the collection.\n        // Cell.get('embeds') holds an array of cell ids only.\n        const { graph } = this;\n        if (!graph) throw new Error('Element must be part of a graph.');\n\n        const childElements = this.getEmbeddedCells().filter(cell => cell.isElement());\n        if (childElements.length === 0) return this;\n\n        this.startBatch('fit-embeds', opt);\n\n        if (opt.deep) {\n            // `opt.deep = true` means \"fit to all descendants\".\n            // As the first action of the fitting algorithm, recursively apply `fitToChildren()` on all descendants.\n            // - i.e. the algorithm is applied in reverse-depth order - start from deepest descendant, then go up (= this element).\n            invoke(childElements, 'fitToChildren', opt);\n        }\n\n        // Set new size and position of this element, based on:\n        // - union of bboxes of all children\n        // - inflated by given `opt.padding`\n        this._fitToElements(Object.assign({ elements: childElements }, opt));\n\n        this.stopBatch('fit-embeds');\n\n        return this;\n    },\n\n    fitParent: function(opt = {}) {\n\n        const { graph } = this;\n        if (!graph) throw new Error('Element must be part of a graph.');\n\n        // When `opt.deep = true`, we want `opt.terminator` to be the last ancestor processed.\n        // If the current element is `opt.terminator`, it means that this element has already been processed as parent so we can exit now.\n        if (opt.deep && opt.terminator && ((opt.terminator === this) || (opt.terminator === this.id))) return this;\n\n        const parentElement = this.getParentCell();\n        if (!parentElement || !parentElement.isElement()) return this;\n\n        // Get all children of parent element (i.e. this element + any sibling elements).\n        const siblingElements = parentElement.getEmbeddedCells().filter(cell => cell.isElement());\n        if (siblingElements.length === 0) return this;\n\n        this.startBatch('fit-parent', opt);\n\n        // Set new size and position of parent element, based on:\n        // - union of bboxes of all children of parent element (i.e. this element + any sibling elements)\n        // - inflated by given `opt.padding`\n        parentElement._fitToElements(Object.assign({ elements: siblingElements }, opt));\n\n        if (opt.deep) {\n            // `opt.deep = true` means \"fit all ancestors to their respective children\".\n            // As the last action of the fitting algorithm, recursively apply `fitParent()` on all ancestors.\n            // - i.e. the algorithm is applied in reverse-depth order - start from deepest descendant (= this element), then go up.\n            parentElement.fitParent(opt);\n        }\n\n        this.stopBatch('fit-parent');\n\n        return this;\n    },\n\n    // Assumption: This element is part of a graph.\n    _fitToElements: function(opt = {}) {\n\n        const elementsBBox = this.graph.getCellsBBox(opt.elements);\n        // If no `opt.elements` were provided, do nothing.\n        if (!elementsBBox) return;\n\n        const { expandOnly, shrinkOnly } = opt;\n        // This combination is meaningless, do nothing.\n        if (expandOnly && shrinkOnly) return;\n\n        // Calculate new size and position of this element based on:\n        // - union of bboxes of `opt.elements`\n        // - inflated by `opt.padding` (if not provided, all four properties = 0)\n        let { x, y, width, height } = elementsBBox;\n        const { left, right, top, bottom } = normalizeSides(opt.padding);\n        x -= left;\n        y -= top;\n        width += left + right;\n        height += bottom + top;\n        let resultBBox = new Rect(x, y, width, height);\n\n        if (expandOnly) {\n            // Non-shrinking is enforced by taking union of this element's current bbox with bbox calculated from `opt.elements`.\n            resultBBox = this.getBBox().union(resultBBox);\n\n        } else if (shrinkOnly) {\n            // Non-expansion is enforced by taking intersection of this element's current bbox with bbox calculated from `opt.elements`.\n            const intersectionBBox = this.getBBox().intersect(resultBBox);\n            // If all children are outside this element's current bbox, then `intersectionBBox` is `null` - does not make sense, do nothing.\n            if (!intersectionBBox) return;\n\n            resultBBox =  intersectionBBox;\n        }\n\n        // Set the new size and position of this element.\n        this.set({\n            position: { x: resultBBox.x, y: resultBBox.y },\n            size: { width: resultBBox.width, height: resultBBox.height }\n        }, opt);\n    },\n\n    // Rotate element by `angle` degrees, optionally around `origin` point.\n    // If `origin` is not provided, it is considered to be the center of the element.\n    // If `absolute` is `true`, the `angle` is considered is absolute, i.e. it is not\n    // the difference from the previous angle.\n    rotate: function(angle, absolute, origin, opt) {\n\n        if (origin) {\n\n            var center = this.getBBox().center();\n            var size = this.get('size');\n            var position = this.get('position');\n            center.rotate(origin, this.get('angle') - angle);\n            var dx = center.x - size.width / 2 - position.x;\n            var dy = center.y - size.height / 2 - position.y;\n            this.startBatch('rotate', { angle: angle, absolute: absolute, origin: origin });\n            this.position(position.x + dx, position.y + dy, opt);\n            this.rotate(angle, absolute, null, opt);\n            this.stopBatch('rotate');\n\n        } else {\n\n            this.set('angle', absolute ? angle : (this.get('angle') + angle) % 360, opt);\n        }\n\n        return this;\n    },\n\n    angle: function() {\n        return normalizeAngle(this.get('angle') || 0);\n    },\n\n    getBBox: function(opt = {}) {\n\n        const { graph, attributes } = this;\n        const { deep, rotate } = opt;\n\n        if (deep && graph) {\n            // Get all the embedded elements using breadth first algorithm.\n            const elements = this.getEmbeddedCells({ deep: true, breadthFirst: true });\n            // Add the model itself.\n            elements.push(this);\n            // Note: the default of getCellsBBox() is rotate=true and can't be\n            // changed without a breaking change\n            return graph.getCellsBBox(elements, opt);\n        }\n\n        const { angle = 0, position: { x, y }, size: { width, height }} = attributes;\n        const bbox = new Rect(x, y, width, height);\n        if (rotate) {\n            bbox.rotateAroundCenter(angle);\n        }\n        return bbox;\n    },\n\n    getPointFromConnectedLink: function(link, endType) {\n        // Center of the model\n        var bbox = this.getBBox();\n        var center = bbox.center();\n        // Center of a port\n        var endDef = link.get(endType);\n        if (!endDef) return center;\n        var portId = endDef.port;\n        if (!portId || !this.hasPort(portId)) return center;\n        var portGroup = this.portProp(portId, ['group']);\n        var portsPositions = this.getPortsPositions(portGroup);\n        var portCenter = new Point(portsPositions[portId]).offset(bbox.origin());\n        var angle = this.angle();\n        if (angle) portCenter.rotate(center, -angle);\n        return portCenter;\n    }\n});\n\nassign(Element.prototype, elementPortPrototype);\n\n","import { Cell } from './Cell.mjs';\nimport { clone, isPlainObject, isFunction, isString, isNumber } from '../util/index.mjs';\nimport { Point, Polyline } from '../g/index.mjs';\n\n// Link base model.\n// --------------------------\n\nexport const Link = Cell.extend({\n\n    // may be overwritten by user to change default label (its markup, size, attrs, position)\n    defaultLabel: undefined,\n\n    // deprecated\n    // may be overwritten by user to change default label markup\n    // lower priority than defaultLabel.markup\n    labelMarkup: undefined,\n\n    // private\n    _builtins: {\n        defaultLabel: {\n            // builtin default markup:\n            // used if neither defaultLabel.markup\n            // nor label.markup is set\n            markup: [\n                {\n                    tagName: 'rect',\n                    selector: 'rect' // faster than tagName CSS selector\n                }, {\n                    tagName: 'text',\n                    selector: 'text' // faster than tagName CSS selector\n                }\n            ],\n            // builtin default attributes:\n            // applied only if builtin default markup is used\n            attrs: {\n                text: {\n                    fill: '#000000',\n                    fontSize: 14,\n                    textAnchor: 'middle',\n                    textVerticalAnchor: 'middle',\n                    pointerEvents: 'none'\n                },\n                rect: {\n                    ref: 'text',\n                    fill: '#ffffff',\n                    rx: 3,\n                    ry: 3,\n                    x: 'calc(x)',\n                    y: 'calc(y)',\n                    width: 'calc(w)',\n                    height: 'calc(h)'\n                }\n            },\n            // builtin default position:\n            // used if neither defaultLabel.position\n            // nor label.position is set\n            position: {\n                distance: 0.5\n            }\n        }\n    },\n\n    defaults: {\n        source: {},\n        target: {}\n    },\n\n    isLink: function() {\n\n        return true;\n    },\n\n    disconnect: function(opt) {\n\n        return this.set({\n            source: { x: 0, y: 0 },\n            target: { x: 0, y: 0 }\n        }, opt);\n    },\n\n    source: function(source, args, opt) {\n\n        // getter\n        if (source === undefined) {\n            return clone(this.get('source'));\n        }\n\n        // setter\n        var setSource;\n        var setOpt;\n\n        // `source` is a cell\n        // take only its `id` and combine with `args`\n        var isCellProvided = source instanceof Cell;\n        if (isCellProvided) { // three arguments\n            setSource = clone(args) || {};\n            setSource.id = source.id;\n            setOpt = opt;\n            return this.set('source', setSource, setOpt);\n        }\n\n        // `source` is a point-like object\n        // for example, a g.Point\n        // take only its `x` and `y` and combine with `args`\n        var isPointProvided = !isPlainObject(source);\n        if (isPointProvided) { // three arguments\n            setSource = clone(args) || {};\n            setSource.x = source.x;\n            setSource.y = source.y;\n            setOpt = opt;\n            return this.set('source', setSource, setOpt);\n        }\n\n        // `source` is an object\n        // no checking\n        // two arguments\n        setSource = source;\n        setOpt = args;\n        return this.set('source', setSource, setOpt);\n    },\n\n    target: function(target, args, opt) {\n\n        // getter\n        if (target === undefined) {\n            return clone(this.get('target'));\n        }\n\n        // setter\n        var setTarget;\n        var setOpt;\n\n        // `target` is a cell\n        // take only its `id` argument and combine with `args`\n        var isCellProvided = target instanceof Cell;\n        if (isCellProvided) { // three arguments\n            setTarget = clone(args) || {};\n            setTarget.id = target.id;\n            setOpt = opt;\n            return this.set('target', setTarget, setOpt);\n        }\n\n        // `target` is a point-like object\n        // for example, a g.Point\n        // take only its `x` and `y` and combine with `args`\n        var isPointProvided = !isPlainObject(target);\n        if (isPointProvided) { // three arguments\n            setTarget = clone(args) || {};\n            setTarget.x = target.x;\n            setTarget.y = target.y;\n            setOpt = opt;\n            return this.set('target', setTarget, setOpt);\n        }\n\n        // `target` is an object\n        // no checking\n        // two arguments\n        setTarget = target;\n        setOpt = args;\n        return this.set('target', setTarget, setOpt);\n    },\n\n    router: function(name, args, opt) {\n\n        // getter\n        if (name === undefined) {\n            var router = this.get('router');\n            if (!router) {\n                return null;\n            }\n            if (typeof router === 'object') return clone(router);\n            return router; // e.g. a function\n        }\n\n        // setter\n        var isRouterProvided = ((typeof name === 'object') || (typeof name === 'function'));\n        var localRouter = isRouterProvided ? name : { name: name, args: args };\n        var localOpt = isRouterProvided ? args : opt;\n\n        return this.set('router', localRouter, localOpt);\n    },\n\n    connector: function(name, args, opt) {\n\n        // getter\n        if (name === undefined) {\n            var connector = this.get('connector');\n            if (!connector) {\n                return null;\n            }\n            if (typeof connector === 'object') return clone(connector);\n            return connector; // e.g. a function\n        }\n\n        // setter\n        var isConnectorProvided = ((typeof name === 'object' || typeof name === 'function'));\n        var localConnector = isConnectorProvided ? name : { name: name, args: args };\n        var localOpt = isConnectorProvided ? args : opt;\n\n        return this.set('connector', localConnector, localOpt);\n    },\n\n    // Labels API\n\n    // A convenient way to set labels. Currently set values will be mixined with `value` if used as a setter.\n    label: function(idx, label, opt) {\n\n        var labels = this.labels();\n\n        idx = (isFinite(idx) && idx !== null) ? (idx | 0) : 0;\n        if (idx < 0) idx = labels.length + idx;\n\n        // getter\n        if (arguments.length <= 1) return this.prop(['labels', idx]);\n        // setter\n        return this.prop(['labels', idx], label, opt);\n    },\n\n    labels: function(labels, opt) {\n\n        // getter\n        if (arguments.length === 0) {\n            labels = this.get('labels');\n            if (!Array.isArray(labels)) return [];\n            return labels.slice();\n        }\n        // setter\n        if (!Array.isArray(labels)) labels = [];\n        return this.set('labels', labels, opt);\n    },\n\n    hasLabels: function() {\n        const { labels } = this.attributes;\n        return Array.isArray(labels) && labels.length > 0;\n    },\n\n    insertLabel: function(idx, label, opt) {\n\n        if (!label) throw new Error('dia.Link: no label provided');\n\n        var labels = this.labels();\n        var n = labels.length;\n        idx = (isFinite(idx) && idx !== null) ? (idx | 0) : n;\n        if (idx < 0) idx = n + idx + 1;\n\n        labels.splice(idx, 0, label);\n        return this.labels(labels, opt);\n    },\n\n    // convenience function\n    // add label to end of labels array\n    appendLabel: function(label, opt) {\n\n        return this.insertLabel(-1, label, opt);\n    },\n\n    removeLabel: function(idx, opt) {\n\n        var labels = this.labels();\n        idx = (isFinite(idx) && idx !== null) ? (idx | 0) : -1;\n\n        labels.splice(idx, 1);\n        return this.labels(labels, opt);\n    },\n\n    // Vertices API\n\n    vertex: function(idx, vertex, opt) {\n\n        var vertices = this.vertices();\n\n        idx = (isFinite(idx) && idx !== null) ? (idx | 0) : 0;\n        if (idx < 0) idx = vertices.length + idx;\n\n        // getter\n        if (arguments.length <= 1) return this.prop(['vertices', idx]);\n\n        // setter\n        var setVertex = this._normalizeVertex(vertex);\n        return this.prop(['vertices', idx], setVertex, opt);\n    },\n\n    vertices: function(vertices, opt) {\n\n        // getter\n        if (arguments.length === 0) {\n            vertices = this.get('vertices');\n            if (!Array.isArray(vertices)) return [];\n            return vertices.slice();\n        }\n\n        // setter\n        if (!Array.isArray(vertices)) vertices = [];\n        var setVertices = [];\n        for (var i = 0; i < vertices.length; i++) {\n            var vertex = vertices[i];\n            var setVertex = this._normalizeVertex(vertex);\n            setVertices.push(setVertex);\n        }\n        return this.set('vertices', setVertices, opt);\n    },\n\n    insertVertex: function(idx, vertex, opt) {\n\n        if (!vertex) throw new Error('dia.Link: no vertex provided');\n\n        var vertices = this.vertices();\n        var n = vertices.length;\n        idx = (isFinite(idx) && idx !== null) ? (idx | 0) : n;\n        if (idx < 0) idx = n + idx + 1;\n\n        var setVertex = this._normalizeVertex(vertex);\n        vertices.splice(idx, 0, setVertex);\n        return this.vertices(vertices, opt);\n    },\n\n    removeVertex: function(idx, opt) {\n\n        var vertices = this.vertices();\n        idx = (isFinite(idx) && idx !== null) ? (idx | 0) : -1;\n\n        vertices.splice(idx, 1);\n        return this.vertices(vertices, opt);\n    },\n\n    _normalizeVertex: function(vertex) {\n\n        // is vertex a point-like object?\n        // for example, a g.Point\n        var isPointProvided = !isPlainObject(vertex);\n        if (isPointProvided) return { x: vertex.x, y: vertex.y };\n\n        // else: return vertex unchanged\n        return vertex;\n    },\n\n    // Transformations\n\n    translate: function(tx, ty, opt) {\n\n        // enrich the option object\n        opt = opt || {};\n        opt.translateBy = opt.translateBy || this.id;\n        opt.tx = tx;\n        opt.ty = ty;\n\n        return this.applyToPoints(function(p) {\n            return { x: (p.x || 0) + tx, y: (p.y || 0) + ty };\n        }, opt);\n    },\n\n    scale: function(sx, sy, origin, opt) {\n\n        return this.applyToPoints(function(p) {\n            return Point(p).scale(sx, sy, origin).toJSON();\n        }, opt);\n    },\n\n    applyToPoints: function(fn, opt) {\n\n        if (!isFunction(fn)) {\n            throw new TypeError('dia.Link: applyToPoints expects its first parameter to be a function.');\n        }\n\n        var attrs = {};\n\n        var { source, target } = this.attributes;\n        if (!source.id) {\n            attrs.source = fn(source);\n        }\n        if (!target.id) {\n            attrs.target = fn(target);\n        }\n\n        var vertices = this.vertices();\n        if (vertices.length > 0) {\n            attrs.vertices = vertices.map(fn);\n        }\n\n        return this.set(attrs, opt);\n    },\n\n    getSourcePoint: function() {\n        var sourceCell = this.getSourceCell();\n        if (!sourceCell) return new Point(this.source());\n        return sourceCell.getPointFromConnectedLink(this, 'source');\n    },\n\n    getTargetPoint: function() {\n        var targetCell = this.getTargetCell();\n        if (!targetCell) return new Point(this.target());\n        return targetCell.getPointFromConnectedLink(this, 'target');\n    },\n\n    getPointFromConnectedLink: function(/* link, endType */) {\n        return this.getPolyline().pointAt(0.5);\n    },\n\n    getPolyline: function() {\n        const points = [\n            this.getSourcePoint(),\n            ...this.vertices().map(Point),\n            this.getTargetPoint()\n        ];\n        return new Polyline(points);\n    },\n\n    getBBox: function() {\n        return this.getPolyline().bbox();\n    },\n\n    reparent: function(opt) {\n\n        var newParent;\n\n        if (this.graph) {\n\n            var source = this.getSourceElement();\n            var target = this.getTargetElement();\n            var prevParent = this.getParentCell();\n\n            if (source && target) {\n                if (source === target || source.isEmbeddedIn(target)) {\n                    newParent = target;\n                } else if (target.isEmbeddedIn(source)) {\n                    newParent = source;\n                } else {\n                    newParent = this.graph.getCommonAncestor(source, target);\n                }\n            }\n\n            if (prevParent && (!newParent || newParent.id !== prevParent.id)) {\n                // Unembed the link if source and target has no common ancestor\n                // or common ancestor changed\n                prevParent.unembed(this, opt);\n            }\n\n            if (newParent) {\n                newParent.embed(this, opt);\n            }\n        }\n\n        return newParent;\n    },\n\n    hasLoop: function(opt) {\n\n        opt = opt || {};\n\n        var { source, target } = this.attributes;\n        var sourceId = source.id;\n        var targetId = target.id;\n\n        if (!sourceId || !targetId) {\n            // Link \"pinned\" to the paper does not have a loop.\n            return false;\n        }\n\n        var loop = sourceId === targetId;\n\n        // Note that there in the deep mode a link can have a loop,\n        // even if it connects only a parent and its embed.\n        // A loop \"target equals source\" is valid in both shallow and deep mode.\n        if (!loop && opt.deep && this.graph) {\n\n            var sourceElement = this.getSourceCell();\n            var targetElement = this.getTargetCell();\n\n            loop = sourceElement.isEmbeddedIn(targetElement) || targetElement.isEmbeddedIn(sourceElement);\n        }\n\n        return loop;\n    },\n\n    // unlike source(), this method returns null if source is a point\n    getSourceCell: function() {\n\n        const { graph, attributes } = this;\n        var source = attributes.source;\n        return (source && source.id && graph && graph.getCell(source.id)) || null;\n    },\n\n    getSourceElement: function() {\n        var cell = this;\n        var visited = {};\n        do {\n            if (visited[cell.id]) return null;\n            visited[cell.id] = true;\n            cell = cell.getSourceCell();\n        } while (cell && cell.isLink());\n        return cell;\n    },\n\n    // unlike target(), this method returns null if target is a point\n    getTargetCell: function() {\n\n        const { graph, attributes } = this;\n        var target = attributes.target;\n        return (target && target.id && graph && graph.getCell(target.id)) || null;\n    },\n\n    getTargetElement: function() {\n        var cell = this;\n        var visited = {};\n        do {\n            if (visited[cell.id]) return null;\n            visited[cell.id] = true;\n            cell = cell.getTargetCell();\n        } while (cell && cell.isLink());\n        return cell;\n    },\n\n    // Returns the common ancestor for the source element,\n    // target element and the link itself.\n    getRelationshipAncestor: function() {\n\n        var connectionAncestor;\n\n        if (this.graph) {\n\n            var cells = [\n                this,\n                this.getSourceElement(), // null if source is a point\n                this.getTargetElement() // null if target is a point\n            ].filter(function(item) {\n                return !!item;\n            });\n\n            connectionAncestor = this.graph.getCommonAncestor.apply(this.graph, cells);\n        }\n\n        return connectionAncestor || null;\n    },\n\n    // Is source, target and the link itself embedded in a given cell?\n    isRelationshipEmbeddedIn: function(cell) {\n\n        var cellId = (isString(cell) || isNumber(cell)) ? cell : cell.id;\n        var ancestor = this.getRelationshipAncestor();\n\n        return !!ancestor && (ancestor.id === cellId || ancestor.isEmbeddedIn(cellId));\n    },\n\n    // Get resolved default label.\n    _getDefaultLabel: function() {\n\n        var defaultLabel = this.get('defaultLabel') || this.defaultLabel || {};\n\n        var label = {};\n        label.markup = defaultLabel.markup || this.get('labelMarkup') || this.labelMarkup;\n        label.position = defaultLabel.position;\n        label.attrs = defaultLabel.attrs;\n        label.size = defaultLabel.size;\n\n        return label;\n    }\n}, {\n\n    endsEqual: function(a, b) {\n\n        var portsEqual = a.port === b.port || !a.port && !b.port;\n        return a.id === b.id && portsEqual;\n    }\n});\n\n","export const env = {\n\n    _results: {},\n\n    _tests: {\n\n        svgforeignobject: function() {\n            return !!document.createElementNS &&\n                /SVGForeignObject/.test(({}).toString.call(document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject')));\n        },\n\n        // works for iOS browsers too\n        isSafari: function() {\n            return /Safari/.test(navigator.userAgent) && /Apple Computer/.test(navigator.vendor);\n        }\n    },\n\n    addTest: function(name, fn) {\n\n        return this._tests[name] = fn;\n    },\n\n    test: function(name) {\n\n        var fn = this._tests[name];\n\n        if (!fn) {\n            throw new Error('Test not defined (\"' + name + '\"). Use `joint.env.addTest(name, fn) to add a new test.`');\n        }\n\n        var result = this._results[name];\n\n        if (typeof result !== 'undefined') {\n            return result;\n        }\n\n        try {\n            result = fn();\n        } catch (error) {\n            result = false;\n        }\n\n        // Cache the test result.\n        this._results[name] = result;\n\n        return result;\n    }\n};\n","import V from '../V/index.mjs';\nimport { Element } from '../dia/Element.mjs';\nimport { Link as LinkBase } from '../dia/Link.mjs';\nimport { isPercentage, assign } from '../util/index.mjs';\nimport { attributes } from '../dia/attributes/index.mjs';\nimport { env } from '../env/index.mjs';\n\n\n// ELEMENTS\n\nexport const Rectangle = Element.define('standard.Rectangle', {\n    attrs: {\n        root: {\n            cursor: 'move'\n        },\n        body: {\n            width: 'calc(w)',\n            height: 'calc(h)',\n            strokeWidth: 2,\n            stroke: '#000000',\n            fill: '#FFFFFF'\n        },\n        label: {\n            textVerticalAnchor: 'middle',\n            textAnchor: 'middle',\n            x: 'calc(w/2)',\n            y: 'calc(h/2)',\n            fontSize: 14,\n            fill: '#333333'\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'rect',\n        selector: 'body',\n    }, {\n        tagName: 'text',\n        selector: 'label'\n    }]\n});\n\nexport const Circle = Element.define('standard.Circle', {\n    attrs: {\n        root: {\n            cursor: 'move'\n        },\n        body: {\n            cx: 'calc(s/2)',\n            cy: 'calc(s/2)',\n            r: 'calc(s/2)',\n            strokeWidth: 2,\n            stroke: '#333333',\n            fill: '#FFFFFF'\n        },\n        label: {\n            textVerticalAnchor: 'middle',\n            textAnchor: 'middle',\n            x: 'calc(w/2)',\n            y: 'calc(h/2)',\n            fontSize: 14,\n            fill: '#333333'\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'circle',\n        selector: 'body'\n    }, {\n        tagName: 'text',\n        selector: 'label'\n    }]\n});\n\nexport const Ellipse = Element.define('standard.Ellipse', {\n    attrs: {\n        root: {\n            cursor: 'move'\n        },\n        body: {\n            cx: 'calc(w/2)',\n            cy: 'calc(h/2)',\n            rx: 'calc(w/2)',\n            ry: 'calc(h/2)',\n            strokeWidth: 2,\n            stroke: '#333333',\n            fill: '#FFFFFF'\n        },\n        label: {\n            textVerticalAnchor: 'middle',\n            textAnchor: 'middle',\n            x: 'calc(w/2)',\n            y: 'calc(h/2)',\n            fontSize: 14,\n            fill: '#333333'\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'ellipse',\n        selector: 'body'\n    }, {\n        tagName: 'text',\n        selector: 'label'\n    }]\n});\n\nexport const Path = Element.define('standard.Path', {\n    attrs: {\n        root: {\n            cursor: 'move'\n        },\n        body: {\n            d: 'M 0 0 H calc(w) V calc(h) H 0 Z',\n            strokeWidth: 2,\n            stroke: '#333333',\n            fill: '#FFFFFF'\n        },\n        label: {\n            textVerticalAnchor: 'middle',\n            textAnchor: 'middle',\n            x: 'calc(w/2)',\n            y: 'calc(h/2)',\n            fontSize: 14,\n            fill: '#333333'\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'path',\n        selector: 'body'\n    }, {\n        tagName: 'text',\n        selector: 'label'\n    }]\n});\n\nexport const Polygon = Element.define('standard.Polygon', {\n    attrs: {\n        root: {\n            cursor: 'move'\n        },\n        body: {\n            points: '0 0 calc(w) 0 calc(w) calc(h) 0 calc(h)',\n            strokeWidth: 2,\n            stroke: '#333333',\n            fill: '#FFFFFF'\n        },\n        label: {\n            textVerticalAnchor: 'middle',\n            textAnchor: 'middle',\n            x: 'calc(w/2)',\n            y: 'calc(h/2)',\n            fontSize: 14,\n            fill: '#333333'\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'polygon',\n        selector: 'body'\n    }, {\n        tagName: 'text',\n        selector: 'label'\n    }]\n});\n\nexport const Polyline = Element.define('standard.Polyline', {\n    attrs: {\n        root: {\n            cursor: 'move'\n        },\n        body: {\n            points: '0 0 calc(w) 0 calc(w) calc(h) 0 calc(h)',\n            strokeWidth: 2,\n            stroke: '#333333',\n            fill: '#FFFFFF'\n        },\n        label: {\n            textVerticalAnchor: 'middle',\n            textAnchor: 'middle',\n            x: 'calc(w/2)',\n            y: 'calc(h/2)',\n            fontSize: 14,\n            fill: '#333333'\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'polyline',\n        selector: 'body'\n    }, {\n        tagName: 'text',\n        selector: 'label'\n    }]\n});\n\nexport const Image = Element.define('standard.Image', {\n    attrs: {\n        root: {\n            cursor: 'move'\n        },\n        image: {\n            width: 'calc(w)',\n            height: 'calc(h)',\n            // xlinkHref: '[URL]'\n        },\n        label: {\n            textVerticalAnchor: 'top',\n            textAnchor: 'middle',\n            x: 'calc(w/2)',\n            y: 'calc(h+10)',\n            fontSize: 14,\n            fill: '#333333'\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'image',\n        selector: 'image'\n    }, {\n        tagName: 'text',\n        selector: 'label'\n    }]\n});\n\nexport const BorderedImage = Element.define('standard.BorderedImage', {\n    attrs: {\n        root: {\n            cursor: 'move'\n        },\n        border: {\n            width: 'calc(w)',\n            height: 'calc(h)',\n            stroke: '#333333',\n            strokeWidth: 2\n        },\n        background: {\n            width: 'calc(w-1)',\n            height: 'calc(h-1)',\n            x: 0.5,\n            y: 0.5,\n            fill: '#FFFFFF'\n        },\n        image: {\n            // xlinkHref: '[URL]'\n            width: 'calc(w-1)',\n            height: 'calc(h-1)',\n            x: 0.5,\n            y: 0.5\n        },\n        label: {\n            textVerticalAnchor: 'top',\n            textAnchor: 'middle',\n            x: 'calc(w/2)',\n            y: 'calc(h+10)',\n            fontSize: 14,\n            fill: '#333333'\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'rect',\n        selector: 'background',\n        attributes: {\n            'stroke': 'none'\n        }\n    }, {\n        tagName: 'image',\n        selector: 'image'\n    }, {\n        tagName: 'rect',\n        selector: 'border',\n        attributes: {\n            'fill': 'none'\n        }\n    }, {\n        tagName: 'text',\n        selector: 'label'\n    }]\n});\n\nexport const EmbeddedImage = Element.define('standard.EmbeddedImage', {\n    attrs: {\n        root: {\n            cursor: 'move'\n        },\n        body: {\n            width: 'calc(w)',\n            height: 'calc(h)',\n            stroke: '#333333',\n            fill: '#FFFFFF',\n            strokeWidth: 2\n        },\n        image: {\n            // xlinkHref: '[URL]'\n            width: 'calc(0.3*w)',\n            height: 'calc(h-20)',\n            x: 10,\n            y: 10,\n            preserveAspectRatio: 'xMidYMin'\n        },\n        label: {\n            textVerticalAnchor: 'top',\n            textAnchor: 'left',\n            x: 'calc(0.3*w+20)', // 10 + 10\n            y: 10,\n            fontSize: 14,\n            fill: '#333333'\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'rect',\n        selector: 'body'\n    }, {\n        tagName: 'image',\n        selector: 'image'\n    }, {\n        tagName: 'text',\n        selector: 'label'\n    }]\n});\n\nexport const InscribedImage = Element.define('standard.InscribedImage', {\n    attrs: {\n        root: {\n            cursor: 'move'\n        },\n        border: {\n            rx: 'calc(w/2)',\n            ry: 'calc(h/2)',\n            cx: 'calc(w/2)',\n            cy: 'calc(h/2)',\n            stroke: '#333333',\n            strokeWidth: 2\n        },\n        background: {\n            rx: 'calc(w/2)',\n            ry: 'calc(h/2)',\n            cx: 'calc(w/2)',\n            cy: 'calc(h/2)',\n            fill: '#FFFFFF'\n        },\n        image: {\n            // The image corners touch the border when its size is Math.sqrt(2) / 2 = 0.707.. ~= 70%\n            width: 'calc(0.68*w)',\n            height: 'calc(0.68*h)',\n            // The image offset is calculated as (100% - 68%) / 2\n            x: 'calc(0.16*w)',\n            y: 'calc(0.16*h)',\n            preserveAspectRatio: 'xMidYMid'\n            // xlinkHref: '[URL]'\n        },\n        label: {\n            textVerticalAnchor: 'top',\n            textAnchor: 'middle',\n            x: 'calc(w/2)',\n            y: 'calc(h+10)',\n            fontSize: 14,\n            fill: '#333333'\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'ellipse',\n        selector: 'background'\n    }, {\n        tagName: 'image',\n        selector: 'image'\n    }, {\n        tagName: 'ellipse',\n        selector: 'border',\n        attributes: {\n            'fill': 'none'\n        }\n    }, {\n        tagName: 'text',\n        selector: 'label'\n    }]\n});\n\nexport const HeaderedRectangle = Element.define('standard.HeaderedRectangle', {\n    attrs: {\n        root: {\n            cursor: 'move'\n        },\n        body: {\n            width: 'calc(w)',\n            height: 'calc(h)',\n            strokeWidth: 2,\n            stroke: '#000000',\n            fill: '#FFFFFF'\n        },\n        header: {\n            width: 'calc(w)',\n            height: 30,\n            strokeWidth: 2,\n            stroke: '#000000',\n            fill: '#FFFFFF'\n        },\n        headerText: {\n            textVerticalAnchor: 'middle',\n            textAnchor: 'middle',\n            x: 'calc(w/2)',\n            y: 15,\n            fontSize: 16,\n            fill: '#333333'\n        },\n        bodyText: {\n            textVerticalAnchor: 'middle',\n            textAnchor: 'middle',\n            x: 'calc(w/2)',\n            y: 'calc(h/2+15)',\n            fontSize: 14,\n            fill: '#333333'\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'rect',\n        selector: 'body'\n    }, {\n        tagName: 'rect',\n        selector: 'header'\n    }, {\n        tagName: 'text',\n        selector: 'headerText'\n    }, {\n        tagName: 'text',\n        selector: 'bodyText'\n    }]\n});\n\nvar CYLINDER_TILT = 10;\n\nexport const Cylinder = Element.define('standard.Cylinder', {\n    attrs: {\n        root: {\n            cursor: 'move'\n        },\n        body: {\n            lateralArea: CYLINDER_TILT,\n            fill: '#FFFFFF',\n            stroke: '#333333',\n            strokeWidth: 2\n        },\n        top: {\n            cx: 'calc(w/2)',\n            cy: CYLINDER_TILT,\n            rx: 'calc(w/2)',\n            ry: CYLINDER_TILT,\n            fill: '#FFFFFF',\n            stroke: '#333333',\n            strokeWidth: 2\n        },\n        label: {\n            textVerticalAnchor: 'middle',\n            textAnchor: 'middle',\n            x: 'calc(w/2)',\n            y: 'calc(h+15)',\n            fontSize: 14,\n            fill: '#333333'\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'path',\n        selector: 'body'\n    }, {\n        tagName: 'ellipse',\n        selector: 'top'\n    }, {\n        tagName: 'text',\n        selector: 'label'\n    }],\n\n    topRy: function(t, opt) {\n        // getter\n        if (t === undefined) return this.attr('body/lateralArea');\n\n        // setter\n        var bodyAttrs = { lateralArea: t };\n\n        var isPercentageSetter = isPercentage(t);\n        var ty = (isPercentageSetter) ? `calc(${parseFloat(t) / 100}*h)` : t;\n        var topAttrs = { cy: ty, ry: ty };\n\n        return this.attr({ body: bodyAttrs, top: topAttrs }, opt);\n    }\n\n}, {\n    attributes: {\n        'lateral-area': {\n            set: function(t, refBBox) {\n                var isPercentageSetter = isPercentage(t);\n                if (isPercentageSetter) t = parseFloat(t) / 100;\n\n                var x = refBBox.x;\n                var y = refBBox.y;\n                var w = refBBox.width;\n                var h = refBBox.height;\n\n                // curve control point variables\n                var rx = w / 2;\n                var ry = isPercentageSetter ? (h * t) : t;\n\n                var kappa = V.KAPPA;\n                var cx = kappa * rx;\n                var cy = kappa * (isPercentageSetter ? (h * t) : t);\n\n                // shape variables\n                var xLeft = x;\n                var xCenter = x + (w / 2);\n                var xRight = x + w;\n\n                var ySideTop = y + ry;\n                var yCurveTop = ySideTop - ry;\n                var ySideBottom = y + h - ry;\n                var yCurveBottom = y + h;\n\n                // return calculated shape\n                var data = [\n                    'M', xLeft, ySideTop,\n                    'L', xLeft, ySideBottom,\n                    'C', x, (ySideBottom + cy), (xCenter - cx), yCurveBottom, xCenter, yCurveBottom,\n                    'C', (xCenter + cx), yCurveBottom, xRight, (ySideBottom + cy), xRight, ySideBottom,\n                    'L', xRight, ySideTop,\n                    'C', xRight, (ySideTop - cy), (xCenter + cx), yCurveTop, xCenter, yCurveTop,\n                    'C', (xCenter - cx), yCurveTop, xLeft, (ySideTop - cy), xLeft, ySideTop,\n                    'Z'\n                ];\n                return { d: data.join(' ') };\n            },\n            unset: 'd'\n        }\n    }\n});\n\nvar foLabelMarkup = {\n    tagName: 'foreignObject',\n    selector: 'foreignObject',\n    attributes: {\n        'overflow': 'hidden'\n    },\n    children: [{\n        tagName: 'div',\n        namespaceURI: 'http://www.w3.org/1999/xhtml',\n        selector: 'label',\n        style: {\n            width: '100%',\n            height: '100%',\n            position: 'static',\n            backgroundColor: 'transparent',\n            textAlign: 'center',\n            margin: 0,\n            padding: '0px 5px',\n            boxSizing: 'border-box',\n            display: 'flex',\n            alignItems: 'center',\n            justifyContent: 'center'\n        }\n    }]\n};\n\nvar svgLabelMarkup = {\n    tagName: 'text',\n    selector: 'label',\n    attributes: {\n        'text-anchor': 'middle'\n    }\n};\n\nvar labelMarkup = (env.test('svgforeignobject')) ? foLabelMarkup : svgLabelMarkup;\n\nexport const TextBlock = Element.define('standard.TextBlock', {\n    attrs: {\n        root: {\n            cursor: 'move'\n        },\n        body: {\n            width: 'calc(w)',\n            height: 'calc(h)',\n            stroke: '#333333',\n            fill: '#ffffff',\n            strokeWidth: 2\n        },\n        foreignObject: {\n            width: 'calc(w)',\n            height: 'calc(h)',\n        },\n        label: {\n            style: {\n                fontSize: 14\n            }\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'rect',\n        selector: 'body'\n    }, labelMarkup]\n}, {\n    attributes: {\n        text: {\n            set: function(text, refBBox, node, attrs) {\n                if (node instanceof HTMLElement) {\n                    node.textContent = text;\n                } else {\n                    // No foreign object\n                    var style = attrs['style'] || {};\n                    var wrapValue = { text, width: -5, height: '100%' };\n                    var wrapAttrs = assign({ 'text-vertical-anchor': 'middle' }, style);\n                    attributes['text-wrap'].set.call(this, wrapValue, refBBox, node, wrapAttrs);\n                    return { fill: style.color || null };\n                }\n            },\n            unset: function(node) {\n                node.textContent = '';\n                if (node instanceof SVGElement) {\n                    return 'fill';\n                }\n            },\n            position: function(text, refBBox, node) {\n                // No foreign object\n                if (node instanceof SVGElement) return refBBox.center();\n            }\n        }\n    }\n});\n\n// LINKS\n\nexport const Link = LinkBase.define('standard.Link', {\n    attrs: {\n        line: {\n            connection: true,\n            stroke: '#333333',\n            strokeWidth: 2,\n            strokeLinejoin: 'round',\n            targetMarker: {\n                'type': 'path',\n                'd': 'M 10 -5 0 0 10 5 z'\n            }\n        },\n        wrapper: {\n            connection: true,\n            strokeWidth: 10,\n            strokeLinejoin: 'round'\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'path',\n        selector: 'wrapper',\n        attributes: {\n            'fill': 'none',\n            'cursor': 'pointer',\n            'stroke': 'transparent',\n            'stroke-linecap': 'round'\n        }\n    }, {\n        tagName: 'path',\n        selector: 'line',\n        attributes: {\n            'fill': 'none',\n            'pointer-events': 'none'\n        }\n    }]\n});\n\nexport const DoubleLink = LinkBase.define('standard.DoubleLink', {\n    attrs: {\n        line: {\n            connection: true,\n            stroke: '#DDDDDD',\n            strokeWidth: 4,\n            strokeLinejoin: 'round',\n            targetMarker: {\n                type: 'path',\n                stroke: '#000000',\n                d: 'M 10 -3 10 -10 -2 0 10 10 10 3'\n            }\n        },\n        outline: {\n            connection: true,\n            stroke: '#000000',\n            strokeWidth: 6,\n            strokeLinejoin: 'round'\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'path',\n        selector: 'outline',\n        attributes: {\n            'fill': 'none',\n            'cursor': 'pointer'\n        }\n    }, {\n        tagName: 'path',\n        selector: 'line',\n        attributes: {\n            'fill': 'none',\n            'pointer-events': 'none'\n        }\n    }]\n});\n\nexport const ShadowLink = LinkBase.define('standard.ShadowLink', {\n    attrs: {\n        line: {\n            connection: true,\n            stroke: '#FF0000',\n            strokeWidth: 20,\n            strokeLinejoin: 'round',\n            targetMarker: {\n                'type': 'path',\n                'stroke': 'none',\n                'd': 'M 0 -10 -10 0 0 10 z'\n            },\n            sourceMarker: {\n                'type': 'path',\n                'stroke': 'none',\n                'd': 'M -10 -10 0 0 -10 10 0 10 0 -10 z'\n            }\n        },\n        shadow: {\n            connection: true,\n            transform: 'translate(3,6)',\n            stroke: '#000000',\n            strokeOpacity: 0.2,\n            strokeWidth: 20,\n            strokeLinejoin: 'round',\n            targetMarker: {\n                'type': 'path',\n                'd': 'M 0 -10 -10 0 0 10 z',\n                'stroke': 'none'\n            },\n            sourceMarker: {\n                'type': 'path',\n                'stroke': 'none',\n                'd': 'M -10 -10 0 0 -10 10 0 10 0 -10 z'\n            }\n        }\n    }\n}, {\n    markup: [{\n        tagName: 'path',\n        selector: 'shadow',\n        attributes: {\n            'fill': 'none',\n            'pointer-events': 'none'\n        }\n    }, {\n        tagName: 'path',\n        selector: 'line',\n        attributes: {\n            'fill': 'none',\n            'cursor': 'pointer'\n        }\n    }]\n});\n","import * as g from '../g/index.mjs';\n\nexport const Positions = {\n    TOP: 'top',\n    RIGHT: 'right',\n    BOTTOM: 'bottom',\n    LEFT: 'left',\n    TOP_LEFT: 'top-left',\n    TOP_RIGHT: 'top-right',\n    BOTTOM_LEFT: 'bottom-left',\n    BOTTOM_RIGHT: 'bottom-right',\n    CENTER: 'center',\n};\n\nexport function getRectPoint(rect, position) {\n    const r = new g.Rect(rect);\n    switch (position) {\n        case undefined:\n            throw new Error('Position required');\n\n        // Middle Points\n        case Positions.LEFT:\n        case 'leftMiddle':\n            return r.leftMiddle();\n\n        case Positions.RIGHT:\n        case 'rightMiddle':\n            return r.rightMiddle();\n\n        case Positions.TOP:\n        case 'topMiddle':\n            return r.topMiddle();\n\n        case Positions.BOTTOM:\n        case 'bottomMiddle':\n            return r.bottomMiddle();\n\n        // Corners\n        case Positions.TOP_LEFT:\n        case 'topLeft':\n        case 'origin':\n            return r.topLeft();\n\n        case Positions.TOP_RIGHT:\n        case 'topRight':\n            return r.topRight();\n\n        case Positions.BOTTOM_LEFT:\n        case 'bottomLeft':\n            return r.bottomLeft();\n\n        case Positions.BOTTOM_RIGHT:\n        case 'bottomRight':\n        case 'corner':\n            return r.bottomRight();\n\n        // Center\n        case Positions.CENTER:\n            return r.center();\n\n        // TODO: calc(), percentage etc.\n        default:\n            throw new Error(`Unknown position: ${position}`);\n    }\n}\n","import { Events } from './Events.mjs';\nimport { Model } from './Model.mjs';\nimport { extend, addMethodsUtil } from './mvcUtils.mjs';\nimport {\n    assign,\n    clone,\n    isFunction,\n    isString,\n    sortBy,\n    toArray\n} from '../util/util.mjs';\n\n\n// Collection\n// -------------------\n\n// If models tend to represent a single row of data, a Collection is\n// more analogous to a table full of data ... or a small slice or page of that\n// table, or a collection of rows that belong together for a particular reason\n// -- all of the messages in this particular folder, all of the documents\n// belonging to this particular author, and so on. Collections maintain\n// indexes of their models, both in order, and for lookup by `id`.\n\n// Create a new **Collection**, perhaps to contain a specific type of `model`.\n// If a `comparator` is specified, the Collection will maintain\n// its models in sort order, as they're added and removed.\nexport var Collection = function(models, options) {\n    options || (options = {});\n    this.preinitialize.apply(this, arguments);\n    if (options.model) this.model = options.model;\n    if (options.comparator !== void 0) this.comparator = options.comparator;\n    this._reset();\n    this.initialize.apply(this, arguments);\n    if (models) this.reset(models, assign({ silent: true }, options));\n};\n\n// Default options for `Collection#set`.\nvar setOptions = { add: true, remove: true, merge: true };\nvar addOptions = { add: true, remove: false };\n\n// Splices `insert` into `array` at index `at`.\nvar splice = function(array, insert, at) {\n    at = Math.min(Math.max(at, 0), array.length);\n    var tail = Array(array.length - at);\n    var length = insert.length;\n    var i;\n    for (i = 0; i < tail.length; i++) tail[i] = array[i + at];\n    for (i = 0; i < length; i++) array[i + at] = insert[i];\n    for (i = 0; i < tail.length; i++) array[i + length + at] = tail[i];\n};\n\n// Define the Collection's inheritable methods.\nassign(Collection.prototype, Events, {\n\n    // The default model for a collection is just a **Model**.\n    // This should be overridden in most cases.\n    model: Model,\n\n\n    // preinitialize is an empty function by default. You can override it with a function\n    // or object.  preinitialize will run before any instantiation logic is run in the Collection.\n    preinitialize: function(){},\n\n    // Initialize is an empty function by default. Override it with your own\n    // initialization logic.\n    initialize: function(){},\n\n    // The JSON representation of a Collection is an array of the\n    // models' attributes.\n    toJSON: function(options) {\n        return this.map(function(model) { return model.toJSON(options); });\n    },\n\n    // Add a model, or list of models to the set. `models` may be\n    // Models or raw JavaScript objects to be converted to Models, or any\n    // combination of the two.\n    add: function(models, options) {\n        return this.set(models, assign({ merge: false }, options, addOptions));\n    },\n\n    // Remove a model, or a list of models from the set.\n    remove: function(models, options) {\n        options = assign({}, options);\n        var singular = !Array.isArray(models);\n        models = singular ? [models] : models.slice();\n        var removed = this._removeModels(models, options);\n        if (!options.silent && removed.length) {\n            options.changes = { added: [], merged: [], removed: removed };\n            this.trigger('update', this, options);\n        }\n        return singular ? removed[0] : removed;\n    },\n\n    // Update a collection by `set`-ing a new list of models, adding new ones,\n    // removing models that are no longer present, and merging models that\n    // already exist in the collection, as necessary. Similar to **Model#set**,\n    // the core operation for updating the data contained by the collection.\n    set: function(models, options) {\n        if (models == null) return;\n\n        options = assign({}, setOptions, options);\n\n        var singular = !Array.isArray(models);\n        models = singular ? [models] : models.slice();\n\n        var at = options.at;\n        if (at != null) at = +at;\n        if (at > this.length) at = this.length;\n        if (at < 0) at += this.length + 1;\n\n        var set = [];\n        var toAdd = [];\n        var toMerge = [];\n        var toRemove = [];\n        var modelMap = {};\n\n        var add = options.add;\n        var merge = options.merge;\n        var remove = options.remove;\n\n        var sort = false;\n        var sortable = this.comparator && at == null && options.sort !== false;\n        var sortAttr = isString(this.comparator) ? this.comparator : null;\n\n        // Turn bare objects into model references, and prevent invalid models\n        // from being added.\n        var model, i;\n        for (i = 0; i < models.length; i++) {\n            model = models[i];\n\n            // If a duplicate is found, prevent it from being added and\n            // optionally merge it into the existing model.\n            var existing = this.get(model);\n            if (existing) {\n                if (merge && model !== existing) {\n                    var attrs = this._isModel(model) ? model.attributes : model;\n                    existing.set(attrs, options);\n                    toMerge.push(existing);\n                    if (sortable && !sort) sort = existing.hasChanged(sortAttr);\n                }\n                if (!modelMap[existing.cid]) {\n                    modelMap[existing.cid] = true;\n                    set.push(existing);\n                }\n                models[i] = existing;\n\n                // If this is a new, valid model, push it to the `toAdd` list.\n            } else if (add) {\n                model = models[i] = this._prepareModel(model, options);\n                if (model) {\n                    toAdd.push(model);\n                    this._addReference(model, options);\n                    modelMap[model.cid] = true;\n                    set.push(model);\n                }\n            }\n        }\n\n        // Remove stale models.\n        if (remove) {\n            for (i = 0; i < this.length; i++) {\n                model = this.models[i];\n                if (!modelMap[model.cid]) toRemove.push(model);\n            }\n            if (toRemove.length) this._removeModels(toRemove, options);\n        }\n\n        // See if sorting is needed, update `length` and splice in new models.\n        var orderChanged = false;\n        var replace = !sortable && add && remove;\n        if (set.length && replace) {\n            orderChanged = this.length !== set.length || this.models.some(function(m, index) {\n                return m !== set[index];\n            });\n            this.models.length = 0;\n            splice(this.models, set, 0);\n            this.length = this.models.length;\n        } else if (toAdd.length) {\n            if (sortable) sort = true;\n            splice(this.models, toAdd, at == null ? this.length : at);\n            this.length = this.models.length;\n        }\n\n        // Silently sort the collection if appropriate.\n        if (sort) this.sort({ silent: true });\n\n        // Unless silenced, it's time to fire all appropriate add/sort/update events.\n        if (!options.silent) {\n            for (i = 0; i < toAdd.length; i++) {\n                if (at != null) options.index = at + i;\n                model = toAdd[i];\n                model.trigger('add', model, this, options);\n            }\n            if (sort || orderChanged) this.trigger('sort', this, options);\n            if (toAdd.length || toRemove.length || toMerge.length) {\n                options.changes = {\n                    added: toAdd,\n                    removed: toRemove,\n                    merged: toMerge\n                };\n                this.trigger('update', this, options);\n            }\n        }\n\n        // Return the added (or merged) model (or models).\n        return singular ? models[0] : models;\n    },\n\n    // When you have more items than you want to add or remove individually,\n    // you can reset the entire set with a new list of models, without firing\n    // any granular `add` or `remove` events. Fires `reset` when finished.\n    // Useful for bulk operations and optimizations.\n    reset: function(models, options) {\n        options = options ? clone(options) : {};\n        for (var i = 0; i < this.models.length; i++) {\n            this._removeReference(this.models[i], options);\n        }\n        options.previousModels = this.models;\n        this._reset();\n        models = this.add(models, assign({ silent: true }, options));\n        if (!options.silent) this.trigger('reset', this, options);\n        return models;\n    },\n\n    // Add a model to the end of the collection.\n    push: function(model, options) {\n        return this.add(model, assign({ at: this.length }, options));\n    },\n\n    // Remove a model from the end of the collection.\n    pop: function(options) {\n        var model = this.at(this.length - 1);\n        return this.remove(model, options);\n    },\n\n    // Add a model to the beginning of the collection.\n    unshift: function(model, options) {\n        return this.add(model, assign({ at: 0 }, options));\n    },\n\n    // Remove a model from the beginning of the collection.\n    shift: function(options) {\n        var model = this.at(0);\n        return this.remove(model, options);\n    },\n\n    // Slice out a sub-array of models from the collection.\n    slice: function() {\n        return Array.prototype.slice.apply(this.models, arguments);\n    },\n\n    // Get a model from the set by id, cid, model object with id or cid\n    // properties, or an attributes object that is transformed through modelId.\n    get: function(obj) {\n        if (obj == null) return void 0;\n        return this._byId[obj] ||\n        this._byId[this.modelId(this._isModel(obj) ? obj.attributes : obj, obj.idAttribute)] ||\n        obj.cid && this._byId[obj.cid];\n    },\n\n    // Returns `true` if the model is in the collection.\n    has: function(obj) {\n        return this.get(obj) != null;\n    },\n\n    // Get the model at the given index.\n    at: function(index) {\n        if (index < 0) index += this.length;\n        return this.models[index];\n    },\n\n    // Force the collection to re-sort itself. You don't need to call this under\n    // normal circumstances, as the set will maintain sort order as each item\n    // is added.\n    sort: function(options) {\n        var comparator = this.comparator;\n        if (!comparator) throw new Error('Cannot sort a set without a comparator');\n        options || (options = {});\n\n        var length = comparator.length;\n        if (isFunction(comparator)) comparator = comparator.bind(this);\n\n        // Run sort based on type of `comparator`.\n        if (length === 1 || isString(comparator)) {\n            this.models = this.sortBy(comparator);\n        } else {\n            this.models.sort(comparator);\n        }\n        if (!options.silent) this.trigger('sort', this, options);\n        return this;\n    },\n\n    // Create a new collection with an identical list of models as this one.\n    clone: function() {\n        return new this.constructor(this.models, {\n            model: this.model,\n            comparator: this.comparator\n        });\n    },\n\n    // Define how to uniquely identify models in the collection.\n    modelId: function(attrs, idAttribute) {\n        return attrs[idAttribute || this.model.prototype.idAttribute || 'id'];\n    },\n\n    // Get an iterator of all models in this collection.\n    values: function() {\n        return new CollectionIterator(this, ITERATOR_VALUES);\n    },\n\n    // Get an iterator of all model IDs in this collection.\n    keys: function() {\n        return new CollectionIterator(this, ITERATOR_KEYS);\n    },\n\n    // Get an iterator of all [ID, model] tuples in this collection.\n    entries: function() {\n        return new CollectionIterator(this, ITERATOR_KEYSVALUES);\n    },\n\n    // Iterate over elements of the collection, and invoke fn for each element\n    each: function(fn, context) {\n        this.models.forEach(fn, context);\n    },\n\n    // Iterate over elements of collection, and return an array of all elements fn returns truthy for\n    filter: function(fn, context) {\n        return this.models.filter(fn, context);\n    },\n\n    find: function(fn, context) {\n        return this.models.find(fn, context);\n    },\n\n    findIndex: function(fn, context) {\n        return this.models.findIndex(fn, context);\n    },\n\n    // Return the first model of the collection\n    first: function() {\n        return this.models[0];\n    },\n\n    // Return true if value is in the collection\n    includes: function(value) {\n        return this.models.includes(value);\n    },\n\n    // Return the last model of the collection\n    last: function() {\n        return this.models[this.models.length - 1];\n    },\n\n    // Return true if collection has no elements\n    isEmpty: function() {\n        return !this.models.length;\n    },\n\n    // Create an array of values by running each element in the collection through fn\n    map: function(fn, context) {\n        return this.models.map(fn, context);\n    },\n\n    // Runs \"reducer\" fn over all elements in the collection, in ascending-index order, and accumulates them into a single value\n    reduce: function(fn, initAcc = this.first()) {\n        return this.models.reduce(fn, initAcc);\n    },\n\n    // Private method to reset all internal state. Called when the collection\n    // is first initialized or reset.\n    _reset: function() {\n        this.length = 0;\n        this.models = [];\n        this._byId  = {};\n    },\n\n    // Prepare a hash of attributes (or other model) to be added to this\n    // collection.\n    _prepareModel: function(attrs, options) {\n        if (this._isModel(attrs)) {\n            if (!attrs.collection) attrs.collection = this;\n            return attrs;\n        }\n        options = options ? clone(options) : {};\n        options.collection = this;\n\n        var model;\n        if (this.model.prototype) {\n            model = new this.model(attrs, options);\n        } else {\n        // ES class methods didn't have prototype\n            model = this.model(attrs, options);\n        }\n\n        if (!model.validationError) return model;\n        this.trigger('invalid', this, model.validationError, options);\n        return false;\n    },\n\n    // Internal method called by both remove and set.\n    _removeModels: function(models, options) {\n        var removed = [];\n        for (var i = 0; i < models.length; i++) {\n            var model = this.get(models[i]);\n            if (!model) continue;\n\n            var index = this.models.indexOf(model);\n            this.models.splice(index, 1);\n            this.length--;\n\n            // Remove references before triggering 'remove' event to prevent an\n            // infinite loop. #3693\n            delete this._byId[model.cid];\n            var id = this.modelId(model.attributes, model.idAttribute);\n            if (id != null) delete this._byId[id];\n\n            if (!options.silent) {\n                options.index = index;\n                model.trigger('remove', model, this, options);\n            }\n\n            removed.push(model);\n            this._removeReference(model, options);\n        }\n        if (models.length > 0 && !options.silent) delete options.index;\n        return removed;\n    },\n\n    // Method for checking whether an object should be considered a model for\n    // the purposes of adding to the collection.\n    _isModel: function(model) {\n        return model instanceof Model;\n    },\n\n    // Internal method to create a model's ties to a collection.\n    _addReference: function(model, options) {\n        this._byId[model.cid] = model;\n        var id = this.modelId(model.attributes, model.idAttribute);\n        if (id != null) this._byId[id] = model;\n        model.on('all', this._onModelEvent, this);\n    },\n\n    // Internal method to sever a model's ties to a collection.\n    _removeReference: function(model, options) {\n        delete this._byId[model.cid];\n        var id = this.modelId(model.attributes, model.idAttribute);\n        if (id != null) delete this._byId[id];\n        if (this === model.collection) delete model.collection;\n        model.off('all', this._onModelEvent, this);\n    },\n\n    // Internal method called every time a model in the set fires an event.\n    // Sets need to update their indexes when models change ids. All other\n    // events simply proxy through. \"add\" and \"remove\" events that originate\n    // in other collections are ignored.\n    _onModelEvent: function(event, model, collection, options) {\n        if (model) {\n            if ((event === 'add' || event === 'remove') && collection !== this) return;\n            if (event === 'changeId') {\n                var prevId = this.modelId(model.previousAttributes(), model.idAttribute);\n                var id = this.modelId(model.attributes, model.idAttribute);\n                if (prevId != null) delete this._byId[prevId];\n                if (id != null) this._byId[id] = model;\n            }\n        }\n        this.trigger.apply(this, arguments);\n    }\n\n});\n\n// Defining an @@iterator method implements JavaScript's Iterable protocol.\n// In modern ES2015 browsers, this value is found at Symbol.iterator.\nvar $$iterator = typeof Symbol === 'function' && Symbol.iterator;\nif ($$iterator) {\n    Collection.prototype[$$iterator] = Collection.prototype.values;\n}\n\n// CollectionIterator\n// ------------------\n\n// A CollectionIterator implements JavaScript's Iterator protocol, allowing the\n// use of `for of` loops in modern browsers and interoperation between\n// Collection and other JavaScript functions and third-party libraries\n// which can operate on Iterables.\nvar CollectionIterator = function(collection, kind) {\n    this._collection = collection;\n    this._kind = kind;\n    this._index = 0;\n};\n\n// This \"enum\" defines the three possible kinds of values which can be emitted\n// by a CollectionIterator that correspond to the values(), keys() and entries()\n// methods on Collection, respectively.\nvar ITERATOR_VALUES = 1;\nvar ITERATOR_KEYS = 2;\nvar ITERATOR_KEYSVALUES = 3;\n\n// All Iterators should themselves be Iterable.\nif ($$iterator) {\n    CollectionIterator.prototype[$$iterator] = function() {\n        return this;\n    };\n}\n\nCollectionIterator.prototype.next = function() {\n    if (this._collection) {\n\n        // Only continue iterating if the iterated collection is long enough.\n        if (this._index < this._collection.length) {\n            var model = this._collection.at(this._index);\n            this._index++;\n\n            // Construct a value depending on what kind of values should be iterated.\n            var value;\n            if (this._kind === ITERATOR_VALUES) {\n                value = model;\n            } else {\n                var id = this._collection.modelId(model.attributes, model.idAttribute);\n                if (this._kind === ITERATOR_KEYS) {\n                    value = id;\n                } else { // ITERATOR_KEYSVALUES\n                    value = [id, model];\n                }\n            }\n            return { value: value, done: false };\n        }\n\n        // Once exhausted, remove the reference to the collection so future\n        // calls to the next method always return done.\n        this._collection = void 0;\n    }\n\n    return { value: void 0, done: true };\n};\n\n//  Methods that we want to implement on the Collection.\nvar collectionMethods = { toArray: 1, sortBy: 3 };\n\n\n// Mix in each method as a proxy to `Collection#models`.\n\nvar config = [ Collection, collectionMethods, 'models' ];\n\nfunction addMethods(config) {\n    var Base = config[0],\n        methods = config[1],\n        attribute = config[2];\n\n    const methodsToAdd = {\n        sortBy,\n        toArray\n    };\n\n    addMethodsUtil(Base, methodsToAdd, methods, attribute);\n}\n\naddMethods(config);\n\n// Set up inheritance for the collection.\nCollection.extend = extend;\n","import { Cell } from '../dia/Cell.mjs';\nimport { isFunction, isString, toArray } from './util.mjs';\n\nexport const wrapWith = function(object, methods, wrapper) {\n\n    if (isString(wrapper)) {\n\n        if (!wrappers[wrapper]) {\n            throw new Error('Unknown wrapper: \"' + wrapper + '\"');\n        }\n\n        wrapper = wrappers[wrapper];\n    }\n\n    if (!isFunction(wrapper)) {\n        throw new Error('Wrapper must be a function.');\n    }\n\n    toArray(methods).forEach(function(method) {\n        object[method] = wrapper(object[method]);\n    });\n};\n\nexport const wrappers = {\n\n    cells: function(fn) {\n\n        return function() {\n\n            var args = Array.from(arguments);\n            var n = args.length;\n            var cells = n > 0 && args[0] || [];\n            var opt = n > 1 && args[n - 1] || {};\n\n            if (!Array.isArray(cells)) {\n\n                if (opt instanceof Cell) {\n                    cells = args;\n                } else if (cells instanceof Cell) {\n                    if (args.length > 1) {\n                        args.pop();\n                    }\n                    cells = args;\n                }\n            }\n\n            if (opt instanceof Cell) {\n                opt = {};\n            }\n\n            return fn.call(this, cells, opt);\n        };\n    }\n\n};\n\n","import * as util from '../util/index.mjs';\nimport * as g from '../g/index.mjs';\n\nimport { Model } from '../mvc/Model.mjs';\nimport { Collection } from '../mvc/Collection.mjs';\nimport { wrappers, wrapWith } from '../util/wrappers.mjs';\nimport { cloneCells } from '../util/index.mjs';\n\nconst GraphCells = Collection.extend({\n\n    initialize: function(models, opt) {\n\n        // Set the optional namespace where all model classes are defined.\n        if (opt.cellNamespace) {\n            this.cellNamespace = opt.cellNamespace;\n        } else {\n            /* eslint-disable no-undef */\n            this.cellNamespace = typeof joint !== 'undefined' && util.has(joint, 'shapes') ? joint.shapes : null;\n            /* eslint-enable no-undef */\n        }\n\n\n        this.graph = opt.graph;\n    },\n\n    model: function(attrs, opt) {\n\n        const collection = opt.collection;\n        const namespace = collection.cellNamespace;\n        const { type } = attrs;\n\n        // Find the model class based on the `type` attribute in the cell namespace\n        const ModelClass = util.getByPath(namespace, type, '.');\n        if (!ModelClass) {\n            throw new Error(`dia.Graph: Could not find cell constructor for type: '${type}'. Make sure to add the constructor to 'cellNamespace'.`);\n        }\n\n        return new ModelClass(attrs, opt);\n    },\n\n    _addReference: function(model, options) {\n        Collection.prototype._addReference.apply(this, arguments);\n        // If not in `dry` mode and the model does not have a graph reference yet,\n        // set the reference.\n        if (!options.dry && !model.graph) {\n            model.graph = this.graph;\n        }\n    },\n\n    _removeReference: function(model, options) {\n        Collection.prototype._removeReference.apply(this, arguments);\n        // If not in `dry` mode and the model has a reference to this exact graph,\n        // remove the reference.\n        if (!options.dry && model.graph === this.graph) {\n            model.graph = null;\n        }\n    },\n\n    // `comparator` makes it easy to sort cells based on their `z` index.\n    comparator: function(model) {\n\n        return model.get('z') || 0;\n    }\n});\n\n\nexport const Graph = Model.extend({\n\n    initialize: function(attrs, opt) {\n\n        opt = opt || {};\n\n        // Passing `cellModel` function in the options object to graph allows for\n        // setting models based on attribute objects. This is especially handy\n        // when processing JSON graphs that are in a different than JointJS format.\n        var cells = new GraphCells([], {\n            model: opt.cellModel,\n            cellNamespace: opt.cellNamespace,\n            graph: this\n        });\n        Model.prototype.set.call(this, 'cells', cells);\n\n        // Make all the events fired in the `cells` collection available.\n        // to the outside world.\n        cells.on('all', this.trigger, this);\n\n        // JointJS automatically doesn't trigger re-sort if models attributes are changed later when\n        // they're already in the collection. Therefore, we're triggering sort manually here.\n        this.on('change:z', this._sortOnChangeZ, this);\n\n        // `joint.dia.Graph` keeps an internal data structure (an adjacency list)\n        // for fast graph queries. All changes that affect the structure of the graph\n        // must be reflected in the `al` object. This object provides fast answers to\n        // questions such as \"what are the neighbours of this node\" or \"what\n        // are the sibling links of this link\".\n\n        // Outgoing edges per node. Note that we use a hash-table for the list\n        // of outgoing edges for a faster lookup.\n        // [nodeId] -> Object [edgeId] -> true\n        this._out = {};\n        // Ingoing edges per node.\n        // [nodeId] -> Object [edgeId] -> true\n        this._in = {};\n        // `_nodes` is useful for quick lookup of all the elements in the graph, without\n        // having to go through the whole cells array.\n        // [node ID] -> true\n        this._nodes = {};\n        // `_edges` is useful for quick lookup of all the links in the graph, without\n        // having to go through the whole cells array.\n        // [edgeId] -> true\n        this._edges = {};\n\n        this._batches = {};\n\n        cells.on('add', this._restructureOnAdd, this);\n        cells.on('remove', this._restructureOnRemove, this);\n        cells.on('reset', this._restructureOnReset, this);\n        cells.on('change:source', this._restructureOnChangeSource, this);\n        cells.on('change:target', this._restructureOnChangeTarget, this);\n        cells.on('remove', this._removeCell, this);\n    },\n\n    _sortOnChangeZ: function() {\n\n        this.get('cells').sort();\n    },\n\n    _restructureOnAdd: function(cell) {\n\n        if (cell.isLink()) {\n            this._edges[cell.id] = true;\n            var { source, target } = cell.attributes;\n            if (source.id) {\n                (this._out[source.id] || (this._out[source.id] = {}))[cell.id] = true;\n            }\n            if (target.id) {\n                (this._in[target.id] || (this._in[target.id] = {}))[cell.id] = true;\n            }\n        } else {\n            this._nodes[cell.id] = true;\n        }\n    },\n\n    _restructureOnRemove: function(cell) {\n\n        if (cell.isLink()) {\n            delete this._edges[cell.id];\n            var { source, target } = cell.attributes;\n            if (source.id && this._out[source.id] && this._out[source.id][cell.id]) {\n                delete this._out[source.id][cell.id];\n            }\n            if (target.id && this._in[target.id] && this._in[target.id][cell.id]) {\n                delete this._in[target.id][cell.id];\n            }\n        } else {\n            delete this._nodes[cell.id];\n        }\n    },\n\n    _restructureOnReset: function(cells) {\n\n        // Normalize into an array of cells. The original `cells` is GraphCells mvc collection.\n        cells = cells.models;\n\n        this._out = {};\n        this._in = {};\n        this._nodes = {};\n        this._edges = {};\n\n        cells.forEach(this._restructureOnAdd, this);\n    },\n\n    _restructureOnChangeSource: function(link) {\n\n        var prevSource = link.previous('source');\n        if (prevSource.id && this._out[prevSource.id]) {\n            delete this._out[prevSource.id][link.id];\n        }\n        var source = link.attributes.source;\n        if (source.id) {\n            (this._out[source.id] || (this._out[source.id] = {}))[link.id] = true;\n        }\n    },\n\n    _restructureOnChangeTarget: function(link) {\n\n        var prevTarget = link.previous('target');\n        if (prevTarget.id && this._in[prevTarget.id]) {\n            delete this._in[prevTarget.id][link.id];\n        }\n        var target = link.get('target');\n        if (target.id) {\n            (this._in[target.id] || (this._in[target.id] = {}))[link.id] = true;\n        }\n    },\n\n    // Return all outbound edges for the node. Return value is an object\n    // of the form: [edgeId] -> true\n    getOutboundEdges: function(node) {\n\n        return (this._out && this._out[node]) || {};\n    },\n\n    // Return all inbound edges for the node. Return value is an object\n    // of the form: [edgeId] -> true\n    getInboundEdges: function(node) {\n\n        return (this._in && this._in[node]) || {};\n    },\n\n    toJSON: function(opt = {}) {\n\n        // JointJS does not recursively call `toJSON()` on attributes that are themselves models/collections.\n        // It just clones the attributes. Therefore, we must call `toJSON()` on the cells collection explicitly.\n        var json = Model.prototype.toJSON.apply(this, arguments);\n        json.cells = this.get('cells').toJSON(opt.cellAttributes);\n        return json;\n    },\n\n    fromJSON: function(json, opt) {\n\n        if (!json.cells) {\n\n            throw new Error('Graph JSON must contain cells array.');\n        }\n\n        return this.set(json, opt);\n    },\n\n    set: function(key, val, opt) {\n\n        var attrs;\n\n        // Handle both `key`, value and {key: value} style arguments.\n        if (typeof key === 'object') {\n            attrs = key;\n            opt = val;\n        } else {\n            (attrs = {})[key] = val;\n        }\n\n        // Make sure that `cells` attribute is handled separately via resetCells().\n        if (attrs.hasOwnProperty('cells')) {\n            this.resetCells(attrs.cells, opt);\n            attrs = util.omit(attrs, 'cells');\n        }\n\n        // The rest of the attributes are applied via original set method.\n        return Model.prototype.set.call(this, attrs, opt);\n    },\n\n    clear: function(opt) {\n\n        opt = util.assign({}, opt, { clear: true });\n\n        var collection = this.get('cells');\n\n        if (collection.length === 0) return this;\n\n        this.startBatch('clear', opt);\n\n        // The elements come after the links.\n        var cells = collection.sortBy(function(cell) {\n            return cell.isLink() ? 1 : 2;\n        });\n\n        do {\n\n            // Remove all the cells one by one.\n            // Note that all the links are removed first, so it's\n            // safe to remove the elements without removing the connected\n            // links first.\n            cells.shift().remove(opt);\n\n        } while (cells.length > 0);\n\n        this.stopBatch('clear');\n\n        return this;\n    },\n\n    _prepareCell: function(cell) {\n\n        let attrs;\n        if (cell instanceof Model) {\n            attrs = cell.attributes;\n        } else {\n            attrs = cell;\n        }\n\n        if (!util.isString(attrs.type)) {\n            throw new TypeError('dia.Graph: cell type must be a string.');\n        }\n\n        return cell;\n    },\n\n    minZIndex: function() {\n\n        var firstCell = this.get('cells').first();\n        return firstCell ? (firstCell.get('z') || 0) : 0;\n    },\n\n    maxZIndex: function() {\n\n        var lastCell = this.get('cells').last();\n        return lastCell ? (lastCell.get('z') || 0) : 0;\n    },\n\n    addCell: function(cell, opt) {\n\n        if (Array.isArray(cell)) {\n\n            return this.addCells(cell, opt);\n        }\n\n        if (cell instanceof Model) {\n\n            if (!cell.has('z')) {\n                cell.set('z', this.maxZIndex() + 1);\n            }\n\n        } else if (cell.z === undefined) {\n\n            cell.z = this.maxZIndex() + 1;\n        }\n\n        this.get('cells').add(this._prepareCell(cell, opt), opt || {});\n\n        return this;\n    },\n\n    addCells: function(cells, opt) {\n\n        if (cells.length === 0) return this;\n\n        cells = util.flattenDeep(cells);\n        opt.maxPosition = opt.position = cells.length - 1;\n\n        this.startBatch('add', opt);\n        cells.forEach(function(cell) {\n            this.addCell(cell, opt);\n            opt.position--;\n        }, this);\n        this.stopBatch('add', opt);\n\n        return this;\n    },\n\n    // When adding a lot of cells, it is much more efficient to\n    // reset the entire cells collection in one go.\n    // Useful for bulk operations and optimizations.\n    resetCells: function(cells, opt) {\n\n        var preparedCells = util.toArray(cells).map(function(cell) {\n            return this._prepareCell(cell, opt);\n        }, this);\n        this.get('cells').reset(preparedCells, opt);\n\n        return this;\n    },\n\n    removeCells: function(cells, opt) {\n\n        if (cells.length) {\n\n            this.startBatch('remove');\n            util.invoke(cells, 'remove', opt);\n            this.stopBatch('remove');\n        }\n\n        return this;\n    },\n\n    _removeCell: function(cell, collection, options) {\n\n        options = options || {};\n\n        if (!options.clear) {\n            // Applications might provide a `disconnectLinks` option set to `true` in order to\n            // disconnect links when a cell is removed rather then removing them. The default\n            // is to remove all the associated links.\n            if (options.disconnectLinks) {\n\n                this.disconnectLinks(cell, options);\n\n            } else {\n\n                this.removeLinks(cell, options);\n            }\n        }\n        // Silently remove the cell from the cells collection. Silently, because\n        // `joint.dia.Cell.prototype.remove` already triggers the `remove` event which is\n        // then propagated to the graph model. If we didn't remove the cell silently, two `remove` events\n        // would be triggered on the graph model.\n        this.get('cells').remove(cell, { silent: true });\n    },\n\n    transferCellEmbeds: function(sourceCell, targetCell, opt = {}) {\n\n        const batchName = 'transfer-embeds';\n        this.startBatch(batchName);\n\n        // Embed children of the source cell in the target cell.\n        const children = sourceCell.getEmbeddedCells();\n        targetCell.embed(children, { ...opt, reparent: true });\n\n        this.stopBatch(batchName);\n    },\n\n    transferCellConnectedLinks: function(sourceCell, targetCell, opt = {}) {\n\n        const batchName = 'transfer-connected-links';\n        this.startBatch(batchName);\n\n        // Reconnect all the links connected to the old cell to the new cell.\n        const connectedLinks = this.getConnectedLinks(sourceCell, opt);\n        connectedLinks.forEach((link) => {\n\n            if (link.getSourceCell() === sourceCell) {\n                link.prop(['source', 'id'], targetCell.id, opt);\n            }\n\n            if (link.getTargetCell() === sourceCell) {\n                link.prop(['target', 'id'], targetCell.id, opt);\n            }\n        });\n\n        this.stopBatch(batchName);\n    },\n\n    // Get a cell by `id`.\n    getCell: function(id) {\n\n        return this.get('cells').get(id);\n    },\n\n    getCells: function() {\n\n        return this.get('cells').toArray();\n    },\n\n    getElements: function() {\n\n        return this.get('cells').toArray().filter(cell => cell.isElement());\n    },\n\n    getLinks: function() {\n\n        return this.get('cells').toArray().filter(cell => cell.isLink());\n    },\n\n    getFirstCell: function() {\n\n        return this.get('cells').first();\n    },\n\n    getLastCell: function() {\n\n        return this.get('cells').last();\n    },\n\n    // Get all inbound and outbound links connected to the cell `model`.\n    getConnectedLinks: function(model, opt) {\n\n        opt = opt || {};\n\n        var indirect = opt.indirect;\n        var inbound = opt.inbound;\n        var outbound = opt.outbound;\n        if ((inbound === undefined) && (outbound === undefined)) {\n            inbound = outbound = true;\n        }\n\n        // the final array of connected link models\n        var links = [];\n        // a hash table of connected edges of the form: [edgeId] -> true\n        // used for quick lookups to check if we already added a link\n        var edges = {};\n\n        if (outbound) {\n            addOutbounds(this, model);\n        }\n        if (inbound) {\n            addInbounds(this, model);\n        }\n\n        function addOutbounds(graph, model) {\n            util.forIn(graph.getOutboundEdges(model.id), function(_, edge) {\n                // skip links that were already added\n                // (those must be self-loop links)\n                // (because they are inbound and outbound edges of the same two elements)\n                if (edges[edge]) return;\n                var link = graph.getCell(edge);\n                links.push(link);\n                edges[edge] = true;\n                if (indirect) {\n                    if (inbound) addInbounds(graph, link);\n                    if (outbound) addOutbounds(graph, link);\n                }\n            }.bind(graph));\n            if (indirect && model.isLink()) {\n                var outCell = model.getTargetCell();\n                if (outCell && outCell.isLink()) {\n                    if (!edges[outCell.id]) {\n                        links.push(outCell);\n                        addOutbounds(graph, outCell);\n                    }\n                }\n            }\n        }\n\n        function addInbounds(graph, model) {\n            util.forIn(graph.getInboundEdges(model.id), function(_, edge) {\n                // skip links that were already added\n                // (those must be self-loop links)\n                // (because they are inbound and outbound edges of the same two elements)\n                if (edges[edge]) return;\n                var link = graph.getCell(edge);\n                links.push(link);\n                edges[edge] = true;\n                if (indirect) {\n                    if (inbound) addInbounds(graph, link);\n                    if (outbound) addOutbounds(graph, link);\n                }\n            }.bind(graph));\n            if (indirect && model.isLink()) {\n                var inCell = model.getSourceCell();\n                if (inCell && inCell.isLink()) {\n                    if (!edges[inCell.id]) {\n                        links.push(inCell);\n                        addInbounds(graph, inCell);\n                    }\n                }\n            }\n        }\n\n        // if `deep` option is `true`, check also all the links that are connected to any of the descendant cells\n        if (opt.deep) {\n\n            var embeddedCells = model.getEmbeddedCells({ deep: true });\n\n            // in the first round, we collect all the embedded elements\n            var embeddedElements = {};\n            embeddedCells.forEach(function(cell) {\n                if (cell.isElement()) {\n                    embeddedElements[cell.id] = true;\n                }\n            });\n\n            embeddedCells.forEach(function(cell) {\n                if (cell.isLink()) return;\n                if (outbound) {\n                    util.forIn(this.getOutboundEdges(cell.id), function(exists, edge) {\n                        if (!edges[edge]) {\n                            var edgeCell = this.getCell(edge);\n                            var { source, target } = edgeCell.attributes;\n                            var sourceId = source.id;\n                            var targetId = target.id;\n\n                            // if `includeEnclosed` option is falsy, skip enclosed links\n                            if (!opt.includeEnclosed\n                                && (sourceId && embeddedElements[sourceId])\n                                && (targetId && embeddedElements[targetId])) {\n                                return;\n                            }\n\n                            links.push(this.getCell(edge));\n                            edges[edge] = true;\n                        }\n                    }.bind(this));\n                }\n                if (inbound) {\n                    util.forIn(this.getInboundEdges(cell.id), function(exists, edge) {\n                        if (!edges[edge]) {\n                            var edgeCell = this.getCell(edge);\n                            var { source, target } = edgeCell.attributes;\n                            var sourceId = source.id;\n                            var targetId = target.id;\n\n                            // if `includeEnclosed` option is falsy, skip enclosed links\n                            if (!opt.includeEnclosed\n                                && (sourceId && embeddedElements[sourceId])\n                                && (targetId && embeddedElements[targetId])) {\n                                return;\n                            }\n\n                            links.push(this.getCell(edge));\n                            edges[edge] = true;\n                        }\n                    }.bind(this));\n                }\n            }, this);\n        }\n\n        return links;\n    },\n\n    getNeighbors: function(model, opt) {\n\n        opt || (opt = {});\n\n        var inbound = opt.inbound;\n        var outbound = opt.outbound;\n        if (inbound === undefined && outbound === undefined) {\n            inbound = outbound = true;\n        }\n\n        var neighbors = this.getConnectedLinks(model, opt).reduce(function(res, link) {\n\n            var { source, target } = link.attributes;\n            var loop = link.hasLoop(opt);\n\n            // Discard if it is a point, or if the neighbor was already added.\n            if (inbound && util.has(source, 'id') && !res[source.id]) {\n\n                var sourceElement = this.getCell(source.id);\n                if (sourceElement.isElement()) {\n                    if (loop || (sourceElement && sourceElement !== model && (!opt.deep || !sourceElement.isEmbeddedIn(model)))) {\n                        res[source.id] = sourceElement;\n                    }\n                }\n            }\n\n            // Discard if it is a point, or if the neighbor was already added.\n            if (outbound && util.has(target, 'id') && !res[target.id]) {\n\n                var targetElement = this.getCell(target.id);\n                if (targetElement.isElement()) {\n                    if (loop || (targetElement && targetElement !== model && (!opt.deep || !targetElement.isEmbeddedIn(model)))) {\n                        res[target.id] = targetElement;\n                    }\n                }\n            }\n\n            return res;\n        }.bind(this), {});\n\n        if (model.isLink()) {\n            if (inbound) {\n                var sourceCell = model.getSourceCell();\n                if (sourceCell && sourceCell.isElement() && !neighbors[sourceCell.id]) {\n                    neighbors[sourceCell.id] = sourceCell;\n                }\n            }\n            if (outbound) {\n                var targetCell = model.getTargetCell();\n                if (targetCell && targetCell.isElement() && !neighbors[targetCell.id]) {\n                    neighbors[targetCell.id] = targetCell;\n                }\n            }\n        }\n\n        return util.toArray(neighbors);\n    },\n\n    getCommonAncestor: function(/* cells */) {\n\n        var cellsAncestors = Array.from(arguments).map(function(cell) {\n\n            var ancestors = [];\n            var parentId = cell.get('parent');\n\n            while (parentId) {\n\n                ancestors.push(parentId);\n                parentId = this.getCell(parentId).get('parent');\n            }\n\n            return ancestors;\n\n        }, this);\n\n        cellsAncestors = cellsAncestors.sort(function(a, b) {\n            return a.length - b.length;\n        });\n\n        var commonAncestor = util.toArray(cellsAncestors.shift()).find(function(ancestor) {\n            return cellsAncestors.every(function(cellAncestors) {\n                return cellAncestors.includes(ancestor);\n            });\n        });\n\n        return this.getCell(commonAncestor);\n    },\n\n    // Find the whole branch starting at `element`.\n    // If `opt.deep` is `true`, take into account embedded elements too.\n    // If `opt.breadthFirst` is `true`, use the Breadth-first search algorithm, otherwise use Depth-first search.\n    getSuccessors: function(element, opt) {\n\n        opt = opt || {};\n        var res = [];\n        // Modify the options so that it includes the `outbound` neighbors only. In other words, search forwards.\n        this.search(element, function(el) {\n            if (el !== element) {\n                res.push(el);\n            }\n        }, util.assign({}, opt, { outbound: true }));\n        return res;\n    },\n\n    cloneCells: cloneCells,\n    // Clone the whole subgraph (including all the connected links whose source/target is in the subgraph).\n    // If `opt.deep` is `true`, also take into account all the embedded cells of all the subgraph cells.\n    // Return a map of the form: [original cell ID] -> [clone].\n    cloneSubgraph: function(cells, opt) {\n\n        var subgraph = this.getSubgraph(cells, opt);\n        return this.cloneCells(subgraph);\n    },\n\n    // Return `cells` and all the connected links that connect cells in the `cells` array.\n    // If `opt.deep` is `true`, return all the cells including all their embedded cells\n    // and all the links that connect any of the returned cells.\n    // For example, for a single shallow element, the result is that very same element.\n    // For two elements connected with a link: `A --- L ---> B`, the result for\n    // `getSubgraph([A, B])` is `[A, L, B]`. The same goes for `getSubgraph([L])`, the result is again `[A, L, B]`.\n    getSubgraph: function(cells, opt) {\n\n        opt = opt || {};\n\n        var subgraph = [];\n        // `cellMap` is used for a quick lookup of existence of a cell in the `cells` array.\n        var cellMap = {};\n        var elements = [];\n        var links = [];\n\n        util.toArray(cells).forEach(function(cell) {\n            if (!cellMap[cell.id]) {\n                subgraph.push(cell);\n                cellMap[cell.id] = cell;\n                if (cell.isLink()) {\n                    links.push(cell);\n                } else {\n                    elements.push(cell);\n                }\n            }\n\n            if (opt.deep) {\n                var embeds = cell.getEmbeddedCells({ deep: true });\n                embeds.forEach(function(embed) {\n                    if (!cellMap[embed.id]) {\n                        subgraph.push(embed);\n                        cellMap[embed.id] = embed;\n                        if (embed.isLink()) {\n                            links.push(embed);\n                        } else {\n                            elements.push(embed);\n                        }\n                    }\n                });\n            }\n        });\n\n        links.forEach(function(link) {\n            // For links, return their source & target (if they are elements - not points).\n            var { source, target } = link.attributes;\n            if (source.id && !cellMap[source.id]) {\n                var sourceElement = this.getCell(source.id);\n                subgraph.push(sourceElement);\n                cellMap[sourceElement.id] = sourceElement;\n                elements.push(sourceElement);\n            }\n            if (target.id && !cellMap[target.id]) {\n                var targetElement = this.getCell(target.id);\n                subgraph.push(this.getCell(target.id));\n                cellMap[targetElement.id] = targetElement;\n                elements.push(targetElement);\n            }\n        }, this);\n\n        elements.forEach(function(element) {\n            // For elements, include their connected links if their source/target is in the subgraph;\n            var links = this.getConnectedLinks(element, opt);\n            links.forEach(function(link) {\n                var { source, target } = link.attributes;\n                if (!cellMap[link.id] && source.id && cellMap[source.id] && target.id && cellMap[target.id]) {\n                    subgraph.push(link);\n                    cellMap[link.id] = link;\n                }\n            });\n        }, this);\n\n        return subgraph;\n    },\n\n    // Find all the predecessors of `element`. This is a reverse operation of `getSuccessors()`.\n    // If `opt.deep` is `true`, take into account embedded elements too.\n    // If `opt.breadthFirst` is `true`, use the Breadth-first search algorithm, otherwise use Depth-first search.\n    getPredecessors: function(element, opt) {\n\n        opt = opt || {};\n        var res = [];\n        // Modify the options so that it includes the `inbound` neighbors only. In other words, search backwards.\n        this.search(element, function(el) {\n            if (el !== element) {\n                res.push(el);\n            }\n        }, util.assign({}, opt, { inbound: true }));\n        return res;\n    },\n\n    // Perform search on the graph.\n    // If `opt.breadthFirst` is `true`, use the Breadth-first Search algorithm, otherwise use Depth-first search.\n    // By setting `opt.inbound` to `true`, you can reverse the direction of the search.\n    // If `opt.deep` is `true`, take into account embedded elements too.\n    // `iteratee` is a function of the form `function(element) {}`.\n    // If `iteratee` explicitly returns `false`, the searching stops.\n    search: function(element, iteratee, opt) {\n\n        opt = opt || {};\n        if (opt.breadthFirst) {\n            this.bfs(element, iteratee, opt);\n        } else {\n            this.dfs(element, iteratee, opt);\n        }\n    },\n\n    // Breadth-first search.\n    // If `opt.deep` is `true`, take into account embedded elements too.\n    // If `opt.inbound` is `true`, reverse the search direction (it's like reversing all the link directions).\n    // `iteratee` is a function of the form `function(element, distance) {}`.\n    // where `element` is the currently visited element and `distance` is the distance of that element\n    // from the root `element` passed the `bfs()`, i.e. the element we started the search from.\n    // Note that the `distance` is not the shortest or longest distance, it is simply the number of levels\n    // crossed till we visited the `element` for the first time. It is especially useful for tree graphs.\n    // If `iteratee` explicitly returns `false`, the searching stops.\n    bfs: function(element, iteratee, opt = {}) {\n\n        const visited = {};\n        const distance = {};\n        const queue = [];\n\n        queue.push(element);\n        distance[element.id] = 0;\n\n        while (queue.length > 0) {\n            var next = queue.shift();\n            if (visited[next.id]) continue;\n            visited[next.id] = true;\n            if (iteratee.call(this, next, distance[next.id]) === false) continue;\n            const neighbors = this.getNeighbors(next, opt);\n            for (let i = 0, n = neighbors.length; i < n; i++) {\n                const neighbor = neighbors[i];\n                distance[neighbor.id] = distance[next.id] + 1;\n                queue.push(neighbor);\n            }\n        }\n    },\n\n    // Depth-first search.\n    // If `opt.deep` is `true`, take into account embedded elements too.\n    // If `opt.inbound` is `true`, reverse the search direction (it's like reversing all the link directions).\n    // `iteratee` is a function of the form `function(element, distance) {}`.\n    // If `iteratee` explicitly returns `false`, the search stops.\n    dfs: function(element, iteratee, opt = {}) {\n\n        const visited = {};\n        const distance = {};\n        const queue = [];\n\n        queue.push(element);\n        distance[element.id] = 0;\n\n        while (queue.length > 0) {\n            const next = queue.pop();\n            if (visited[next.id]) continue;\n            visited[next.id] = true;\n            if (iteratee.call(this, next, distance[next.id]) === false) continue;\n            const neighbors = this.getNeighbors(next, opt);\n            const lastIndex = queue.length;\n            for (let i = 0, n = neighbors.length; i < n; i++) {\n                const neighbor = neighbors[i];\n                distance[neighbor.id] = distance[next.id] + 1;\n                queue.splice(lastIndex, 0, neighbor);\n            }\n        }\n    },\n\n    // Get all the roots of the graph. Time complexity: O(|V|).\n    getSources: function() {\n\n        var sources = [];\n        util.forIn(this._nodes, function(exists, node) {\n            if (!this._in[node] || util.isEmpty(this._in[node])) {\n                sources.push(this.getCell(node));\n            }\n        }.bind(this));\n        return sources;\n    },\n\n    // Get all the leafs of the graph. Time complexity: O(|V|).\n    getSinks: function() {\n\n        var sinks = [];\n        util.forIn(this._nodes, function(exists, node) {\n            if (!this._out[node] || util.isEmpty(this._out[node])) {\n                sinks.push(this.getCell(node));\n            }\n        }.bind(this));\n        return sinks;\n    },\n\n    // Return `true` if `element` is a root. Time complexity: O(1).\n    isSource: function(element) {\n\n        return !this._in[element.id] || util.isEmpty(this._in[element.id]);\n    },\n\n    // Return `true` if `element` is a leaf. Time complexity: O(1).\n    isSink: function(element) {\n\n        return !this._out[element.id] || util.isEmpty(this._out[element.id]);\n    },\n\n    // Return `true` is `elementB` is a successor of `elementA`. Return `false` otherwise.\n    isSuccessor: function(elementA, elementB) {\n\n        var isSuccessor = false;\n        this.search(elementA, function(element) {\n            if (element === elementB && element !== elementA) {\n                isSuccessor = true;\n                return false;\n            }\n        }, { outbound: true });\n        return isSuccessor;\n    },\n\n    // Return `true` is `elementB` is a predecessor of `elementA`. Return `false` otherwise.\n    isPredecessor: function(elementA, elementB) {\n\n        var isPredecessor = false;\n        this.search(elementA, function(element) {\n            if (element === elementB && element !== elementA) {\n                isPredecessor = true;\n                return false;\n            }\n        }, { inbound: true });\n        return isPredecessor;\n    },\n\n    // Return `true` is `elementB` is a neighbor of `elementA`. Return `false` otherwise.\n    // `opt.deep` controls whether to take into account embedded elements as well. See `getNeighbors()`\n    // for more details.\n    // If `opt.outbound` is set to `true`, return `true` only if `elementB` is a successor neighbor.\n    // Similarly, if `opt.inbound` is set to `true`, return `true` only if `elementB` is a predecessor neighbor.\n    isNeighbor: function(elementA, elementB, opt) {\n\n        opt = opt || {};\n\n        var inbound = opt.inbound;\n        var outbound = opt.outbound;\n        if ((inbound === undefined) && (outbound === undefined)) {\n            inbound = outbound = true;\n        }\n\n        var isNeighbor = false;\n\n        this.getConnectedLinks(elementA, opt).forEach(function(link) {\n\n            var { source, target } = link.attributes;\n\n            // Discard if it is a point.\n            if (inbound && util.has(source, 'id') && (source.id === elementB.id)) {\n                isNeighbor = true;\n                return false;\n            }\n\n            // Discard if it is a point, or if the neighbor was already added.\n            if (outbound && util.has(target, 'id') && (target.id === elementB.id)) {\n                isNeighbor = true;\n                return false;\n            }\n        });\n\n        return isNeighbor;\n    },\n\n    // Disconnect links connected to the cell `model`.\n    disconnectLinks: function(model, opt) {\n\n        this.getConnectedLinks(model).forEach(function(link) {\n\n            link.set((link.attributes.source.id === model.id ? 'source' : 'target'), { x: 0, y: 0 }, opt);\n        });\n    },\n\n    // Remove links connected to the cell `model` completely.\n    removeLinks: function(model, opt) {\n\n        util.invoke(this.getConnectedLinks(model), 'remove', opt);\n    },\n\n    // Find all cells at given point\n\n    findElementsAtPoint: function(point, opt) {\n        return this._filterAtPoint(this.getElements(), point, opt);\n    },\n\n    findLinksAtPoint: function(point, opt) {\n        return this._filterAtPoint(this.getLinks(), point, opt);\n    },\n\n    findCellsAtPoint: function(point, opt) {\n        return this._filterAtPoint(this.getCells(), point, opt);\n    },\n\n    _filterAtPoint: function(cells, point, opt = {}) {\n        return cells.filter(el => el.getBBox({ rotate: true }).containsPoint(point, opt));\n    },\n\n    // Find all cells in given area\n\n    findElementsInArea: function(area, opt = {}) {\n        return this._filterInArea(this.getElements(), area, opt);\n    },\n\n    findLinksInArea: function(area, opt = {}) {\n        return this._filterInArea(this.getLinks(), area, opt);\n    },\n\n    findCellsInArea: function(area, opt = {}) {\n        return this._filterInArea(this.getCells(), area, opt);\n    },\n\n    _filterInArea: function(cells, area, opt = {}) {\n        const r = new g.Rect(area);\n        const { strict = false } = opt;\n        const method = strict ? 'containsRect' : 'intersect';\n        return cells.filter(el => r[method](el.getBBox({ rotate: true })));\n    },\n\n    // Find all cells under the given element.\n\n    findElementsUnderElement: function(element, opt) {\n        return this._filterCellsUnderElement(this.getElements(), element, opt);\n    },\n\n    findLinksUnderElement: function(element, opt) {\n        return this._filterCellsUnderElement(this.getLinks(), element, opt);\n    },\n\n    findCellsUnderElement: function(element, opt) {\n        return this._filterCellsUnderElement(this.getCells(), element, opt);\n    },\n\n    _isValidElementUnderElement: function(el1, el2) {\n        return el1.id !== el2.id && !el1.isEmbeddedIn(el2);\n    },\n\n    _isValidLinkUnderElement: function(link, el) {\n        return (\n            link.source().id !== el.id &&\n            link.target().id !== el.id &&\n            !link.isEmbeddedIn(el)\n        );\n    },\n\n    _validateCellsUnderElement: function(cells, element) {\n        return cells.filter(cell => {\n            return cell.isLink()\n                ? this._isValidLinkUnderElement(cell, element)\n                : this._isValidElementUnderElement(cell, element);\n        });\n    },\n\n    _getFindUnderElementGeometry: function(element, searchBy = 'bbox') {\n        const bbox = element.getBBox({ rotate: true });\n        return (searchBy !== 'bbox') ? util.getRectPoint(bbox, searchBy) : bbox;\n    },\n\n    _filterCellsUnderElement: function(cells, element, opt = {}) {\n        const geometry = this._getFindUnderElementGeometry(element, opt.searchBy);\n        const filteredCells = (geometry.type === g.types.Point)\n            ? this._filterAtPoint(cells, geometry)\n            : this._filterInArea(cells, geometry, opt);\n        return this._validateCellsUnderElement(filteredCells, element);\n    },\n\n    // @deprecated use `findElementsInArea` instead\n    findModelsInArea: function(area, opt) {\n        return this.findElementsInArea(area, opt);\n    },\n\n    // @deprecated use `findElementsAtPoint` instead\n    findModelsFromPoint: function(point) {\n        return this.findElementsAtPoint(point);\n    },\n\n    // @deprecated use `findModelsUnderElement` instead\n    findModelsUnderElement: function(element, opt) {\n        return this.findElementsUnderElement(element, opt);\n    },\n\n    // Return bounding box of all elements.\n    getBBox: function() {\n\n        return this.getCellsBBox(this.getCells());\n    },\n\n    // Return the bounding box of all cells in array provided.\n    getCellsBBox: function(cells, opt = {}) {\n        const { rotate = true } = opt;\n        return util.toArray(cells).reduce(function(memo, cell) {\n            const rect = cell.getBBox({ rotate });\n            if (!rect) return memo;\n            if (memo) {\n                return memo.union(rect);\n            }\n            return rect;\n        }, null);\n    },\n\n    translate: function(dx, dy, opt) {\n\n        // Don't translate cells that are embedded in any other cell.\n        var cells = this.getCells().filter(function(cell) {\n            return !cell.isEmbedded();\n        });\n\n        util.invoke(cells, 'translate', dx, dy, opt);\n\n        return this;\n    },\n\n    resize: function(width, height, opt) {\n\n        return this.resizeCells(width, height, this.getCells(), opt);\n    },\n\n    resizeCells: function(width, height, cells, opt) {\n\n        // `getBBox` method returns `null` if no elements provided.\n        // i.e. cells can be an array of links\n        var bbox = this.getCellsBBox(cells);\n        if (bbox) {\n            var sx = Math.max(width / bbox.width, 0);\n            var sy = Math.max(height / bbox.height, 0);\n            util.invoke(cells, 'scale', sx, sy, bbox.origin(), opt);\n        }\n\n        return this;\n    },\n\n    startBatch: function(name, data) {\n\n        data = data || {};\n        this._batches[name] = (this._batches[name] || 0) + 1;\n\n        return this.trigger('batch:start', util.assign({}, data, { batchName: name }));\n    },\n\n    stopBatch: function(name, data) {\n\n        data = data || {};\n        this._batches[name] = (this._batches[name] || 0) - 1;\n\n        return this.trigger('batch:stop', util.assign({}, data, { batchName: name }));\n    },\n\n    hasActiveBatch: function(name) {\n\n        const batches = this._batches;\n        let names;\n\n        if (arguments.length === 0) {\n            names = Object.keys(batches);\n        } else if (Array.isArray(name)) {\n            names = name;\n        } else {\n            names = [name];\n        }\n\n        return names.some((batch) => batches[batch] > 0);\n    }\n\n}, {\n\n    validations: {\n\n        multiLinks: function(graph, link) {\n\n            // Do not allow multiple links to have the same source and target.\n            var { source, target } = link.attributes;\n\n            if (source.id && target.id) {\n\n                var sourceModel = link.getSourceCell();\n                if (sourceModel) {\n\n                    var connectedLinks = graph.getConnectedLinks(sourceModel, { outbound: true });\n                    var sameLinks = connectedLinks.filter(function(_link) {\n\n                        var { source: _source, target: _target } = _link.attributes;\n                        return _source && _source.id === source.id &&\n                            (!_source.port || (_source.port === source.port)) &&\n                            _target && _target.id === target.id &&\n                            (!_target.port || (_target.port === target.port));\n\n                    });\n\n                    if (sameLinks.length > 1) {\n                        return false;\n                    }\n                }\n            }\n\n            return true;\n        },\n\n        linkPinning: function(_graph, link) {\n            var { source, target } = link.attributes;\n            return source.id && target.id;\n        }\n    }\n\n});\n\nwrapWith(Graph.prototype, ['resetCells', 'addCells', 'removeCells'], wrappers.cells);\n","import $ from './Dom/index.mjs';\n\nimport { Events } from './Events.mjs';\nimport { extend } from './mvcUtils.mjs';\nimport {\n    assign,\n    isFunction,\n    pick,\n    result,\n    uniqueId\n} from '../util/util.mjs';\n\n// ViewBase\n// -------------\n\n// ViewBases are almost more convention than they are actual code. A View\n// is simply a JavaScript object that represents a logical chunk of UI in the\n// DOM. This might be a single item, an entire list, a sidebar or panel, or\n// even the surrounding frame which wraps your whole app. Defining a chunk of\n// UI as a **View** allows you to define your DOM events declaratively, without\n// having to worry about render order ... and makes it easy for the view to\n// react to specific changes in the state of your models.\n\n// Creating a ViewBase creates its initial element outside of the DOM,\n// if an existing element is not provided...\nexport var ViewBase = function(options) {\n    this.cid = uniqueId('view');\n    this.preinitialize.apply(this, arguments);\n    assign(this, pick(options, viewOptions));\n    this._ensureElement();\n    this.initialize.apply(this, arguments);\n};\n\n// Cached regex to split keys for `delegate`.\nvar delegateEventSplitter = /^(\\S+)\\s*(.*)$/;\n\n// List of view options to be set as properties.\n// TODO: `style` attribute is not supported in ViewBase class yet, but only in View class that extends ViewBase.\nvar viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events', 'style'];\n\n// Set up all inheritable **ViewBase** properties and methods.\nassign(ViewBase.prototype, Events, {\n\n    // The default `tagName` of a View's element is `\"div\"`.\n    tagName: 'div',\n\n    // mvc.$ delegate for element lookup, scoped to DOM elements within the\n    // current view. This should be preferred to global lookups where possible.\n    $: function(selector) {\n        return this.$el.find(selector);\n    },\n\n    // preinitialize is an empty function by default. You can override it with a function\n    // or object.  preinitialize will run before any instantiation logic is run in the View\n    preinitialize: function(){},\n\n    // Initialize is an empty function by default. Override it with your own\n    // initialization logic.\n    initialize: function(){},\n\n    // **render** is the core function that your view should override, in order\n    // to populate its element (`this.el`), with the appropriate HTML. The\n    // convention is for **render** to always return `this`.\n    render: function() {\n        return this;\n    },\n\n    // Remove this view by taking the element out of the DOM, and removing any\n    // applicable Events listeners.\n    remove: function() {\n        this._removeElement();\n        this.stopListening();\n        return this;\n    },\n\n    // Remove this view's element from the document and all event listeners\n    // attached to it. Exposed for subclasses using an alternative DOM\n    // manipulation API.\n    _removeElement: function() {\n        this.$el.remove();\n    },\n\n    // Change the view's element (`this.el` property) and re-delegate the\n    // view's events on the new element.\n    setElement: function(element) {\n        this.undelegateEvents();\n        this._setElement(element);\n        this.delegateEvents();\n        return this;\n    },\n\n    // Creates the `this.el` and `this.$el` references for this view using the\n    // given `el`. `el` can be a CSS selector or an HTML string, a mvc.$\n    // context or an element. Subclasses can override this to utilize an\n    // alternative DOM manipulation API and are only required to set the\n    // `this.el` property.\n    _setElement: function(el) {\n        this.$el = el instanceof $ ? el : $(el);\n        this.el = this.$el[0];\n    },\n\n    // Set callbacks, where `this.events` is a hash of\n    //\n    // *{\"event selector\": \"callback\"}*\n    //\n    //     {\n    //       'mousedown .title':  'edit',\n    //       'click .button':     'save',\n    //       'click .open':       function(e) { ... }\n    //     }\n    //\n    // pairs. Callbacks will be bound to the view, with `this` set properly.\n    // Uses event delegation for efficiency.\n    // Omitting the selector binds the event to `this.el`.\n    delegateEvents: function(events) {\n        events || (events = result(this, 'events'));\n        if (!events) return this;\n        this.undelegateEvents();\n        for (var key in events) {\n            var method = events[key];\n            if (!isFunction(method)) method = this[method];\n            if (!method) continue;\n            var match = key.match(delegateEventSplitter);\n            this.delegate(match[1], match[2], method.bind(this));\n        }\n        return this;\n    },\n\n    // Add a single event listener to the view's element (or a child element\n    // using `selector`). This only works for delegate-able events: not `focus`,\n    // `blur`, and not `change`, `submit`, and `reset` in Internet Explorer.\n    delegate: function(eventName, selector, listener) {\n        this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener);\n        return this;\n    },\n\n    // Clears all callbacks previously bound to the view by `delegateEvents`.\n    // You usually don't need to use this, but may wish to if you have multiple\n    // viewbases attached to the same DOM element.\n    undelegateEvents: function() {\n        if (this.$el) this.$el.off('.delegateEvents' + this.cid);\n        return this;\n    },\n\n    // A finer-grained `undelegateEvents` for removing a single delegated event.\n    // `selector` and `listener` are both optional.\n    undelegate: function(eventName, selector, listener) {\n        this.$el.off(eventName + '.delegateEvents' + this.cid, selector, listener);\n        return this;\n    },\n\n    // Produces a DOM element to be assigned to your view. Exposed for\n    // subclasses using an alternative DOM manipulation API.\n    _createElement: function(tagName) {\n        return document.createElement(tagName);\n    },\n\n    // Ensure that the View has a DOM element to render into.\n    // If `this.el` is a string, pass it through `$()`, take the first\n    // matching element, and re-assign it to `el`. Otherwise, create\n    // an element from the `id`, `className` and `tagName` properties.\n    _ensureElement: function() {\n        if (!this.el) {\n            var attrs = assign({}, result(this, 'attributes'));\n            if (this.id) attrs.id = result(this, 'id');\n            if (this.className) attrs['class'] = result(this, 'className');\n            this.setElement(this._createElement(result(this, 'tagName')));\n            this._setAttributes(attrs);\n        } else {\n            this.setElement(result(this, 'el'));\n        }\n    },\n\n    // Set attributes from a hash on this view's element.  Exposed for\n    // subclasses using an alternative DOM manipulation API.\n    _setAttributes: function(attributes) {\n        this.$el.attr(attributes);\n    }\n\n});\n\n// Set up inheritance for the view.\nViewBase.extend = extend;\n","import $ from './Dom/index.mjs';\nimport * as util from '../util/index.mjs';\nimport V from '../V/index.mjs';\nimport { ViewBase } from './ViewBase.mjs';\nimport { config } from '../config/index.mjs';\n\nexport const views = {};\n\nexport const View = ViewBase.extend({\n\n    options: {},\n    theme: null,\n    themeClassNamePrefix: util.addClassNamePrefix('theme-'),\n    requireSetThemeOverride: false,\n    defaultTheme: config.defaultTheme,\n    children: null,\n    childNodes: null,\n\n    DETACHABLE: true,\n    UPDATE_PRIORITY: 2,\n    FLAG_INSERT: 1<<30,\n    FLAG_REMOVE: 1<<29,\n    FLAG_INIT: 1<<28,\n\n    constructor: function(options) {\n\n        this.requireSetThemeOverride = options && !!options.theme;\n        this.options = util.assign({}, this.options, options);\n\n        ViewBase.call(this, options);\n    },\n\n    initialize: function() {\n\n        views[this.cid] = this;\n\n        this.setTheme(this.options.theme || this.defaultTheme);\n        this.init();\n    },\n\n    unmount: function() {\n        if (this.svgElement) {\n            this.vel.remove();\n        } else {\n            this.$el.remove();\n        }\n    },\n\n    isMounted: function() {\n        return this.el.parentNode !== null;\n    },\n\n    renderChildren: function(children) {\n        children || (children = util.result(this, 'children'));\n        if (children) {\n            var isSVG = this.svgElement;\n            var namespace = V.namespace[isSVG ? 'svg' : 'xhtml'];\n            var doc = util.parseDOMJSON(children, namespace);\n            (isSVG ? this.vel : this.$el).empty().append(doc.fragment);\n            this.childNodes = doc.selectors;\n        }\n        return this;\n    },\n\n    findAttributeNode: function(attributeName, node) {\n        let currentNode = node;\n        while (currentNode && currentNode.nodeType === 1) {\n            // attribute found\n            // (empty value does not count as attribute found)\n            if (currentNode.getAttribute(attributeName)) return currentNode;\n            // do not climb up the DOM\n            if (currentNode === this.el) return null;\n            // try parent node\n            currentNode = currentNode.parentNode;\n        }\n        return null;\n    },\n\n    findAttribute: function(attributeName, node) {\n        const matchedNode = this.findAttributeNode(attributeName, node);\n        return matchedNode && matchedNode.getAttribute(attributeName);\n    },\n\n    // Override the mvc ViewBase `_ensureElement()` method in order to create an\n    // svg element (e.g., `<g>`) node that wraps all the nodes of the Cell view.\n    // Expose class name setter as a separate method.\n    _ensureElement: function() {\n        if (!this.el) {\n            var tagName = util.result(this, 'tagName');\n            var attrs = util.assign({}, util.result(this, 'attributes'));\n            var style = util.assign({}, util.result(this, 'style'));\n            if (this.id) attrs.id = util.result(this, 'id');\n            this.setElement(this._createElement(tagName));\n            this._setAttributes(attrs);\n            this._setStyle(style);\n        } else {\n            this.setElement(util.result(this, 'el'));\n        }\n        this._ensureElClassName();\n    },\n\n    _setAttributes: function(attrs) {\n        if (this.svgElement) {\n            this.vel.attr(attrs);\n        } else {\n            this.$el.attr(attrs);\n        }\n    },\n\n    _setStyle: function(style) {\n        this.$el.css(style);\n    },\n\n    _createElement: function(tagName) {\n        if (this.svgElement) {\n            return document.createElementNS(V.namespace.svg, tagName);\n        } else {\n            return document.createElement(tagName);\n        }\n    },\n\n    // Utilize an alternative DOM manipulation API by\n    // adding an element reference wrapped in Vectorizer.\n    _setElement: function(el) {\n        this.$el = el instanceof $ ? el : $(el);\n        this.el = this.$el[0];\n        if (this.svgElement) this.vel = V(this.el);\n    },\n\n    _ensureElClassName: function() {\n        var className = util.result(this, 'className');\n        if (!className) return;\n        var prefixedClassName = util.addClassNamePrefix(className);\n        // Note: className removal here kept for backwards compatibility only\n        if (this.svgElement) {\n            this.vel.removeClass(className).addClass(prefixedClassName);\n        } else {\n            this.$el.removeClass(className).addClass(prefixedClassName);\n        }\n    },\n\n    init: function() {\n        // Intentionally empty.\n        // This method is meant to be overridden.\n    },\n\n    onRender: function() {\n        // Intentionally empty.\n        // This method is meant to be overridden.\n    },\n\n    confirmUpdate: function() {\n        // Intentionally empty.\n        // This method is meant to be overridden.\n        return 0;\n    },\n\n    setTheme: function(theme, opt) {\n\n        opt = opt || {};\n\n        // Theme is already set, override is required, and override has not been set.\n        // Don't set the theme.\n        if (this.theme && this.requireSetThemeOverride && !opt.override) {\n            return this;\n        }\n\n        this.removeThemeClassName();\n        this.addThemeClassName(theme);\n        this.onSetTheme(this.theme/* oldTheme */, theme/* newTheme */);\n        this.theme = theme;\n\n        return this;\n    },\n\n    addThemeClassName: function(theme) {\n\n        theme = theme || this.theme;\n        if (!theme) return this;\n\n        var className = this.themeClassNamePrefix + theme;\n\n        if (this.svgElement) {\n            this.vel.addClass(className);\n        } else {\n            this.$el.addClass(className);\n        }\n\n        return this;\n    },\n\n    removeThemeClassName: function(theme) {\n\n        theme = theme || this.theme;\n\n        var className = this.themeClassNamePrefix + theme;\n\n        if (this.svgElement) {\n            this.vel.removeClass(className);\n        } else {\n            this.$el.removeClass(className);\n        }\n\n        return this;\n    },\n\n    onSetTheme: function(oldTheme, newTheme) {\n        // Intentionally empty.\n        // This method is meant to be overridden.\n    },\n\n    remove: function() {\n\n        this.onRemove();\n        this.undelegateDocumentEvents();\n\n        views[this.cid] = null;\n\n        ViewBase.prototype.remove.apply(this, arguments);\n\n        return this;\n    },\n\n    onRemove: function() {\n        // Intentionally empty.\n        // This method is meant to be overridden.\n    },\n\n    getEventNamespace: function() {\n        // Returns a per-session unique namespace\n        return '.joint-event-ns-' + this.cid;\n    },\n\n    delegateElementEvents: function(element, events, data) {\n        if (!events) return this;\n        data || (data = {});\n        var eventNS = this.getEventNamespace();\n        for (var eventName in events) {\n            var method = events[eventName];\n            if (typeof method !== 'function') method = this[method];\n            if (!method) continue;\n            $(element).on(eventName + eventNS, data, method.bind(this));\n        }\n        return this;\n    },\n\n    undelegateElementEvents: function(element) {\n        $(element).off(this.getEventNamespace());\n        return this;\n    },\n\n    delegateDocumentEvents: function(events, data) {\n        events || (events = util.result(this, 'documentEvents'));\n        return this.delegateElementEvents(document, events, data);\n    },\n\n    undelegateDocumentEvents: function() {\n        return this.undelegateElementEvents(document);\n    },\n\n    eventData: function(evt, data) {\n        if (!evt) throw new Error('eventData(): event object required.');\n        var currentData = evt.data;\n        var key = '__' + this.cid + '__';\n        if (data === undefined) {\n            if (!currentData) return {};\n            return currentData[key] || {};\n        }\n        currentData || (currentData = evt.data = {});\n        currentData[key] || (currentData[key] = {});\n        util.assign(currentData[key], data);\n        return this;\n    },\n\n    stopPropagation: function(evt) {\n        this.eventData(evt, { propagationStopped: true });\n        return this;\n    },\n\n    isPropagationStopped: function(evt) {\n        return !!this.eventData(evt).propagationStopped;\n    }\n\n}, {\n\n    extend: function() {\n\n        var args = Array.from(arguments);\n\n        // Deep clone the prototype and static properties objects.\n        // This prevents unexpected behavior where some properties are overwritten outside of this function.\n        var protoProps = args[0] && util.assign({}, args[0]) || {};\n        var staticProps = args[1] && util.assign({}, args[1]) || {};\n\n        // Need the real render method so that we can wrap it and call it later.\n        var renderFn = protoProps.render || (this.prototype && this.prototype.render) || null;\n\n        /*\n            Wrap the real render method so that:\n                .. `onRender` is always called.\n                .. `this` is always returned.\n        */\n        protoProps.render = function() {\n\n            if (typeof renderFn === 'function') {\n                // Call the original render method.\n                renderFn.apply(this, arguments);\n            }\n\n            if (this.render.__render__ === renderFn) {\n                // Should always call onRender() method.\n                // Should call it only once when renderFn is actual prototype method i.e. not the wrapper\n                this.onRender();\n            }\n\n            // Should always return itself.\n            return this;\n        };\n\n        protoProps.render.__render__ = renderFn;\n\n        return ViewBase.extend.call(this, protoProps, staticProps);\n    }\n});\n","import * as mvc from '../mvc/index.mjs';\nimport V from '../V/index.mjs';\nimport { isPlainObject, result } from '../util/util.mjs';\n\nfunction toArray(obj) {\n    if (!obj) return [];\n    if (Array.isArray(obj)) return obj;\n    return [obj];\n}\n\nexport const HighlighterView = mvc.View.extend({\n\n    tagName: 'g',\n    svgElement: true,\n    className: 'highlight',\n\n    HIGHLIGHT_FLAG: 1,\n    UPDATE_PRIORITY: 3,\n    DETACHABLE: false,\n    UPDATABLE: true,\n    MOUNTABLE: true,\n\n    cellView: null,\n    nodeSelector: null,\n    node: null,\n    updateRequested: false,\n    postponedUpdate: false,\n    transformGroup: null,\n    detachedTransformGroup: null,\n\n    requestUpdate(cellView, nodeSelector) {\n        const { paper } = cellView;\n        this.cellView = cellView;\n        this.nodeSelector = nodeSelector;\n        if (paper) {\n            this.updateRequested = true;\n            paper.requestViewUpdate(this, this.HIGHLIGHT_FLAG, this.UPDATE_PRIORITY);\n        }\n    },\n\n    confirmUpdate() {\n        // The cellView is now rendered/updated since it has a higher update priority.\n        this.updateRequested = false;\n        const { cellView, nodeSelector } = this;\n        if (!cellView.isMounted()) {\n            this.postponedUpdate = true;\n            return 0;\n        }\n        this.update(cellView, nodeSelector);\n        this.mount();\n        this.transform();\n        return 0;\n    },\n\n    findNode(cellView, nodeSelector = null) {\n        let el;\n        if (typeof nodeSelector === 'string') {\n            el = cellView.findNode(nodeSelector);\n        } else if (isPlainObject(nodeSelector)) {\n            const isLink = cellView.model.isLink();\n            const { label = null, port, selector } = nodeSelector;\n            if (isLink && label !== null) {\n                // Link Label Selector\n                el = cellView.findLabelNode(label, selector);\n            } else if (!isLink && port) {\n                // Element Port Selector\n                el = cellView.findPortNode(port, selector);\n            } else {\n                // Cell Selector\n                el = cellView.findNode(selector);\n            }\n        } else if (nodeSelector) {\n            el = V.toNode(nodeSelector);\n            if (!(el instanceof SVGElement)) el = null;\n        }\n        return el ? el : null;\n    },\n\n    getNodeMatrix(cellView, node) {\n        const { options } = this;\n        const { layer } = options;\n        const { rotatableNode } = cellView;\n        const nodeMatrix = cellView.getNodeMatrix(node);\n        if (rotatableNode) {\n            if (layer) {\n                if (rotatableNode.contains(node)) {\n                    return nodeMatrix;\n                }\n                // The node is outside of the rotatable group.\n                // Compensate the rotation set by transformGroup.\n                return cellView.getRootRotateMatrix().inverse().multiply(nodeMatrix);\n            } else {\n                return cellView.getNodeRotateMatrix(node).multiply(nodeMatrix);\n            }\n        }\n        return nodeMatrix;\n    },\n\n    mount() {\n        const { MOUNTABLE, cellView, el, options, transformGroup, detachedTransformGroup, postponedUpdate, nodeSelector } = this;\n        if (!MOUNTABLE || transformGroup) return;\n        if (postponedUpdate) {\n            // The cellView was not mounted when the update was requested.\n            // The update was postponed until the cellView is mounted.\n            this.update(cellView, nodeSelector);\n            this.transform();\n            return;\n        }\n        const { vel: cellViewRoot, paper } = cellView;\n        const { layer: layerName } = options;\n        if (layerName) {\n            let vGroup;\n            if (detachedTransformGroup) {\n                vGroup = detachedTransformGroup;\n                this.detachedTransformGroup = null;\n            } else {\n                vGroup = V('g').addClass('highlight-transform').append(el);\n            }\n            this.transformGroup = vGroup;\n            paper.getLayerView(layerName).insertSortedNode(vGroup.node, options.z);\n        } else {\n            // TODO: prepend vs append\n            if (!el.parentNode || el.nextSibling) {\n                // Not appended yet or not the last child\n                cellViewRoot.append(el);\n            }\n        }\n    },\n\n    unmount() {\n        const { MOUNTABLE, transformGroup, vel } = this;\n        if (!MOUNTABLE) return;\n        if (transformGroup) {\n            this.transformGroup = null;\n            this.detachedTransformGroup = transformGroup;\n            transformGroup.remove();\n        } else {\n            vel.remove();\n        }\n    },\n\n    transform() {\n        const { transformGroup, cellView, updateRequested } = this;\n        if (!transformGroup || cellView.model.isLink() || updateRequested) return;\n        const translateMatrix = cellView.getRootTranslateMatrix();\n        const rotateMatrix = cellView.getRootRotateMatrix();\n        const transformMatrix = translateMatrix.multiply(rotateMatrix);\n        transformGroup.attr('transform', V.matrixToTransformString(transformMatrix));\n    },\n\n    update() {\n        const { node: prevNode, cellView, nodeSelector, updateRequested, id } = this;\n        if (updateRequested) return;\n        this.postponedUpdate = false;\n        const node = this.node = this.findNode(cellView, nodeSelector);\n        if (prevNode) {\n            this.unhighlight(cellView, prevNode);\n        }\n        if (node) {\n            this.highlight(cellView, node);\n            this.mount();\n        } else {\n            this.unmount();\n            cellView.notify('cell:highlight:invalid', id, this);\n        }\n    },\n\n    onRemove() {\n        const { node, cellView, id, constructor } = this;\n        if (node) {\n            this.unhighlight(cellView, node);\n        }\n        this.unmount();\n        constructor._removeRef(cellView, id);\n    },\n\n    highlight(_cellView, _node) {\n        // to be overridden\n    },\n\n    unhighlight(_cellView, _node) {\n        // to be overridden\n    },\n\n    // Update Attributes\n\n    listenToUpdateAttributes(cellView) {\n        const attributes = result(this, 'UPDATE_ATTRIBUTES');\n        if (!Array.isArray(attributes) || attributes.length === 0) return;\n        this.listenTo(cellView.model, 'change', this.onCellAttributeChange);\n    },\n\n    onCellAttributeChange() {\n        const { cellView } = this;\n        if (!cellView) return;\n        const { model, paper } = cellView;\n        const attributes = result(this, 'UPDATE_ATTRIBUTES');\n        if (!attributes.some(attribute => model.hasChanged(attribute))) return;\n        paper.requestViewUpdate(this, this.HIGHLIGHT_FLAG, this.UPDATE_PRIORITY);\n    }\n\n}, {\n\n    _views: {},\n\n    // Used internally by CellView highlight()\n    highlight: function(cellView, node, opt) {\n        const id = this.uniqueId(node, opt);\n        this.add(cellView, node, id, opt);\n    },\n\n    // Used internally by CellView unhighlight()\n    unhighlight: function(cellView, node, opt) {\n        const id = this.uniqueId(node, opt);\n        this.remove(cellView, id);\n    },\n\n    get(cellView, id = null) {\n        const { cid } = cellView;\n        const { _views } = this;\n        const refs = _views[cid];\n        if (id === null) {\n            // all highlighters\n            const views = [];\n            if (!refs) return views;\n            for (let hid in refs) {\n                const ref = refs[hid];\n                if (ref instanceof this) {\n                    views.push(ref);\n                }\n            }\n            return views;\n        } else {\n            // single highlighter\n            if (!refs) return null;\n            if (id in refs) {\n                const ref = refs[id];\n                if (ref instanceof this) return ref;\n            }\n            return null;\n        }\n    },\n\n    add(cellView, nodeSelector, id, opt = {}) {\n        if (!id) throw new Error('dia.HighlighterView: An ID required.');\n        // Search the existing view amongst all the highlighters\n        const previousView = HighlighterView.get(cellView, id);\n        if (previousView) previousView.remove();\n        const view = new this(opt);\n        view.id = id;\n        this._addRef(cellView, id, view);\n        view.requestUpdate(cellView, nodeSelector);\n        view.listenToUpdateAttributes(cellView);\n        return view;\n    },\n\n    _addRef(cellView, id, view) {\n        const { cid } = cellView;\n        const { _views } = this;\n        let refs = _views[cid];\n        if (!refs) refs = _views[cid] = {};\n        refs[id] = view;\n    },\n\n    _removeRef(cellView, id) {\n        const { cid } = cellView;\n        const { _views } = this;\n        const refs = _views[cid];\n        if (!refs) return;\n        if (id) delete refs[id];\n        for (let _ in refs) return;\n        delete _views[cid];\n    },\n\n    remove(cellView, id = null) {\n        toArray(this.get(cellView, id)).forEach(view => {\n            view.remove();\n        });\n    },\n\n    getAll(paper, id = null) {\n        const views = [];\n        const { _views } = this;\n        for (let cid in _views) {\n            for (let hid in _views[cid]) {\n                const view = _views[cid][hid];\n                if (view.cellView.paper === paper && view instanceof this && (id === null || hid === id)) {\n                    views.push(view);\n                }\n            }\n        }\n        return views;\n    },\n\n    removeAll(paper, id = null) {\n        this.getAll(paper, id).forEach(view => view.remove());\n    },\n\n    update(cellView, id = null, dirty = false) {\n        toArray(this.get(cellView, id)).forEach(view => {\n            if (dirty || view.UPDATABLE) view.update();\n        });\n    },\n\n    transform(cellView, id = null) {\n        toArray(this.get(cellView, id)).forEach(view => {\n            if (view.UPDATABLE) view.transform();\n        });\n    },\n\n    unmount(cellView, id = null) {\n        toArray(this.get(cellView, id)).forEach(view => view.unmount());\n    },\n\n    mount(cellView, id = null) {\n        toArray(this.get(cellView, id)).forEach(view => view.mount());\n    },\n\n    uniqueId(node, opt = '') {\n        return V.ensureId(node) + JSON.stringify(opt);\n    }\n\n});\n","import { isCalcExpression, evalCalcExpression } from '../../util/calc.mjs';\n\nconst calcAttributesList = [\n    'transform',\n    'x',\n    'y',\n    'cx',\n    'cy',\n    'dx',\n    'dy',\n    'x1',\n    'y1',\n    'x2',\n    'y2',\n    'points',\n    'd',\n    'r',\n    'rx',\n    'ry',\n    'width',\n    'height',\n    'stroke-width',\n    'font-size',\n];\n\nconst positiveValueList = [\n    'r',\n    'rx',\n    'ry',\n    'width',\n    'height',\n    'stroke-width',\n    'font-size',\n];\n\nconst calcAttributes = calcAttributesList.reduce((acc, attrName) => {\n    acc[attrName] = true;\n    return acc;\n}, {});\n\nconst positiveValueAttributes = positiveValueList.reduce((acc, attrName) => {\n    acc[attrName] = true;\n    return acc;\n}, {});\n\nexport function evalAttributes(attrs, refBBox) {\n    const evalAttrs = {};\n    for (let attrName in attrs) {\n        if (!attrs.hasOwnProperty(attrName)) continue;\n        evalAttrs[attrName] = evalAttribute(attrName, attrs[attrName], refBBox);\n    }\n    return evalAttrs;\n}\n\nexport function evalAttribute(attrName, attrValue, refBBox) {\n    if (attrName in calcAttributes && isCalcExpression(attrValue)) {\n        let evalAttrValue = evalCalcExpression(attrValue, refBBox);\n        if (attrName in positiveValueAttributes) {\n            evalAttrValue = Math.max(0, evalAttrValue);\n        }\n        return evalAttrValue;\n    }\n    return attrValue;\n}\n","import { config } from '../config/index.mjs';\nimport { View } from '../mvc/index.mjs';\nimport {\n    assign,\n    guid,\n    omit,\n    parseDOMJSON,\n    isFunction,\n    isObject,\n    isPlainObject,\n    isBoolean,\n    isEmpty,\n    isString,\n    result,\n    sortedIndex,\n    merge,\n    uniq\n} from '../util/index.mjs';\nimport { Point, Rect, intersection } from '../g/index.mjs';\nimport V from '../V/index.mjs';\nimport $ from '../mvc/Dom/index.mjs';\nimport { HighlighterView } from './HighlighterView.mjs';\nimport { evalAttributes, evalAttribute } from './attributes/eval.mjs';\n\nconst HighlightingTypes = {\n    DEFAULT: 'default',\n    EMBEDDING: 'embedding',\n    CONNECTING: 'connecting',\n    MAGNET_AVAILABILITY: 'magnetAvailability',\n    ELEMENT_AVAILABILITY: 'elementAvailability'\n};\n\nconst Flags = {\n    TOOLS: 'TOOLS',\n};\n\n// CellView base view and controller.\n// --------------------------------------------\n\n// This is the base view and controller for `ElementView` and `LinkView`.\nexport const CellView = View.extend({\n\n    tagName: 'g',\n\n    svgElement: true,\n\n    selector: 'root',\n\n    metrics: null,\n\n    className: function() {\n\n        var classNames = ['cell'];\n        var type = this.model.get('type');\n\n        if (type) {\n\n            type.toLowerCase().split('.').forEach(function(value, index, list) {\n                classNames.push('type-' + list.slice(0, index + 1).join('-'));\n            });\n        }\n\n        return classNames.join(' ');\n    },\n\n    _presentationAttributes: null,\n    _flags: null,\n\n    setFlags: function() {\n        var flags = {};\n        var attributes = {};\n        var shift = 0;\n        var i, n, label;\n        var presentationAttributes = result(this, 'presentationAttributes');\n        for (var attribute in presentationAttributes) {\n            if (!presentationAttributes.hasOwnProperty(attribute)) continue;\n            var labels = presentationAttributes[attribute];\n            if (!Array.isArray(labels)) labels = [labels];\n            for (i = 0, n = labels.length; i < n; i++) {\n                label = labels[i];\n                var flag = flags[label];\n                if (!flag) {\n                    flag = flags[label] = 1<<(shift++);\n                }\n                attributes[attribute] |= flag;\n            }\n        }\n        var initFlag = result(this, 'initFlag');\n        if (!Array.isArray(initFlag)) initFlag = [initFlag];\n        for (i = 0, n = initFlag.length; i < n; i++) {\n            label = initFlag[i];\n            if (!flags[label]) flags[label] = 1<<(shift++);\n        }\n\n        // 26 - 30 are reserved for paper flags\n        // 31+ overflows maximal number\n        if (shift > 25) throw new Error('dia.CellView: Maximum number of flags exceeded.');\n\n        this._flags = flags;\n        this._presentationAttributes = attributes;\n    },\n\n    hasFlag: function(flag, label) {\n        return flag & this.getFlag(label);\n    },\n\n    removeFlag: function(flag, label) {\n        return flag ^ (flag & this.getFlag(label));\n    },\n\n    getFlag: function(label) {\n        var flags = this._flags;\n        if (!flags) return 0;\n        var flag = 0;\n        if (Array.isArray(label)) {\n            for (var i = 0, n = label.length; i < n; i++) flag |= flags[label[i]];\n        } else {\n            flag |= flags[label];\n        }\n        return flag;\n    },\n\n    attributes: function() {\n        var cell = this.model;\n        return {\n            'model-id': cell.id,\n            'data-type': cell.attributes.type\n        };\n    },\n\n    constructor: function(options) {\n\n        // Make sure a global unique id is assigned to this view. Store this id also to the properties object.\n        // The global unique id makes sure that the same view can be rendered on e.g. different machines and\n        // still be associated to the same object among all those clients. This is necessary for real-time\n        // collaboration mechanism.\n        options.id = options.id || guid(this);\n\n        View.call(this, options);\n    },\n\n    initialize: function() {\n\n        this.setFlags();\n\n        View.prototype.initialize.apply(this, arguments);\n\n        this.cleanNodesCache();\n\n        this.startListening();\n    },\n\n    startListening: function() {\n        this.listenTo(this.model, 'change', this.onAttributesChange);\n    },\n\n    onAttributesChange: function(model, opt) {\n        var flag = model.getChangeFlag(this._presentationAttributes);\n        if (opt.updateHandled || !flag) return;\n        if (opt.dirty && this.hasFlag(flag, 'UPDATE')) flag |= this.getFlag('RENDER');\n        // TODO: tool changes does not need to be sync\n        // Fix Segments tools\n        if (opt.tool) opt.async = false;\n        this.requestUpdate(flag, opt);\n    },\n\n    requestUpdate: function(flags, opt) {\n        const { paper } = this;\n        if (paper && flags > 0) {\n            paper.requestViewUpdate(this, flags, this.UPDATE_PRIORITY, opt);\n        }\n    },\n\n    parseDOMJSON: function(markup, root) {\n\n        var doc = parseDOMJSON(markup);\n        var selectors = doc.selectors;\n        var groups = doc.groupSelectors;\n        for (var group in groups) {\n            if (selectors[group]) throw new Error('dia.CellView: ambiguous group selector');\n            selectors[group] = groups[group];\n        }\n        if (root) {\n            var rootSelector = this.selector;\n            if (selectors[rootSelector]) throw new Error('dia.CellView: ambiguous root selector.');\n            selectors[rootSelector] = root;\n        }\n        return { fragment: doc.fragment, selectors: selectors };\n    },\n\n    // Return `true` if cell link is allowed to perform a certain UI `feature`.\n    // Example: `can('labelMove')`.\n    can: function(feature) {\n\n        var interactive = isFunction(this.options.interactive)\n            ? this.options.interactive(this)\n            : this.options.interactive;\n\n        return (isObject(interactive) && interactive[feature] !== false) ||\n            (isBoolean(interactive) && interactive !== false);\n    },\n\n    findBySelector: function(selector, root, selectors) {\n\n        // These are either descendants of `this.$el` of `this.$el` itself.\n        // `.` is a special selector used to select the wrapping `<g>` element.\n        if (!selector || selector === '.') return [root];\n        if (selectors) {\n            var nodes = selectors[selector];\n            if (nodes) {\n                if (Array.isArray(nodes)) return nodes;\n                return [nodes];\n            }\n        }\n\n        // Maintaining backwards compatibility\n        // e.g. `circle:first` would fail with querySelector() call\n        if (this.useCSSSelectors) return $(root).find(selector).toArray();\n\n        return [];\n    },\n\n    findNodes: function(selector) {\n        return this.findBySelector(selector, this.el, this.selectors);\n    },\n\n    findNode: function(selector) {\n        const [node = null] = this.findNodes(selector);\n        return node;\n    },\n\n    notify: function(eventName) {\n\n        if (this.paper) {\n\n            var args = Array.prototype.slice.call(arguments, 1);\n\n            // Trigger the event on both the element itself and also on the paper.\n            this.trigger.apply(this, [eventName].concat(args));\n\n            // Paper event handlers receive the view object as the first argument.\n            this.paper.trigger.apply(this.paper, [eventName, this].concat(args));\n        }\n    },\n\n    getBBox: function(opt) {\n\n        var bbox;\n        if (opt && opt.useModelGeometry) {\n            var model = this.model;\n            bbox = model.getBBox().bbox(model.angle());\n        } else {\n            bbox = this.getNodeBBox(this.el);\n        }\n\n        return this.paper.localToPaperRect(bbox);\n    },\n\n    getNodeBBox: function(magnet) {\n\n        const rect = this.getNodeBoundingRect(magnet);\n        const transformMatrix = this.getRootTranslateMatrix().multiply(this.getNodeRotateMatrix(magnet));\n        const magnetMatrix = this.getNodeMatrix(magnet);\n        return V.transformRect(rect, transformMatrix.multiply(magnetMatrix));\n    },\n\n    getNodeRotateMatrix(node) {\n        if (!this.rotatableNode || this.rotatableNode.contains(node)) {\n            // Rotate transformation is applied to all nodes when no rotatableGroup\n            // is present or to nodes inside the rotatableGroup only.\n            return this.getRootRotateMatrix();\n        }\n        // Nodes outside the rotatable group\n        return V.createSVGMatrix();\n    },\n\n    getNodeUnrotatedBBox: function(magnet) {\n\n        var rect = this.getNodeBoundingRect(magnet);\n        var magnetMatrix = this.getNodeMatrix(magnet);\n        var translateMatrix = this.getRootTranslateMatrix();\n        return V.transformRect(rect, translateMatrix.multiply(magnetMatrix));\n    },\n\n    getRootTranslateMatrix: function() {\n\n        var model = this.model;\n        var position = model.position();\n        var mt = V.createSVGMatrix().translate(position.x, position.y);\n        return mt;\n    },\n\n    getRootRotateMatrix: function() {\n\n        var mr = V.createSVGMatrix();\n        var model = this.model;\n        var angle = model.angle();\n        if (angle) {\n            var bbox = model.getBBox();\n            var cx = bbox.width / 2;\n            var cy = bbox.height / 2;\n            mr = mr.translate(cx, cy).rotate(angle).translate(-cx, -cy);\n        }\n        return mr;\n    },\n\n    _notifyHighlight: function(eventName, el, opt = {}) {\n        const { el: rootNode } = this;\n        let node;\n        if (typeof el === 'string') {\n            node = this.findNode(el) || rootNode;\n        } else {\n            [node = rootNode] = this.$(el);\n        }\n        // set partial flag if the highlighted element is not the entire view.\n        opt.partial = (node !== rootNode);\n        // translate type flag into a type string\n        if (opt.type === undefined) {\n            let type;\n            switch (true) {\n                case opt.embedding:\n                    type = HighlightingTypes.EMBEDDING;\n                    break;\n                case opt.connecting:\n                    type = HighlightingTypes.CONNECTING;\n                    break;\n                case opt.magnetAvailability:\n                    type = HighlightingTypes.MAGNET_AVAILABILITY;\n                    break;\n                case opt.elementAvailability:\n                    type = HighlightingTypes.ELEMENT_AVAILABILITY;\n                    break;\n                default:\n                    type = HighlightingTypes.DEFAULT;\n                    break;\n            }\n            opt.type = type;\n        }\n        this.notify(eventName, node, opt);\n        return this;\n    },\n\n    highlight: function(el, opt) {\n        return this._notifyHighlight('cell:highlight', el, opt);\n    },\n\n    unhighlight: function(el, opt = {}) {\n        return this._notifyHighlight('cell:unhighlight', el, opt);\n    },\n\n    // Find the closest element that has the `magnet` attribute set to `true`. If there was not such\n    // an element found, return the root element of the cell view.\n    findMagnet: function(el) {\n\n        const root = this.el;\n        let magnet = this.$(el)[0];\n        if (!magnet) {\n            magnet = root;\n        }\n\n        do {\n            const magnetAttribute = magnet.getAttribute('magnet');\n            const isMagnetRoot = (magnet === root);\n            if ((magnetAttribute || isMagnetRoot) && magnetAttribute !== 'false') {\n                return magnet;\n            }\n            if (isMagnetRoot) {\n                // If the overall cell has set `magnet === false`, then return `undefined` to\n                // announce there is no magnet found for this cell.\n                // This is especially useful to set on cells that have 'ports'. In this case,\n                // only the ports have set `magnet === true` and the overall element has `magnet === false`.\n                return undefined;\n            }\n            magnet = magnet.parentNode;\n        } while (magnet);\n\n        return undefined;\n    },\n\n    findProxyNode: function(el, type) {\n        el || (el = this.el);\n        const nodeSelector = el.getAttribute(`${type}-selector`);\n        if (nodeSelector) {\n            const proxyNode = this.findNode(nodeSelector);\n            if (proxyNode) return proxyNode;\n        }\n        return el;\n    },\n\n    // Construct a unique selector for the `el` element within this view.\n    // `prevSelector` is being collected through the recursive call.\n    // No value for `prevSelector` is expected when using this method.\n    getSelector: function(el, prevSelector) {\n\n        var selector;\n\n        if (el === this.el) {\n            if (typeof prevSelector === 'string') selector = ':scope > ' + prevSelector;\n            return selector;\n        }\n\n        if (el) {\n\n            var nthChild = V(el).index() + 1;\n            selector = el.tagName + ':nth-child(' + nthChild + ')';\n\n            if (prevSelector) {\n                selector += ' > ' + prevSelector;\n            }\n\n            selector = this.getSelector(el.parentNode, selector);\n        }\n\n        return selector;\n    },\n\n    addLinkFromMagnet: function(magnet, x, y) {\n\n        var paper = this.paper;\n        var graph = paper.model;\n\n        var link = paper.getDefaultLink(this, magnet);\n        link.set({\n            source: this.getLinkEnd(magnet, x, y, link, 'source'),\n            target: { x: x, y: y }\n        }).addTo(graph, {\n            async: false,\n            ui: true\n        });\n\n        return link.findView(paper);\n    },\n\n    getLinkEnd: function(magnet, ...args) {\n\n        const model = this.model;\n        const id = model.id;\n        // Find a node with the `port` attribute set on it.\n        const portNode = this.findAttributeNode('port', magnet);\n        // Find a unique `selector` of the element under pointer that is a magnet.\n        const selector = magnet.getAttribute('joint-selector');\n\n        const end = { id: id };\n        if (selector != null) end.magnet = selector;\n        if (portNode != null) {\n            let port = portNode.getAttribute('port');\n            if (portNode.getAttribute('port-id-type') === 'number') {\n                port = parseInt(port, 10);\n            }\n            end.port = port;\n            if (!model.hasPort(port) && !selector) {\n                // port created via the `port` attribute (not API)\n                end.selector = this.getSelector(magnet);\n            }\n        } else if (selector == null && this.el !== magnet) {\n            end.selector = this.getSelector(magnet);\n        }\n\n        return this.customizeLinkEnd(end, magnet, ...args);\n    },\n\n    customizeLinkEnd: function(end, magnet, x, y, link, endType) {\n        const { paper } = this;\n        const { connectionStrategy } = paper.options;\n        if (typeof connectionStrategy === 'function') {\n            var strategy = connectionStrategy.call(paper, end, this, magnet, new Point(x, y), link, endType, paper);\n            if (strategy) return strategy;\n        }\n        return end;\n    },\n\n    getMagnetFromLinkEnd: function(end) {\n\n        var port = end.port;\n        var selector = end.magnet;\n        var model = this.model;\n        var magnet;\n        if (port != null && model.isElement() && model.hasPort(port)) {\n            magnet = this.findPortNode(port, selector) || this.el;\n        } else {\n            if (!selector) selector = end.selector;\n            if (!selector && port != null) {\n                // link end has only `id` and `port` property referencing\n                // a port created via the `port` attribute (not API).\n                selector = '[port=\"' + port + '\"]';\n            }\n            magnet = this.findNode(selector);\n        }\n\n        return this.findProxyNode(magnet, 'magnet');\n    },\n\n    dragLinkStart: function(evt, magnet, x, y) {\n        this.model.startBatch('add-link');\n        const linkView = this.addLinkFromMagnet(magnet, x, y);\n        // backwards compatibility events\n        linkView.notifyPointerdown(evt, x, y);\n        linkView.eventData(evt, linkView.startArrowheadMove('target', { whenNotAllowed: 'remove' }));\n        this.eventData(evt, { linkView });\n    },\n\n    dragLink: function(evt, x, y) {\n        var data = this.eventData(evt);\n        var linkView = data.linkView;\n        if (linkView) {\n            linkView.pointermove(evt, x, y);\n        } else {\n            var paper = this.paper;\n            var magnetThreshold = paper.options.magnetThreshold;\n            var currentTarget = this.getEventTarget(evt);\n            var targetMagnet = data.targetMagnet;\n            if (magnetThreshold === 'onleave') {\n                // magnetThreshold when the pointer leaves the magnet\n                if (targetMagnet === currentTarget || V(targetMagnet).contains(currentTarget)) return;\n            } else {\n                // magnetThreshold defined as a number of movements\n                if (paper.eventData(evt).mousemoved <= magnetThreshold) return;\n            }\n            this.dragLinkStart(evt, targetMagnet, x, y);\n        }\n    },\n\n    dragLinkEnd: function(evt, x, y) {\n        var data = this.eventData(evt);\n        var linkView = data.linkView;\n        if (!linkView) return;\n        linkView.pointerup(evt, x, y);\n        this.model.stopBatch('add-link');\n    },\n\n    getAttributeDefinition: function(attrName) {\n\n        return this.model.constructor.getAttributeDefinition(attrName);\n    },\n\n    setNodeAttributes: function(node, attrs) {\n\n        if (!isEmpty(attrs)) {\n            if (node instanceof SVGElement) {\n                V(node).attr(attrs);\n            } else {\n                $(node).attr(attrs);\n            }\n        }\n    },\n\n    processNodeAttributes: function(node, attrs) {\n\n        var attrName, attrVal, def, i, n;\n        var normalAttrs, setAttrs, positionAttrs, offsetAttrs;\n        var relatives = [];\n        const rawAttrs = {};\n        for (attrName in attrs) {\n            if (!attrs.hasOwnProperty(attrName)) continue;\n            rawAttrs[V.attributeNames[attrName]] = attrs[attrName];\n        }\n        // divide the attributes between normal and special\n        for (attrName in rawAttrs) {\n            if (!rawAttrs.hasOwnProperty(attrName)) continue;\n            attrVal = rawAttrs[attrName];\n            def = this.getAttributeDefinition(attrName);\n            if (def) {\n                if (attrVal === null) {\n                    // Assign the unset attribute name.\n                    let unsetAttrName;\n                    if (isFunction(def.unset)) {\n                        unsetAttrName = def.unset.call(this, node, rawAttrs, this);\n                    } else {\n                        unsetAttrName = def.unset;\n                    }\n                    if (!unsetAttrName && isString(def.set)) {\n                        // We unset an alias attribute.\n                        unsetAttrName = def.set;\n                    }\n                    if (!unsetAttrName) {\n                        // There is no alias for the attribute. We unset the attribute itself.\n                        unsetAttrName = attrName;\n                    }\n                    // Unset the attribute.\n                    if (isString(unsetAttrName) && unsetAttrName) {\n                        // Unset a single attribute.\n                        normalAttrs || (normalAttrs = {});\n                        // values takes precedence over unset values\n                        if (unsetAttrName in normalAttrs) continue;\n                        normalAttrs[unsetAttrName] = attrVal;\n                    } else if (Array.isArray(unsetAttrName) && unsetAttrName.length > 0) {\n                        // Unset multiple attributes.\n                        normalAttrs || (normalAttrs = {});\n                        for (i = 0, n = unsetAttrName.length; i < n; i++) {\n                            const attrName = unsetAttrName[i];\n                            // values takes precedence over unset values\n                            if (attrName in normalAttrs) continue;\n                            normalAttrs[attrName] = attrVal;\n                        }\n                    }\n                    // The unset value is neither a string nor an array.\n                    // The attribute is not unset.\n                } else {\n                    if (!isFunction(def.qualify) || def.qualify.call(this, attrVal, node, rawAttrs, this)) {\n                        if (isString(def.set)) {\n                            // An alias e.g 'xlink:href' -> 'href'\n                            normalAttrs || (normalAttrs = {});\n                            normalAttrs[def.set] = attrVal;\n                        }\n                        relatives.push(attrName, def);\n                    } else {\n                        normalAttrs || (normalAttrs = {});\n                        normalAttrs[attrName] = attrVal;\n                    }\n                }\n            } else {\n                normalAttrs || (normalAttrs = {});\n                normalAttrs[attrName] = attrVal;\n            }\n        }\n\n        // handle the rest of attributes via related method\n        // from the special attributes namespace.\n        for (i = 0, n = relatives.length; i < n; i+=2) {\n            attrName = relatives[i];\n            def = relatives[i+1];\n            attrVal = attrs[attrName];\n            if (isFunction(def.set)) {\n                setAttrs || (setAttrs = {});\n                setAttrs[attrName] = attrVal;\n            }\n            if (isFunction(def.position)) {\n                positionAttrs || (positionAttrs = {});\n                positionAttrs[attrName] = attrVal;\n            }\n            if (isFunction(def.offset)) {\n                offsetAttrs || (offsetAttrs = {});\n                offsetAttrs[attrName] = attrVal;\n            }\n        }\n\n        return {\n            raw: rawAttrs,\n            normal: normalAttrs,\n            set: setAttrs,\n            position: positionAttrs,\n            offset: offsetAttrs\n        };\n    },\n\n    updateRelativeAttributes: function(node, attrs, refBBox, opt) {\n\n        opt || (opt = {});\n\n        var attrName, attrVal, def;\n        var evalAttrs = evalAttributes(attrs.raw || {}, refBBox);\n        var nodeAttrs = attrs.normal || {};\n        for (const nodeAttrName in nodeAttrs) {\n            nodeAttrs[nodeAttrName] = evalAttrs[nodeAttrName];\n        }\n        var setAttrs = attrs.set;\n        var positionAttrs = attrs.position;\n        var offsetAttrs = attrs.offset;\n\n        for (attrName in setAttrs) {\n            attrVal = evalAttrs[attrName];\n            def = this.getAttributeDefinition(attrName);\n            // SET - set function should return attributes to be set on the node,\n            // which will affect the node dimensions based on the reference bounding\n            // box. e.g. `width`, `height`, `d`, `rx`, `ry`, `points\n            var setResult = def.set.call(this, attrVal, refBBox.clone(), node, evalAttrs, this);\n            if (isObject(setResult)) {\n                assign(nodeAttrs, setResult);\n            } else if (setResult !== undefined) {\n                nodeAttrs[attrName] = setResult;\n            }\n        }\n\n        if (node instanceof HTMLElement) {\n            // TODO: setting the `transform` attribute on HTMLElements\n            // via `node.style.transform = 'matrix(...)';` would introduce\n            // a breaking change (e.g. basic.TextBlock).\n            this.setNodeAttributes(node, nodeAttrs);\n            return;\n        }\n\n        // The final translation of the subelement.\n        var nodeTransform = nodeAttrs.transform;\n        var nodeMatrix = V.transformStringToMatrix(nodeTransform);\n        var nodePosition = Point(nodeMatrix.e, nodeMatrix.f);\n        if (nodeTransform) {\n            nodeAttrs = omit(nodeAttrs, 'transform');\n            nodeMatrix.e = nodeMatrix.f = 0;\n        }\n\n        // Calculate node scale determined by the scalable group\n        // only if later needed.\n        var sx, sy, translation;\n        if (positionAttrs || offsetAttrs) {\n            var nodeScale = this.getNodeScale(node, opt.scalableNode);\n            sx = nodeScale.sx;\n            sy = nodeScale.sy;\n        }\n\n        var positioned = false;\n        for (attrName in positionAttrs) {\n            attrVal = evalAttrs[attrName];\n            def = this.getAttributeDefinition(attrName);\n            // POSITION - position function should return a point from the\n            // reference bounding box. The default position of the node is x:0, y:0 of\n            // the reference bounding box or could be further specify by some\n            // SVG attributes e.g. `x`, `y`\n            translation = def.position.call(this, attrVal, refBBox.clone(), node, evalAttrs, this);\n            if (translation) {\n                nodePosition.offset(Point(translation).scale(sx, sy));\n                positioned || (positioned = true);\n            }\n        }\n\n        // The node bounding box could depend on the `size` set from the previous loop.\n        // Here we know, that all the size attributes have been already set.\n        this.setNodeAttributes(node, nodeAttrs);\n\n        var offseted = false;\n        if (offsetAttrs) {\n            // Check if the node is visible\n            var nodeBoundingRect = this.getNodeBoundingRect(node);\n            if (nodeBoundingRect.width > 0 && nodeBoundingRect.height > 0) {\n                var nodeBBox = V.transformRect(nodeBoundingRect, nodeMatrix).scale(1 / sx, 1 / sy);\n                for (attrName in offsetAttrs) {\n                    attrVal = evalAttrs[attrName];\n                    def = this.getAttributeDefinition(attrName);\n                    // OFFSET - offset function should return a point from the element\n                    // bounding box. The default offset point is x:0, y:0 (origin) or could be further\n                    // specify with some SVG attributes e.g. `text-anchor`, `cx`, `cy`\n                    translation = def.offset.call(this, attrVal, nodeBBox, node, evalAttrs, this);\n                    if (translation) {\n                        nodePosition.offset(Point(translation).scale(sx, sy));\n                        offseted || (offseted = true);\n                    }\n                }\n            }\n        }\n\n        // Do not touch node's transform attribute if there is no transformation applied.\n        if (nodeTransform !== undefined || positioned || offseted) {\n            // Round the coordinates to 1 decimal point.\n            nodePosition.round(1);\n            nodeMatrix.e = nodePosition.x;\n            nodeMatrix.f = nodePosition.y;\n            node.setAttribute('transform', V.matrixToTransformString(nodeMatrix));\n            // TODO: store nodeMatrix metrics?\n        }\n    },\n\n    getNodeScale: function(node, scalableNode) {\n\n        // Check if the node is a descendant of the scalable group.\n        var sx, sy;\n        if (scalableNode && scalableNode.contains(node)) {\n            var scale = scalableNode.scale();\n            sx = 1 / scale.sx;\n            sy = 1 / scale.sy;\n        } else {\n            sx = 1;\n            sy = 1;\n        }\n\n        return { sx: sx, sy: sy };\n    },\n\n    cleanNodesCache: function() {\n        this.metrics = {};\n    },\n\n    cleanNodeCache: function(node) {\n        const id = node.id;\n        if (!id) return;\n        delete this.metrics[id];\n    },\n\n    nodeCache: function(magnet) {\n\n        var metrics = this.metrics;\n        // Don't use cache? It most likely a custom view with overridden update.\n        if (!metrics) return {};\n        var id = V.ensureId(magnet);\n        var value = metrics[id];\n        if (!value) value = metrics[id] = {};\n        return value;\n    },\n\n    getNodeData: function(magnet) {\n\n        var metrics = this.nodeCache(magnet);\n        if (!metrics.data) metrics.data = {};\n        return metrics.data;\n    },\n\n    getNodeBoundingRect: function(magnet) {\n\n        var metrics = this.nodeCache(magnet);\n        if (metrics.boundingRect === undefined) metrics.boundingRect = V(magnet).getBBox();\n        return new Rect(metrics.boundingRect);\n    },\n\n    getNodeMatrix: function(magnet) {\n\n        const metrics = this.nodeCache(magnet);\n        if (metrics.magnetMatrix === undefined) {\n            const { rotatableNode, el } = this;\n            let target;\n            if (rotatableNode && rotatableNode.contains(magnet)) {\n                target = rotatableNode;\n            } else {\n                target = el;\n            }\n            metrics.magnetMatrix = V(magnet).getTransformToElement(target);\n        }\n        return V.createSVGMatrix(metrics.magnetMatrix);\n    },\n\n    getNodeShape: function(magnet) {\n\n        var metrics = this.nodeCache(magnet);\n        if (metrics.geometryShape === undefined) metrics.geometryShape = V(magnet).toGeometryShape();\n        return metrics.geometryShape.clone();\n    },\n\n    isNodeConnection: function(node) {\n        return this.model.isLink() && (!node || node === this.el);\n    },\n\n    findNodesAttributes: function(attrs, root, selectorCache, selectors) {\n\n        var i, n, nodeAttrs, nodeId;\n        var nodesAttrs = {};\n        var mergeIds = [];\n        for (var selector in attrs) {\n            if (!attrs.hasOwnProperty(selector)) continue;\n            nodeAttrs = attrs[selector];\n            if (!isPlainObject(nodeAttrs)) continue; // Not a valid selector-attributes pair\n            var selected = selectorCache[selector] = this.findBySelector(selector, root, selectors);\n            for (i = 0, n = selected.length; i < n; i++) {\n                var node = selected[i];\n                nodeId = V.ensureId(node);\n                // \"unique\" selectors are selectors that referencing a single node (defined by `selector`)\n                // groupSelector referencing a single node is not \"unique\"\n                var unique = (selectors && selectors[selector] === node);\n                var prevNodeAttrs = nodesAttrs[nodeId];\n                if (prevNodeAttrs) {\n                    // Note, that nodes referenced by deprecated `CSS selectors` are not taken into account.\n                    // e.g. css:`.circle` and selector:`circle` can be applied in a random order\n                    if (!prevNodeAttrs.array) {\n                        mergeIds.push(nodeId);\n                        prevNodeAttrs.array = true;\n                        prevNodeAttrs.attributes = [prevNodeAttrs.attributes];\n                        prevNodeAttrs.selectedLength = [prevNodeAttrs.selectedLength];\n                    }\n                    var attributes = prevNodeAttrs.attributes;\n                    var selectedLength = prevNodeAttrs.selectedLength;\n                    if (unique) {\n                        // node referenced by `selector`\n                        attributes.unshift(nodeAttrs);\n                        selectedLength.unshift(-1);\n                    } else {\n                        // node referenced by `groupSelector`\n                        var sortIndex = sortedIndex(selectedLength, n);\n                        attributes.splice(sortIndex, 0, nodeAttrs);\n                        selectedLength.splice(sortIndex, 0, n);\n                    }\n                } else {\n                    nodesAttrs[nodeId] = {\n                        attributes: nodeAttrs,\n                        selectedLength: unique ? -1 : n,\n                        node: node,\n                        array: false\n                    };\n                }\n            }\n        }\n\n        for (i = 0, n = mergeIds.length; i < n; i++) {\n            nodeId = mergeIds[i];\n            nodeAttrs = nodesAttrs[nodeId];\n            nodeAttrs.attributes = merge({}, ...nodeAttrs.attributes.reverse());\n        }\n\n        return nodesAttrs;\n    },\n\n    getEventTarget: function(evt, opt = {}) {\n        const { target, type, clientX = 0, clientY = 0 } = evt;\n        if (\n            // Explicitly defined `fromPoint` option\n            opt.fromPoint ||\n            // Touchmove/Touchend event's target is not reflecting the element under the coordinates as mousemove does.\n            // It holds the element when a touchstart triggered.\n            type === 'touchmove' || type === 'touchend' ||\n            // Pointermove/Pointerup event with the pointer captured\n            ('pointerId' in evt && target.hasPointerCapture(evt.pointerId))\n        ) {\n            return document.elementFromPoint(clientX, clientY);\n        }\n\n        return target;\n    },\n\n    // Default is to process the `model.attributes.attrs` object and set attributes on subelements based on the selectors,\n    // unless `attrs` parameter was passed.\n    updateDOMSubtreeAttributes: function(rootNode, attrs, opt) {\n\n        opt || (opt = {});\n        opt.rootBBox || (opt.rootBBox = Rect());\n        opt.selectors || (opt.selectors = this.selectors); // selector collection to use\n\n        // Cache table for query results and bounding box calculation.\n        // Note that `selectorCache` needs to be invalidated for all\n        // `updateAttributes` calls, as the selectors might pointing\n        // to nodes designated by an attribute or elements dynamically\n        // created.\n        var selectorCache = {};\n        var bboxCache = {};\n        var relativeItems = [];\n        var relativeRefItems = [];\n        var item, node, nodeAttrs, nodeData, processedAttrs;\n\n        var roAttrs = opt.roAttributes;\n        var nodesAttrs = this.findNodesAttributes(roAttrs || attrs, rootNode, selectorCache, opt.selectors);\n        // `nodesAttrs` are different from all attributes, when\n        // rendering only  attributes sent to this method.\n        var nodesAllAttrs = (roAttrs)\n            ? this.findNodesAttributes(attrs, rootNode, selectorCache, opt.selectors)\n            : nodesAttrs;\n\n        for (var nodeId in nodesAttrs) {\n            nodeData = nodesAttrs[nodeId];\n            nodeAttrs = nodeData.attributes;\n            node = nodeData.node;\n            processedAttrs = this.processNodeAttributes(node, nodeAttrs);\n\n            if (!processedAttrs.set && !processedAttrs.position && !processedAttrs.offset && !processedAttrs.raw.ref) {\n                // Set all the normal attributes right on the SVG/HTML element.\n                this.setNodeAttributes(node, evalAttributes(processedAttrs.normal, opt.rootBBox));\n\n            } else {\n\n                var nodeAllAttrs = nodesAllAttrs[nodeId] && nodesAllAttrs[nodeId].attributes;\n                var refSelector = (nodeAllAttrs && (nodeAttrs.ref === undefined))\n                    ? nodeAllAttrs.ref\n                    : nodeAttrs.ref;\n\n                var refNode;\n                if (refSelector) {\n                    refNode = (selectorCache[refSelector] || this.findBySelector(refSelector, rootNode, opt.selectors))[0];\n                    if (!refNode) {\n                        throw new Error('dia.CellView: \"' + refSelector + '\" reference does not exist.');\n                    }\n                } else {\n                    refNode = null;\n                }\n\n                item = {\n                    node: node,\n                    refNode: refNode,\n                    processedAttributes: processedAttrs,\n                    allAttributes: nodeAllAttrs\n                };\n\n                if (refNode) {\n                    // If an element in the list is positioned relative to this one, then\n                    // we want to insert this one before it in the list.\n                    var itemIndex = relativeRefItems.findIndex(function(item) {\n                        return item.refNode === node;\n                    });\n\n                    if (itemIndex > -1) {\n                        relativeRefItems.splice(itemIndex, 0, item);\n                    } else {\n                        relativeRefItems.push(item);\n                    }\n                } else {\n                    // A node with no ref attribute. To be updated before the nodes referencing other nodes.\n                    // The order of no-ref-items is not specified/important.\n                    relativeItems.push(item);\n                }\n            }\n        }\n\n        relativeItems.push(...relativeRefItems);\n\n        for (let i = 0, n = relativeItems.length; i < n; i++) {\n            item = relativeItems[i];\n            node = item.node;\n            refNode = item.refNode;\n\n            // Find the reference element bounding box. If no reference was provided, we\n            // use the optional bounding box.\n            const refNodeId = refNode ? V.ensureId(refNode) : '';\n            let refBBox = bboxCache[refNodeId];\n            if (!refBBox) {\n                // Get the bounding box of the reference element using to the common ancestor\n                // transformation space.\n                //\n                // @example 1\n                // <g transform=\"translate(11, 13)\">\n                //     <rect @selector=\"b\" x=\"1\" y=\"2\" width=\"3\" height=\"4\"/>\n                //     <rect @selector=\"a\"/>\n                // </g>\n                //\n                // In this case, the reference bounding box can not be affected\n                // by the `transform` attribute of the `<g>` element,\n                // because the exact transformation will be applied to the `a` element\n                // as well as to the `b` element.\n                //\n                // @example 2\n                // <g transform=\"translate(11, 13)\">\n                //     <rect @selector=\"b\" x=\"1\" y=\"2\" width=\"3\" height=\"4\"/>\n                // </g>\n                // <rect @selector=\"a\"/>\n                //\n                // In this case, the reference bounding box have to be affected by the\n                // `transform` attribute of the `<g>` element, because the `a` element\n                // is not descendant of the `<g>` element and will not be affected\n                // by the transformation.\n                refBBox = bboxCache[refNodeId] = (refNode)\n                    ? V(refNode).getBBox({ target: getCommonAncestorNode(node, refNode) })\n                    : opt.rootBBox;\n            }\n\n            if (roAttrs) {\n                // if there was a special attribute affecting the position amongst passed-in attributes\n                // we have to merge it with the rest of the element's attributes as they are necessary\n                // to update the position relatively (i.e `ref-x` && 'ref-dx')\n                processedAttrs = this.processNodeAttributes(node, item.allAttributes);\n                this.mergeProcessedAttributes(processedAttrs, item.processedAttributes);\n\n            } else {\n                processedAttrs = item.processedAttributes;\n            }\n\n            this.updateRelativeAttributes(node, processedAttrs, refBBox, opt);\n        }\n    },\n\n    mergeProcessedAttributes: function(processedAttrs, roProcessedAttrs) {\n\n        processedAttrs.set || (processedAttrs.set = {});\n        processedAttrs.position || (processedAttrs.position = {});\n        processedAttrs.offset || (processedAttrs.offset = {});\n\n        assign(processedAttrs.set, roProcessedAttrs.set);\n        assign(processedAttrs.position, roProcessedAttrs.position);\n        assign(processedAttrs.offset, roProcessedAttrs.offset);\n\n        // Handle also the special transform property.\n        var transform = processedAttrs.normal && processedAttrs.normal.transform;\n        if (transform !== undefined && roProcessedAttrs.normal) {\n            roProcessedAttrs.normal.transform = transform;\n        }\n        processedAttrs.normal = roProcessedAttrs.normal;\n    },\n\n    // Lifecycle methods\n\n    // Called when the view is attached to the DOM,\n    // as result of `cell.addTo(graph)` being called (isInitialMount === true)\n    // or `paper.options.viewport` returning `true` (isInitialMount === false).\n    onMount(isInitialMount) {\n        if (isInitialMount) return;\n        this.mountTools();\n        HighlighterView.mount(this);\n    },\n\n    // Called when the view is detached from the DOM,\n    // as result of `paper.options.viewport` returning `false`.\n    onDetach() {\n        this.unmountTools();\n        HighlighterView.unmount(this);\n    },\n\n    // Called when the view is removed from the DOM\n    // as result of `cell.remove()`.\n    onRemove: function() {\n        this.removeTools();\n        this.removeHighlighters();\n    },\n\n    _toolsView: null,\n\n    hasTools: function(name) {\n        var toolsView = this._toolsView;\n        if (!toolsView) return false;\n        if (!name) return true;\n        return (toolsView.getName() === name);\n    },\n\n    addTools: function(toolsView) {\n\n        this.removeTools();\n\n        if (toolsView) {\n            this._toolsView = toolsView;\n            toolsView.configure({ relatedView: this });\n            toolsView.listenTo(this.paper, 'tools:event', this.onToolEvent.bind(this));\n        }\n        return this;\n    },\n\n    unmountTools() {\n        const toolsView = this._toolsView;\n        if (toolsView) toolsView.unmount();\n        return this;\n    },\n\n    mountTools() {\n        const toolsView = this._toolsView;\n        // Prevent unnecessary re-appending of the tools.\n        if (toolsView && !toolsView.isMounted()) toolsView.mount();\n        return this;\n    },\n\n    updateTools: function(opt) {\n\n        var toolsView = this._toolsView;\n        if (toolsView) toolsView.update(opt);\n        return this;\n    },\n\n    removeTools: function() {\n\n        var toolsView = this._toolsView;\n        if (toolsView) {\n            toolsView.remove();\n            this._toolsView = null;\n        }\n        return this;\n    },\n\n    hideTools: function() {\n\n        var toolsView = this._toolsView;\n        if (toolsView) toolsView.hide();\n        return this;\n    },\n\n    showTools: function() {\n\n        var toolsView = this._toolsView;\n        if (toolsView) toolsView.show();\n        return this;\n    },\n\n    onToolEvent: function(event) {\n        switch (event) {\n            case 'remove':\n                this.removeTools();\n                break;\n            case 'hide':\n                this.hideTools();\n                break;\n            case 'show':\n                this.showTools();\n                break;\n        }\n    },\n\n    removeHighlighters: function() {\n        HighlighterView.remove(this);\n    },\n\n    updateHighlighters: function(dirty = false) {\n        HighlighterView.update(this, null, dirty);\n    },\n\n    transformHighlighters: function() {\n        HighlighterView.transform(this);\n    },\n\n    // Interaction. The controller part.\n    // ---------------------------------\n\n    preventDefaultInteraction(evt) {\n        this.eventData(evt, { defaultInteractionPrevented: true  });\n    },\n\n    isDefaultInteractionPrevented(evt) {\n        const { defaultInteractionPrevented = false } = this.eventData(evt);\n        return defaultInteractionPrevented;\n    },\n\n    // Interaction is handled by the paper and delegated to the view in interest.\n    // `x` & `y` parameters passed to these functions represent the coordinates already snapped to the paper grid.\n    // If necessary, real coordinates can be obtained from the `evt` event object.\n\n    // These functions are supposed to be overridden by the views that inherit from `joint.dia.Cell`,\n    // i.e. `joint.dia.Element` and `joint.dia.Link`.\n\n    pointerdblclick: function(evt, x, y) {\n\n        this.notify('cell:pointerdblclick', evt, x, y);\n    },\n\n    pointerclick: function(evt, x, y) {\n\n        this.notify('cell:pointerclick', evt, x, y);\n    },\n\n    contextmenu: function(evt, x, y) {\n\n        this.notify('cell:contextmenu', evt, x, y);\n    },\n\n    pointerdown: function(evt, x, y) {\n\n        const { model } = this;\n        const { graph } = model;\n        if (graph) {\n            model.startBatch('pointer');\n            this.eventData(evt, { graph });\n        }\n\n        this.notify('cell:pointerdown', evt, x, y);\n    },\n\n    pointermove: function(evt, x, y) {\n\n        this.notify('cell:pointermove', evt, x, y);\n    },\n\n    pointerup: function(evt, x, y) {\n\n        const { graph } = this.eventData(evt);\n\n        this.notify('cell:pointerup', evt, x, y);\n\n        if (graph) {\n            // we don't want to trigger event on model as model doesn't\n            // need to be member of collection anymore (remove)\n            graph.stopBatch('pointer', { cell: this.model });\n        }\n    },\n\n    mouseover: function(evt) {\n\n        this.notify('cell:mouseover', evt);\n    },\n\n    mouseout: function(evt) {\n\n        this.notify('cell:mouseout', evt);\n    },\n\n    mouseenter: function(evt) {\n\n        this.notify('cell:mouseenter', evt);\n    },\n\n    mouseleave: function(evt) {\n\n        this.notify('cell:mouseleave', evt);\n    },\n\n    mousewheel: function(evt, x, y, delta) {\n\n        this.notify('cell:mousewheel', evt, x, y, delta);\n    },\n\n    onevent: function(evt, eventName, x, y) {\n\n        this.notify(eventName, evt, x, y);\n    },\n\n    onmagnet: function() {\n\n        // noop\n    },\n\n    magnetpointerdblclick: function() {\n\n        // noop\n    },\n\n    magnetcontextmenu: function() {\n\n        // noop\n    },\n\n    checkMouseleave(evt) {\n        const { paper, model } = this;\n        if (paper.isAsync()) {\n            // Make sure the source/target views are updated before this view.\n            // It's not 100% bulletproof (see below) but it's a good enough solution for now.\n            // The connected cells could be links as well. In that case, we would\n            // need to recursively go through all the connected links and update\n            // their source/target views as well.\n            if (model.isLink()) {\n                // The `this.sourceView` and `this.targetView` might not be updated yet.\n                // We need to find the view by the model.\n                const sourceElement = model.getSourceElement();\n                if (sourceElement) {\n                    const sourceView = paper.findViewByModel(sourceElement);\n                    if (sourceView) {\n                        paper.dumpView(sourceView);\n                        paper.checkViewVisibility(sourceView);\n                    }\n                }\n                const targetElement = model.getTargetElement();\n                if (targetElement) {\n                    const targetView = paper.findViewByModel(targetElement);\n                    if (targetView) {\n                        paper.dumpView(targetView);\n                        paper.checkViewVisibility(targetView);\n                    }\n                }\n            }\n            // Do the updates of the current view synchronously now\n            paper.dumpView(this);\n            paper.checkViewVisibility(this);\n        }\n        const target = this.getEventTarget(evt, { fromPoint: true });\n        const view = paper.findView(target);\n        if (view === this) return;\n        // Leaving the current view\n        this.mouseleave(evt);\n        if (!view) return;\n        // Entering another view\n        view.mouseenter(evt);\n    },\n\n    setInteractivity: function(value) {\n\n        this.options.interactive = value;\n    },\n\n    isIntersecting: function(geometryShape, geometryData) {\n        return intersection.exists(geometryShape, this.getNodeBBox(this.el), geometryData);\n    },\n\n    isEnclosedIn: function(geometryRect) {\n        return geometryRect.containsRect(this.getNodeBBox(this.el));\n    },\n\n    isInArea: function(geometryRect, options = {}) {\n        if (options.strict) {\n            return this.isEnclosedIn(geometryRect);\n        }\n        return this.isIntersecting(geometryRect);\n    },\n\n    isAtPoint: function(point, options) {\n        return this.getNodeBBox(this.el).containsPoint(point, options);\n    }\n\n}, {\n\n    Flags,\n\n    Highlighting: HighlightingTypes,\n\n    addPresentationAttributes: function(presentationAttributes) {\n        return merge({}, result(this.prototype, 'presentationAttributes'), presentationAttributes, function(a, b) {\n            if (!a || !b) return;\n            if (typeof a === 'string') a = [a];\n            if (typeof b === 'string') b = [b];\n            if (Array.isArray(a) && Array.isArray(b)) return uniq(a.concat(b));\n        });\n    },\n\n    evalAttribute,\n\n});\n\n\nObject.defineProperty(CellView.prototype, 'useCSSSelectors', {\n    get() {\n        const localUse = this.model.useCSSSelectors;\n        if (localUse !== undefined) return localUse;\n        return config.useCSSSelectors;\n    }\n});\n\n// TODO: Move to Vectorizer library.\nfunction getCommonAncestorNode(node1, node2) {\n    let parent = node1;\n    do {\n        if (parent.contains(node2)) return parent;\n        parent = parent.parentNode;\n    } while (parent);\n    return null;\n}\n\n\n","import { assign, isFunction, toArray } from '../util/index.mjs';\nimport { CellView } from './CellView.mjs';\nimport { Cell } from './Cell.mjs';\nimport V from '../V/index.mjs';\nimport { elementViewPortPrototype } from './ports.mjs';\nimport { Rect, snapToGrid } from '../g/index.mjs';\n\nconst Flags = {\n    TOOLS: CellView.Flags.TOOLS,\n    UPDATE: 'UPDATE',\n    TRANSLATE: 'TRANSLATE',\n    RESIZE: 'RESIZE',\n    PORTS: 'PORTS',\n    ROTATE: 'ROTATE',\n    RENDER: 'RENDER'\n};\n\nconst DragActions = {\n    MOVE: 'move',\n    MAGNET: 'magnet',\n};\n// Element base view and controller.\n// -------------------------------------------\n\nexport const ElementView = CellView.extend({\n\n    /**\n     * @abstract\n     */\n    _removePorts: function() {\n        // implemented in ports.js\n    },\n\n    /**\n     *\n     * @abstract\n     */\n    _renderPorts: function() {\n        // implemented in ports.js\n    },\n\n    className: function() {\n\n        var classNames = CellView.prototype.className.apply(this).split(' ');\n\n        classNames.push('element');\n\n        return classNames.join(' ');\n    },\n\n    initialize: function() {\n\n        CellView.prototype.initialize.apply(this, arguments);\n\n        this._initializePorts();\n    },\n\n    presentationAttributes: {\n        'attrs': [Flags.UPDATE],\n        'position': [Flags.TRANSLATE, Flags.TOOLS],\n        'size': [Flags.RESIZE, Flags.PORTS, Flags.TOOLS],\n        'angle': [Flags.ROTATE, Flags.TOOLS],\n        'markup': [Flags.RENDER],\n        'ports': [Flags.PORTS],\n    },\n\n    initFlag: [Flags.RENDER],\n\n    UPDATE_PRIORITY: 0,\n\n    confirmUpdate: function(flag, opt) {\n\n        const { useCSSSelectors } = this;\n        if (this.hasFlag(flag, Flags.PORTS)) {\n            this._removePorts();\n            this._cleanPortsCache();\n        }\n        let transformHighlighters = false;\n        if (this.hasFlag(flag, Flags.RENDER)) {\n            this.render();\n            this.updateTools(opt);\n            this.updateHighlighters(true);\n            transformHighlighters = true;\n            flag = this.removeFlag(flag, [Flags.RENDER, Flags.UPDATE, Flags.RESIZE, Flags.TRANSLATE, Flags.ROTATE, Flags.PORTS, Flags.TOOLS]);\n        } else {\n            let updateHighlighters = false;\n\n            // Skip this branch if render is required\n            if (this.hasFlag(flag, Flags.RESIZE)) {\n                this.resize(opt);\n                updateHighlighters = true;\n                // Resize method is calling `update()` internally\n                flag = this.removeFlag(flag, [Flags.RESIZE, Flags.UPDATE]);\n                if (useCSSSelectors) {\n                    // `resize()` rendered the ports when useCSSSelectors are enabled\n                    flag = this.removeFlag(flag, Flags.PORTS);\n                }\n            }\n            if (this.hasFlag(flag, Flags.UPDATE)) {\n                this.update(this.model, null, opt);\n                flag = this.removeFlag(flag, Flags.UPDATE);\n                updateHighlighters = true;\n                if (useCSSSelectors) {\n                    // `update()` will render ports when useCSSSelectors are enabled\n                    flag = this.removeFlag(flag, Flags.PORTS);\n                }\n            }\n            if (this.hasFlag(flag, Flags.TRANSLATE)) {\n                this.translate();\n                flag = this.removeFlag(flag, Flags.TRANSLATE);\n                transformHighlighters = true;\n            }\n            if (this.hasFlag(flag, Flags.ROTATE)) {\n                this.rotate();\n                flag = this.removeFlag(flag, Flags.ROTATE);\n                transformHighlighters = true;\n            }\n            if (this.hasFlag(flag, Flags.PORTS)) {\n                this._renderPorts();\n                updateHighlighters = true;\n                flag = this.removeFlag(flag, Flags.PORTS);\n            }\n\n            if (updateHighlighters) {\n                this.updateHighlighters(false);\n            }\n        }\n\n        if (transformHighlighters) {\n            this.transformHighlighters();\n        }\n\n        if (this.hasFlag(flag, Flags.TOOLS)) {\n            this.updateTools(opt);\n            flag = this.removeFlag(flag, Flags.TOOLS);\n        }\n\n        return flag;\n    },\n\n    /**\n     * @abstract\n     */\n    _initializePorts: function() {\n\n    },\n\n    update: function(_, renderingOnlyAttrs) {\n\n        this.cleanNodesCache();\n\n        // When CSS selector strings are used, make sure no rule matches port nodes.\n        const { useCSSSelectors } = this;\n        if (useCSSSelectors) this._removePorts();\n\n        var model = this.model;\n        var modelAttrs = model.attr();\n        this.updateDOMSubtreeAttributes(this.el, modelAttrs, {\n            rootBBox: new Rect(model.size()),\n            selectors: this.selectors,\n            scalableNode: this.scalableNode,\n            rotatableNode: this.rotatableNode,\n            // Use rendering only attributes if they differs from the model attributes\n            roAttributes: (renderingOnlyAttrs === modelAttrs) ? null : renderingOnlyAttrs\n        });\n\n        if (useCSSSelectors) {\n            this._renderPorts();\n        }\n    },\n\n    rotatableSelector: 'rotatable',\n    scalableSelector: 'scalable',\n    scalableNode: null,\n    rotatableNode: null,\n\n    // `prototype.markup` is rendered by default. Set the `markup` attribute on the model if the\n    // default markup is not desirable.\n    renderMarkup: function() {\n\n        var element = this.model;\n        var markup = element.get('markup') || element.markup;\n        if (!markup) throw new Error('dia.ElementView: markup required');\n        if (Array.isArray(markup)) return this.renderJSONMarkup(markup);\n        if (typeof markup === 'string') return this.renderStringMarkup(markup);\n        throw new Error('dia.ElementView: invalid markup');\n    },\n\n    renderJSONMarkup: function(markup) {\n\n        var doc = this.parseDOMJSON(markup, this.el);\n        var selectors = this.selectors = doc.selectors;\n        this.rotatableNode = V(selectors[this.rotatableSelector]) || null;\n        this.scalableNode = V(selectors[this.scalableSelector]) || null;\n        // Fragment\n        this.vel.append(doc.fragment);\n    },\n\n    renderStringMarkup: function(markup) {\n\n        var vel = this.vel;\n        vel.append(V(markup));\n        // Cache transformation groups\n        this.rotatableNode = vel.findOne('.rotatable');\n        this.scalableNode = vel.findOne('.scalable');\n\n        var selectors = this.selectors = {};\n        selectors[this.selector] = this.el;\n    },\n\n    render: function() {\n\n        this.vel.empty();\n        this.renderMarkup();\n        if (this.scalableNode) {\n            // Double update is necessary for elements with the scalable group only\n            // Note the resize() triggers the other `update`.\n            this.update();\n        }\n        this.resize();\n        if (this.rotatableNode) {\n            // Translate transformation is applied on `this.el` while the rotation transformation\n            // on `this.rotatableNode`\n            this.rotate();\n            this.translate();\n        } else {\n            this.updateTransformation();\n        }\n        if (!this.useCSSSelectors) this._renderPorts();\n        return this;\n    },\n\n    resize: function(opt) {\n\n        if (this.scalableNode) return this.sgResize(opt);\n        if (this.model.attributes.angle) this.rotate();\n        this.update();\n    },\n\n    translate: function() {\n\n        if (this.rotatableNode) return this.rgTranslate();\n        this.updateTransformation();\n    },\n\n    rotate: function() {\n\n        if (this.rotatableNode) {\n            this.rgRotate();\n            // It's necessary to call the update for the nodes outside\n            // the rotatable group referencing nodes inside the group\n            this.update();\n            return;\n        }\n        this.updateTransformation();\n    },\n\n    updateTransformation: function() {\n\n        var transformation = this.getTranslateString();\n        var rotateString = this.getRotateString();\n        if (rotateString) transformation += ' ' + rotateString;\n        this.vel.attr('transform', transformation);\n    },\n\n    getTranslateString: function() {\n\n        const { x, y } = this.model.position();\n        return `translate(${x},${y})`;\n    },\n\n    getRotateString: function() {\n\n        const angle = this.model.angle();\n        if (!angle) return null;\n        const { width, height } = this.model.size();\n        return `rotate(${angle},${width / 2},${height / 2})`;\n    },\n\n    // Rotatable & Scalable Group\n    // always slower, kept mainly for backwards compatibility\n\n    rgRotate: function() {\n\n        this.rotatableNode.attr('transform', this.getRotateString());\n    },\n\n    rgTranslate: function() {\n\n        this.vel.attr('transform', this.getTranslateString());\n    },\n\n    sgResize: function(opt) {\n\n        var model = this.model;\n        var angle = model.angle();\n        var size = model.size();\n        var scalable = this.scalableNode;\n\n        // Getting scalable group's bbox.\n        // Due to a bug in webkit's native SVG .getBBox implementation, the bbox of groups with path children includes the paths' control points.\n        // To work around the issue, we need to check whether there are any path elements inside the scalable group.\n        var recursive = false;\n        if (scalable.node.getElementsByTagName('path').length > 0) {\n            // If scalable has at least one descendant that is a path, we need to switch to recursive bbox calculation.\n            // If there are no path descendants, group bbox calculation works and so we can use the (faster) native function directly.\n            recursive = true;\n        }\n        var scalableBBox = scalable.getBBox({ recursive: recursive });\n\n        // Make sure `scalableBbox.width` and `scalableBbox.height` are not zero which can happen if the element does not have any content. By making\n        // the width/height 1, we prevent HTML errors of the type `scale(Infinity, Infinity)`.\n        var sx = (size.width / (scalableBBox.width || 1));\n        var sy = (size.height / (scalableBBox.height || 1));\n        scalable.attr('transform', 'scale(' + sx + ',' + sy + ')');\n\n        // Now the interesting part. The goal is to be able to store the object geometry via just `x`, `y`, `angle`, `width` and `height`\n        // Order of transformations is significant but we want to reconstruct the object always in the order:\n        // resize(), rotate(), translate() no matter of how the object was transformed. For that to work,\n        // we must adjust the `x` and `y` coordinates of the object whenever we resize it (because the origin of the\n        // rotation changes). The new `x` and `y` coordinates are computed by canceling the previous rotation\n        // around the center of the resized object (which is a different origin then the origin of the previous rotation)\n        // and getting the top-left corner of the resulting object. Then we clean up the rotation back to what it originally was.\n\n        // Cancel the rotation but now around a different origin, which is the center of the scaled object.\n        var rotatable = this.rotatableNode;\n        var rotation = rotatable && rotatable.attr('transform');\n        if (rotation) {\n\n            rotatable.attr('transform', rotation + ' rotate(' + (-angle) + ',' + (size.width / 2) + ',' + (size.height / 2) + ')');\n            var rotatableBBox = scalable.getBBox({ target: this.paper.cells });\n\n            // Store new x, y and perform rotate() again against the new rotation origin.\n            model.set('position', { x: rotatableBBox.x, y: rotatableBBox.y }, assign({ updateHandled: true }, opt));\n            this.translate();\n            this.rotate();\n        }\n\n        // Update must always be called on non-rotated element. Otherwise, relative positioning\n        // would work with wrong (rotated) bounding boxes.\n        this.update();\n    },\n\n    // Embedding mode methods.\n    // -----------------------\n\n    prepareEmbedding: function(data = {}) {\n\n        const element = data.model || this.model;\n        const paper = data.paper || this.paper;\n        const graph = paper.model;\n\n        const initialZIndices = data.initialZIndices = {};\n        const embeddedCells = element.getEmbeddedCells({ deep: true });\n        const connectedLinks = graph.getConnectedLinks(element, { deep: true, includeEnclosed: true });\n\n        // Note: an embedded cell can be a connect link, but it's fine\n        // to iterate over the cell twice.\n        [\n            element,\n            ...embeddedCells,\n            ...connectedLinks\n        ].forEach(cell => initialZIndices[cell.id] = cell.attributes.z);\n\n        element.startBatch('to-front');\n\n        // Bring the model to the front with all his embeds.\n        element.toFront({ deep: true, ui: true });\n\n        // Note that at this point cells in the collection are not sorted by z index (it's running in the batch, see\n        // the dia.Graph._sortOnChangeZ), so we can't assume that the last cell in the collection has the highest z.\n        const maxZ = graph.getElements().reduce((max, cell) => Math.max(max, cell.attributes.z || 0), 0);\n\n        // Move to front also all the inbound and outbound links that are connected\n        // to any of the element descendant. If we bring to front only embedded elements,\n        // links connected to them would stay in the background.\n        connectedLinks.forEach((link) => {\n            if (link.attributes.z <= maxZ) {\n                link.set('z', maxZ + 1, { ui: true });\n            }\n        });\n\n        element.stopBatch('to-front');\n\n        // Before we start looking for suitable parent we remove the current one.\n        const parentId = element.parent();\n        if (parentId) {\n            const parent = graph.getCell(parentId);\n            parent.unembed(element, { ui: true });\n            data.initialParentId = parentId;\n        } else {\n            data.initialParentId = null;\n        }\n    },\n\n    processEmbedding: function(data = {}, evt, x, y) {\n\n        const model = data.model || this.model;\n        const paper = data.paper || this.paper;\n        const graph = paper.model;\n        const { findParentBy, frontParentOnly, validateEmbedding } = paper.options;\n\n        let candidates;\n        if (isFunction(findParentBy)) {\n            candidates = toArray(findParentBy.call(graph, this, evt, x, y));\n        } else if (findParentBy === 'pointer') {\n            candidates = graph.findElementsAtPoint({ x, y });\n        } else {\n            candidates = graph.findElementsUnderElement(model, { searchBy: findParentBy });\n        }\n\n        candidates = candidates.filter((el) => {\n            return (el instanceof Cell) && (model.id !== el.id) && !el.isEmbeddedIn(model);\n        });\n\n        if (frontParentOnly) {\n            // pick the element with the highest `z` index\n            candidates = candidates.slice(-1);\n        }\n\n        let newCandidateView = null;\n        const prevCandidateView = data.candidateEmbedView;\n\n        // iterate over all candidates starting from the last one (has the highest z-index).\n        for (let i = candidates.length - 1; i >= 0; i--) {\n            const candidate = candidates[i];\n            if (prevCandidateView && prevCandidateView.model.id == candidate.id) {\n                // candidate remains the same\n                newCandidateView = prevCandidateView;\n                break;\n            } else {\n                const view = candidate.findView(paper);\n                if (!isFunction(validateEmbedding) || validateEmbedding.call(paper, this, view)) {\n                    // flip to the new candidate\n                    newCandidateView = view;\n                    break;\n                }\n            }\n        }\n\n        if (newCandidateView && newCandidateView != prevCandidateView) {\n            // A new candidate view found. Highlight the new one.\n            this.clearEmbedding(data);\n            data.candidateEmbedView = newCandidateView.highlight(\n                newCandidateView.findProxyNode(null, 'container'),\n                { embedding: true }\n            );\n        }\n\n        if (!newCandidateView && prevCandidateView) {\n            // No candidate view found. Unhighlight the previous candidate.\n            this.clearEmbedding(data);\n        }\n    },\n\n    clearEmbedding: function(data) {\n\n        data || (data = {});\n\n        var candidateView = data.candidateEmbedView;\n        if (candidateView) {\n            // No candidate view found. Unhighlight the previous candidate.\n            candidateView.unhighlight(\n                candidateView.findProxyNode(null, 'container'),\n                { embedding: true }\n            );\n            data.candidateEmbedView = null;\n        }\n    },\n\n    finalizeEmbedding: function(data = {}) {\n\n        const candidateView = data.candidateEmbedView;\n        const element = data.model || this.model;\n        const paper = data.paper || this.paper;\n\n        if (candidateView) {\n\n            // We finished embedding. Candidate view is chosen to become the parent of the model.\n            candidateView.model.embed(element, { ui: true });\n            candidateView.unhighlight(candidateView.findProxyNode(null, 'container'), { embedding: true });\n\n            data.candidateEmbedView = null;\n\n        } else {\n\n            const { validateUnembedding } = paper.options;\n            const { initialParentId } = data;\n            // The element was originally embedded into another element.\n            // The interaction would unembed the element. Let's validate\n            // if the element can be unembedded.\n            if (\n                initialParentId &&\n                typeof validateUnembedding === 'function' &&\n                !validateUnembedding.call(paper, this)\n            ) {\n                this._disallowUnembed(data);\n                return;\n            }\n        }\n\n        paper.model.getConnectedLinks(element, { deep: true }).forEach(link => {\n            link.reparent({ ui: true });\n        });\n    },\n\n    _disallowUnembed: function(data) {\n        const { model, whenNotAllowed = 'revert' } = data;\n        const element = model || this.model;\n        const paper = data.paper || this.paper;\n        const graph = paper.model;\n        switch (whenNotAllowed) {\n            case 'remove': {\n                element.remove({ ui: true });\n                break;\n            }\n            case 'revert': {\n                const { initialParentId, initialPosition, initialZIndices } = data;\n                // Revert the element's position (and the position of its embedded cells if any)\n                if (initialPosition) {\n                    const { x, y } = initialPosition;\n                    element.position(x, y, { deep: true, ui: true });\n                }\n                // Revert all the z-indices changed during the embedding\n                if (initialZIndices) {\n                    Object.keys(initialZIndices).forEach(id => {\n                        const cell = graph.getCell(id);\n                        if (cell) {\n                            cell.set('z', initialZIndices[id], { ui: true });\n                        }\n                    });\n                }\n                // Revert the original parent\n                const parent = graph.getCell(initialParentId);\n                if (parent) {\n                    parent.embed(element, { ui: true });\n                }\n                break;\n            }\n        }\n    },\n\n    getTargetParentView: function(evt) {\n        const { candidateEmbedView = null } = this.eventData(evt);\n        return candidateEmbedView;\n    },\n\n    getDelegatedView: function() {\n\n        var view = this;\n        var model = view.model;\n        var paper = view.paper;\n\n        while (view) {\n            if (model.isLink()) break;\n            if (!model.isEmbedded() || view.can('stopDelegation')) return view;\n            model = model.getParentCell();\n            view = paper.findViewByModel(model);\n        }\n\n        return null;\n    },\n\n    findProxyNode: function(el, type) {\n        el || (el = this.el);\n        const nodeSelector = el.getAttribute(`${type}-selector`);\n        if (nodeSelector) {\n            const port = this.findAttribute('port', el);\n            if (port) {\n                const proxyPortNode = this.findPortNode(port, nodeSelector);\n                if (proxyPortNode) return proxyPortNode;\n            } else {\n                const proxyNode = this.findNode(nodeSelector);\n                if (proxyNode) return proxyNode;\n            }\n        }\n        return el;\n    },\n\n    // Interaction. The controller part.\n    // ---------------------------------\n\n    notifyPointerdown(evt, x, y) {\n        CellView.prototype.pointerdown.call(this, evt, x, y);\n        this.notify('element:pointerdown', evt, x, y);\n    },\n\n    notifyPointermove(evt, x, y) {\n        CellView.prototype.pointermove.call(this, evt, x, y);\n        this.notify('element:pointermove', evt, x, y);\n    },\n\n    notifyPointerup(evt, x, y) {\n        this.notify('element:pointerup', evt, x, y);\n        CellView.prototype.pointerup.call(this, evt, x, y);\n    },\n\n    pointerdblclick: function(evt, x, y) {\n\n        CellView.prototype.pointerdblclick.apply(this, arguments);\n        this.notify('element:pointerdblclick', evt, x, y);\n    },\n\n    pointerclick: function(evt, x, y) {\n\n        CellView.prototype.pointerclick.apply(this, arguments);\n        this.notify('element:pointerclick', evt, x, y);\n    },\n\n    contextmenu: function(evt, x, y) {\n\n        CellView.prototype.contextmenu.apply(this, arguments);\n        this.notify('element:contextmenu', evt, x, y);\n    },\n\n    pointerdown: function(evt, x, y) {\n\n        this.notifyPointerdown(evt, x, y);\n        this.dragStart(evt, x, y);\n    },\n\n    pointermove: function(evt, x, y) {\n\n        const data = this.eventData(evt);\n        const { targetMagnet, action, delegatedView } = data;\n\n        if (targetMagnet) {\n            this.magnetpointermove(evt, targetMagnet, x, y);\n        }\n\n        switch (action) {\n            case DragActions.MAGNET:\n                this.dragMagnet(evt, x, y);\n                break;\n            case DragActions.MOVE:\n                (delegatedView || this).drag(evt, x, y);\n            // eslint: no-fallthrough=false\n            default:\n                if (data.preventPointerEvents) break;\n                this.notifyPointermove(evt, x, y);\n                break;\n        }\n\n        // Make sure the element view data is passed along.\n        // It could have been wiped out in the handlers above.\n        this.eventData(evt, data);\n    },\n\n    pointerup: function(evt, x, y) {\n\n        const data = this.eventData(evt);\n        const { targetMagnet, action, delegatedView } = data;\n\n        if (targetMagnet) {\n            this.magnetpointerup(evt, targetMagnet, x, y);\n        }\n\n        switch (action) {\n            case DragActions.MAGNET:\n                this.dragMagnetEnd(evt, x, y);\n                break;\n            case DragActions.MOVE:\n                (delegatedView || this).dragEnd(evt, x, y);\n            // eslint: no-fallthrough=false\n            default:\n                if (data.preventPointerEvents) break;\n                this.notifyPointerup(evt, x, y);\n        }\n\n        if (targetMagnet) {\n            this.magnetpointerclick(evt, targetMagnet, x, y);\n        }\n\n        this.checkMouseleave(evt);\n    },\n\n    mouseover: function(evt) {\n\n        CellView.prototype.mouseover.apply(this, arguments);\n        this.notify('element:mouseover', evt);\n    },\n\n    mouseout: function(evt) {\n\n        CellView.prototype.mouseout.apply(this, arguments);\n        this.notify('element:mouseout', evt);\n    },\n\n    mouseenter: function(evt) {\n\n        CellView.prototype.mouseenter.apply(this, arguments);\n        this.notify('element:mouseenter', evt);\n    },\n\n    mouseleave: function(evt) {\n\n        CellView.prototype.mouseleave.apply(this, arguments);\n        this.notify('element:mouseleave', evt);\n    },\n\n    mousewheel: function(evt, x, y, delta) {\n\n        CellView.prototype.mousewheel.apply(this, arguments);\n        this.notify('element:mousewheel', evt, x, y, delta);\n    },\n\n    onmagnet: function(evt, x, y) {\n\n        const { currentTarget: targetMagnet } = evt;\n        this.magnetpointerdown(evt, targetMagnet, x, y);\n        this.eventData(evt, { targetMagnet });\n        this.dragMagnetStart(evt, x, y);\n    },\n\n    magnetpointerdown: function(evt, magnet, x, y) {\n\n        this.notify('element:magnet:pointerdown', evt, magnet, x, y);\n    },\n\n    magnetpointermove: function(evt, magnet, x, y) {\n\n        this.notify('element:magnet:pointermove', evt, magnet, x, y);\n    },\n\n    magnetpointerup: function(evt, magnet, x, y) {\n\n        this.notify('element:magnet:pointerup', evt, magnet, x, y);\n    },\n\n    magnetpointerdblclick: function(evt, magnet, x, y) {\n\n        this.notify('element:magnet:pointerdblclick', evt, magnet, x, y);\n    },\n\n    magnetcontextmenu: function(evt, magnet, x, y) {\n\n        this.notify('element:magnet:contextmenu', evt, magnet, x, y);\n    },\n\n    // Drag Start Handlers\n\n    dragStart: function(evt, x, y) {\n\n        if (this.isDefaultInteractionPrevented(evt)) return;\n\n        var view = this.getDelegatedView();\n        if (!view || !view.can('elementMove')) return;\n\n        this.eventData(evt, {\n            action: DragActions.MOVE,\n            delegatedView: view\n        });\n\n        const position = view.model.position();\n        view.eventData(evt, {\n            initialPosition: position,\n            pointerOffset: position.difference(x, y),\n            restrictedArea: this.paper.getRestrictedArea(view, x, y)\n        });\n    },\n\n    dragMagnetStart: function(evt, x, y) {\n\n        const { paper } = this;\n        const isPropagationAlreadyStopped = evt.isPropagationStopped();\n        if (isPropagationAlreadyStopped) {\n            // Special case when the propagation was already stopped\n            // on the `element:magnet:pointerdown` event.\n            // Do not trigger any `element:pointer*` events\n            // but still start the magnet dragging.\n            this.eventData(evt, { preventPointerEvents: true });\n        }\n\n        if (this.isDefaultInteractionPrevented(evt) || !this.can('addLinkFromMagnet')) {\n            // Stop the default action, which is to start dragging a link.\n            return;\n        }\n\n        const { targetMagnet = evt.currentTarget } = this.eventData(evt);\n        evt.stopPropagation();\n\n        // Invalid (Passive) magnet. Start dragging the element.\n        if (!paper.options.validateMagnet.call(paper, this, targetMagnet, evt)) {\n            if (isPropagationAlreadyStopped) {\n                // Do not trigger `element:pointerdown` and start element dragging\n                // if the propagation was stopped.\n                this.dragStart(evt, x, y);\n                // The `element:pointerdown` event is not triggered because\n                // of `preventPointerEvents` flag.\n            } else {\n                // We need to reset the action\n                // to `MOVE` so that the element is dragged.\n                this.pointerdown(evt, x, y);\n            }\n            return;\n        }\n\n        // Valid magnet. Start dragging a link.\n        if (paper.options.magnetThreshold <= 0) {\n            this.dragLinkStart(evt, targetMagnet, x, y);\n        }\n        this.eventData(evt, { action: DragActions.MAGNET });\n    },\n\n    // Drag Handlers\n\n    drag: function(evt, x, y) {\n\n        var paper = this.paper;\n        var grid = paper.options.gridSize;\n        var element = this.model;\n        var data = this.eventData(evt);\n        var { pointerOffset, restrictedArea, embedding } = data;\n\n        // Make sure the new element's position always snaps to the current grid\n        var elX = snapToGrid(x + pointerOffset.x, grid);\n        var elY = snapToGrid(y + pointerOffset.y, grid);\n\n        element.position(elX, elY, { restrictedArea, deep: true, ui: true });\n\n        if (paper.options.embeddingMode) {\n            if (!embedding) {\n                // Prepare the element for embedding only if the pointer moves.\n                // We don't want to do unnecessary action with the element\n                // if an user only clicks/dblclicks on it.\n                this.prepareEmbedding(data);\n                embedding = true;\n            }\n            this.processEmbedding(data, evt, x, y);\n        }\n\n        this.eventData(evt, {\n            embedding\n        });\n    },\n\n    dragMagnet: function(evt, x, y) {\n        this.dragLink(evt, x, y);\n    },\n\n    // Drag End Handlers\n\n    dragEnd: function(evt, x, y) {\n\n        var data = this.eventData(evt);\n        if (data.embedding) this.finalizeEmbedding(data);\n    },\n\n    dragMagnetEnd: function(evt, x, y) {\n        this.dragLinkEnd(evt, x, y);\n    },\n\n    magnetpointerclick: function(evt, magnet, x, y) {\n        var paper = this.paper;\n        if (paper.eventData(evt).mousemoved > paper.options.clickThreshold) return;\n        this.notify('element:magnet:pointerclick', evt, magnet, x, y);\n    }\n\n}, {\n\n    Flags: Flags,\n});\n\nassign(ElementView.prototype, elementViewPortPrototype);\n","// Does not make any changes to vertices.\n// Returns the arguments that are passed to it, unchanged.\nexport const normal = function(vertices, opt, linkView) {\n\n    return vertices;\n};\n","import * as util from '../util/index.mjs';\n\n// Routes the link always to/from a certain side\n//\n// Arguments:\n//   padding ... gap between the element and the first vertex. :: Default 40.\n//   side ... 'left' | 'right' | 'top' | 'bottom' :: Default 'bottom'.\n//\nexport const oneSide = function(vertices, opt, linkView) {\n\n    var side = opt.side || 'bottom';\n    var padding = util.normalizeSides(opt.padding || 40);\n\n    // LinkView contains cached source an target bboxes.\n    // Note that those are Geometry rectangle objects.\n    var sourceBBox = linkView.sourceBBox;\n    var targetBBox = linkView.targetBBox;\n    var sourcePoint = sourceBBox.center();\n    var targetPoint = targetBBox.center();\n\n    var coordinate, dimension, direction;\n\n    switch (side) {\n        case 'bottom':\n            direction = 1;\n            coordinate = 'y';\n            dimension = 'height';\n            break;\n        case 'top':\n            direction = -1;\n            coordinate = 'y';\n            dimension = 'height';\n            break;\n        case 'left':\n            direction = -1;\n            coordinate = 'x';\n            dimension = 'width';\n            break;\n        case 'right':\n            direction = 1;\n            coordinate = 'x';\n            dimension = 'width';\n            break;\n        default:\n            throw new Error('Router: invalid side');\n    }\n\n    // move the points from the center of the element to outside of it.\n    sourcePoint[coordinate] += direction * (sourceBBox[dimension] / 2 + padding[side]);\n    targetPoint[coordinate] += direction * (targetBBox[dimension] / 2 + padding[side]);\n\n    // make link orthogonal (at least the first and last vertex).\n    if ((direction * (sourcePoint[coordinate] - targetPoint[coordinate])) > 0) {\n        targetPoint[coordinate] = sourcePoint[coordinate];\n    } else {\n        sourcePoint[coordinate] = targetPoint[coordinate];\n    }\n\n    return [sourcePoint].concat(vertices, targetPoint);\n};\n","import * as g from '../g/index.mjs';\nimport * as util from '../util/index.mjs';\n\n// bearing -> opposite bearing\nvar opposites = {\n    N: 'S',\n    S: 'N',\n    E: 'W',\n    W: 'E'\n};\n\n// bearing -> radians\nvar radians = {\n    N: -Math.PI / 2 * 3,\n    S: -Math.PI / 2,\n    E: 0,\n    W: Math.PI\n};\n\n// HELPERS //\n\n// returns a point `p` where lines p,p1 and p,p2 are perpendicular and p is not contained\n// in the given box\nfunction freeJoin(p1, p2, bbox) {\n\n    var p = new g.Point(p1.x, p2.y);\n    if (bbox.containsPoint(p)) p = new g.Point(p2.x, p1.y);\n    // kept for reference\n    // if (bbox.containsPoint(p)) p = null;\n\n    return p;\n}\n\n// returns either width or height of a bbox based on the given bearing\nfunction getBBoxSize(bbox, bearing) {\n\n    return bbox[(bearing === 'W' || bearing === 'E') ? 'width' : 'height'];\n}\n\n// simple bearing method (calculates only orthogonal cardinals)\nfunction getBearing(from, to) {\n\n    if (from.x === to.x) return (from.y > to.y) ? 'N' : 'S';\n    if (from.y === to.y) return (from.x > to.x) ? 'W' : 'E';\n    return null;\n}\n\n// transform point to a rect\nfunction getPointBox(p) {\n\n    return new g.Rect(p.x, p.y, 0, 0);\n}\n\nfunction getPaddingBox(opt) {\n\n    // if both provided, opt.padding wins over opt.elementPadding\n    var sides = util.normalizeSides(opt.padding || opt.elementPadding || 20);\n\n    return {\n        x: -sides.left,\n        y: -sides.top,\n        width: sides.left + sides.right,\n        height: sides.top + sides.bottom\n    };\n}\n\n// return source bbox\nfunction getSourceBBox(linkView, opt) {\n\n    return linkView.sourceBBox.clone().moveAndExpand(getPaddingBox(opt));\n}\n\n// return target bbox\nfunction getTargetBBox(linkView, opt) {\n\n    return linkView.targetBBox.clone().moveAndExpand(getPaddingBox(opt));\n}\n\n// return source anchor\nfunction getSourceAnchor(linkView, opt) {\n\n    if (linkView.sourceAnchor) return linkView.sourceAnchor;\n\n    // fallback: center of bbox\n    var sourceBBox = getSourceBBox(linkView, opt);\n    return sourceBBox.center();\n}\n\n// return target anchor\nfunction getTargetAnchor(linkView, opt) {\n\n    if (linkView.targetAnchor) return linkView.targetAnchor;\n\n    // fallback: center of bbox\n    var targetBBox = getTargetBBox(linkView, opt);\n    return targetBBox.center(); // default\n}\n\n// PARTIAL ROUTERS //\n\nfunction vertexVertex(from, to, bearing) {\n\n    var p1 = new g.Point(from.x, to.y);\n    var p2 = new g.Point(to.x, from.y);\n    var d1 = getBearing(from, p1);\n    var d2 = getBearing(from, p2);\n    var opposite = opposites[bearing];\n\n    var p = (d1 === bearing || (d1 !== opposite && (d2 === opposite || d2 !== bearing))) ? p1 : p2;\n\n    return { points: [p], direction: getBearing(p, to) };\n}\n\nfunction elementVertex(from, to, fromBBox) {\n\n    var p = freeJoin(from, to, fromBBox);\n\n    return { points: [p], direction: getBearing(p, to) };\n}\n\nfunction vertexElement(from, to, toBBox, bearing) {\n\n    var route = {};\n\n    var points = [new g.Point(from.x, to.y), new g.Point(to.x, from.y)];\n    var freePoints = points.filter(function(pt) {\n        return !toBBox.containsPoint(pt);\n    });\n    var freeBearingPoints = freePoints.filter(function(pt) {\n        return getBearing(pt, from) !== bearing;\n    });\n\n    var p;\n\n    if (freeBearingPoints.length > 0) {\n        // Try to pick a point which bears the same direction as the previous segment.\n\n        p = freeBearingPoints.filter(function(pt) {\n            return getBearing(from, pt) === bearing;\n        }).pop();\n        p = p || freeBearingPoints[0];\n\n        route.points = [p];\n        route.direction = getBearing(p, to);\n\n    } else {\n        // Here we found only points which are either contained in the element or they would create\n        // a link segment going in opposite direction from the previous one.\n        // We take the point inside element and move it outside the element in the direction the\n        // route is going. Now we can join this point with the current end (using freeJoin).\n\n        p = util.difference(points, freePoints)[0];\n\n        var p2 = (new g.Point(to)).move(p, -getBBoxSize(toBBox, bearing) / 2);\n        var p1 = freeJoin(p2, from, toBBox);\n\n        route.points = [p1, p2];\n        route.direction = getBearing(p2, to);\n    }\n\n    return route;\n}\n\nfunction elementElement(from, to, fromBBox, toBBox) {\n\n    var route = elementVertex(to, from, toBBox);\n    var p1 = route.points[0];\n\n    if (fromBBox.containsPoint(p1)) {\n\n        route = elementVertex(from, to, fromBBox);\n        var p2 = route.points[0];\n\n        if (toBBox.containsPoint(p2)) {\n\n            var fromBorder = (new g.Point(from)).move(p2, -getBBoxSize(fromBBox, getBearing(from, p2)) / 2);\n            var toBorder = (new g.Point(to)).move(p1, -getBBoxSize(toBBox, getBearing(to, p1)) / 2);\n            var mid = (new g.Line(fromBorder, toBorder)).midpoint();\n\n            var startRoute = elementVertex(from, mid, fromBBox);\n            var endRoute = vertexVertex(mid, to, startRoute.direction);\n\n            route.points = [startRoute.points[0], endRoute.points[0]];\n            route.direction = endRoute.direction;\n        }\n    }\n\n    return route;\n}\n\n// Finds route for situations where one element is inside the other.\n// Typically the route is directed outside the outer element first and\n// then back towards the inner element.\nfunction insideElement(from, to, fromBBox, toBBox, bearing) {\n\n    var route = {};\n    var boundary = fromBBox.union(toBBox).inflate(1);\n\n    // start from the point which is closer to the boundary\n    var reversed = boundary.center().distance(to) > boundary.center().distance(from);\n    var start = reversed ? to : from;\n    var end = reversed ? from : to;\n\n    var p1, p2, p3;\n\n    if (bearing) {\n        // Points on circle with radius equals 'W + H` are always outside the rectangle\n        // with width W and height H if the center of that circle is the center of that rectangle.\n        p1 = g.Point.fromPolar(boundary.width + boundary.height, radians[bearing], start);\n        p1 = boundary.pointNearestToPoint(p1).move(p1, -1);\n\n    } else {\n        p1 = boundary.pointNearestToPoint(start).move(start, 1);\n    }\n\n    p2 = freeJoin(p1, end, boundary);\n\n    if (p1.round().equals(p2.round())) {\n        p2 = g.Point.fromPolar(boundary.width + boundary.height, g.toRad(p1.theta(start)) + Math.PI / 2, end);\n        p2 = boundary.pointNearestToPoint(p2).move(end, 1).round();\n        p3 = freeJoin(p1, p2, boundary);\n        route.points = reversed ? [p2, p3, p1] : [p1, p3, p2];\n\n    } else {\n        route.points = reversed ? [p2, p1] : [p1, p2];\n    }\n\n    route.direction = reversed ? getBearing(p1, to) : getBearing(p2, to);\n\n    return route;\n}\n\n// MAIN ROUTER //\n\n// Return points through which a connection needs to be drawn in order to obtain an orthogonal link\n// routing from source to target going through `vertices`.\nexport function orthogonal(vertices, opt, linkView) {\n\n    var sourceBBox = getSourceBBox(linkView, opt);\n    var targetBBox = getTargetBBox(linkView, opt);\n\n    var sourceAnchor = getSourceAnchor(linkView, opt);\n    var targetAnchor = getTargetAnchor(linkView, opt);\n\n    // if anchor lies outside of bbox, the bbox expands to include it\n    sourceBBox = sourceBBox.union(getPointBox(sourceAnchor));\n    targetBBox = targetBBox.union(getPointBox(targetAnchor));\n\n    vertices = util.toArray(vertices).map(g.Point);\n    vertices.unshift(sourceAnchor);\n    vertices.push(targetAnchor);\n\n    var bearing; // bearing of previous route segment\n\n    var orthogonalVertices = []; // the array of found orthogonal vertices to be returned\n    for (var i = 0, max = vertices.length - 1; i < max; i++) {\n\n        var route = null;\n\n        var from = vertices[i];\n        var to = vertices[i + 1];\n\n        var isOrthogonal = !!getBearing(from, to);\n\n        if (i === 0) { // source\n\n            if (i + 1 === max) { // route source -> target\n\n                // Expand one of the elements by 1px to detect situations when the two\n                // elements are positioned next to each other with no gap in between.\n                if (sourceBBox.intersect(targetBBox.clone().inflate(1))) {\n                    route = insideElement(from, to, sourceBBox, targetBBox);\n\n                } else if (!isOrthogonal) {\n                    route = elementElement(from, to, sourceBBox, targetBBox);\n                }\n\n            } else { // route source -> vertex\n\n                if (sourceBBox.containsPoint(to)) {\n                    route = insideElement(from, to, sourceBBox, getPointBox(to).moveAndExpand(getPaddingBox(opt)));\n\n                } else if (!isOrthogonal) {\n                    route = elementVertex(from, to, sourceBBox);\n                }\n            }\n\n        } else if (i + 1 === max) { // route vertex -> target\n\n            // prevent overlaps with previous line segment\n            var isOrthogonalLoop = isOrthogonal && getBearing(to, from) === bearing;\n\n            if (targetBBox.containsPoint(from) || isOrthogonalLoop) {\n                route = insideElement(from, to, getPointBox(from).moveAndExpand(getPaddingBox(opt)), targetBBox, bearing);\n\n            } else if (!isOrthogonal) {\n                route = vertexElement(from, to, targetBBox, bearing);\n            }\n\n        } else if (!isOrthogonal) { // route vertex -> vertex\n            route = vertexVertex(from, to, bearing);\n        }\n\n        // applicable to all routes:\n\n        // set bearing for next iteration\n        if (route) {\n            Array.prototype.push.apply(orthogonalVertices, route.points);\n            bearing = route.direction;\n\n        } else {\n            // orthogonal route and not looped\n            bearing = getBearing(from, to);\n        }\n\n        // push `to` point to identified orthogonal vertices array\n        if (i + 1 < max) {\n            orthogonalVertices.push(to);\n        }\n    }\n\n    return orthogonalVertices;\n}\n","import * as g from '../g/index.mjs';\nimport * as util from '../util/index.mjs';\nimport { orthogonal } from './orthogonal.mjs';\n\nvar config = {\n\n    // size of the step to find a route (the grid of the manhattan pathfinder)\n    step: 10,\n\n    // the number of route finding loops that cause the router to abort\n    // returns fallback route instead\n    maximumLoops: 2000,\n\n    // the number of decimal places to round floating point coordinates\n    precision: 1,\n\n    // maximum change of direction\n    maxAllowedDirectionChange: 90,\n\n    // should the router use perpendicular linkView option?\n    // does not connect anchor of element but rather a point close-by that is orthogonal\n    // this looks much better\n    perpendicular: true,\n\n    // should the source and/or target not be considered as obstacles?\n    excludeEnds: [], // 'source', 'target'\n\n    // should certain types of elements not be considered as obstacles?\n    excludeTypes: [],\n\n    // possible starting directions from an element\n    startDirections: ['top', 'right', 'bottom', 'left'],\n\n    // possible ending directions to an element\n    endDirections: ['top', 'right', 'bottom', 'left'],\n\n    // specify the directions used above and what they mean\n    directionMap: {\n        top: { x: 0, y: -1 },\n        right: { x: 1, y: 0 },\n        bottom: { x: 0, y: 1 },\n        left: { x: -1, y: 0 }\n    },\n\n    // cost of an orthogonal step\n    cost: function() {\n\n        return this.step;\n    },\n\n    // an array of directions to find next points on the route\n    // different from start/end directions\n    directions: function() {\n\n        var step = this.step;\n        var cost = this.cost();\n\n        return [\n            { offsetX: step, offsetY: 0, cost: cost },\n            { offsetX: -step, offsetY: 0, cost: cost },\n            { offsetX: 0, offsetY: step, cost: cost },\n            { offsetX: 0, offsetY: -step, cost: cost }\n        ];\n    },\n\n    // a penalty received for direction change\n    penalties: function() {\n\n        return {\n            0: 0,\n            45: this.step / 2,\n            90: this.step / 2\n        };\n    },\n\n    // padding applied on the element bounding boxes\n    paddingBox: function() {\n\n        var step = this.step;\n\n        return {\n            x: -step,\n            y: -step,\n            width: 2 * step,\n            height: 2 * step\n        };\n    },\n\n    // A function that determines whether a given point is an obstacle or not.\n    // If used, the `padding`, `excludeEnds`and `excludeTypes` options are ignored.\n    // (point: dia.Point) => boolean;\n    isPointObstacle: null,\n\n    // a router to use when the manhattan router fails\n    // (one of the partial routes returns null)\n    fallbackRouter: function(vertices, opt, linkView) {\n\n        if (!util.isFunction(orthogonal)) {\n            throw new Error('Manhattan requires the orthogonal router as default fallback.');\n        }\n\n        return orthogonal(vertices, util.assign({}, config, opt), linkView);\n    },\n\n    /* Deprecated */\n    // a simple route used in situations when main routing method fails\n    // (exceed max number of loop iterations, inaccessible)\n    fallbackRoute: function(from, to, opt) {\n\n        return null; // null result will trigger the fallbackRouter\n\n        // left for reference:\n        /*// Find an orthogonal route ignoring obstacles.\n\n        var point = ((opt.previousDirAngle || 0) % 180 === 0)\n                ? new g.Point(from.x, to.y)\n                : new g.Point(to.x, from.y);\n\n        return [point];*/\n    },\n\n    // if a function is provided, it's used to route the link while dragging an end\n    // i.e. function(from, to, opt) { return []; }\n    draggingRoute: null\n};\n\n// HELPER CLASSES //\n\n// Map of obstacles\n// Helper structure to identify whether a point lies inside an obstacle.\nfunction ObstacleMap(opt) {\n\n    this.map = {};\n    this.options = opt;\n    // tells how to divide the paper when creating the elements map\n    this.mapGridSize = 100;\n}\n\nObstacleMap.prototype.build = function(graph, link) {\n\n    var opt = this.options;\n\n    // source or target element could be excluded from set of obstacles\n    var excludedEnds = util.toArray(opt.excludeEnds).reduce(function(res, item) {\n\n        var end = link.get(item);\n        if (end) {\n            var cell = graph.getCell(end.id);\n            if (cell) {\n                res.push(cell);\n            }\n        }\n\n        return res;\n    }, []);\n\n    // Exclude any embedded elements from the source and the target element.\n    var excludedAncestors = [];\n\n    var source = graph.getCell(link.get('source').id);\n    if (source) {\n        excludedAncestors = util.union(excludedAncestors, source.getAncestors().map(function(cell) {\n            return cell.id;\n        }));\n    }\n\n    var target = graph.getCell(link.get('target').id);\n    if (target) {\n        excludedAncestors = util.union(excludedAncestors, target.getAncestors().map(function(cell) {\n            return cell.id;\n        }));\n    }\n\n    // Builds a map of all elements for quicker obstacle queries (i.e. is a point contained\n    // in any obstacle?) (a simplified grid search).\n    // The paper is divided into smaller cells, where each holds information about which\n    // elements belong to it. When we query whether a point lies inside an obstacle we\n    // don't need to go through all obstacles, we check only those in a particular cell.\n    var mapGridSize = this.mapGridSize;\n\n    graph.getElements().reduce(function(map, element) {\n\n        var isExcludedType = util.toArray(opt.excludeTypes).includes(element.get('type'));\n        var isExcludedEnd = excludedEnds.find(function(excluded) {\n            return excluded.id === element.id;\n        });\n        var isExcludedAncestor = excludedAncestors.includes(element.id);\n\n        var isExcluded = isExcludedType || isExcludedEnd || isExcludedAncestor;\n        if (!isExcluded) {\n            var bbox = element.getBBox().moveAndExpand(opt.paddingBox);\n\n            var origin = bbox.origin().snapToGrid(mapGridSize);\n            var corner = bbox.corner().snapToGrid(mapGridSize);\n\n            for (var x = origin.x; x <= corner.x; x += mapGridSize) {\n                for (var y = origin.y; y <= corner.y; y += mapGridSize) {\n                    var gridKey = x + '@' + y;\n                    map[gridKey] = map[gridKey] || [];\n                    map[gridKey].push(bbox);\n                }\n            }\n        }\n\n        return map;\n    }, this.map);\n\n    return this;\n};\n\nObstacleMap.prototype.isPointAccessible = function(point) {\n\n    var mapKey = point.clone().snapToGrid(this.mapGridSize).toString();\n\n    return util.toArray(this.map[mapKey]).every(function(obstacle) {\n        return !obstacle.containsPoint(point);\n    });\n};\n\n// Sorted Set\n// Set of items sorted by given value.\nfunction SortedSet() {\n    this.items = [];\n    this.hash = {};\n    this.values = {};\n    this.OPEN = 1;\n    this.CLOSE = 2;\n}\n\nSortedSet.prototype.add = function(item, value) {\n\n    if (this.hash[item]) {\n        // item removal\n        this.items.splice(this.items.indexOf(item), 1);\n    } else {\n        this.hash[item] = this.OPEN;\n    }\n\n    this.values[item] = value;\n\n    var index = util.sortedIndex(this.items, item, function(i) {\n        return this.values[i];\n    }.bind(this));\n\n    this.items.splice(index, 0, item);\n};\n\nSortedSet.prototype.remove = function(item) {\n\n    this.hash[item] = this.CLOSE;\n};\n\nSortedSet.prototype.isOpen = function(item) {\n\n    return this.hash[item] === this.OPEN;\n};\n\nSortedSet.prototype.isClose = function(item) {\n\n    return this.hash[item] === this.CLOSE;\n};\n\nSortedSet.prototype.isEmpty = function() {\n\n    return this.items.length === 0;\n};\n\nSortedSet.prototype.pop = function() {\n\n    var item = this.items.shift();\n    this.remove(item);\n    return item;\n};\n\n// HELPERS //\n\n// return source bbox\nfunction getSourceBBox(linkView, opt) {\n\n    // expand by padding box\n    if (opt && opt.paddingBox) return linkView.sourceBBox.clone().moveAndExpand(opt.paddingBox);\n\n    return linkView.sourceBBox.clone();\n}\n\n// return target bbox\nfunction getTargetBBox(linkView, opt) {\n\n    // expand by padding box\n    if (opt && opt.paddingBox) return linkView.targetBBox.clone().moveAndExpand(opt.paddingBox);\n\n    return linkView.targetBBox.clone();\n}\n\n// return source anchor\nfunction getSourceAnchor(linkView, opt) {\n\n    if (linkView.sourceAnchor) return linkView.sourceAnchor;\n\n    // fallback: center of bbox\n    var sourceBBox = getSourceBBox(linkView, opt);\n    return sourceBBox.center();\n}\n\n// return target anchor\nfunction getTargetAnchor(linkView, opt) {\n\n    if (linkView.targetAnchor) return linkView.targetAnchor;\n\n    // fallback: center of bbox\n    var targetBBox = getTargetBBox(linkView, opt);\n    return targetBBox.center(); // default\n}\n\n// returns a direction index from start point to end point\n// corrects for grid deformation between start and end\nfunction getDirectionAngle(start, end, numDirections, grid, opt) {\n\n    var quadrant = 360 / numDirections;\n    var angleTheta = start.theta(fixAngleEnd(start, end, grid, opt));\n    var normalizedAngle = g.normalizeAngle(angleTheta + (quadrant / 2));\n    return quadrant * Math.floor(normalizedAngle / quadrant);\n}\n\n// helper function for getDirectionAngle()\n// corrects for grid deformation\n// (if a point is one grid steps away from another in both dimensions,\n// it is considered to be 45 degrees away, even if the real angle is different)\n// this causes visible angle discrepancies if `opt.step` is much larger than `paper.gridSize`\nfunction fixAngleEnd(start, end, grid, opt) {\n\n    var step = opt.step;\n\n    var diffX = end.x - start.x;\n    var diffY = end.y - start.y;\n\n    var gridStepsX = diffX / grid.x;\n    var gridStepsY = diffY / grid.y;\n\n    var distanceX = gridStepsX * step;\n    var distanceY = gridStepsY * step;\n\n    return new g.Point(start.x + distanceX, start.y + distanceY);\n}\n\n// return the change in direction between two direction angles\nfunction getDirectionChange(angle1, angle2) {\n\n    var directionChange = Math.abs(angle1 - angle2);\n    return (directionChange > 180) ? (360 - directionChange) : directionChange;\n}\n\n// fix direction offsets according to current grid\nfunction getGridOffsets(directions, grid, opt) {\n\n    var step = opt.step;\n\n    util.toArray(opt.directions).forEach(function(direction) {\n\n        direction.gridOffsetX = (direction.offsetX / step) * grid.x;\n        direction.gridOffsetY = (direction.offsetY / step) * grid.y;\n    });\n}\n\n// get grid size in x and y dimensions, adapted to source and target positions\nfunction getGrid(step, source, target) {\n\n    return {\n        source: source.clone(),\n        x: getGridDimension(target.x - source.x, step),\n        y: getGridDimension(target.y - source.y, step)\n    };\n}\n\n// helper function for getGrid()\nfunction getGridDimension(diff, step) {\n\n    // return step if diff = 0\n    if (!diff) return step;\n\n    var absDiff = Math.abs(diff);\n    var numSteps = Math.round(absDiff / step);\n\n    // return absDiff if less than one step apart\n    if (!numSteps) return absDiff;\n\n    // otherwise, return corrected step\n    var roundedDiff = numSteps * step;\n    var remainder = absDiff - roundedDiff;\n    var stepCorrection = remainder / numSteps;\n\n    return step + stepCorrection;\n}\n\n// return a clone of point snapped to grid\nfunction snapToGrid(point, grid) {\n\n    var source = grid.source;\n\n    var snappedX = g.snapToGrid(point.x - source.x, grid.x) + source.x;\n    var snappedY = g.snapToGrid(point.y - source.y, grid.y) + source.y;\n\n    return new g.Point(snappedX, snappedY);\n}\n\n// round the point to opt.precision\nfunction round(point, precision) {\n\n    return point.round(precision);\n}\n\n// snap to grid and then round the point\nfunction align(point, grid, precision) {\n\n    return round(snapToGrid(point.clone(), grid), precision);\n}\n\n// return a string representing the point\n// string is rounded in both dimensions\nfunction getKey(point) {\n\n    return point.clone().toString();\n}\n\n// return a normalized vector from given point\n// used to determine the direction of a difference of two points\nfunction normalizePoint(point) {\n\n    return new g.Point(\n        point.x === 0 ? 0 : Math.abs(point.x) / point.x,\n        point.y === 0 ? 0 : Math.abs(point.y) / point.y\n    );\n}\n\n// PATHFINDING //\n\n// reconstructs a route by concatenating points with their parents\nfunction reconstructRoute(parents, points, tailPoint, from, to, grid, opt) {\n\n    var route = [];\n\n    var prevDiff = normalizePoint(to.difference(tailPoint));\n\n    // tailPoint is assumed to be aligned already\n    var currentKey = getKey(tailPoint);\n    var parent = parents[currentKey];\n\n    var point;\n    while (parent) {\n\n        // point is assumed to be aligned already\n        point = points[currentKey];\n\n        var diff = normalizePoint(point.difference(parent));\n        if (!diff.equals(prevDiff)) {\n            route.unshift(point);\n            prevDiff = diff;\n        }\n\n        // parent is assumed to be aligned already\n        currentKey = getKey(parent);\n        parent = parents[currentKey];\n    }\n\n    // leadPoint is assumed to be aligned already\n    var leadPoint = points[currentKey];\n\n    var fromDiff = normalizePoint(leadPoint.difference(from));\n    if (!fromDiff.equals(prevDiff)) {\n        route.unshift(leadPoint);\n    }\n\n    return route;\n}\n\n// heuristic method to determine the distance between two points\nfunction estimateCost(from, endPoints) {\n\n    var min = Infinity;\n\n    for (var i = 0, len = endPoints.length; i < len; i++) {\n        var cost = from.manhattanDistance(endPoints[i]);\n        if (cost < min) min = cost;\n    }\n\n    return min;\n}\n\n// find points around the bbox taking given directions into account\n// lines are drawn from anchor in given directions, intersections recorded\n// if anchor is outside bbox, only those directions that intersect get a rect point\n// the anchor itself is returned as rect point (representing some directions)\n// (since those directions are unobstructed by the bbox)\nfunction getRectPoints(anchor, bbox, directionList, grid, opt) {\n\n    var precision = opt.precision;\n    var directionMap = opt.directionMap;\n\n    var anchorCenterVector = anchor.difference(bbox.center());\n\n    var keys = util.isObject(directionMap) ? Object.keys(directionMap) : [];\n    var dirList = util.toArray(directionList);\n    var rectPoints = keys.reduce(function(res, key) {\n\n        if (dirList.includes(key)) {\n            var direction = directionMap[key];\n\n            // create a line that is guaranteed to intersect the bbox if bbox is in the direction\n            // even if anchor lies outside of bbox\n            var endpoint = new g.Point(\n                anchor.x + direction.x * (Math.abs(anchorCenterVector.x) + bbox.width),\n                anchor.y + direction.y * (Math.abs(anchorCenterVector.y) + bbox.height)\n            );\n            var intersectionLine = new g.Line(anchor, endpoint);\n\n            // get the farther intersection, in case there are two\n            // (that happens if anchor lies next to bbox)\n            var intersections = intersectionLine.intersect(bbox) || [];\n            var numIntersections = intersections.length;\n            var farthestIntersectionDistance;\n            var farthestIntersection = null;\n            for (var i = 0; i < numIntersections; i++) {\n                var currentIntersection = intersections[i];\n                var distance = anchor.squaredDistance(currentIntersection);\n                if ((farthestIntersectionDistance === undefined) || (distance > farthestIntersectionDistance)) {\n                    farthestIntersectionDistance = distance;\n                    farthestIntersection = currentIntersection;\n                }\n            }\n\n            // if an intersection was found in this direction, it is our rectPoint\n            if (farthestIntersection) {\n                var point = align(farthestIntersection, grid, precision);\n\n                // if the rectPoint lies inside the bbox, offset it by one more step\n                if (bbox.containsPoint(point)) {\n                    point = align(point.offset(direction.x * grid.x, direction.y * grid.y), grid, precision);\n                }\n\n                // then add the point to the result array\n                // aligned\n                res.push(point);\n            }\n        }\n\n        return res;\n    }, []);\n\n    // if anchor lies outside of bbox, add it to the array of points\n    if (!bbox.containsPoint(anchor)) {\n        // aligned\n        rectPoints.push(align(anchor, grid, precision));\n    }\n\n    return rectPoints;\n}\n\n// finds the route between two points/rectangles (`from`, `to`) implementing A* algorithm\n// rectangles get rect points assigned by getRectPoints()\nfunction findRoute(from, to, isPointObstacle, opt) {\n\n    var precision = opt.precision;\n\n    // Get grid for this route.\n\n    var sourceAnchor, targetAnchor;\n\n    if (from instanceof g.Rect) { // `from` is sourceBBox\n        sourceAnchor = round(getSourceAnchor(this, opt).clone(), precision);\n    } else {\n        sourceAnchor = round(from.clone(), precision);\n    }\n\n    if (to instanceof g.Rect) { // `to` is targetBBox\n        targetAnchor = round(getTargetAnchor(this, opt).clone(), precision);\n    } else {\n        targetAnchor = round(to.clone(), precision);\n    }\n\n    var grid = getGrid(opt.step, sourceAnchor, targetAnchor);\n\n    // Get pathfinding points.\n\n    var start, end; // aligned with grid by definition\n    var startPoints, endPoints; // assumed to be aligned with grid already\n\n    // set of points we start pathfinding from\n    if (from instanceof g.Rect) { // `from` is sourceBBox\n        start = sourceAnchor;\n        startPoints = getRectPoints(start, from, opt.startDirections, grid, opt);\n\n    } else {\n        start = sourceAnchor;\n        startPoints = [start];\n    }\n\n    // set of points we want the pathfinding to finish at\n    if (to instanceof g.Rect) { // `to` is targetBBox\n        end = targetAnchor;\n        endPoints = getRectPoints(targetAnchor, to, opt.endDirections, grid, opt);\n\n    } else {\n        end = targetAnchor;\n        endPoints = [end];\n    }\n\n    // take into account only accessible rect points (those not under obstacles)\n    startPoints = startPoints.filter(p => !isPointObstacle(p));\n    endPoints = endPoints.filter(p => !isPointObstacle(p));\n\n    // Check that there is an accessible route point on both sides.\n    // Otherwise, use fallbackRoute().\n    if (startPoints.length > 0 && endPoints.length > 0) {\n\n        // The set of tentative points to be evaluated, initially containing the start points.\n        // Rounded to nearest integer for simplicity.\n        var openSet = new SortedSet();\n        // Keeps reference to actual points for given elements of the open set.\n        var points = {};\n        // Keeps reference to a point that is immediate predecessor of given element.\n        var parents = {};\n        // Cost from start to a point along best known path.\n        var costs = {};\n\n        for (var i = 0, n = startPoints.length; i < n; i++) {\n            // startPoint is assumed to be aligned already\n            var startPoint = startPoints[i];\n\n            var key = getKey(startPoint);\n\n            openSet.add(key, estimateCost(startPoint, endPoints));\n            points[key] = startPoint;\n            costs[key] = 0;\n        }\n\n        var previousRouteDirectionAngle = opt.previousDirectionAngle; // undefined for first route\n        var isPathBeginning = (previousRouteDirectionAngle === undefined);\n\n        // directions\n        var direction, directionChange;\n        var directions = opt.directions;\n        getGridOffsets(directions, grid, opt);\n\n        var numDirections = directions.length;\n\n        var endPointsKeys = util.toArray(endPoints).reduce(function(res, endPoint) {\n            // endPoint is assumed to be aligned already\n\n            var key = getKey(endPoint);\n            res.push(key);\n            return res;\n        }, []);\n\n        // main route finding loop\n        var loopsRemaining = opt.maximumLoops;\n        while (!openSet.isEmpty() && loopsRemaining > 0) {\n\n            // remove current from the open list\n            var currentKey = openSet.pop();\n            var currentPoint = points[currentKey];\n            var currentParent = parents[currentKey];\n            var currentCost = costs[currentKey];\n\n            var isRouteBeginning = (currentParent === undefined); // undefined for route starts\n            var isStart = currentPoint.equals(start); // (is source anchor or `from` point) = can leave in any direction\n\n            var previousDirectionAngle;\n            if (!isRouteBeginning) previousDirectionAngle = getDirectionAngle(currentParent, currentPoint, numDirections, grid, opt); // a vertex on the route\n            else if (!isPathBeginning) previousDirectionAngle = previousRouteDirectionAngle; // beginning of route on the path\n            else if (!isStart) previousDirectionAngle = getDirectionAngle(start, currentPoint, numDirections, grid, opt); // beginning of path, start rect point\n            else previousDirectionAngle = null; // beginning of path, source anchor or `from` point\n\n            // check if we reached any endpoint\n            var samePoints = startPoints.length === endPoints.length;\n            if (samePoints) {\n                for (var j = 0; j < startPoints.length; j++) {\n                    if (!startPoints[j].equals(endPoints[j])) {\n                        samePoints = false;\n                        break;\n                    }\n                }\n            }\n            var skipEndCheck = (isRouteBeginning && samePoints);\n            if (!skipEndCheck && (endPointsKeys.indexOf(currentKey) >= 0)) {\n                opt.previousDirectionAngle = previousDirectionAngle;\n                return reconstructRoute(parents, points, currentPoint, start, end, grid, opt);\n            }\n\n            // go over all possible directions and find neighbors\n            for (i = 0; i < numDirections; i++) {\n                direction = directions[i];\n\n                var directionAngle = direction.angle;\n                directionChange = getDirectionChange(previousDirectionAngle, directionAngle);\n\n                // if the direction changed rapidly, don't use this point\n                // any direction is allowed for starting points\n                if (!(isPathBeginning && isStart) && directionChange > opt.maxAllowedDirectionChange) continue;\n\n                var neighborPoint = align(currentPoint.clone().offset(direction.gridOffsetX, direction.gridOffsetY), grid, precision);\n                var neighborKey = getKey(neighborPoint);\n\n                // Closed points from the openSet were already evaluated.\n                if (openSet.isClose(neighborKey) || isPointObstacle(neighborPoint)) continue;\n\n                // We can only enter end points at an acceptable angle.\n                if (endPointsKeys.indexOf(neighborKey) >= 0) { // neighbor is an end point\n\n                    var isNeighborEnd = neighborPoint.equals(end); // (is target anchor or `to` point) = can be entered in any direction\n\n                    if (!isNeighborEnd) {\n                        var endDirectionAngle = getDirectionAngle(neighborPoint, end, numDirections, grid, opt);\n                        var endDirectionChange = getDirectionChange(directionAngle, endDirectionAngle);\n\n                        if (endDirectionChange > opt.maxAllowedDirectionChange) continue;\n                    }\n                }\n\n                // The current direction is ok.\n\n                var neighborCost = direction.cost;\n                var neighborPenalty = isStart ? 0 : opt.penalties[directionChange]; // no penalties for start point\n                var costFromStart = currentCost + neighborCost + neighborPenalty;\n\n                if (!openSet.isOpen(neighborKey) || (costFromStart < costs[neighborKey])) {\n                    // neighbor point has not been processed yet\n                    // or the cost of the path from start is lower than previously calculated\n\n                    points[neighborKey] = neighborPoint;\n                    parents[neighborKey] = currentPoint;\n                    costs[neighborKey] = costFromStart;\n                    openSet.add(neighborKey, costFromStart + estimateCost(neighborPoint, endPoints));\n                }\n            }\n\n            loopsRemaining--;\n        }\n    }\n\n    // no route found (`to` point either wasn't accessible or finding route took\n    // way too much calculation)\n    return opt.fallbackRoute.call(this, start, end, opt);\n}\n\n// resolve some of the options\nfunction resolveOptions(opt) {\n\n    opt.directions = util.result(opt, 'directions');\n    opt.penalties = util.result(opt, 'penalties');\n    opt.paddingBox = util.result(opt, 'paddingBox');\n    opt.padding = util.result(opt, 'padding');\n\n    if (opt.padding) {\n        // if both provided, opt.padding wins over opt.paddingBox\n        var sides = util.normalizeSides(opt.padding);\n        opt.paddingBox = {\n            x: -sides.left,\n            y: -sides.top,\n            width: sides.left + sides.right,\n            height: sides.top + sides.bottom\n        };\n    }\n\n    util.toArray(opt.directions).forEach(function(direction) {\n\n        var point1 = new g.Point(0, 0);\n        var point2 = new g.Point(direction.offsetX, direction.offsetY);\n\n        direction.angle = g.normalizeAngle(point1.theta(point2));\n    });\n}\n\n// initialization of the route finding\nfunction router(vertices, opt, linkView) {\n\n    resolveOptions(opt);\n\n    // enable/disable linkView perpendicular option\n    linkView.options.perpendicular = !!opt.perpendicular;\n\n    var sourceBBox = getSourceBBox(linkView, opt);\n    var targetBBox = getTargetBBox(linkView, opt);\n\n    var sourceAnchor = getSourceAnchor(linkView, opt);\n    //var targetAnchor = getTargetAnchor(linkView, opt);\n\n    // pathfinding\n    let isPointObstacle;\n    if (typeof opt.isPointObstacle === 'function') {\n        isPointObstacle = opt.isPointObstacle;\n    } else {\n        const map = new ObstacleMap(opt);\n        map.build(linkView.paper.model, linkView.model);\n        isPointObstacle = (point) => !map.isPointAccessible(point);\n    }\n\n    var oldVertices = util.toArray(vertices).map(g.Point);\n    var newVertices = [];\n    var tailPoint = sourceAnchor; // the origin of first route's grid, does not need snapping\n\n    // find a route by concatenating all partial routes (routes need to pass through vertices)\n    // source -> vertex[1] -> ... -> vertex[n] -> target\n    var to, from;\n\n    for (var i = 0, len = oldVertices.length; i <= len; i++) {\n\n        var partialRoute = null;\n\n        from = to || sourceBBox;\n        to = oldVertices[i];\n\n        if (!to) {\n            // this is the last iteration\n            // we ran through all vertices in oldVertices\n            // 'to' is not a vertex.\n\n            to = targetBBox;\n\n            // If the target is a point (i.e. it's not an element), we\n            // should use dragging route instead of main routing method if it has been provided.\n            var isEndingAtPoint = !linkView.model.get('source').id || !linkView.model.get('target').id;\n\n            if (isEndingAtPoint && util.isFunction(opt.draggingRoute)) {\n                // Make sure we are passing points only (not rects).\n                var dragFrom = (from === sourceBBox) ? sourceAnchor : from;\n                var dragTo = to.origin();\n\n                partialRoute = opt.draggingRoute.call(linkView, dragFrom, dragTo, opt);\n            }\n        }\n\n        // if partial route has not been calculated yet use the main routing method to find one\n        partialRoute = partialRoute || findRoute.call(linkView, from, to, isPointObstacle, opt);\n\n        if (partialRoute === null) { // the partial route cannot be found\n            return opt.fallbackRouter(vertices, opt, linkView);\n        }\n\n        var leadPoint = partialRoute[0];\n\n        // remove the first point if the previous partial route had the same point as last\n        if (leadPoint && leadPoint.equals(tailPoint)) partialRoute.shift();\n\n        // save tailPoint for next iteration\n        tailPoint = partialRoute[partialRoute.length - 1] || tailPoint;\n\n        Array.prototype.push.apply(newVertices, partialRoute);\n    }\n\n    return newVertices;\n}\n\n// public function\nexport const manhattan = function(vertices, opt, linkView) {\n    return router(vertices, util.assign({}, config, opt), linkView);\n};\n","import { manhattan } from './manhattan.mjs';\nimport * as util from '../util/index.mjs';\nimport * as g from '../g/index.mjs';\n\nvar config = {\n\n    maxAllowedDirectionChange: 45,\n\n    // cost of a diagonal step\n    diagonalCost: function() {\n\n        var step = this.step;\n        return Math.ceil(Math.sqrt(step * step << 1));\n    },\n\n    // an array of directions to find next points on the route\n    // different from start/end directions\n    directions: function() {\n\n        var step = this.step;\n        var cost = this.cost();\n        var diagonalCost = this.diagonalCost();\n\n        return [\n            { offsetX: step, offsetY: 0, cost: cost },\n            { offsetX: step, offsetY: step, cost: diagonalCost },\n            { offsetX: 0, offsetY: step, cost: cost },\n            { offsetX: -step, offsetY: step, cost: diagonalCost },\n            { offsetX: -step, offsetY: 0, cost: cost },\n            { offsetX: -step, offsetY: -step, cost: diagonalCost },\n            { offsetX: 0, offsetY: -step, cost: cost },\n            { offsetX: step, offsetY: -step, cost: diagonalCost }\n        ];\n    },\n\n    // a simple route used in situations when main routing method fails\n    // (exceed max number of loop iterations, inaccessible)\n    fallbackRoute: function(from, to, opt) {\n\n        // Find a route which breaks by 45 degrees ignoring all obstacles.\n\n        var theta = from.theta(to);\n\n        var route = [];\n\n        var a = { x: to.x, y: from.y };\n        var b = { x: from.x, y: to.y };\n\n        if (theta % 180 > 90) {\n            var t = a;\n            a = b;\n            b = t;\n        }\n\n        var p1 = (theta % 90) < 45 ? a : b;\n        var l1 = new g.Line(from, p1);\n\n        var alpha = 90 * Math.ceil(theta / 90);\n\n        var p2 = g.Point.fromPolar(l1.squaredLength(), g.toRad(alpha + 135), p1);\n        var l2 = new g.Line(to, p2);\n\n        var intersectionPoint = l1.intersection(l2);\n        var point = intersectionPoint ? intersectionPoint : to;\n\n        var directionFrom = intersectionPoint ? point : from;\n\n        var quadrant = 360 / opt.directions.length;\n        var angleTheta = directionFrom.theta(to);\n        var normalizedAngle = g.normalizeAngle(angleTheta + (quadrant / 2));\n        var directionAngle = quadrant * Math.floor(normalizedAngle / quadrant);\n\n        opt.previousDirectionAngle = directionAngle;\n\n        if (point) route.push(point.round());\n        route.push(to);\n\n        return route;\n    }\n};\n\n// public function\nexport const metro = function(vertices, opt, linkView) {\n\n    if (!util.isFunction(manhattan)) {\n        throw new Error('Metro requires the manhattan router.');\n    }\n\n    return manhattan(vertices, util.assign({}, config, opt), linkView);\n};\n\n","import * as g from '../g/index.mjs';\n\nconst Directions = {\n    AUTO: 'auto',\n    LEFT: 'left',\n    RIGHT: 'right',\n    TOP: 'top',\n    BOTTOM: 'bottom',\n    ANCHOR_SIDE: 'anchor-side',\n    MAGNET_SIDE: 'magnet-side'\n};\n\nconst DEFINED_DIRECTIONS = [Directions.LEFT, Directions.RIGHT, Directions.TOP, Directions.BOTTOM];\n\nconst OPPOSITE_DIRECTIONS = {\n    [Directions.LEFT]: Directions.RIGHT,\n    [Directions.RIGHT]: Directions.LEFT,\n    [Directions.TOP]: Directions.BOTTOM,\n    [Directions.BOTTOM]: Directions.TOP\n};\n\nconst VERTICAL_DIRECTIONS = [Directions.TOP, Directions.BOTTOM];\n\nconst ANGLE_DIRECTION_MAP = {\n    0: Directions.RIGHT,\n    180: Directions.LEFT,\n    270: Directions.TOP,\n    90: Directions.BOTTOM\n};\n\nfunction getSegmentAngle(line) {\n    // TODO: the angle() method is general and therefore unnecessarily heavy for orthogonal links\n    return line.angle();\n}\n\nfunction simplifyPoints(points) {\n    // TODO: use own more efficient implementation (filter points that do not change direction).\n    // To simplify segments that are almost aligned (start and end points differ by e.g. 0.5px), use a threshold of 1.\n    return new g.Polyline(points).simplify({ threshold: 1 }).points;\n}\n\nfunction resolveSides(source, target) {\n    const { point: sourcePoint, x0: sx0, y0: sy0, view: sourceView, bbox: sourceBBox, direction: sourceDirection } = source;\n    const { point: targetPoint, x0: tx0, y0: ty0, view: targetView, bbox: targetBBox, direction: targetDirection } = target;\n\n    let sourceSide;\n\n    if (!sourceView) {\n        const sourceLinkAnchorBBox = new g.Rect(sx0, sy0, 0, 0);\n        sourceSide = DEFINED_DIRECTIONS.includes(sourceDirection) ? sourceDirection : sourceLinkAnchorBBox.sideNearestToPoint(targetPoint);\n    } else if (sourceView.model.isLink()) {\n        sourceSide = getDirectionForLinkConnection(targetPoint, sourcePoint, sourceView);\n    } else if (sourceDirection === Directions.ANCHOR_SIDE) {\n        sourceSide = sourceBBox.sideNearestToPoint(sourcePoint);\n    } else if (sourceDirection === Directions.MAGNET_SIDE) {\n        sourceSide = sourceView.model.getBBox().sideNearestToPoint(sourcePoint);\n    } else {\n        sourceSide = sourceDirection;\n    }\n\n    let targetSide;\n\n    if (!targetView) {\n        const targetLinkAnchorBBox = new g.Rect(tx0, ty0, 0, 0);\n        targetSide = DEFINED_DIRECTIONS.includes(targetDirection) ? targetDirection : targetLinkAnchorBBox.sideNearestToPoint(sourcePoint);\n    } else if (targetView.model.isLink()) {\n        targetSide = getDirectionForLinkConnection(sourcePoint, targetPoint, targetView);\n    } else if (targetDirection === Directions.ANCHOR_SIDE) {\n        targetSide = targetBBox.sideNearestToPoint(targetPoint);\n    } else if (targetDirection === Directions.MAGNET_SIDE) {\n        targetSide = targetView.model.getBBox().sideNearestToPoint(targetPoint);\n    } else {\n        targetSide = targetDirection;\n    }\n\n    return [sourceSide, targetSide];\n}\n\nfunction resolveForTopSourceSide(source, target, nextInLine) {\n    const { x0: sx0, y0: sy0, width, height, point: anchor, margin } = source;\n    const sx1 = sx0 + width;\n    const sy1 = sy0 + height;\n    const smx0 = sx0 - margin;\n    const smx1 = sx1 + margin;\n    const smy0 = sy0 - margin;\n\n    const { x: ax } = anchor;\n    const { x0: tx, y0: ty } = target;\n\n    if (tx === ax && ty < sy0) return Directions.BOTTOM;\n    if (tx < ax && ty < smy0) {\n        if (nextInLine.point.x === ax) return Directions.BOTTOM;\n        return Directions.RIGHT;\n    }\n    if (tx > ax && ty < smy0) {\n        if (nextInLine.point.x === ax) return Directions.BOTTOM;\n        return Directions.LEFT;\n    }\n    if (tx < smx0 && ty > smy0) return Directions.TOP;\n    if (tx > smx1 && ty > smy0) return Directions.TOP;\n    if (tx >= smx0 && tx <= ax && ty > sy1) {\n        if (nextInLine.point.x < tx) {\n            return Directions.RIGHT;\n        }\n        return Directions.LEFT;\n    }\n    if (tx <= smx1 && tx >= ax && ty > sy1) {\n        if (nextInLine.point.x < tx) {\n            return Directions.RIGHT;\n        }\n        return Directions.LEFT;\n    }\n\n    return Directions.BOTTOM;\n}\n\nfunction resolveForBottomSourceSide(source, target, nextInLine) {\n    const { x0: sx0, y0: sy0, width, height, point: anchor, margin } = source;\n    const sx1 = sx0 + width;\n    const sy1 = sy0 + height;\n    const smx0 = sx0 - margin;\n    const smx1 = sx1 + margin;\n    const smy1 = sy1 + margin;\n\n    const { x: ax } = anchor;\n    const { x0: tx, y0: ty } = target;\n\n    if (tx === ax && ty > sy1) return Directions.TOP;\n    if (tx < ax && ty > smy1) {\n        if (nextInLine.point.x === ax) return Directions.TOP;\n        return Directions.RIGHT;\n    }\n    if (tx > ax && ty > smy1) {\n        if (nextInLine.point.x === ax) return Directions.TOP;\n        return Directions.LEFT;\n    }\n    if (tx < smx0 && ty < smy1) return Directions.BOTTOM;\n    if (tx > smx1 && ty < smy1) return Directions.BOTTOM;\n    if (tx >= smx0 && tx <= ax && ty < sy0) {\n        if (nextInLine.point.x < tx) {\n            return Directions.RIGHT;\n        }\n        return Directions.LEFT;\n    }\n    if (tx <= smx1 && tx >= ax && ty < sy0) {\n        if (nextInLine.point.x < tx) {\n            return Directions.RIGHT;\n        }\n        return Directions.LEFT;\n    }\n\n    return Directions.TOP;\n}\n\nfunction resolveForLeftSourceSide(source, target, nextInLine) {\n    const { y0: sy0, x0: sx0, width, height, point: anchor, margin } = source;\n    const sx1 = sx0 + width;\n    const sy1 = sy0 + height;\n    const smx0 = sx0 - margin;\n    const smy0 = sy0 - margin;\n    const smy1 = sy1 + margin;\n\n    const { x: ax, y: ay } = anchor;\n    const { x0: tx, y0: ty } = target;\n\n    if (tx < ax && ty === ay) return Directions.RIGHT;\n    if (tx <= smx0 && ty < ay) return Directions.BOTTOM;\n    if (tx <= smx0 && ty > ay) return Directions.TOP;\n    if (tx >= smx0 && ty < smy0) return Directions.LEFT;\n    if (tx >= smx0 && ty > smy1) return Directions.LEFT;\n    if (tx > sx1 && ty >= smy0 && ty <= ay) {\n        if (nextInLine.point.y < ty) {\n            return Directions.BOTTOM;\n        }\n\n        return Directions.TOP;\n    }\n    if (tx > sx1 && ty <= smy1 && ty >= ay) {\n        if (nextInLine.point.y < ty) {\n            return Directions.BOTTOM;\n        }\n\n        return Directions.TOP;\n    }\n\n    return Directions.RIGHT;\n}\n\nfunction resolveForRightSourceSide(source, target, nextInLine) {\n    const { y0: sy0, x0: sx0, width, height, point: anchor, margin } = source;\n    const sx1 = sx0 + width;\n    const sy1 = sy0 + height;\n    const smx1 = sx1 + margin;\n    const smy0 = sy0 - margin;\n    const smy1 = sy1 + margin;\n\n    const { x: ax, y: ay } = anchor;\n    const { x0: tx, y0: ty } = target;\n\n    if (tx > ax && ty === ay) return Directions.LEFT;\n    if (tx >= smx1 && ty < ay) return Directions.BOTTOM;\n    if (tx >= smx1 && ty > ay) return Directions.TOP;\n    if (tx <= smx1 && ty < smy0) return Directions.RIGHT;\n    if (tx <= smx1 && ty > smy1) return Directions.RIGHT;\n    if (tx < sx0 && ty >= smy0 && ty <= ay) {\n        if (nextInLine.point.y < ty) {\n            return Directions.BOTTOM;\n        }\n\n        return Directions.TOP;\n    }\n    if (tx < sx0 && ty <= smy1 && ty >= ay) {\n        if (nextInLine.point.y < ty) {\n            return Directions.BOTTOM;\n        }\n\n        return Directions.TOP;\n    }\n\n    return Directions.LEFT;\n}\n\nfunction resolveInitialDirection(source, target, nextInLine) {\n    const [sourceSide] = resolveSides(source, target);\n\n    switch (sourceSide) {\n        case Directions.TOP:\n            return resolveForTopSourceSide(source, target, nextInLine);\n        case Directions.RIGHT:\n            return resolveForRightSourceSide(source, target, nextInLine);\n        case Directions.BOTTOM:\n            return resolveForBottomSourceSide(source, target, nextInLine);\n        case Directions.LEFT:\n            return resolveForLeftSourceSide(source, target, nextInLine);\n    }\n}\n\nfunction getDirectionForLinkConnection(linkOrigin, connectionPoint, linkView) {\n    const tangent = linkView.getTangentAtLength(linkView.getClosestPointLength(connectionPoint));\n    const roundedAngle = Math.round(getSegmentAngle(tangent) / 90) * 90;\n\n    if (roundedAngle % 180 === 0 && linkOrigin.y === connectionPoint.y) {\n        return linkOrigin.x < connectionPoint.x ? Directions.LEFT : Directions.RIGHT;\n    } else if (linkOrigin.x === connectionPoint.x) {\n        return linkOrigin.y < connectionPoint.y ? Directions.TOP : Directions.BOTTOM;\n    }\n\n    switch (roundedAngle) {\n        case 0:\n        case 180:\n        case 360:\n            return linkOrigin.y < connectionPoint.y ? Directions.TOP : Directions.BOTTOM;\n        case 90:\n        case 270:\n            return linkOrigin.x < connectionPoint.x ? Directions.LEFT : Directions.RIGHT;\n    }\n}\n\nfunction pointDataFromAnchor(view, point, bbox, direction, isPort, fallBackAnchor, margin) {\n    if (direction === Directions.AUTO) {\n        direction = isPort ? Directions.MAGNET_SIDE : Directions.ANCHOR_SIDE;\n    }\n\n    const isElement = view && view.model.isElement();\n\n    const {\n        x: x0,\n        y: y0,\n        width = 0,\n        height = 0\n    } = isElement ? g.Rect.fromRectUnion(bbox, view.model.getBBox()) : fallBackAnchor;\n\n    return {\n        point,\n        x0,\n        y0,\n        view,\n        bbox,\n        width,\n        height,\n        direction,\n        margin: isElement ? margin : 0\n    };\n}\n\nfunction pointDataFromVertex({ x, y }) {\n    const point = new g.Point(x, y);\n\n    return {\n        point,\n        x0: point.x,\n        y0: point.y,\n        view: null,\n        bbox: new g.Rect(x, y, 0, 0),\n        width: 0,\n        height: 0,\n        direction: null,\n        margin: 0\n    };\n}\n\nfunction getOutsidePoint(side, pointData, margin) {\n    const outsidePoint = pointData.point.clone();\n\n    const { x0, y0, width, height } = pointData;\n\n    switch (side) {\n        case 'left':\n            outsidePoint.x = x0 - margin;\n            break;\n        case 'right':\n            outsidePoint.x = x0 + width + margin;\n            break;\n        case 'top':\n            outsidePoint.y = y0 - margin;\n            break;\n        case 'bottom':\n            outsidePoint.y = y0 + height + margin;\n            break;\n    }\n\n    return outsidePoint;\n}\n\nfunction createLoop(from, to, { dx = 0, dy = 0 }) {\n    const p1 = { x: from.point.x + dx, y: from.point.y + dy };\n    const p2 = { x: to.point.x + dx, y: to.point.y + dy };\n\n    return [from.point, p1, p2, to.point];\n}\n\nfunction loopSegment(from, to, connectionSegmentAngle, margin) {\n    // Find out the loop coordinates.\n    const angle = g.normalizeAngle(connectionSegmentAngle - 90);\n\n    let dx = 0;\n    let dy = 0;\n\n    if (angle === 90) {\n        dy = -margin;\n    } else if (angle === 180) {\n        dx = -margin;\n    } else if (angle === 270) {\n        dy = margin;\n    } else if (angle === 0) {\n        dx = margin;\n    }\n\n    const loopRoute = createLoop(from, to, { dx, dy });\n\n    const secondCreatedPoint = loopRoute[2];\n    const loopEndSegment = new g.Line(to.point, secondCreatedPoint);\n    // The direction in which the loop should continue.\n    const continueDirection = ANGLE_DIRECTION_MAP[getSegmentAngle(loopEndSegment)];\n\n    return {\n        loopRoute,\n        continueDirection\n    };\n}\n\n// Calculates the distances along the horizontal axis for the left and right route.\nfunction getHorizontalDistance(source, target) {\n\n    const { x0: sx0, x1: sx1, outsidePoint: sourcePoint } = source;\n    const { x0: tx0, x1: tx1, outsidePoint: targetPoint } = target;\n\n    // Furthest left boundary\n    let leftBoundary = Math.min(sx0, tx0);\n    // Furthest right boundary\n    let rightBoundary = Math.max(sx1, tx1);\n\n    // If the source and target elements are on the same side, we need to figure out what shape defines the boundary.\n    if (source.direction === target.direction) {\n\n        const aboveShape = source.y0 < target.y0 ? source : target;\n        const belowShape = aboveShape === source ? target : source;\n\n        // The source and target anchors are on the top => then the `aboveShape` defines the boundary.\n        // The source and target anchors are on the bottom => then the `belowShape` defines the boundary.\n        const boundaryDefiningShape = source.direction === Directions.TOP ? aboveShape : belowShape;\n\n        leftBoundary = boundaryDefiningShape.x0;\n        rightBoundary = boundaryDefiningShape.x1;\n    }\n\n    const { x: sox } = sourcePoint;\n    const { x: tox } = targetPoint;\n\n    // Calculate the distances for the left route\n    const leftDistance1 = Math.abs(sox - leftBoundary);\n    const leftDistance2 = Math.abs(tox - leftBoundary);\n    const leftD = leftDistance1 + leftDistance2;\n\n    // Calculate the distances for the right route\n    const rightDistance1 = Math.abs(sox - rightBoundary);\n    const rightDistance2 = Math.abs(tox - rightBoundary);\n    const rightD = rightDistance1 + rightDistance2;\n\n    return [leftD, rightD];\n}\n\n// Calculates the distances along the vertical axis for the top and bottom route.\nfunction getVerticalDistance(source, target) {\n\n    const { y0: sy0, y1: sy1, outsidePoint: sourcePoint } = source;\n    const { y0: ty0, y1: ty1, outsidePoint: targetPoint } = target;\n\n    // Furthest top boundary\n    let topBoundary = Math.min(sy0, ty0);\n    // Furthest bottom boundary\n    let bottomBoundary = Math.max(sy1, ty1);\n\n    // If the source and target elements are on the same side, we need to figure out what shape defines the boundary.\n    if (source.direction === target.direction) {\n\n        const leftShape = source.x0 < target.x0 ? source : target;\n        const rightShape = leftShape === source ? target : source;\n\n        // The source and target anchors are on the left => then the `leftShape` defines the boundary.\n        // The source and target anchors are on the right => then the `rightShape` defines the boundary.\n        const boundaryDefiningShape = source.direction === Directions.LEFT ? leftShape : rightShape;\n\n        topBoundary = boundaryDefiningShape.y0;\n        bottomBoundary = boundaryDefiningShape.y1;  \n    }\n\n    const { y: soy } = sourcePoint;\n    const { y: toy } = targetPoint;\n\n    // Calculate the distances for the top route\n    const topDistance1 = Math.abs(soy - topBoundary);\n    const topDistance2 = Math.abs(toy - topBoundary);\n    const topD = topDistance1 + topDistance2;\n\n    // Calculate the distances for the bottom route\n    const bottomDistance1 = Math.abs(soy - bottomBoundary);\n    const bottomDistance2 = Math.abs(toy - bottomBoundary);\n    const bottomD = bottomDistance1 + bottomDistance2;\n\n    return [topD, bottomD];\n}\n\n// Inflate bbox in 3 directions depending on the direction of the anchor\n// don't inflate in the opposite direction of the anchor\nfunction moveAndExpandBBox(bbox, direction, margin) {\n    switch (direction) {\n        case Directions.LEFT:\n            bbox.inflate(0, margin).moveAndExpand({ x: -margin, width: margin });\n            break;\n        case Directions.RIGHT:\n            bbox.inflate(0, margin).moveAndExpand({ width: margin });\n            break;\n        case Directions.TOP:\n            bbox.inflate(margin, 0).moveAndExpand({ y: -margin, height: margin });\n            break;\n        case Directions.BOTTOM:\n            bbox.inflate(margin, 0).moveAndExpand({ height: margin });\n            break;\n    }\n\n    return bbox;\n}\n\nfunction routeBetweenPoints(source, target, opt = {}) {\n    const { point: sourcePoint, x0: sx0, y0: sy0, width: sourceWidth, height: sourceHeight, margin: sourceMargin } = source;\n    const { point: targetPoint, x0: tx0, y0: ty0, width: targetWidth, height: targetHeight, margin: targetMargin } = target;\n    const { targetInSourceBBox = false } = opt;\n\n    const tx1 = tx0 + targetWidth;\n    const ty1 = ty0 + targetHeight;\n    const sx1 = sx0 + sourceWidth;\n    const sy1 = sy0 + sourceHeight;\n\n    // Key coordinates including the margin\n    const smx0 = sx0 - sourceMargin;\n    const smx1 = sx1 + sourceMargin;\n    const smy0 = sy0 - sourceMargin;\n    const smy1 = sy1 + sourceMargin;\n\n    const tmx0 = tx0 - targetMargin;\n    const tmx1 = tx1 + targetMargin;\n    const tmy0 = ty0 - targetMargin;\n    const tmy1 = ty1 + targetMargin;\n\n    const [sourceSide, targetSide] = resolveSides(source, target);\n\n    const sourceOutsidePoint = getOutsidePoint(sourceSide, { point: sourcePoint, x0: sx0, y0: sy0, width: sourceWidth, height: sourceHeight }, sourceMargin);\n    const targetOutsidePoint = getOutsidePoint(targetSide, { point: targetPoint, x0: tx0, y0: ty0, width: targetWidth, height: targetHeight }, targetMargin);\n\n    const { x: sox, y: soy } = sourceOutsidePoint;\n    const { x: tox, y: toy } = targetOutsidePoint;\n    const tcx = (tx0 + tx1) / 2;\n    const tcy = (ty0 + ty1) / 2;\n    const scx = (sx0 + sx1) / 2;\n    const scy = (sy0 + sy1) / 2;\n    const middleOfVerticalSides = (scx < tcx ? (sx1 + tx0) : (tx1 + sx0)) / 2;\n    const middleOfHorizontalSides = (scy < tcy ? (sy1 + ty0) : (ty1 + sy0)) / 2;\n\n    const sourceBBox = new g.Rect(sx0, sy0, sourceWidth, sourceHeight);\n    const targetBBox = new g.Rect(tx0, ty0, targetWidth, targetHeight);\n    const inflatedSourceBBox = sourceBBox.clone().inflate(sourceMargin);\n    const inflatedTargetBBox = targetBBox.clone().inflate(targetMargin);\n\n    const sourceForDistance = Object.assign({}, source, { x1: sx1, y1: sy1, outsidePoint: sourceOutsidePoint, direction: sourceSide });\n    const targetForDistance = Object.assign({}, target, { x1: tx1, y1: ty1, outsidePoint: targetOutsidePoint, direction: targetSide });\n\n    // Distances used to determine the shortest route along the connections on horizontal sides for\n    // bottom => bottom\n    // top => bottom\n    // bottom => top\n    // top => top\n    const [leftD, rightD] = getHorizontalDistance(sourceForDistance, targetForDistance);\n\n    // Distances used to determine the shortest route along the connection on vertical sides for\n    // left => left\n    // left => right\n    // right => right\n    // right => left\n    const [topD, bottomD] = getVerticalDistance(sourceForDistance, targetForDistance);\n\n    // All possible combinations of source and target sides\n    if (sourceSide === 'left' && targetSide === 'right') {\n        const isPointInsideSource = inflatedSourceBBox.containsPoint(targetOutsidePoint);\n        const isPointInsideTarget = inflatedTargetBBox.containsPoint(sourceOutsidePoint);\n\n        // Use S-shaped connection\n        if (isPointInsideSource || isPointInsideTarget) {\n            const middleOfAnchors = (soy + toy) / 2;\n            \n            return [\n                { x: sox, y: soy },\n                { x: sox, y: middleOfAnchors },\n                { x: tox, y: middleOfAnchors },\n                { x: tox, y: toy }\n            ];\n        }\n\n        if (smx0 < tox) {\n            let y = middleOfHorizontalSides;\n            let x1 = sox;\n            let x2 = tox;\n\n            const isUpwardsShorter = topD < bottomD;\n\n            // If the source and target elements overlap, we need to make sure the connection\n            // goes around the target element.\n            if ((y >= smy0 && y <= smy1) || (y >= tmy0 && y <= tmy1)) {\n                if (smy1 >= tmy0 && isUpwardsShorter) {\n                    y = Math.min(tmy0, smy0);\n                } else if (smy0 <= tmy1 && !isUpwardsShorter) {\n                    y = Math.max(tmy1, smy1);\n                }\n\n                // This handles the case when the source and target elements overlap as well as\n                // the case when the source is to the left of the target element.\n                x1 = Math.min(sox, tmx0);\n                x2 = Math.max(tox, smx1);\n            \n                // This is an edge case when the source and target intersect and\n                if ((isUpwardsShorter && soy < ty0) || (!isUpwardsShorter && soy > ty1)) {\n                    // the path should no longer rely on minimal x boundary in `x1`\n                    x1 = sox;\n                } else if ((isUpwardsShorter && toy < sy0) || (!isUpwardsShorter && toy > sy1)) {\n                    // the path should no longer rely on maximal x boundary in `x2`\n                    x2 = tox;\n                }\n            }\n\n            return [\n                { x: x1, y: soy },\n                { x: x1, y },\n                { x: x2, y },\n                { x: x2, y: toy }\n            ];\n        }\n\n        const x = (sox + tox) / 2;\n        return [\n            { x, y: soy },\n            { x, y: toy },\n        ];\n    } else if (sourceSide === 'right' && targetSide === 'left') {\n        const isPointInsideSource = inflatedSourceBBox.containsPoint(targetOutsidePoint);\n        const isPointInsideTarget = inflatedTargetBBox.containsPoint(sourceOutsidePoint);\n\n        // Use S-shaped connection\n        if (isPointInsideSource || isPointInsideTarget) {\n            const middleOfAnchors = (soy + toy) / 2;\n            \n            return [\n                { x: sox, y: soy },\n                { x: sox, y: middleOfAnchors },\n                { x: tox, y: middleOfAnchors },\n                { x: tox, y: toy }\n            ];\n        }\n\n        if (smx1 > tox) {\n            let y = middleOfHorizontalSides;\n            let x1 = sox;\n            let x2 = tox;\n\n            const isUpwardsShorter = topD < bottomD;\n\n            // If the source and target elements overlap, we need to make sure the connection\n            // goes around the target element.\n            if ((y >= smy0 && y <= smy1) || (y >= tmy0 && y <= tmy1)) {\n                if (smy1 >= tmy0 && isUpwardsShorter) {\n                    y = Math.min(tmy0, smy0);\n                } else if (smy0 <= tmy1 && !isUpwardsShorter) {\n                    y = Math.max(tmy1, smy1);\n                }\n\n                // This handles the case when the source and target elements overlap as well as\n                // the case when the source is to the left of the target element.\n                x1 = Math.max(sox, tmx1);\n                x2 = Math.min(tox, smx0);\n\n                // This is an edge case when the source and target intersect and\n                if ((isUpwardsShorter && soy < ty0) || (!isUpwardsShorter && soy > ty1)) {\n                    // the path should no longer rely on maximal x boundary in `x1`\n                    x1 = sox;\n                } else if ((isUpwardsShorter && toy < sy0) || (!isUpwardsShorter && toy > sy1)) {\n                    // the path should no longer rely on minimal x boundary in `x2`\n                    x2 = tox;\n                }\n            }\n\n            return [\n                { x: x1, y: soy },\n                { x: x1, y },\n                { x: x2, y },\n                { x: x2, y: toy }\n            ];\n        }\n\n        const x = (sox + tox) / 2;\n        return [\n            { x, y: soy },\n            { x, y: toy }\n        ];\n    } else if (sourceSide === 'top' && targetSide === 'bottom') {\n        const isPointInsideSource = inflatedSourceBBox.containsPoint(targetOutsidePoint);\n        const isPointInsideTarget = inflatedTargetBBox.containsPoint(sourceOutsidePoint);\n\n        // Use S-shaped connection\n        if (isPointInsideSource || isPointInsideTarget) {\n            const middleOfAnchors = (sox + tox) / 2;\n\n            return [\n                { x: sox, y: soy },\n                { x: middleOfAnchors, y: soy },\n                { x: middleOfAnchors, y: toy },\n                { x: tox, y: toy }\n            ];\n        }\n\n        if (smy0 < toy) {\n            let x = middleOfVerticalSides;\n            let y1 = soy;\n            let y2 = toy;\n\n            const isLeftShorter = leftD < rightD;\n\n            // If the source and target elements overlap, we need to make sure the connection\n            // goes around the target element.\n            if ((x >= smx0 && x <= smx1) || (x >= tmx0 && x <= tmx1)) {\n                if (smx1 >= tmx0 && isLeftShorter) {\n                    x = Math.min(tmx0, smx0);\n                } else if (smx0 <= tmx1 && !isLeftShorter) {\n                    x = Math.max(tmx1, smx1);\n                }\n\n                // This handles the case when the source and target elements overlap as well as\n                // the case when the source is to the left of the target element.\n                y1 = Math.min(soy, tmy0);\n                y2 = Math.max(toy, smy1);\n\n                // This is an edge case when the source and target intersect and\n                if ((isLeftShorter && sox < tx0) || (!isLeftShorter && sox > tx1)) {\n                    // the path should no longer rely on minimal y boundary in `y1`\n                    y1 = soy;\n                } else if ((isLeftShorter && tox < sx0) || (!isLeftShorter && tox > sx1)) {\n                    // the path should no longer rely on maximal y boundary in `y2`\n                    y2 = toy;\n                }\n            }\n\n            return [\n                { x: sox, y: y1 },\n                { x, y: y1 },\n                { x, y: y2 },\n                { x: tox, y: y2 }\n            ];\n        }\n\n        const y = (soy + toy) / 2;\n        return [\n            { x: sox, y },\n            { x: tox, y }\n        ];\n    } else if (sourceSide === 'bottom' && targetSide === 'top') {\n        const isPointInsideSource = inflatedSourceBBox.containsPoint(targetOutsidePoint);\n        const isPointInsideTarget = inflatedTargetBBox.containsPoint(sourceOutsidePoint);\n\n        // Use S-shaped connection\n        if (isPointInsideSource || isPointInsideTarget) {\n            const middleOfAnchors = (sox + tox) / 2;\n\n            return [\n                { x: sox, y: soy },\n                { x: middleOfAnchors, y: soy },\n                { x: middleOfAnchors, y: toy },\n                { x: tox, y: toy }\n            ];\n        }\n\n        if (smy1 > toy) {\n            let x = middleOfVerticalSides;\n            let y1 = soy;\n            let y2 = toy;\n            \n            const isLeftShorter = leftD < rightD;\n\n            // If the source and target elements overlap, we need to make sure the connection\n            // goes around the target element.\n            if ((x >= smx0 && x <= smx1) || (x >= tmx0 && x <= tmx1)) {\n                if (smx1 >= tmx0 && isLeftShorter) {\n                    x = Math.min(tmx0, smx0);\n                } else if (smx0 <= tmx1 && !isLeftShorter) {\n                    x = Math.max(tmx1, smx1);\n                }\n\n                // This handles the case when the source and target elements overlap as well as\n                // the case when the source is to the left of the target element.\n                y1 = Math.max(soy, tmy1);\n                y2 = Math.min(toy, smy0);\n\n                // This is an edge case when the source and target intersect and\n                if ((isLeftShorter && sox < tx0) || (!isLeftShorter && sox > tx1)) {\n                    // the path should no longer rely on maximal y boundary in `y1`\n                    y1 = soy;\n                } else if ((isLeftShorter && tox < sx0) || (!isLeftShorter && tox > sx1)) {\n                    // the path should no longer rely on minimal y boundary in `y2`\n                    y2 = toy;\n                }\n            }\n\n            return [\n                { x: sox, y: y1 },\n                { x, y: y1 },\n                { x, y: y2 },\n                { x: tox, y: y2 }\n            ];\n        }\n\n        const y = (soy + toy) / 2;\n        return [\n            { x: sox, y },\n            { x: tox, y }\n        ];\n    } else if (sourceSide === 'top' && targetSide === 'top') {\n        const useUShapeConnection =\n            targetInSourceBBox ||\n            g.intersection.rectWithRect(inflatedSourceBBox, targetBBox) ||\n            (soy <= ty0 && (inflatedSourceBBox.bottomRight().x <= tox || inflatedSourceBBox.bottomLeft().x >= tox)) ||\n            (soy >= ty0 && (inflatedTargetBBox.bottomRight().x <= sox || inflatedTargetBBox.bottomLeft().x >= sox));\n\n        // U-shape connection is a straight line if `sox` and `tox` are the same\n        if (useUShapeConnection && sox !== tox) {\n            return [\n                { x: sox, y: Math.min(soy, toy) },\n                { x: tox, y: Math.min(soy, toy) }\n            ];\n        }\n\n        let x;\n        let y1 = Math.min((sy1 + ty0) / 2, toy);\n        let y2 = Math.min((sy0 + ty1) / 2, soy);\n\n        if (toy < soy) {\n            // Use the shortest path along the connections on horizontal sides\n            if (rightD > leftD) {\n                x = Math.min(sox, tmx0);\n            } else {\n                x = Math.max(sox, tmx1);\n            }\n        } else {\n            if (rightD > leftD) {\n                x = Math.min(tox, smx0);\n            } else {\n                x = Math.max(tox, smx1);\n            }\n        }\n\n        return [\n            { x: sox, y: y2 },\n            { x, y: y2 },\n            { x, y: y1 },\n            { x: tox, y: y1 }\n        ];\n    } else if (sourceSide === 'bottom' && targetSide === 'bottom') {\n        const useUShapeConnection =\n            targetInSourceBBox ||\n            g.intersection.rectWithRect(inflatedSourceBBox, targetBBox) ||\n            (soy >= toy && (inflatedSourceBBox.topRight().x <= tox || inflatedSourceBBox.topLeft().x >= tox)) ||\n            (soy <= toy && (inflatedTargetBBox.topRight().x <= sox || inflatedTargetBBox.topLeft().x >= sox));\n\n        // U-shape connection is a straight line if `sox` and `tox` are the same\n        if (useUShapeConnection && sox !== tox) {\n            return [\n                { x: sox, y: Math.max(soy, toy) },\n                { x: tox, y: Math.max(soy, toy) }\n            ];\n        }\n\n        let x;\n        let y1 = Math.max((sy0 + ty1) / 2, toy);\n        let y2 = Math.max((sy1 + ty0) / 2, soy);\n\n        if (toy > soy) {\n            // Use the shortest path along the connections on horizontal sides\n            if (rightD > leftD) {\n                x = Math.min(sox, tmx0);\n            } else {\n                x = Math.max(sox, tmx1);\n            }\n        } else {\n            if (rightD > leftD) {\n                x = Math.min(tox, smx0);\n            } else {\n                x = Math.max(tox, smx1);\n            }\n        }\n\n        return [\n            { x: sox, y: y2 },\n            { x, y: y2 },\n            { x, y: y1 },\n            { x: tox, y: y1 }\n        ];\n    } else if (sourceSide === 'left' && targetSide === 'left') {\n        const useUShapeConnection = \n            targetInSourceBBox ||\n            g.intersection.rectWithRect(inflatedSourceBBox, targetBBox) ||\n            (sox <= tox && (inflatedSourceBBox.bottomRight().y <= toy || inflatedSourceBBox.topRight().y >= toy)) ||\n            (sox >= tox && (inflatedTargetBBox.bottomRight().y <= soy || inflatedTargetBBox.topRight().y >= soy));\n\n        // U-shape connection is a straight line if `soy` and `toy` are the same\n        if (useUShapeConnection && soy !== toy) {\n            return [\n                { x: Math.min(sox, tox), y: soy },\n                { x: Math.min(sox, tox), y: toy }\n            ];\n        }\n\n        let y;\n        let x1 = Math.min((sx1 + tx0) / 2, tox);\n        let x2 = Math.min((sx0 + tx1) / 2, sox);\n\n        if (tox > sox) {\n            if (topD <= bottomD) {\n                y = Math.min(smy0, toy);\n            } else {\n                y = Math.max(smy1, toy);\n            }\n        } else {\n            if (topD <= bottomD) {\n                y = Math.min(tmy0, soy);\n            } else {\n                y = Math.max(tmy1, soy);\n            }\n        }\n\n        return [\n            { x: x2, y: soy },\n            { x: x2, y },\n            { x: x1, y },\n            { x: x1, y: toy }\n        ];\n    } else if (sourceSide === 'right' && targetSide === 'right') {\n        const useUShapeConnection =\n            targetInSourceBBox ||\n            g.intersection.rectWithRect(inflatedSourceBBox, targetBBox) ||\n            (sox >= tox && (inflatedSourceBBox.bottomLeft().y <= toy || inflatedSourceBBox.topLeft().y >= toy)) ||\n            (sox <= tox && (inflatedTargetBBox.bottomLeft().y <= soy || inflatedTargetBBox.topLeft().y >= soy));\n\n        // U-shape connection is a straight line if `soy` and `toy` are the same\n        if (useUShapeConnection && soy !== toy) {\n            return [\n                { x: Math.max(sox, tox), y: soy },\n                { x: Math.max(sox, tox), y: toy }\n            ];\n        }\n\n        let y;\n        let x1 = Math.max((sx0 + tx1) / 2, tox);\n        let x2 = Math.max((sx1 + tx0) / 2, sox);\n\n        if (tox <= sox) {\n            if (topD <= bottomD) {\n                y = Math.min(smy0, toy);\n            } else {\n                y = Math.max(smy1, toy);\n            }\n        } else {\n            if (topD <= bottomD) {\n                y = Math.min(tmy0, soy);\n            } else {\n                y = Math.max(tmy1, soy);\n            }\n        }\n\n        return [\n            { x: x2, y: soy },\n            { x: x2, y },\n            { x: x1, y },\n            { x: x1, y: toy }\n        ];\n    } else if (sourceSide === 'top' && targetSide === 'right') {\n        const isPointInsideSource = inflatedSourceBBox.containsPoint(targetPoint);\n\n        // The target point is inside the source element\n        if (isPointInsideSource) {\n            if (sox <= tmx1) {\n                const x = Math.max(sox + sourceMargin, tox);\n                const y = Math.min(smy0, tmy0);\n\n                // Target anchor is on the right side of the source anchor\n                return [\n                    { x: sox, y },\n                    { x: x, y },\n                    { x: x, y: toy }\n                ];\n            }\n\n            // Target anchor is on the left side of the source anchor\n            // Subtract the `sourceMargin` since the source anchor is on the right side of the target anchor\n            const anchorMiddleX = (sox - sourceMargin + tox) / 2;\n\n            return [\n                { x: sox, y: soy },\n                { x: anchorMiddleX, y: soy },\n                { x: anchorMiddleX, y: toy }\n            ];\n        }\n\n        if (smy0 > toy) {\n            if (sox < tox) {\n                let y = tmy0;\n\n                if (tmy1 <= smy0 && tmx1 >= sox) {\n                    y = middleOfHorizontalSides;\n                }\n\n                return [\n                    { x: sox, y },\n                    { x: tox, y },\n                    { x: tox, y: toy }\n                ];\n            }\n\n            return [{ x: sox, y: toy }];\n        }\n\n        const x = Math.max(middleOfVerticalSides, tmx1);\n\n        if (sox > tox && sy1 >= toy) {\n            return [\n                { x: sox, y: soy },\n                { x, y: soy },\n                { x, y: toy }\n            ];\n        }\n\n        if (x > smx0 && soy < ty1) {\n            const y = Math.min(smy0, tmy0);\n            const x = Math.max(smx1, tmx1);\n            return [\n                { x: sox, y },\n                { x, y },\n                { x, y: toy }\n            ];\n        }\n\n        return [\n            { x: sox, y: soy },\n            { x, y: soy },\n            { x, y: toy }\n        ];\n    } else if (sourceSide === 'top' && targetSide === 'left') {\n        const isPointInsideSource = inflatedSourceBBox.containsPoint(targetPoint);\n\n        // The target point is inside the source element\n        if (isPointInsideSource) {\n            if (sox >= tmx0) {\n                const x = Math.min(sox - sourceMargin, tox);\n                const y = Math.min(smy0, tmy0);\n\n                // Target anchor is on the left side of the source anchor\n                return [\n                    { x: sox, y },\n                    { x: x, y },\n                    { x: x, y: toy }\n                ];\n            }\n\n            // Target anchor is on the right side of the source anchor\n            // Add the `sourceMargin` since the source anchor is on the left side of the target anchor\n            const anchorMiddleX = (sox + sourceMargin + tox) / 2;\n\n            return [\n                { x: sox, y: soy },\n                { x: anchorMiddleX, y: soy },\n                { x: anchorMiddleX, y: toy }\n            ];\n        }\n\n        if (smy0 > toy) {\n            if (sox > tox) {\n                let y = tmy0;\n\n                if (tmy1 <= smy0 && tmx0 <= sox) {\n                    y = middleOfHorizontalSides;\n                }\n\n                return [\n                    { x: sox, y },\n                    { x: tox, y },\n                    { x: tox, y: toy }\n                ];\n            }\n\n            return [{ x: sox, y: toy }];\n        }\n\n        const x = Math.min(tmx0, middleOfVerticalSides);\n\n        if (sox < tox && sy1 >= toy) {\n            return [\n                { x: sox, y: soy },\n                { x, y: soy },\n                { x, y: toy }];\n        }\n\n        if (x < smx1 && soy < ty1) {\n            const y = Math.min(smy0, tmy0);\n            const x = Math.min(smx0, tmx0);\n            return [\n                { x: sox, y },\n                { x, y },\n                { x, y: toy }\n            ];\n        }\n\n        return [\n            { x: sox, y: soy },\n            { x, y: soy },\n            { x, y: toy }\n        ];\n    } else if (sourceSide === 'bottom' && targetSide === 'right') {\n        const isPointInsideSource = inflatedSourceBBox.containsPoint(targetPoint);\n\n        // The target point is inside the source element\n        if (isPointInsideSource) {\n            if (sox <= tmx1) {\n                const x = Math.max(sox + sourceMargin, tox);\n                const y = Math.max(smy1, tmy1);\n\n                // Target anchor is on the right side of the source anchor\n                return [\n                    { x: sox, y },\n                    { x, y },\n                    { x, y: toy }\n                ];\n            }\n\n            // Target anchor is on the left side of the source anchor\n            // Subtract the `sourceMargin` since the source anchor is on the right side of the target anchor\n            const anchorMiddleX = (sox - sourceMargin + tox) / 2;\n\n            return [\n                { x: sox, y: soy },\n                { x: anchorMiddleX, y: soy },\n                { x: anchorMiddleX, y: toy }\n            ];\n        }\n\n        if (smy1 < toy) {\n            if (sox < tox) {\n                let y = tmy1;\n\n                if (tmy0 >= smy1 && tmx1 >= sox) {\n                    y = middleOfHorizontalSides;\n                }\n\n                return [\n                    { x: sox, y },\n                    { x: tox, y },\n                    { x: tox, y: toy }\n                ];\n            }\n\n            return [{ x: sox, y: toy }];\n        }\n\n        const x = Math.max(middleOfVerticalSides, tmx1);\n\n        if (sox > tox && sy0 <= toy) {\n            return [\n                { x: sox, y: soy },\n                { x, y: soy },\n                { x, y: toy }\n            ];\n        }\n\n        if (x > smx0 && soy > ty0) {\n            const y = Math.max(smy1, tmy1);\n            const x = Math.max(smx1, tmx1);\n            return [\n                { x: sox, y },\n                { x, y },\n                { x, y: toy }\n            ];\n        }\n\n        return [\n            { x: sox, y: soy },\n            { x, y: soy },\n            { x, y: toy }\n        ];\n    } else if (sourceSide === 'bottom' && targetSide === 'left') {\n        const isPointInsideSource = inflatedSourceBBox.containsPoint(targetPoint);\n\n        // The target point is inside the source element\n        if (isPointInsideSource) {\n            if (sox >= tmx0) {\n                const x = Math.min(sox - sourceMargin, tox);\n                const y = Math.max(smy1, tmy1);\n\n                // Target anchor is on the left side of the source anchor\n                return [\n                    { x: sox, y },\n                    { x, y },\n                    { x, y: toy }\n                ];\n            }\n\n            // Target anchor is on the right side of the source anchor\n            // Add the `sourceMargin` since the source anchor is on the left side of the target anchor\n            const anchorMiddleX = (sox + sourceMargin + tox) / 2;\n\n            return [\n                { x: sox, y: soy },\n                { x: anchorMiddleX, y: soy },\n                { x: anchorMiddleX, y: toy }\n            ];\n        }\n\n        if (smy1 < toy) {\n            if (sox > tox) {\n                let y = tmy1;\n\n                if (tmy0 >= smy1 && tmx0 <= sox) {\n                    y = middleOfHorizontalSides;\n                }\n\n                return [\n                    { x: sox, y },\n                    { x: tox, y },\n                    { x: tox, y: toy }\n                ];\n            }\n\n            return [{ x: sox, y: toy }];\n        }\n\n        const x = Math.min(tmx0, middleOfVerticalSides);\n\n        if (sox < tox && sy0 <= toy) {\n            return [\n                { x: sox, y: soy },\n                { x, y: soy },\n                { x, y: toy }\n            ];\n        }\n\n        if (x < smx1 && soy > ty0) {\n            const y = Math.max(smy1, tmy1);\n            const x = Math.min(smx0, tmx0);\n            return [\n                { x: sox, y },\n                { x, y },\n                { x, y: toy }\n            ];\n        }\n\n        return [\n            { x: sox, y: soy },\n            { x, y: soy },\n            { x, y: toy }\n        ];\n    } else if (sourceSide === 'left' && targetSide === 'bottom') {\n        const isPointInsideSource = inflatedSourceBBox.containsPoint(targetPoint);\n\n        // The target point is inside the source element\n        if (isPointInsideSource) {\n            if (soy <= tmy1) {\n                const x = Math.min(smx0, tmx0);\n                const y = Math.max(soy + sourceMargin, toy);\n\n                return [\n                    { x, y: soy },\n                    { x, y },\n                    { x: tox, y }\n                ];\n            }\n\n            // Target anchor is above the source anchor\n            const anchorMiddleY = (soy - sourceMargin + toy) / 2;\n\n            return [\n                { x: sox, y: soy },\n                { x: sox, y: anchorMiddleY },\n                { x: tox, y: anchorMiddleY }\n            ];\n        }\n\n        if (smx0 > tox) {\n            if (soy < toy) {\n                let x = tmx0;\n\n                if (tmx1 <= smx0 && tmy1 >= soy) {\n                    x = middleOfVerticalSides;\n                }\n\n                return [\n                    { x, y: soy },\n                    { x, y: toy },\n                    { x: tox, y: toy }\n                ];\n            }\n\n            return [{ x: tox, y: soy }];\n        }\n\n        const y = Math.max(tmy1, middleOfHorizontalSides);\n\n        if (soy > toy && sx1 >= tox) {\n            return [\n                { x: sox, y: soy },\n                { x: sox, y },\n                { x: tox, y }\n            ];\n        }\n\n        if (y > smy0 && sox < tx1) {\n            const x = Math.min(smx0, tmx0);\n            const y = Math.max(smy1, tmy1);\n\n            return [\n                { x, y: soy },\n                { x, y },\n                { x: tox, y }\n            ];\n        }\n\n        return [\n            { x: sox, y: soy },\n            { x: sox, y },\n            { x: tox, y }\n        ];\n    } else if (sourceSide === 'left' && targetSide === 'top') {\n        const isPointInsideSource = inflatedSourceBBox.containsPoint(targetPoint);\n\n        // The target point is inside the source element\n        if (isPointInsideSource) {\n            if (soy >= tmy0) {\n                const y = Math.min(soy - sourceMargin, toy);\n                const x = Math.min(smx0, tmx0);\n\n                // Target anchor is on the top side of the source anchor\n                return [\n                    { x, y: soy },\n                    { x, y },\n                    { x: tox, y }\n                ];\n            }\n\n            // Target anchor is below the source anchor\n            // Add the `sourceMargin` since the source anchor is above the target anchor\n            const anchorMiddleY = (soy + sourceMargin + toy) / 2;\n\n            return [\n                { x: sox, y: soy },\n                { x: sox, y: anchorMiddleY },\n                { x: tox, y: anchorMiddleY }\n            ];\n        }\n\n        if (smx0 > tox) {\n            if (soy > toy) {\n                let x = tmx0;\n\n                if (tmx1 <= smx0 && tmy0 <= soy) {\n                    x = middleOfVerticalSides;\n                }\n\n                return [\n                    { x, y: soy },\n                    { x, y: toy },\n                    { x: tox, y: toy }\n                ];\n            }\n\n            return [{ x: tox, y: soy }];\n        }\n\n        const y = Math.min(tmy0, middleOfHorizontalSides);\n\n        if (soy < toy && sx1 >= tox) {\n            return [\n                { x: sox, y: soy },\n                { x: sox, y },\n                { x: tox, y }];\n        }\n\n        if (y < smy1 && sox < tx1) {\n            const x = Math.min(smx0, tmx0);\n            const y = Math.min(smy0, tmy0);\n            return [\n                { x, y: soy },\n                { x, y },\n                { x: tox, y }\n            ];\n        }\n\n        return [\n            { x: sox, y: soy },\n            { x: sox, y },\n            { x: tox, y }\n        ];\n    } else if (sourceSide === 'right' && targetSide === 'top') {\n        const isPointInsideSource = inflatedSourceBBox.containsPoint(targetPoint);\n\n        // The target point is inside the source element\n        if (isPointInsideSource) {\n            if (soy >= tmy0) {\n                const x = Math.max(smx1, tmx1);\n                const y = Math.min(soy - sourceMargin, toy);\n\n                // Target anchor is on the top side of the source anchor\n                return [\n                    { x, y: soy },\n                    { x, y }, // Path adjustment for right side start\n                    { x: tox, y }\n                ];\n            }\n\n            // Target anchor is below the source anchor\n            // Adjust sourceMargin calculation since the source anchor is now on the right\n            const anchorMiddleY = (soy + sourceMargin + toy) / 2;\n\n            return [\n                { x: sox, y: soy },\n                { x: sox, y: anchorMiddleY },\n                { x: tox, y: anchorMiddleY }\n            ];\n        }\n\n        if (smx1 < tox) {\n            if (soy > toy) {\n                let x = tmx1;\n\n                if (tmx0 >= smx1 && tmy0 <= soy) {\n                    x = middleOfVerticalSides;\n                }\n\n                return [\n                    { x, y: soy },\n                    { x, y: toy },\n                    { x: tox, y: toy }\n                ];\n            }\n\n            return [{ x: tox, y: soy }];\n        }\n\n        const y = Math.min(tmy0, middleOfHorizontalSides);\n\n        if (soy < toy && sx0 <= tox) {\n            return [\n                { x: sox, y: soy },\n                { x: sox, y },\n                { x: tox, y }];\n        }\n\n        if (y < smy1 && sox > tx0) {\n            const x = Math.max(smx1, tmx1);\n            const y = Math.min(smy0, tmy0);\n\n            return [\n                { x, y: soy },\n                { x, y },\n                { x: tox, y }\n            ];\n        }\n\n        return [\n            { x: sox, y: soy },\n            { x: sox, y },\n            { x: tox, y }\n        ];\n    } else if (sourceSide === 'right' && targetSide === 'bottom') {\n        const isPointInsideSource = inflatedSourceBBox.containsPoint(targetPoint);\n\n        // The target point is inside the source element\n        if (isPointInsideSource) {\n            if (soy <= tmy1) {\n                const x = Math.max(smx1, tmx1);\n                const y = Math.max(soy + sourceMargin, toy);\n\n                return [\n                    { x, y: soy },\n                    { x, y },\n                    { x: tox, y }\n                ];\n            }\n\n            // Target anchor is above the source anchor\n            const anchorMiddleY = (soy - sourceMargin + toy) / 2;\n\n            return [\n                { x: sox, y: soy },\n                { x: sox, y: anchorMiddleY },\n                { x: tox, y: anchorMiddleY }\n            ];\n        }\n\n        if (smx1 < tox) {\n            if (soy < toy) {\n                let x = tmx1;\n\n                if (tmx0 >= smx1 && tmy1 >= soy) {\n                    x = middleOfVerticalSides;\n                }\n\n                return [\n                    { x, y: soy },\n                    { x, y: toy },\n                    { x: tox, y: toy }\n                ];\n            }\n\n            return [{ x: tox, y: soy }];\n        }\n\n        const y = Math.max(tmy1, middleOfHorizontalSides);\n\n        if (soy > toy && sx0 <= tox) {\n            return [\n                { x: sox, y: soy },\n                { x: sox, y },\n                { x: tox, y }\n            ];\n        }\n\n        if (y > smy0 && sox > tx0) {\n            const x = Math.max(smx1, tmx1);\n            const y = Math.max(smy1, tmy1);\n\n            return [\n                { x, y: soy },\n                { x, y },\n                { x: tox, y }\n            ];\n        }\n\n        return [\n            { x: sox, y: soy },\n            { x: sox, y },\n            { x: tox, y }\n        ];\n    }\n}\n\nfunction getLoopCoordinates(direction, angle, margin) {\n    const isHorizontal = direction === Directions.LEFT || direction === Directions.RIGHT;\n\n    let dx = 0;\n    let dy = 0;\n\n    switch (g.normalizeAngle(Math.round(angle))) {\n        case 0:\n        case 90:\n            dx = isHorizontal ? 0 : margin;\n            dy = isHorizontal ? margin : 0;\n            break;\n        case 180:\n        case 270:\n            dx = isHorizontal ? 0 : -margin;\n            dy = isHorizontal ? -margin : 0;\n            break;\n    }\n\n    return { dx, dy };\n}\n\nfunction rightAngleRouter(vertices, opt, linkView) {\n    const { sourceDirection = Directions.AUTO, targetDirection = Directions.AUTO } = opt;\n    const margin = opt.margin || 20;\n    const useVertices = opt.useVertices || false;\n\n    const isSourcePort = !!linkView.model.source().port;\n    const sourcePoint = pointDataFromAnchor(linkView.sourceView, linkView.sourceAnchor, linkView.sourceBBox, sourceDirection, isSourcePort, linkView.sourceAnchor, margin);\n\n    const isTargetPort = !!linkView.model.target().port;\n    const targetPoint = pointDataFromAnchor(linkView.targetView, linkView.targetAnchor, linkView.targetBBox, targetDirection, isTargetPort, linkView.targetAnchor, margin);\n\n    let resultVertices = [];\n\n    if (!useVertices || vertices.length === 0) {\n        return simplifyPoints(routeBetweenPoints(sourcePoint, targetPoint));\n    }\n\n    const verticesData = vertices.map((v) => pointDataFromVertex(v));\n    const [firstVertex] = verticesData;\n\n    const [resolvedSourceDirection] = resolveSides(sourcePoint, firstVertex);\n    const isElement = sourcePoint.view && sourcePoint.view.model.isElement();\n    const sourceBBox = isElement ? moveAndExpandBBox(sourcePoint.view.model.getBBox(), resolvedSourceDirection, margin) : null;\n    const isVertexInside = isElement ? sourceBBox.containsPoint(firstVertex.point) : false;\n\n    if (isVertexInside) {\n        const outsidePoint = getOutsidePoint(resolvedSourceDirection, sourcePoint, margin);\n        const firstPointOverlap = outsidePoint.equals(firstVertex.point);\n\n        const alignsVertically = sourcePoint.point.x === firstVertex.point.x;\n        const alignsHorizontally = sourcePoint.point.y === firstVertex.point.y;\n\n        const isVerticalAndAligns = alignsVertically && (resolvedSourceDirection === Directions.TOP || resolvedSourceDirection === Directions.BOTTOM);\n        const isHorizontalAndAligns = alignsHorizontally && (resolvedSourceDirection === Directions.LEFT || resolvedSourceDirection === Directions.RIGHT);\n\n        const firstSegment = new g.Line(sourcePoint.point, outsidePoint);\n        const isVertexOnSegment = firstSegment.containsPoint(firstVertex.point);\n\n        const isVertexAlignedAndInside = isVertexInside && (isHorizontalAndAligns || isVerticalAndAligns);\n\n        \n\n        if (firstPointOverlap) {\n            resultVertices.push(sourcePoint.point, firstVertex.point);\n            // Set the access direction as the opposite of the source direction that will be used to connect the route with the next vertex\n            firstVertex.direction = OPPOSITE_DIRECTIONS[resolvedSourceDirection];\n        } else if (isVertexOnSegment || isVertexAlignedAndInside) {\n            // Case where there is a need to create a loop\n            const angle = getSegmentAngle(isVertexOnSegment ? firstSegment : new g.Line(sourcePoint.point, firstVertex.point));\n            const { dx, dy } = getLoopCoordinates(resolvedSourceDirection, angle, margin);\n\n            const loop = createLoop({ point: outsidePoint }, firstVertex, { dx, dy });\n            const secondCreatedPoint = loop[2];\n            const loopEndSegment = new g.Line(firstVertex.point, secondCreatedPoint);\n\n            const accessDirection = ANGLE_DIRECTION_MAP[getSegmentAngle(loopEndSegment)];\n            firstVertex.direction = accessDirection;\n            resultVertices.push(...loop);\n        } else {\n            // No need to create a route, use the `routeBetweenPoints` to construct a route\n            firstVertex.direction = resolvedSourceDirection;\n            firstVertex.margin = margin;\n            resultVertices.push(...routeBetweenPoints(sourcePoint, firstVertex, { targetInSourceBBox: true }), firstVertex.point);\n        }\n    } else {\n        // The first point responsible for the initial direction of the route\n        const next = verticesData[1] || targetPoint;\n        const direction = resolveInitialDirection(sourcePoint, firstVertex, next);\n        firstVertex.direction = direction;\n\n        resultVertices.push(...routeBetweenPoints(sourcePoint, firstVertex), firstVertex.point);\n    }\n\n    for (let i = 0; i < verticesData.length - 1; i++) {\n        const from = verticesData[i];\n        const to = verticesData[i + 1];\n\n        const connectionSegment = new g.Line(from.point, to.point);\n        const connectionSegmentAngle = getSegmentAngle(connectionSegment);\n        if (connectionSegmentAngle % 90 === 0) {\n            // Segment is horizontal or vertical\n            const connectionDirection = ANGLE_DIRECTION_MAP[connectionSegmentAngle];\n\n            const simplifiedRoute = simplifyPoints([...resultVertices, from.point]);\n            // const simplifiedRoute2 = simplifyPoints([from.point, ...resultVertices]);\n            // Find out the direction that is used to connect the current route with the next vertex\n            const accessSegment = new g.Line(simplifiedRoute[simplifiedRoute.length - 2], simplifiedRoute[simplifiedRoute.length - 1]);\n            // const accessSegment2 = new g.Line(simplifiedRoute2[simplifiedRoute2.length - 2], simplifiedRoute2[simplifiedRoute2.length - 1]);\n            const accessDirection = ANGLE_DIRECTION_MAP[Math.round(getSegmentAngle(accessSegment))];\n            // const accessDirection2 = ANGLE_DIRECTION_MAP[Math.round(getSegmentAngle(accessSegment2))];\n            // console.log(accessDirection);\n            // console.log(accessDirection2);\n            // if (accessDirection !== accessDirection2) {\n            //     console.log('error');\n            // }\n            // console.log('------------------');\n\n            if (connectionDirection !== OPPOSITE_DIRECTIONS[accessDirection]) {\n                // The directions are not opposite, so we can connect the vertices directly\n                resultVertices.push(from.point, to.point);\n                const [, toDirection] = resolveSides(from, to);\n                to.direction = toDirection;\n            } else {\n                // The directions are overlapping, so we need to create a loop\n                const { loopRoute, continueDirection } = loopSegment(from, to, connectionSegmentAngle, margin);\n                to.direction = continueDirection;\n                // Constructing a loop\n                resultVertices.push(...loopRoute);\n            }\n\n            continue;\n        }\n\n        // Vertices are not aligned vertically nor horizontally\n        // so we need to route between them\n\n        const [fromDirection, toDirection] = resolveDirection(from, to);\n\n        from.direction = fromDirection;\n        to.direction = toDirection;\n\n        resultVertices.push(...routeBetweenPoints(from, to), to.point);\n    }\n\n    const lastVertex = verticesData[verticesData.length - 1];\n\n    if (targetPoint.view && targetPoint.view.model.isElement()) {\n        const [, resolvedTargetDirection] = resolveSides(lastVertex, targetPoint);\n        const outsidePoint = getOutsidePoint(resolvedTargetDirection, targetPoint, margin);\n\n        // the last point of `simplified` array is the last defined vertex\n        // this will ensure that the last segment continues in a straight line\n        const simplified = simplifyPoints([...resultVertices, lastVertex.point]);\n        const simplifiedSegment = new g.Line(simplified[simplified.length - 2], simplified[simplified.length - 1]);\n        const simplifiedSegmentAngle = Math.round(getSegmentAngle(simplifiedSegment));\n        const definedDirection = ANGLE_DIRECTION_MAP[simplifiedSegmentAngle];\n\n        const lastPointOverlap = outsidePoint.equals(lastVertex.point);\n\n        if (!lastPointOverlap || (lastPointOverlap && definedDirection === resolvedTargetDirection)) {\n\n            lastVertex.direction = definedDirection;\n\n            let lastSegmentRoute = routeBetweenPoints(lastVertex, targetPoint);\n            const [p1, p2] = simplifyPoints([...lastSegmentRoute, targetPoint.point]);\n\n            const lastSegment = new g.Line(p1, p2);\n            const roundedLastSegmentAngle = Math.round(getSegmentAngle(lastSegment));\n            const lastSegmentDirection = ANGLE_DIRECTION_MAP[roundedLastSegmentAngle];\n\n            const targetBBox = moveAndExpandBBox(targetPoint.view.model.getBBox(), resolvedTargetDirection, margin);\n\n            const alignsVertically = lastVertex.point.x === targetPoint.point.x;\n            const alignsHorizontally = lastVertex.point.y === targetPoint.point.y;\n            const isVertexInside = targetBBox.containsPoint(lastVertex.point);\n\n            const isVerticalAndAligns = alignsVertically && (resolvedTargetDirection === Directions.TOP || resolvedTargetDirection === Directions.BOTTOM);\n            const isHorizontalAndAligns = alignsHorizontally && (resolvedTargetDirection === Directions.LEFT || resolvedTargetDirection === Directions.RIGHT);\n\n            \n            if (!lastPointOverlap && isVertexInside && (isHorizontalAndAligns || isVerticalAndAligns)) {\n                // Handle special cases when the last vertex is inside the target element\n                // and in is aligned with the connection point => construct a loop\n                const { dx, dy } = getLoopCoordinates(resolvedTargetDirection, simplifiedSegmentAngle, margin);\n                lastSegmentRoute = createLoop(lastVertex, { point: outsidePoint }, { dx, dy });\n            } else if (isVertexInside && resolvedTargetDirection !== OPPOSITE_DIRECTIONS[definedDirection]) {\n                lastVertex.margin = margin;\n                lastVertex.direction = resolvedTargetDirection;\n                lastSegmentRoute = routeBetweenPoints(lastVertex, targetPoint);\n            } else if (lastSegmentDirection !== definedDirection && definedDirection === OPPOSITE_DIRECTIONS[lastSegmentDirection]) {\n                lastVertex.margin = margin;\n                lastSegmentRoute = routeBetweenPoints(lastVertex, targetPoint);\n            }\n\n            resultVertices.push(...lastSegmentRoute);\n        }\n    } else {\n        // since the target is only a point we can apply the same logic as if we connected two verticesData\n        const from = lastVertex;\n        const to = targetPoint;\n\n        const connectionSegment = new g.Line(from.point, to.point);\n        const connectionSegmentAngle = getSegmentAngle(connectionSegment);\n        if (connectionSegmentAngle % 90 === 0) {\n            // Segment is horizontal or vertical\n            const connectionDirection = ANGLE_DIRECTION_MAP[connectionSegmentAngle];\n\n            const simplifiedRoute = simplifyPoints(resultVertices);\n            // Find out the direction that is used to connect the current route with the next vertex\n            const accessSegment = new g.Line(simplifiedRoute[simplifiedRoute.length - 2], from.point);\n            const accessDirection = ANGLE_DIRECTION_MAP[Math.round(getSegmentAngle(accessSegment))];\n\n            if (connectionDirection !== OPPOSITE_DIRECTIONS[accessDirection]) {\n                // The directions are not opposite, so we can connect the vertices directly by adding the first point\n                // the target point is handled separately\n                resultVertices.push(from.point);\n            } else {\n                // The directions are overlapping, so we need to create a loop\n                const { loopRoute } = loopSegment(from, to, connectionSegmentAngle, margin);\n                // Remove the last point since it is the target that is handled separately\n                loopRoute.pop();\n                // Constructing a loop\n                resultVertices.push(...loopRoute);\n            }\n        } else {\n            // The last vertex and the target are not aligned vertically nor horizontally\n            // so we need to route between them\n            const [fromDirection, toDirection] = resolveDirection(from, to);\n\n            from.direction = fromDirection;\n            to.direction = toDirection;\n\n            resultVertices.push(...routeBetweenPoints(from, to));\n        }\n    }\n\n    return simplifyPoints(resultVertices);\n}\n\nfunction resolveDirection(from, to) {\n    const accessDirection = from.direction;\n    const isDirectionVertical = VERTICAL_DIRECTIONS.includes(accessDirection);\n\n    let sourceDirection = from.direction;\n    let targetDirection = to.direction;\n\n    if (isDirectionVertical) {\n        const isToAbove = from.point.y > to.point.y;\n        const dx = to.point.x - from.point.x;\n\n        if (accessDirection === Directions.BOTTOM) {\n            // If isToAbove === false and we need figure out if to go left or right\n            sourceDirection = isToAbove ? OPPOSITE_DIRECTIONS[accessDirection] : dx >= 0 ? Directions.RIGHT : Directions.LEFT;\n\n            if (dx > 0) {\n                targetDirection = isToAbove ? Directions.LEFT : Directions.TOP;\n            } else if (dx < 0) {\n                targetDirection = isToAbove ? Directions.RIGHT : Directions.TOP;\n            }\n        } else {\n            // If isToAbove === true and we need figure out if to go left or right\n            sourceDirection = isToAbove ? dx >= 0 ? Directions.RIGHT : Directions.LEFT : OPPOSITE_DIRECTIONS[accessDirection];\n\n            if (dx > 0) {\n                targetDirection = isToAbove ? Directions.BOTTOM : Directions.LEFT;\n            } else if (dx < 0) {\n                targetDirection = isToAbove ? Directions.BOTTOM : Directions.RIGHT;\n            }\n        }\n    } else {\n        const isToLeft = from.point.x > to.point.x;\n        const dy = to.point.y - from.point.y;\n\n        if (accessDirection === Directions.RIGHT) {\n            sourceDirection = isToLeft ? OPPOSITE_DIRECTIONS[accessDirection] : dy >= 0 ? Directions.BOTTOM : Directions.TOP;\n\n            if (dy > 0) {\n                targetDirection = isToLeft ? Directions.TOP : Directions.LEFT;\n            } else if (dy < 0) {\n                targetDirection = isToLeft ? Directions.BOTTOM : Directions.LEFT;\n            }\n        } else {\n            sourceDirection = isToLeft ? dy >= 0 ? Directions.BOTTOM : Directions.TOP : OPPOSITE_DIRECTIONS[accessDirection];\n\n            if (dy > 0) {\n                targetDirection = isToLeft ? Directions.RIGHT : Directions.TOP;\n            } else if (dy < 0) {\n                targetDirection = isToLeft ? Directions.RIGHT : Directions.BOTTOM;\n            }\n        }\n    }\n\n    return [sourceDirection, targetDirection];\n}\n\nrightAngleRouter.Directions = Directions;\n\nexport const rightAngle = rightAngleRouter;\n","import * as g from '../g/index.mjs';\n\nconst CornerTypes = {\n    POINT: 'point',\n    CUBIC: 'cubic',\n    LINE: 'line',\n    GAP: 'gap'\n};\n\nconst DEFINED_CORNER_TYPES = Object.values(CornerTypes);\n\nconst CORNER_RADIUS = 10;\nconst PRECISION = 1;\n\nexport const straight = function(sourcePoint, targetPoint, routePoints = [], opt = {}) {\n\n    const {\n        cornerType = CornerTypes.POINT,\n        cornerRadius = CORNER_RADIUS,\n        cornerPreserveAspectRatio = false,\n        precision = PRECISION,\n        raw = false\n    } = opt;\n\n    if (DEFINED_CORNER_TYPES.indexOf(cornerType) === -1) {\n        // unknown `cornerType` provided => error\n        throw new Error('Invalid `cornerType` provided to `straight` connector.');\n    }\n\n    let path;\n\n    if ((cornerType === CornerTypes.POINT) || !cornerRadius) {\n        // default option => normal connector\n        // simply connect all points with straight lines\n        const points = [sourcePoint].concat(routePoints).concat([targetPoint]);\n        const polyline = new g.Polyline(points);\n        path = new g.Path(polyline);\n\n    } else {\n        // `cornerType` is not unknown and not 'point' (default) => must be one of other valid types\n        path = new g.Path();\n\n        // add initial gap segment = to source point\n        path.appendSegment(g.Path.createSegment('M', sourcePoint));\n\n        let nextDistance;\n        const routePointsLength = routePoints.length;\n        for (let i = 0; i < routePointsLength; i++) {\n\n            const curr = new g.Point(routePoints[i]);\n            const prev = (routePoints[i - 1] || sourcePoint);\n            const next = (routePoints[i + 1] || targetPoint);\n            const prevDistance = (nextDistance || (curr.distance(prev) / 2)); // try to re-use previously-computed `nextDistance`\n            nextDistance = (curr.distance(next) / 2);\n\n            let startMove, endMove;\n            if (!cornerPreserveAspectRatio) {\n                // `startMove` and `endMove` may be different\n                // (this happens when next or previous path point is closer than `2 * cornerRadius`)\n                startMove = -Math.min(cornerRadius, prevDistance);\n                endMove = -Math.min(cornerRadius, nextDistance);\n            } else {\n                // force `startMove` and `endMove` to be the same\n                startMove = endMove = -Math.min(cornerRadius, prevDistance, nextDistance);\n            }\n\n            // to find `cornerStart` and `cornerEnd`, the logic is as follows (using `cornerStart` as example):\n            // - find a point lying on the line `prev - startMove` such that...\n            // - ...the point lies `abs(startMove)` distance away from `curr`...\n            // - ...and its coordinates are rounded to whole numbers\n            const cornerStart = curr.clone().move(prev, startMove).round(precision);\n            const cornerEnd = curr.clone().move(next, endMove).round(precision);\n\n            // add in-between straight segment = from previous route point to corner start point\n            // (may have zero length)\n            path.appendSegment(g.Path.createSegment('L', cornerStart));\n\n            // add corner segment = from corner start point to corner end point\n            switch (cornerType) {\n                case CornerTypes.CUBIC: {\n                    // corner is rounded\n                    const _13 = (1 / 3);\n                    const _23 = (2 / 3);\n                    const control1 = new g.Point((_13 * cornerStart.x) + (_23 * curr.x), (_23 * curr.y) + (_13 * cornerStart.y));\n                    const control2 = new g.Point((_13 * cornerEnd.x) + (_23 * curr.x), (_23 * curr.y) + (_13 * cornerEnd.y));\n                    path.appendSegment(g.Path.createSegment('C', control1, control2, cornerEnd));\n                    break;\n                }\n                case CornerTypes.LINE: {\n                    // corner has bevel\n                    path.appendSegment(g.Path.createSegment('L', cornerEnd));\n                    break;\n                }\n                case CornerTypes.GAP: {\n                    // corner has empty space\n                    path.appendSegment(g.Path.createSegment('M', cornerEnd));\n                    break;\n                }\n                // default: no segment is created\n            }\n        }\n\n        // add final straight segment = from last corner end point to target point\n        // (= or from start point to end point, if there are no route points)\n        // (may have zero length)\n        path.appendSegment(g.Path.createSegment('L', targetPoint));\n    }\n\n    return ((raw) ? path : path.serialize());\n};\n","import * as util from '../util/index.mjs';\nimport * as g from '../g/index.mjs';\n\n// default size of jump if not specified in options\nvar JUMP_SIZE = 5;\n\n// available jump types\n// first one taken as default\nvar JUMP_TYPES = ['arc', 'gap', 'cubic'];\n\n// default radius\nvar RADIUS = 0;\n\n// takes care of math. error for case when jump is too close to end of line\nvar CLOSE_PROXIMITY_PADDING = 1;\n\n// list of connector types not to jump over.\nvar IGNORED_CONNECTORS = ['smooth'];\n\n// internal constants for round segment\nvar _13 = 1 / 3;\nvar _23 = 2 / 3;\n\nfunction sortPointsAscending(p1, p2) {\n\n    let { x: x1, y: y1 } = p1;\n    let { x: x2, y: y2 } = p2;\n\n    if (x1 > x2) {\n\n        let swap = x1;\n        x1 = x2;\n        x2 = swap;\n\n        swap = y1;\n        y1 = y2;\n        y2 = swap;\n    }\n\n    if (y1 > y2) {\n        let swap = x1;\n        x1 = x2;\n        x2 = swap;\n\n        swap = y1;\n        y1 = y2;\n        y2 = swap;\n    }\n\n    return [new g.Point(x1, y1), new g.Point(x2, y2)];\n}\n\nfunction overlapExists(line1, line2) {\n\n    const [{ x: x1, y: y1 }, { x: x2, y: y2 }] = sortPointsAscending(line1.start, line1.end);\n    const [{ x: x3, y: y3 }, { x: x4, y: y4 }] = sortPointsAscending(line2.start, line2.end);\n\n    const xMatch = x1 <= x4 && x3 <= x2;\n    const yMatch = y1 <= y4 && y3 <= y2;\n\n    return xMatch && yMatch;\n}\n\n/**\n * Transform start/end and route into series of lines\n * @param {g.point} sourcePoint start point\n * @param {g.point} targetPoint end point\n * @param {g.point[]} route optional list of route\n * @return {g.line[]} [description]\n */\nfunction createLines(sourcePoint, targetPoint, route) {\n    // make a flattened array of all points\n    var points = [].concat(sourcePoint, route, targetPoint);\n    return points.reduce(function(resultLines, point, idx) {\n        // if there is a next point, make a line with it\n        var nextPoint = points[idx + 1];\n        if (nextPoint != null) {\n            resultLines[idx] = g.line(point, nextPoint);\n        }\n        return resultLines;\n    }, []);\n}\n\nfunction setupUpdating(jumpOverLinkView) {\n    var paper = jumpOverLinkView.paper;\n    var updateList = paper._jumpOverUpdateList;\n\n    // first time setup for this paper\n    if (updateList == null) {\n        updateList = paper._jumpOverUpdateList = [];\n        var graph = paper.model;\n        graph.on('batch:stop', function() {\n            if (this.hasActiveBatch()) return;\n            updateJumpOver(paper);\n        });\n        graph.on('reset', function() {\n            updateList = paper._jumpOverUpdateList = [];\n        });\n    }\n\n    // add this link to a list so it can be updated when some other link is updated\n    if (updateList.indexOf(jumpOverLinkView) < 0) {\n        updateList.push(jumpOverLinkView);\n\n        // watch for change of connector type or removal of link itself\n        // to remove the link from a list of jump over connectors\n        jumpOverLinkView.listenToOnce(jumpOverLinkView.model, 'change:connector remove', function() {\n            updateList.splice(updateList.indexOf(jumpOverLinkView), 1);\n        });\n    }\n}\n\n/**\n * Handler for a batch:stop event to force\n * update of all registered links with jump over connector\n * @param {object} batchEvent optional object with info about batch\n */\nfunction updateJumpOver(paper) {\n    var updateList = paper._jumpOverUpdateList;\n    for (var i = 0; i < updateList.length; i++) {\n        const linkView = updateList[i];\n        const updateFlag = linkView.getFlag(linkView.constructor.Flags.CONNECTOR);\n        linkView.requestUpdate(updateFlag);\n    }\n}\n\n/**\n * Utility function to collect all intersection points of a single\n * line against group of other lines.\n * @param {g.line} line where to find points\n * @param {g.line[]} crossCheckLines lines to cross\n * @return {g.point[]} list of intersection points\n */\nfunction findLineIntersections(line, crossCheckLines) {\n    return util.toArray(crossCheckLines).reduce(function(res, crossCheckLine) {\n        var intersection = line.intersection(crossCheckLine);\n        if (intersection) {\n            res.push(intersection);\n        }\n        return res;\n    }, []);\n}\n\n/**\n * Sorting function for list of points by their distance.\n * @param {g.point} p1 first point\n * @param {g.point} p2 second point\n * @return {number} squared distance between points\n */\nfunction sortPoints(p1, p2) {\n    return g.line(p1, p2).squaredLength();\n}\n\n/**\n * Split input line into multiple based on intersection points.\n * @param {g.line} line input line to split\n * @param {g.point[]} intersections points where to split the line\n * @param {number} jumpSize the size of jump arc (length empty spot on a line)\n * @return {g.line[]} list of lines being split\n */\nfunction createJumps(line, intersections, jumpSize) {\n    return intersections.reduce(function(resultLines, point, idx) {\n        // skipping points that were merged with the previous line\n        // to make bigger arc over multiple lines that are close to each other\n        if (point.skip === true) {\n            return resultLines;\n        }\n\n        // always grab the last line from buffer and modify it\n        var lastLine = resultLines.pop() || line;\n\n        // calculate start and end of jump by moving by a given size of jump\n        var jumpStart = g.point(point).move(lastLine.start, -(jumpSize));\n        var jumpEnd = g.point(point).move(lastLine.start, +(jumpSize));\n\n        // now try to look at the next intersection point\n        var nextPoint = intersections[idx + 1];\n        if (nextPoint != null) {\n            var distance = jumpEnd.distance(nextPoint);\n            if (distance <= jumpSize) {\n                // next point is close enough, move the jump end by this\n                // difference and mark the next point to be skipped\n                jumpEnd = nextPoint.move(lastLine.start, distance);\n                nextPoint.skip = true;\n            }\n        } else {\n            // this block is inside of `else` as an optimization so the distance is\n            // not calculated when we know there are no other intersection points\n            var endDistance = jumpStart.distance(lastLine.end);\n            // if the end is too close to possible jump, draw remaining line instead of a jump\n            if (endDistance < jumpSize * 2 + CLOSE_PROXIMITY_PADDING) {\n                resultLines.push(lastLine);\n                return resultLines;\n            }\n        }\n\n        var startDistance = jumpEnd.distance(lastLine.start);\n        if (startDistance < jumpSize * 2 + CLOSE_PROXIMITY_PADDING) {\n            // if the start of line is too close to jump, draw that line instead of a jump\n            resultLines.push(lastLine);\n            return resultLines;\n        }\n\n        // finally create a jump line\n        var jumpLine = g.line(jumpStart, jumpEnd);\n        // it's just simple line but with a `isJump` property\n        jumpLine.isJump = true;\n\n        resultLines.push(\n            g.line(lastLine.start, jumpStart),\n            jumpLine,\n            g.line(jumpEnd, lastLine.end)\n        );\n        return resultLines;\n    }, []);\n}\n\n/**\n * Assemble `D` attribute of a SVG path by iterating given lines.\n * @param {g.line[]} lines source lines to use\n * @param {number} jumpSize the size of jump arc (length empty spot on a line)\n * @param {number} radius the radius\n * @return {string}\n */\nfunction buildPath(lines, jumpSize, jumpType, radius) {\n\n    var path = new g.Path();\n    var segment;\n\n    // first move to the start of a first line\n    segment = g.Path.createSegment('M', lines[0].start);\n    path.appendSegment(segment);\n\n    // make a paths from lines\n    util.toArray(lines).forEach(function(line, index) {\n\n        if (line.isJump) {\n            var angle, diff;\n\n            var control1, control2;\n\n            if (jumpType === 'arc') { // approximates semicircle with 2 curves\n                angle = -90;\n                // determine rotation of arc based on difference between points\n                diff = line.start.difference(line.end);\n                // make sure the arc always points up (or right)\n                var xAxisRotate = Number((diff.x < 0) || (diff.x === 0 && diff.y < 0));\n                if (xAxisRotate) angle += 180;\n\n                var midpoint = line.midpoint();\n                var centerLine = new g.Line(midpoint, line.end).rotate(midpoint, angle);\n\n                var halfLine;\n\n                // first half\n                halfLine = new g.Line(line.start, midpoint);\n\n                control1 = halfLine.pointAt(2 / 3).rotate(line.start, angle);\n                control2 = centerLine.pointAt(1 / 3).rotate(centerLine.end, -angle);\n\n                segment = g.Path.createSegment('C', control1, control2, centerLine.end);\n                path.appendSegment(segment);\n\n                // second half\n                halfLine = new g.Line(midpoint, line.end);\n\n                control1 = centerLine.pointAt(1 / 3).rotate(centerLine.end, angle);\n                control2 = halfLine.pointAt(1 / 3).rotate(line.end, -angle);\n\n                segment = g.Path.createSegment('C', control1, control2, line.end);\n                path.appendSegment(segment);\n\n            } else if (jumpType === 'gap') {\n                segment = g.Path.createSegment('M', line.end);\n                path.appendSegment(segment);\n\n            } else if (jumpType === 'cubic') { // approximates semicircle with 1 curve\n                angle = line.start.theta(line.end);\n\n                var xOffset = jumpSize * 0.6;\n                var yOffset = jumpSize * 1.35;\n\n                // determine rotation of arc based on difference between points\n                diff = line.start.difference(line.end);\n                // make sure the arc always points up (or right)\n                xAxisRotate = Number((diff.x < 0) || (diff.x === 0 && diff.y < 0));\n                if (xAxisRotate) yOffset *= -1;\n\n                control1 = g.Point(line.start.x + xOffset, line.start.y + yOffset).rotate(line.start, angle);\n                control2 = g.Point(line.end.x - xOffset, line.end.y + yOffset).rotate(line.end, angle);\n\n                segment = g.Path.createSegment('C', control1, control2, line.end);\n                path.appendSegment(segment);\n            }\n\n        } else {\n            var nextLine = lines[index + 1];\n            if (radius == 0 || !nextLine || nextLine.isJump) {\n                segment = g.Path.createSegment('L', line.end);\n                path.appendSegment(segment);\n            } else {\n                buildRoundedSegment(radius, path, line.end, line.start, nextLine.end);\n            }\n        }\n    });\n\n    return path;\n}\n\nfunction buildRoundedSegment(offset, path, curr, prev, next) {\n    var prevDistance = curr.distance(prev) / 2;\n    var nextDistance = curr.distance(next) / 2;\n\n    var startMove = -Math.min(offset, prevDistance);\n    var endMove = -Math.min(offset, nextDistance);\n\n    var roundedStart = curr.clone().move(prev, startMove).round();\n    var roundedEnd = curr.clone().move(next, endMove).round();\n\n    var control1 = new g.Point((_13 * roundedStart.x) + (_23 * curr.x), (_23 * curr.y) + (_13 * roundedStart.y));\n    var control2 = new g.Point((_13 * roundedEnd.x) + (_23 * curr.x), (_23 * curr.y) + (_13 * roundedEnd.y));\n\n    var segment;\n    segment = g.Path.createSegment('L', roundedStart);\n    path.appendSegment(segment);\n\n    segment = g.Path.createSegment('C', control1, control2, roundedEnd);\n    path.appendSegment(segment);\n}\n\n/**\n * Actual connector function that will be run on every update.\n * @param {g.point} sourcePoint start point of this link\n * @param {g.point} targetPoint end point of this link\n * @param {g.point[]} route of this link\n * @param {object} opt options\n * @property {number} size optional size of a jump arc\n * @return {string} created `D` attribute of SVG path\n */\nexport const jumpover = function(sourcePoint, targetPoint, route, opt) { // eslint-disable-line max-params\n\n    setupUpdating(this);\n\n    var raw = opt.raw;\n    var jumpSize = opt.size || JUMP_SIZE;\n    var jumpType = opt.jump && ('' + opt.jump).toLowerCase();\n    var radius = opt.radius || RADIUS;\n    var ignoreConnectors = opt.ignoreConnectors || IGNORED_CONNECTORS;\n\n    // grab the first jump type as a default if specified one is invalid\n    if (JUMP_TYPES.indexOf(jumpType) === -1) {\n        jumpType = JUMP_TYPES[0];\n    }\n\n    var paper = this.paper;\n    var graph = paper.model;\n    var allLinks = graph.getLinks();\n\n    // there is just one link, draw it directly\n    if (allLinks.length === 1) {\n        return buildPath(\n            createLines(sourcePoint, targetPoint, route),\n            jumpSize, jumpType, radius\n        );\n    }\n\n    var thisModel = this.model;\n    var thisIndex = allLinks.indexOf(thisModel);\n    var defaultConnector = paper.options.defaultConnector || {};\n\n    // not all links are meant to be jumped over.\n    var links = allLinks.filter(function(link, idx) {\n\n        var connector = link.get('connector') || defaultConnector;\n\n        // avoid jumping over links with connector type listed in `ignored connectors`.\n        if (util.toArray(ignoreConnectors).includes(connector.name)) {\n            return false;\n        }\n        // filter out links that are above this one and  have the same connector type\n        // otherwise there would double hoops for each intersection\n        if (idx > thisIndex) {\n            return connector.name !== 'jumpover';\n        }\n        return true;\n    });\n\n    // find views for all links\n    var linkViews = links.map(function(link) {\n        return paper.findViewByModel(link);\n    });\n\n    // create lines for this link\n    var thisLines = createLines(\n        sourcePoint,\n        targetPoint,\n        route\n    );\n\n    // create lines for all other links\n    var linkLines = linkViews.map(function(linkView) {\n        if (linkView == null) {\n            return [];\n        }\n        if (linkView === this) {\n            return thisLines;\n        }\n        return createLines(\n            linkView.sourcePoint,\n            linkView.targetPoint,\n            linkView.route\n        );\n    }, this);\n\n    // transform lines for this link by splitting with jump lines at\n    // points of intersection with other links\n    var jumpingLines = thisLines.reduce(function(resultLines, thisLine) {\n        // iterate all links and grab the intersections with this line\n        // these are then sorted by distance so the line can be split more easily\n        var intersections = links.reduce(function(res, link, i) {\n            // don't intersection with itself\n            if (link !== thisModel) {\n\n                const linkLinesToTest = linkLines[i].slice();\n                const overlapIndex = linkLinesToTest.findIndex((line) => overlapExists(thisLine, line));\n\n                // Overlap occurs and the end point of one segment lies on thisLine\n                if (overlapIndex > -1 && thisLine.containsPoint(linkLinesToTest[overlapIndex].end)) {\n                    // Remove the next segment because there will never be a jump\n                    linkLinesToTest.splice(overlapIndex + 1, 1);\n                }\n                const lineIntersections = findLineIntersections(thisLine, linkLinesToTest);\n                res.push.apply(res, lineIntersections);\n            }\n            return res;\n        }, []).sort(function(a, b) {\n            return sortPoints(thisLine.start, a) - sortPoints(thisLine.start, b);\n        });\n\n        if (intersections.length > 0) {\n            // split the line based on found intersection points\n            resultLines.push.apply(resultLines, createJumps(thisLine, intersections, jumpSize));\n        } else {\n            // without any intersection the line goes uninterrupted\n            resultLines.push(thisLine);\n        }\n        return resultLines;\n    }, []);\n\n    var path = buildPath(jumpingLines, jumpSize, jumpType, radius);\n    return (raw) ? path : path.serialize();\n};\n","import { straight } from './straight.mjs';\n\nexport const normal = function(sourcePoint, targetPoint, route = [], opt = {}) {\n\n    const { raw } = opt;\n    const localOpt = {\n        cornerType: 'point',\n        raw\n    };\n\n    return straight(sourcePoint, targetPoint, route, localOpt);\n};\n","import { straight } from './straight.mjs';\n\nconst CORNER_RADIUS = 10;\nconst PRECISION = 0;\n\nexport const rounded = function(sourcePoint, targetPoint, route = [], opt = {}) {\n\n    const { radius = CORNER_RADIUS, raw } = opt;\n    const localOpt = {\n        cornerType: 'cubic',\n        cornerRadius: radius,\n        precision: PRECISION,\n        raw\n    };\n\n    return straight(sourcePoint, targetPoint, route, localOpt);\n};\n","import * as g from '../g/index.mjs';\n\nexport const smooth = function(sourcePoint, targetPoint, route, opt) {\n\n    var raw = opt && opt.raw;\n    var path;\n\n    if (route && route.length !== 0) {\n\n        var points = [sourcePoint].concat(route).concat([targetPoint]);\n        var curves = g.Curve.throughPoints(points);\n\n        path = new g.Path(curves);\n\n    } else {\n        // if we have no route, use a default cubic bezier curve\n        // cubic bezier requires two control points\n        // the control points have `x` midway between source and target\n        // this produces an S-like curve\n\n        path = new g.Path();\n\n        var segment;\n\n        segment = g.Path.createSegment('M', sourcePoint);\n        path.appendSegment(segment);\n\n        if ((Math.abs(sourcePoint.x - targetPoint.x)) >= (Math.abs(sourcePoint.y - targetPoint.y))) {\n            var controlPointX = (sourcePoint.x + targetPoint.x) / 2;\n\n            segment = g.Path.createSegment('C', controlPointX, sourcePoint.y, controlPointX, targetPoint.y, targetPoint.x, targetPoint.y);\n            path.appendSegment(segment);\n\n        } else {\n            var controlPointY = (sourcePoint.y + targetPoint.y) / 2;\n\n            segment = g.Path.createSegment('C', sourcePoint.x, controlPointY, targetPoint.x, controlPointY, targetPoint.x, targetPoint.y);\n            path.appendSegment(segment);\n\n        }\n    }\n\n    return (raw) ? path : path.serialize();\n};\n","import { Path, Point, Curve } from '../g/index.mjs';\n\nconst Directions = {\n    AUTO: 'auto',\n    HORIZONTAL: 'horizontal',\n    VERTICAL: 'vertical',\n    CLOSEST_POINT: 'closest-point',\n    OUTWARDS: 'outwards'\n};\n\nconst TangentDirections = {\n    UP: 'up',\n    DOWN: 'down',\n    LEFT: 'left',\n    RIGHT: 'right',\n    AUTO: 'auto',\n    CLOSEST_POINT: 'closest-point',\n    OUTWARDS: 'outwards'\n};\n\nexport const curve = function(sourcePoint, targetPoint, route = [], opt = {}, linkView) {\n    const raw = Boolean(opt.raw);\n    // distanceCoefficient - a coefficient of the tangent vector length relative to the distance between points.\n    // angleTangentCoefficient - a coefficient of the end tangents length in the case of angles larger than 45 degrees.\n    // tension - a Catmull-Rom curve tension parameter.\n    // sourceTangent - a tangent vector along the curve at the sourcePoint.\n    // sourceDirection - a unit direction vector along the curve at the sourcePoint.\n    // targetTangent - a tangent vector along the curve at the targetPoint.\n    // targetDirection - a unit direction vector along the curve at the targetPoint.\n    // precision - a rounding precision for path values.\n    const { direction = Directions.AUTO, precision = 3 } = opt;\n    const options = {\n        coeff: opt.distanceCoefficient || 0.6,\n        angleTangentCoefficient: opt.angleTangentCoefficient || 80,\n        tau: opt.tension || 0.5,\n        sourceTangent: opt.sourceTangent ? new Point(opt.sourceTangent) : null,\n        targetTangent: opt.targetTangent ? new Point(opt.targetTangent) : null,\n        rotate: Boolean(opt.rotate)\n    };\n    if (typeof opt.sourceDirection === 'string')\n        options.sourceDirection = opt.sourceDirection;\n    else if (typeof opt.sourceDirection === 'number')\n        options.sourceDirection = new Point(1, 0).rotate(null, opt.sourceDirection);\n    else\n        options.sourceDirection = opt.sourceDirection ? new Point(opt.sourceDirection).normalize() : null;\n\n    if (typeof opt.targetDirection === 'string')\n        options.targetDirection = opt.targetDirection;\n    else if (typeof opt.targetDirection === 'number')\n        options.targetDirection = new Point(1, 0).rotate(null, opt.targetDirection);\n    else\n        options.targetDirection = opt.targetDirection ? new Point(opt.targetDirection).normalize() : null;\n\n    const completeRoute = [sourcePoint, ...route, targetPoint].map(p => new Point(p));\n\n    // The calculation of a sourceTangent\n    let sourceTangent;\n    if (options.sourceTangent) {\n        sourceTangent = options.sourceTangent;\n    } else {\n        const sourceDirection = getSourceTangentDirection(linkView, completeRoute, direction, options);\n        const tangentLength = completeRoute[0].distance(completeRoute[1]) * options.coeff;\n        const pointsVector = completeRoute[1].difference(completeRoute[0]).normalize();\n        const angle = angleBetweenVectors(sourceDirection, pointsVector);\n        if (angle > Math.PI / 4) {\n            const updatedLength = tangentLength + (angle - Math.PI / 4) * options.angleTangentCoefficient;\n            sourceTangent = sourceDirection.clone().scale(updatedLength, updatedLength);\n        } else {\n            sourceTangent = sourceDirection.clone().scale(tangentLength, tangentLength);\n        }\n    }\n\n    // The calculation of a targetTangent\n    let targetTangent;\n    if (options.targetTangent) {\n        targetTangent = options.targetTangent;\n    } else {\n        const targetDirection = getTargetTangentDirection(linkView, completeRoute, direction, options);\n        const last = completeRoute.length - 1;\n        const tangentLength = completeRoute[last - 1].distance(completeRoute[last]) * options.coeff;\n        const pointsVector = completeRoute[last - 1].difference(completeRoute[last]).normalize();\n        const angle = angleBetweenVectors(targetDirection, pointsVector);\n        if (angle > Math.PI / 4) {\n            const updatedLength = tangentLength + (angle - Math.PI / 4) * options.angleTangentCoefficient;\n            targetTangent = targetDirection.clone().scale(updatedLength, updatedLength);\n        } else {\n            targetTangent = targetDirection.clone().scale(tangentLength, tangentLength);\n        }\n    }\n\n    const catmullRomCurves = createCatmullRomCurves(completeRoute, sourceTangent, targetTangent, options);\n    const bezierCurves = catmullRomCurves.map(curve => catmullRomToBezier(curve, options));\n    const path = new Path(bezierCurves).round(precision);\n\n    return (raw) ? path : path.serialize();\n};\ncurve.Directions = Directions;\ncurve.TangentDirections = TangentDirections;\n\nfunction getHorizontalSourceDirection(linkView, route, options) {\n    const { sourceBBox } = linkView;\n\n    let sourceSide;\n    let rotation;\n    if (!linkView.sourceView) {\n        if (sourceBBox.x > route[1].x)\n            sourceSide = 'right';\n        else\n            sourceSide = 'left';\n    } else {\n        rotation = linkView.sourceView.model.angle();\n        if (options.rotate && rotation) {\n            const unrotatedBBox = linkView.sourceView.getNodeUnrotatedBBox(linkView.sourceView.el);\n            const sourcePoint = route[0].clone();\n            sourcePoint.rotate(sourceBBox.center(), rotation);\n            sourceSide = unrotatedBBox.sideNearestToPoint(sourcePoint);\n        } else {\n            sourceSide = sourceBBox.sideNearestToPoint(route[0]);\n        }\n    }\n\n    let direction;\n    switch (sourceSide) {\n        case 'left':\n            direction = new Point(-1, 0);\n            break;\n        case 'right':\n        default:\n            direction = new Point(1, 0);\n            break;\n    }\n\n    if (options.rotate && rotation) {\n        direction.rotate(null, -rotation);\n    }\n\n    return direction;\n}\n\nfunction getHorizontalTargetDirection(linkView, route, options) {\n    const { targetBBox } = linkView;\n\n    let targetSide;\n    let rotation;\n    if (!linkView.targetView) {\n        if (targetBBox.x > route[route.length - 2].x)\n            targetSide = 'left';\n        else\n            targetSide = 'right';\n    } else {\n        rotation = linkView.targetView.model.angle();\n        if (options.rotate && rotation) {\n            const unrotatedBBox = linkView.targetView.getNodeUnrotatedBBox(linkView.targetView.el);\n            const targetPoint = route[route.length - 1].clone();\n            targetPoint.rotate(targetBBox.center(), rotation);\n            targetSide = unrotatedBBox.sideNearestToPoint(targetPoint);\n        } else {\n            targetSide = targetBBox.sideNearestToPoint(route[route.length - 1]);\n        }\n    }\n\n    let direction;\n    switch (targetSide) {\n        case 'left':\n            direction = new Point(-1, 0);\n            break;\n        case 'right':\n        default:\n            direction = new Point(1, 0);\n            break;\n    }\n\n    if (options.rotate && rotation) {\n        direction.rotate(null, -rotation);\n    }\n\n    return direction;\n}\n\nfunction getVerticalSourceDirection(linkView, route, options) {\n    const { sourceBBox } = linkView;\n\n    let sourceSide;\n    let rotation;\n    if (!linkView.sourceView) {\n        if (sourceBBox.y > route[1].y)\n            sourceSide = 'bottom';\n        else\n            sourceSide = 'top';\n    } else {\n        rotation = linkView.sourceView.model.angle();\n        if (options.rotate && rotation) {\n            const unrotatedBBox = linkView.sourceView.getNodeUnrotatedBBox(linkView.sourceView.el);\n            const sourcePoint = route[0].clone();\n            sourcePoint.rotate(sourceBBox.center(), rotation);\n            sourceSide = unrotatedBBox.sideNearestToPoint(sourcePoint);\n        } else {\n            sourceSide = sourceBBox.sideNearestToPoint(route[0]);\n        }\n    }\n\n    let direction;\n    switch (sourceSide) {\n        case 'top':\n            direction = new Point(0, -1);\n            break;\n        case 'bottom':\n        default:\n            direction = new Point(0, 1);\n            break;\n    }\n\n    if (options.rotate && rotation) {\n        direction.rotate(null, -rotation);\n    }\n\n    return direction;\n}\n\nfunction getVerticalTargetDirection(linkView, route, options) {\n    const { targetBBox } = linkView;\n\n    let targetSide;\n    let rotation;\n    if (!linkView.targetView) {\n        if (targetBBox.y > route[route.length - 2].y)\n            targetSide = 'top';\n        else\n            targetSide = 'bottom';\n    } else {\n        rotation = linkView.targetView.model.angle();\n        if (options.rotate && rotation) {\n            const unrotatedBBox = linkView.targetView.getNodeUnrotatedBBox(linkView.targetView.el);\n            const targetPoint = route[route.length - 1].clone();\n            targetPoint.rotate(targetBBox.center(), rotation);\n            targetSide = unrotatedBBox.sideNearestToPoint(targetPoint);\n        } else {\n            targetSide = targetBBox.sideNearestToPoint(route[route.length - 1]);\n        }\n    }\n\n\n    let direction;\n    switch (targetSide) {\n        case 'top':\n            direction = new Point(0, -1);\n            break;\n        case 'bottom':\n        default:\n            direction = new Point(0, 1);\n            break;\n    }\n\n    if (options.rotate && rotation) {\n        direction.rotate(null, -rotation);\n    }\n\n    return direction;\n}\n\nfunction getAutoSourceDirection(linkView, route, options) {\n    const { sourceBBox } = linkView;\n\n    let sourceSide;\n    let rotation;\n    if (!linkView.sourceView) {\n        sourceSide = sourceBBox.sideNearestToPoint(route[1]);\n    } else {\n        rotation = linkView.sourceView.model.angle();\n        if (options.rotate && rotation) {\n            const unrotatedBBox = linkView.sourceView.getNodeUnrotatedBBox(linkView.sourceView.el);\n            const sourcePoint = route[0].clone();\n            sourcePoint.rotate(sourceBBox.center(), rotation);\n            sourceSide = unrotatedBBox.sideNearestToPoint(sourcePoint);\n        } else {\n            sourceSide = sourceBBox.sideNearestToPoint(route[0]);\n        }\n    }\n\n    let direction;\n    switch (sourceSide) {\n        case 'top':\n            direction = new Point(0, -1);\n            break;\n        case 'bottom':\n            direction = new Point(0, 1);\n            break;\n        case 'right':\n            direction = new Point(1, 0);\n            break;\n        case 'left':\n            direction = new Point(-1, 0);\n            break;\n    }\n\n    if (options.rotate && rotation) {\n        direction.rotate(null, -rotation);\n    }\n\n    return direction;\n}\n\nfunction getAutoTargetDirection(linkView, route, options) {\n    const { targetBBox } = linkView;\n\n    let targetSide;\n    let rotation;\n    if (!linkView.targetView) {\n        targetSide = targetBBox.sideNearestToPoint(route[route.length - 2]);\n    } else {\n        rotation = linkView.targetView.model.angle();\n        if (options.rotate && rotation) {\n            const unrotatedBBox = linkView.targetView.getNodeUnrotatedBBox(linkView.targetView.el);\n            const targetPoint = route[route.length - 1].clone();\n            targetPoint.rotate(targetBBox.center(), rotation);\n            targetSide = unrotatedBBox.sideNearestToPoint(targetPoint);\n        } else {\n            targetSide = targetBBox.sideNearestToPoint(route[route.length - 1]);\n        }\n    }\n\n    let direction;\n    switch (targetSide) {\n        case 'top':\n            direction = new Point(0, -1);\n            break;\n        case 'bottom':\n            direction = new Point(0, 1);\n            break;\n        case 'right':\n            direction = new Point(1, 0);\n            break;\n        case 'left':\n            direction = new Point(-1, 0);\n            break;\n    }\n\n    if (options.rotate && rotation) {\n        direction.rotate(null, -rotation);\n    }\n\n    return direction;\n}\n\nfunction getClosestPointSourceDirection(linkView, route, options) {\n    return route[1].difference(route[0]).normalize();\n}\n\nfunction getClosestPointTargetDirection(linkView, route, options) {\n    const last = route.length - 1;\n    return route[last - 1].difference(route[last]).normalize();\n}\n\nfunction getOutwardsSourceDirection(linkView, route, options) {\n    const { sourceBBox } = linkView;\n    const sourceCenter = sourceBBox.center();\n    return route[0].difference(sourceCenter).normalize();\n}\n\nfunction getOutwardsTargetDirection(linkView, route, options) {\n    const { targetBBox } = linkView;\n    const targetCenter = targetBBox.center();\n    return route[route.length - 1].difference(targetCenter).normalize();\n}\n\nfunction getSourceTangentDirection(linkView, route, direction, options) {\n    if (options.sourceDirection) {\n        switch (options.sourceDirection) {\n            case TangentDirections.UP:\n                return new Point(0, -1);\n            case TangentDirections.DOWN:\n                return new Point(0, 1);\n            case TangentDirections.LEFT:\n                return new Point(-1, 0);\n            case TangentDirections.RIGHT:\n                return new Point(1, 0);\n            case TangentDirections.AUTO:\n                return getAutoSourceDirection(linkView, route, options);\n            case TangentDirections.CLOSEST_POINT:\n                return getClosestPointSourceDirection(linkView, route, options);\n            case TangentDirections.OUTWARDS:\n                return getOutwardsSourceDirection(linkView, route, options);\n            default:\n                return options.sourceDirection;\n        }\n    }\n\n    switch (direction) {\n        case Directions.HORIZONTAL:\n            return getHorizontalSourceDirection(linkView, route, options);\n        case Directions.VERTICAL:\n            return getVerticalSourceDirection(linkView, route, options);\n        case Directions.CLOSEST_POINT:\n            return getClosestPointSourceDirection(linkView, route, options);\n        case Directions.OUTWARDS:\n            return getOutwardsSourceDirection(linkView, route, options);\n        case Directions.AUTO:\n        default:\n            return getAutoSourceDirection(linkView, route, options);\n    }\n}\n\nfunction getTargetTangentDirection(linkView, route, direction, options) {\n    if (options.targetDirection) {\n        switch (options.targetDirection) {\n            case TangentDirections.UP:\n                return new Point(0, -1);\n            case TangentDirections.DOWN:\n                return new Point(0, 1);\n            case TangentDirections.LEFT:\n                return new Point(-1, 0);\n            case TangentDirections.RIGHT:\n                return new Point(1, 0);\n            case TangentDirections.AUTO:\n                return getAutoTargetDirection(linkView, route, options);\n            case TangentDirections.CLOSEST_POINT:\n                return getClosestPointTargetDirection(linkView, route, options);\n            case TangentDirections.OUTWARDS:\n                return getOutwardsTargetDirection(linkView, route, options);\n            default:\n                return options.targetDirection;\n        }\n    }\n\n    switch (direction) {\n        case Directions.HORIZONTAL:\n            return getHorizontalTargetDirection(linkView, route, options);\n        case Directions.VERTICAL:\n            return getVerticalTargetDirection(linkView, route, options);\n        case Directions.CLOSEST_POINT:\n            return getClosestPointTargetDirection(linkView, route, options);\n        case Directions.OUTWARDS:\n            return getOutwardsTargetDirection(linkView, route, options);\n        case Directions.AUTO:\n        default:\n            return getAutoTargetDirection(linkView, route, options);\n    }\n}\n\nfunction rotateVector(vector, angle) {\n    const cos = Math.cos(angle);\n    const sin = Math.sin(angle);\n    const x = cos * vector.x - sin * vector.y;\n    const y = sin * vector.x + cos * vector.y;\n    vector.x = x;\n    vector.y = y;\n}\n\nfunction angleBetweenVectors(v1, v2) {\n    let cos = v1.dot(v2) / (v1.magnitude() * v2.magnitude());\n    if (cos < -1) cos = -1;\n    if (cos > 1) cos = 1;\n    return Math.acos(cos);\n}\n\nfunction determinant(v1, v2) {\n    return v1.x * v2.y - v1.y * v2.x;\n}\n\nfunction createCatmullRomCurves(points, sourceTangent, targetTangent, options) {\n    const { tau, coeff } = options;\n    const distances = [];\n    const tangents = [];\n    const catmullRomCurves = [];\n    const n = points.length - 1;\n\n    for (let i = 0; i < n; i++) {\n        distances[i] = points[i].distance(points[i + 1]);\n    }\n\n    tangents[0] = sourceTangent;\n    tangents[n] = targetTangent;\n\n    // The calculation of tangents of vertices\n    for (let i = 1; i < n; i++) {\n        let tpPrev;\n        let tpNext;\n        if (i === 1) {\n            tpPrev = points[i - 1].clone().offset(tangents[i - 1].x, tangents[i - 1].y);\n        } else {\n            tpPrev = points[i - 1].clone();\n        }\n        if (i === n - 1) {\n            tpNext = points[i + 1].clone().offset(tangents[i + 1].x, tangents[i + 1].y);\n        } else {\n            tpNext = points[i + 1].clone();\n        }\n        const v1 = tpPrev.difference(points[i]).normalize();\n        const v2 = tpNext.difference(points[i]).normalize();\n        const vAngle = angleBetweenVectors(v1, v2);\n\n        let rot = (Math.PI - vAngle) / 2;\n        let t;\n        const vectorDeterminant = determinant(v1, v2);\n        let pointsDeterminant;\n        pointsDeterminant = determinant(points[i].difference(points[i + 1]), points[i].difference(points[i - 1]));\n        if (vectorDeterminant < 0) {\n            rot = -rot;\n        }\n        if ((vAngle < Math.PI / 2) && ((rot < 0 && pointsDeterminant < 0) || (rot > 0 && pointsDeterminant > 0))) {\n            rot = rot - Math.PI;\n        }\n        t = v2.clone();\n        rotateVector(t, rot);\n\n        const t1 = t.clone();\n        const t2 = t.clone();\n        const scaleFactor1 = distances[i - 1] * coeff;\n        const scaleFactor2 = distances[i] * coeff;\n        t1.scale(scaleFactor1, scaleFactor1);\n        t2.scale(scaleFactor2, scaleFactor2);\n\n        tangents[i] = [t1, t2];\n    }\n\n    // The building of a Catmull-Rom curve based of tangents of points\n    for (let i = 0; i < n; i++) {\n        let p0;\n        let p3;\n        if (i === 0) {\n            p0 = points[i + 1].difference(tangents[i].x / tau, tangents[i].y / tau);\n        } else {\n            p0 = points[i + 1].difference(tangents[i][1].x / tau, tangents[i][1].y / tau);\n        }\n        if (i === n - 1) {\n            p3 = points[i].clone().offset(tangents[i + 1].x / tau, tangents[i + 1].y / tau);\n        } else {\n            p3 = points[i].difference(tangents[i + 1][0].x / tau, tangents[i + 1][0].y / tau);\n        }\n\n        catmullRomCurves[i] = [p0, points[i], points[i + 1], p3];\n    }\n    return catmullRomCurves;\n}\n\n// The function to convert Catmull-Rom curve to Bezier curve using the tension (tau)\nfunction catmullRomToBezier(points, options) {\n    const { tau } = options;\n\n    const bcp1 = new Point();\n    bcp1.x = points[1].x + (points[2].x - points[0].x) / (6 * tau);\n    bcp1.y = points[1].y + (points[2].y - points[0].y) / (6 * tau);\n\n    const bcp2 = new Point();\n    bcp2.x = points[2].x + (points[3].x - points[1].x) / (6 * tau);\n    bcp2.y = points[2].y + (points[3].y - points[1].y) / (6 * tau);\n    return new Curve(\n        points[1],\n        bcp1,\n        bcp2,\n        points[2]\n    );\n}\n","import { CellView } from './CellView.mjs';\nimport { Link } from './Link.mjs';\nimport V from '../V/index.mjs';\nimport { addClassNamePrefix, merge, assign, isObject, isFunction, clone, isPercentage, result, isEqual } from '../util/index.mjs';\nimport { Point, Line, Path, normalizeAngle, Rect, Polyline, intersection } from '../g/index.mjs';\nimport * as routers from '../routers/index.mjs';\nimport * as connectors from '../connectors/index.mjs';\nimport { env } from '../env/index.mjs';\n\nconst Flags = {\n    TOOLS: CellView.Flags.TOOLS,\n    RENDER: 'RENDER',\n    UPDATE: 'UPDATE',\n    LABELS: 'LABELS',\n    SOURCE: 'SOURCE',\n    TARGET: 'TARGET',\n    CONNECTOR: 'CONNECTOR'\n};\n\n// Link base view and controller.\n// ----------------------------------------\n\nexport const LinkView = CellView.extend({\n\n    className: function() {\n\n        var classNames = CellView.prototype.className.apply(this).split(' ');\n\n        classNames.push('link');\n\n        return classNames.join(' ');\n    },\n\n    _labelCache: null,\n    _labelSelectors: null,\n    _V: null,\n    _dragData: null, // deprecated\n\n    metrics: null,\n    decimalsRounding: 2,\n\n    initialize: function() {\n\n        CellView.prototype.initialize.apply(this, arguments);\n\n        // `_.labelCache` is a mapping of indexes of labels in the `this.get('labels')` array to\n        // `<g class=\"label\">` nodes wrapped by Vectorizer. This allows for quick access to the\n        // nodes in `updateLabelPosition()` in order to update the label positions.\n        this._labelCache = {};\n\n        // a cache of label selectors\n        this._labelSelectors = {};\n\n        // cache of default markup nodes\n        this._V = {};\n\n        // connection path metrics\n        this.cleanNodesCache();\n    },\n\n    presentationAttributes: {\n        markup: [Flags.RENDER],\n        attrs: [Flags.UPDATE],\n        router: [Flags.UPDATE],\n        connector: [Flags.CONNECTOR],\n        labels: [Flags.LABELS, Flags.TOOLS],\n        labelMarkup: [Flags.LABELS],\n        vertices: [Flags.UPDATE],\n        source: [Flags.SOURCE, Flags.UPDATE],\n        target: [Flags.TARGET, Flags.UPDATE]\n    },\n\n    initFlag: [Flags.RENDER, Flags.SOURCE, Flags.TARGET, Flags.TOOLS],\n\n    UPDATE_PRIORITY: 1,\n    EPSILON: 1e-6,\n\n    confirmUpdate: function(flags, opt) {\n\n        opt || (opt = {});\n\n        if (this.hasFlag(flags, Flags.SOURCE)) {\n            if (!this.updateEndProperties('source')) return flags;\n            flags = this.removeFlag(flags, Flags.SOURCE);\n        }\n\n        if (this.hasFlag(flags, Flags.TARGET)) {\n            if (!this.updateEndProperties('target')) return flags;\n            flags = this.removeFlag(flags, Flags.TARGET);\n        }\n\n        const { paper, sourceView, targetView } = this;\n        if (paper && ((sourceView && !paper.isViewMounted(sourceView)) || (targetView && !paper.isViewMounted(targetView)))) {\n            // Wait for the sourceView and targetView to be rendered\n            return flags;\n        }\n\n        if (this.hasFlag(flags, Flags.RENDER)) {\n            this.render();\n            this.updateHighlighters(true);\n            this.updateTools(opt);\n            flags = this.removeFlag(flags, [Flags.RENDER, Flags.UPDATE, Flags.LABELS, Flags.TOOLS, Flags.CONNECTOR]);\n\n            if (env.test('isSafari')) {\n                this.__fixSafariBug268376();\n            }\n\n            return flags;\n        }\n\n        let updateHighlighters = false;\n\n        const { model } = this;\n        const { attributes } = model;\n        let updateLabels = this.hasFlag(flags, Flags.LABELS);\n\n        if (updateLabels) {\n            this.onLabelsChange(model, attributes.labels, opt);\n            flags = this.removeFlag(flags, Flags.LABELS);\n            updateHighlighters = true;\n        }\n\n        const updateAll = this.hasFlag(flags, Flags.UPDATE);\n        const updateConnector = this.hasFlag(flags, Flags.CONNECTOR);\n        if (updateAll || updateConnector) {\n            if (!updateAll) {\n                // Keep the current route and update the geometry\n                this.updatePath();\n                this.updateDOM();\n            } else if (opt.translateBy && model.isRelationshipEmbeddedIn(opt.translateBy)) {\n                // The link is being translated by an ancestor that will\n                // shift source point, target point and all vertices\n                // by an equal distance.\n                this.translate(opt.tx, opt.ty);\n            } else {\n                this.update();\n            }\n            this.updateTools(opt);\n            flags = this.removeFlag(flags, [Flags.UPDATE, Flags.TOOLS, Flags.CONNECTOR]);\n            updateLabels = false;\n            updateHighlighters = true;\n        }\n\n        if (updateLabels) {\n            this.updateLabelPositions();\n        }\n\n        if (updateHighlighters) {\n            this.updateHighlighters();\n        }\n\n        if (this.hasFlag(flags, Flags.TOOLS)) {\n            this.updateTools(opt);\n            flags = this.removeFlag(flags, Flags.TOOLS);\n        }\n\n        return flags;\n    },\n\n    __fixSafariBug268376: function() {\n        // Safari has a bug where any change after the first render is not reflected in the DOM.\n        // https://bugs.webkit.org/show_bug.cgi?id=268376\n        const { el } = this;\n        const childNodes = Array.from(el.childNodes);\n        const fragment = document.createDocumentFragment();\n        for (let i = 0, n = childNodes.length; i < n; i++) {\n            el.removeChild(childNodes[i]);\n            fragment.appendChild(childNodes[i]);\n        }\n        el.appendChild(fragment);\n    },\n\n    requestConnectionUpdate: function(opt) {\n        this.requestUpdate(this.getFlag(Flags.UPDATE), opt);\n    },\n\n    isLabelsRenderRequired: function(opt = {}) {\n\n        const previousLabels = this.model.previous('labels');\n        if (!previousLabels) return true;\n\n        // Here is an optimization for cases when we know, that change does\n        // not require re-rendering of all labels.\n        if (('propertyPathArray' in opt) && ('propertyValue' in opt)) {\n            // The label is setting by `prop()` method\n            var pathArray = opt.propertyPathArray || [];\n            var pathLength = pathArray.length;\n            if (pathLength > 1) {\n                // We are changing a single label here e.g. 'labels/0/position'\n                var labelExists = !!previousLabels[pathArray[1]];\n                if (labelExists) {\n                    if (pathLength === 2) {\n                        // We are changing the entire label. Need to check if the\n                        // markup is also being changed.\n                        return ('markup' in Object(opt.propertyValue));\n                    } else if (pathArray[2] !== 'markup') {\n                        // We are changing a label property but not the markup\n                        return false;\n                    }\n                }\n            }\n        }\n\n        return true;\n    },\n\n    onLabelsChange: function(_link, _labels, opt) {\n\n        // Note: this optimization works in async=false mode only\n        if (this.isLabelsRenderRequired(opt)) {\n            this.renderLabels();\n        } else {\n            this.updateLabels();\n        }\n    },\n\n    // Rendering.\n    // ----------\n\n    render: function() {\n\n        this.vel.empty();\n        this.unmountLabels();\n        this._V = {};\n        this.renderMarkup();\n        // rendering labels has to be run after the link is appended to DOM tree. (otherwise <Text> bbox\n        // returns zero values)\n        this.renderLabels();\n        this.update();\n\n        return this;\n    },\n\n    renderMarkup: function() {\n\n        var link = this.model;\n        var markup = link.get('markup') || link.markup;\n        if (!markup) throw new Error('dia.LinkView: markup required');\n        if (Array.isArray(markup)) return this.renderJSONMarkup(markup);\n        if (typeof markup === 'string') return this.renderStringMarkup(markup);\n        throw new Error('dia.LinkView: invalid markup');\n    },\n\n    renderJSONMarkup: function(markup) {\n\n        var doc = this.parseDOMJSON(markup, this.el);\n        // Selectors\n        this.selectors = doc.selectors;\n        // Fragment\n        this.vel.append(doc.fragment);\n    },\n\n    renderStringMarkup: function(markup) {\n\n        // A special markup can be given in the `properties.markup` property. This might be handy\n        // if e.g. arrowhead markers should be `<image>` elements or any other element than `<path>`s.\n        // `.connection`, `.connection-wrap`, `.marker-source` and `.marker-target` selectors\n        // of elements with special meaning though. Therefore, those classes should be preserved in any\n        // special markup passed in `properties.markup`.\n        var children = V(markup);\n        // custom markup may contain only one children\n        if (!Array.isArray(children)) children = [children];\n\n        this.vel.append(children);\n    },\n\n    _getLabelMarkup: function(labelMarkup) {\n\n        if (!labelMarkup) return undefined;\n\n        if (Array.isArray(labelMarkup)) return this.parseDOMJSON(labelMarkup, null);\n        if (typeof labelMarkup === 'string') return this._getLabelStringMarkup(labelMarkup);\n        throw new Error('dia.linkView: invalid label markup');\n    },\n\n    _getLabelStringMarkup: function(labelMarkup) {\n\n        var children = V(labelMarkup);\n        var fragment = document.createDocumentFragment();\n\n        if (!Array.isArray(children)) {\n            fragment.appendChild(children.node);\n\n        } else {\n            for (var i = 0, n = children.length; i < n; i++) {\n                var currentChild = children[i].node;\n                fragment.appendChild(currentChild);\n            }\n        }\n\n        return { fragment: fragment, selectors: {}}; // no selectors\n    },\n\n    // Label markup fragment may come wrapped in <g class=\"label\" />, or not.\n    // If it doesn't, add the <g /> container here.\n    _normalizeLabelMarkup: function(markup) {\n\n        if (!markup) return undefined;\n\n        var fragment = markup.fragment;\n        if (!(markup.fragment instanceof DocumentFragment) || !markup.fragment.hasChildNodes()) throw new Error('dia.LinkView: invalid label markup.');\n\n        var vNode;\n        var childNodes = fragment.childNodes;\n\n        if ((childNodes.length > 1) || childNodes[0].nodeName.toUpperCase() !== 'G') {\n            // default markup fragment is not wrapped in <g />\n            // add a <g /> container\n            vNode = V('g').append(fragment);\n        } else {\n            vNode = V(childNodes[0]);\n        }\n\n        vNode.addClass('label');\n\n        return { node: vNode.node, selectors: markup.selectors };\n    },\n\n    renderLabels: function() {\n\n        var cache = this._V;\n        var vLabels = cache.labels;\n        var labelCache = this._labelCache = {};\n        var labelSelectors = this._labelSelectors = {};\n        var model = this.model;\n        var labels = model.attributes.labels || [];\n        var labelsCount = labels.length;\n\n        if (labelsCount === 0) {\n            if (vLabels) vLabels.remove();\n            return this;\n        }\n\n        if (vLabels) {\n            vLabels.empty();\n        }  else {\n            // there is no label container in the markup but some labels are defined\n            // add a <g class=\"labels\" /> container\n            vLabels = cache.labels = V('g').addClass('labels');\n            if (this.options.labelsLayer) {\n                vLabels.addClass(addClassNamePrefix(result(this, 'className')));\n                vLabels.attr('model-id', model.id);\n            }\n        }\n\n        for (var i = 0; i < labelsCount; i++) {\n\n            var label = labels[i];\n            var labelMarkup = this._normalizeLabelMarkup(this._getLabelMarkup(label.markup));\n            var labelNode;\n            var selectors;\n            if (labelMarkup) {\n\n                labelNode = labelMarkup.node;\n                selectors = labelMarkup.selectors;\n\n            } else {\n\n                var builtinDefaultLabel =  model._builtins.defaultLabel;\n                var builtinDefaultLabelMarkup = this._normalizeLabelMarkup(this._getLabelMarkup(builtinDefaultLabel.markup));\n                var defaultLabel = model._getDefaultLabel();\n                var defaultLabelMarkup = this._normalizeLabelMarkup(this._getLabelMarkup(defaultLabel.markup));\n                var defaultMarkup = defaultLabelMarkup || builtinDefaultLabelMarkup;\n\n                labelNode = defaultMarkup.node;\n                selectors = defaultMarkup.selectors;\n            }\n\n            labelNode.setAttribute('label-idx', i); // assign label-idx\n            vLabels.append(labelNode);\n            labelCache[i] = labelNode; // cache node for `updateLabels()` so it can just update label node positions\n\n            var rootSelector = this.selector;\n            if (selectors[rootSelector]) throw new Error('dia.LinkView: ambiguous label root selector.');\n            selectors[rootSelector] = labelNode;\n\n            labelSelectors[i] = selectors; // cache label selectors for `updateLabels()`\n        }\n        if (!vLabels.parent()) {\n            this.mountLabels();\n        }\n\n        this.updateLabels();\n\n        return this;\n    },\n\n    mountLabels: function() {\n        const { el, paper, model, _V, options } = this;\n        const { labels: vLabels } = _V;\n        if (!vLabels || !model.hasLabels()) return;\n        const { node } = vLabels;\n        if (options.labelsLayer) {\n            paper.getLayerView(options.labelsLayer).insertSortedNode(node, model.get('z'));\n        } else {\n            if (node.parentNode !== el) {\n                el.appendChild(node);\n            }\n        }\n    },\n\n    unmountLabels: function() {\n        const { options, _V } = this;\n        if (!_V) return;\n        const { labels: vLabels } = _V;\n        if (vLabels && options.labelsLayer) {\n            vLabels.remove();\n        }\n    },\n\n    findLabelNodes: function(labelIndex, selector) {\n        const labelRoot = this._labelCache[labelIndex];\n        if (!labelRoot) return [];\n        const labelSelectors = this._labelSelectors[labelIndex];\n        return this.findBySelector(selector, labelRoot, labelSelectors);\n    },\n\n    findLabelNode: function(labelIndex, selector) {\n        const [node = null] = this.findLabelNodes(labelIndex, selector);\n        return node;\n    },\n\n    // merge default label attrs into label attrs (or use built-in default label attrs if neither is provided)\n    // keep `undefined` or `null` because `{}` means something else\n    _mergeLabelAttrs: function(hasCustomMarkup, labelAttrs, defaultLabelAttrs, builtinDefaultLabelAttrs) {\n\n        if (labelAttrs === null) return null;\n        if (labelAttrs === undefined) {\n\n            if (defaultLabelAttrs === null) return null;\n            if (defaultLabelAttrs === undefined) {\n\n                if (hasCustomMarkup) return undefined;\n                return builtinDefaultLabelAttrs;\n            }\n\n            if (hasCustomMarkup) return defaultLabelAttrs;\n            return merge({}, builtinDefaultLabelAttrs, defaultLabelAttrs);\n        }\n\n        if (hasCustomMarkup) return merge({}, defaultLabelAttrs, labelAttrs);\n        return merge({}, builtinDefaultLabelAttrs, defaultLabelAttrs, labelAttrs);\n    },\n\n    // merge default label size into label size (no built-in default)\n    // keep `undefined` or `null` because `{}` means something else\n    _mergeLabelSize: function(labelSize, defaultLabelSize) {\n\n        if (labelSize === null) return null;\n        if (labelSize === undefined) {\n\n            if (defaultLabelSize === null) return null;\n            if (defaultLabelSize === undefined) return undefined;\n\n            return defaultLabelSize;\n        }\n\n        return merge({}, defaultLabelSize, labelSize);\n    },\n\n    updateLabels: function() {\n\n        if (!this._V.labels) return this;\n\n        if (!this.paper.options.labelLayer) {\n            // If there is no label layer, the cache needs to be cleared\n            // of the root node because the labels are attached\n            // to it and could affect the bounding box.\n            this.cleanNodeCache(this.el);\n        }\n\n        var model = this.model;\n        var labels = model.get('labels') || [];\n        var canLabelMove = this.can('labelMove');\n\n        var builtinDefaultLabel = model._builtins.defaultLabel;\n        var builtinDefaultLabelAttrs = builtinDefaultLabel.attrs;\n\n        var defaultLabel = model._getDefaultLabel();\n        var defaultLabelMarkup = defaultLabel.markup;\n        var defaultLabelAttrs = defaultLabel.attrs;\n        var defaultLabelSize = defaultLabel.size;\n\n        for (var i = 0, n = labels.length; i < n; i++) {\n\n            var labelNode = this._labelCache[i];\n            labelNode.setAttribute('cursor', (canLabelMove ? 'move' : 'default'));\n\n            var selectors = this._labelSelectors[i];\n\n            var label = labels[i];\n            var labelMarkup = label.markup;\n            var labelAttrs = label.attrs;\n            var labelSize = label.size;\n\n            var attrs = this._mergeLabelAttrs(\n                (labelMarkup || defaultLabelMarkup),\n                labelAttrs,\n                defaultLabelAttrs,\n                builtinDefaultLabelAttrs\n            );\n\n            var size = this._mergeLabelSize(\n                labelSize,\n                defaultLabelSize\n            );\n\n            this.updateDOMSubtreeAttributes(labelNode, attrs, {\n                rootBBox: new Rect(size),\n                selectors: selectors\n            });\n        }\n\n        return this;\n    },\n\n    // remove vertices that lie on (or nearly on) straight lines within the link\n    // return the number of removed points\n    removeRedundantLinearVertices: function(opt) {\n\n        const SIMPLIFY_THRESHOLD = 0.001;\n\n        const link = this.model;\n        const vertices = link.vertices();\n        const routePoints = [this.sourceAnchor, ...vertices, this.targetAnchor];\n        const numRoutePoints = routePoints.length;\n\n        // put routePoints into a polyline and try to simplify\n        const polyline = new Polyline(routePoints);\n        polyline.simplify({ threshold: SIMPLIFY_THRESHOLD });\n        const polylinePoints = polyline.points.map((point) => (point.toJSON())); // JSON of points after simplification\n        const numPolylinePoints = polylinePoints.length; // number of points after simplification\n\n        // shortcut if simplification did not remove any redundant vertices:\n        if (numRoutePoints === numPolylinePoints) return 0;\n\n        // else: set simplified polyline points as link vertices\n        // remove first and last polyline points again (= source/target anchors)\n        link.vertices(polylinePoints.slice(1, numPolylinePoints - 1), opt);\n        return (numRoutePoints - numPolylinePoints);\n    },\n\n    getEndView: function(type) {\n        switch (type) {\n            case 'source':\n                return this.sourceView || null;\n            case 'target':\n                return this.targetView || null;\n            default:\n                throw new Error('dia.LinkView: type parameter required.');\n        }\n    },\n\n    getEndAnchor: function(type) {\n        switch (type) {\n            case 'source':\n                return new Point(this.sourceAnchor);\n            case 'target':\n                return new Point(this.targetAnchor);\n            default:\n                throw new Error('dia.LinkView: type parameter required.');\n        }\n    },\n\n    getEndConnectionPoint: function(type) {\n        switch (type) {\n            case 'source':\n                return new Point(this.sourcePoint);\n            case 'target':\n                return new Point(this.targetPoint);\n            default:\n                throw new Error('dia.LinkView: type parameter required.');\n        }\n    },\n\n    getEndMagnet: function(type) {\n        switch (type) {\n            case 'source':\n                var sourceView = this.sourceView;\n                if (!sourceView) break;\n                return this.sourceMagnet || sourceView.el;\n            case 'target':\n                var targetView = this.targetView;\n                if (!targetView) break;\n                return this.targetMagnet || targetView.el;\n            default:\n                throw new Error('dia.LinkView: type parameter required.');\n        }\n        return null;\n    },\n\n\n    // Updating.\n    // ---------\n\n    update: function() {\n        this.updateRoute();\n        this.updatePath();\n        this.updateDOM();\n        return this;\n    },\n\n    translate: function(tx = 0, ty = 0) {\n        const { route, path } = this;\n        if (!route || !path) return;\n        // translate the route\n        const polyline = new Polyline(route);\n        polyline.translate(tx, ty);\n        this.route = polyline.points;\n        // translate source and target connection and anchor points.\n        this.sourcePoint.offset(tx, ty);\n        this.targetPoint.offset(tx, ty);\n        this.sourceAnchor.offset(tx, ty);\n        this.targetAnchor.offset(tx, ty);\n        // translate the geometry path\n        path.translate(tx, ty);\n        this.updateDOM();\n    },\n\n    updateDOM() {\n        const { el, model, selectors } = this;\n        this.cleanNodesCache();\n        // update SVG attributes defined by 'attrs/'.\n        this.updateDOMSubtreeAttributes(el, model.attr(), { selectors });\n        // update the label position etc.\n        this.updateLabelPositions();\n        // *Deprecated*\n        // Local perpendicular flag (as opposed to one defined on paper).\n        // Could be enabled inside a connector/router. It's valid only\n        // during the update execution.\n        this.options.perpendicular = null;\n    },\n\n    updateRoute: function() {\n        const { model } = this;\n        const vertices = model.vertices();\n        // 1. Find Anchors\n        const anchors = this.findAnchors(vertices);\n        const sourceAnchor = this.sourceAnchor = anchors.source;\n        const targetAnchor = this.targetAnchor = anchors.target;\n        // 2. Find Route\n        const route = this.findRoute(vertices);\n        this.route = route;\n        // 3. Find Connection Points\n        var connectionPoints = this.findConnectionPoints(route, sourceAnchor, targetAnchor);\n        this.sourcePoint = connectionPoints.source;\n        this.targetPoint = connectionPoints.target;\n    },\n\n    updatePath: function() {\n        const { route, sourcePoint, targetPoint } = this;\n        // 4. Find Connection\n        const path = this.findPath(route, sourcePoint.clone(), targetPoint.clone());\n        this.path = path;\n    },\n\n    findAnchorsOrdered: function(firstEndType, firstRef, secondEndType, secondRef) {\n\n        var firstAnchor, secondAnchor;\n        var firstAnchorRef, secondAnchorRef;\n        var model = this.model;\n        var firstDef = model.get(firstEndType);\n        var secondDef = model.get(secondEndType);\n        var firstView = this.getEndView(firstEndType);\n        var secondView = this.getEndView(secondEndType);\n        var firstMagnet = this.getEndMagnet(firstEndType);\n        var secondMagnet = this.getEndMagnet(secondEndType);\n\n        // Anchor first\n        if (firstView) {\n            if (firstRef) {\n                firstAnchorRef = new Point(firstRef);\n            } else if (secondView) {\n                firstAnchorRef = secondMagnet;\n            } else {\n                firstAnchorRef = new Point(secondDef);\n            }\n            firstAnchor = this.getAnchor(firstDef.anchor, firstView, firstMagnet, firstAnchorRef, firstEndType);\n        } else {\n            firstAnchor = new Point(firstDef);\n        }\n\n        // Anchor second\n        if (secondView) {\n            secondAnchorRef = new Point(secondRef || firstAnchor);\n            secondAnchor = this.getAnchor(secondDef.anchor, secondView, secondMagnet, secondAnchorRef, secondEndType);\n        } else {\n            secondAnchor = new Point(secondDef);\n        }\n\n        var res = {};\n        res[firstEndType] = firstAnchor;\n        res[secondEndType] = secondAnchor;\n        return res;\n    },\n\n    findAnchors: function(vertices) {\n\n        var model = this.model;\n        var firstVertex = vertices[0];\n        var lastVertex = vertices[vertices.length - 1];\n\n        if (model.target().priority && !model.source().priority) {\n            // Reversed order\n            return this.findAnchorsOrdered('target', lastVertex, 'source', firstVertex);\n        }\n\n        // Usual order\n        return this.findAnchorsOrdered('source', firstVertex, 'target', lastVertex);\n    },\n\n    findConnectionPoints: function(route, sourceAnchor, targetAnchor) {\n\n        var firstWaypoint = route[0];\n        var lastWaypoint = route[route.length - 1];\n        var model = this.model;\n        var sourceDef = model.get('source');\n        var targetDef = model.get('target');\n        var sourceView = this.sourceView;\n        var targetView = this.targetView;\n        var paperOptions = this.paper.options;\n        var sourceMagnet, targetMagnet;\n\n        // Connection Point Source\n        var sourcePoint;\n        if (sourceView && !sourceView.isNodeConnection(this.sourceMagnet)) {\n            sourceMagnet = (this.sourceMagnet || sourceView.el);\n            var sourceConnectionPointDef = sourceDef.connectionPoint || paperOptions.defaultConnectionPoint;\n            var sourcePointRef = firstWaypoint || targetAnchor;\n            var sourceLine = new Line(sourcePointRef, sourceAnchor);\n            sourcePoint = this.getConnectionPoint(\n                sourceConnectionPointDef,\n                sourceView,\n                sourceMagnet,\n                sourceLine,\n                'source'\n            );\n        } else {\n            sourcePoint = sourceAnchor;\n        }\n        // Connection Point Target\n        var targetPoint;\n        if (targetView && !targetView.isNodeConnection(this.targetMagnet)) {\n            targetMagnet = (this.targetMagnet || targetView.el);\n            var targetConnectionPointDef = targetDef.connectionPoint || paperOptions.defaultConnectionPoint;\n            var targetPointRef = lastWaypoint || sourceAnchor;\n            var targetLine = new Line(targetPointRef, targetAnchor);\n            targetPoint = this.getConnectionPoint(\n                targetConnectionPointDef,\n                targetView,\n                targetMagnet,\n                targetLine,\n                'target'\n            );\n        } else {\n            targetPoint = targetAnchor;\n        }\n\n        return {\n            source: sourcePoint,\n            target: targetPoint\n        };\n    },\n\n    getAnchor: function(anchorDef, cellView, magnet, ref, endType) {\n\n        var isConnection = cellView.isNodeConnection(magnet);\n        var paperOptions = this.paper.options;\n        if (!anchorDef) {\n            if (isConnection) {\n                anchorDef = paperOptions.defaultLinkAnchor;\n            } else {\n                if (this.options.perpendicular) {\n                    // Backwards compatibility\n                    // See `manhattan` router for more details\n                    anchorDef = { name: 'perpendicular' };\n                } else {\n                    anchorDef = paperOptions.defaultAnchor;\n                }\n            }\n        }\n\n        if (!anchorDef) throw new Error('Anchor required.');\n        var anchorFn;\n        if (typeof anchorDef === 'function') {\n            anchorFn = anchorDef;\n        } else {\n            var anchorName = anchorDef.name;\n            var anchorNamespace = isConnection ? 'linkAnchorNamespace' : 'anchorNamespace';\n            anchorFn = paperOptions[anchorNamespace][anchorName];\n            if (typeof anchorFn !== 'function') throw new Error('Unknown anchor: ' + anchorName);\n        }\n        var anchor = anchorFn.call(\n            this,\n            cellView,\n            magnet,\n            ref,\n            anchorDef.args || {},\n            endType,\n            this\n        );\n        if (!anchor) return new Point();\n        return anchor.round(this.decimalsRounding);\n    },\n\n\n    getConnectionPoint: function(connectionPointDef, view, magnet, line, endType) {\n\n        var connectionPoint;\n        var anchor = line.end;\n        var paperOptions = this.paper.options;\n\n        if (!connectionPointDef) return anchor;\n        var connectionPointFn;\n        if (typeof connectionPointDef === 'function') {\n            connectionPointFn = connectionPointDef;\n        } else {\n            var connectionPointName = connectionPointDef.name;\n            connectionPointFn = paperOptions.connectionPointNamespace[connectionPointName];\n            if (typeof connectionPointFn !== 'function') throw new Error('Unknown connection point: ' + connectionPointName);\n        }\n        connectionPoint = connectionPointFn.call(this, line, view, magnet, connectionPointDef.args || {}, endType, this);\n        if (!connectionPoint) return anchor;\n        return connectionPoint.round(this.decimalsRounding);\n    },\n\n    isIntersecting: function(geometryShape, geometryData) {\n        const connection = this.getConnection();\n        if (!connection) return false;\n        return intersection.exists(\n            geometryShape,\n            connection,\n            geometryData,\n            { segmentSubdivisions: this.getConnectionSubdivisions() },\n        );\n    },\n\n    isEnclosedIn: function(geometryRect) {\n        const connection = this.getConnection();\n        if (!connection) return false;\n        const bbox = connection.bbox();\n        if (!bbox) return false;\n        return geometryRect.containsRect(bbox);\n    },\n\n    isAtPoint: function(point /*, options */) {\n        // Note: `strict` option is not applicable for links.\n        // There is currently no method to determine if a path contains a point.\n        const area = new Rect(point);\n        // Intersection with a zero-size area is not possible.\n        area.inflate(this.EPSILON);\n        return this.isIntersecting(area);\n    },\n\n    // combine default label position with built-in default label position\n    _getDefaultLabelPositionProperty: function() {\n\n        var model = this.model;\n\n        var builtinDefaultLabel = model._builtins.defaultLabel;\n        var builtinDefaultLabelPosition = builtinDefaultLabel.position;\n\n        var defaultLabel = model._getDefaultLabel();\n        var defaultLabelPosition = this._normalizeLabelPosition(defaultLabel.position);\n\n        return merge({}, builtinDefaultLabelPosition, defaultLabelPosition);\n    },\n\n    // if label position is a number, normalize it to a position object\n    // this makes sure that label positions can be merged properly\n    _normalizeLabelPosition: function(labelPosition) {\n\n        if (typeof labelPosition === 'number') return { distance: labelPosition, offset: null, angle: 0, args: null };\n        return labelPosition;\n    },\n\n    // expects normalized position properties\n    // e.g. `this._normalizeLabelPosition(labelPosition)` and `this._getDefaultLabelPositionProperty()`\n    _mergeLabelPositionProperty: function(normalizedLabelPosition, normalizedDefaultLabelPosition) {\n\n        if (normalizedLabelPosition === null) return null;\n        if (normalizedLabelPosition === undefined) {\n\n            if (normalizedDefaultLabelPosition === null) return null;\n            return normalizedDefaultLabelPosition;\n        }\n\n        return merge({}, normalizedDefaultLabelPosition, normalizedLabelPosition);\n    },\n\n    updateLabelPositions: function() {\n\n        if (!this._V.labels) return this;\n\n        var path = this.path;\n        if (!path) return this;\n\n        // This method assumes all the label nodes are stored in the `this._labelCache` hash table\n        // by their indices in the `this.get('labels')` array. This is done in the `renderLabels()` method.\n\n        var model = this.model;\n        var labels = model.get('labels') || [];\n        if (!labels.length) return this;\n\n        var defaultLabelPosition = this._getDefaultLabelPositionProperty();\n\n        for (var idx = 0, n = labels.length; idx < n; idx++) {\n            var labelNode = this._labelCache[idx];\n            if (!labelNode) continue;\n            var label = labels[idx];\n            var labelPosition = this._normalizeLabelPosition(label.position);\n            var position = this._mergeLabelPositionProperty(labelPosition, defaultLabelPosition);\n            var transformationMatrix = this._getLabelTransformationMatrix(position);\n            labelNode.setAttribute('transform', V.matrixToTransformString(transformationMatrix));\n            this._cleanLabelMatrices(idx);\n        }\n\n        return this;\n    },\n\n    _cleanLabelMatrices: function(index) {\n        // Clean magnetMatrix for all nodes of the label.\n        // Cached BoundingRect does not need to updated when the position changes\n        // TODO: this doesn't work for labels with XML String markups.\n        const { metrics, _labelSelectors } = this;\n        const selectors = _labelSelectors[index];\n        if (!selectors) return;\n        for (let selector in selectors) {\n            const { id } = selectors[selector];\n            if (id && (id in metrics)) delete metrics[id].magnetMatrix;\n        }\n    },\n\n    updateEndProperties: function(endType) {\n\n        const { model, paper } = this;\n        const endViewProperty = `${endType}View`;\n        const endDef = model.get(endType);\n        const endId = endDef && endDef.id;\n\n        if (!endId) {\n            // the link end is a point ~ rect 0x0\n            this[endViewProperty] = null;\n            this.updateEndMagnet(endType);\n            return true;\n        }\n\n        const endModel = paper.getModelById(endId);\n        if (!endModel) throw new Error('LinkView: invalid ' + endType + ' cell.');\n\n        const endView = endModel.findView(paper);\n        if (!endView) {\n            // A view for a model should always exist\n            return false;\n        }\n\n        this[endViewProperty] = endView;\n        this.updateEndMagnet(endType);\n        return true;\n    },\n\n    updateEndMagnet: function(endType) {\n\n        const endMagnetProperty = `${endType}Magnet`;\n        const endView = this.getEndView(endType);\n        if (endView) {\n            let connectedMagnet = endView.getMagnetFromLinkEnd(this.model.get(endType));\n            if (connectedMagnet === endView.el) connectedMagnet = null;\n            this[endMagnetProperty] = connectedMagnet;\n        } else {\n            this[endMagnetProperty] = null;\n        }\n    },\n\n    _getLabelPositionProperty: function(idx) {\n\n        return (this.model.label(idx).position || {});\n    },\n\n    _getLabelPositionAngle: function(idx) {\n\n        var labelPosition = this._getLabelPositionProperty(idx);\n        return (labelPosition.angle || 0);\n    },\n\n    _getLabelPositionArgs: function(idx) {\n\n        var labelPosition = this._getLabelPositionProperty(idx);\n        return labelPosition.args;\n    },\n\n    _getDefaultLabelPositionArgs: function() {\n\n        var defaultLabel = this.model._getDefaultLabel();\n        var defaultLabelPosition = defaultLabel.position || {};\n        return defaultLabelPosition.args;\n    },\n\n    // merge default label position args into label position args\n    // keep `undefined` or `null` because `{}` means something else\n    _mergeLabelPositionArgs: function(labelPositionArgs, defaultLabelPositionArgs) {\n\n        if (labelPositionArgs === null) return null;\n        if (labelPositionArgs === undefined) {\n\n            if (defaultLabelPositionArgs === null) return null;\n            return defaultLabelPositionArgs;\n        }\n\n        return merge({}, defaultLabelPositionArgs, labelPositionArgs);\n    },\n\n    // Add default label at given position at end of `labels` array.\n    // Four signatures:\n    // - obj, obj = point, opt\n    // - obj, num, obj = point, angle, opt\n    // - num, num, obj = x, y, opt\n    // - num, num, num, obj = x, y, angle, opt\n    // Assigns relative coordinates by default:\n    // `opt.absoluteDistance` forces absolute coordinates.\n    // `opt.reverseDistance` forces reverse absolute coordinates (if absoluteDistance = true).\n    // `opt.absoluteOffset` forces absolute coordinates for offset.\n    // Additional args:\n    // `opt.keepGradient` auto-adjusts the angle of the label to match path gradient at position.\n    // `opt.ensureLegibility` rotates labels so they are never upside-down.\n    addLabel: function(p1, p2, p3, p4) {\n\n        // normalize data from the four possible signatures\n        var localX;\n        var localY;\n        var localAngle = 0;\n        var localOpt;\n        if (typeof p1 !== 'number') {\n            // {x, y} object provided as first parameter\n            localX = p1.x;\n            localY = p1.y;\n            if (typeof p2 === 'number') {\n                // angle and opt provided as second and third parameters\n                localAngle = p2;\n                localOpt = p3;\n            } else {\n                // opt provided as second parameter\n                localOpt = p2;\n            }\n        } else {\n            // x and y provided as first and second parameters\n            localX = p1;\n            localY = p2;\n            if (typeof p3 === 'number') {\n                // angle and opt provided as third and fourth parameters\n                localAngle = p3;\n                localOpt = p4;\n            } else {\n                // opt provided as third parameter\n                localOpt = p3;\n            }\n        }\n\n        // merge label position arguments\n        var defaultLabelPositionArgs = this._getDefaultLabelPositionArgs();\n        var labelPositionArgs = localOpt;\n        var positionArgs = this._mergeLabelPositionArgs(labelPositionArgs, defaultLabelPositionArgs);\n\n        // append label to labels array\n        var label = { position: this.getLabelPosition(localX, localY, localAngle, positionArgs) };\n        var idx = -1;\n        this.model.insertLabel(idx, label, localOpt);\n        return idx;\n    },\n\n    // Add a new vertex at calculated index to the `vertices` array.\n    addVertex: function(x, y, opt) {\n\n        // accept input in form `{ x, y }, opt` or `x, y, opt`\n        var isPointProvided = (typeof x !== 'number');\n        var localX = isPointProvided ? x.x : x;\n        var localY = isPointProvided ? x.y : y;\n        var localOpt = isPointProvided ? y : opt;\n\n        var vertex = { x: localX, y: localY };\n        var idx = this.getVertexIndex(localX, localY);\n        this.model.insertVertex(idx, vertex, localOpt);\n        return idx;\n    },\n\n    // Send a token (an SVG element, usually a circle) along the connection path.\n    // Example: `link.findView(paper).sendToken(V('circle', { r: 7, fill: 'green' }).node)`\n    // `opt.duration` is optional and is a time in milliseconds that the token travels from the source to the target of the link. Default is `1000`.\n    // `opt.direction` is optional and it determines whether the token goes from source to target or other way round (`reverse`)\n    // `opt.connection` is an optional selector to the connection path.\n    // `callback` is optional and is a function to be called once the token reaches the target.\n    sendToken: function(token, opt, callback) {\n\n        function onAnimationEnd(vToken, callback) {\n            return function() {\n                vToken.remove();\n                if (typeof callback === 'function') {\n                    callback();\n                }\n            };\n        }\n\n        var duration, isReversed, selector;\n        if (isObject(opt)) {\n            duration = opt.duration;\n            isReversed = (opt.direction === 'reverse');\n            selector = opt.connection;\n        } else {\n            // Backwards compatibility\n            duration = opt;\n            isReversed = false;\n            selector = null;\n        }\n\n        duration = duration || 1000;\n\n        var animationAttributes = {\n            dur: duration + 'ms',\n            repeatCount: 1,\n            calcMode: 'linear',\n            fill: 'freeze'\n        };\n\n        if (isReversed) {\n            animationAttributes.keyPoints = '1;0';\n            animationAttributes.keyTimes = '0;1';\n        }\n\n        var vToken = V(token);\n        var connection;\n        if (typeof selector === 'string') {\n            // Use custom connection path.\n            connection = this.findNode(selector);\n        } else {\n            // Select connection path automatically.\n            var cache = this._V;\n            connection = (cache.connection) ? cache.connection.node : this.el.querySelector('path');\n        }\n\n        if (!(connection instanceof SVGPathElement)) {\n            throw new Error('dia.LinkView: token animation requires a valid connection path.');\n        }\n\n        vToken\n            .appendTo(this.paper.cells)\n            .animateAlongPath(animationAttributes, connection);\n\n        setTimeout(onAnimationEnd(vToken, callback), duration);\n    },\n\n    findRoute: function(vertices) {\n\n        vertices || (vertices = []);\n\n        var namespace = this.paper.options.routerNamespace || routers;\n        var router = this.model.router();\n        var defaultRouter = this.paper.options.defaultRouter;\n\n        if (!router) {\n            if (defaultRouter) router = defaultRouter;\n            else return vertices.map(Point); // no router specified\n        }\n\n        var routerFn = isFunction(router) ? router : namespace[router.name];\n        if (!isFunction(routerFn)) {\n            throw new Error('dia.LinkView: unknown router: \"' + router.name + '\".');\n        }\n\n        var args = router.args || {};\n\n        var route = routerFn.call(\n            this, // context\n            vertices, // vertices\n            args, // options\n            this // linkView\n        );\n\n        if (!route) return vertices.map(Point);\n        return route;\n    },\n\n    // Return the `d` attribute value of the `<path>` element representing the link\n    // between `source` and `target`.\n    findPath: function(route, sourcePoint, targetPoint) {\n\n        var namespace = this.paper.options.connectorNamespace || connectors;\n        var connector = this.model.connector();\n        var defaultConnector = this.paper.options.defaultConnector;\n\n        if (!connector) {\n            connector = defaultConnector || {};\n        }\n\n        var connectorFn = isFunction(connector) ? connector : namespace[connector.name];\n        if (!isFunction(connectorFn)) {\n            throw new Error('dia.LinkView: unknown connector: \"' + connector.name + '\".');\n        }\n\n        var args = clone(connector.args || {});\n        args.raw = true; // Request raw g.Path as the result.\n\n        var path = connectorFn.call(\n            this, // context\n            sourcePoint, // start point\n            targetPoint, // end point\n            route, // vertices\n            args, // options\n            this // linkView\n        );\n\n        if (typeof path === 'string') {\n            // Backwards compatibility for connectors not supporting `raw` option.\n            path = new Path(V.normalizePathData(path));\n        }\n\n        return path;\n    },\n\n    // Public API.\n    // -----------\n\n    getConnection: function() {\n\n        var path = this.path;\n        if (!path) return null;\n\n        return path.clone();\n    },\n\n    getSerializedConnection: function() {\n\n        var path = this.path;\n        if (!path) return null;\n\n        var metrics = this.metrics;\n        if (metrics.hasOwnProperty('data')) return metrics.data;\n        var data = path.serialize();\n        metrics.data = data;\n        return data;\n    },\n\n    getConnectionSubdivisions: function() {\n\n        var path = this.path;\n        if (!path) return null;\n\n        var metrics = this.metrics;\n        if (metrics.hasOwnProperty('segmentSubdivisions')) return metrics.segmentSubdivisions;\n        var subdivisions = path.getSegmentSubdivisions();\n        metrics.segmentSubdivisions = subdivisions;\n        return subdivisions;\n    },\n\n    getConnectionLength: function() {\n\n        var path = this.path;\n        if (!path) return 0;\n\n        var metrics = this.metrics;\n        if (metrics.hasOwnProperty('length')) return metrics.length;\n        var length = path.length({ segmentSubdivisions: this.getConnectionSubdivisions() });\n        metrics.length = length;\n        return length;\n    },\n\n    getPointAtLength: function(length) {\n\n        var path = this.path;\n        if (!path) return null;\n\n        return path.pointAtLength(length, { segmentSubdivisions: this.getConnectionSubdivisions() });\n    },\n\n    getPointAtRatio: function(ratio) {\n\n        var path = this.path;\n        if (!path) return null;\n        if (isPercentage(ratio)) ratio = parseFloat(ratio) / 100;\n        return path.pointAt(ratio, { segmentSubdivisions: this.getConnectionSubdivisions() });\n    },\n\n    getTangentAtLength: function(length) {\n\n        var path = this.path;\n        if (!path) return null;\n\n        return path.tangentAtLength(length, { segmentSubdivisions: this.getConnectionSubdivisions() });\n    },\n\n    getTangentAtRatio: function(ratio) {\n\n        var path = this.path;\n        if (!path) return null;\n\n        return path.tangentAt(ratio, { segmentSubdivisions: this.getConnectionSubdivisions() });\n    },\n\n    getClosestPoint: function(point) {\n\n        var path = this.path;\n        if (!path) return null;\n\n        return path.closestPoint(point, { segmentSubdivisions: this.getConnectionSubdivisions() });\n    },\n\n    getClosestPointLength: function(point) {\n\n        var path = this.path;\n        if (!path) return null;\n\n        return path.closestPointLength(point, { segmentSubdivisions: this.getConnectionSubdivisions() });\n    },\n\n    getClosestPointRatio: function(point) {\n\n        var path = this.path;\n        if (!path) return null;\n\n        return path.closestPointNormalizedLength(point, { segmentSubdivisions: this.getConnectionSubdivisions() });\n    },\n\n    // Get label position object based on two provided coordinates, x and y.\n    // (Used behind the scenes when user moves labels around.)\n    // Two signatures:\n    // - num, num, obj = x, y, options\n    // - num, num, num, obj = x, y, angle, options\n    // Accepts distance/offset options = `absoluteDistance: boolean`, `reverseDistance: boolean`, `absoluteOffset: boolean`\n    // - `absoluteOffset` is necessary in order to move beyond connection endpoints\n    // Additional options = `keepGradient: boolean`, `ensureLegibility: boolean`\n    getLabelPosition: function(x, y, p3, p4) {\n\n        var position = {};\n\n        // normalize data from the two possible signatures\n        var localAngle = 0;\n        var localOpt;\n        if (typeof p3 === 'number') {\n            // angle and opt provided as third and fourth argument\n            localAngle = p3;\n            localOpt = p4;\n        } else {\n            // opt provided as third argument\n            localOpt = p3;\n        }\n\n        // save localOpt as `args` of the position object that is passed along\n        if (localOpt) position.args = localOpt;\n\n        // identify distance/offset settings\n        var isDistanceRelative = !(localOpt && localOpt.absoluteDistance); // relative by default\n        var isDistanceAbsoluteReverse = (localOpt && localOpt.absoluteDistance && localOpt.reverseDistance); // non-reverse by default\n        var isOffsetAbsolute = localOpt && localOpt.absoluteOffset; // offset is non-absolute by default\n\n        // find closest point t\n        var path = this.path;\n        var pathOpt = { segmentSubdivisions: this.getConnectionSubdivisions() };\n        var labelPoint = new Point(x, y);\n        var t = path.closestPointT(labelPoint, pathOpt);\n\n        // DISTANCE:\n        var labelDistance = path.lengthAtT(t, pathOpt);\n        if (isDistanceRelative) labelDistance = (labelDistance / this.getConnectionLength()) || 0; // fix to prevent NaN for 0 length\n        if (isDistanceAbsoluteReverse) labelDistance = (-1 * (this.getConnectionLength() - labelDistance)) || 1; // fix for end point (-0 => 1)\n        position.distance = labelDistance;\n\n        // OFFSET:\n        // use absolute offset if:\n        // - opt.absoluteOffset is true,\n        // - opt.absoluteOffset is not true but there is no tangent\n        var tangent;\n        if (!isOffsetAbsolute) tangent = path.tangentAtT(t);\n        var labelOffset;\n        if (tangent) {\n            labelOffset = tangent.pointOffset(labelPoint);\n        } else {\n            var closestPoint = path.pointAtT(t);\n            var labelOffsetDiff = labelPoint.difference(closestPoint);\n            labelOffset = { x: labelOffsetDiff.x, y: labelOffsetDiff.y };\n        }\n        position.offset = labelOffset;\n\n        // ANGLE:\n        position.angle = localAngle;\n\n        return position;\n    },\n\n    _getLabelTransformationMatrix: function(labelPosition) {\n\n        var labelDistance;\n        var labelAngle = 0;\n        var args = {};\n        if (typeof labelPosition === 'number') {\n            labelDistance = labelPosition;\n        } else if (typeof labelPosition.distance === 'number') {\n            args = labelPosition.args || {};\n            labelDistance = labelPosition.distance;\n            labelAngle = labelPosition.angle || 0;\n        } else {\n            throw new Error('dia.LinkView: invalid label position distance.');\n        }\n\n        var isDistanceRelative = ((labelDistance > 0) && (labelDistance <= 1));\n\n        var labelOffset = 0;\n        var labelOffsetCoordinates = { x: 0, y: 0 };\n        if (labelPosition.offset) {\n            var positionOffset = labelPosition.offset;\n            if (typeof positionOffset === 'number') labelOffset = positionOffset;\n            if (positionOffset.x) labelOffsetCoordinates.x = positionOffset.x;\n            if (positionOffset.y) labelOffsetCoordinates.y = positionOffset.y;\n        }\n\n        var isOffsetAbsolute = ((labelOffsetCoordinates.x !== 0) || (labelOffsetCoordinates.y !== 0) || labelOffset === 0);\n\n        var isKeepGradient = args.keepGradient;\n        var isEnsureLegibility = args.ensureLegibility;\n\n        var path = this.path;\n        var pathOpt = { segmentSubdivisions: this.getConnectionSubdivisions() };\n\n        var distance = isDistanceRelative ? (labelDistance * this.getConnectionLength()) : labelDistance;\n        var tangent = path.tangentAtLength(distance, pathOpt);\n\n        var translation;\n        var angle = labelAngle;\n        if (tangent) {\n            if (isOffsetAbsolute) {\n                translation = tangent.start.clone();\n                translation.offset(labelOffsetCoordinates);\n            } else {\n                var normal = tangent.clone();\n                normal.rotate(tangent.start, -90);\n                normal.setLength(labelOffset);\n                translation = normal.end;\n            }\n\n            if (isKeepGradient) {\n                angle = (tangent.angle() + labelAngle);\n                if (isEnsureLegibility) {\n                    angle = normalizeAngle(((angle + 90) % 180) - 90);\n                }\n            }\n\n        } else {\n            // fallback - the connection has zero length\n            translation = path.start.clone();\n            if (isOffsetAbsolute) translation.offset(labelOffsetCoordinates);\n        }\n\n        return V.createSVGMatrix()\n            .translate(translation.x, translation.y)\n            .rotate(angle);\n    },\n\n    getLabelCoordinates: function(labelPosition) {\n\n        var transformationMatrix = this._getLabelTransformationMatrix(labelPosition);\n        return new Point(transformationMatrix.e, transformationMatrix.f);\n    },\n\n    getVertexIndex: function(x, y) {\n\n        var model = this.model;\n        var vertices = model.vertices();\n\n        var vertexLength = this.getClosestPointLength(new Point(x, y));\n\n        var idx = 0;\n        for (var n = vertices.length; idx < n; idx++) {\n            var currentVertex = vertices[idx];\n            var currentVertexLength = this.getClosestPointLength(currentVertex);\n            if (vertexLength < currentVertexLength) break;\n        }\n\n        return idx;\n    },\n\n    // Interaction. The controller part.\n    // ---------------------------------\n\n    notifyPointerdown(evt, x, y) {\n        CellView.prototype.pointerdown.call(this, evt, x, y);\n        this.notify('link:pointerdown', evt, x, y);\n    },\n\n    notifyPointermove(evt, x, y) {\n        CellView.prototype.pointermove.call(this, evt, x, y);\n        this.notify('link:pointermove', evt, x, y);\n    },\n\n    notifyPointerup(evt, x, y) {\n        this.notify('link:pointerup', evt, x, y);\n        CellView.prototype.pointerup.call(this, evt, x, y);\n    },\n\n    pointerdblclick: function(evt, x, y) {\n\n        CellView.prototype.pointerdblclick.apply(this, arguments);\n        this.notify('link:pointerdblclick', evt, x, y);\n    },\n\n    pointerclick: function(evt, x, y) {\n\n        CellView.prototype.pointerclick.apply(this, arguments);\n        this.notify('link:pointerclick', evt, x, y);\n    },\n\n    contextmenu: function(evt, x, y) {\n\n        CellView.prototype.contextmenu.apply(this, arguments);\n        this.notify('link:contextmenu', evt, x, y);\n    },\n\n    pointerdown: function(evt, x, y) {\n\n        this.notifyPointerdown(evt, x, y);\n        this.dragStart(evt, x, y);\n    },\n\n    pointermove: function(evt, x, y) {\n\n        // Backwards compatibility\n        var dragData = this._dragData;\n        if (dragData) this.eventData(evt, dragData);\n\n        var data = this.eventData(evt);\n        switch (data.action) {\n\n            case 'label-move':\n                this.dragLabel(evt, x, y);\n                break;\n\n            case 'arrowhead-move':\n                this.dragArrowhead(evt, x, y);\n                break;\n\n            case 'move':\n                this.drag(evt, x, y);\n                break;\n        }\n\n        // Backwards compatibility\n        if (dragData) assign(dragData, this.eventData(evt));\n\n        this.notifyPointermove(evt, x, y);\n    },\n\n    pointerup: function(evt, x, y) {\n\n        // Backwards compatibility\n        var dragData = this._dragData;\n        if (dragData) {\n            this.eventData(evt, dragData);\n            this._dragData = null;\n        }\n\n        var data = this.eventData(evt);\n        switch (data.action) {\n\n            case 'label-move':\n                this.dragLabelEnd(evt, x, y);\n                break;\n\n            case 'arrowhead-move':\n                this.dragArrowheadEnd(evt, x, y);\n                break;\n\n            case 'move':\n                this.dragEnd(evt, x, y);\n        }\n\n        this.notifyPointerup(evt, x, y);\n        this.checkMouseleave(evt);\n    },\n\n    mouseover: function(evt) {\n\n        CellView.prototype.mouseover.apply(this, arguments);\n        this.notify('link:mouseover', evt);\n    },\n\n    mouseout: function(evt) {\n\n        CellView.prototype.mouseout.apply(this, arguments);\n        this.notify('link:mouseout', evt);\n    },\n\n    mouseenter: function(evt) {\n\n        CellView.prototype.mouseenter.apply(this, arguments);\n        this.notify('link:mouseenter', evt);\n    },\n\n    mouseleave: function(evt) {\n\n        CellView.prototype.mouseleave.apply(this, arguments);\n        this.notify('link:mouseleave', evt);\n    },\n\n    mousewheel: function(evt, x, y, delta) {\n\n        CellView.prototype.mousewheel.apply(this, arguments);\n        this.notify('link:mousewheel', evt, x, y, delta);\n    },\n\n    onlabel: function(evt, x, y) {\n\n        this.notifyPointerdown(evt, x, y);\n\n        this.dragLabelStart(evt, x, y);\n\n        var stopPropagation = this.eventData(evt).stopPropagation;\n        if (stopPropagation) evt.stopPropagation();\n    },\n\n    // Drag Start Handlers\n\n    dragLabelStart: function(evt, x, y) {\n\n        if (this.can('labelMove')) {\n\n            if (this.isDefaultInteractionPrevented(evt)) return;\n\n            var labelNode = evt.currentTarget;\n            var labelIdx = parseInt(labelNode.getAttribute('label-idx'), 10);\n\n            var defaultLabelPosition = this._getDefaultLabelPositionProperty();\n            var initialLabelPosition = this._normalizeLabelPosition(this._getLabelPositionProperty(labelIdx));\n            var position = this._mergeLabelPositionProperty(initialLabelPosition, defaultLabelPosition);\n\n            var coords = this.getLabelCoordinates(position);\n            var dx = coords.x - x; // how much needs to be added to cursor x to get to label x\n            var dy = coords.y - y; // how much needs to be added to cursor y to get to label y\n\n            var positionAngle = this._getLabelPositionAngle(labelIdx);\n            var labelPositionArgs = this._getLabelPositionArgs(labelIdx);\n            var defaultLabelPositionArgs = this._getDefaultLabelPositionArgs();\n            var positionArgs = this._mergeLabelPositionArgs(labelPositionArgs, defaultLabelPositionArgs);\n\n            this.eventData(evt, {\n                action: 'label-move',\n                labelIdx: labelIdx,\n                dx: dx,\n                dy: dy,\n                positionAngle: positionAngle,\n                positionArgs: positionArgs,\n                stopPropagation: true\n            });\n\n        } else {\n\n            // Backwards compatibility:\n            // If labels can't be dragged no default action is triggered.\n            this.eventData(evt, { stopPropagation: true });\n        }\n\n        this.paper.delegateDragEvents(this, evt.data);\n    },\n\n    dragArrowheadStart: function(evt, x, y) {\n\n        if (!this.can('arrowheadMove')) return;\n\n        var arrowheadNode = evt.target;\n        var arrowheadType = arrowheadNode.getAttribute('end');\n        var data = this.startArrowheadMove(arrowheadType, { ignoreBackwardsCompatibility: true });\n\n        this.eventData(evt, data);\n    },\n\n    dragStart: function(evt, x, y) {\n\n        if (this.isDefaultInteractionPrevented(evt)) return;\n\n        if (!this.can('linkMove')) return;\n\n        this.eventData(evt, {\n            action: 'move',\n            dx: x,\n            dy: y\n        });\n    },\n\n    // Drag Handlers\n    dragLabel: function(evt, x, y) {\n\n        var data = this.eventData(evt);\n        var label = { position: this.getLabelPosition((x + data.dx), (y + data.dy), data.positionAngle, data.positionArgs) };\n        if (this.paper.options.snapLabels) delete label.position.offset;\n        // The `touchmove' events are not fired\n        // when the original event target is removed from the DOM.\n        // The labels are currently re-rendered completely when only\n        // the position changes. This is why we need to make sure that\n        // the label is updated synchronously.\n        // TODO: replace `touchmove` with `pointermove` (breaking change).\n        const setOptions = { ui: true };\n        if (this.paper.isAsync() && evt.type === 'touchmove') {\n            setOptions.async = false;\n        }\n        this.model.label(data.labelIdx, label, setOptions);\n    },\n\n    dragArrowhead: function(evt, x, y) {\n        if (this.paper.options.snapLinks) {\n            const isSnapped = this._snapArrowhead(evt, x, y);\n            if (!isSnapped && this.paper.options.snapLinksSelf) {\n                this._snapArrowheadSelf(evt, x, y);\n            }\n        } else {\n            if (this.paper.options.snapLinksSelf) {\n                this._snapArrowheadSelf(evt, x, y);\n            } else {\n                this._connectArrowhead(this.getEventTarget(evt), x, y, this.eventData(evt));\n            }\n        }\n    },\n\n    drag: function(evt, x, y) {\n\n        var data = this.eventData(evt);\n        this.model.translate(x - data.dx, y - data.dy, { ui: true });\n        this.eventData(evt, {\n            dx: x,\n            dy: y\n        });\n    },\n\n    // Drag End Handlers\n\n    dragLabelEnd: function() {\n        // noop\n    },\n\n    dragArrowheadEnd: function(evt, x, y) {\n\n        var data = this.eventData(evt);\n        var paper = this.paper;\n\n        if (paper.options.snapLinks) {\n            this._snapArrowheadEnd(data);\n        } else {\n            this._connectArrowheadEnd(data, x, y);\n        }\n\n        if (!paper.linkAllowed(this)) {\n            // If the changed link is not allowed, revert to its previous state.\n            this._disallow(data);\n        } else {\n            this._finishEmbedding(data);\n            this._notifyConnectEvent(data, evt);\n        }\n\n        this._afterArrowheadMove(data);\n    },\n\n    dragEnd: function() {\n        // noop\n    },\n\n    _disallow: function(data) {\n\n        switch (data.whenNotAllowed) {\n\n            case 'remove':\n                this.model.remove({ ui: true });\n                break;\n\n            case 'revert':\n            default:\n                this.model.set(data.arrowhead, data.initialEnd, { ui: true });\n                break;\n        }\n    },\n\n    _finishEmbedding: function(data) {\n\n        // Reparent the link if embedding is enabled\n        if (this.paper.options.embeddingMode && this.model.reparent()) {\n            // Make sure we don't reverse to the original 'z' index (see afterArrowheadMove()).\n            data.z = null;\n        }\n    },\n\n    _notifyConnectEvent: function(data, evt) {\n\n        var arrowhead = data.arrowhead;\n        var initialEnd = data.initialEnd;\n        var currentEnd = this.model.prop(arrowhead);\n        var endChanged = currentEnd && !Link.endsEqual(initialEnd, currentEnd);\n        if (endChanged) {\n            var paper = this.paper;\n            if (initialEnd.id) {\n                this.notify('link:disconnect', evt, paper.findViewByModel(initialEnd.id), data.initialMagnet, arrowhead);\n            }\n            if (currentEnd.id) {\n                this.notify('link:connect', evt, paper.findViewByModel(currentEnd.id), data.magnetUnderPointer, arrowhead);\n            }\n        }\n    },\n\n    _snapToPoints: function(snapPoint, points, radius) {\n        let closestPointX = null;\n        let closestDistanceX = Infinity;\n\n        let closestPointY = null;\n        let closestDistanceY = Infinity;\n\n        let x = snapPoint.x;\n        let y = snapPoint.y;\n\n        for (let i = 0; i < points.length; i++) {\n            const distX = Math.abs(points[i].x - snapPoint.x);\n            if (distX < closestDistanceX) {\n                closestDistanceX = distX;\n                closestPointX = points[i];\n            }\n\n            const distY = Math.abs(points[i].y - snapPoint.y);\n            if (distY < closestDistanceY) {\n                closestDistanceY = distY;\n                closestPointY = points[i];\n            }\n        }\n\n        if (closestDistanceX < radius) {\n            x = closestPointX.x;\n        }\n        if (closestDistanceY < radius) {\n            y = closestPointY.y;\n        }\n\n        return { x, y };\n    },\n\n    _snapArrowheadSelf: function(evt, x, y) {\n\n        const { paper, model } = this;\n        const { snapLinksSelf } = paper.options;\n        const data = this.eventData(evt);\n        const radius = snapLinksSelf.radius || 20;\n\n        const anchor = this.getEndAnchor(data.arrowhead === 'source' ? 'target' : 'source');\n        const vertices = model.vertices();\n        const points = [anchor, ...vertices];\n\n        const snapPoint = this._snapToPoints({ x: x, y: y }, points, radius);\n\n        const point = paper.localToClientPoint(snapPoint);\n        this._connectArrowhead(document.elementFromPoint(point.x, point.y), snapPoint.x, snapPoint.y, this.eventData(evt));\n    },\n\n    _snapArrowhead: function(evt, x, y) {\n\n        const { paper } = this;\n        const { snapLinks, connectionStrategy } = paper.options;\n        const data = this.eventData(evt);\n        let isSnapped = false;\n        // checking view in close area of the pointer\n\n        var r = snapLinks.radius || 50;\n        var viewsInArea = paper.findElementViewsInArea(\n            { x: x - r, y: y - r, width: 2 * r, height: 2 * r },\n            snapLinks.findInAreaOptions\n        );\n\n        var prevClosestView = data.closestView || null;\n        var prevClosestMagnet = data.closestMagnet || null;\n        var prevMagnetProxy = data.magnetProxy || null;\n\n        data.closestView = data.closestMagnet = data.magnetProxy = null;\n\n        var minDistance = Number.MAX_VALUE;\n        var pointer = new Point(x, y);\n\n        viewsInArea.forEach(function(view) {\n            const candidates = [];\n            // skip connecting to the element in case '.': { magnet: false } attribute present\n            if (view.el.getAttribute('magnet') !== 'false') {\n                candidates.push({\n                    bbox: view.model.getBBox(),\n                    magnet: view.el\n                });\n            }\n\n            view.$('[magnet]').toArray().forEach(magnet => {\n                candidates.push({\n                    bbox: view.getNodeBBox(magnet),\n                    magnet\n                });\n            });\n\n            candidates.forEach(candidate => {\n                const { magnet, bbox } = candidate;\n                // find distance from the center of the model to pointer coordinates\n                const distance = bbox.center().squaredDistance(pointer);\n                // the connection is looked up in a circle area by `distance < r`\n                if (distance < minDistance) {\n                    const isAlreadyValidated = prevClosestMagnet === magnet;\n                    if (isAlreadyValidated || paper.options.validateConnection.apply(\n                        paper, data.validateConnectionArgs(view, (view.el === magnet) ? null : magnet)\n                    )) {\n                        minDistance = distance;\n                        data.closestView = view;\n                        data.closestMagnet = magnet;\n                    }\n                }\n            });\n\n        }, this);\n\n        var end;\n        var magnetProxy = null;\n        var closestView = data.closestView;\n        var closestMagnet = data.closestMagnet;\n        if (closestMagnet) {\n            magnetProxy = data.magnetProxy = closestView.findProxyNode(closestMagnet, 'highlighter');\n        }\n        var endType = data.arrowhead;\n        var newClosestMagnet = (prevClosestMagnet !== closestMagnet);\n        if (prevClosestView && newClosestMagnet) {\n            prevClosestView.unhighlight(prevMagnetProxy, {\n                connecting: true,\n                snapping: true\n            });\n        }\n\n        if (closestView) {\n            const { prevEnd, prevX, prevY } = data;\n            data.prevX = x;\n            data.prevY = y;\n            isSnapped = true;\n\n            if (!newClosestMagnet)  {\n                if (typeof connectionStrategy !== 'function' || (prevX === x && prevY === y)) {\n                    // the magnet has not changed and the link's end does not depend on the x and y\n                    return isSnapped;\n                }\n            }\n\n            end = closestView.getLinkEnd(closestMagnet, x, y, this.model, endType);\n            if (!newClosestMagnet && isEqual(prevEnd, end)) {\n                // the source/target json has not changed\n                return isSnapped;\n            }\n\n            data.prevEnd = end;\n\n            if (newClosestMagnet) {\n                closestView.highlight(magnetProxy, {\n                    connecting: true,\n                    snapping: true\n                });\n            }\n\n        } else {\n\n            end = { x: x, y: y };\n        }\n\n        this.model.set(endType, end || { x: x, y: y }, { ui: true });\n\n        if (prevClosestView) {\n            this.notify('link:snap:disconnect', evt, prevClosestView, prevClosestMagnet, endType);\n        }\n        if (closestView) {\n            this.notify('link:snap:connect', evt, closestView, closestMagnet, endType);\n        }\n\n        return isSnapped;\n    },\n\n    _snapArrowheadEnd: function(data) {\n\n        // Finish off link snapping.\n        // Everything except view unhighlighting was already done on pointermove.\n        var closestView = data.closestView;\n        var closestMagnet = data.closestMagnet;\n        if (closestView && closestMagnet) {\n\n            closestView.unhighlight(data.magnetProxy, { connecting: true, snapping: true });\n            data.magnetUnderPointer = closestView.findMagnet(closestMagnet);\n        }\n\n        data.closestView = data.closestMagnet = null;\n    },\n\n    _connectArrowhead: function(target, x, y, data) {\n\n        // checking views right under the pointer\n        const { paper, model } = this;\n\n        if (data.eventTarget !== target) {\n            // Unhighlight the previous view under pointer if there was one.\n            if (data.magnetProxy) {\n                data.viewUnderPointer.unhighlight(data.magnetProxy, {\n                    connecting: true\n                });\n            }\n\n            const viewUnderPointer = data.viewUnderPointer = paper.findView(target);\n            if (viewUnderPointer) {\n                // If we found a view that is under the pointer, we need to find the closest\n                // magnet based on the real target element of the event.\n                const magnetUnderPointer = data.magnetUnderPointer = viewUnderPointer.findMagnet(target);\n                const magnetProxy = data.magnetProxy = viewUnderPointer.findProxyNode(magnetUnderPointer, 'highlighter');\n\n                if (magnetUnderPointer && this.paper.options.validateConnection.apply(\n                    paper,\n                    data.validateConnectionArgs(viewUnderPointer, magnetUnderPointer)\n                )) {\n                    // If there was no magnet found, do not highlight anything and assume there\n                    // is no view under pointer we're interested in reconnecting to.\n                    // This can only happen if the overall element has the attribute `'.': { magnet: false }`.\n                    if (magnetProxy) {\n                        viewUnderPointer.highlight(magnetProxy, {\n                            connecting: true\n                        });\n                    }\n                } else {\n                    // This type of connection is not valid. Disregard this magnet.\n                    data.magnetUnderPointer = null;\n                    data.magnetProxy = null;\n                }\n            } else {\n                // Make sure we'll unset previous magnet.\n                data.magnetUnderPointer = null;\n                data.magnetProxy = null;\n            }\n        }\n\n        data.eventTarget = target;\n\n        model.set(data.arrowhead, { x: x, y: y }, { ui: true });\n    },\n\n    _connectArrowheadEnd: function(data = {}, x, y) {\n\n        const { model } = this;\n        const { viewUnderPointer, magnetUnderPointer, magnetProxy, arrowhead } = data;\n\n        if (!magnetUnderPointer || !magnetProxy || !viewUnderPointer) return;\n\n        viewUnderPointer.unhighlight(magnetProxy, { connecting: true });\n\n        // The link end is taken from the magnet under the pointer, not the proxy.\n        const end = viewUnderPointer.getLinkEnd(magnetUnderPointer, x, y, model, arrowhead);\n        model.set(arrowhead, end, { ui: true });\n    },\n\n    _beforeArrowheadMove: function(data) {\n\n        data.z = this.model.get('z');\n        this.model.toFront();\n\n        // Let the pointer propagate through the link view elements so that\n        // the `evt.target` is another element under the pointer, not the link itself.\n        var style = this.el.style;\n        data.pointerEvents = style.pointerEvents;\n        style.pointerEvents = 'none';\n\n        if (this.paper.options.markAvailable) {\n            this._markAvailableMagnets(data);\n        }\n    },\n\n    _afterArrowheadMove: function(data) {\n\n        if (data.z !== null) {\n            this.model.set('z', data.z, { ui: true });\n            data.z = null;\n        }\n\n        // Put `pointer-events` back to its original value. See `_beforeArrowheadMove()` for explanation.\n        this.el.style.pointerEvents = data.pointerEvents;\n\n        if (this.paper.options.markAvailable) {\n            this._unmarkAvailableMagnets(data);\n        }\n    },\n\n    _createValidateConnectionArgs: function(arrowhead) {\n        // It makes sure the arguments for validateConnection have the following form:\n        // (source view, source magnet, target view, target magnet and link view)\n        var args = [];\n\n        args[4] = arrowhead;\n        args[5] = this;\n\n        var oppositeArrowhead;\n        var i = 0;\n        var j = 0;\n\n        if (arrowhead === 'source') {\n            i = 2;\n            oppositeArrowhead = 'target';\n        } else {\n            j = 2;\n            oppositeArrowhead = 'source';\n        }\n\n        var end = this.model.get(oppositeArrowhead);\n\n        if (end.id) {\n            var view = args[i] = this.paper.findViewByModel(end.id);\n            var magnet = view.getMagnetFromLinkEnd(end);\n            if (magnet === view.el) magnet = undefined;\n            args[i + 1] = magnet;\n        }\n\n        function validateConnectionArgs(cellView, magnet) {\n            args[j] = cellView;\n            args[j + 1] = cellView.el === magnet ? undefined : magnet;\n            return args;\n        }\n\n        return validateConnectionArgs;\n    },\n\n    _markAvailableMagnets: function(data) {\n\n        function isMagnetAvailable(view, magnet) {\n            var paper = view.paper;\n            var validate = paper.options.validateConnection;\n            return validate.apply(paper, this.validateConnectionArgs(view, magnet));\n        }\n\n        var paper = this.paper;\n        var elements = paper.model.getCells();\n        data.marked = {};\n\n        for (var i = 0, n = elements.length; i < n; i++) {\n            var view = elements[i].findView(paper);\n\n            if (!view) {\n                continue;\n            }\n\n            var magnets = Array.prototype.slice.call(view.el.querySelectorAll('[magnet]'));\n            if (view.el.getAttribute('magnet') !== 'false') {\n                // Element wrapping group is also a magnet\n                magnets.push(view.el);\n            }\n\n            var availableMagnets = magnets.filter(isMagnetAvailable.bind(data, view));\n\n            if (availableMagnets.length > 0) {\n                // highlight all available magnets\n                for (var j = 0, m = availableMagnets.length; j < m; j++) {\n                    view.highlight(availableMagnets[j], { magnetAvailability: true });\n                }\n                // highlight the entire view\n                view.highlight(null, { elementAvailability: true });\n\n                data.marked[view.model.id] = availableMagnets;\n            }\n        }\n    },\n\n    _unmarkAvailableMagnets: function(data) {\n\n        var markedKeys = Object.keys(data.marked);\n        var id;\n        var markedMagnets;\n\n        for (var i = 0, n = markedKeys.length; i < n; i++) {\n            id = markedKeys[i];\n            markedMagnets = data.marked[id];\n\n            var view = this.paper.findViewByModel(id);\n            if (view) {\n                for (var j = 0, m = markedMagnets.length; j < m; j++) {\n                    view.unhighlight(markedMagnets[j], { magnetAvailability: true });\n                }\n                view.unhighlight(null, { elementAvailability: true });\n            }\n        }\n\n        data.marked = null;\n    },\n\n    startArrowheadMove: function(end, opt) {\n\n        opt || (opt = {});\n\n        // Allow to delegate events from an another view to this linkView in order to trigger arrowhead\n        // move without need to click on the actual arrowhead dom element.\n        var data = {\n            action: 'arrowhead-move',\n            arrowhead: end,\n            whenNotAllowed: opt.whenNotAllowed || 'revert',\n            initialMagnet: this[end + 'Magnet'] || (this[end + 'View'] ? this[end + 'View'].el : null),\n            initialEnd: clone(this.model.get(end)),\n            validateConnectionArgs: this._createValidateConnectionArgs(end)\n        };\n\n        this._beforeArrowheadMove(data);\n\n        if (opt.ignoreBackwardsCompatibility !== true) {\n            this._dragData = data;\n        }\n\n        return data;\n    },\n\n    // Lifecycle methods\n\n    onMount: function() {\n        CellView.prototype.onMount.apply(this, arguments);\n        this.mountLabels();\n    },\n\n    onDetach: function() {\n        CellView.prototype.onDetach.apply(this, arguments);\n        this.unmountLabels();\n    },\n\n    onRemove: function() {\n        CellView.prototype.onRemove.apply(this, arguments);\n        this.unmountLabels();\n    }\n\n}, {\n\n    Flags: Flags,\n});\n\nObject.defineProperty(LinkView.prototype, 'sourceBBox', {\n\n    enumerable: true,\n\n    get: function() {\n        var sourceView = this.sourceView;\n        if (!sourceView) {\n            var sourceDef = this.model.source();\n            return new Rect(sourceDef.x, sourceDef.y);\n        }\n        var sourceMagnet = this.sourceMagnet;\n        if (sourceView.isNodeConnection(sourceMagnet)) {\n            return new Rect(this.sourceAnchor);\n        }\n        return sourceView.getNodeBBox(sourceMagnet || sourceView.el);\n    }\n\n});\n\nObject.defineProperty(LinkView.prototype, 'targetBBox', {\n\n    enumerable: true,\n\n    get: function() {\n        var targetView = this.targetView;\n        if (!targetView) {\n            var targetDef = this.model.target();\n            return new Rect(targetDef.x, targetDef.y);\n        }\n        var targetMagnet = this.targetMagnet;\n        if (targetView.isNodeConnection(targetMagnet)) {\n            return new Rect(this.targetAnchor);\n        }\n        return targetView.getNodeBBox(targetMagnet || targetView.el);\n    }\n});\n\n","import { View } from '../mvc/index.mjs';\nimport { addClassNamePrefix } from '../util/util.mjs';\n\nexport const LayersNames = {\n    GRID: 'grid',\n    CELLS: 'cells',\n    BACK: 'back',\n    FRONT: 'front',\n    TOOLS: 'tools',\n    LABELS: 'labels'\n};\n\nexport const PaperLayer = View.extend({\n\n    tagName: 'g',\n    svgElement: true,\n    pivotNodes: null,\n    defaultTheme: null,\n\n    options: {\n        name: ''\n    },\n\n    className: function() {\n        return addClassNamePrefix(`${this.options.name}-layer`);\n    },\n\n    init: function() {\n        this.pivotNodes = {};\n    },\n\n    insertSortedNode: function(node, z) {\n        this.el.insertBefore(node, this.insertPivot(z));\n    },\n\n    insertNode: function(node) {\n        const { el } = this;\n        if (node.parentNode !== el) {\n            el.appendChild(node);\n        }\n    },\n\n    insertPivot: function(z) {\n        const { el, pivotNodes } = this;\n        z = +z;\n        z || (z = 0);\n        let pivotNode = pivotNodes[z];\n        if (pivotNode) return pivotNode;\n        pivotNode = pivotNodes[z] = document.createComment('z-index:' + (z + 1));\n        let neighborZ = -Infinity;\n        for (let currentZ in pivotNodes) {\n            currentZ = +currentZ;\n            if (currentZ < z && currentZ > neighborZ) {\n                neighborZ = currentZ;\n                if (neighborZ === z - 1) continue;\n            }\n        }\n        if (neighborZ !== -Infinity) {\n            const neighborPivot = pivotNodes[neighborZ];\n            // Insert After\n            el.insertBefore(pivotNode, neighborPivot.nextSibling);\n        } else {\n            // First Child\n            el.insertBefore(pivotNode, el.firstChild);\n        }\n        return pivotNode;\n    },\n\n    removePivots: function() {\n        const { el, pivotNodes } = this;\n        for (let z in pivotNodes) el.removeChild(pivotNodes[z]);\n        this.pivotNodes = {};\n    }\n\n});\n","import { assign } from '../util/index.mjs';\nimport V from '../V/index.mjs';\nimport { HighlighterView } from '../dia/HighlighterView.mjs';\n\nexport const stroke = HighlighterView.extend({\n\n    tagName: 'path',\n    className: 'highlight-stroke',\n    attributes: {\n        'pointer-events': 'none',\n        'fill': 'none'\n    },\n\n    options: {\n        padding: 3,\n        rx: 0,\n        ry: 0,\n        useFirstSubpath: false,\n        attrs: {\n            'stroke-width': 3,\n            'stroke': '#FEB663'\n        }\n    },\n\n    getPathData(cellView, node) {\n        const { options } = this;\n        const { useFirstSubpath } = options;\n        let d;\n        try {\n            const vNode = V(node);\n            d = vNode.convertToPathData().trim();\n            if (vNode.tagName() === 'PATH' && useFirstSubpath) {\n                const secondSubpathIndex = d.search(/.M/i) + 1;\n                if (secondSubpathIndex > 0) {\n                    d = d.substr(0, secondSubpathIndex);\n                }\n            }\n        } catch (error) {\n            // Failed to get path data from magnet element.\n            // Draw a rectangle around the node instead.\n            const nodeBBox = cellView.getNodeBoundingRect(node);\n            d = V.rectToPath(assign({}, options, nodeBBox.toJSON()));\n        }\n        return d;\n    },\n\n    highlightConnection(cellView) {\n        this.vel.attr('d', cellView.getSerializedConnection());\n    },\n\n    highlightNode(cellView, node) {\n        const { vel, options } = this;\n        const { padding, layer } = options;\n        let highlightMatrix = this.getNodeMatrix(cellView, node);\n        // Add padding to the highlight element.\n        if (padding) {\n            if (!layer && node === cellView.el) {\n                // If the highlighter is appended to the cellView\n                // and we measure the size of the cellView wrapping group\n                // it's necessary to remove the highlighter first\n                vel.remove();\n            }\n            let nodeBBox = cellView.getNodeBoundingRect(node);\n            const cx = nodeBBox.x + (nodeBBox.width / 2);\n            const cy = nodeBBox.y + (nodeBBox.height / 2);\n            nodeBBox = V.transformRect(nodeBBox, highlightMatrix);\n            const width = Math.max(nodeBBox.width, 1);\n            const height = Math.max(nodeBBox.height, 1);\n            const sx = (width + padding) / width;\n            const sy = (height + padding) / height;\n            const paddingMatrix = V.createSVGMatrix({\n                a: sx,\n                b: 0,\n                c: 0,\n                d: sy,\n                e: cx - sx * cx,\n                f: cy - sy * cy\n            });\n            highlightMatrix = highlightMatrix.multiply(paddingMatrix);\n        }\n        vel.attr({\n            'd': this.getPathData(cellView, node),\n            'transform': V.matrixToTransformString(highlightMatrix)\n        });\n    },\n\n    highlight(cellView, node) {\n        const { vel, options } = this;\n        vel.attr(options.attrs);\n        if (options.nonScalingStroke) {\n            vel.attr('vector-effect', 'non-scaling-stroke');\n        }\n        if (cellView.isNodeConnection(node)) {\n            this.highlightConnection(cellView);\n        } else {\n            this.highlightNode(cellView, node);\n        }\n    }\n\n});\n","import V from '../V/index.mjs';\nimport { HighlighterView } from '../dia/HighlighterView.mjs';\n\nconst MASK_CLIP = 20;\n\nfunction forEachDescendant(vel, fn) {\n    const descendants = vel.children();\n    while (descendants.length > 0) {\n        const descendant = descendants.shift();\n        if (fn(descendant)) {\n            descendants.push(...descendant.children());\n        }\n    }\n}\n\nexport const mask = HighlighterView.extend({\n\n    tagName: 'rect',\n    className: 'highlight-mask',\n    attributes: {\n        'pointer-events': 'none'\n    },\n\n    options: {\n        padding: 3,\n        maskClip: MASK_CLIP,\n        deep: false,\n        attrs: {\n            'stroke': '#FEB663',\n            'stroke-width': 3,\n            'stroke-linecap': 'butt',\n            'stroke-linejoin': 'miter',\n        }\n    },\n\n    VISIBLE: 'white',\n    INVISIBLE: 'black',\n\n    MASK_ROOT_ATTRIBUTE_BLACKLIST: [\n        'marker-start',\n        'marker-end',\n        'marker-mid',\n        'transform',\n        'stroke-dasharray',\n        'class',\n    ],\n\n    MASK_CHILD_ATTRIBUTE_BLACKLIST: [\n        'stroke',\n        'fill',\n        'stroke-width',\n        'stroke-opacity',\n        'stroke-dasharray',\n        'fill-opacity',\n        'marker-start',\n        'marker-end',\n        'marker-mid',\n        'class',\n    ],\n\n    // TODO: change the list to a function callback\n    MASK_REPLACE_TAGS: [\n        'FOREIGNOBJECT',\n        'IMAGE',\n        'USE',\n        'TEXT',\n        'TSPAN',\n        'TEXTPATH'\n    ],\n\n    // TODO: change the list to a function callback\n    MASK_REMOVE_TAGS: [\n        'TEXT',\n        'TSPAN',\n        'TEXTPATH'\n    ],\n\n    transformMaskChild(cellView, childEl) {\n        const {\n            MASK_CHILD_ATTRIBUTE_BLACKLIST,\n            MASK_REPLACE_TAGS,\n            MASK_REMOVE_TAGS\n        } = this;\n        const childTagName = childEl.tagName();\n        // Do not include the element in the mask's image\n        if (!V.isSVGGraphicsElement(childEl) || MASK_REMOVE_TAGS.includes(childTagName)) {\n            childEl.remove();\n            return false;\n        }\n        // Replace the element with a rectangle\n        if (MASK_REPLACE_TAGS.includes(childTagName)) {\n            // Note: clone() method does not change the children ids\n            const originalChild = cellView.vel.findOne(`#${childEl.id}`);\n            if (originalChild) {\n                const { node: originalNode } = originalChild;\n                let childBBox = cellView.getNodeBoundingRect(originalNode);\n                if (cellView.model.isElement()) {\n                    childBBox = V.transformRect(childBBox, cellView.getNodeMatrix(originalNode));\n                }\n                const replacement = V('rect', childBBox.toJSON());\n                const { x: ox, y: oy } = childBBox.center();\n                const { angle, cx = ox, cy = oy } = originalChild.rotate();\n                if (angle) replacement.rotate(angle, cx, cy);\n                // Note: it's not important to keep the same sibling index since all subnodes are filled\n                childEl.parent().append(replacement);\n            }\n            childEl.remove();\n            return false;\n        }\n        // Keep the element, but clean it from certain attributes\n        MASK_CHILD_ATTRIBUTE_BLACKLIST.forEach(attrName => {\n            if (attrName === 'fill' && childEl.attr('fill') === 'none') return;\n            childEl.removeAttr(attrName);\n        });\n        return true;\n    },\n\n    transformMaskRoot(_cellView, rootEl) {\n        const { MASK_ROOT_ATTRIBUTE_BLACKLIST } = this;\n        MASK_ROOT_ATTRIBUTE_BLACKLIST.forEach(attrName => {\n            rootEl.removeAttr(attrName);\n        });\n    },\n\n    getMaskShape(cellView, vel) {\n        const { options, MASK_REPLACE_TAGS } = this;\n        const { deep } = options;\n        const tagName = vel.tagName();\n        let maskRoot;\n        if (tagName === 'G') {\n            if (!deep) return null;\n            maskRoot = vel.clone();\n            forEachDescendant(maskRoot, maskChild => this.transformMaskChild(cellView, maskChild));\n        } else {\n            if (MASK_REPLACE_TAGS.includes(tagName)) return null;\n            maskRoot = vel.clone();\n        }\n        this.transformMaskRoot(cellView, maskRoot);\n        return maskRoot;\n    },\n\n    getMaskId() {\n        return `highlight-mask-${this.cid}`;\n    },\n\n    getMask(cellView, vNode) {\n\n        const { VISIBLE, INVISIBLE, options } = this;\n        const { padding, attrs } = options;\n        // support both `strokeWidth` and `stroke-width` attribute names\n        const strokeWidth = parseFloat(V('g').attr(attrs).attr('stroke-width'));\n        const hasNodeFill = vNode.attr('fill') !== 'none';\n        let magnetStrokeWidth = parseFloat(vNode.attr('stroke-width'));\n        if (isNaN(magnetStrokeWidth)) magnetStrokeWidth = 1;\n        // stroke of the invisible shape\n        const minStrokeWidth = magnetStrokeWidth + padding * 2;\n        // stroke of the visible shape\n        const maxStrokeWidth = minStrokeWidth + strokeWidth * 2;\n        let maskEl = this.getMaskShape(cellView, vNode);\n        if (!maskEl) {\n            const nodeBBox = cellView.getNodeBoundingRect(vNode.node);\n            // Make sure the rect is visible\n            nodeBBox.inflate(nodeBBox.width ? 0 : 0.5, nodeBBox.height ? 0 : 0.5);\n            maskEl =  V('rect', nodeBBox.toJSON());\n        }\n        maskEl.attr(attrs);\n        return V('mask', {\n            'id': this.getMaskId()\n        }).append([\n            maskEl.clone().attr({\n                'fill': hasNodeFill ? VISIBLE : 'none',\n                'stroke': VISIBLE,\n                'stroke-width': maxStrokeWidth\n            }),\n            maskEl.clone().attr({\n                'fill': hasNodeFill ? INVISIBLE : 'none',\n                'stroke': INVISIBLE,\n                'stroke-width': minStrokeWidth\n            })\n        ]);\n    },\n\n    removeMask(paper) {\n        const maskNode = paper.svg.getElementById(this.getMaskId());\n        if (maskNode) {\n            paper.defs.removeChild(maskNode);\n        }\n    },\n\n    addMask(paper, maskEl) {\n        paper.defs.appendChild(maskEl.node);\n    },\n\n    highlight(cellView, node) {\n        const { options, vel } = this;\n        const { padding, attrs, maskClip = MASK_CLIP, layer } = options;\n        const color = ('stroke' in attrs) ? attrs['stroke'] : '#000000';\n        if (!layer && node === cellView.el) {\n            // If the highlighter is appended to the cellView\n            // and we measure the size of the cellView wrapping group\n            // it's necessary to remove the highlighter first\n            vel.remove();\n        }\n        const highlighterBBox = cellView.getNodeBoundingRect(node).inflate(padding + maskClip);\n        const highlightMatrix = this.getNodeMatrix(cellView, node);\n        const maskEl = this.getMask(cellView, V(node));\n        this.addMask(cellView.paper, maskEl);\n        vel.attr(highlighterBBox.toJSON());\n        vel.attr({\n            'transform': V.matrixToTransformString(highlightMatrix),\n            'mask': `url(#${maskEl.id})`,\n            'fill': color\n        });\n    },\n\n    unhighlight(cellView) {\n        this.removeMask(cellView.paper);\n    }\n\n});\n","import { HighlighterView } from '../dia/HighlighterView.mjs';\n\nexport const opacity = HighlighterView.extend({\n\n    UPDATABLE: false,\n    MOUNTABLE: false,\n\n    highlight: function(_cellView, node) {\n        const { alphaValue = 0.3 } = this.options;\n        node.style.opacity = alphaValue;\n    },\n\n    unhighlight: function(_cellView, node) {\n        node.style.opacity = '';\n    }\n\n});\n","import * as util from '../util/index.mjs';\nimport V from '../V/index.mjs';\nimport { HighlighterView } from '../dia/HighlighterView.mjs';\n\nconst className = util.addClassNamePrefix('highlighted');\n\nexport const addClass = HighlighterView.extend({\n\n    UPDATABLE: false,\n    MOUNTABLE: false,\n\n    options: {\n        className\n    },\n\n    highlight: function(_cellView, node) {\n        V(node).addClass(this.options.className);\n    },\n\n    unhighlight: function(_cellView, node) {\n        V(node).removeClass(this.options.className);\n    }\n\n}, {\n    // Backwards Compatibility\n    className\n});\n","import { Rect } from '../g/index.mjs';\nimport { HighlighterView } from '../dia/HighlighterView.mjs';\nimport {\n    normalizeSides,\n    isEqual,\n} from '../util/index.mjs';\nimport {\n    Positions,\n    getRectPoint,\n} from '../util/getRectPoint.mjs';\n\nconst Directions = {\n    ROW: 'row',\n    COLUMN: 'column'\n};\n\nexport const list = HighlighterView.extend({\n\n    tagName: 'g',\n    MOUNTABLE: true,\n    UPDATE_ATTRIBUTES: function() {\n        return [this.options.attribute];\n    },\n\n    _prevItems: null,\n\n    highlight(elementView, node) {\n        const element = elementView.model;\n        const { attribute, size = 20, gap = 5, direction = Directions.ROW } = this.options;\n        if (!attribute) throw new Error('List: attribute is required');\n        const normalizedSize = (typeof size === 'number') ? { width: size, height: size } : size;\n        const isRowDirection = (direction === Directions.ROW);\n        const itemWidth = isRowDirection ? normalizedSize.width : normalizedSize.height;\n        let items = element.get(attribute);\n        if (!Array.isArray(items)) items = [];\n        const prevItems = this._prevItems || [];\n        const comparison = items.map((item, index) => isEqual(prevItems[index], items[index]));\n        if (prevItems.length !== items.length || comparison.some(unchanged => !unchanged)) {\n            const prevEls = this.vel.children();\n            const itemsEls = items.map((item, index) => {\n                const prevEl = (index in prevEls) ? prevEls[index].node : null;\n                if (comparison[index]) return prevEl;\n                const itemEl = this.createListItem(item, normalizedSize, prevEl);\n                if (!itemEl) return null;\n                if (!(itemEl instanceof SVGElement)) throw new Error('List: item must be an SVGElement');\n                itemEl.dataset.index = index;\n                itemEl.dataset.attribute = attribute;\n                const offset = index * (itemWidth + gap);\n                itemEl.setAttribute('transform', (isRowDirection)\n                    ? `translate(${offset}, 0)`\n                    : `translate(0, ${offset})`\n                );\n                return itemEl;\n            });\n            this.vel.empty().append(itemsEls);\n            this._prevItems = items;\n        }\n        const itemsCount = items.length;\n        const length = (itemsCount === 0)\n            ? 0\n            : (itemsCount * itemWidth + (itemsCount - 1) * gap);\n        const listSize = (isRowDirection)\n            ? { width: length, height: normalizedSize.height }\n            : { width: normalizedSize.width, height: length };\n\n        this.position(element, listSize);\n    },\n\n    position(element, listSize) {\n        const { vel, options } = this;\n        const { margin = 5, position = 'top-left' } = options;\n        const { width, height } = element.size();\n        const { left, right, top, bottom } = normalizeSides(margin);\n        const bbox = new Rect(left, top, width - (left + right), height - (top + bottom));\n        let { x, y } = getRectPoint(bbox, position);\n        // x\n        switch (position) {\n            case Positions.CENTER:\n            case Positions.TOP:\n            case Positions.BOTTOM: {\n                x -= listSize.width / 2;\n                break;\n            }\n            case Positions.RIGHT:\n            case Positions.BOTTOM_RIGHT:\n            case Positions.TOP_RIGHT: {\n                x -= listSize.width;\n                break;\n            }\n        }\n        // y\n        switch (position) {\n            case Positions.CENTER:\n            case Positions.RIGHT:\n            case Positions.LEFT: {\n                y -= listSize.height / 2;\n                break;\n            }\n            case Positions.BOTTOM:\n            case Positions.BOTTOM_RIGHT:\n            case Positions.BOTTOM_LEFT: {\n                y -= listSize.height;\n                break;\n            }\n        }\n        vel.attr('transform', `translate(${x}, ${y})`);\n    }\n}, {\n    Directions,\n    Positions\n});\n","import { Line, Point } from '../g/index.mjs';\nimport { isPercentage } from '../util/index.mjs';\n\nfunction connectionRatio(view, _magnet, _refPoint, opt) {\n\n    var ratio = ('ratio' in opt) ? opt.ratio : 0.5;\n    return view.getPointAtRatio(ratio);\n}\n\nfunction connectionLength(view, _magnet, _refPoint, opt) {\n\n    var length = ('length' in opt) ? opt.length : 20;\n    return view.getPointAtLength(length);\n}\n\nfunction _connectionPerpendicular(view, _magnet, refPoint, opt) {\n\n    var OFFSET = 1e6;\n    var path = view.getConnection();\n    var segmentSubdivisions = view.getConnectionSubdivisions();\n    var verticalLine = new Line(refPoint.clone().offset(0, OFFSET), refPoint.clone().offset(0, -OFFSET));\n    var horizontalLine = new Line(refPoint.clone().offset(OFFSET, 0), refPoint.clone().offset(-OFFSET, 0));\n    var verticalIntersections = verticalLine.intersect(path, { segmentSubdivisions: segmentSubdivisions });\n    var horizontalIntersections = horizontalLine.intersect(path, { segmentSubdivisions: segmentSubdivisions });\n    var intersections = [];\n    if (verticalIntersections) Array.prototype.push.apply(intersections, verticalIntersections);\n    if (horizontalIntersections) Array.prototype.push.apply(intersections, horizontalIntersections);\n    if (intersections.length > 0) return refPoint.chooseClosest(intersections);\n    if ('fallbackAt' in opt) {\n        return getPointAtLink(view, opt.fallbackAt);\n    }\n    return connectionClosest(view, _magnet, refPoint, opt);\n}\n\nfunction _connectionClosest(view, _magnet, refPoint, _opt) {\n\n    var closestPoint = view.getClosestPoint(refPoint);\n    if (!closestPoint) return new Point();\n    return closestPoint;\n}\n\nexport function resolveRef(fn) {\n    return function(view, magnet, ref, opt) {\n        if (ref instanceof Element) {\n            var refView = this.paper.findView(ref);\n            var refPoint;\n            if (refView) {\n                if (refView.isNodeConnection(ref)) {\n                    var distance = ('fixedAt' in opt) ? opt.fixedAt : '50%';\n                    refPoint = getPointAtLink(refView, distance);\n                } else {\n                    refPoint = refView.getNodeBBox(ref).center();\n                }\n            } else {\n                // Something went wrong\n                refPoint = new Point();\n            }\n            return fn.call(this, view, magnet, refPoint, opt);\n        }\n        return fn.apply(this, arguments);\n    };\n}\n\nfunction getPointAtLink(view, value) {\n    var parsedValue = parseFloat(value);\n    if (isPercentage(value)) {\n        return view.getPointAtRatio(parsedValue / 100);\n    } else {\n        return view.getPointAtLength(parsedValue);\n    }\n}\n\n// joint.linkAnchors\nexport { connectionRatio, connectionLength };\nexport const connectionPerpendicular = resolveRef(_connectionPerpendicular);\nexport const connectionClosest = resolveRef(_connectionClosest);\n","import * as g from '../g/index.mjs';\nimport V from '../V/index.mjs';\nimport * as util from '../util/index.mjs';\n\nfunction offsetPoint(p1, p2, offset) {\n    if (util.isPlainObject(offset)) {\n        const { x, y } = offset;\n        if (isFinite(y)) {\n            const line =  new g.Line(p2, p1);\n            const { start, end } = line.parallel(y);\n            p2 = start;\n            p1 = end;\n        }\n        offset = x;\n    }\n    if (!isFinite(offset)) return p1;\n    var length = p1.distance(p2);\n    if (offset === 0 && length > 0) return p1;\n    return p1.move(p2, -Math.min(offset, length - 1));\n}\n\nfunction stroke(magnet) {\n\n    var stroke = magnet.getAttribute('stroke-width');\n    if (stroke === null) return 0;\n    return parseFloat(stroke) || 0;\n}\n\nfunction alignLine(line, type, offset = 0) {\n    let coordinate, a, b, direction;\n    const { start, end } = line;\n    switch (type) {\n        case 'left':\n            coordinate = 'x';\n            a = end;\n            b = start;\n            direction = -1;\n            break;\n        case 'right':\n            coordinate = 'x';\n            a = start;\n            b = end;\n            direction = 1;\n            break;\n        case 'top':\n            coordinate = 'y';\n            a = end;\n            b = start;\n            direction = -1;\n            break;\n        case 'bottom':\n            coordinate = 'y';\n            a = start;\n            b = end;\n            direction = 1;\n            break;\n        default:\n            return;\n    }\n    if (start[coordinate] < end[coordinate]) {\n        a[coordinate] = b[coordinate];\n    } else {\n        b[coordinate] = a[coordinate];\n    }\n    if (isFinite(offset)) {\n        a[coordinate] += direction * offset;\n        b[coordinate] += direction * offset;\n    }\n}\n\n// Connection Points\n\nfunction anchorConnectionPoint(line, _view, _magnet, opt) {\n    let { offset, alignOffset, align } = opt;\n    if (align) alignLine(line, align, alignOffset);\n    return offsetPoint(line.end, line.start, offset);\n}\n\nfunction bboxIntersection(line, view, magnet, opt) {\n\n    var bbox = view.getNodeBBox(magnet);\n    if (opt.stroke) bbox.inflate(stroke(magnet) / 2);\n    var intersections = line.intersect(bbox);\n    var cp = (intersections)\n        ? line.start.chooseClosest(intersections)\n        : line.end;\n    return offsetPoint(cp, line.start, opt.offset);\n}\n\nfunction rectangleIntersection(line, view, magnet, opt) {\n\n    var angle = view.model.angle();\n    if (angle === 0) {\n        return bboxIntersection(line, view, magnet, opt);\n    }\n\n    var bboxWORotation = view.getNodeUnrotatedBBox(magnet);\n    if (opt.stroke) bboxWORotation.inflate(stroke(magnet) / 2);\n    var center = bboxWORotation.center();\n    var lineWORotation = line.clone().rotate(center, angle);\n    var intersections = lineWORotation.setLength(1e6).intersect(bboxWORotation);\n    var cp = (intersections)\n        ? lineWORotation.start.chooseClosest(intersections).rotate(center, -angle)\n        : line.end;\n    return offsetPoint(cp, line.start, opt.offset);\n}\n\nfunction findShapeNode(magnet) {\n    if (!magnet) return null;\n    var node = magnet;\n    do {\n        var tagName = node.tagName;\n        if (typeof tagName !== 'string') return null;\n        tagName = tagName.toUpperCase();\n        if (tagName === 'G') {\n            node = node.firstElementChild;\n        } else if (tagName === 'TITLE') {\n            node = node.nextElementSibling;\n        } else break;\n    } while (node);\n    return node;\n}\n\nvar BNDR_SUBDIVISIONS = 'segmentSubdivisons';\nvar BNDR_SHAPE_BBOX = 'shapeBBox';\n\nfunction boundaryIntersection(line, view, magnet, opt) {\n\n    var node, intersection;\n    var selector = opt.selector;\n    var anchor = line.end;\n\n    if (typeof selector === 'string') {\n        node = view.findNode(selector);\n    } else if (selector === false) {\n        node = magnet;\n    } else if (Array.isArray(selector)) {\n        node = util.getByPath(magnet, selector);\n    } else {\n        node = findShapeNode(magnet);\n    }\n\n    if (!V.isSVGGraphicsElement(node)) {\n        if (node === magnet || !V.isSVGGraphicsElement(magnet)) return anchor;\n        node = magnet;\n    }\n\n    var localShape = view.getNodeShape(node);\n    var magnetMatrix = view.getNodeMatrix(node);\n    var translateMatrix = view.getRootTranslateMatrix();\n    var rotateMatrix = view.getRootRotateMatrix();\n    var targetMatrix = translateMatrix.multiply(rotateMatrix).multiply(magnetMatrix);\n    var localMatrix = targetMatrix.inverse();\n    var localLine = V.transformLine(line, localMatrix);\n    var localRef = localLine.start.clone();\n    var data = view.getNodeData(node);\n\n    if (opt.insideout === false) {\n        if (!data[BNDR_SHAPE_BBOX]) data[BNDR_SHAPE_BBOX] = localShape.bbox();\n        var localBBox = data[BNDR_SHAPE_BBOX];\n        if (localBBox.containsPoint(localRef)) return anchor;\n    }\n\n    // Caching segment subdivisions for paths\n    var pathOpt;\n    if (localShape instanceof g.Path) {\n        var precision = opt.precision || 2;\n        if (!data[BNDR_SUBDIVISIONS]) data[BNDR_SUBDIVISIONS] = localShape.getSegmentSubdivisions({ precision: precision });\n        pathOpt = {\n            precision: precision,\n            segmentSubdivisions: data[BNDR_SUBDIVISIONS]\n        };\n    }\n\n    if (opt.extrapolate === true) localLine.setLength(1e6);\n\n    intersection = localLine.intersect(localShape, pathOpt);\n    if (intersection) {\n        // More than one intersection\n        if (V.isArray(intersection)) intersection = localRef.chooseClosest(intersection);\n    } else if (opt.sticky === true) {\n        // No intersection, find the closest point instead\n        if (localShape instanceof g.Rect) {\n            intersection = localShape.pointNearestToPoint(localRef);\n        } else if (localShape instanceof g.Ellipse) {\n            intersection = localShape.intersectionWithLineFromCenterToPoint(localRef);\n        } else {\n            intersection = localShape.closestPoint(localRef, pathOpt);\n        }\n    }\n\n    var cp = (intersection) ? V.transformPoint(intersection, targetMatrix) : anchor;\n    var cpOffset = opt.offset || 0;\n    if (opt.stroke) cpOffset += stroke(node) / 2;\n\n    return offsetPoint(cp, line.start, cpOffset);\n}\n\nexport const anchor = anchorConnectionPoint;\nexport const bbox = bboxIntersection;\nexport const rectangle = rectangleIntersection;\nexport const boundary = boundaryIntersection;\n","import * as util from '../util/index.mjs';\nimport { toRad } from '../g/index.mjs';\nimport { resolveRef } from '../linkAnchors/index.mjs';\n\nfunction bboxWrapper(method) {\n\n    return function(view, magnet, ref, opt) {\n\n        var rotate = !!opt.rotate;\n        var bbox = (rotate) ? view.getNodeUnrotatedBBox(magnet) : view.getNodeBBox(magnet);\n        var anchor = bbox[method]();\n\n        var dx = opt.dx;\n        if (dx) {\n            var dxPercentage = util.isPercentage(dx);\n            dx = parseFloat(dx);\n            if (isFinite(dx)) {\n                if (dxPercentage) {\n                    dx /= 100;\n                    dx *= bbox.width;\n                }\n                anchor.x += dx;\n            }\n        }\n\n        var dy = opt.dy;\n        if (dy) {\n            var dyPercentage = util.isPercentage(dy);\n            dy = parseFloat(dy);\n            if (isFinite(dy)) {\n                if (dyPercentage) {\n                    dy /= 100;\n                    dy *= bbox.height;\n                }\n                anchor.y += dy;\n            }\n        }\n\n        return (rotate) ? anchor.rotate(view.model.getBBox().center(), -view.model.angle()) : anchor;\n    };\n}\n\nfunction _perpendicular(view, magnet, refPoint, opt) {\n\n    var angle = view.model.angle();\n    var bbox = view.getNodeBBox(magnet);\n    var anchor = bbox.center();\n    var topLeft = bbox.origin();\n    var bottomRight = bbox.corner();\n\n    var padding = opt.padding;\n    if (!isFinite(padding)) padding = 0;\n\n    if ((topLeft.y + padding) <= refPoint.y && refPoint.y <= (bottomRight.y - padding)) {\n        var dy = (refPoint.y - anchor.y);\n        anchor.x += (angle === 0 || angle === 180) ? 0 : dy * 1 / Math.tan(toRad(angle));\n        anchor.y += dy;\n    } else if ((topLeft.x + padding) <= refPoint.x && refPoint.x <= (bottomRight.x - padding)) {\n        var dx = (refPoint.x - anchor.x);\n        anchor.y += (angle === 90 || angle === 270) ? 0 : dx * Math.tan(toRad(angle));\n        anchor.x += dx;\n    }\n\n    return anchor;\n}\n\nfunction _midSide(view, magnet, refPoint, opt) {\n\n    var rotate = !!opt.rotate;\n    var bbox, angle, center;\n    if (rotate) {\n        bbox = view.getNodeUnrotatedBBox(magnet);\n        center = view.model.getBBox().center();\n        angle = view.model.angle();\n    } else {\n        bbox = view.getNodeBBox(magnet);\n    }\n\n    var padding = opt.padding;\n    if (isFinite(padding)) bbox.inflate(padding);\n\n    if (rotate) refPoint.rotate(center, angle);\n\n    var side = bbox.sideNearestToPoint(refPoint);\n    var anchor;\n    switch (side) {\n        case 'left':\n            anchor = bbox.leftMiddle();\n            break;\n        case 'right':\n            anchor = bbox.rightMiddle();\n            break;\n        case 'top':\n            anchor = bbox.topMiddle();\n            break;\n        case 'bottom':\n            anchor = bbox.bottomMiddle();\n            break;\n    }\n\n    return (rotate) ? anchor.rotate(center, -angle) : anchor;\n}\n\n// Can find anchor from model, when there is no selector or the link end\n// is connected to a port\nfunction _modelCenter(view, _magnet, _refPoint, opt, endType) {\n    return view.model.getPointFromConnectedLink(this.model, endType).offset(opt.dx, opt.dy);\n}\n\n//joint.anchors\nexport const center = bboxWrapper('center');\nexport const top = bboxWrapper('topMiddle');\nexport const bottom = bboxWrapper('bottomMiddle');\nexport const left = bboxWrapper('leftMiddle');\nexport const right = bboxWrapper('rightMiddle');\nexport const topLeft = bboxWrapper('origin');\nexport const topRight = bboxWrapper('topRight');\nexport const bottomLeft = bboxWrapper('bottomLeft');\nexport const bottomRight = bboxWrapper('corner');\nexport const perpendicular = resolveRef(_perpendicular);\nexport const midSide = resolveRef(_midSide);\nexport const modelCenter = _modelCenter;\n\n","import { PaperLayer } from '../PaperLayer.mjs';\nimport {\n    isFunction,\n    isString,\n    defaults,\n    omit,\n    assign,\n    merge,\n} from '../../util/index.mjs';\nimport V from '../../V/index.mjs';\n\nexport const GridLayer = PaperLayer.extend({\n\n    style: {\n        'pointer-events': 'none'\n    },\n\n    _gridCache: null,\n    _gridSettings: null,\n\n    init() {\n        PaperLayer.prototype.init.apply(this, arguments);\n        const { options: { paper }} = this;\n        this._gridCache = null;\n        this._gridSettings = [];\n        this.listenTo(paper, 'transform resize', this.updateGrid);\n    },\n\n    setGrid(drawGrid) {\n        this._gridSettings = this.getGridSettings(drawGrid);\n        this.renderGrid();\n    },\n\n    getGridSettings(drawGrid) {\n        const gridSettings = [];\n        if (drawGrid) {\n            const optionsList = Array.isArray(drawGrid) ? drawGrid : [drawGrid || {}];\n            optionsList.forEach((item) => {\n                gridSettings.push(...this._resolveDrawGridOption(item));\n            });\n        }\n        return gridSettings;\n    },\n\n    removeGrid() {\n        const { _gridCache: grid } = this;\n        if (!grid) return;\n        grid.root.remove();\n        this._gridCache = null;\n    },\n\n    renderGrid() {\n\n        const { options: { paper }} = this;\n        const { _gridSettings: gridSettings } = this;\n\n        this.removeGrid();\n\n        if (gridSettings.length === 0) return;\n\n        const gridSize = paper.options.drawGridSize || paper.options.gridSize;\n        if (gridSize <= 1) {\n            return;\n        }\n\n        const refs = this._getGridRefs();\n\n        gridSettings.forEach((gridLayerSetting, index) => {\n\n            const id = this._getPatternId(index);\n            const options = merge({}, gridLayerSetting);\n            const { scaleFactor = 1 } = options;\n            options.width = gridSize * scaleFactor || 1;\n            options.height = gridSize * scaleFactor || 1;\n\n            let vPattern;\n            if (!refs.exist(id)) {\n                vPattern = V('pattern', { id: id, patternUnits: 'userSpaceOnUse' }, V(options.markup));\n                refs.add(id, vPattern);\n            } else {\n                vPattern = refs.get(id);\n            }\n\n            if (isFunction(options.render)) {\n                options.render(vPattern.node.firstChild, options, paper);\n            }\n            vPattern.attr({\n                width: options.width,\n                height: options.height\n            });\n        });\n\n        refs.root.appendTo(this.el);\n        this.updateGrid();\n    },\n\n    updateGrid() {\n\n        const { _gridCache: grid, _gridSettings: gridSettings, options: { paper }} = this;\n        if (!grid) return;\n        const { root: vSvg, patterns } = grid;\n        const { x, y, width, height } = paper.getArea();\n        vSvg.attr({ x, y, width, height });\n        for (const patternId in patterns) {\n            const vPattern = patterns[patternId];\n            vPattern.attr({ x: -x, y: -y });\n        }\n        gridSettings.forEach((options, index) => {\n            if (isFunction(options.update)) {\n                const vPattern = patterns[this._getPatternId(index)];\n                options.update(vPattern.node.firstChild, options, paper);\n            }\n        });\n    },\n\n    _getPatternId(index) {\n        return `pattern_${this.options.paper.cid}_${index}`;\n    },\n\n    _getGridRefs() {\n        let { _gridCache: grid } = this;\n        if (grid) return grid;\n        const defsVEl = V('defs');\n        const svgVEl = V('svg', { width: '100%', height: '100%' }, [defsVEl]);\n        grid = this._gridCache = {\n            root: svgVEl,\n            patterns: {},\n            add: function(id, patternVEl) {\n                const rectVEl = V('rect', { width: '100%', height: '100%', fill: `url(#${id})` });\n                defsVEl.append(patternVEl);\n                svgVEl.append(rectVEl);\n                this.patterns[id] = patternVEl;\n            },\n            get: function(id) {\n                return this.patterns[id];\n            },\n            exist: function(id) {\n                return this.patterns[id] !== undefined;\n            }\n        };\n        return grid;\n    },\n\n    _resolveDrawGridOption(opt) {\n\n        var namespace = this.options.patterns;\n        if (isString(opt) && Array.isArray(namespace[opt])) {\n            return namespace[opt].map(function(item) {\n                return assign({}, item);\n            });\n        }\n\n        var options = opt || { args: [{}] };\n        var isArray = Array.isArray(options);\n        var name = options.name;\n\n        if (!isArray && !name && !options.markup) {\n            name = 'dot';\n        }\n\n        if (name && Array.isArray(namespace[name])) {\n            var pattern = namespace[name].map(function(item) {\n                return assign({}, item);\n            });\n\n            var args = Array.isArray(options.args) ? options.args : [options.args || {}];\n\n            defaults(args[0], omit(opt, 'args'));\n            for (var i = 0; i < args.length; i++) {\n                if (pattern[i]) {\n                    assign(pattern[i], args[i]);\n                }\n            }\n            return pattern;\n        }\n\n        return isArray ? options : [options];\n    },\n\n});\n","import V from '../V/index.mjs';\nimport {\n    isNumber,\n    assign,\n    nextFrame,\n    isObject,\n    cancelFrame,\n    defaults,\n    defaultsDeep,\n    addClassNamePrefix,\n    normalizeSides,\n    isFunction,\n    isPlainObject,\n    getByPath,\n    sortElements,\n    isString,\n    guid,\n    normalizeEvent,\n    normalizeWheel,\n    cap,\n    debounce,\n    omit,\n    result,\n    camelCase,\n    cloneDeep,\n    invoke,\n    hashCode,\n    filter as _filter,\n    parseDOMJSON,\n    toArray,\n    has\n} from '../util/index.mjs';\nimport { ViewBase } from '../mvc/ViewBase.mjs';\nimport { Rect, Point, toRad } from '../g/index.mjs';\nimport { View, views } from '../mvc/index.mjs';\nimport { CellView } from './CellView.mjs';\nimport { ElementView } from './ElementView.mjs';\nimport { LinkView } from './LinkView.mjs';\nimport { Cell } from './Cell.mjs';\nimport { Graph } from './Graph.mjs';\nimport { LayersNames, PaperLayer } from './PaperLayer.mjs';\nimport * as highlighters from '../highlighters/index.mjs';\nimport * as linkAnchors from '../linkAnchors/index.mjs';\nimport * as connectionPoints from '../connectionPoints/index.mjs';\nimport * as anchors from '../anchors/index.mjs';\n\nimport $ from '../mvc/Dom/index.mjs';\nimport { GridLayer } from './layers/GridLayer.mjs';\n\nconst sortingTypes = {\n    NONE: 'sorting-none',\n    APPROX: 'sorting-approximate',\n    EXACT: 'sorting-exact'\n};\n\nconst WHEEL_CAP = 50;\nconst WHEEL_WAIT_MS = 20;\nconst MOUNT_BATCH_SIZE = 1000;\nconst UPDATE_BATCH_SIZE = Infinity;\nconst MIN_PRIORITY = 9007199254740991; // Number.MAX_SAFE_INTEGER\n\nconst HighlightingTypes = CellView.Highlighting;\n\nconst defaultHighlighting = {\n    [HighlightingTypes.DEFAULT]: {\n        name: 'stroke',\n        options: {\n            padding: 3\n        }\n    },\n    [HighlightingTypes.MAGNET_AVAILABILITY]: {\n        name: 'addClass',\n        options: {\n            className: 'available-magnet'\n        }\n    },\n    [HighlightingTypes.ELEMENT_AVAILABILITY]: {\n        name: 'addClass',\n        options: {\n            className: 'available-cell'\n        }\n    }\n};\n\nconst defaultLayers = [{\n    name: LayersNames.GRID,\n}, {\n    name: LayersNames.BACK,\n}, {\n    name: LayersNames.CELLS,\n}, {\n    name: LayersNames.LABELS,\n}, {\n    name: LayersNames.FRONT\n}, {\n    name: LayersNames.TOOLS\n}];\n\nexport const Paper = View.extend({\n\n    className: 'paper',\n\n    options: {\n\n        width: 800,\n        height: 600,\n        gridSize: 1,\n        // Whether or not to draw the grid lines on the paper's DOM element.\n        // e.g drawGrid: true, drawGrid: { color: 'red', thickness: 2 }\n        drawGrid: false,\n        // If not set, the size of the visual grid is the same as the `gridSize`.\n        drawGridSize: null,\n\n        // Whether or not to draw the background on the paper's DOM element.\n        // e.g. background: { color: 'lightblue', image: '/paper-background.png', repeat: 'flip-xy' }\n        background: false,\n\n        elementView: ElementView,\n        linkView: LinkView,\n        snapLabels: false, // false, true\n        snapLinks: false, // false, true, { radius: value }\n        snapLinksSelf: false, // false, true, { radius: value }\n\n        // Should the link labels be rendered into its own layer?\n        // `false` - the labels are part of the links\n        // `true` - the labels are appended to LayersName.LABELS\n        // [LayersName] - the labels are appended to the layer specified\n        labelsLayer: false,\n\n        // When set to FALSE, an element may not have more than 1 link with the same source and target element.\n        multiLinks: true,\n\n        // For adding custom guard logic.\n        guard: function(evt, view) {\n\n            // FALSE means the event isn't guarded.\n            return false;\n        },\n\n        highlighting: defaultHighlighting,\n\n        // Prevent the default context menu from being displayed.\n        preventContextMenu: true,\n\n        // Prevent the default action for blank:pointer<action>.\n        preventDefaultBlankAction: true,\n\n        // Prevent the default action for cell:pointer<action>.\n        preventDefaultViewAction: true,\n\n        // Restrict the translation of elements by given bounding box.\n        // Option accepts a boolean:\n        //  true - the translation is restricted to the paper area\n        //  false - no restrictions\n        // A method:\n        // restrictTranslate: function(elementView) {\n        //     var parentId = elementView.model.get('parent');\n        //     return parentId && this.model.getCell(parentId).getBBox();\n        // },\n        // Or a bounding box:\n        // restrictTranslate: { x: 10, y: 10, width: 790, height: 590 }\n        restrictTranslate: false,\n\n        // Marks all available magnets with 'available-magnet' class name and all available cells with\n        // 'available-cell' class name. Marks them when dragging a link is started and unmark\n        // when the dragging is stopped.\n        markAvailable: false,\n\n        // Defines what link model is added to the graph after an user clicks on an active magnet.\n        // Value could be the mvc.model or a function returning the mvc.model\n        // defaultLink: (elementView, magnet) => {\n        //   return condition ? new customLink1() : new customLink2()\n        // }\n        defaultLink: function() {\n            // Do not create hard dependency on the joint.shapes.standard namespace (by importing the standard.Link model directly)\n            const { cellNamespace } = this.model.get('cells');\n            const ctor = getByPath(cellNamespace, ['standard', 'Link']);\n            if (!ctor) throw new Error('dia.Paper: no default link model found. Use `options.defaultLink` to specify a default link model.');\n            return new ctor();\n        },\n\n        // A connector that is used by links with no connector defined on the model.\n        // e.g. { name: 'rounded', args: { radius: 5 }} or a function\n        defaultConnector: { name: 'normal' },\n\n        // A router that is used by links with no router defined on the model.\n        // e.g. { name: 'oneSide', args: { padding: 10 }} or a function\n        defaultRouter: { name: 'normal' },\n\n        defaultAnchor: { name: 'center' },\n\n        defaultLinkAnchor: { name: 'connectionRatio' },\n\n        defaultConnectionPoint: { name: 'boundary' },\n\n        /* CONNECTING */\n\n        connectionStrategy: null,\n\n        // Check whether to add a new link to the graph when user clicks on an a magnet.\n        validateMagnet: function(_cellView, magnet, _evt) {\n            return magnet.getAttribute('magnet') !== 'passive';\n        },\n\n        // Check whether to allow or disallow the link connection while an arrowhead end (source/target)\n        // being changed.\n        validateConnection: function(cellViewS, _magnetS, cellViewT, _magnetT, end, _linkView) {\n            return (end === 'target' ? cellViewT : cellViewS) instanceof ElementView;\n        },\n\n        /* EMBEDDING */\n\n        // Enables embedding. Re-parent the dragged element with elements under it and makes sure that\n        // all links and elements are visible taken the level of embedding into account.\n        embeddingMode: false,\n\n        // Check whether to allow or disallow the element embedding while an element being translated.\n        validateEmbedding: function(childView, parentView) {\n            // by default all elements can be in relation child-parent\n            return true;\n        },\n\n        // Check whether to allow or disallow an embedded element to be unembedded / to become a root.\n        validateUnembedding: function(childView) {\n            // by default all elements can become roots\n            return true;\n        },\n\n        // Determines the way how a cell finds a suitable parent when it's dragged over the paper.\n        // The cell with the highest z-index (visually on the top) will be chosen.\n        findParentBy: 'bbox', // 'bbox'|'center'|'origin'|'corner'|'topRight'|'bottomLeft'\n\n        // If enabled only the element on the very front is taken into account for the embedding.\n        // If disabled the elements under the dragged view are tested one by one\n        // (from front to back) until a valid parent found.\n        frontParentOnly: true,\n\n        // Interactive flags. See online docs for the complete list of interactive flags.\n        interactive: {\n            labelMove: false\n        },\n\n        // When set to true the links can be pinned to the paper.\n        // i.e. link source/target can be a point e.g. link.get('source') ==> { x: 100, y: 100 };\n        linkPinning: true,\n\n        // Custom validation after an interaction with a link ends.\n        // Recognizes a function. If `false` is returned, the link is disallowed (removed or reverted)\n        // (linkView, paper) => boolean\n        allowLink: null,\n\n        // Allowed number of mousemove events after which the pointerclick event will be still triggered.\n        clickThreshold: 0,\n\n        // Number of required mousemove events before the first pointermove event will be triggered.\n        moveThreshold: 0,\n\n        // Number of required mousemove events before a link is created out of the magnet.\n        // Or string `onleave` so the link is created when the pointer leaves the magnet\n        magnetThreshold: 0,\n\n        // Rendering Options\n\n        sorting: sortingTypes.APPROX,\n\n        frozen: false,\n\n        autoFreeze: false,\n\n        // no docs yet\n        onViewUpdate: function(view, flag, priority, opt, paper) {\n            // Do not update connected links when:\n            // 1. the view was just inserted (added to the graph and rendered)\n            // 2. the view was just mounted (added back to the paper by viewport function)\n            // 3. the change was marked as `isolate`.\n            // 4. the view model was just removed from the graph\n            if ((flag & (view.FLAG_INSERT | view.FLAG_REMOVE)) || opt.mounting || opt.isolate) return;\n            paper.requestConnectedLinksUpdate(view, priority, opt);\n        },\n\n        // no docs yet\n        onViewPostponed: function(view, flag, paper) {\n            return paper.forcePostponedViewUpdate(view, flag);\n        },\n\n        beforeRender: null, // function(opt, paper) { },\n\n        afterRender: null, // function(stats, opt, paper) {\n\n        viewport: null,\n\n        // Default namespaces\n\n        cellViewNamespace: null,\n\n        routerNamespace: null,\n\n        connectorNamespace: null,\n\n        highlighterNamespace: highlighters,\n\n        anchorNamespace: anchors,\n\n        linkAnchorNamespace: linkAnchors,\n\n        connectionPointNamespace: connectionPoints,\n\n        overflow: false\n    },\n\n    events: {\n        'dblclick': 'pointerdblclick',\n        'dbltap': 'pointerdblclick',\n        'contextmenu': 'contextmenu',\n        'mousedown': 'pointerdown',\n        'touchstart': 'pointerdown',\n        'mouseover': 'mouseover',\n        'mouseout': 'mouseout',\n        'mouseenter': 'mouseenter',\n        'mouseleave': 'mouseleave',\n        'wheel': 'mousewheel',\n        'mouseenter .joint-cell': 'mouseenter',\n        'mouseleave .joint-cell': 'mouseleave',\n        'mouseenter .joint-tools': 'mouseenter',\n        'mouseleave .joint-tools': 'mouseleave',\n        'dblclick .joint-cell [magnet]': 'magnetpointerdblclick',\n        'contextmenu .joint-cell [magnet]': 'magnetcontextmenu',\n        'mousedown .joint-link .label': 'onlabel', // interaction with link label\n        'touchstart .joint-link .label': 'onlabel',\n        'dragstart .joint-cell image': 'onImageDragStart' // firefox fix\n    },\n\n    documentEvents: {\n        'mousemove': 'pointermove',\n        'touchmove': 'pointermove',\n        'mouseup': 'pointerup',\n        'touchend': 'pointerup',\n        'touchcancel': 'pointerup'\n    },\n\n    /* CSS within the SVG document\n    * 1. Adding vector-effect: non-scaling-stroke; to prevent the stroke width from scaling for\n    *    elements that use the `scalable` group.\n    */\n    stylesheet: /*css*/`\n        .joint-element .scalable * {\n            vector-effect: non-scaling-stroke;\n        }\n    `,\n\n    svg: null,\n    viewport: null,\n    defs: null,\n    tools: null,\n    layers: null,\n\n    // For storing the current transformation matrix (CTM) of the paper's viewport.\n    _viewportMatrix: null,\n    // For verifying whether the CTM is up-to-date. The viewport transform attribute\n    // could have been manipulated directly.\n    _viewportTransformString: null,\n    // Updates data (priorities, unmounted views etc.)\n    _updates: null,\n    // Paper Layers\n    _layers: null,\n\n    SORT_DELAYING_BATCHES: ['add', 'to-front', 'to-back'],\n    UPDATE_DELAYING_BATCHES: ['translate'],\n    // If you interact with these elements,\n    // the default interaction such as `element move` is prevented.\n    FORM_CONTROL_TAG_NAMES: ['TEXTAREA', 'INPUT', 'BUTTON', 'SELECT', 'OPTION'] ,\n    // If you interact with these elements, the events are not propagated to the paper\n    // i.e. paper events such as `element:pointerdown` are not triggered.\n    GUARDED_TAG_NAMES: [\n        // Guard <select> for consistency. When you click on it:\n        // Chrome: triggers `pointerdown`, `pointerup`, `pointerclick` to open\n        // Firefox: triggers `pointerdown` on open, `pointerup` (and `pointerclick` only if you haven't moved).\n        //          on close. However, if you open and then close by clicking elsewhere on the page,\n        //           no other event is triggered.\n        // Safari: when you open it, it triggers `pointerdown`. That's it.\n        'SELECT',\n    ],\n    MIN_SCALE: 1e-6,\n\n    // Default find buffer for the findViewsInArea and findViewsAtPoint methods.\n    // The find buffer is used to extend the area of the search\n    // to mitigate the differences between the model and view geometry.\n    DEFAULT_FIND_BUFFER: 200,\n\n    init: function() {\n\n        const { options } = this;\n        if (!options.cellViewNamespace) {\n            /* eslint-disable no-undef */\n            options.cellViewNamespace = typeof joint !== 'undefined' && has(joint, 'shapes') ? joint.shapes : null;\n            /* eslint-enable no-undef */\n        }\n\n        const model = this.model = options.model || new Graph;\n\n        // Layers (SVGGroups)\n        this._layers = {};\n\n        this.cloneOptions();\n        this.render();\n        this._setDimensions();\n        this.startListening();\n\n        // Hash of all cell views.\n        this._views = {};\n\n        // Mouse wheel events buffer\n        this._mw_evt_buffer = {\n            event: null,\n            deltas: [],\n        };\n\n        // Render existing cells in the graph\n        this.resetViews(model.attributes.cells.models);\n        // Start the Rendering Loop\n        if (!this.isFrozen() && this.isAsync()) this.updateViewsAsync();\n    },\n\n    _resetUpdates: function() {\n        if (this._updates && this._updates.id) cancelFrame(this._updates.id);\n\n        return this._updates = {\n            id: null,\n            priorities: [{}, {}, {}],\n            unmountedCids: [],\n            mountedCids: [],\n            unmounted: {},\n            mounted: {},\n            count: 0,\n            keyFrozen: false,\n            freezeKey: null,\n            sort: false,\n            disabled: false,\n            idle: false\n        };\n    },\n\n    startListening: function() {\n        var model = this.model;\n        this.listenTo(model, 'add', this.onCellAdded)\n            .listenTo(model, 'remove', this.onCellRemoved)\n            .listenTo(model, 'change', this.onCellChange)\n            .listenTo(model, 'reset', this.onGraphReset)\n            .listenTo(model, 'sort', this.onGraphSort)\n            .listenTo(model, 'batch:stop', this.onGraphBatchStop);\n        this.on('cell:highlight', this.onCellHighlight)\n            .on('cell:unhighlight', this.onCellUnhighlight)\n            .on('transform', this.update);\n    },\n\n    onCellAdded: function(cell, _, opt) {\n        var position = opt.position;\n        if (this.isAsync() || !isNumber(position)) {\n            this.renderView(cell, opt);\n        } else {\n            if (opt.maxPosition === position) this.freeze({ key: 'addCells' });\n            this.renderView(cell, opt);\n            if (position === 0) this.unfreeze({ key: 'addCells' });\n        }\n    },\n\n    onCellRemoved: function(cell, _, opt) {\n        const view = this.findViewByModel(cell);\n        if (view) this.requestViewUpdate(view, view.FLAG_REMOVE, view.UPDATE_PRIORITY, opt);\n    },\n\n    onCellChange: function(cell, opt) {\n        if (cell === this.model.attributes.cells) return;\n        if (cell.hasChanged('z') && this.options.sorting === sortingTypes.APPROX) {\n            const view = this.findViewByModel(cell);\n            if (view) this.requestViewUpdate(view, view.FLAG_INSERT, view.UPDATE_PRIORITY, opt);\n        }\n    },\n\n    onGraphReset: function(collection, opt) {\n        this.resetLayers();\n        this.resetViews(collection.models, opt);\n    },\n\n    onGraphSort: function() {\n        if (this.model.hasActiveBatch(this.SORT_DELAYING_BATCHES)) return;\n        this.sortViews();\n    },\n\n    onGraphBatchStop: function(data) {\n        if (this.isFrozen()) return;\n        var name = data && data.batchName;\n        var graph = this.model;\n        if (!this.isAsync()) {\n            var updateDelayingBatches = this.UPDATE_DELAYING_BATCHES;\n            if (updateDelayingBatches.includes(name) && !graph.hasActiveBatch(updateDelayingBatches)) {\n                this.updateViews(data);\n            }\n        }\n        var sortDelayingBatches = this.SORT_DELAYING_BATCHES;\n        if (sortDelayingBatches.includes(name) && !graph.hasActiveBatch(sortDelayingBatches)) {\n            this.sortViews();\n        }\n    },\n\n    cloneOptions: function() {\n\n        const { options } = this;\n        const {\n            defaultConnector,\n            defaultRouter,\n            defaultConnectionPoint,\n            defaultAnchor,\n            defaultLinkAnchor,\n            highlighting,\n            cellViewNamespace,\n            interactive\n        } = options;\n\n        // Default cellView namespace for ES5\n        /* eslint-disable no-undef */\n        if (!cellViewNamespace && typeof joint !== 'undefined' && has(joint, 'shapes')) {\n            options.cellViewNamespace = joint.shapes;\n        }\n        /* eslint-enable no-undef */\n\n        // Here if a function was provided, we can not clone it, as this would result in loosing the function.\n        // If the default is used, the cloning is necessary in order to prevent modifying the options on prototype.\n        if (!isFunction(defaultConnector)) {\n            options.defaultConnector = cloneDeep(defaultConnector);\n        }\n        if (!isFunction(defaultRouter)) {\n            options.defaultRouter = cloneDeep(defaultRouter);\n        }\n        if (!isFunction(defaultConnectionPoint)) {\n            options.defaultConnectionPoint = cloneDeep(defaultConnectionPoint);\n        }\n        if (!isFunction(defaultAnchor)) {\n            options.defaultAnchor = cloneDeep(defaultAnchor);\n        }\n        if (!isFunction(defaultLinkAnchor)) {\n            options.defaultLinkAnchor = cloneDeep(defaultLinkAnchor);\n        }\n        if (isPlainObject(interactive)) {\n            options.interactive = assign({}, interactive);\n        }\n        if (isPlainObject(highlighting)) {\n            // Return the default highlighting options into the user specified options.\n            options.highlighting = defaultsDeep({}, highlighting, defaultHighlighting);\n        }\n    },\n\n    children: function() {\n        var ns = V.namespace;\n        return [{\n            namespaceURI: ns.xhtml,\n            tagName: 'div',\n            className: addClassNamePrefix('paper-background'),\n            selector: 'background',\n            style: {\n                position: 'absolute',\n                inset: 0\n            }\n        }, {\n            namespaceURI: ns.svg,\n            tagName: 'svg',\n            attributes: {\n                'width': '100%',\n                'height': '100%',\n                'xmlns:xlink': ns.xlink\n            },\n            selector: 'svg',\n            style: {\n                position: 'absolute',\n                inset: 0\n            },\n            children: [{\n                // Append `<defs>` element to the SVG document. This is useful for filters and gradients.\n                // It's desired to have the defs defined before the viewport (e.g. to make a PDF document pick up defs properly).\n                tagName: 'defs',\n                selector: 'defs'\n            }, {\n                tagName: 'g',\n                className: addClassNamePrefix('layers'),\n                selector: 'layers'\n            }]\n        }];\n    },\n\n    hasLayerView(layerName) {\n        return  (layerName in this._layers);\n    },\n\n    getLayerView(layerName) {\n        const { _layers } = this;\n        if (layerName in _layers) return _layers[layerName];\n        throw new Error(`dia.Paper: Unknown layer \"${layerName}\"`);\n    },\n\n    getLayerNode(layerName) {\n        return this.getLayerView(layerName).el;\n    },\n\n    render: function() {\n\n        this.renderChildren();\n        const { el, childNodes, options, stylesheet } = this;\n        const { svg, defs, layers } = childNodes;\n\n        el.style.position = 'relative';\n        svg.style.overflow = options.overflow ? 'visible' : 'hidden';\n\n        this.svg = svg;\n        this.defs = defs;\n        this.layers = layers;\n\n        this.renderLayers();\n\n        V.ensureId(svg);\n\n        this.addStylesheet(stylesheet);\n\n        if (options.background) {\n            this.drawBackground(options.background);\n        }\n\n        if (options.drawGrid) {\n            this.setGrid(options.drawGrid);\n        }\n\n        return this;\n    },\n\n    addStylesheet: function(css) {\n        if (!css) return;\n        V(this.svg).prepend(V.createSVGStyle(css));\n    },\n\n    createLayer(name) {\n        switch (name) {\n            case LayersNames.GRID:\n                return new GridLayer({ name, paper: this, patterns: this.constructor.gridPatterns });\n            default:\n                return new PaperLayer({ name });\n        }\n    },\n\n    renderLayers: function(layers = defaultLayers) {\n        this.removeLayers();\n        // TODO: Layers to be read from the graph `layers` attribute\n        layers.forEach(({ name, sorted }) => {\n            const layerView = this.createLayer(name);\n            this.layers.appendChild(layerView.el);\n            this._layers[name] = layerView;\n        });\n        // Throws an exception if doesn't exist\n        const cellsLayerView = this.getLayerView(LayersNames.CELLS);\n        const toolsLayerView = this.getLayerView(LayersNames.TOOLS);\n        const labelsLayerView = this.getLayerView(LayersNames.LABELS);\n        // backwards compatibility\n        this.tools = toolsLayerView.el;\n        this.cells = this.viewport = cellsLayerView.el;\n        // user-select: none;\n        cellsLayerView.vel.addClass(addClassNamePrefix('viewport'));\n        labelsLayerView.vel.addClass(addClassNamePrefix('viewport'));\n        cellsLayerView.el.style.webkitUserSelect = 'none';\n        cellsLayerView.el.style.userSelect = 'none';\n        labelsLayerView.el.style.webkitUserSelect = 'none';\n        labelsLayerView.el.style.userSelect = 'none';\n    },\n\n    removeLayers: function() {\n        const { _layers } = this;\n        Object.keys(_layers).forEach(name => {\n            _layers[name].remove();\n            delete _layers[name];\n        });\n    },\n\n    resetLayers: function() {\n        const { _layers } = this;\n        Object.keys(_layers).forEach(name => {\n            _layers[name].removePivots();\n        });\n    },\n\n    update: function() {\n\n        if (this._background) {\n            this.updateBackgroundImage(this._background);\n        }\n\n        return this;\n    },\n\n    scale: function(sx, sy, data) {\n        const ctm = this.matrix();\n        // getter\n        if (sx === undefined) {\n            return V.matrixToScale(ctm);\n        }\n        // setter\n        if (sy === undefined) {\n            sy = sx;\n        }\n        sx = Math.max(sx || 0, this.MIN_SCALE);\n        sy = Math.max(sy || 0, this.MIN_SCALE);\n        ctm.a = sx;\n        ctm.d = sy;\n        this.matrix(ctm, data);\n        return this;\n    },\n\n    scaleUniformAtPoint: function(scale, point, data) {\n        const { a: sx, d: sy, e: tx, f: ty } = this.matrix();\n        scale = Math.max(scale || 0, this.MIN_SCALE);\n        if (scale === sx && scale === sy) {\n            // The scale is the same as the current one.\n            return this;\n        }\n        const matrix = V.createSVGMatrix()\n            .translate(\n                tx - point.x * (scale - sx),\n                ty - point.y * (scale - sy)\n            )\n            .scale(scale, scale);\n        this.matrix(matrix, data);\n        return this;\n    },\n\n    translate: function(tx, ty, data) {\n        const ctm = this.matrix();\n        // getter\n        if (tx === undefined) {\n            return V.matrixToTranslate(ctm);\n        }\n        // setter\n        tx || (tx = 0);\n        ty || (ty = 0);\n        if (ctm.e === tx && ctm.f === ty) return this;\n        ctm.e = tx;\n        ctm.f = ty;\n        this.matrix(ctm, data);\n        return this;\n    },\n\n    matrix: function(ctm, data = {}) {\n\n        var viewport = this.layers;\n\n        // Getter:\n        if (ctm === undefined) {\n\n            var transformString = viewport.getAttribute('transform');\n\n            if ((this._viewportTransformString || null) === transformString) {\n                // It's ok to return the cached matrix. The transform attribute has not changed since\n                // the matrix was stored.\n                ctm = this._viewportMatrix;\n            } else {\n                // The viewport transform attribute has changed. Measure the matrix and cache again.\n                ctm = viewport.getCTM();\n                this._viewportMatrix = ctm;\n                this._viewportTransformString = transformString;\n            }\n\n            // Clone the cached current transformation matrix.\n            // If no matrix previously stored the identity matrix is returned.\n            return V.createSVGMatrix(ctm);\n        }\n\n        // Setter:\n        const prev = this.matrix();\n        const current = V.createSVGMatrix(ctm);\n        const currentTransformString = this._viewportTransformString;\n        const ctmString = V.matrixToTransformString(current);\n        if (ctmString === currentTransformString) {\n            // The new transform string is the same as the current one.\n            // No need to update the transform attribute.\n            return this;\n        }\n        if (!currentTransformString && V.matrixToTransformString() === ctmString) {\n            // The current transform string is empty and the new one is an identity matrix.\n            // No need to update the transform attribute.\n            return this;\n        }\n\n        const { a, d, e, f } = current;\n\n        viewport.setAttribute('transform', ctmString);\n        this._viewportMatrix = current;\n        this._viewportTransformString = viewport.getAttribute('transform');\n\n        // scale event\n        if (a !== prev.a || d !== prev.d) {\n            this.trigger('scale', a, d, data);\n        }\n\n        // translate event\n        if (e !== prev.e || f !== prev.f) {\n            this.trigger('translate', e, f, data);\n        }\n\n        this.trigger('transform', current, data);\n        return this;\n    },\n\n    clientMatrix: function() {\n\n        return V.createSVGMatrix(this.cells.getScreenCTM());\n    },\n\n    requestConnectedLinksUpdate: function(view, priority, opt) {\n        if (view instanceof CellView) {\n            var model = view.model;\n            var links = this.model.getConnectedLinks(model);\n            for (var j = 0, n = links.length; j < n; j++) {\n                var link = links[j];\n                var linkView = this.findViewByModel(link);\n                if (!linkView) continue;\n                var flagLabels = ['UPDATE'];\n                if (link.getTargetCell() === model) flagLabels.push('TARGET');\n                if (link.getSourceCell() === model) flagLabels.push('SOURCE');\n                var nextPriority = Math.max(priority + 1, linkView.UPDATE_PRIORITY);\n                this.scheduleViewUpdate(linkView, linkView.getFlag(flagLabels), nextPriority, opt);\n            }\n        }\n    },\n\n    forcePostponedViewUpdate: function(view, flag) {\n        if (!view || !(view instanceof CellView)) return false;\n        var model = view.model;\n        if (model.isElement()) return false;\n        if ((flag & view.getFlag(['SOURCE', 'TARGET'])) === 0) {\n            var dumpOptions = { silent: true };\n            // LinkView is waiting for the target or the source cellView to be rendered\n            // This can happen when the cells are not in the viewport.\n            var sourceFlag = 0;\n            var sourceView = this.findViewByModel(model.getSourceCell());\n            if (sourceView && !this.isViewMounted(sourceView)) {\n                sourceFlag = this.dumpView(sourceView, dumpOptions);\n                view.updateEndMagnet('source');\n            }\n            var targetFlag = 0;\n            var targetView = this.findViewByModel(model.getTargetCell());\n            if (targetView && !this.isViewMounted(targetView)) {\n                targetFlag = this.dumpView(targetView, dumpOptions);\n                view.updateEndMagnet('target');\n            }\n            if (sourceFlag === 0 && targetFlag === 0) {\n                // If leftover flag is 0, all view updates were done.\n                return !this.dumpView(view, dumpOptions);\n            }\n        }\n        return false;\n    },\n\n    requestViewUpdate: function(view, flag, priority, opt) {\n        opt || (opt = {});\n        this.scheduleViewUpdate(view, flag, priority, opt);\n        var isAsync = this.isAsync();\n        if (this.isFrozen() || (isAsync && opt.async !== false)) return;\n        if (this.model.hasActiveBatch(this.UPDATE_DELAYING_BATCHES)) return;\n        var stats = this.updateViews(opt);\n        if (isAsync) this.notifyAfterRender(stats, opt);\n    },\n\n    scheduleViewUpdate: function(view, type, priority, opt) {\n        const { _updates: updates, options } = this;\n        if (updates.idle) {\n            if (options.autoFreeze) {\n                updates.idle = false;\n                this.unfreeze();\n            }\n        }\n        const { FLAG_REMOVE, FLAG_INSERT, UPDATE_PRIORITY, cid } = view;\n        let priorityUpdates = updates.priorities[priority];\n        if (!priorityUpdates) priorityUpdates = updates.priorities[priority] = {};\n        // Move higher priority updates to this priority\n        if (priority > UPDATE_PRIORITY) {\n            // Not the default priority for this view. It's most likely a link view\n            // connected to another link view, which triggered the update.\n            // TODO: If there is an update scheduled with a lower priority already, we should\n            // change the requested priority to the lowest one. Does not seem to be critical\n            // right now, as it \"only\" results in multiple updates on the same view.\n            for (let i = priority - 1; i >= UPDATE_PRIORITY; i--) {\n                const prevPriorityUpdates = updates.priorities[i];\n                if (!prevPriorityUpdates || !(cid in prevPriorityUpdates)) continue;\n                priorityUpdates[cid] |= prevPriorityUpdates[cid];\n                delete prevPriorityUpdates[cid];\n            }\n        }\n        let currentType = priorityUpdates[cid] || 0;\n        // Prevent cycling\n        if ((currentType & type) === type) return;\n        if (!currentType) updates.count++;\n        if (type & FLAG_REMOVE && currentType & FLAG_INSERT) {\n            // When a view is removed we need to remove the insert flag as this is a reinsert\n            priorityUpdates[cid] ^= FLAG_INSERT;\n        } else if (type & FLAG_INSERT && currentType & FLAG_REMOVE) {\n            // When a view is added we need to remove the remove flag as this is view was previously removed\n            priorityUpdates[cid] ^= FLAG_REMOVE;\n        }\n        priorityUpdates[cid] |= type;\n        const viewUpdateFn = options.onViewUpdate;\n        if (typeof viewUpdateFn === 'function') viewUpdateFn.call(this, view, type, priority, opt || {}, this);\n    },\n\n    dumpViewUpdate: function(view) {\n        if (!view) return 0;\n        var updates = this._updates;\n        var cid = view.cid;\n        var priorityUpdates = updates.priorities[view.UPDATE_PRIORITY];\n        var flag = this.registerMountedView(view) | priorityUpdates[cid];\n        delete priorityUpdates[cid];\n        return flag;\n    },\n\n    dumpView: function(view, opt = {}) {\n        const flag = this.dumpViewUpdate(view);\n        if (!flag) return 0;\n        const shouldNotify = !opt.silent;\n        if (shouldNotify) this.notifyBeforeRender(opt);\n        const leftover = this.updateView(view, flag, opt);\n        if (shouldNotify) {\n            const stats = { updated: 1, priority: view.UPDATE_PRIORITY };\n            this.notifyAfterRender(stats, opt);\n        }\n        return leftover;\n    },\n\n    updateView: function(view, flag, opt) {\n        if (!view) return 0;\n        const { FLAG_REMOVE, FLAG_INSERT, FLAG_INIT, model } = view;\n        if (view instanceof CellView) {\n            if (flag & FLAG_REMOVE) {\n                this.removeView(model);\n                return 0;\n            }\n            if (flag & FLAG_INSERT) {\n                const isInitialInsert = !!(flag & FLAG_INIT);\n                if (isInitialInsert) {\n                    flag ^= FLAG_INIT;\n                }\n                this.insertView(view, isInitialInsert);\n                flag ^= FLAG_INSERT;\n            }\n        }\n        if (!flag) return 0;\n        return view.confirmUpdate(flag, opt || {});\n    },\n\n    requireView: function(model, opt) {\n        var view = this.findViewByModel(model);\n        if (!view) return null;\n        this.dumpView(view, opt);\n        return view;\n    },\n\n    registerUnmountedView: function(view) {\n        var cid = view.cid;\n        var updates = this._updates;\n        if (cid in updates.unmounted) return 0;\n        var flag = updates.unmounted[cid] |= view.FLAG_INSERT;\n        updates.unmountedCids.push(cid);\n        delete updates.mounted[cid];\n        return flag;\n    },\n\n    registerMountedView: function(view) {\n        var cid = view.cid;\n        var updates = this._updates;\n        if (cid in updates.mounted) return 0;\n        updates.mounted[cid] = true;\n        updates.mountedCids.push(cid);\n        var flag = updates.unmounted[cid] || 0;\n        delete updates.unmounted[cid];\n        return flag;\n    },\n\n    isViewMounted: function(view) {\n        if (!view) return false;\n        var cid = view.cid;\n        var updates = this._updates;\n        return (cid in updates.mounted);\n    },\n\n    dumpViews: function(opt) {\n        var passingOpt = defaults({}, opt, { viewport: null });\n        this.checkViewport(passingOpt);\n        this.updateViews(passingOpt);\n    },\n\n    // Synchronous views update\n    updateViews: function(opt) {\n        this.notifyBeforeRender(opt);\n        let batchStats;\n        let updateCount = 0;\n        let batchCount = 0;\n        let priority = MIN_PRIORITY;\n        do {\n            batchCount++;\n            batchStats = this.updateViewsBatch(opt);\n            updateCount += batchStats.updated;\n            priority = Math.min(batchStats.priority, priority);\n        } while (!batchStats.empty);\n        const stats = { updated: updateCount, batches: batchCount, priority };\n        this.notifyAfterRender(stats, opt);\n        return stats;\n    },\n\n    hasScheduledUpdates: function() {\n        const priorities = this._updates.priorities;\n        const priorityIndexes = Object.keys(priorities); // convert priorities to a dense array\n        let i = priorityIndexes.length;\n        while (i > 0 && i--) {\n            // a faster way how to check if an object is empty\n            for (let _key in priorities[priorityIndexes[i]]) return true;\n        }\n        return false;\n    },\n\n    updateViewsAsync: function(opt, data) {\n        opt || (opt = {});\n        data || (data = { processed: 0, priority: MIN_PRIORITY });\n        const { _updates: updates, options } = this;\n        const id = updates.id;\n        if (id) {\n            cancelFrame(id);\n            if (data.processed === 0 && this.hasScheduledUpdates()) {\n                this.notifyBeforeRender(opt);\n            }\n            const stats = this.updateViewsBatch(opt);\n            const passingOpt = defaults({}, opt, {\n                mountBatchSize: MOUNT_BATCH_SIZE - stats.mounted,\n                unmountBatchSize: MOUNT_BATCH_SIZE - stats.unmounted\n            });\n            const checkStats = this.checkViewport(passingOpt);\n            const unmountCount = checkStats.unmounted;\n            const mountCount = checkStats.mounted;\n            let processed = data.processed;\n            const total = updates.count;\n            if (stats.updated > 0) {\n                // Some updates have been just processed\n                processed += stats.updated + stats.unmounted;\n                stats.processed = processed;\n                data.priority = Math.min(stats.priority, data.priority);\n                if (stats.empty && mountCount === 0) {\n                    stats.unmounted += unmountCount;\n                    stats.mounted += mountCount;\n                    stats.priority = data.priority;\n                    this.notifyAfterRender(stats, opt);\n                    data.processed = 0;\n                    data.priority = MIN_PRIORITY;\n                    updates.count = 0;\n                } else {\n                    data.processed = processed;\n                }\n            } else {\n                if (!updates.idle) {\n                    if (options.autoFreeze) {\n                        this.freeze();\n                        updates.idle = true;\n                        this.trigger('render:idle', opt);\n                    }\n                }\n            }\n            // Progress callback\n            const progressFn = opt.progress;\n            if (total && typeof progressFn === 'function') {\n                progressFn.call(this, stats.empty, processed, total, stats, this);\n            }\n            // The current frame could have been canceled in a callback\n            if (updates.id !== id) return;\n        }\n        if (updates.disabled) {\n            throw new Error('dia.Paper: can not unfreeze the paper after it was removed');\n        }\n        updates.id = nextFrame(this.updateViewsAsync, this, opt, data);\n    },\n\n    notifyBeforeRender: function(opt = {}) {\n        let beforeFn = opt.beforeRender;\n        if (typeof beforeFn !== 'function') {\n            beforeFn = this.options.beforeRender;\n            if (typeof beforeFn !== 'function') return;\n        }\n        beforeFn.call(this, opt, this);\n    },\n\n    notifyAfterRender: function(stats, opt = {}) {\n        let afterFn = opt.afterRender;\n        if (typeof afterFn !== 'function') {\n            afterFn = this.options.afterRender;\n        }\n        if (typeof afterFn === 'function') {\n            afterFn.call(this, stats, opt, this);\n        }\n        this.trigger('render:done', stats, opt);\n    },\n\n    updateViewsBatch: function(opt) {\n        opt || (opt = {});\n        var batchSize = opt.batchSize || UPDATE_BATCH_SIZE;\n        var updates = this._updates;\n        var updateCount = 0;\n        var postponeCount = 0;\n        var unmountCount = 0;\n        var mountCount = 0;\n        var maxPriority = MIN_PRIORITY;\n        var empty = true;\n        var options = this.options;\n        var priorities = updates.priorities;\n        var viewportFn = 'viewport' in opt ? opt.viewport : options.viewport;\n        if (typeof viewportFn !== 'function') viewportFn = null;\n        var postponeViewFn = options.onViewPostponed;\n        if (typeof postponeViewFn !== 'function') postponeViewFn = null;\n        var priorityIndexes = Object.keys(priorities); // convert priorities to a dense array\n        main: for (var i = 0, n = priorityIndexes.length; i < n; i++) {\n            var priority = +priorityIndexes[i];\n            var priorityUpdates = priorities[priority];\n            for (var cid in priorityUpdates) {\n                if (updateCount >= batchSize) {\n                    empty = false;\n                    break main;\n                }\n                var view = views[cid];\n                if (!view) {\n                    // This should not occur\n                    delete priorityUpdates[cid];\n                    continue;\n                }\n                var currentFlag = priorityUpdates[cid];\n                if ((currentFlag & view.FLAG_REMOVE) === 0) {\n                    // We should never check a view for viewport if we are about to remove the view\n                    var isDetached = cid in updates.unmounted;\n                    if (view.DETACHABLE && viewportFn && !viewportFn.call(this, view, !isDetached, this)) {\n                        // Unmount View\n                        if (!isDetached) {\n                            this.registerUnmountedView(view);\n                            this.detachView(view);\n                        }\n                        updates.unmounted[cid] |= currentFlag;\n                        delete priorityUpdates[cid];\n                        unmountCount++;\n                        continue;\n                    }\n                    // Mount View\n                    if (isDetached) {\n                        currentFlag |= view.FLAG_INSERT;\n                        mountCount++;\n                    }\n                    currentFlag |= this.registerMountedView(view);\n                }\n                var leftoverFlag = this.updateView(view, currentFlag, opt);\n                if (leftoverFlag > 0) {\n                    // View update has not finished completely\n                    priorityUpdates[cid] = leftoverFlag;\n                    if (!postponeViewFn || !postponeViewFn.call(this, view, leftoverFlag, this) || priorityUpdates[cid]) {\n                        postponeCount++;\n                        empty = false;\n                        continue;\n                    }\n                }\n                if (maxPriority > priority) maxPriority = priority;\n                updateCount++;\n                delete priorityUpdates[cid];\n            }\n        }\n        return {\n            priority: maxPriority,\n            updated: updateCount,\n            postponed: postponeCount,\n            unmounted: unmountCount,\n            mounted: mountCount,\n            empty: empty\n        };\n    },\n\n    getUnmountedViews: function() {\n        const updates = this._updates;\n        const unmountedCids = Object.keys(updates.unmounted);\n        const n = unmountedCids.length;\n        const unmountedViews = new Array(n);\n        for (var i = 0; i < n; i++) {\n            unmountedViews[i] = views[unmountedCids[i]];\n        }\n        return unmountedViews;\n    },\n\n    getMountedViews: function() {\n        const updates = this._updates;\n        const mountedCids = Object.keys(updates.mounted);\n        const n = mountedCids.length;\n        const mountedViews = new Array(n);\n        for (var i = 0; i < n; i++) {\n            mountedViews[i] = views[mountedCids[i]];\n        }\n        return mountedViews;\n    },\n\n    checkUnmountedViews: function(viewportFn, opt) {\n        opt || (opt  = {});\n        var mountCount = 0;\n        if (typeof viewportFn !== 'function') viewportFn = null;\n        var batchSize = 'mountBatchSize' in opt ? opt.mountBatchSize : Infinity;\n        var updates = this._updates;\n        var unmountedCids = updates.unmountedCids;\n        var unmounted = updates.unmounted;\n        for (var i = 0, n = Math.min(unmountedCids.length, batchSize); i < n; i++) {\n            var cid = unmountedCids[i];\n            if (!(cid in unmounted)) continue;\n            var view = views[cid];\n            if (!view) continue;\n            if (view.DETACHABLE && viewportFn && !viewportFn.call(this, view, false, this)) {\n                // Push at the end of all unmounted ids, so this can be check later again\n                unmountedCids.push(cid);\n                continue;\n            }\n            mountCount++;\n            var flag = this.registerMountedView(view);\n            if (flag) this.scheduleViewUpdate(view, flag, view.UPDATE_PRIORITY, { mounting: true });\n        }\n        // Get rid of views, that have been mounted\n        unmountedCids.splice(0, i);\n        return mountCount;\n    },\n\n    checkMountedViews: function(viewportFn, opt) {\n        opt || (opt = {});\n        var unmountCount = 0;\n        if (typeof viewportFn !== 'function') return unmountCount;\n        var batchSize = 'unmountBatchSize' in opt ? opt.unmountBatchSize : Infinity;\n        var updates = this._updates;\n        var mountedCids = updates.mountedCids;\n        var mounted = updates.mounted;\n        for (var i = 0, n = Math.min(mountedCids.length, batchSize); i < n; i++) {\n            var cid = mountedCids[i];\n            if (!(cid in mounted)) continue;\n            var view = views[cid];\n            if (!view) continue;\n            if (!view.DETACHABLE || viewportFn.call(this, view, true, this)) {\n                // Push at the end of all mounted ids, so this can be check later again\n                mountedCids.push(cid);\n                continue;\n            }\n            unmountCount++;\n            var flag = this.registerUnmountedView(view);\n            if (flag) this.detachView(view);\n        }\n        // Get rid of views, that have been unmounted\n        mountedCids.splice(0, i);\n        return unmountCount;\n    },\n\n    checkViewVisibility: function(cellView, opt = {}) {\n        let viewportFn = 'viewport' in opt ? opt.viewport : this.options.viewport;\n        if (typeof viewportFn !== 'function') viewportFn = null;\n        const updates = this._updates;\n        const { mounted, unmounted } = updates;\n        const visible = !cellView.DETACHABLE || !viewportFn || viewportFn.call(this, cellView, false, this);\n\n        let isUnmounted = false;\n        let isMounted = false;\n\n        if (cellView.cid in mounted && !visible) {\n            const flag = this.registerUnmountedView(cellView);\n            if (flag) this.detachView(cellView);\n            const i = updates.mountedCids.indexOf(cellView.cid);\n            updates.mountedCids.splice(i, 1);\n            isUnmounted = true;\n        }\n\n        if (!isUnmounted && cellView.cid in unmounted && visible) {\n            const i = updates.unmountedCids.indexOf(cellView.cid);\n            updates.unmountedCids.splice(i, 1);\n            var flag = this.registerMountedView(cellView);\n            if (flag) this.scheduleViewUpdate(cellView, flag, cellView.UPDATE_PRIORITY, { mounting: true });\n            isMounted = true;\n        }\n\n        return {\n            mounted: isMounted ? 1 : 0,\n            unmounted: isUnmounted ? 1 : 0\n        };\n    },\n\n    checkViewport: function(opt) {\n        var passingOpt = defaults({}, opt, {\n            mountBatchSize: Infinity,\n            unmountBatchSize: Infinity\n        });\n        var viewportFn = 'viewport' in passingOpt ? passingOpt.viewport : this.options.viewport;\n        var unmountedCount = this.checkMountedViews(viewportFn, passingOpt);\n        if (unmountedCount > 0) {\n            // Do not check views, that have been just unmounted and pushed at the end of the cids array\n            var unmountedCids = this._updates.unmountedCids;\n            passingOpt.mountBatchSize = Math.min(unmountedCids.length - unmountedCount, passingOpt.mountBatchSize);\n        }\n        var mountedCount = this.checkUnmountedViews(viewportFn, passingOpt);\n        return {\n            mounted: mountedCount,\n            unmounted: unmountedCount\n        };\n    },\n\n    freeze: function(opt) {\n        opt || (opt = {});\n        var updates = this._updates;\n        var key = opt.key;\n        var isFrozen = this.options.frozen;\n        var freezeKey = updates.freezeKey;\n        if (key && key !== freezeKey)  {\n            // key passed, but the paper is already freezed with another key\n            if (isFrozen && freezeKey) return;\n            updates.freezeKey = key;\n            updates.keyFrozen = isFrozen;\n        }\n        this.options.frozen = true;\n        var id = updates.id;\n        updates.id = null;\n        if (this.isAsync() && id) cancelFrame(id);\n    },\n\n    unfreeze: function(opt) {\n        opt || (opt = {});\n        var updates = this._updates;\n        var key = opt.key;\n        var freezeKey = updates.freezeKey;\n        // key passed, but the paper is already freezed with another key\n        if (key && freezeKey && key !== freezeKey) return;\n        updates.freezeKey = null;\n        // key passed, but the paper is already freezed\n        if (key && key === freezeKey && updates.keyFrozen) return;\n        if (this.isAsync()) {\n            this.freeze();\n            this.updateViewsAsync(opt);\n        } else {\n            this.updateViews(opt);\n        }\n        this.options.frozen = updates.keyFrozen = false;\n        if (updates.sort) {\n            this.sortViews();\n            updates.sort = false;\n        }\n    },\n\n    isAsync: function() {\n        return !!this.options.async;\n    },\n\n    isFrozen: function() {\n        return !!this.options.frozen;\n    },\n\n    isExactSorting: function() {\n        return this.options.sorting === sortingTypes.EXACT;\n    },\n\n    onRemove: function() {\n\n        this.freeze();\n        this._updates.disabled = true;\n        //clean up all DOM elements/views to prevent memory leaks\n        this.removeLayers();\n        this.removeViews();\n    },\n\n    getComputedSize: function() {\n\n        var options = this.options;\n        var w = options.width;\n        var h = options.height;\n        if (!isNumber(w)) w = this.el.clientWidth;\n        if (!isNumber(h)) h = this.el.clientHeight;\n        return { width: w, height: h };\n    },\n\n    setDimensions: function(width, height, data = {}) {\n        const { options } = this;\n        const { width: currentWidth, height: currentHeight } = options;\n        let w = (width === undefined) ? currentWidth : width;\n        let h = (height === undefined) ? currentHeight : height;\n        if (currentWidth === w && currentHeight === h) return;\n        options.width = w;\n        options.height = h;\n        this._setDimensions();\n        const computedSize = this.getComputedSize();\n        this.trigger('resize', computedSize.width, computedSize.height, data);\n    },\n\n    _setDimensions: function() {\n        const { options } = this;\n        let w = options.width;\n        let h = options.height;\n        if (isNumber(w)) w = `${Math.round(w)}px`;\n        if (isNumber(h)) h = `${Math.round(h)}px`;\n        this.$el.css({\n            width: (w === null) ? '' : w,\n            height: (h === null) ? '' : h\n        });\n    },\n\n    // Expand/shrink the paper to fit the content.\n    // Alternatively signature function(opt)\n    fitToContent: function(gridWidth, gridHeight, padding, opt) {\n\n        if (isObject(gridWidth)) {\n            // first parameter is an option object\n            opt = gridWidth;\n        } else {\n            // Support for a deprecated signature\n            opt = assign({ gridWidth, gridHeight, padding }, opt);\n        }\n\n        const { x, y, width, height } = this.getFitToContentArea(opt);\n        const { sx, sy } = this.scale();\n\n        this.translate(-x * sx, -y * sy, opt);\n        this.setDimensions(width * sx, height * sy, opt);\n\n        return new Rect(x, y, width, height);\n    },\n\n    getFitToContentArea: function(opt = {}) {\n\n        // Calculate the paper size to accommodate all the graph's elements.\n\n        const gridWidth = opt.gridWidth || 1;\n        const gridHeight = opt.gridHeight || 1;\n        const padding = normalizeSides(opt.padding || 0);\n\n        const minWidth = Math.max(opt.minWidth || 0, gridWidth);\n        const minHeight = Math.max(opt.minHeight || 0, gridHeight);\n        const maxWidth = opt.maxWidth || Number.MAX_VALUE;\n        const maxHeight = opt.maxHeight || Number.MAX_VALUE;\n        const newOrigin = opt.allowNewOrigin;\n\n        const area = ('contentArea' in opt) ? new Rect(opt.contentArea) : this.getContentArea(opt);\n        const { sx, sy } = this.scale();\n        area.x *= sx;\n        area.y *= sy;\n        area.width *= sx;\n        area.height *= sy;\n\n        let calcWidth = Math.ceil((area.width + area.x) / gridWidth);\n        let calcHeight = Math.ceil((area.height + area.y) / gridHeight);\n        if (!opt.allowNegativeBottomRight) {\n            calcWidth = Math.max(calcWidth, 1);\n            calcHeight = Math.max(calcHeight, 1);\n        }\n        calcWidth *= gridWidth;\n        calcHeight *= gridHeight;\n\n        let tx = 0;\n        if ((newOrigin === 'negative' && area.x < 0) || (newOrigin === 'positive' && area.x >= 0) || newOrigin === 'any') {\n            tx = Math.ceil(-area.x / gridWidth) * gridWidth;\n            tx += padding.left;\n            calcWidth += tx;\n        }\n\n        let ty = 0;\n        if ((newOrigin === 'negative' && area.y < 0) || (newOrigin === 'positive' && area.y >= 0) || newOrigin === 'any') {\n            ty = Math.ceil(-area.y / gridHeight) * gridHeight;\n            ty += padding.top;\n            calcHeight += ty;\n        }\n\n        calcWidth += padding.right;\n        calcHeight += padding.bottom;\n\n        // Make sure the resulting width and height are greater than minimum.\n        calcWidth = Math.max(calcWidth, minWidth);\n        calcHeight = Math.max(calcHeight, minHeight);\n\n        // Make sure the resulting width and height are lesser than maximum.\n        calcWidth = Math.min(calcWidth, maxWidth);\n        calcHeight = Math.min(calcHeight, maxHeight);\n\n        return new Rect(-tx / sx, -ty / sy, calcWidth / sx, calcHeight / sy);\n    },\n\n    transformToFitContent: function(opt) {\n        opt || (opt = {});\n\n        let contentBBox, contentLocalOrigin;\n        if ('contentArea' in opt) {\n            const contentArea = opt.contentArea;\n            contentBBox = this.localToPaperRect(contentArea);\n            contentLocalOrigin = new Point(contentArea);\n        } else {\n            contentBBox = this.getContentBBox(opt);\n            contentLocalOrigin = this.paperToLocalPoint(contentBBox);\n        }\n\n        if (!contentBBox.width || !contentBBox.height) return;\n\n        defaults(opt, {\n            padding: 0,\n            preserveAspectRatio: true,\n            scaleGrid: null,\n            minScale: 0,\n            maxScale: Number.MAX_VALUE,\n            verticalAlign: 'top',\n            horizontalAlign: 'left',\n            //minScaleX\n            //minScaleY\n            //maxScaleX\n            //maxScaleY\n            //fittingBBox\n        });\n\n        const padding = normalizeSides(opt.padding);\n\n        const minScaleX = opt.minScaleX || opt.minScale;\n        const maxScaleX = opt.maxScaleX || opt.maxScale;\n        const minScaleY = opt.minScaleY || opt.minScale;\n        const maxScaleY = opt.maxScaleY || opt.maxScale;\n\n        let fittingBBox;\n        if (opt.fittingBBox) {\n            fittingBBox = opt.fittingBBox;\n        } else {\n            const currentTranslate = this.translate();\n            const computedSize = this.getComputedSize();\n            fittingBBox = {\n                x: currentTranslate.tx,\n                y: currentTranslate.ty,\n                width: computedSize.width,\n                height: computedSize.height\n            };\n        }\n\n        fittingBBox = new Rect(fittingBBox).moveAndExpand({\n            x: padding.left,\n            y: padding.top,\n            width: -padding.left - padding.right,\n            height: -padding.top - padding.bottom\n        });\n\n        const ctm = this.matrix();\n        const { a: sx, d: sy, e: tx, f: ty } = ctm;\n\n        let newSx = fittingBBox.width / contentBBox.width * sx;\n        let newSy = fittingBBox.height / contentBBox.height * sy;\n\n        if (opt.preserveAspectRatio) {\n            newSx = newSy = Math.min(newSx, newSy);\n        }\n\n        // snap scale to a grid\n        if (opt.scaleGrid) {\n\n            const gridSize = opt.scaleGrid;\n\n            newSx = gridSize * Math.floor(newSx / gridSize);\n            newSy = gridSize * Math.floor(newSy / gridSize);\n        }\n\n        // scale min/max boundaries\n        newSx = Math.min(maxScaleX, Math.max(minScaleX, newSx));\n        newSy = Math.min(maxScaleY, Math.max(minScaleY, newSy));\n\n        const scaleDiff = {\n            x: newSx / sx,\n            y: newSy / sy\n        };\n\n        let newOx = fittingBBox.x - contentLocalOrigin.x * newSx - tx;\n        let newOy = fittingBBox.y - contentLocalOrigin.y * newSy - ty;\n\n        switch (opt.verticalAlign) {\n            case 'middle':\n                newOy = newOy + (fittingBBox.height - contentBBox.height * scaleDiff.y) / 2;\n                break;\n            case 'bottom':\n                newOy = newOy + (fittingBBox.height - contentBBox.height * scaleDiff.y);\n                break;\n            case 'top':\n            default:\n                break;\n        }\n\n        switch (opt.horizontalAlign) {\n            case 'middle':\n                newOx = newOx + (fittingBBox.width - contentBBox.width * scaleDiff.x) / 2;\n                break;\n            case 'right':\n                newOx = newOx + (fittingBBox.width - contentBBox.width * scaleDiff.x);\n                break;\n            case 'left':\n            default:\n                break;\n        }\n\n        ctm.a = newSx;\n        ctm.d = newSy;\n        ctm.e = newOx;\n        ctm.f = newOy;\n        this.matrix(ctm, opt);\n    },\n\n    scaleContentToFit: function(opt) {\n        this.transformToFitContent(opt);\n    },\n\n    // Return the dimensions of the content area in local units (without transformations).\n    getContentArea: function(opt) {\n\n        if (opt && opt.useModelGeometry) {\n            return this.model.getBBox() || new Rect();\n        }\n\n        return V(this.cells).getBBox();\n    },\n\n    // Return the dimensions of the content bbox in the paper units (as it appears on screen).\n    getContentBBox: function(opt) {\n\n        return this.localToPaperRect(this.getContentArea(opt));\n    },\n\n    // Returns a geometry rectangle representing the entire\n    // paper area (coordinates from the left paper border to the right one\n    // and the top border to the bottom one).\n    getArea: function() {\n\n        return this.paperToLocalRect(this.getComputedSize());\n    },\n\n    getRestrictedArea: function(...args) {\n\n        const { restrictTranslate } = this.options;\n\n        let restrictedArea;\n        if (isFunction(restrictTranslate)) {\n            // A method returning a bounding box\n            restrictedArea = restrictTranslate.apply(this, args);\n        } else if (restrictTranslate === true) {\n            // The paper area\n            restrictedArea = this.getArea();\n        } else if (!restrictTranslate) {\n            // falsy value\n            restrictedArea = null;\n        } else {\n            // any other value\n            restrictedArea = new Rect(restrictTranslate);\n        }\n\n        return restrictedArea;\n    },\n\n    createViewForModel: function(cell) {\n\n        const { options } = this;\n        // A class taken from the paper options.\n        var optionalViewClass;\n\n        // A default basic class (either dia.ElementView or dia.LinkView)\n        var defaultViewClass;\n\n        // A special class defined for this model in the corresponding namespace.\n        // e.g. joint.shapes.standard.Rectangle searches for joint.shapes.standard.RectangleView\n        var namespace = options.cellViewNamespace;\n        var type = cell.get('type') + 'View';\n        var namespaceViewClass = getByPath(namespace, type, '.');\n\n        if (cell.isLink()) {\n            optionalViewClass = options.linkView;\n            defaultViewClass = LinkView;\n        } else {\n            optionalViewClass = options.elementView;\n            defaultViewClass = ElementView;\n        }\n\n        // a) the paper options view is a class (deprecated)\n        //  1. search the namespace for a view\n        //  2. if no view was found, use view from the paper options\n        // b) the paper options view is a function\n        //  1. call the function from the paper options\n        //  2. if no view was return, search the namespace for a view\n        //  3. if no view was found, use the default\n        var ViewClass = (optionalViewClass.prototype instanceof ViewBase)\n            ? namespaceViewClass || optionalViewClass\n            : optionalViewClass.call(this, cell) || namespaceViewClass || defaultViewClass;\n\n        return new ViewClass({\n            model: cell,\n            interactive: options.interactive,\n            labelsLayer: options.labelsLayer === true ? LayersNames.LABELS : options.labelsLayer\n        });\n    },\n\n    removeView: function(cell) {\n\n        const { id } = cell;\n        const { _views, _updates } = this;\n        const view = _views[id];\n        if (view) {\n            var { cid } = view;\n            const { mounted, unmounted } = _updates;\n            view.remove();\n            delete _views[id];\n            delete mounted[cid];\n            delete unmounted[cid];\n        }\n        return view;\n    },\n\n    renderView: function(cell, opt) {\n\n        const { id } = cell;\n        const views = this._views;\n        let view, flag;\n        let create = true;\n        if (id in views) {\n            view = views[id];\n            if (view.model === cell) {\n                flag = view.FLAG_INSERT;\n                create = false;\n            } else {\n                // The view for this `id` already exist.\n                // The cell is a new instance of the model with identical id\n                // We simply remove the existing view and create a new one\n                this.removeView(cell);\n            }\n        }\n        if (create) {\n            view = views[id] = this.createViewForModel(cell);\n            view.paper = this;\n            flag = this.registerUnmountedView(view) | this.FLAG_INIT | view.getFlag(result(view, 'initFlag'));\n        }\n        this.requestViewUpdate(view, flag, view.UPDATE_PRIORITY, opt);\n        return view;\n    },\n\n    onImageDragStart: function() {\n        // This is the only way to prevent image dragging in Firefox that works.\n        // Setting -moz-user-select: none, draggable=\"false\" attribute or user-drag: none didn't help.\n\n        return false;\n    },\n\n    resetViews: function(cells, opt) {\n        opt || (opt = {});\n        cells || (cells = []);\n        this._resetUpdates();\n        // clearing views removes any event listeners\n        this.removeViews();\n        // Allows to unfreeze normally while in the idle state using autoFreeze option\n        const key = this.options.autoFreeze ? null : 'reset';\n        this.freeze({ key });\n        for (var i = 0, n = cells.length; i < n; i++) {\n            this.renderView(cells[i], opt);\n        }\n        this.unfreeze({ key });\n        this.sortViews();\n    },\n\n    removeViews: function() {\n\n        invoke(this._views, 'remove');\n\n        this._views = {};\n    },\n\n    sortViews: function() {\n\n        if (!this.isExactSorting()) {\n            // noop\n            return;\n        }\n        if (this.isFrozen()) {\n            // sort views once unfrozen\n            this._updates.sort = true;\n            return;\n        }\n        this.sortViewsExact();\n    },\n\n    sortViewsExact: function() {\n\n        // Run insertion sort algorithm in order to efficiently sort DOM elements according to their\n        // associated model `z` attribute.\n\n        var cellNodes = Array.from(this.cells.childNodes).filter(node => node.getAttribute('model-id'));\n        var cells = this.model.get('cells');\n\n        sortElements(cellNodes, function(a, b) {\n            var cellA = cells.get(a.getAttribute('model-id'));\n            var cellB = cells.get(b.getAttribute('model-id'));\n            var zA = cellA.attributes.z || 0;\n            var zB = cellB.attributes.z || 0;\n            return (zA === zB) ? 0 : (zA < zB) ? -1 : 1;\n        });\n    },\n\n    insertView: function(view, isInitialInsert) {\n        const layerView = this.getLayerView(LayersNames.CELLS);\n        const { el, model } = view;\n        switch (this.options.sorting) {\n            case sortingTypes.APPROX:\n                layerView.insertSortedNode(el, model.get('z'));\n                break;\n            case sortingTypes.EXACT:\n            default:\n                layerView.insertNode(el);\n                break;\n        }\n        view.onMount(isInitialInsert);\n    },\n\n    detachView(view) {\n        view.unmount();\n        view.onDetach();\n    },\n\n    // Find the first view climbing up the DOM tree starting at element `el`. Note that `el` can also\n    // be a selector or a jQuery object.\n    findView: function($el) {\n\n        var el = isString($el)\n            ? this.cells.querySelector($el)\n            : $el instanceof $ ? $el[0] : $el;\n\n        var id = this.findAttribute('model-id', el);\n        if (id) return this._views[id];\n\n        return undefined;\n    },\n\n    // Find a view for a model `cell`. `cell` can also be a string or number representing a model `id`.\n    findViewByModel: function(cell) {\n\n        var id = (isString(cell) || isNumber(cell)) ? cell : (cell && cell.id);\n\n        return this._views[id];\n    },\n\n    // Find all views at given point\n    findViewsFromPoint: function(p) {\n\n        p = new Point(p);\n\n        var views = this.model.getElements().map(this.findViewByModel, this);\n\n        return views.filter(function(view) {\n            return view && view.vel.getBBox({ target: this.cells }).containsPoint(p);\n        }, this);\n    },\n\n    // Find all views in given area\n    findViewsInArea: function(rect, opt) {\n\n        opt = defaults(opt || {}, { strict: false });\n        rect = new Rect(rect);\n\n        var views = this.model.getElements().map(this.findViewByModel, this);\n        var method = opt.strict ? 'containsRect' : 'intersect';\n\n        return views.filter(function(view) {\n            return view && rect[method](view.vel.getBBox({ target: this.cells }));\n        }, this);\n    },\n\n    findElementViewsInArea(plainArea, opt) {\n        return this._filterViewsInArea(\n            plainArea,\n            (extArea, findOpt) => this.model.findElementsInArea(extArea, findOpt),\n            opt\n        );\n    },\n\n    findLinkViewsInArea: function(plainArea, opt) {\n        return this._filterViewsInArea(\n            plainArea,\n            (extArea, findOpt) => this.model.findLinksInArea(extArea, findOpt),\n            opt\n        );\n    },\n\n    findCellViewsInArea: function(plainArea, opt) {\n        return this._filterViewsInArea(\n            plainArea,\n            (extArea, findOpt) => this.model.findCellsInArea(extArea, findOpt),\n            opt\n        );\n    },\n\n    findElementViewsAtPoint: function(plainPoint, opt) {\n        return this._filterViewsAtPoint(\n            plainPoint,\n            (extArea) => this.model.findElementsInArea(extArea),\n            opt\n        );\n    },\n\n    findLinkViewsAtPoint: function(plainPoint, opt) {\n        return this._filterViewsAtPoint(\n            plainPoint,\n            (extArea) => this.model.findLinksInArea(extArea),\n            opt,\n        );\n    },\n\n    findCellViewsAtPoint: function(plainPoint, opt) {\n        return this._filterViewsAtPoint(\n            plainPoint,\n            // Note: we do not want to pass `opt` to `findCellsInArea`\n            // because the `strict` option works differently for querying at a point\n            (extArea) => this.model.findCellsInArea(extArea),\n            opt\n        );\n    },\n\n    _findInExtendedArea: function(area, findCellsFn, opt = {}) {\n        const {\n            buffer = this.DEFAULT_FIND_BUFFER,\n        } = opt;\n        const extendedArea = (new Rect(area)).inflate(buffer);\n        const cellsInExtendedArea = findCellsFn(extendedArea, opt);\n        return cellsInExtendedArea.map(element => this.findViewByModel(element));\n    },\n\n    _filterViewsInArea: function(plainArea, findCells, opt = {}) {\n        const area = new Rect(plainArea);\n        const viewsInExtendedArea = this._findInExtendedArea(area, findCells, opt);\n        const viewsInArea = viewsInExtendedArea.filter(view => {\n            if (!view) return false;\n            return view.isInArea(area, opt);\n        });\n        return viewsInArea;\n    },\n\n    _filterViewsAtPoint: function(plainPoint, findCells, opt = {}) {\n        const area = new Rect(plainPoint); // zero-size area\n        const viewsInExtendedArea = this._findInExtendedArea(area, findCells, opt);\n        const viewsAtPoint = viewsInExtendedArea.filter(view => {\n            if (!view) return false;\n            return view.isAtPoint(plainPoint, opt);\n        });\n        return viewsAtPoint;\n    },\n\n    removeTools: function() {\n        this.dispatchToolsEvent('remove');\n        return this;\n    },\n\n    hideTools: function() {\n        this.dispatchToolsEvent('hide');\n        return this;\n    },\n\n    showTools: function() {\n        this.dispatchToolsEvent('show');\n        return this;\n    },\n\n    dispatchToolsEvent: function(event, ...args) {\n        if (typeof event !== 'string') return;\n        this.trigger('tools:event', event, ...args);\n    },\n\n\n    getModelById: function(id) {\n\n        return this.model.getCell(id);\n    },\n\n    snapToGrid: function(x, y) {\n\n        // Convert global coordinates to the local ones of the `viewport`. Otherwise,\n        // improper transformation would be applied when the viewport gets transformed (scaled/rotated).\n        return this.clientToLocalPoint(x, y).snapToGrid(this.options.gridSize);\n    },\n\n    localToPaperPoint: function(x, y) {\n        // allow `x` to be a point and `y` undefined\n        var localPoint = new Point(x, y);\n        var paperPoint = V.transformPoint(localPoint, this.matrix());\n        return paperPoint;\n    },\n\n    localToPaperRect: function(x, y, width, height) {\n        // allow `x` to be a rectangle and rest arguments undefined\n        var localRect = new Rect(x, y, width, height);\n        var paperRect = V.transformRect(localRect, this.matrix());\n        return paperRect;\n    },\n\n    paperToLocalPoint: function(x, y) {\n        // allow `x` to be a point and `y` undefined\n        var paperPoint = new Point(x, y);\n        var localPoint = V.transformPoint(paperPoint, this.matrix().inverse());\n        return localPoint;\n    },\n\n    paperToLocalRect: function(x, y, width, height) {\n        // allow `x` to be a rectangle and rest arguments undefined\n        var paperRect = new Rect(x, y, width, height);\n        var localRect = V.transformRect(paperRect, this.matrix().inverse());\n        return localRect;\n    },\n\n    localToClientPoint: function(x, y) {\n        // allow `x` to be a point and `y` undefined\n        var localPoint = new Point(x, y);\n        var clientPoint = V.transformPoint(localPoint, this.clientMatrix());\n        return clientPoint;\n    },\n\n    localToClientRect: function(x, y, width, height) {\n        // allow `x` to be a point and `y` undefined\n        var localRect = new Rect(x, y, width, height);\n        var clientRect = V.transformRect(localRect, this.clientMatrix());\n        return clientRect;\n    },\n\n    // Transform client coordinates to the paper local coordinates.\n    // Useful when you have a mouse event object and you'd like to get coordinates\n    // inside the paper that correspond to `evt.clientX` and `evt.clientY` point.\n    // Example: var localPoint = paper.clientToLocalPoint({ x: evt.clientX, y: evt.clientY });\n    clientToLocalPoint: function(x, y) {\n        // allow `x` to be a point and `y` undefined\n        var clientPoint = new Point(x, y);\n        var localPoint = V.transformPoint(clientPoint, this.clientMatrix().inverse());\n        return localPoint;\n    },\n\n    clientToLocalRect: function(x, y, width, height) {\n        // allow `x` to be a point and `y` undefined\n        var clientRect = new Rect(x, y, width, height);\n        var localRect = V.transformRect(clientRect, this.clientMatrix().inverse());\n        return localRect;\n    },\n\n    localToPagePoint: function(x, y) {\n\n        return this.localToPaperPoint(x, y).offset(this.pageOffset());\n    },\n\n    localToPageRect: function(x, y, width, height) {\n\n        return this.localToPaperRect(x, y, width, height).offset(this.pageOffset());\n    },\n\n    pageToLocalPoint: function(x, y) {\n\n        var pagePoint = new Point(x, y);\n        var paperPoint = pagePoint.difference(this.pageOffset());\n        return this.paperToLocalPoint(paperPoint);\n    },\n\n    pageToLocalRect: function(x, y, width, height) {\n\n        var pageOffset = this.pageOffset();\n        var paperRect = new Rect(x, y, width, height);\n        paperRect.x -= pageOffset.x;\n        paperRect.y -= pageOffset.y;\n        return this.paperToLocalRect(paperRect);\n    },\n\n    clientOffset: function() {\n\n        var clientRect = this.svg.getBoundingClientRect();\n        return new Point(clientRect.left, clientRect.top);\n    },\n\n    pageOffset: function() {\n\n        return this.clientOffset().offset(window.scrollX, window.scrollY);\n    },\n\n    linkAllowed: function(linkView) {\n\n        if (!(linkView instanceof LinkView)) {\n            throw new Error('Must provide a linkView.');\n        }\n\n        var link = linkView.model;\n        var paperOptions = this.options;\n        var graph = this.model;\n        var ns = graph.constructor.validations;\n\n        if (!paperOptions.multiLinks) {\n            if (!ns.multiLinks.call(this, graph, link)) return false;\n        }\n\n        if (!paperOptions.linkPinning) {\n            // Link pinning is not allowed and the link is not connected to the target.\n            if (!ns.linkPinning.call(this, graph, link)) return false;\n        }\n\n        if (typeof paperOptions.allowLink === 'function') {\n            if (!paperOptions.allowLink.call(this, linkView, this)) return false;\n        }\n\n        return true;\n    },\n\n    getDefaultLink: function(cellView, magnet) {\n\n        return isFunction(this.options.defaultLink)\n        // default link is a function producing link model\n            ? this.options.defaultLink.call(this, cellView, magnet)\n        // default link is the mvc model\n            : this.options.defaultLink.clone();\n    },\n\n    // Cell highlighting.\n    // ------------------\n\n    resolveHighlighter: function(opt = {}) {\n\n        let { highlighter: highlighterDef, type } = opt;\n        const { highlighting,highlighterNamespace  } = this.options;\n\n        /*\n            Expecting opt.highlighter to have the following structure:\n            {\n                name: 'highlighter-name',\n                options: {\n                    some: 'value'\n                }\n            }\n        */\n        if (highlighterDef === undefined) {\n\n            // Is highlighting disabled?\n            if (!highlighting) return false;\n            // check for built-in types\n            if (type) {\n                highlighterDef = highlighting[type];\n                // Is a specific type highlight disabled?\n                if (highlighterDef === false) return false;\n            }\n            if (!highlighterDef) {\n                // Type not defined use default highlight\n                highlighterDef = highlighting['default'];\n            }\n        }\n\n        // Do nothing if opt.highlighter is falsy.\n        // This allows the case to not highlight cell(s) in certain cases.\n        // For example, if you want to NOT highlight when embedding elements\n        // or use a custom highlighter.\n        if (!highlighterDef) return false;\n\n        // Allow specifying a highlighter by name.\n        if (isString(highlighterDef)) {\n            highlighterDef = {\n                name: highlighterDef\n            };\n        }\n\n        const name = highlighterDef.name;\n        const highlighter = highlighterNamespace[name];\n\n        // Highlighter validation\n        if (!highlighter) {\n            throw new Error('Unknown highlighter (\"' + name + '\")');\n        }\n        if (typeof highlighter.highlight !== 'function') {\n            throw new Error('Highlighter (\"' + name + '\") is missing required highlight() method');\n        }\n        if (typeof highlighter.unhighlight !== 'function') {\n            throw new Error('Highlighter (\"' + name + '\") is missing required unhighlight() method');\n        }\n\n        return {\n            highlighter,\n            options: highlighterDef.options || {},\n            name\n        };\n    },\n\n    onCellHighlight: function(cellView, magnetEl, opt) {\n        const highlighterDescriptor = this.resolveHighlighter(opt);\n        if (!highlighterDescriptor) return;\n        const { highlighter, options } = highlighterDescriptor;\n        highlighter.highlight(cellView, magnetEl, options);\n    },\n\n    onCellUnhighlight: function(cellView, magnetEl, opt) {\n        const highlighterDescriptor = this.resolveHighlighter(opt);\n        if (!highlighterDescriptor) return;\n        const { highlighter, options } = highlighterDescriptor;\n        highlighter.unhighlight(cellView, magnetEl, options);\n    },\n\n    // Interaction.\n    // ------------\n\n    pointerdblclick: function(evt) {\n\n        evt.preventDefault();\n\n        // magnetpointerdblclick can stop propagation\n\n        evt = normalizeEvent(evt);\n\n        var view = this.findView(evt.target);\n        if (this.guard(evt, view)) return;\n\n        var localPoint = this.snapToGrid(evt.clientX, evt.clientY);\n\n        if (view) {\n            view.pointerdblclick(evt, localPoint.x, localPoint.y);\n\n        } else {\n            this.trigger('blank:pointerdblclick', evt, localPoint.x, localPoint.y);\n        }\n    },\n\n    pointerclick: function(evt) {\n\n        // magnetpointerclick can stop propagation\n\n        var data = this.eventData(evt);\n        // Trigger event only if mouse has not moved.\n        if (data.mousemoved <= this.options.clickThreshold) {\n\n            evt = normalizeEvent(evt);\n\n            var view = this.findView(evt.target);\n            if (this.guard(evt, view)) return;\n\n            var localPoint = this.snapToGrid(evt.clientX, evt.clientY);\n\n            if (view) {\n                view.pointerclick(evt, localPoint.x, localPoint.y);\n\n            } else {\n                this.trigger('blank:pointerclick', evt, localPoint.x, localPoint.y);\n            }\n        }\n    },\n\n    contextmenu: function(evt) {\n\n        if (this.options.preventContextMenu) evt.preventDefault();\n\n        if (this.contextMenuFired) {\n            this.contextMenuFired = false;\n            return;\n        }\n\n        evt = normalizeEvent(evt);\n\n        this.contextMenuTrigger(evt);\n    },\n\n    contextMenuTrigger: function(evt) {\n        var view = this.findView(evt.target);\n        if (this.guard(evt, view)) return;\n\n        var localPoint = this.snapToGrid(evt.clientX, evt.clientY);\n\n        if (view) {\n            view.contextmenu(evt, localPoint.x, localPoint.y);\n\n        } else {\n            this.trigger('blank:contextmenu', evt, localPoint.x, localPoint.y);\n        }\n    },\n\n    pointerdown: function(evt) {\n\n        evt = normalizeEvent(evt);\n\n        const { target, button } = evt;\n        const view = this.findView(target);\n        const isContextMenu = (button === 2);\n\n        if (view) {\n\n            if (!isContextMenu && this.guard(evt, view)) return;\n\n            const isTargetFormNode = this.FORM_CONTROL_TAG_NAMES.includes(target.tagName);\n\n            if (this.options.preventDefaultViewAction && !isTargetFormNode) {\n                // If the target is a form element, we do not want to prevent the default action.\n                // For example, we want to be able to select text in a text input or\n                // to be able to click on a checkbox.\n                evt.preventDefault();\n            }\n\n            if (isTargetFormNode) {\n                // If the target is a form element, we do not want to start dragging the element.\n                // For example, we want to be able to select text by dragging the mouse.\n                view.preventDefaultInteraction(evt);\n            }\n\n            // Custom event\n            const eventEvt = this.customEventTrigger(evt, view);\n            if (eventEvt) {\n            // `onevent` could have stopped propagation\n                if (eventEvt.isPropagationStopped()) return;\n\n                evt.data = eventEvt.data;\n            }\n\n            // Element magnet\n            const magnetNode = target.closest('[magnet]');\n            if (magnetNode && view.el !== magnetNode && view.el.contains(magnetNode)) {\n                const magnetEvt = normalizeEvent(new $.Event(evt.originalEvent, {\n                    data: evt.data,\n                    // Originally the event listener was attached to the magnet element.\n                    currentTarget: magnetNode\n                }));\n                this.onmagnet(magnetEvt);\n                if (magnetEvt.isDefaultPrevented()) {\n                    evt.preventDefault();\n                }\n                // `onmagnet` stops propagation when `addLinkFromMagnet` is allowed\n                if (magnetEvt.isPropagationStopped()) {\n                    // `magnet:pointermove` and `magnet:pointerup` events must be fired\n                    if (isContextMenu) return;\n                    this.delegateDragEvents(view, magnetEvt.data);\n                    return;\n                }\n                evt.data = magnetEvt.data;\n            }\n        }\n\n        if (isContextMenu) {\n            this.contextMenuFired = true;\n            const contextmenuEvt = new $.Event(evt.originalEvent, { type: 'contextmenu', data: evt.data });\n            this.contextMenuTrigger(contextmenuEvt);\n        } else {\n            const localPoint = this.snapToGrid(evt.clientX, evt.clientY);\n            if (view) {\n                view.pointerdown(evt, localPoint.x, localPoint.y);\n            } else {\n                if (this.options.preventDefaultBlankAction) {\n                    evt.preventDefault();\n                }\n                this.trigger('blank:pointerdown', evt, localPoint.x, localPoint.y);\n            }\n\n            this.delegateDragEvents(view, evt.data);\n        }\n\n    },\n\n    pointermove: function(evt) {\n\n        // mouse moved counter\n        var data = this.eventData(evt);\n        if (!data.mousemoved) {\n            data.mousemoved = 0;\n            // Make sure that events like `mouseenter` and `mouseleave` are\n            // not triggered while the user is dragging a cellView.\n            this.undelegateEvents();\n            // Note: the events are undelegated after the first `pointermove` event.\n            // Not on `pointerdown` to make sure that `dbltap` is recognized.\n        }\n\n        var mousemoved = ++data.mousemoved;\n\n        if (mousemoved <= this.options.moveThreshold) return;\n\n        evt = normalizeEvent(evt);\n\n        var localPoint = this.snapToGrid(evt.clientX, evt.clientY);\n\n        var view = data.sourceView;\n        if (view) {\n            view.pointermove(evt, localPoint.x, localPoint.y);\n        } else {\n            this.trigger('blank:pointermove', evt, localPoint.x, localPoint.y);\n        }\n\n        this.eventData(evt, data);\n    },\n\n    pointerup: function(evt) {\n\n        this.undelegateDocumentEvents();\n\n        var normalizedEvt = normalizeEvent(evt);\n\n        var localPoint = this.snapToGrid(normalizedEvt.clientX, normalizedEvt.clientY);\n\n        var view = this.eventData(evt).sourceView;\n        if (view) {\n            view.pointerup(normalizedEvt, localPoint.x, localPoint.y);\n        } else {\n            this.trigger('blank:pointerup', normalizedEvt, localPoint.x, localPoint.y);\n        }\n\n        if (!normalizedEvt.isPropagationStopped()) {\n            this.pointerclick(new $.Event(evt.originalEvent, { type: 'click', data: evt.data }));\n        }\n\n        this.delegateEvents();\n    },\n\n    mouseover: function(evt) {\n\n        evt = normalizeEvent(evt);\n\n        var view = this.findView(evt.target);\n        if (this.guard(evt, view)) return;\n\n        if (view) {\n            view.mouseover(evt);\n\n        } else {\n            if (this.el === evt.target) return; // prevent border of paper from triggering this\n            this.trigger('blank:mouseover', evt);\n        }\n    },\n\n    mouseout: function(evt) {\n\n        evt = normalizeEvent(evt);\n\n        var view = this.findView(evt.target);\n        if (this.guard(evt, view)) return;\n\n        if (view) {\n            view.mouseout(evt);\n\n        } else {\n            if (this.el === evt.target) return; // prevent border of paper from triggering this\n            this.trigger('blank:mouseout', evt);\n        }\n    },\n\n    mouseenter: function(evt) {\n\n        evt = normalizeEvent(evt);\n\n        const {\n            target, // The EventTarget the pointing device entered to\n            relatedTarget, // The EventTarget the pointing device exited from\n            currentTarget // The EventTarget on which the event listener was registered\n        } = evt;\n        const view = this.findView(target);\n        if (this.guard(evt, view)) return;\n        const relatedView = this.findView(relatedTarget);\n        if (view) {\n            if (relatedView === view) {\n                // Mouse left a cell tool\n                return;\n            }\n            view.mouseenter(evt);\n            if (this.el.contains(relatedTarget)) {\n                // The pointer remains inside the paper.\n                return;\n            }\n        }\n        if (relatedView) {\n            return;\n        }\n        // prevent double `mouseenter` event if the `relatedTarget` is outside the paper\n        // (mouseenter method would be fired twice)\n        if (currentTarget === this.el) {\n            // `paper` (more descriptive), not `blank`\n            this.trigger('paper:mouseenter', evt);\n        }\n    },\n\n    mouseleave: function(evt) {\n\n        evt = normalizeEvent(evt);\n\n        const {\n            target, // The EventTarget the pointing device exited from\n            relatedTarget, // The EventTarget the pointing device entered to\n            currentTarget // The EventTarget on which the event listener was registered\n        } = evt;\n        const view = this.findView(target);\n        if (this.guard(evt, view)) return;\n        const relatedView = this.findView(relatedTarget);\n        if (view) {\n            if (relatedView === view) {\n                // Mouse entered a cell tool\n                return;\n            }\n            view.mouseleave(evt);\n            if (this.el.contains(relatedTarget)) {\n                // The pointer has exited a cellView. The pointer is still inside of the paper.\n                return;\n            }\n        }\n        if (relatedView) {\n            // The pointer has entered a new cellView\n            return;\n        }\n        // prevent double `mouseleave` event if the `relatedTarget` is outside the paper\n        // (mouseleave method would be fired twice)\n        if (currentTarget === this.el) {\n            // There is no cellView under the pointer, nor the blank area of the paper\n            this.trigger('paper:mouseleave', evt);\n        }\n    },\n\n    _processMouseWheelEvtBuf: debounce(function() {\n        const { event, deltas } = this._mw_evt_buffer;\n        const deltaY = deltas.reduce((acc, deltaY) => acc + cap(deltaY, WHEEL_CAP), 0);\n\n        const scale = Math.pow(0.995, deltaY); // 1.005 for inverted pinch/zoom\n        const { x, y } = this.clientToLocalPoint(event.clientX, event.clientY);\n        this.trigger('paper:pinch', event, x, y, scale);\n\n        this._mw_evt_buffer = {\n            event: null,\n            deltas: [],\n        };\n    }, WHEEL_WAIT_MS, { maxWait: WHEEL_WAIT_MS }),\n\n    mousewheel: function(evt) {\n\n        evt = normalizeEvent(evt);\n\n        const view = this.findView(evt.target);\n        if (this.guard(evt, view)) return;\n\n        const originalEvent = evt.originalEvent;\n        const localPoint = this.snapToGrid(originalEvent.clientX, originalEvent.clientY);\n        const { deltaX, deltaY } = normalizeWheel(originalEvent);\n\n        const pinchHandlers = this._events['paper:pinch'];\n\n        // Touchpad devices will send a fake CTRL press when a pinch is performed\n        //\n        // We also check if there are any subscribers to paper:pinch event. If there are none,\n        // just skip the entire block of code (we don't want to blindly call\n        // .preventDefault() if we really don't have to).\n        if (evt.ctrlKey && pinchHandlers && pinchHandlers.length > 0) {\n            // This is a pinch gesture, it's safe to assume that we must call .preventDefault()\n            originalEvent.preventDefault();\n            this._mw_evt_buffer.event = evt;\n            this._mw_evt_buffer.deltas.push(deltaY);\n            this._processMouseWheelEvtBuf();\n        } else {\n            const delta = Math.max(-1, Math.min(1, originalEvent.wheelDelta));\n            if (view) {\n                view.mousewheel(evt, localPoint.x, localPoint.y, delta);\n\n            } else {\n                this.trigger('blank:mousewheel', evt, localPoint.x, localPoint.y, delta);\n            }\n\n            this.trigger('paper:pan', evt, deltaX, deltaY);\n        }\n    },\n\n    onevent: function(evt) {\n\n        var eventNode = evt.currentTarget;\n        var eventName = eventNode.getAttribute('event');\n        if (eventName) {\n            var view = this.findView(eventNode);\n            if (view) {\n\n                evt = normalizeEvent(evt);\n                if (this.guard(evt, view)) return;\n\n                var localPoint = this.snapToGrid(evt.clientX, evt.clientY);\n                view.onevent(evt, eventName, localPoint.x, localPoint.y);\n            }\n        }\n    },\n\n    magnetEvent: function(evt, handler) {\n\n        var magnetNode = evt.currentTarget;\n        var magnetValue = magnetNode.getAttribute('magnet');\n        if (magnetValue) {\n            var view = this.findView(magnetNode);\n            if (view) {\n                evt = normalizeEvent(evt);\n                if (this.guard(evt, view)) return;\n                var localPoint = this.snapToGrid(evt.clientX, evt.clientY);\n                handler.call(this, view, evt, magnetNode, localPoint.x, localPoint.y);\n            }\n        }\n    },\n\n    onmagnet: function(evt) {\n\n        if (evt.button === 2) {\n            this.contextMenuFired = true;\n            this.magnetContextMenuFired = true;\n            const contextmenuEvt = new $.Event(evt.originalEvent, {\n                type: 'contextmenu',\n                data: evt.data,\n                currentTarget: evt.currentTarget,\n            });\n            this.magnetContextMenuTrigger(contextmenuEvt);\n            if (contextmenuEvt.isPropagationStopped()) {\n                evt.stopPropagation();\n            }\n        } else {\n            this.magnetEvent(evt, function(view, evt, _, x, y) {\n                view.onmagnet(evt, x, y);\n            });\n        }\n    },\n\n    magnetpointerdblclick: function(evt) {\n\n        this.magnetEvent(evt, function(view, evt, magnet, x, y) {\n            view.magnetpointerdblclick(evt, magnet, x, y);\n        });\n    },\n\n    magnetcontextmenu: function(evt) {\n        if (this.options.preventContextMenu) evt.preventDefault();\n\n        if (this.magnetContextMenuFired) {\n            this.magnetContextMenuFired = false;\n            return;\n        }\n\n        this.magnetContextMenuTrigger(evt);\n    },\n\n    magnetContextMenuTrigger: function(evt) {\n        this.magnetEvent(evt, function(view, evt, magnet, x, y) {\n            view.magnetcontextmenu(evt, magnet, x, y);\n        });\n    },\n\n    onlabel: function(evt) {\n\n        var labelNode = evt.currentTarget;\n\n        var view = this.findView(labelNode);\n        if (!view) return;\n\n        evt = normalizeEvent(evt);\n        if (this.guard(evt, view)) return;\n\n        // Custom event\n        const eventEvt = this.customEventTrigger(evt, view, labelNode);\n        if (eventEvt) {\n            // `onevent` could have stopped propagation\n            if (eventEvt.isPropagationStopped()) return;\n\n            evt.data = eventEvt.data;\n        }\n\n        var localPoint = this.snapToGrid(evt.clientX, evt.clientY);\n        view.onlabel(evt, localPoint.x, localPoint.y);\n    },\n\n    getPointerArgs(evt) {\n        const normalizedEvt = normalizeEvent(evt);\n        const { x, y } = this.snapToGrid(normalizedEvt.clientX, normalizedEvt.clientY);\n        return [normalizedEvt, x, y];\n    },\n\n    delegateDragEvents: function(view, data) {\n\n        data || (data = {});\n        this.eventData({ data: data }, { sourceView: view || null, mousemoved: 0 });\n        this.delegateDocumentEvents(null, data);\n    },\n\n    // Guard the specified event. If the event should be ignored, guard returns `true`.\n    // Otherwise, it returns `false`.\n    guard: function(evt, view) {\n\n        if (evt.type === 'mousedown' && evt.button === 2) {\n            // handled as `contextmenu` type\n            return true;\n        }\n\n        if (this.options.guard && this.options.guard(evt, view)) {\n            return true;\n        }\n\n        if (evt.data && evt.data.guarded !== undefined) {\n            return evt.data.guarded;\n        }\n\n        const { target } = evt;\n\n        if (this.GUARDED_TAG_NAMES.includes(target.tagName)) {\n            return true;\n        }\n\n        if (view && view.model && (view.model instanceof Cell)) {\n            return false;\n        }\n\n        if (this.el === target || this.svg.contains(target)) {\n            return false;\n        }\n\n        return true;    // Event guarded. Paper should not react on it in any way.\n    },\n\n    setGridSize: function(gridSize) {\n        const { options } = this;\n        options.gridSize = gridSize;\n        if (options.drawGrid && !options.drawGridSize) {\n            // Do not redraw the grid if the `drawGridSize` is set.\n            this.getLayerView(LayersNames.GRID).renderGrid();\n        }\n        return this;\n    },\n\n    setGrid: function(drawGrid) {\n        this.getLayerView(LayersNames.GRID).setGrid(drawGrid);\n        return this;\n    },\n\n    updateBackgroundImage: function(opt) {\n\n        opt = opt || {};\n\n        var backgroundPosition = opt.position || 'center';\n        var backgroundSize = opt.size || 'auto auto';\n\n        var currentScale = this.scale();\n        var currentTranslate = this.translate();\n\n        // backgroundPosition\n        if (isObject(backgroundPosition)) {\n            var x = currentTranslate.tx + (currentScale.sx * (backgroundPosition.x || 0));\n            var y = currentTranslate.ty + (currentScale.sy * (backgroundPosition.y || 0));\n            backgroundPosition = x + 'px ' + y + 'px';\n        }\n\n        // backgroundSize\n        if (isObject(backgroundSize)) {\n            backgroundSize = new Rect(backgroundSize).scale(currentScale.sx, currentScale.sy);\n            backgroundSize = backgroundSize.width + 'px ' + backgroundSize.height + 'px';\n        }\n\n        const { background } = this.childNodes;\n        background.style.backgroundSize = backgroundSize;\n        background.style.backgroundPosition = backgroundPosition;\n    },\n\n    drawBackgroundImage: function(img, opt) {\n\n        // Clear the background image if no image provided\n        if (!(img instanceof HTMLImageElement)) {\n            this.childNodes.background.style.backgroundImage = '';\n            return;\n        }\n\n        if (!this._background || this._background.id !== opt.id) {\n            // Draw only the last image requested (see drawBackground())\n            return;\n        }\n\n        opt = opt || {};\n\n        var backgroundImage;\n        var backgroundSize = opt.size;\n        var backgroundRepeat = opt.repeat || 'no-repeat';\n        var backgroundOpacity = opt.opacity || 1;\n        var backgroundQuality = Math.abs(opt.quality) || 1;\n        var backgroundPattern = this.constructor.backgroundPatterns[camelCase(backgroundRepeat)];\n\n        if (isFunction(backgroundPattern)) {\n            // 'flip-x', 'flip-y', 'flip-xy', 'watermark' and custom\n            img.width *= backgroundQuality;\n            img.height *= backgroundQuality;\n            var canvas = backgroundPattern(img, opt);\n            if (!(canvas instanceof HTMLCanvasElement)) {\n                throw new Error('dia.Paper: background pattern must return an HTML Canvas instance');\n            }\n\n            backgroundImage = canvas.toDataURL('image/png');\n            backgroundRepeat = 'repeat';\n            if (isObject(backgroundSize)) {\n                // recalculate the tile size if an object passed in\n                backgroundSize.width *= canvas.width / img.width;\n                backgroundSize.height *= canvas.height / img.height;\n            } else if (backgroundSize === undefined) {\n                // calculate the tile size if no provided\n                opt.size = {\n                    width: canvas.width / backgroundQuality,\n                    height: canvas.height / backgroundQuality\n                };\n            }\n        } else {\n            // backgroundRepeat:\n            // no-repeat', 'round', 'space', 'repeat', 'repeat-x', 'repeat-y'\n            backgroundImage = img.src;\n            if (backgroundSize === undefined) {\n                // pass the image size for  the backgroundSize if no size provided\n                opt.size = {\n                    width: img.width,\n                    height: img.height\n                };\n            }\n        }\n\n        this.childNodes.background.style.opacity = backgroundOpacity;\n        this.childNodes.background.style.backgroundRepeat = backgroundRepeat;\n        this.childNodes.background.style.backgroundImage = `url(${backgroundImage})`;\n\n        this.updateBackgroundImage(opt);\n    },\n\n    updateBackgroundColor: function(color) {\n\n        this.$el.css('backgroundColor', color || '');\n    },\n\n    drawBackground: function(opt) {\n\n        opt = opt || {};\n\n        this.updateBackgroundColor(opt.color);\n\n        if (opt.image) {\n            opt = this._background = cloneDeep(opt);\n            guid(opt);\n            var img = document.createElement('img');\n            img.onload = this.drawBackgroundImage.bind(this, img, opt);\n            img.src = opt.image;\n        } else {\n            this.drawBackgroundImage(null);\n            this._background = null;\n        }\n\n        return this;\n    },\n\n    setInteractivity: function(value) {\n\n        this.options.interactive = value;\n\n        invoke(this._views, 'setInteractivity', value);\n    },\n\n    // Paper definitions.\n    // ------------------\n\n    isDefined: function(defId) {\n\n        return !!this.svg.getElementById(defId);\n    },\n\n    defineFilter: function(filter) {\n\n        if (!isObject(filter)) {\n            throw new TypeError('dia.Paper: defineFilter() requires 1. argument to be an object.');\n        }\n\n        var filterId = filter.id;\n        var name = filter.name;\n        // Generate a hash code from the stringified filter definition. This gives us\n        // a unique filter ID for different definitions.\n        if (!filterId) {\n            filterId = name + this.svg.id + hashCode(JSON.stringify(filter));\n        }\n        // If the filter already exists in the document,\n        // we're done and we can just use it (reference it using `url()`).\n        // If not, create one.\n        if (!this.isDefined(filterId)) {\n\n            var namespace = _filter;\n            var filterSVGString = namespace[name] && namespace[name](filter.args || {});\n            if (!filterSVGString) {\n                throw new Error('Non-existing filter ' + name);\n            }\n\n            // SVG <filter/> attributes\n            var filterAttrs = assign({\n                filterUnits: 'userSpaceOnUse',\n            }, filter.attrs, {\n                id: filterId\n            });\n\n            V(filterSVGString, filterAttrs).appendTo(this.defs);\n        }\n\n        return filterId;\n    },\n\n    defineGradient: function(gradient) {\n        if (!isObject(gradient)) {\n            throw new TypeError('dia.Paper: defineGradient() requires 1. argument to be an object.');\n        }\n        const { svg, defs } = this;\n        const {\n            type,\n            // Generate a hash code from the stringified filter definition. This gives us\n            // a unique filter ID for different definitions.\n            id = type + svg.id + hashCode(JSON.stringify(gradient)),\n            stops,\n            attrs = {}\n        } = gradient;\n        // If the gradient already exists in the document,\n        // we're done and we can just use it (reference it using `url()`).\n        if (this.isDefined(id)) return id;\n        // If not, create one.\n        const stopVEls = toArray(stops).map(({ offset, color, opacity }) => {\n            return V('stop').attr({\n                'offset': offset,\n                'stop-color': color,\n                'stop-opacity': Number.isFinite(opacity) ? opacity : 1\n            });\n        });\n        const gradientVEl = V(type, attrs, stopVEls);\n        gradientVEl.id = id;\n        gradientVEl.appendTo(defs);\n        return id;\n    },\n\n    definePattern: function(pattern) {\n        if (!isObject(pattern)) {\n            throw new TypeError('dia.Paper: definePattern() requires 1. argument to be an object.');\n        }\n        const { svg, defs } = this;\n        const {\n            // Generate a hash code from the stringified filter definition. This gives us\n            // a unique filter ID for different definitions.\n            id = svg.id + hashCode(JSON.stringify(pattern)),\n            markup,\n            attrs = {}\n        } = pattern;\n        if (!markup) {\n            throw new TypeError('dia.Paper: definePattern() requires markup.');\n        }\n        // If the gradient already exists in the document,\n        // we're done and we can just use it (reference it using `url()`).\n        if (this.isDefined(id)) return id;\n        // If not, create one.\n        const patternVEl = V('pattern', {\n            patternUnits: 'userSpaceOnUse'\n        });\n        patternVEl.id = id;\n        patternVEl.attr(attrs);\n        if (typeof markup === 'string') {\n            patternVEl.append(V(markup));\n        } else {\n            const { fragment } = parseDOMJSON(markup);\n            patternVEl.append(fragment);\n        }\n        patternVEl.appendTo(defs);\n        return id;\n    },\n\n    defineMarker: function(marker) {\n        if (!isObject(marker)) {\n            throw new TypeError('dia.Paper: defineMarker() requires the first argument to be an object.');\n        }\n        const { svg, defs } = this;\n        const {\n            // Generate a hash code from the stringified filter definition. This gives us\n            // a unique filter ID for different definitions.\n            id = svg.id + hashCode(JSON.stringify(marker)),\n            // user-provided markup\n            // (e.g. defined when creating link via `attrs/line/sourceMarker/markup`)\n            markup,\n            // user-provided attributes\n            // (e.g. defined when creating link via `attrs/line/sourceMarker/attrs`)\n            // note: `transform` attrs are ignored by browsers\n            attrs = {},\n            // deprecated - use `attrs/markerUnits` instead (which has higher priority)\n            markerUnits = 'userSpaceOnUse'\n        } = marker;\n        // If the marker already exists in the document,\n        // we're done and we can just use it (reference it using `url()`).\n        if (this.isDefined(id)) return id;\n        // If not, create one.\n        const markerVEl = V('marker', {\n            orient: 'auto',\n            overflow: 'visible',\n            markerUnits: markerUnits\n        });\n        markerVEl.id = id;\n        markerVEl.attr(attrs);\n        let markerContentVEl;\n        if (markup) {\n            let markupVEl;\n            if (typeof markup === 'string') {\n                // Marker object has a `markup` property of type string.\n                // - Construct V from the provided string.\n                markupVEl = V(markup);\n                // `markupVEl` is now either a single VEl, or an array of VEls.\n                // - Coerce it to an array.\n                markupVEl = (Array.isArray(markupVEl) ? markupVEl : [markupVEl]);\n            } else {\n                // Marker object has a `markup` property of type object.\n                // - Construct V from the object by parsing it as DOM JSON.\n                const { fragment } = parseDOMJSON(markup);\n                markupVEl = V(fragment).children();\n            }\n            // `markupVEl` is an array with one or more VEls inside.\n            // - If there are multiple VEls, wrap them in a newly-constructed <g> element\n            if (markupVEl.length > 1) {\n                markerContentVEl = V('g').append(markupVEl);\n            } else {\n                markerContentVEl = markupVEl[0];\n            }\n        } else {\n            // Marker object is a flat structure.\n            // - Construct a new V of type `marker.type`.\n            const { type = 'path' } = marker;\n            markerContentVEl = V(type);\n        }\n        // `markerContentVEl` is a single VEl.\n        // Assign additional attributes to it (= context attributes + marker attributes):\n        // - Attribute values are taken from non-special properties of `marker`.\n        const markerAttrs = omit(marker, 'type', 'id', 'markup', 'attrs', 'markerUnits');\n        const markerAttrsKeys = Object.keys(markerAttrs);\n        markerAttrsKeys.forEach((key) => {\n            const value = markerAttrs[key];\n            const markupValue = markerContentVEl.attr(key); // value coming from markupVEl (if any) = higher priority\n            if (markupValue == null) {\n                // Default logic:\n                markerContentVEl.attr(key, value);\n            } else {\n                // Properties with special logic should be added as cases to this switch block:\n                switch(key) {\n                    case 'transform':\n                        // - Prepend `transform` to existing value.\n                        markerContentVEl.attr(key, (value + ' ' + markupValue));\n                        break;\n                }\n            }\n        });\n        markerContentVEl.appendTo(markerVEl);\n        markerVEl.appendTo(defs);\n        return id;\n    },\n\n    customEventTrigger: function(evt, view, rootNode = view.el) {\n\n        const eventNode = evt.target.closest('[event]');\n\n        if (eventNode && rootNode !== eventNode && view.el.contains(eventNode)) {\n            const eventEvt = normalizeEvent(new $.Event(evt.originalEvent, {\n                data: evt.data,\n                // Originally the event listener was attached to the event element.\n                currentTarget: eventNode\n            }));\n\n            this.onevent(eventEvt);\n\n            if (eventEvt.isDefaultPrevented()) {\n                evt.preventDefault();\n            }\n\n            return eventEvt;\n        }\n\n        return null;\n    }\n\n}, {\n\n    sorting: sortingTypes,\n\n    Layers: LayersNames,\n\n    backgroundPatterns: {\n\n        flipXy: function(img) {\n            // d b\n            // q p\n\n            var canvas = document.createElement('canvas');\n            var imgWidth = img.width;\n            var imgHeight = img.height;\n\n            canvas.width = 2 * imgWidth;\n            canvas.height = 2 * imgHeight;\n\n            var ctx = canvas.getContext('2d');\n            // top-left image\n            ctx.drawImage(img, 0, 0, imgWidth, imgHeight);\n            // xy-flipped bottom-right image\n            ctx.setTransform(-1, 0, 0, -1, canvas.width, canvas.height);\n            ctx.drawImage(img, 0, 0, imgWidth, imgHeight);\n            // x-flipped top-right image\n            ctx.setTransform(-1, 0, 0, 1, canvas.width, 0);\n            ctx.drawImage(img, 0, 0, imgWidth, imgHeight);\n            // y-flipped bottom-left image\n            ctx.setTransform(1, 0, 0, -1, 0, canvas.height);\n            ctx.drawImage(img, 0, 0, imgWidth, imgHeight);\n\n            return canvas;\n        },\n\n        flipX: function(img) {\n            // d b\n            // d b\n\n            var canvas = document.createElement('canvas');\n            var imgWidth = img.width;\n            var imgHeight = img.height;\n\n            canvas.width = imgWidth * 2;\n            canvas.height = imgHeight;\n\n            var ctx = canvas.getContext('2d');\n            // left image\n            ctx.drawImage(img, 0, 0, imgWidth, imgHeight);\n            // flipped right image\n            ctx.translate(2 * imgWidth, 0);\n            ctx.scale(-1, 1);\n            ctx.drawImage(img, 0, 0, imgWidth, imgHeight);\n\n            return canvas;\n        },\n\n        flipY: function(img) {\n            // d d\n            // q q\n\n            var canvas = document.createElement('canvas');\n            var imgWidth = img.width;\n            var imgHeight = img.height;\n\n            canvas.width = imgWidth;\n            canvas.height = imgHeight * 2;\n\n            var ctx = canvas.getContext('2d');\n            // top image\n            ctx.drawImage(img, 0, 0, imgWidth, imgHeight);\n            // flipped bottom image\n            ctx.translate(0, 2 * imgHeight);\n            ctx.scale(1, -1);\n            ctx.drawImage(img, 0, 0, imgWidth, imgHeight);\n\n            return canvas;\n        },\n\n        watermark: function(img, opt) {\n            //   d\n            // d\n\n            opt = opt || {};\n\n            var imgWidth = img.width;\n            var imgHeight = img.height;\n\n            var canvas = document.createElement('canvas');\n            canvas.width = imgWidth * 3;\n            canvas.height = imgHeight * 3;\n\n            var ctx = canvas.getContext('2d');\n            var angle = isNumber(opt.watermarkAngle) ? -opt.watermarkAngle : -20;\n            var radians = toRad(angle);\n            var stepX = canvas.width / 4;\n            var stepY = canvas.height / 4;\n\n            for (var i = 0; i < 4; i++) {\n                for (var j = 0; j < 4; j++) {\n                    if ((i + j) % 2 > 0) {\n                        // reset the current transformations\n                        ctx.setTransform(1, 0, 0, 1, (2 * i - 1) * stepX, (2 * j - 1) * stepY);\n                        ctx.rotate(radians);\n                        ctx.drawImage(img, -imgWidth / 2, -imgHeight / 2, imgWidth, imgHeight);\n                    }\n                }\n            }\n\n            return canvas;\n        }\n    },\n\n    gridPatterns: {\n        dot: [{\n            color: '#AAAAAA',\n            thickness: 1,\n            markup: 'rect',\n            render: function(el, opt) {\n                V(el).attr({\n                    width: opt.thickness,\n                    height: opt.thickness,\n                    fill: opt.color\n                });\n            }\n        }],\n        fixedDot: [{\n            color: '#AAAAAA',\n            thickness: 1,\n            markup: 'rect',\n            render: function(el, opt) {\n                V(el).attr({ fill: opt.color });\n            },\n            update: function(el, opt, paper) {\n                const { sx, sy } = paper.scale();\n                const width = sx <= 1 ? opt.thickness : opt.thickness / sx;\n                const height = sy <= 1 ? opt.thickness : opt.thickness / sy;\n                V(el).attr({ width, height });\n            }\n        }],\n        mesh: [{\n            color: '#AAAAAA',\n            thickness: 1,\n            markup: 'path',\n            render: function(el, opt) {\n\n                var d;\n                var width = opt.width;\n                var height = opt.height;\n                var thickness = opt.thickness;\n\n                if (width - thickness >= 0 && height - thickness >= 0) {\n                    d = ['M', width, 0, 'H0 M0 0 V0', height].join(' ');\n                } else {\n                    d = 'M 0 0 0 0';\n                }\n\n                V(el).attr({ 'd': d, stroke: opt.color, 'stroke-width': opt.thickness });\n            }\n        }],\n        doubleMesh: [{\n            color: '#AAAAAA',\n            thickness: 1,\n            markup: 'path',\n            render: function(el, opt) {\n\n                var d;\n                var width = opt.width;\n                var height = opt.height;\n                var thickness = opt.thickness;\n\n                if (width - thickness >= 0 && height - thickness >= 0) {\n                    d = ['M', width, 0, 'H0 M0 0 V0', height].join(' ');\n                } else {\n                    d = 'M 0 0 0 0';\n                }\n\n                V(el).attr({ 'd': d, stroke: opt.color, 'stroke-width': opt.thickness });\n            }\n        }, {\n            color: '#000000',\n            thickness: 3,\n            scaleFactor: 4,\n            markup: 'path',\n            render: function(el, opt) {\n\n                var d;\n                var width = opt.width;\n                var height = opt.height;\n                var thickness = opt.thickness;\n\n                if (width - thickness >= 0 && height - thickness >= 0) {\n                    d = ['M', width, 0, 'H0 M0 0 V0', height].join(' ');\n                } else {\n                    d = 'M 0 0 0 0';\n                }\n\n                V(el).attr({ 'd': d, stroke: opt.color, 'stroke-width': opt.thickness });\n            }\n        }]\n    }\n});\n\n","import * as mvc from '../mvc/index.mjs';\n\nexport const ToolView = mvc.View.extend({\n    name: null,\n    tagName: 'g',\n    className: 'tool',\n    svgElement: true,\n    _visible: true,\n    _visibleExplicit: true,\n\n    init: function() {\n        var name = this.name;\n        if (name) this.vel.attr('data-tool-name', name);\n    },\n\n    configure: function(view, toolsView) {\n        this.relatedView = view;\n        this.paper = view.paper;\n        this.parentView = toolsView;\n        this.simulateRelatedView(this.el);\n        // Delegate events in case the ToolView was removed from the DOM and reused.\n        this.delegateEvents();\n        return this;\n    },\n\n    simulateRelatedView: function(el) {\n        if (el) el.setAttribute('model-id', this.relatedView.model.id);\n    },\n\n    getName: function() {\n        return this.name;\n    },\n\n    // Evaluate the visibility of the tool and update the `display` CSS property\n    updateVisibility: function() {\n        const isVisible = this.computeVisibility();\n        this.el.style.display = isVisible ? '' : 'none';\n        this._visible = isVisible;\n    },\n\n    // Evaluate the visibility of the tool. The method returns `true` if the tool\n    // should be visible in the DOM.\n    computeVisibility() {\n        if (!this.isExplicitlyVisible()) return false;\n        const { visibility } = this.options;\n        if (typeof visibility !== 'function') return true;\n        return !!visibility.call(this, this.relatedView, this);\n    },\n\n    show: function() {\n        this._visibleExplicit = true;\n        this.updateVisibility();\n    },\n\n    hide: function() {\n        this._visibleExplicit = false;\n        this.updateVisibility();\n    },\n\n    // The method returns `false` if the `hide()` method was called on the tool.\n    isExplicitlyVisible: function() {\n        return !!this._visibleExplicit;\n    },\n\n    // The method returns `false` if the tool is not visible (it has `display: none`).\n    // This can happen if the `hide()` method was called or the tool is not visible\n    // because of the `visibility` option was evaluated to `false`.\n    isVisible: function() {\n        return !!this._visible;\n    },\n\n    focus: function() {\n        var opacity = this.options.focusOpacity;\n        if (isFinite(opacity)) this.el.style.opacity = opacity;\n        this.parentView.focusTool(this);\n    },\n\n    blur: function() {\n        this.el.style.opacity = '';\n        this.parentView.blurTool(this);\n    },\n\n    update: function() {\n        // to be overridden\n    },\n\n    guard: function(evt) {\n        // Let the context-menu event bubble up to the relatedView\n        const { paper, relatedView } = this;\n        if (!paper || !relatedView) return true;\n        return paper.guard(evt, relatedView);\n    }\n});\n\n","import * as g from '../g/index.mjs';\nimport * as util from '../util/index.mjs';\nimport * as mvc from '../mvc/index.mjs';\nimport { ToolView } from '../dia/ToolView.mjs';\nimport V from '../V/index.mjs';\n\n\n// Vertex Handles\nvar VertexHandle = mvc.View.extend({\n    tagName: 'circle',\n    svgElement: true,\n    className: 'marker-vertex',\n    events: {\n        mousedown: 'onPointerDown',\n        touchstart: 'onPointerDown',\n        dblclick: 'onDoubleClick',\n        dbltap: 'onDoubleClick'\n    },\n    documentEvents: {\n        mousemove: 'onPointerMove',\n        touchmove: 'onPointerMove',\n        mouseup: 'onPointerUp',\n        touchend: 'onPointerUp',\n        touchcancel: 'onPointerUp'\n    },\n    attributes: {\n        'r': 6,\n        'fill': '#33334F',\n        'stroke': '#FFFFFF',\n        'stroke-width': 2,\n        'cursor': 'move'\n    },\n    position: function(x, y) {\n        const { vel, options } = this;\n        const { scale } = options;\n        let matrix = V.createSVGMatrix().translate(x, y);\n        if (scale) matrix = matrix.scale(scale);\n        vel.transform(matrix, { absolute: true });\n    },\n    onPointerDown: function(evt) {\n        if (this.options.guard(evt)) return;\n        evt.stopPropagation();\n        evt.preventDefault();\n        this.options.paper.undelegateEvents();\n        this.delegateDocumentEvents(null, evt.data);\n        this.trigger('will-change', this, evt);\n    },\n    onPointerMove: function(evt) {\n        this.trigger('changing', this, evt);\n    },\n    onDoubleClick: function(evt) {\n        this.trigger('remove', this, evt);\n    },\n    onPointerUp: function(evt) {\n        this.trigger('changed', this, evt);\n        this.undelegateDocumentEvents();\n        this.options.paper.delegateEvents();\n    }\n});\n\nexport const Vertices = ToolView.extend({\n    name: 'vertices',\n    options: {\n        handleClass: VertexHandle,\n        snapRadius: 20,\n        redundancyRemoval: true,\n        vertexAdding: true,\n        // vertexRemoving: true,\n        // vertexMoving: true,\n        stopPropagation: true,\n        scale: null\n    },\n    children: [{\n        tagName: 'path',\n        selector: 'connection',\n        className: 'joint-vertices-path',\n        attributes: {\n            'fill': 'none',\n            'stroke': 'transparent',\n            'stroke-width': 10,\n            'cursor': 'cell'\n        }\n    }],\n    handles: null,\n    interactiveLinkNode: null,\n    events: {\n        'mousedown .joint-vertices-path': 'onPathPointerDown',\n        'touchstart .joint-vertices-path': 'onPathPointerDown'\n    },\n    linkEvents: {\n        mousedown: 'onLinkPointerDown',\n        touchstart: 'onLinkPointerDown'\n    },\n    onRender: function() {\n        const { vertexAdding } = this.options;\n        if (vertexAdding) {\n            const { interactiveLinkNode = null } = vertexAdding;\n            if (interactiveLinkNode) {\n                this.delegateLinkEvents(interactiveLinkNode);\n            } else {\n                this.renderChildren();\n                this.updatePath();\n            }\n        }\n        this.resetHandles();\n        this.renderHandles();\n        return this;\n    },\n    delegateLinkEvents: function(selector) {\n        this.undelegateLinkEvents();\n        const el = this.relatedView.findNode(selector);\n        if (!el) {\n            console.warn(`Interactive link node \"${selector}\" not found.`);\n            return;\n        }\n        el.classList.add('joint-vertices-path');\n        this.interactiveLinkNode = el;\n        this.delegateElementEvents(el, this.linkEvents);\n    },\n    undelegateLinkEvents: function() {\n        const el = this.interactiveLinkNode;\n        if (!el) return;\n        this.undelegateElementEvents(el);\n        el.classList.remove('joint-vertices-path');\n        this.interactiveLinkNode = null;\n    },\n    update: function() {\n        var relatedView = this.relatedView;\n        var vertices = relatedView.model.vertices();\n        if (vertices.length === this.handles.length) {\n            this.updateHandles();\n        } else {\n            this.resetHandles();\n            this.renderHandles();\n        }\n        if (this.options.vertexAdding) {\n            this.updatePath();\n        }\n        return this;\n    },\n    resetHandles: function() {\n        var handles = this.handles;\n        this.handles = [];\n        this.stopListening();\n        if (!Array.isArray(handles)) return;\n        for (var i = 0, n = handles.length; i < n; i++) {\n            handles[i].remove();\n        }\n    },\n    renderHandles: function() {\n        var relatedView = this.relatedView;\n        var vertices = relatedView.model.vertices();\n        for (var i = 0, n = vertices.length; i < n; i++) {\n            var vertex = vertices[i];\n            var handle = new (this.options.handleClass)({\n                index: i,\n                paper: this.paper,\n                scale: this.options.scale,\n                guard: evt => this.guard(evt)\n            });\n            handle.render();\n            handle.position(vertex.x, vertex.y);\n            this.simulateRelatedView(handle.el);\n            handle.vel.appendTo(this.el);\n            this.handles.push(handle);\n            this.startHandleListening(handle);\n        }\n    },\n    updateHandles: function() {\n        var relatedView = this.relatedView;\n        var vertices = relatedView.model.vertices();\n        for (var i = 0, n = vertices.length; i < n; i++) {\n            var vertex = vertices[i];\n            var handle = this.handles[i];\n            if (!handle) return;\n            handle.position(vertex.x, vertex.y);\n        }\n    },\n    updatePath: function() {\n        if (this.interactiveLinkNode) return;\n        const connection = this.childNodes.connection;\n        if (connection) connection.setAttribute('d', this.relatedView.getSerializedConnection());\n    },\n    startHandleListening: function(handle) {\n        const { vertexRemoving = true, vertexMoving = true } = this.options;\n        if (vertexMoving) {\n            this.listenTo(handle, 'will-change', this.onHandleWillChange);\n            this.listenTo(handle, 'changing', this.onHandleChanging);\n            this.listenTo(handle, 'changed', this.onHandleChanged);\n        }\n        if (vertexRemoving) {\n            this.listenTo(handle, 'remove', this.onHandleRemove);\n        }\n    },\n    getNeighborPoints: function(index) {\n        var linkView = this.relatedView;\n        var vertices = linkView.model.vertices();\n        var prev = (index > 0) ? vertices[index - 1] : linkView.sourceAnchor;\n        var next = (index < vertices.length - 1) ? vertices[index + 1] : linkView.targetAnchor;\n        return {\n            prev: new g.Point(prev),\n            next: new g.Point(next)\n        };\n    },\n    onHandleWillChange: function(_handle, evt) {\n        this.focus();\n        const { relatedView, options } = this;\n        relatedView.model.startBatch('vertex-move', { ui: true, tool: this.cid });\n        if (!options.stopPropagation) relatedView.notifyPointerdown(...relatedView.paper.getPointerArgs(evt));\n    },\n    onHandleChanging: function(handle, evt) {\n        const { options, relatedView: linkView } = this;\n        var index = handle.options.index;\n        var [normalizedEvent, x, y] = linkView.paper.getPointerArgs(evt);\n        var vertex = { x, y };\n        this.snapVertex(vertex, index);\n        linkView.model.vertex(index, vertex, { ui: true, tool: this.cid });\n        handle.position(vertex.x, vertex.y);\n        if (!options.stopPropagation) linkView.notifyPointermove(normalizedEvent, x, y);\n    },\n    onHandleChanged: function(_handle, evt) {\n        const { options, relatedView: linkView } = this;\n        if (options.vertexAdding) this.updatePath();\n        if (!options.redundancyRemoval) {\n            linkView.checkMouseleave(util.normalizeEvent(evt));\n            return;\n        }\n        var verticesRemoved = linkView.removeRedundantLinearVertices({ ui: true, tool: this.cid });\n        if (verticesRemoved) this.render();\n        this.blur();\n        linkView.model.stopBatch('vertex-move', { ui: true, tool: this.cid });\n        if (this.eventData(evt).vertexAdded) {\n            linkView.model.stopBatch('vertex-add', { ui: true, tool: this.cid });\n        }\n        var [normalizedEvt, x, y] = linkView.paper.getPointerArgs(evt);\n        if (!options.stopPropagation) linkView.notifyPointerup(normalizedEvt, x, y);\n        linkView.checkMouseleave(normalizedEvt);\n    },\n    snapVertex: function(vertex, index) {\n        var snapRadius = this.options.snapRadius;\n        if (snapRadius > 0) {\n            var neighbors = this.getNeighborPoints(index);\n            var prev = neighbors.prev;\n            var next = neighbors.next;\n            if (Math.abs(vertex.x - prev.x) < snapRadius) {\n                vertex.x = prev.x;\n            } else if (Math.abs(vertex.x - next.x) < snapRadius) {\n                vertex.x = next.x;\n            }\n            if (Math.abs(vertex.y - prev.y) < snapRadius) {\n                vertex.y = neighbors.prev.y;\n            } else if (Math.abs(vertex.y - next.y) < snapRadius) {\n                vertex.y = next.y;\n            }\n        }\n    },\n    onHandleRemove: function(handle, evt) {\n        var index = handle.options.index;\n        var linkView = this.relatedView;\n        linkView.model.removeVertex(index, { ui: true });\n        if (this.options.vertexAdding) this.updatePath();\n        linkView.checkMouseleave(util.normalizeEvent(evt));\n    },\n    onPathPointerDown: function(evt) {\n        if (this.guard(evt)) return;\n        evt.stopPropagation();\n        evt.preventDefault();\n        var normalizedEvent = util.normalizeEvent(evt);\n        var vertex = this.paper.snapToGrid(normalizedEvent.clientX, normalizedEvent.clientY).toJSON();\n        var relatedView = this.relatedView;\n        relatedView.model.startBatch('vertex-add', { ui: true, tool: this.cid });\n        var index = relatedView.getVertexIndex(vertex.x, vertex.y);\n        this.snapVertex(vertex, index);\n        relatedView.model.insertVertex(index, vertex, { ui: true, tool: this.cid });\n        this.update();\n        var handle = this.handles[index];\n        this.eventData(normalizedEvent, { vertexAdded: true });\n        handle.onPointerDown(normalizedEvent);\n    },\n    onLinkPointerDown: function(evt) {\n        this.relatedView.preventDefaultInteraction(evt);\n        this.onPathPointerDown(evt);\n    },\n    onRemove: function() {\n        this.resetHandles();\n        this.undelegateLinkEvents();\n    }\n}, {\n    VertexHandle: VertexHandle // keep as class property\n});\n","import * as util from '../util/index.mjs';\n\nfunction abs2rel(absolute, max) {\n\n    if (max === 0) return '0%';\n    // round to 3 decimal places\n    const dp = 1000;\n    const relative = Math.round(absolute / max * 100 * dp) / dp;\n    return `${relative}%`;\n}\n\nfunction pin(relative) {\n\n    return function(end, view, magnet, coords) {\n        var fn = (view.isNodeConnection(magnet)) ? pinnedLinkEnd : pinnedElementEnd;\n        return fn(relative, end, view, magnet, coords);\n    };\n}\n\nfunction pinnedElementEnd(relative, end, view, magnet, coords) {\n\n    var angle = view.model.angle();\n    var bbox = view.getNodeUnrotatedBBox(magnet);\n    var origin = view.model.getBBox().center();\n    coords.rotate(origin, angle);\n    var dx = coords.x - bbox.x;\n    var dy = coords.y - bbox.y;\n\n    if (relative) {\n        dx = abs2rel(dx, bbox.width);\n        dy = abs2rel(dy, bbox.height);\n    }\n\n    end.anchor = {\n        name: 'topLeft',\n        args: {\n            dx: dx,\n            dy: dy,\n            rotate: true\n        }\n    };\n\n    return end;\n}\n\nfunction pinnedLinkEnd(relative, end, view, _magnet, coords) {\n\n    var connection = view.getConnection();\n    if (!connection) return end;\n    var length = connection.closestPointLength(coords);\n    if (relative) {\n        var totalLength = connection.length();\n        end.anchor = {\n            name: 'connectionRatio',\n            args: {\n                ratio: length / totalLength\n            }\n        };\n    } else {\n        end.anchor = {\n            name: 'connectionLength',\n            args: {\n                length: length\n            }\n        };\n    }\n    return end;\n}\n\nexport const useDefaults = util.noop;\nexport const pinAbsolute = pin(false);\nexport const pinRelative = pin(true);\n\n","import * as g from '../g/index.mjs';\nimport V from '../V/index.mjs';\nimport * as util from '../util/index.mjs';\nimport * as mvc from '../mvc/index.mjs';\nimport { ToolView } from '../dia/ToolView.mjs';\nimport { getAnchor } from '../cellTools/helpers.mjs';\n\nvar SegmentHandle = mvc.View.extend({\n    tagName: 'g',\n    svgElement: true,\n    className: 'marker-segment',\n    events: {\n        mousedown: 'onPointerDown',\n        touchstart: 'onPointerDown'\n    },\n    documentEvents: {\n        mousemove: 'onPointerMove',\n        touchmove: 'onPointerMove',\n        mouseup: 'onPointerUp',\n        touchend: 'onPointerUp',\n        touchcancel: 'onPointerUp'\n    },\n    children: [{\n        tagName: 'line',\n        selector: 'line',\n        attributes: {\n            'stroke': '#33334F',\n            'stroke-width': 2,\n            'fill': 'none',\n            'pointer-events': 'none'\n        }\n    }, {\n        tagName: 'rect',\n        selector: 'handle',\n        attributes: {\n            'width': 20,\n            'height': 8,\n            'x': -10,\n            'y': -4,\n            'rx': 4,\n            'ry': 4,\n            'fill': '#33334F',\n            'stroke': '#FFFFFF',\n            'stroke-width': 2\n        }\n    }],\n    onRender: function() {\n        this.renderChildren();\n    },\n    position: function(x, y, angle, view) {\n        const { scale } = this.options;\n        let matrix = V.createSVGMatrix().translate(x, y).rotate(angle);\n        if (scale) matrix = matrix.scale(scale);\n\n        var handle = this.childNodes.handle;\n        handle.setAttribute('transform', V.matrixToTransformString(matrix));\n        handle.setAttribute('cursor', (angle % 180 === 0) ? 'row-resize' : 'col-resize');\n\n        var viewPoint = view.getClosestPoint(new g.Point(x, y));\n        var line = this.childNodes.line;\n        line.setAttribute('x1', x);\n        line.setAttribute('y1', y);\n        line.setAttribute('x2', viewPoint.x);\n        line.setAttribute('y2', viewPoint.y);\n    },\n    onPointerDown: function(evt) {\n        if (this.options.guard(evt)) return;\n        this.trigger('change:start', this, evt);\n        evt.stopPropagation();\n        evt.preventDefault();\n        this.options.paper.undelegateEvents();\n        this.delegateDocumentEvents(null, evt.data);\n    },\n    onPointerMove: function(evt) {\n        this.trigger('changing', this, evt);\n    },\n    onPointerUp: function(evt) {\n        this.undelegateDocumentEvents();\n        this.options.paper.delegateEvents();\n        this.trigger('change:end', this, evt);\n    },\n    show: function() {\n        this.el.style.display = '';\n    },\n    hide: function() {\n        this.el.style.display = 'none';\n    }\n});\n\nexport const Segments = ToolView.extend({\n    name: 'segments',\n    precision: .5,\n    options: {\n        handleClass: SegmentHandle,\n        segmentLengthThreshold: 40,\n        redundancyRemoval: true,\n        anchor: getAnchor,\n        snapRadius: 10,\n        snapHandle: true,\n        stopPropagation: true\n    },\n    handles: null,\n    onRender: function() {\n        this.resetHandles();\n        var relatedView = this.relatedView;\n        var vertices = relatedView.model.vertices();\n        vertices.unshift(relatedView.sourcePoint);\n        vertices.push(relatedView.targetPoint);\n        for (var i = 0, n = vertices.length; i < n - 1; i++) {\n            var vertex = vertices[i];\n            var nextVertex = vertices[i + 1];\n            var handle = this.renderHandle(vertex, nextVertex);\n            this.simulateRelatedView(handle.el);\n            this.handles.push(handle);\n            handle.options.index = i;\n        }\n        return this;\n    },\n    renderHandle: function(vertex, nextVertex) {\n        var handle = new (this.options.handleClass)({\n            paper: this.paper,\n            scale: this.options.scale,\n            guard: evt => this.guard(evt)\n        });\n        handle.render();\n        this.updateHandle(handle, vertex, nextVertex);\n        handle.vel.appendTo(this.el);\n        this.startHandleListening(handle);\n        return handle;\n    },\n    update: function() {\n        this.render();\n        return this;\n    },\n    startHandleListening: function(handle) {\n        this.listenTo(handle, 'change:start', this.onHandleChangeStart);\n        this.listenTo(handle, 'changing', this.onHandleChanging);\n        this.listenTo(handle, 'change:end', this.onHandleChangeEnd);\n    },\n    resetHandles: function() {\n        var handles = this.handles;\n        this.handles = [];\n        this.stopListening();\n        if (!Array.isArray(handles)) return;\n        for (var i = 0, n = handles.length; i < n; i++) {\n            handles[i].remove();\n        }\n    },\n    shiftHandleIndexes: function(value) {\n        var handles = this.handles;\n        for (var i = 0, n = handles.length; i < n; i++) handles[i].options.index += value;\n    },\n    resetAnchor: function(type, anchor) {\n        var relatedModel = this.relatedView.model;\n        if (anchor) {\n            relatedModel.prop([type, 'anchor'], anchor, {\n                rewrite: true,\n                ui: true,\n                tool: this.cid\n            });\n        } else {\n            relatedModel.removeProp([type, 'anchor'], {\n                ui: true,\n                tool: this.cid\n            });\n        }\n    },\n    snapHandle: function(handle, position, data) {\n\n        var index = handle.options.index;\n        var linkView = this.relatedView;\n        var link = linkView.model;\n        var vertices = link.vertices();\n        var axis = handle.options.axis;\n        var prev = vertices[index - 2] || data.sourceAnchor;\n        var next = vertices[index + 1] || data.targetAnchor;\n        var snapRadius = this.options.snapRadius;\n        if (Math.abs(position[axis] - prev[axis]) < snapRadius) {\n            position[axis] = prev[axis];\n        } else if (Math.abs(position[axis] - next[axis]) < snapRadius) {\n            position[axis] = next[axis];\n        }\n        return position;\n    },\n\n    onHandleChanging: function(handle, evt) {\n\n        const { options } = this;\n        var data = this.eventData(evt);\n        var relatedView = this.relatedView;\n        var paper = relatedView.paper;\n        var index = handle.options.index - 1;\n        var normalizedEvent = util.normalizeEvent(evt);\n        var coords = paper.snapToGrid(normalizedEvent.clientX, normalizedEvent.clientY);\n        var position = this.snapHandle(handle, coords.clone(), data);\n        var axis = handle.options.axis;\n        var offset = (this.options.snapHandle) ? 0 : (coords[axis] - position[axis]);\n        var link = relatedView.model;\n        var vertices = util.cloneDeep(link.vertices());\n        var anchorFn = this.options.anchor;\n        if (typeof anchorFn !== 'function') anchorFn = null;\n\n        const handleIndex = handle.options.index;\n\n        const vertexPoints = [relatedView.sourcePoint.clone(), ...vertices, relatedView.targetPoint.clone()];\n        let indexOffset = 0;\n\n        // check if vertex before handle vertex exists\n        if (handleIndex - 1 >= 0) {\n            const v1 = vertexPoints[handleIndex - 1];\n            const v2 = vertexPoints[handleIndex];\n\n            const theta = new g.Line(v1, v2).vector().theta();\n\n            // check only non-orthogonal segments\n            if (theta % 90 !== 0) {\n                vertices.splice(handleIndex - 1, 0, data.originalVertices[handleIndex - 1]);\n                indexOffset++;\n                this.shiftHandleIndexes(1);\n            }\n        }\n\n        var vertex = vertices[index + indexOffset];\n        var nextVertex = vertices[index + 1 + indexOffset];\n\n        // check if vertex after handle vertex exists\n        if (handleIndex + 2 < vertexPoints.length) {\n            const v1 = vertexPoints[handleIndex + 1];\n            const v2 = vertexPoints[handleIndex + 2];\n\n            const theta = new g.Line(v1, v2).vector().theta();\n\n            // check only non-orthogonal segments\n            if (theta % 90 !== 0) {\n                const isSingleVertex = data.originalVertices.length === 1;\n                const origVIndex = isSingleVertex ? 0 : handleIndex;\n                const additionalOffset = data.firstHandleShifted && !isSingleVertex ? 1 : 0;\n                let nextVIndex = 1 + indexOffset;\n                vertices.splice(handleIndex + nextVIndex, 0, data.originalVertices[origVIndex - additionalOffset]);\n            }\n        }\n\n        // First Segment\n        var sourceView = relatedView.sourceView;\n        var sourceBBox = relatedView.sourceBBox;\n        var changeSourceAnchor = false;\n        var deleteSourceAnchor = false;\n        if (!vertex) {\n            vertex = relatedView.sourceAnchor.toJSON();\n            vertex[axis] = position[axis];\n            if (sourceBBox.containsPoint(vertex)) {\n                vertex[axis] = position[axis];\n                changeSourceAnchor = true;\n            } else {\n                // we left the area of the source magnet for the first time\n                vertices.unshift(vertex);\n                this.shiftHandleIndexes(1);\n                data.firstHandleShifted = true;\n                deleteSourceAnchor = true;\n            }\n        } else if (index === 0) {\n            if (sourceBBox.containsPoint(vertex)) {\n                vertices.shift();\n                this.shiftHandleIndexes(-1);\n                changeSourceAnchor = true;\n            } else {\n                vertex[axis] = position[axis];\n                deleteSourceAnchor = true;\n            }\n        } else {\n            vertex[axis] = position[axis];\n        }\n\n        if (anchorFn && sourceView) {\n            if (changeSourceAnchor) {\n                var sourceAnchorPosition = data.sourceAnchor.clone();\n                sourceAnchorPosition[axis] = position[axis];\n                var sourceAnchor = anchorFn.call(relatedView, sourceAnchorPosition, sourceView, relatedView.sourceMagnet || sourceView.el, 'source', relatedView);\n                this.resetAnchor('source', sourceAnchor);\n            }\n            if (deleteSourceAnchor) {\n                this.resetAnchor('source', data.sourceAnchorDef);\n            }\n        }\n\n        // Last segment\n        var targetView = relatedView.targetView;\n        var targetBBox = relatedView.targetBBox;\n        var changeTargetAnchor = false;\n        var deleteTargetAnchor = false;\n        if (!nextVertex) {\n            nextVertex = relatedView.targetAnchor.toJSON();\n            nextVertex[axis] = position[axis];\n            if (targetBBox.containsPoint(nextVertex)) {\n                changeTargetAnchor = true;\n            } else {\n                // we left the area of the target magnet for the first time\n                vertices.push(nextVertex);\n                deleteTargetAnchor = true;\n            }\n        } else if (index === vertices.length - 2) {\n            if (targetBBox.containsPoint(nextVertex)) {\n                vertices.pop();\n                changeTargetAnchor = true;\n            } else {\n                nextVertex[axis] = position[axis];\n                deleteTargetAnchor = true;\n            }\n        } else {\n            nextVertex[axis] = position[axis];\n        }\n\n        if (anchorFn && targetView) {\n            if (changeTargetAnchor) {\n                var targetAnchorPosition = data.targetAnchor.clone();\n                targetAnchorPosition[axis] = position[axis];\n                var targetAnchor = anchorFn.call(relatedView, targetAnchorPosition, targetView, relatedView.targetMagnet || targetView.el, 'target', relatedView);\n                this.resetAnchor('target', targetAnchor);\n            }\n            if (deleteTargetAnchor) {\n                this.resetAnchor('target', data.targetAnchorDef);\n            }\n        }\n        if (vertices.some(v => !v)) {\n            // This can happen when the link is using a smart routing and the number of\n            // vertices is not the same as the number of route points.\n            throw new Error('Segments: incompatible router in use');\n        }\n        link.vertices(vertices, { ui: true, tool: this.cid });\n        this.updateHandle(handle, vertex, nextVertex, offset);\n        if (!options.stopPropagation) relatedView.notifyPointermove(normalizedEvent, coords.x, coords.y);\n    },\n    onHandleChangeStart: function(handle, evt) {\n        const { options, handles, relatedView: linkView } = this;\n        const { model, paper } = linkView;\n        var index = handle.options.index;\n        if (!Array.isArray(handles)) return;\n        for (var i = 0, n = handles.length; i < n; i++) {\n            if (i !== index) handles[i].hide();\n        }\n        this.focus();\n        this.eventData(evt, {\n            sourceAnchor: linkView.sourceAnchor.clone(),\n            targetAnchor: linkView.targetAnchor.clone(),\n            sourceAnchorDef: util.clone(model.prop(['source', 'anchor'])),\n            targetAnchorDef: util.clone(model.prop(['target', 'anchor'])),\n            originalVertices: util.cloneDeep(model.vertices()),\n            firstHandleShifted: false\n        });\n        model.startBatch('segment-move', { ui: true, tool: this.cid });\n        if (!options.stopPropagation) linkView.notifyPointerdown(...paper.getPointerArgs(evt));\n    },\n    onHandleChangeEnd: function(_handle, evt) {\n        const { options, relatedView: linkView }= this;\n        const { paper, model } = linkView;\n        if (options.redundancyRemoval) {\n            linkView.removeRedundantLinearVertices({ ui: true, tool: this.cid });\n        }\n        const normalizedEvent = util.normalizeEvent(evt);\n        const coords = paper.snapToGrid(normalizedEvent.clientX, normalizedEvent.clientY);\n        this.render();\n        this.blur();\n        model.stopBatch('segment-move', { ui: true, tool: this.cid });\n        if (!options.stopPropagation) linkView.notifyPointerup(normalizedEvent, coords.x, coords.y);\n        linkView.checkMouseleave(normalizedEvent);\n    },\n    updateHandle: function(handle, vertex, nextVertex, offset) {\n        var vertical = Math.abs(vertex.x - nextVertex.x) < this.precision;\n        var horizontal = Math.abs(vertex.y - nextVertex.y) < this.precision;\n        if (vertical || horizontal) {\n            var segmentLine = new g.Line(vertex, nextVertex);\n            var length = segmentLine.length();\n            if (length < this.options.segmentLengthThreshold) {\n                handle.hide();\n            } else {\n                var position = segmentLine.midpoint();\n                var axis = (vertical) ? 'x' : 'y';\n                position[axis] += offset || 0;\n                var angle = segmentLine.vector().vectorAngle(new g.Point(1, 0));\n                handle.position(position.x, position.y, angle, this.relatedView);\n                handle.show();\n                handle.options.axis = axis;\n            }\n        } else {\n            handle.hide();\n        }\n    },\n    onRemove: function() {\n        this.resetHandles();\n    }\n}, {\n    SegmentHandle: SegmentHandle // keep as class property\n});\n","import * as connectionStrategies from '../connectionStrategies/index.mjs';\n\nexport function getViewBBox(view, useModelGeometry) {\n    const { model } = view;\n    if (useModelGeometry) return model.getBBox();\n    return (model.isLink()) ? view.getConnection().bbox() : view.getNodeUnrotatedBBox(view.el);\n}\n\nexport function getAnchor(coords, view, magnet) {\n    // take advantage of an existing logic inside of the\n    // pin relative connection strategy\n    var end = connectionStrategies.pinRelative.call(\n        this.paper,\n        {},\n        view,\n        magnet,\n        coords,\n        this.model\n    );\n    return end.anchor;\n}\n\nexport function snapAnchor(coords, view, magnet, type, relatedView, toolView) {\n    var snapRadius = toolView.options.snapRadius;\n    var isSource = (type === 'source');\n    var refIndex = (isSource ? 0 : -1);\n    var ref = this.model.vertex(refIndex) || this.getEndAnchor(isSource ? 'target' : 'source');\n    if (ref) {\n        if (Math.abs(ref.x - coords.x) < snapRadius) coords.x = ref.x;\n        if (Math.abs(ref.y - coords.y) < snapRadius) coords.y = ref.y;\n    }\n    return coords;\n}\n","import * as mvc from '../mvc/index.mjs';\nimport * as util from '../util/index.mjs';\nimport { CellView } from './CellView.mjs';\nimport { LayersNames } from './PaperLayer.mjs';\nimport { ToolView } from './ToolView.mjs';\n\nexport const ToolsView = mvc.View.extend({\n    tagName: 'g',\n    className: 'tools',\n    svgElement: true,\n    tools: null,\n    isRendered: false,\n    options: {\n        tools: null,\n        relatedView: null,\n        name: null,\n        // layer?: LayersNames.TOOLS\n        // z?: number\n    },\n\n    configure: function(options) {\n        options = util.assign(this.options, options);\n        var tools = options.tools;\n        if (!Array.isArray(tools)) return this;\n        var relatedView = options.relatedView;\n        if (!(relatedView instanceof CellView)) return this;\n        var views = this.tools = [];\n        for (var i = 0, n = tools.length; i < n; i++) {\n            var tool = tools[i];\n            if (!(tool instanceof ToolView)) continue;\n            tool.configure(relatedView, this);\n            this.vel.append(tool.el);\n            views.push(tool);\n        }\n        this.isRendered = false;\n        relatedView.requestUpdate(relatedView.getFlag('TOOLS'));\n        return this;\n    },\n\n    getName: function() {\n        return this.options.name;\n    },\n\n    update: function(opt) {\n\n        opt || (opt = {});\n        const tools = this.tools;\n        if (!tools) return this;\n        const n = tools.length;\n        const wasRendered = this.isRendered;\n        for (let i = 0; i < n; i++) {\n            const tool = tools[i];\n            tool.updateVisibility();\n            if (!tool.isVisible()) continue;\n            if (this.ensureToolRendered(tools, i) && opt.tool !== tool.cid) {\n                tool.update();\n            }\n        }\n        if (!this.isRendered && n > 0) {\n            // None of the tools is visible\n            // Note: ToolsView with no tools are always mounted\n            return this;\n        }\n        if (!this.isMounted()) {\n            this.mount();\n        }\n        if (!wasRendered) {\n            // Make sure tools are visible (if they were hidden and the tool removed)\n            this.blurTool();\n        }\n        return this;\n    },\n\n    ensureToolRendered(tools, i) {\n        if (!this.isRendered) {\n            // There is at least one visible tool\n            this.isRendered = Array(tools.length).fill(false);\n        }\n        if (!this.isRendered[i]) {\n            // First update executes render()\n            tools[i].render();\n            this.isRendered[i] = true;\n            return false;\n        }\n        return true;\n    },\n\n    focusTool: function(focusedTool) {\n\n        var tools = this.tools;\n        if (!tools) return this;\n        for (var i = 0, n = tools.length; i < n; i++) {\n            var tool = tools[i];\n            if (focusedTool === tool) {\n                tool.show();\n            } else {\n                tool.hide();\n            }\n        }\n        return this;\n    },\n\n    blurTool: function(blurredTool) {\n        var tools = this.tools;\n        if (!tools) return this;\n        for (var i = 0, n = tools.length; i < n; i++) {\n            var tool = tools[i];\n            if (tool !== blurredTool && !tool.isExplicitlyVisible()) {\n                tool.show();\n                // Check if the tool is conditionally visible too\n                if (tool.isVisible()) {\n                    this.ensureToolRendered(tools, i) && tool.update();\n                }\n            }\n        }\n        return this;\n    },\n\n    hide: function() {\n        return this.focusTool(null);\n    },\n\n    show: function() {\n        this.blurTool(null);\n        // If this the first time the tools are shown, make sure they are mounted\n        if (!this.isMounted()) {\n            this.mount();\n        }\n        return this;\n    },\n\n    onRemove: function() {\n        var tools = this.tools;\n        if (!tools) return this;\n        for (var i = 0, n = tools.length; i < n; i++) {\n            tools[i].remove();\n        }\n        this.tools = null;\n    },\n\n    mount: function() {\n        const { options, el } = this;\n        const { relatedView, layer = LayersNames.TOOLS, z } = options;\n        if (relatedView) {\n            if (layer) {\n                relatedView.paper.getLayerView(layer).insertSortedNode(el, z);\n            } else {\n                relatedView.el.appendChild(el);\n            }\n        }\n        return this;\n    }\n\n});\n","import * as joint from '@joint/core';\r\n\r\ninterface FlowEditorOptions {\r\n    container: HTMLElement;\r\n    width: number;\r\n    height: number;\r\n    dotNetHelper: any;\r\n    futureStateMode: boolean;\r\n}\r\n\r\ninterface FlowPreviewOptions {\r\n    container: HTMLElement;\r\n    graphJson: string;\r\n}\r\n\r\nenum ShapeType {\r\n    CorporationCFC = 1,\r\n    BranchThirdParty = 2,\r\n    Partnership = 3,\r\n    HybridEntity = 4,\r\n    ReverseHybridEntity = 5,\r\n    DRE = 6,\r\n    Group = 7,\r\n}\r\n\r\nenum TransactionType {\r\n    ServiceFee,\r\n    Royalty,\r\n    IPTransfer,\r\n}\r\n\r\nenum FlowType {\r\n    Physical,\r\n    Legal,\r\n    Payment,\r\n    Service,\r\n    IPTransfer,\r\n    IPLicense,\r\n    Agreement,\r\n    Miscellaneous,\r\n}\r\n\r\nenum Jurisdiction {\r\n    US = 1,\r\n    NonUS = 2,\r\n    Mixed = 3,\r\n}\r\n\r\nenum PaymentType {\r\n    Royalty = 0,\r\n    ServiceFee = 1,\r\n    BuySell = 2,\r\n}\r\n\r\nclass DefaultValues {\r\n    static readonly PrimaryColor: string = '#000000';\r\n    static readonly SecondaryColor: string = '#0D838F';\r\n    static readonly EmphasizedColor: string = '#87BC24';\r\n    static readonly ThirdPartyColor: string = '#52575B';\r\n}\r\n\r\ntype LinkTypeColor = {\r\n    type: string;\r\n    color: string;\r\n};\r\n\r\nconst linkTypeColors: readonly LinkTypeColor[] = [\r\n    { type: 'PhysicalLink', color: '#CE1210' },\r\n    { type: 'LegalLink', color: '#99C13C' },\r\n    { type: 'PaymentLink', color: '#9B9B9D' },\r\n    { type: 'ServiceLink', color: 'black' },\r\n    { type: 'IPTransferLink', color: '#FFA500' },\r\n    { type: 'IPLicenseLink', color: '#8E25AB' },\r\n    { type: 'AgreementLink', color: '#256F8C' },\r\n    { type: 'MiscellaneousLink', color: '#EB8100' }\r\n];\r\n\r\nclass Node extends joint.dia.Element {\r\n    //_entityIds: string[] = [];\r\n    get entityIds() {\r\n        return this.prop('entityIds');\r\n    }\r\n    set entityIds(value: string[]) {\r\n        this.prop('entityIds', value);\r\n    }\r\n\r\n    get isNewEntity() {\r\n        return this.prop('isNewEntity');\r\n    }\r\n    set isNewEntity(value: boolean) {\r\n        this.prop('isNewEntity', value);\r\n    }\r\n\r\n    public setColor(color: string) {\r\n        this.attr('body/fill', color);\r\n    }\r\n\r\n    get functions() {\r\n        return this.prop('functions');\r\n    }\r\n    set functions(value: string[]) {\r\n        this.removeProp('functions');\r\n        this.prop('functions', value);\r\n    }\r\n\r\n    public setColorByJurisdiction(jurisdiction: Jurisdiction) {\r\n        switch (jurisdiction) {\r\n            case Jurisdiction.US:\r\n                this.setColor(DefaultValues.PrimaryColor);\r\n                break;\r\n            case Jurisdiction.NonUS:\r\n                this.setColor(DefaultValues.SecondaryColor);\r\n                break;\r\n            case Jurisdiction.Mixed: // overridden in EntityGroup\r\n                this.setColor(DefaultValues.PrimaryColor);\r\n                break;\r\n            default:\r\n                this.setColor(DefaultValues.PrimaryColor);\r\n                break;\r\n        }\r\n    }\r\n\r\n    public setLabel(label: string) {\r\n        // if the string is too long, split on all spaces and add a newline where the string exceeds a certain length\r\n        if (label.length > 15) {\r\n            var splitLabel = '';\r\n            var words = label.split(' ');\r\n            var lineLength = 0;\r\n            words.forEach(word => {\r\n                if (lineLength + word.length > 15) {\r\n                    splitLabel += '\\n' + word + ' ';\r\n                    lineLength = word.length;\r\n                } else {\r\n                    splitLabel += word + ' ';\r\n                    lineLength += word.length;\r\n                }\r\n            });\r\n\r\n            this.attr('label/text', splitLabel.trim());\r\n        } else {\r\n            this.attr('label/text', label);\r\n        }\r\n    }\r\n\r\n    public setSecondaryLabel(label: string) {\r\n        // if the string is too long, split on all spaces and add a newline where the string exceeds a certain length\r\n        if (label.length > 15) {\r\n            var splitLabel = '';\r\n            var words = label.split(' ');\r\n            var lineLength = 0;\r\n            words.forEach(word => {\r\n                if (lineLength + word.length > 15) {\r\n                    splitLabel += '\\n' + word + ' ';\r\n                    lineLength = word.length;\r\n                } else {\r\n                    splitLabel += word + ' ';\r\n                    lineLength += word.length;\r\n                }\r\n            });\r\n            this.attr('label2/text', splitLabel.trim());\r\n        } else {\r\n            this.attr('label2/text', label);\r\n        }\r\n    }\r\n\r\n    public async setFunctionIcon(iconName: string): Promise<void> {\r\n        try {\r\n            const iconPath = `/icons/functions/${iconName}.svg`;\r\n\r\n            const response = await fetch(iconPath);\r\n            if (!response.ok) {\r\n                throw new Error(`HTTP error! Status: ${response.status}`);\r\n            }\r\n            const svgContent = await response.text();\r\n            const encodedSvg = encodeURIComponent(svgContent);\r\n\r\n            this.attr({\r\n                functionIcon: {\r\n                    'xlink:href': `data:image/svg+xml;utf8,${encodedSvg}`\r\n                }\r\n            });\r\n        } catch (error) {\r\n            console.error('Failed to load SVG:', error);\r\n        }\r\n    }\r\n\r\n    public async addFunctionIcons(functions: string[]): Promise<void> {\r\n        console.debug(\"old functions: \", this.functions)\r\n        console.debug(\"new functions: \", functions)\r\n        this.functions = functions;\r\n        const iconSize = 30;\r\n        const padding = 5;\r\n        const elementWidth = 170;\r\n        const elementHeight = 100;\r\n\r\n        //// Check if there is already a functionIcon with a non-empty href\r\n        //const existingIconHref = this.attr('functionIcon/xlink:href');\r\n        //let startX;\r\n        //let startY = iconSize;\r\n\r\n        //if (existingIconHref && existingIconHref !== '') {\r\n        //    // If there's an existing icon, start to the left of it\r\n        //    startX = elementWidth - (functions.length * iconSize + (functions.length - 1) * padding) - padding;\r\n        //} else {\r\n        //    // If no existing icon, start from the left side of the element\r\n        //    startX = (iconSize / 2);\r\n        //}\r\n\r\n        //for (let i = 0; i < functions.length; i++) {\r\n        //    const functionName = functions[i];\r\n\r\n        //    try {\r\n        //        const iconPath = `/icons/functions/${functionName}.svg`;\r\n\r\n        //        const response = await fetch(iconPath);\r\n        //        if (!response.ok) {\r\n        //            throw new Error(`HTTP error! Status: ${response.status}`);\r\n        //        }\r\n        //        const svgContent = await response.text();\r\n        //        const encodedSvg = encodeURIComponent(svgContent);\r\n\r\n        //        const refX = (startX / elementWidth) * 100 + '%';\r\n        //        const refY = (startY / elementHeight) * 100 + '%';\r\n\r\n        //        this.attr({\r\n        //            [`functionIcon${i}`]: {\r\n        //                'xlink:href': `data:image/svg+xml;utf8,${encodedSvg}`,\r\n        //                width: iconSize,\r\n        //                height: iconSize,\r\n        //                refX: refX,\r\n        //                refY: refY,\r\n        //            }\r\n        //        });\r\n\r\n        //        startX += iconSize + padding;\r\n\r\n        //    } catch (error) {\r\n        //        console.error(`Failed to load SVG for ${functionName}:`, error);\r\n        //    }\r\n        //}\r\n    }\r\n}\r\n\r\ninterface EntityNodeOptions {\r\n    jurisdiction: Jurisdiction;\r\n    shape: ShapeType;\r\n    label: string;\r\n    entityIds: string[];\r\n    functions: string[];\r\n    isNewEntity: boolean;\r\n}\r\n\r\ninterface MenuOption {\r\n    text: string;\r\n    action: () => void | any;\r\n    subMenu?: MenuOption[];\r\n}\r\n\r\nenum ToolMode {\r\n    AddFlow,\r\n    AddTransaction,\r\n    DrawRectangle,\r\n    MoveExpense,\r\n    MoveRevenue,\r\n    MoveFunction,\r\n}\r\n\r\nconst toolModesWithTargetSelection = [ToolMode.AddFlow, ToolMode.AddTransaction, ToolMode.MoveExpense, ToolMode.MoveRevenue, ToolMode.MoveFunction];\r\n\r\nexport class FlowEditor {\r\n    private readonly namespace = joint.shapes;\r\n    private paper: joint.dia.Paper;\r\n    private graph: joint.dia.Graph;\r\n    private dotNetHelper: any;\r\n    private readonly futureStateMode: boolean;\r\n    private readonly container: HTMLElement;\r\n\r\n    // context variables\r\n    private activeTool: ToolMode | null = null;\r\n    // for adding flows\r\n    private flowTypeToCreate: FlowType | null = null;\r\n    // for adding transactions\r\n    private transactionTypeToCreate: TransactionType | null = null;\r\n    // for adding flows or transactions\r\n    private selectedElement: joint.dia.Element | null = null;\r\n    private hoveredElementClickDisabled: boolean = false;\r\n    // for moving functions\r\n    private functionNameToMove: string | null = null;\r\n    // for drawing rectangles\r\n    private startRectangle: { x: number, y: number } | null = null;\r\n    private tempRectangleElement: DrawnRectangle | null = null;\r\n    // for panning the paper\r\n    private panStartPosition: { x: number, y: number } | null = null;\r\n\r\n\r\n    public getGraphJson() {\r\n        var graphJson = JSON.stringify(this.graph?.toJSON());\r\n        return graphJson;\r\n    }\r\n\r\n\r\n    public setGraphJson(graphJson: string) {\r\n        console.debug('setGraphJson');\r\n        this.closeMenus();\r\n\r\n        if (graphJson) {\r\n            console.debug('loading graph from JSON');\r\n            this.paper.model.fromJSON(JSON.parse(graphJson), { cellNamespace: this.namespace });\r\n\r\n            this.graph.getElements().forEach(element => {\r\n                if (element instanceof Node) {\r\n                    let markup = element.get('markup');\r\n\r\n                    if (!Array.isArray(markup)) {\r\n                        markup = [markup];\r\n                    }\r\n\r\n                    // clean-up unused function icon markup\r\n                    const newMarkup = markup.filter(markupElement =>\r\n                        typeof markupElement === 'object' && 'tagName' in markupElement && markupElement.tagName !== 'image' && !markupElement.selector.includes('functionIcon')\r\n                    );\r\n\r\n                    element.set('markup', newMarkup);\r\n\r\n                    // backwards compatibility check for entity ids with spaces in them (in case flows were created before spaces were disallowed)\r\n                    const entityIds = element.entityIds;\r\n                    if (entityIds.some(id => id.includes(' '))) {\r\n                        element.entityIds = entityIds.map(id => id.replace(' ', '_'));\r\n                    }\r\n\r\n                    // backwards compatibility check for populating flow legend with entities created before svgPath property was defined\r\n                    if (element.get('type') !== null && !element.get('svgPath')) {\r\n                        const entityType = element.get('type');\r\n                        const svgPath = `/icons/${entityType}.svg`;\r\n                        element.set('svgPath', svgPath);\r\n                    }\r\n                }\r\n            });\r\n\r\n            // TEMP workaround for populating flow legend with links created before custom link classes were defined\r\n            this.graph.getLinks().forEach(link => {\r\n\r\n                // delete instances of MiscellaneousLink\r\n                if (link instanceof MiscellaneousLink) {\r\n                    link.remove();\r\n                    return;\r\n                }\r\n                // and check legacy flows by colorMiscellaneousLinks\r\n                else if (link.attributes.type === 'standard.Link' && link.attributes.attrs?.line?.stroke === '#EB8100') {\r\n                    link.remove();\r\n                    return;\r\n                }\r\n\r\n                if (link.attributes.type === 'standard.Link' && link.attributes.attrs?.line?.stroke) {\r\n                    const linkColor = link.attributes.attrs.line.stroke;\r\n                    const matchingLink = linkTypeColors.find(lc => lc.color === linkColor);\r\n\r\n                    if (matchingLink) {\r\n                        link.attributes.color = linkColor;\r\n                        link.attributes.type = matchingLink.type;\r\n                    }\r\n                }\r\n\r\n            });\r\n\r\n            this.paper.scale(1, 1);\r\n            this.paper.transformToFitContent({ verticalAlign: 'middle', horizontalAlign: 'middle', minScale: 1, maxScale: 1 });\r\n        } else {\r\n            console.debug('creating new graph');\r\n            this.paper.model.clear();\r\n        }\r\n        console.debug('setGraphJson done');\r\n    }\r\n\r\n\r\n\r\n    // Invoked by C#\r\n    private setRectangleMode(value: boolean) {\r\n        console.debug('rectangle mode ' + value)\r\n        this.activeTool = value ? ToolMode.DrawRectangle : null;\r\n    }\r\n\r\n    private drawRectangle(evt: joint.dia.Event, x: number, y: number) {\r\n        if (this.startRectangle) {\r\n            console.debug('drawing rectangle')\r\n            this.tempRectangleElement?.remove();\r\n\r\n            // Create the rectangle shape (if it is big enough to be visible, based on gridSize)\r\n            if (Math.abs(x - this.startRectangle.x) >= this.paper.options.gridSize\r\n                && Math.abs(y - this.startRectangle.y) >= this.paper.options.gridSize) {\r\n\r\n                this.tempRectangleElement = new DrawnRectangle({\r\n                    size: {\r\n                        width: Math.abs(x - this.startRectangle.x),\r\n                        height: Math.abs(y - this.startRectangle.y)\r\n                    },\r\n                    position: {\r\n                        x: this.startRectangle.x > x ? x : this.startRectangle.x,\r\n                        y: this.startRectangle.y > y ? y : this.startRectangle.y\r\n                    },\r\n                });\r\n\r\n                // Add the shape to the graph\r\n                this.graph.addCell(this.tempRectangleElement);\r\n            }\r\n        }\r\n    }\r\n\r\n    private async addTransaction(source: Node, target: Node, transactionType: TransactionType) {\r\n        // if the source and target are the same, do nothing\r\n        if (source.id != target.id) {\r\n\r\n            // Determine success based on transaction type and future state mode\r\n            switch (transactionType) {\r\n                case TransactionType.ServiceFee:\r\n                    this.futureStateMode ? await this.addPaymentByDialog(source, target, PaymentType.ServiceFee, FlowType.Service) : true;\r\n                    break;\r\n                case TransactionType.Royalty:\r\n                    this.futureStateMode ? await this.addPaymentByDialog(source, target, PaymentType.Royalty, FlowType.IPLicense) : true;\r\n                    break;\r\n                case TransactionType.IPTransfer:\r\n                    this.futureStateMode ? await this.addIPTransferByDialog(target, source, FlowType.IPTransfer) : true;\r\n                    break;\r\n                default:\r\n                    throw new Error(\"Unsupported transaction type\");\r\n            }\r\n        }\r\n    }\r\n\r\n    private addFlow(source: joint.dia.Element, target: joint.dia.Element, flowType: FlowType, label?: string | null, stepId?: string) {\r\n        if (source.id != target.id) {\r\n            let newLink: joint.shapes.standard.Link;\r\n\r\n            switch (flowType) {\r\n                case FlowType.Physical:\r\n                    newLink = new (joint.shapes as any).PhysicalLink();\r\n                    break;\r\n                case FlowType.Legal:\r\n                    newLink = new (joint.shapes as any).LegalLink();\r\n                    break;\r\n                case FlowType.Payment:\r\n                    newLink = new (joint.shapes as any).PaymentLink();\r\n                    break;\r\n                case FlowType.Service:\r\n                    newLink = new (joint.shapes as any).ServiceLink();\r\n                    break;\r\n                case FlowType.IPTransfer:\r\n                    newLink = new (joint.shapes as any).IPTransferLink();\r\n                    break;\r\n                case FlowType.IPLicense:\r\n                    newLink = new (joint.shapes as any).IPLicenseLink();\r\n                    break;\r\n                case FlowType.Agreement:\r\n                    newLink = new (joint.shapes as any).AgreementLink();\r\n                    break;\r\n                case FlowType.Miscellaneous:\r\n                    newLink = new (joint.shapes as any).MiscellaneousLink();\r\n                    break;\r\n            }\r\n\r\n            if (stepId) {\r\n                newLink.prop('stepId', stepId);\r\n            }\r\n\r\n            newLink.source(source);\r\n            newLink.target(target);\r\n            var sourceEntityIds = (source as Node).entityIds;\r\n            var targetEntityIds = (target as Node).entityIds;\r\n\r\n            if (!stepId && this.futureStateMode == true) {\r\n                // call C# to add AddRelationshipStep\r\n                stepId = this.dotNetHelper.invokeMethod('AddRelationshipStep', sourceEntityIds, targetEntityIds, newLink.labels()[0]?.attrs.text.text, flowType);\r\n                newLink.prop('stepId', stepId);\r\n            }\r\n\r\n            this.graph.addCell(newLink);\r\n\r\n            this.dotNetHelper.invokeMethodAsync('SetFlowLegendItems');\r\n        }\r\n    }\r\n\r\n    // called from C#\r\n    private addFlowBetweenEntities(sourceEntityId: string, targetEntityId: string, flowType: FlowType, label: string, stepId: string): void {\r\n        const sourceNode = this.graph.getElements().find(node => node instanceof Node && node.entityIds.includes(sourceEntityId));\r\n        const targetNode = this.graph.getElements().find(node => node instanceof Node && node.entityIds.includes(targetEntityId));\r\n\r\n        if (sourceNode && targetNode) {\r\n            this.addFlow(sourceNode, targetNode, flowType, label, stepId);\r\n        }\r\n    }\r\n\r\n    // called from C#\r\n    private removeFlowBetweenEntities(sourceEntityId: string, targetEntityId: string, flowType: FlowType): void {\r\n        const links = this.graph.getLinks();\r\n        const linkToRemove = links.filter(link => {\r\n            const sourceNode = link.getSourceElement() as Node;\r\n            const targetNode = link.getTargetElement() as Node;\r\n            const sourceEntityIds = sourceNode.entityIds;\r\n            const targetEntityIds = targetNode.entityIds;\r\n            let linkType;\r\n            switch (flowType) {\r\n                case FlowType.Physical:\r\n                    linkType = 'PhysicalLink';\r\n                    break;\r\n                case FlowType.Legal:\r\n                    linkType = 'LegalLink';\r\n                    break;\r\n                case FlowType.Payment:\r\n                    linkType = 'PaymentLink';\r\n                    break;\r\n                case FlowType.Service:\r\n                    linkType = 'ServiceLink';\r\n                    break;\r\n                case FlowType.IPTransfer:\r\n                    linkType = 'IPTransferLink';\r\n                    break;\r\n                case FlowType.IPLicense:\r\n                    linkType = 'IPLicenseLink';\r\n                    break;\r\n                case FlowType.Agreement:\r\n                    linkType = 'AgreementLink';\r\n                    break;\r\n                case FlowType.Miscellaneous:\r\n                    linkType = 'MiscellaneousLink';\r\n                    break;\r\n            }\r\n\r\n            return sourceEntityIds.includes(sourceEntityId) && targetEntityIds.includes(targetEntityId) && link.attributes.type === linkType;\r\n        });\r\n\r\n        linkToRemove.forEach(link => {\r\n            link.remove();\r\n        });\r\n\r\n        this.dotNetHelper.invokeMethodAsync('SetFlowLegendItems');\r\n    }\r\n\r\n    // Called from C#\r\n    private removeFlowByStepId(stepId: string): void {\r\n        const links = this.graph.getLinks();\r\n        const linksToRemove = links.filter(link => link.prop('stepId') === stepId);\r\n        if (linksToRemove) {\r\n            linksToRemove.forEach(link => link.remove());\r\n            this.dotNetHelper.invokeMethodAsync('SetFlowLegendItems');\r\n        }\r\n    }\r\n\r\n    // Called from C#\r\n    private toggleFlowElementVisibility(flowType: string, isVisible: boolean) {\r\n        let elements;\r\n        elements = this.graph.getCells().filter(cell => {\r\n            return cell.attributes.type?.toLowerCase().replace('link', '') === flowType.toLowerCase().replace('link', '');\r\n        });\r\n\r\n        elements.forEach(element => {\r\n            // Show/Hide entity cells\r\n            element.attr('body/display', isVisible ? 'block' : 'none');\r\n            const elementView = this.paper.findViewByModel(element);\r\n\r\n            if (elementView) {\r\n                const children = elementView.el.querySelectorAll('*');\r\n                children.forEach((child: SVGElement) => {\r\n                    child.setAttribute('display', isVisible ? 'block' : 'none');\r\n                });\r\n            }\r\n\r\n            if (element instanceof joint.shapes.standard.Link) {\r\n                element.attr('line/display', isVisible ? 'block' : 'none');\r\n                element.label(0, {\r\n                    attrs: {\r\n                        text: { display: isVisible ? 'block' : 'none' },\r\n                        rect: { display: isVisible ? 'block' : 'none' }\r\n                    }\r\n                });\r\n            }\r\n\r\n        });\r\n\r\n        this.dotNetHelper.invokeMethodAsync('SetFlowLegendItems');\r\n    }\r\n\r\n    private openMenu(cell: joint.dia.Cell, x: number, y: number) {\r\n        // 1. Create Menu\r\n        var menu = document.createElement('div');\r\n        menu.className = 'flow-editor-menu';\r\n\r\n        // 2. Position Menu\r\n        menu.style.top = y + 'px'; //evt.pageY\r\n        menu.style.left = x + 'px'; //evt.pageX\r\n\r\n        // 3. Add Menu Options\r\n        var options: MenuOption[] = [];\r\n\r\n        if (cell instanceof EmptyElement || cell instanceof EmptyThirdParty) {\r\n            options = [\r\n                //{ text: 'Choose Entity(s)', action: async () => { await this.chooseEntities(cell) } },\r\n                { text: null, action: null },\r\n                { text: 'Delete', action: () => { cell.remove() } },\r\n            ];\r\n        } else if (cell instanceof DrawnRectangle) {\r\n            options = [\r\n                { text: 'Edit Label', action: () => { this.changeElementPrimaryText(cell) } },\r\n                { text: null, action: null },\r\n                { text: 'Delete', action: () => { cell.remove() } },\r\n            ];\r\n        } else if (cell instanceof Node) {\r\n            if (this.futureStateMode) {\r\n                options = [\r\n                    {\r\n                        text: 'Add Transaction', action: null,\r\n                        subMenu: [\r\n                            { text: 'Pay a Service Fee to...', action: () => { this.beginAddTransaction(cell, TransactionType.ServiceFee) } },\r\n                            { text: 'Pay a Royalty Fee to...', action: () => { this.beginAddTransaction(cell, TransactionType.Royalty) } },\r\n                            { text: 'Transfer IP to...', action: () => { this.beginAddTransaction(cell, TransactionType.IPTransfer) } },\r\n                        ]\r\n                    },\r\n                    { text: 'Move Revenues to...', action: () => { this.beginMoveRevenue(cell) } },\r\n                    { text: 'Move Expenses to...', action: () => { this.beginMoveExpense(cell) } },\r\n                ];\r\n\r\n                if (!(cell instanceof EntityGroup)) {\r\n                    // Ability to add, remove, or edit existing functions\r\n                    options = options.concat([\r\n                        {\r\n                            text: 'Edit Function(s)',\r\n                            action: () => {\r\n                                this.dotNetHelper.invokeMethodAsync('EditEntityFunctions', cell.entityIds[0], cell.functions)\r\n                            }\r\n                        },\r\n                    ]);\r\n                    // Move an existing function\r\n                    if (cell.functions?.length > 0) {\r\n                        options = options.concat([\r\n                            {\r\n                                text: 'Move Function', action: null,\r\n                                subMenu: cell.functions.map((functionName, index) => {\r\n                                    return {\r\n                                        text: functionName,\r\n                                        action: () => { this.beginMoveFunction(cell, functionName) }\r\n                                    };\r\n                                })\r\n                            }\r\n                        ]);\r\n                    }\r\n                    // No existing functions to move\r\n                    else {\r\n                        options = options.concat([\r\n                            {\r\n                                text: 'Move Function', action: () => null,\r\n                                subMenu: [\r\n                                    {\r\n                                        text: 'No functions available', action: () => null\r\n                                    }\r\n                                ]\r\n                            },\r\n                        ]);\r\n                    }\r\n                    options = options.concat([\r\n                        {\r\n                            text: 'Edit Entity Type(s)',\r\n                            action: () => {\r\n                                this.dotNetHelper.invokeMethodAsync('EditEntityTypes', cell.entityIds[0])\r\n                            }\r\n                        },\r\n                    ]);\r\n                }\r\n                // Edit tax rates\r\n                options = options.concat([\r\n                    {\r\n                        text: 'Edit Tax Rates', action: () => {\r\n                            this.dotNetHelper.invokeMethodAsync('EditTaxRatesByDialog', cell.entityIds[0])\r\n                        }\r\n                    },\r\n                ]);\r\n\r\n                options.push({ text: null, action: null });\r\n            }\r\n\r\n            options = options.concat([\r\n                {\r\n                    text: 'Add Flow', action: null,\r\n                    subMenu: [\r\n                        { text: 'Physical', action: () => { this.beginAddFlow(cell, FlowType.Physical) } },\r\n                        { text: 'Legal Title', action: () => { this.beginAddFlow(cell, FlowType.Legal) } },\r\n                        { text: 'Payment', action: () => { this.beginAddFlow(cell, FlowType.Payment) } },\r\n                        { text: 'Service', action: () => { this.beginAddFlow(cell, FlowType.Service) } },\r\n                        { text: 'IP Transfer', action: () => { this.beginAddFlow(cell, FlowType.IPTransfer) } },\r\n                        { text: 'IP License', action: () => { this.beginAddFlow(cell, FlowType.IPLicense) } },\r\n                        { text: 'Agreement', action: () => { this.beginAddFlow(cell, FlowType.Agreement) } },\r\n                        //TODO: cleanup Miscellaneous flows throughout solution\r\n                        //{ text: 'Miscellaneous', action: () => { this.beginAddFlow(cell, FlowType.Miscellaneous) } },\r\n                    ]\r\n                },\r\n                { text: null, action: null },\r\n            ]);\r\n\r\n            if (this.futureStateMode) {\r\n                if (cell.isNewEntity) {\r\n                    options = options.concat([\r\n                        { text: 'Edit P&L', action: () => { this.addPnlByDialog(cell) } }\r\n                    ]);\r\n                }\r\n                options = options.concat([\r\n                    { text: 'Preview P&L', action: () => { this.dotNetHelper.invokeMethodAsync('PreviewPnlByDialog', cell.entityIds, cell.attr('label/text')) } },\r\n                ]);\r\n            }\r\n\r\n            // TODO: After design is agreed upon, re-implement function icons feature...\r\n            //const functionIconOptions = [\r\n            //    { text: 'Commercial', action: () => { this.changeFunctionIcon(cell, 'Commercial') } },\r\n            //    { text: 'Deliver', action: () => { this.changeFunctionIcon(cell, 'Deliver') } },\r\n            //    { text: 'Develop', action: () => { this.changeFunctionIcon(cell, 'Develop') } },\r\n            //    { text: 'Digital IP', action: () => { this.changeFunctionIcon(cell, 'Digital IP') } },\r\n            //    { text: 'eCommerce', action: () => { this.changeFunctionIcon(cell, 'eCommerce') } },\r\n            //    { text: 'ESG', action: () => { this.changeFunctionIcon(cell, 'ESG') } },\r\n            //    { text: 'Headquarter Oversight', action: () => { this.changeFunctionIcon(cell, 'Headquarter Oversight') } },\r\n            //    { text: 'Internal Support', action: () => { this.changeFunctionIcon(cell, 'Internal Support') } },\r\n            //    { text: 'Logistics', action: () => { this.changeFunctionIcon(cell, 'Logistics') } },\r\n            //    { text: 'Make', action: () => { this.changeFunctionIcon(cell, 'Make') } },\r\n            //    { text: 'Market', action: () => { this.changeFunctionIcon(cell, 'Market') } },\r\n            //    { text: 'Quality', action: () => { this.changeFunctionIcon(cell, 'Quality') } },\r\n            //    { text: 'Regulatory Process', action: () => { this.changeFunctionIcon(cell, 'Regulatory Process') } },\r\n            //    { text: 'Retail', action: () => { this.changeFunctionIcon(cell, 'Retail') } },\r\n            //    { text: 'Sell', action: () => { this.changeFunctionIcon(cell, 'Sell') } },\r\n            //    { text: 'Services', action: () => { this.changeFunctionIcon(cell, 'Services') } },\r\n            //    { text: 'Source', action: () => { this.changeFunctionIcon(cell, 'Source') } },\r\n            //    { text: 'Strategy', action: () => { this.changeFunctionIcon(cell, 'Strategy') } },\r\n            //    { text: 'US Legal IP', action: () => { this.changeFunctionIcon(cell, 'US Legal IP') } },\r\n            //    { text: 'US Newly Developed IP', action: () => { this.changeFunctionIcon(cell, 'US Newly Developed IP') } },\r\n            //    { text: 'Warehousing', action: () => { this.changeFunctionIcon(cell, 'Warehousing') } },\r\n            //    { text: 'Wholesale', action: () => { this.changeFunctionIcon(cell, 'Wholesale') } }\r\n            //];\r\n\r\n            //if (cell.attr('functionIcon/xlink:href')) {\r\n            //    functionIconOptions.unshift({ text: 'None', action: () => { this.changeFunctionIcon(cell, 'None') } });\r\n            //}\r\n\r\n            options = options.concat([\r\n                { text: 'Edit Color', action: () => { this.changeElementColor(cell) } },\r\n                { text: 'Edit Primary Label', action: () => { this.changeElementPrimaryText(cell) } },\r\n                { text: cell.attr('label2/text') === '' ? 'Add Secondary Label' : 'Edit Secondary Label', action: () => { this.changeElementSecondaryText(cell) } },\r\n                //{\r\n                //    text: cell.attr('functionIcon/xlink:href') === '' ? 'Add Function Icon' : 'Edit Function Icon',\r\n                //    action: null,\r\n                //    subMenu: functionIconOptions\r\n                //},\r\n                { text: null, action: null },\r\n                { text: 'Delete', action: () => { this.confirmDeleteElement(cell) } },\r\n            ]);\r\n\r\n        } else if (cell instanceof joint.shapes.standard.Link) {\r\n            var sourceNode = cell.getSourceElement() as Node;\r\n            var targetNode = cell.getTargetElement() as Node;\r\n\r\n            options = [\r\n                { text: 'Edit Label', action: () => { this.changeLinkText(cell) } },\r\n                { text: null, action: null },\r\n                { text: 'Delete Flow', action: () => { this.confirmDeleteRelationship(cell) } },\r\n            ];\r\n        }\r\n\r\n        options.forEach(option => {\r\n            var menuOption = document.createElement('div');\r\n\r\n            if (option.text == null && option.action == null) {\r\n                menuOption.className = 'flow-editor-menu-divider';\r\n                menu.appendChild(menuOption);\r\n                return;\r\n            }\r\n\r\n            menuOption.className = 'flow-editor-menu-option';\r\n            var menuText = document.createElement('span');\r\n            menuText.textContent = option.text;\r\n            menuOption.appendChild(menuText);\r\n\r\n            if (option.subMenu) {\r\n                var arrow = document.createElement('span');\r\n                arrow.textContent = '>';\r\n                menuOption.appendChild(arrow);\r\n            }\r\n\r\n            menu.appendChild(menuOption);\r\n\r\n            menuOption.addEventListener('click', async () => {\r\n                if (option.subMenu) {\r\n                    // if there is a sub-menu, open it\r\n                    var bounds = menuOption.getBoundingClientRect();\r\n                    var x = bounds.left + bounds.width;\r\n                    var y = bounds.top;\r\n                    this.openSubMenu(x, y, option.subMenu);\r\n                } else {\r\n                    // else perform the action\r\n                    await option.action();\r\n                    await this.closeMenus();\r\n                }\r\n            });\r\n        });\r\n\r\n        // 4. Show Menu\r\n        menu.style.visibility = 'hidden'; // hide the menu to calculate the height\r\n        document.body.appendChild(menu);\r\n\r\n        // Calculate the distance between the bottom of the div and the bottom of the window to avoid collisions\r\n        var divBottom = menu.offsetTop + menu.offsetHeight;\r\n        var windowHeight = window.innerHeight || document.documentElement.clientHeight;\r\n        var distanceToBottom = windowHeight - divBottom;\r\n\r\n        console.debug(\"divBottom: \" + divBottom);\r\n        console.debug(\"windowHeight: \" + windowHeight);\r\n        console.debug(\"distanceToBottom: \" + distanceToBottom);\r\n\r\n        // Check if the distance will cause the menu to go off the screen\r\n        if (distanceToBottom < 0) {\r\n            menu.style.top = (menu.offsetTop - menu.offsetHeight) + 'px';\r\n        }\r\n        menu.style.visibility = 'visible';\r\n    }\r\n\r\n    public openSubMenu(x: number, y: number, options: MenuOption[]) {\r\n        // close any other sub-menus that are open\r\n        this.closeSubMenus();\r\n\r\n        // 1. Create Sub-Menu\r\n        var menu = document.createElement('div');\r\n        menu.className = 'flow-editor-menu';\r\n        menu.classList.add('flow-editor-submenu');\r\n\r\n        // 2. Position Menu\r\n        menu.style.top = y + 'px';\r\n        menu.style.left = x + 'px';\r\n\r\n        menu.style.maxHeight = '200px';\r\n        menu.style.overflowY = 'scroll';\r\n\r\n        // 3. Add Menu Options\r\n        options.forEach(option => {\r\n            var menuOption = document.createElement('div');\r\n\r\n            if (option.text == null && option.action == null) {\r\n                menuOption.className = 'flow-editor-menu-divider';\r\n                menu.appendChild(menuOption);\r\n                return;\r\n            }\r\n\r\n            menuOption.className = 'flow-editor-menu-option';\r\n            var menuText = document.createElement('span');\r\n            menuText.textContent = option.text;\r\n            menuOption.appendChild(menuText);\r\n            menu.appendChild(menuOption);\r\n\r\n            menuOption.addEventListener('click', async () => {\r\n                if (option.subMenu) {\r\n                    // if there is a sub-menu, open it\r\n                    var bounds = menuOption.getBoundingClientRect();\r\n                    var x = bounds.left + bounds.width;\r\n                    var y = bounds.top;\r\n                    this.openSubMenu(x, y, option.subMenu);\r\n                } else {\r\n                    // else perform the action\r\n                    await option.action();\r\n                    await this.closeMenus();\r\n                }\r\n            });\r\n        });\r\n\r\n        // 4. Show Menu\r\n        menu.style.visibility = 'hidden'; // hide the menu to calculate the height\r\n        document.body.appendChild(menu);\r\n\r\n        // Calculate the distance between the bottom of the div and the bottom of the window to avoid collisions\r\n        var divBottom = menu.offsetTop + menu.offsetHeight;\r\n        var windowHeight = window.innerHeight || document.documentElement.clientHeight;\r\n        var distanceToBottom = windowHeight - divBottom;\r\n\r\n        console.debug(\"divBottom: \" + divBottom);\r\n        console.debug(\"windowHeight: \" + windowHeight);\r\n        console.debug(\"distanceToBottom: \" + distanceToBottom);\r\n\r\n        // Check if the distance will cause the menu to go off the screen\r\n        if (distanceToBottom < 0) {\r\n            menu.style.top = (menu.offsetTop - menu.offsetHeight) + 'px';\r\n        }\r\n\r\n        // Calculate the distance between the right of the div and the right of the window to avoid horizontal collisions\r\n        var divRight = menu.offsetLeft + menu.offsetWidth;\r\n        var windowWidth = window.innerWidth || document.documentElement.clientWidth;\r\n        var distanceToRight = windowWidth - divRight;\r\n\r\n\r\n        // Check if the distance will cause the menu to go off the screen\r\n        if (distanceToRight < 0) {\r\n            menu.style.left = (menu.offsetLeft - menu.offsetWidth) + 'px';\r\n        }\r\n\r\n        menu.style.visibility = 'visible';\r\n    }\r\n\r\n    public closeMenus() {\r\n        // 1. Retrieve all open menus\r\n        var openMenus = Array.from(document.getElementsByClassName('flow-editor-menu'));\r\n\r\n        // 2. Close all open menus\r\n        openMenus.forEach(menu => {\r\n            menu.remove();\r\n        });\r\n    }\r\n\r\n    public closeSubMenus() {\r\n        // retrieve all open sub-menus\r\n        var openSubMenus = Array.from(document.getElementsByClassName('flow-editor-submenu'));\r\n\r\n        // close all open sub-menus\r\n        openSubMenus.forEach(menu => {\r\n            menu.remove();\r\n        });\r\n    }\r\n\r\n    private beginAddTransaction(sourceElement: Node, transactionType: TransactionType) {\r\n\r\n        // set the activeTool\r\n        this.activeTool = ToolMode.AddTransaction;\r\n\r\n        // set context variables\r\n        this.selectedElement = sourceElement;\r\n        this.transactionTypeToCreate = transactionType;\r\n\r\n        // add a border filter to the element to indicate that it is selected\r\n        sourceElement.attr('body/filter', { name: 'highlight', args: { color: 'orange', width: 3, opacity: 0.75, blur: 5, } });\r\n        this.closeMenus();\r\n    }\r\n\r\n    private beginAddFlow(sourceElement: Node, flowType: FlowType) {\r\n        // set the activeTool\r\n        this.activeTool = ToolMode.AddFlow;\r\n\r\n        // set context variables\r\n        this.selectedElement = sourceElement;\r\n        this.flowTypeToCreate = flowType;\r\n\r\n        // add a border filter to the element to indicate that it is selected\r\n        sourceElement.attr('body/filter', { name: 'highlight', args: { color: 'orange', width: 3, opacity: 0.75, blur: 5, } });\r\n        this.closeMenus();\r\n    }\r\n\r\n    private beginMoveExpense(sourceElement: Node) {\r\n        // set the activeTool\r\n        this.activeTool = ToolMode.MoveExpense;\r\n\r\n        // set context variables\r\n        this.selectedElement = sourceElement;\r\n\r\n        // add a border filter to the element to indicate that it is selected\r\n        sourceElement.attr('body/filter', { name: 'highlight', args: { color: 'orange', width: 3, opacity: 0.75, blur: 5, } });\r\n        this.closeMenus();\r\n    }\r\n\r\n    private beginMoveRevenue(sourceElement: Node) {\r\n        // set the activeTool\r\n        this.activeTool = ToolMode.MoveRevenue;\r\n\r\n        // set context variables\r\n        this.selectedElement = sourceElement;\r\n\r\n        // add a border filter to the element to indicate that it is selected\r\n        sourceElement.attr('body/filter', { name: 'highlight', args: { color: 'orange', width: 3, opacity: 0.75, blur: 5, } });\r\n        this.closeMenus();\r\n    }\r\n\r\n    private beginMoveFunction(sourceElement: Node, functionName: string) {\r\n        // set the activeTool\r\n        this.activeTool = ToolMode.MoveFunction;\r\n\r\n        // set context variables\r\n        this.selectedElement = sourceElement;\r\n        this.functionNameToMove = functionName;\r\n\r\n        // add a border filter to the element to indicate that it is selected\r\n        sourceElement.attr('body/filter', { name: 'highlight', args: { color: 'orange', width: 3, opacity: 0.75, blur: 5, } });\r\n        this.closeMenus();\r\n    }\r\n\r\n    private async addPaymentByDialog(source: Node, target: Node, paymentType: PaymentType, flowType: FlowType): Promise<void> {\r\n        var sourceEntityIds = source.entityIds ?? [];\r\n        var targetEntityIds = target.entityIds ?? [];\r\n        var sourceLabel = source.attr('label/text');\r\n        var targetLabel = target.attr('label/text');\r\n\r\n        var dialogResult = paymentType === PaymentType.ServiceFee\r\n            ? await this.dotNetHelper.invokeMethodAsync('AddServiceFeeByDialog', sourceEntityIds, targetEntityIds, sourceLabel, targetLabel)\r\n            : await this.dotNetHelper.invokeMethodAsync('AddRoyaltyFeeByDialog', sourceEntityIds, targetEntityIds, sourceLabel, targetLabel);\r\n\r\n        // Bind new step's ID with the flow/link created\r\n        if (dialogResult) {\r\n            const stepId = dialogResult.data[0].id;\r\n\r\n            // Add the Service or Royalty flow\r\n            this.addFlow(target, source, flowType, null, stepId);\r\n            // Add the Payment flow\r\n            this.addFlow(source, target, FlowType.Payment, null, stepId);\r\n        }\r\n    }\r\n\r\n    private async addIPTransferByDialog(source: Node, target: Node, flowType: FlowType): Promise<void> {\r\n        var sourceEntityIds = source.entityIds ?? [];\r\n        var targetEntityIds = target.entityIds ?? [];\r\n        var sourceLabel = source.attr('label/text');\r\n        var targetLabel = target.attr('label/text');\r\n\r\n        var dialogResult = await this.dotNetHelper.invokeMethodAsync('AddIpTransferStepByDialog', sourceEntityIds, targetEntityIds, sourceLabel, targetLabel);\r\n\r\n        // Bind new step's ID with the flow/link created\r\n        if (dialogResult) {\r\n            const stepId = dialogResult.data[0].id;\r\n\r\n            // Add the IP Transfer flow\r\n            this.addFlow(target, source, flowType, null, stepId);\r\n            // Add the Payment flow\r\n            this.addFlow(source, target, FlowType.Payment, null, stepId);\r\n        }\r\n    }\r\n\r\n    private async addPnlByDialog(node: Node) {\r\n        var entityId = node.entityIds[0]; // there should only be one entity id (for a new entity)\r\n\r\n        await this.dotNetHelper.invokeMethodAsync('EditPnlByDialog', entityId);\r\n    }\r\n\r\n    public async addEntityNode() {\r\n        console.debug(\"addEntityNode\")\r\n\r\n        var entityIdsToExclude: string[] = [];\r\n        this.graph.getElements().forEach(node => {\r\n            if (node instanceof Node) {\r\n                entityIdsToExclude.push(...node.entityIds);\r\n            }\r\n        });\r\n\r\n        var results: EntityNodeOptions[] = await this.dotNetHelper.invokeMethodAsync('SearchEntitiesByDialog', entityIdsToExclude);\r\n        if (results != null) {\r\n            var x = (this.container.offsetWidth / 2) - (results.length * 45);\r\n            var y = (this.container.offsetHeight / 2) - (results.length * 45);\r\n            console.debug(results);\r\n\r\n            results.forEach(result => {\r\n                // create the new type of element based on the incoming entity(s)\r\n                var newElement: Node = this.CreateEntityNode(result.shape);\r\n\r\n                // set the entityIds of the new element\r\n                newElement.entityIds = result.entityIds;\r\n\r\n                // set the label of the new element\r\n                newElement.setLabel(result.label);\r\n\r\n                // set the color of the new element\r\n                newElement.setColorByJurisdiction(result.jurisdiction);\r\n\r\n                newElement.position(x, y);\r\n                newElement.resize(170, 100);\r\n                this.graph.addCell(newElement);\r\n\r\n                // set the functions\r\n                if (result.functions && result.functions.length > 0) {\r\n                    newElement.addFunctionIcons(result.functions);\r\n                }\r\n\r\n                x = x + 45;\r\n                y = y + 45;\r\n            });\r\n\r\n            await this.dotNetHelper.invokeMethodAsync('SetFlowLegendItems');\r\n        }\r\n    }\r\n\r\n    public async addThirdPartyNode() {\r\n        console.debug(\"addThirdPartyNode\")\r\n\r\n        var entityIdsToExclude: string[] = [];\r\n        this.graph.getElements().forEach(node => {\r\n            if (node instanceof Node) {\r\n                entityIdsToExclude.push(...node.entityIds);\r\n            }\r\n        });\r\n\r\n        var results: EntityNodeOptions[] = await this.dotNetHelper.invokeMethodAsync('SearchExternalEntitiesByDialog', entityIdsToExclude);\r\n        if (results != null) {\r\n            var x = (this.container.offsetWidth / 2) - (results.length * 45);\r\n            var y = (this.container.offsetHeight / 2) - (results.length * 45);\r\n            console.debug(results);\r\n\r\n            results.forEach(result => {\r\n                // create the new type of element based on the incoming entity(s)\r\n                var newElement: Node = this.CreateEntityNode(result.shape);\r\n                // set the entityIds of the new element\r\n                newElement.entityIds = result.entityIds;\r\n\r\n                // set the label of the new element\r\n                newElement.setLabel(result.label);\r\n\r\n                // set the color of the new element\r\n                newElement.setColorByJurisdiction(result.jurisdiction);\r\n\r\n                newElement.position(x, y);\r\n                newElement.resize(170, 100);\r\n                this.graph.addCell(newElement);\r\n\r\n                x = x + 45;\r\n                y = y + 45;\r\n\r\n            });\r\n            await this.dotNetHelper.invokeMethodAsync('SetFlowLegendItems');\r\n        }\r\n    }\r\n\r\n    //// TODO: allow changing the entity for a node that was already added.\r\n    //// This should call C# to update any Future State steps that are associated with the existing entity.\r\n    //private async chooseEntities(element: joint.dia.Element) {\r\n    //    // first get all entity ids from all nodes in the graph to exclude from search\r\n    //    var entityIdsToExclude: string[] = [];\r\n    //    this.graph.getElements().forEach(node => {\r\n    //        if (node instanceof Node) {\r\n    //            entityIdsToExclude.push(...node.entityIds);\r\n    //        }\r\n    //    });\r\n\r\n    //    var results: EntityNodeOptions[];\r\n\r\n    //    if (element instanceof EmptyThirdParty || element instanceof BranchThirdParty) {\r\n    //        results = await this.dotNetHelper.invokeMethodAsync('SearchExternalEntitiesByDialog', entityIdsToExclude);\r\n    //    }\r\n    //    else {\r\n    //        results = await this.dotNetHelper.invokeMethodAsync('SearchEntitiesByDialog', entityIdsToExclude);\r\n    //    }\r\n    //    //console.log('result: ' + result);\r\n\r\n    //    if (results != null) {\r\n    //        // do something\r\n    //    }\r\n    //}\r\n\r\n    // called from C# \r\n    public async updateEntityFunctions(entityId: string, functionNames: string[]) {\r\n        var entityNode = this.graph.getElements().find(e => e instanceof Node && e.entityIds.includes(entityId)) as Node;\r\n        console.log(entityNode, functionNames);\r\n        entityNode?.addFunctionIcons(functionNames);\r\n    }\r\n\r\n    // called from C# to add a new entity node to the graph\r\n    public async addEntityByEntityNodeOptions(options: EntityNodeOptions) {\r\n        console.debug(options);\r\n\r\n        // check if the any of the element ids already exist in the graph\r\n        var element = this.graph.getElements().find(e => e instanceof Node &&\r\n            e.entityIds.filter(id => options.entityIds.includes(id)).length > 0);\r\n\r\n        if (element) {\r\n            console.debug('error: cannot add duplicate entity id(s) to graph');\r\n            return;\r\n        }\r\n\r\n        var newElement: Node = this.CreateEntityNode(options.shape);\r\n\r\n        // set the entityIds of the new element\r\n        newElement.entityIds = options.entityIds;\r\n\r\n        // set the label of the new element\r\n        newElement.setLabel(options.label);\r\n\r\n        // set the color of the new element\r\n        newElement.setColorByJurisdiction(options.jurisdiction);\r\n\r\n        // set the isNewEntity property of the new element\r\n        newElement.isNewEntity = options.isNewEntity;\r\n\r\n        // set the position of the new element to the center of the container\r\n        var position = [this.container.offsetWidth / 2, this.container.offsetHeight / 2];\r\n        console.debug(position)\r\n\r\n        // check if another entity element is already positioned at the same location\r\n        do {\r\n            var overlappingPositionElement = this.graph.getElements().find(e => e instanceof Node &&\r\n                e.position().x === position[0] &&\r\n                e.position().y === position[1]);\r\n\r\n            if (overlappingPositionElement) {\r\n                console.debug('overlapping element')\r\n                position[0] = position[0] + 45;\r\n                position[1] = position[1] + 45;\r\n\r\n                console.debug(position)\r\n            }\r\n            console.debug('no overlapping element')\r\n        }\r\n        while (overlappingPositionElement);\r\n\r\n        newElement.position(position[0], position[1]);\r\n        newElement.resize(170, 100);\r\n\r\n        // Add function icons\r\n        if (options.functions && options.functions.length > 0) {\r\n            await newElement.addFunctionIcons(options.functions);\r\n        }\r\n\r\n        this.graph.addCell(newElement);\r\n        await this.dotNetHelper.invokeMethodAsync('SetFlowLegendItems');\r\n\r\n\r\n    }\r\n\r\n    // called from C# to replace an entity node with a new one\r\n    public async replaceEntityNodeByEntityId(entityId: string, options: EntityNodeOptions) {\r\n        var element = this.graph.getElements().find(e => e instanceof Node &&\r\n            e.entityIds.length == 1 && e.entityIds[0] == entityId);\r\n\r\n        if (element) {\r\n            var newElement: Node = this.CreateEntityNode(options.shape);\r\n\r\n            // set the entityIds of the new element\r\n            newElement.entityIds = options.entityIds;\r\n\r\n            // set the label of the new element\r\n            newElement.setLabel(options.label);\r\n\r\n            // set the color of the new element\r\n            newElement.setColorByJurisdiction(options.jurisdiction);\r\n\r\n            newElement.position(element.attributes.position.x, element.attributes.position.y);\r\n            newElement.resize(170, 100);\r\n            this.graph.addCell(newElement);\r\n\r\n            // set the functions\r\n            if (options.functions && options.functions.length > 0) {\r\n                newElement.addFunctionIcons(options.functions);\r\n            }\r\n\r\n            // update any existing links to reference the new element\r\n            var links = this.graph.getConnectedLinks(element);\r\n            links.forEach(link => {\r\n                if (link.get('source').id === element.id) {\r\n                    link.source(newElement);\r\n                }\r\n                if (link.get('target').id === element.id) {\r\n                    link.target(newElement);\r\n                }\r\n            });\r\n\r\n            // remove the original element\r\n            element.remove();\r\n            await this.dotNetHelper.invokeMethodAsync('SetFlowLegendItems');\r\n        }\r\n    }\r\n\r\n    private async confirmDeleteElement(element: joint.dia.Element) {\r\n        if (this.futureStateMode && element instanceof Node) {\r\n            var entityIds = element.entityIds ?? [];\r\n            var label = element.attr('label/text');\r\n\r\n            var result = await this.dotNetHelper.invokeMethodAsync('ConfirmDeleteEntityByDialog', entityIds, label);\r\n            if (result) {\r\n                element.remove();\r\n            }\r\n        }\r\n        else {\r\n            element.remove();\r\n        }\r\n        await this.dotNetHelper.invokeMethodAsync('SetFlowLegendItems');\r\n    }\r\n\r\n    private async confirmDeleteRelationship(link: joint.shapes.standard.Link) {\r\n        if (this.futureStateMode) {\r\n            var sourceNode = link.getSourceElement() as Node;\r\n            var targetNode = link.getTargetElement() as Node;\r\n            var sourceEntityIds = sourceNode.entityIds ?? [];\r\n            var targetEntityIds = targetNode.entityIds ?? [];\r\n            var stepId = link.prop('stepId');\r\n\r\n            var result = await this.dotNetHelper.invokeMethodAsync('ConfirmDeleteRelationshipByDialog', sourceEntityIds, targetEntityIds, stepId);\r\n            if (result) {\r\n                // TODO: for now we decided not to add RemoveRelationshipSteps because there's no way to visualize them. \r\n                //if (!link.prop('stepId')){\r\n                // if no step id exists on the link, call C# to add RemoveRelationshipStep (in theory this link is from the Current State)\r\n                // if a step id exists, the link was added by a different step, or is associated with an AddRelationshipStep (added in FS)\r\n                //await this.dotNetHelper.invokeMethodAsync('RemoveRelationshipStep', sourceEntityIds, targetEntityIds, link.labels()[0]?.attrs.text.text);\r\n                //}\r\n                link.remove();\r\n                await this.dotNetHelper.invokeMethodAsync('SetFlowLegendItems');\r\n            }\r\n        }\r\n        else {\r\n            link.remove();\r\n            await this.dotNetHelper.invokeMethodAsync('SetFlowLegendItems');\r\n        }\r\n    }\r\n\r\n    // called from C# to remove an entity node from the graph\r\n    public async removeEntityNodeByEntityId(entityId: string) {\r\n        var element = this.graph.getElements().find(e => e instanceof Node &&\r\n            e.entityIds.length == 1 && e.entityIds[0] == entityId);\r\n\r\n        if (element) {\r\n            element.remove();\r\n            await this.dotNetHelper.invokeMethodAsync('SetFlowLegendItems');\r\n        }\r\n    }\r\n\r\n    public async addFunctionToEntityNode(entityId: string, functionName: string) {\r\n        var element = this.graph.getElements().find(e => e instanceof Node &&\r\n            e.entityIds.length == 1 && e.entityIds[0] == entityId) as Node;\r\n\r\n        if (element) {\r\n            element.functions.push(functionName);\r\n            this.updateEntityFunctions(entityId, element.functions);\r\n        }\r\n    }\r\n\r\n    public async removeFunctionFromEntityNode(entityId: string, functionName: string) {\r\n        var element = this.graph.getElements().find(e => e instanceof Node &&\r\n            e.entityIds.length == 1 && e.entityIds[0] == entityId) as Node;\r\n\r\n        if (element) {\r\n            var updatedFunctions = element.functions.filter(f => f !== functionName);\r\n            this.updateEntityFunctions(entityId, updatedFunctions);\r\n        }\r\n    }\r\n\r\n    public async onMoveFunctionStepDelete(sourceEntityId: string, targetEntityId: string, functionName: string) {\r\n        this.removeFunctionFromEntityNode(targetEntityId, functionName);\r\n        this.addFunctionToEntityNode(sourceEntityId, functionName);\r\n    }\r\n\r\n    public resetToolMode() {\r\n        this.activeTool = null;\r\n\r\n        if (this.selectedElement) {\r\n            this.selectedElement.attr('body/filter', null);\r\n            this.selectedElement = null;\r\n        }\r\n\r\n        this.flowTypeToCreate = null;\r\n        this.transactionTypeToCreate = null;\r\n\r\n        this.startRectangle = null;\r\n        this.tempRectangleElement?.remove();\r\n\r\n        this.graph.getElements().forEach(element => {\r\n            if (element instanceof Node) {\r\n                element.attr('body/filter', null);\r\n            }\r\n        });\r\n    }\r\n\r\n    private async changeElementPrimaryText(element: Node | DrawnRectangle) {\r\n        // get the current text of the entity\r\n        var oldText = element.attr('label/text');\r\n\r\n        var newText = await this.dotNetHelper.invokeMethodAsync('EditTextByDialog', oldText);\r\n        console.debug('newText: ' + newText);\r\n\r\n        // if newText is not null (allow empty strings)\r\n        if (newText != null) {\r\n            element.setLabel(newText);\r\n        }\r\n    }\r\n\r\n    private async changeElementSecondaryText(element: Node) {\r\n        // get the current text of the entity\r\n        var oldText = element.attr('label2/text');\r\n\r\n        var newText = await this.dotNetHelper.invokeMethodAsync('EditTextByDialog', oldText);\r\n        console.debug('newText: ' + newText);\r\n\r\n        // if newText is not null (allow empty strings)\r\n        if (newText != null) {\r\n            element.setSecondaryLabel(newText);\r\n        }\r\n    }\r\n\r\n    private async changeFunctionIcon(element: Node, functionName: string) {\r\n\r\n        try {\r\n\r\n            if (functionName === \"None\") {\r\n                element.attr('functionIcon/xlink:href', '');\r\n                return;\r\n            }\r\n\r\n            const iconPath = `/icons/functions/${functionName}.svg`;\r\n            const response = await fetch(iconPath);\r\n\r\n            if (!response.ok) {\r\n                throw new Error(`Error fetching Function Icon path: ${response.status}`);\r\n            }\r\n            const svgContent = await response.text();\r\n\r\n            const encodedSvgContent = encodeURIComponent(svgContent);\r\n\r\n            if (element.attr('functionIcon')) {\r\n                element.attr({\r\n                    functionIcon: {\r\n                        'xlink:href': `data:image/svg+xml;charset=utf8,${encodedSvgContent}`,\r\n                        width: 30,\r\n                        height: 30,\r\n                        refX: '20%',\r\n                        refY: '10%',\r\n                    }\r\n                });\r\n            } else {\r\n                element.setFunctionIcon(functionName);\r\n            }\r\n        } catch (error) {\r\n            console.error('Error loading or setting SVG:', error);\r\n        }\r\n    }\r\n\r\n\r\n    private async changeLinkText(link: joint.shapes.standard.Link) {\r\n        // get the current text of the link\r\n        var oldText = link.labels()[0]?.attrs.text.text;\r\n        //var oldLabelPosition = link.labels()[0]?.position;\r\n\r\n        var newText = await this.dotNetHelper.invokeMethodAsync('EditTextByDialog', oldText);\r\n        //console.debug('newText: ' + newText);\r\n\r\n        // if newText is not null (allow empty strings)\r\n        if (newText != null) {\r\n            link.label(0, {\r\n                attrs: {\r\n                    text: {\r\n                        text: newText\r\n                    }\r\n                }\r\n            });\r\n        }\r\n    }\r\n\r\n    private async changeElementColor(element: joint.dia.Element) {\r\n        // get the current color of the entity\r\n        var oldColor = element.attr('body/fill');\r\n\r\n        var color = await this.dotNetHelper.invokeMethodAsync('ChooseColorByDialog', oldColor);\r\n\r\n        // if color is not null or empty string\r\n        if (color) {\r\n            element.attr('body/fill', color);\r\n        }\r\n    }\r\n\r\n    private CreateEntityNode(shapeType: ShapeType): any {\r\n        switch (shapeType) {\r\n            case ShapeType.CorporationCFC:\r\n                return new CorporationCFC();\r\n                break;\r\n            case ShapeType.BranchThirdParty:\r\n                return new BranchThirdParty();\r\n                break;\r\n            case ShapeType.Partnership:\r\n                return new Partnership();\r\n                break;\r\n            case ShapeType.HybridEntity:\r\n                return new HybridEntity();\r\n                break;\r\n            case ShapeType.ReverseHybridEntity:\r\n                return new ReverseHybrid();\r\n                break;\r\n            case ShapeType.DRE:\r\n                return new Disregarded();\r\n                break;\r\n            case ShapeType.Group:\r\n                return new EntityGroup();\r\n                break;\r\n            default:\r\n                return new CorporationCFC();\r\n                break;\r\n        }\r\n    }\r\n\r\n    constructor(options: FlowEditorOptions) {\r\n        this.graph = new joint.dia.Graph({}, { cellNamespace: this.namespace });\r\n\r\n        this.graph.on('add remove change', (cell) => {\r\n            // if we need to perform some logic when an alement is added, removed, changed\r\n        });\r\n\r\n        this.paper = new joint.dia.Paper({\r\n            el: options.container,\r\n            model: this.graph,\r\n            width: null, // this is controlled by CSS\r\n            height: null, // this is controlled by CSS\r\n            gridSize: 15,\r\n            drawGrid: {\r\n                name: 'dot', args: { color: 'black' }\r\n            },\r\n            interactive: {\r\n                linkMove: true,\r\n                labelMove: true,\r\n            },\r\n            snapLabels: true,\r\n            labelsLayer: true,\r\n            moveThreshold: 1,\r\n            restrictTranslate: true,\r\n            cellViewNamespace: this.namespace\r\n        });\r\n\r\n        this.dotNetHelper = options.dotNetHelper;\r\n        this.futureStateMode = options.futureStateMode;\r\n        this.container = options.container;\r\n\r\n        console.debug('futureStateMode: ' + options.futureStateMode)\r\n\r\n        var verticesTool = new joint.linkTools.Vertices({\r\n            snapRadius: 30,\r\n            stopPropagation: false,\r\n        });\r\n\r\n        var segmentsTool = new joint.linkTools.Segments({\r\n            snapRadius: 15,\r\n            stopPropagation: false,\r\n        });\r\n\r\n        var toolsView = new joint.dia.ToolsView({\r\n            tools: [\r\n                verticesTool,\r\n                segmentsTool,\r\n            ],\r\n        });\r\n\r\n        this.paper.on('link:mouseenter', function (linkView) {\r\n            linkView.addTools(toolsView);\r\n        });\r\n\r\n        this.paper.on('blank:mouseover', () => {\r\n            this.paper.removeTools();\r\n        });\r\n\r\n        this.paper.on({\r\n            'element:mouseenter': (cellView, evt) => {\r\n                //console.log('Element mouse enter');\r\n\r\n                if (cellView.model instanceof Node\r\n                    && this.selectedElement\r\n                    && this.selectedElement.id != cellView.model.id\r\n                    && this.activeTool in toolModesWithTargetSelection) {\r\n\r\n                    // the only valid tool that targets third party entities is AddFlow\r\n                    if (!(cellView.model instanceof BranchThirdParty) || this.activeTool == ToolMode.AddFlow) {\r\n                        cellView.model.attr('body/filter', { name: 'highlight', args: { color: 'purple', width: 3, opacity: 0.75, blur: 5, } });\r\n                    } else {\r\n                        // ignore if this element is clicked\r\n                        joint.highlighters.addClass.add(cellView, 'root', 'not-allowed-highlighter', { className: 'not-allowed' });\r\n                        this.hoveredElementClickDisabled = true;\r\n                    }\r\n                }\r\n            },\r\n            'element:mouseleave': (cellView, evt) => {\r\n                //console.log('Element mouse leave');\r\n\r\n                if (cellView.model instanceof Node\r\n                    && this.selectedElement\r\n                    && this.selectedElement.id != cellView.model.id\r\n                    && this.activeTool in toolModesWithTargetSelection) {\r\n\r\n                    cellView.model.attr('body/filter', null);\r\n                }\r\n\r\n                joint.highlighters.addClass.remove(cellView, 'not-allowed-highlighter');\r\n                this.hoveredElementClickDisabled = false;\r\n            },\r\n            'element.pointerup': (cellView, evt) => {\r\n                evt.stopPropagation();\r\n                console.log('Element pointer up');\r\n            },\r\n            'element:pointerclick': async (cellView, evt, x, y) => {\r\n                evt.stopPropagation();\r\n                if (this.hoveredElementClickDisabled) {\r\n                    // ignore the click event\r\n                    return;\r\n                }\r\n\r\n                console.log('Element pointer click - selectedElement is ' + this.selectedElement?.id);\r\n                this.closeMenus();\r\n\r\n                const element = cellView.model;\r\n\r\n                // If an element is already selected, and it is not the same as this clicked element\r\n                if (this.selectedElement && this.selectedElement != element) {\r\n\r\n                    if (this.activeTool == ToolMode.AddTransaction && this.selectedElement instanceof Node && element instanceof Node) {\r\n                        // add a link between the selected element and the current element\r\n                        this.addTransaction(this.selectedElement, element, this.transactionTypeToCreate);\r\n                    } else if (this.activeTool == ToolMode.AddFlow) {\r\n                        // add a link between the selected element and the current element\r\n                        this.addFlow(this.selectedElement, element, this.flowTypeToCreate);\r\n                    } else if (this.activeTool == ToolMode.MoveExpense) {\r\n                        // add a Transfer Expense step between the selected element and the current element\r\n                        var sourceEntityIds = (this.selectedElement as Node).entityIds ?? []\r\n                        var targetEntityIds = (element as Node).entityIds ?? [];\r\n                        var sourceLabel = (this.selectedElement as Node).attr('label/text');\r\n                        var targetLabel = (element as Node).attr('label/text');\r\n                        await this.dotNetHelper.invokeMethodAsync('AddTransferExpenseStepByDialog', sourceEntityIds, targetEntityIds, sourceLabel, targetLabel);\r\n                    } else if (this.activeTool == ToolMode.MoveRevenue) {\r\n                        // add a Transfer Revenue step between the selected element and the current element\r\n                        var sourceEntityIds = (this.selectedElement as Node).entityIds ?? [];\r\n                        var targetEntityIds = (element as Node).entityIds ?? [];\r\n                        var sourceLabel = (this.selectedElement as Node).attr('label/text');\r\n                        var targetLabel = (element as Node).attr('label/text');\r\n                        await this.dotNetHelper.invokeMethodAsync('AddTransferRevenueStepByDialog', sourceEntityIds, targetEntityIds, sourceLabel, targetLabel);\r\n                    } else if (this.activeTool == ToolMode.MoveFunction) {\r\n                        // add a Move Function step between the selected element and the current element\r\n                        var sourceEntityIds = (this.selectedElement as Node).entityIds ?? [];\r\n                        var targetEntityIds = (element as Node).entityIds ?? [];\r\n                        var sourceLabel = (this.selectedElement as Node).attr('label/text');\r\n                        var targetLabel = (element as Node).attr('label/text');\r\n                        await this.dotNetHelper.invokeMethodAsync('AddMoveFunctionStep', sourceEntityIds, targetEntityIds, this.functionNameToMove);\r\n                    }\r\n\r\n                    this.dotNetHelper.invokeMethodAsync('SetFlowLegendItems');\r\n\r\n                    // reset the selected element\r\n                    this.resetToolMode();\r\n                }\r\n                else { // Else, open a menu for the current element\r\n                    this.openMenu(element, evt.pageX, evt.pageY);\r\n                }\r\n            },\r\n            'link:pointerclick': (cellView, evt) => {\r\n                evt.stopPropagation();\r\n                console.log('Link pointer click');\r\n                this.closeMenus();\r\n\r\n                var link = cellView.model;\r\n                this.openMenu(link, evt.pageX, evt.pageY);\r\n            },\r\n            'element:pointermove': (cellView, evt, x, y) => {\r\n                // Logic for handling pointer down events (e.g., drag start)\r\n                //evt.stopPropagation();\r\n                console.log('Element pointer move');\r\n                this.closeMenus();\r\n                this.resetToolMode();\r\n            },\r\n            // we have no use case for double clicking at this time.\r\n            //'element:pointerdblclick': (cellView, evt, x, y) => {\r\n            //    // Logic for handling double click events on elements\r\n            //    evt.stopPropagation();\r\n            //    console.log('Element double click');\r\n            //},\r\n            'blank:pointerdown': (evt, x, y) => {\r\n                // Logic for handling pointer down events on the blank paper\r\n                //evt.stopPropagation();\r\n                console.log('Blank pointer down');\r\n                this.closeMenus();\r\n\r\n                if (this.activeTool == ToolMode.DrawRectangle) {\r\n                    this.startRectangle = { x: x, y: y };\r\n                    console.debug('starting draw rectangle')\r\n                }\r\n                else {\r\n                    this.resetToolMode();\r\n\r\n                    // Logic to start panning the paper\r\n                    var scale = this.paper.scale();\r\n                    this.panStartPosition = { x: x * scale.sx, y: y * scale.sy };\r\n                }\r\n            },\r\n            'blank:pointerup': async (evt, x, y) => {\r\n                // Logic for handling pointer up events on the blank paper\r\n                //evt.stopPropagation();\r\n                console.log('Blank pointer up');\r\n                this.closeMenus();\r\n\r\n                if (this.activeTool == ToolMode.DrawRectangle && this.startRectangle) {\r\n                    this.startRectangle = null;\r\n                    this.tempRectangleElement?.setLabel(\"Click to edit text\");\r\n                    this.tempRectangleElement = null;\r\n                    await this.dotNetHelper.invokeMethodAsync('SetRectangleMode', false);\r\n                } else {\r\n                    // Logic to stop panning the paper\r\n                    this.panStartPosition = null;\r\n                }\r\n            },\r\n            'blank:pointermove': (evt, x, y) => {\r\n                // Logic for handling pointer move events on the blank paper\r\n                console.log('Blank pointer move');\r\n                if (this.activeTool == ToolMode.DrawRectangle) {\r\n                    this.drawRectangle(evt, x, y);\r\n                }\r\n            },\r\n            'element:label:pointerclick': (cellView, evt) => {\r\n                evt.stopPropagation();\r\n                console.log('Element label pointer click');\r\n                this.closeMenus();\r\n                this.changeElementPrimaryText(cellView.model);\r\n            },\r\n        });\r\n\r\n        // Panning and Zooming\r\n        // General approach from: https://medium.com/@ishaanshettigar/guide-panning-and-zooming-in-jointjs-for-free-step-by-step-tutorial-4a56590d2761\r\n\r\n        // handle panning the paper\r\n        // https://stackoverflow.com/questions/28431384/how-to-make-a-paper-draggable\r\n        this.container.addEventListener('mousemove', (evt) => {\r\n            if (this.panStartPosition) {\r\n                this.paper.translate(\r\n                    evt.offsetX - this.panStartPosition.x,\r\n                    evt.offsetY - this.panStartPosition.y);\r\n            }\r\n        });\r\n\r\n        // handle zooming the paper\r\n        // https://stackoverflow.com/a/69196310\r\n        this.paper.on(\"blank:mousewheel\", (evt, x, y, delta) => {\r\n            evt.preventDefault();\r\n            const oldscale = this.paper.scale().sx;\r\n            const newscale = oldscale + 0.2 * delta * oldscale\r\n\r\n            if (newscale > 0.2 && newscale < 5) {\r\n                this.paper.scale(newscale, newscale);\r\n                this.paper.translate(-x * newscale + evt.offsetX, -y * newscale + evt.offsetY);\r\n            }\r\n        });\r\n\r\n        // handle resize of the window\r\n        window.addEventListener('resize', () => {\r\n            console.log('window resize');\r\n            var currentScale = this.paper.scale();\r\n            this.paper.transformToFitContent({ verticalAlign: 'middle', horizontalAlign: 'middle', minScale: currentScale.sx, maxScale: currentScale.sx });\r\n        });\r\n    }\r\n\r\n    public dispose() {\r\n        this.closeMenus();\r\n    }\r\n}\r\n\r\nexport function createFlowEditor(options: FlowEditorOptions): FlowEditor {\r\n    return new FlowEditor(options);\r\n}\r\n\r\nexport class FlowPreview {\r\n    private readonly namespace = joint.shapes;\r\n    private paper: joint.dia.Paper;\r\n    private graph: joint.dia.Graph;\r\n\r\n    constructor(options: FlowPreviewOptions) {\r\n        this.graph = new joint.dia.Graph({}, { cellNamespace: this.namespace });\r\n\r\n        this.paper = new joint.dia.Paper({\r\n            el: options.container,\r\n            model: this.graph,\r\n            width: options.container.offsetWidth,\r\n            height: options.container.offsetHeight,\r\n            interactive: false,\r\n            cellViewNamespace: this.namespace,\r\n        });\r\n\r\n        this.paper.model.fromJSON(JSON.parse(options.graphJson), { cellNamespace: this.namespace });\r\n        this.paper.transformToFitContent({ verticalAlign: 'middle', horizontalAlign: 'middle', maxScale: 2 });\r\n    }\r\n}\r\n\r\nexport function createFlowPreview(options) {\r\n    try {\r\n        const graphJson = JSON.parse(options.graphJson);\r\n        return new FlowPreview(options);\r\n    } catch (error) {\r\n        console.error('Invalid JSON input', error);\r\n        console.error('Options:', options);\r\n    }\r\n}\r\n\r\n\r\n// Define a custom element to represent an Empty Node\r\nexport class EmptyElement extends Node {\r\n    defaults() {\r\n        return {\r\n            type: 'EmptyElement',\r\n            svg: '',\r\n            attrs: {\r\n                body: {\r\n                    fill: 'white',\r\n                    stroke: 'white',\r\n                    strokeWidth: 2,\r\n                    width: 'calc(w)',\r\n                    height: 'calc(h)',\r\n                    rx: 10,\r\n                    ry: 10,\r\n                    class: 'orange-dashed-border',\r\n                },\r\n                label: {\r\n                    //refX: '50%',\r\n                    //refY: '50%',\r\n                    //refDx: 0,\r\n                    //refDy: 0,\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.5*h)',\r\n                    fill: 'black',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    fontWeight: 'bold',\r\n                    text: 'Click to\\nchoose Entity(s)',\r\n                }\r\n            },\r\n            markup: [{\r\n                tagName: 'rect',\r\n                selector: 'body'\r\n            },\r\n            {\r\n                tagName: 'text',\r\n                selector: 'label'\r\n            }],\r\n        }\r\n    }\r\n}\r\nObject.assign(joint.shapes, { EmptyElement });\r\n\r\nexport class EmptyThirdParty extends Node {\r\n    defaults() {\r\n        return {\r\n            type: 'EmptyThirdParty',\r\n            svgPath: '/icons/BranchThirdParty.svg',\r\n            attrs: {\r\n                body: {\r\n                    fill: 'gray',\r\n                    stroke: 'white',\r\n                    strokeWidth: 2,\r\n                    width: 'calc(w)',\r\n                    height: 'calc(h)',\r\n                    rx: 'calc(w / 2)',\r\n                    ry: 'calc(h / 2)',\r\n                    cx: 'calc(w / 2)',\r\n                    cy: 'calc(h / 2)',\r\n                    class: 'orange-dashed-border',\r\n                },\r\n                label: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.5*h)',\r\n                    fill: 'black',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    fontWeight: 'bold',\r\n                    text: 'Click to choose\\nThird Party(s)',\r\n                }\r\n            },\r\n            markup: [{\r\n                tagName: 'ellipse',\r\n                selector: 'body'\r\n            },\r\n            {\r\n                tagName: 'text',\r\n                selector: 'label'\r\n            }],\r\n        }\r\n    }\r\n}\r\nObject.assign(joint.shapes, { EmptyThirdParty });\r\n\r\n// Define a custom element to represent a Corporation/CFC Entity Node\r\nexport class CorporationCFC extends Node {\r\n    defaults() {\r\n        return {\r\n            type: 'CorporationCFC',\r\n            svgPath: '/icons/Corporation.svg',\r\n            attrs: {\r\n                body: {\r\n                    fill: '#0A2065',\r\n                    stroke: 'white',\r\n                    strokeWidth: 2,\r\n                    width: 'calc(w)',\r\n                    height: 'calc(h)',\r\n                    rx: 10,\r\n                    ry: 10,\r\n                },\r\n                label: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.5*h)',\r\n                    fill: 'white',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    fontWeight: 'bold',\r\n                    text: 'Corporation',\r\n                },\r\n                label2: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.75*h)',\r\n                    fill: 'white',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    text: '',\r\n                }\r\n            },\r\n            markup: [{\r\n                tagName: 'rect',\r\n                selector: 'body'\r\n            }, {\r\n                tagName: 'text',\r\n                selector: 'label'\r\n            }, {\r\n                tagName: 'text',\r\n                selector: 'label2'\r\n            }],\r\n        }\r\n    }\r\n}\r\nObject.assign(joint.shapes, { CorporationCFC });\r\n\r\n// Define a custom element to represent a Branch/Third Party Entity Node\r\nexport class BranchThirdParty extends Node {\r\n    defaults() {\r\n        return {\r\n            type: 'BranchThirdParty',\r\n            svgPath: '/icons/BranchThirdParty.svg',\r\n            attrs: {\r\n                body: {\r\n                    fill: 'gray',\r\n                    stroke: 'white',\r\n                    strokeWidth: 2,\r\n                    width: 'calc(w)',\r\n                    height: 'calc(h)',\r\n                    rx: 'calc(w / 2)',\r\n                    ry: 'calc(h / 2)',\r\n                    cx: 'calc(w / 2)',\r\n                    cy: 'calc(h / 2)',\r\n                },\r\n                label: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.5*h)',\r\n                    fill: 'white',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    fontWeight: 'bold',\r\n                    text: 'Corporation',\r\n                },\r\n                label2: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.75*h)',\r\n                    fill: 'white',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    text: '',\r\n                }\r\n            },\r\n            markup: [{\r\n                tagName: 'ellipse',\r\n                selector: 'body'\r\n            }, {\r\n                tagName: 'text',\r\n                selector: 'label'\r\n            }, {\r\n                tagName: 'text',\r\n                selector: 'label2'\r\n            }],\r\n        }\r\n    }\r\n\r\n    setColorByJurisdiction(jurisdiction: Jurisdiction) {\r\n        // Third Parties are always gray\r\n        this.setColor(DefaultValues.ThirdPartyColor);\r\n    }\r\n}\r\nObject.assign(joint.shapes, { BranchThirdParty });\r\n\r\n// Define a custom element to represent a Partnership Entity Node\r\nexport class Partnership extends Node {\r\n    defaults() {\r\n        return {\r\n            type: 'Partnership',\r\n            svgPath: '/icons/Partnership.svg',\r\n            attrs: {\r\n                body: {\r\n                    fill: '#0A2065',\r\n                    stroke: 'white',\r\n                    strokeWidth: 2,\r\n                    width: 'calc(w)',\r\n                    height: 'calc(h)',\r\n                    points: '0,calc(h), calc(w/2),0, calc(w),calc(h)'\r\n                },\r\n                label: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    refY: 0.25,\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.5*h)',\r\n                    fill: 'white',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    fontWeight: 'bold',\r\n                    text: 'Corporation',\r\n                },\r\n                label2: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    refY: 0.25,\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.75*h)',\r\n                    fill: 'white',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    text: '',\r\n                }\r\n            },\r\n            markup: [{\r\n                tagName: 'polygon',\r\n                selector: 'body'\r\n            }, {\r\n                tagName: 'text',\r\n                selector: 'label'\r\n            }, {\r\n                tagName: 'text',\r\n                selector: 'label2'\r\n            }],\r\n        }\r\n    }\r\n}\r\nObject.assign(joint.shapes, { Partnership });\r\n\r\n\r\n// Define a custom element to represent a Hybrid Entity Node\r\nexport class HybridEntity extends Node {\r\n    defaults() {\r\n        return {\r\n            type: 'HybridEntity',\r\n            svgPath: '/icons/HybridEntity.svg',\r\n            attrs: {\r\n                body: {\r\n                    fill: '#0A2065',\r\n                    stroke: 'white',\r\n                    strokeWidth: 2,\r\n                    width: 'calc(w)',\r\n                    height: 'calc(h)',\r\n                    d: 'M 0 0 L calc(w) 0 L calc(w) calc(h) L 0 calc(h) Z M 0 calc(h) L calc(w/2) 0 L calc(w) calc(h)'\r\n                },\r\n                label: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.5*h)',\r\n                    fill: 'white',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    fontWeight: 'bold',\r\n                    text: 'Corporation',\r\n                },\r\n                label2: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.75*h)',\r\n                    fill: 'white',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    text: '',\r\n                }\r\n            },\r\n            markup: [{\r\n                tagName: 'path',\r\n                selector: 'body'\r\n            }, {\r\n                tagName: 'text',\r\n                selector: 'label'\r\n            }, {\r\n                tagName: 'text',\r\n                selector: 'label2'\r\n            }],\r\n        }\r\n    }\r\n}\r\nObject.assign(joint.shapes, { HybridEntity });\r\n\r\n// Define a custom element to represent a Reverse Hybrid Entity Node\r\nexport class ReverseHybrid extends Node {\r\n    defaults() {\r\n        return {\r\n            type: 'ReverseHybrid',\r\n            svgPath: '/icons/ReverseHybrid.svg',\r\n            attrs: {\r\n                body: {\r\n                    fill: '#0A2065',\r\n                    stroke: 'white',\r\n                    strokeWidth: 2,\r\n                    width: 'calc(w)',\r\n                    height: 'calc(h)',\r\n                    transform: 'rotate(180 calc(w/2) calc(h/2))',\r\n                    d: 'M 0 0 L calc(w) 0 L calc(w) calc(h) L 0 calc(h) Z M 0 calc(h) L calc(w/2) 0 L calc(w) calc(h)'\r\n                },\r\n                label: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.5*h)',\r\n                    fill: 'white',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    fontWeight: 'bold',\r\n                    text: 'Corporation',\r\n                },\r\n                label2: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.75*h)',\r\n                    fill: 'white',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    text: '',\r\n                }\r\n            },\r\n            markup: [{\r\n                tagName: 'path',\r\n                selector: 'body'\r\n            }, {\r\n                tagName: 'text',\r\n                selector: 'label'\r\n            }, {\r\n                tagName: 'text',\r\n                selector: 'label2'\r\n            }],\r\n        }\r\n    }\r\n}\r\nObject.assign(joint.shapes, { ReverseHybrid });\r\n\r\n// Define a custom element to represent a DRE Entity Node\r\nexport class Disregarded extends Node {\r\n    defaults() {\r\n        return {\r\n            type: 'Disregarded',\r\n            svgPath: '/icons/Disregarded.svg',\r\n            attrs: {\r\n                body: {\r\n                    fill: '#0A2065',\r\n                    stroke: 'white',\r\n                    strokeWidth: 2,\r\n                    width: 'calc(w)',\r\n                    height: 'calc(h)',\r\n                    rx: 10,\r\n                    ry: 10,\r\n                },\r\n                body2: {\r\n                    fill: 'transparent',\r\n                    stroke: 'white',\r\n                    strokeWidth: 2,\r\n                    rx: 'calc(w / 2)',\r\n                    ry: 'calc(h / 2)',\r\n                    cx: 'calc(w / 2)',\r\n                    cy: 'calc(h / 2)',\r\n                },\r\n                label: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.5*h)',\r\n                    fill: 'white',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    fontWeight: 'bold',\r\n                    text: 'Corporation',\r\n                },\r\n                label2: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.75*h)',\r\n                    fill: 'white',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    text: '',\r\n                }\r\n            },\r\n            markup: [{\r\n                tagName: 'rect',\r\n                selector: 'body'\r\n            }, {\r\n                tagName: 'ellipse',\r\n                selector: 'body2'\r\n            }, {\r\n                tagName: 'text',\r\n                selector: 'label'\r\n            }, {\r\n                tagName: 'text',\r\n                selector: 'label2'\r\n            }],\r\n        }\r\n    }\r\n}\r\nObject.assign(joint.shapes, { Disregarded });\r\n\r\n// Define a custom element to represent an Entity Group Node\r\nexport class EntityGroup extends Node {\r\n    defaults() {\r\n        return {\r\n            type: 'EntityGroup',\r\n            svgPath: '/icons/EntityGroup.svg',\r\n            attrs: {\r\n                body: {\r\n                    fill: '#0A2065',\r\n                    stroke: 'white',\r\n                    strokeWidth: 2,\r\n                    width: 'calc(w)',\r\n                    height: 'calc(h)',\r\n                    rx: 10,\r\n                    ry: 10,\r\n                    x: -5,\r\n                    y: -5,\r\n                },\r\n                body2: {\r\n                    fill: '#0A2065',\r\n                    stroke: 'white',\r\n                    strokeWidth: 2,\r\n                    width: 'calc(w)',\r\n                    height: 'calc(h)',\r\n                    rx: 10,\r\n                    ry: 10,\r\n                    x: 5,\r\n                    y: 5,\r\n                },\r\n                label: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.5*h)',\r\n                    fill: 'white',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    fontWeight: 'bold',\r\n                    text: '',\r\n                },\r\n                label2: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'middle',\r\n                    x: 'calc(0.5*w)',\r\n                    y: 'calc(0.75*h)',\r\n                    fill: 'white',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    text: '',\r\n                }\r\n            },\r\n            markup: [{\r\n                tagName: 'rect',\r\n                selector: 'body2'\r\n            },\r\n            {\r\n                tagName: 'rect',\r\n                selector: 'body'\r\n            },\r\n            {\r\n                tagName: 'text',\r\n                selector: 'label'\r\n            },\r\n            {\r\n                tagName: 'text',\r\n                selector: 'label2'\r\n            }],\r\n        }\r\n    }\r\n\r\n    setColor(color: string) {\r\n        this.attr('body/fill', color);\r\n        this.attr('body2/fill', color);\r\n    }\r\n\r\n    setColorByJurisdiction(jurisdiction: Jurisdiction) {\r\n        switch (jurisdiction) {\r\n            case Jurisdiction.US:\r\n                this.setColor(DefaultValues.PrimaryColor);\r\n                break;\r\n            case Jurisdiction.NonUS:\r\n                this.setColor(DefaultValues.SecondaryColor);\r\n                break;\r\n            case Jurisdiction.Mixed:\r\n                this.attr('body/fill', DefaultValues.PrimaryColor);\r\n                this.attr('body2/fill', DefaultValues.SecondaryColor);\r\n                break;\r\n            default:\r\n                this.setColor(DefaultValues.PrimaryColor);\r\n                break;\r\n        }\r\n    }\r\n}\r\nObject.assign(joint.shapes, { EntityGroup });\r\n\r\n// Define a custom element to represent a drawn rectangle\r\nexport class DrawnRectangle extends joint.shapes.standard.Rectangle {\r\n    defaults() {\r\n        return {\r\n            type: 'DrawnRectangle',\r\n            attrs: {\r\n                body: {\r\n                    fill: 'none',\r\n                    stroke: 'black',\r\n                    strokeWidth: 3,\r\n                    width: 'calc(w)',\r\n                    height: 'calc(h)',\r\n                },\r\n                'label-background': {\r\n                    ref: 'label',\r\n                    fill: 'white',\r\n                    stroke: '#D0D0CE',\r\n                    strokeWidth: 1,\r\n                    width: 'calc(w+12)',\r\n                    height: 'calc(h+10)',\r\n                    x: 'calc(x-6)',\r\n                    y: 'calc(y-5)',\r\n                    rx: 1,\r\n                    ry: 1,\r\n                },\r\n                label: {\r\n                    textAnchor: 'middle',\r\n                    textVerticalAnchor: 'top',\r\n                    x: 'calc(0.5*w)',\r\n                    y: '-7',\r\n                    fill: 'black',\r\n                    fontSize: 14,\r\n                    fontFamily: '\"Open Sans\", sans-serif',\r\n                    fontWeight: 'bold',\r\n                    text: '',\r\n                    cursor: 'text',\r\n                    event: 'element:label:pointerclick',\r\n                },\r\n            },\r\n            markup: [{\r\n                tagName: 'rect',\r\n                selector: 'body'\r\n            },\r\n            {\r\n                tagName: 'rect',\r\n                selector: 'label-background'\r\n            }, {\r\n                tagName: 'text',\r\n                selector: 'label'\r\n            }],\r\n        }\r\n    }\r\n\r\n    public setLabel(label: string) {\r\n        this.attr('label/text', label);\r\n    }\r\n}\r\n\r\nObject.assign(joint.shapes, { DrawnRectangle });\r\n\r\nexport class PhysicalLink extends joint.shapes.standard.Link {\r\n    defaults() {\r\n        return joint.util.defaultsDeep({\r\n            type: 'PhysicalLink',\r\n            color: '#CE1210', // custom attribute - metadata only\r\n            attrs: {\r\n                line: {\r\n                    stroke: '#CE1210',\r\n                    strokeWidth: 3,\r\n                    targetMarker: {\r\n                        d: 'M 10 -5 0 0 10 5 Z',\r\n                    }\r\n                },\r\n            },\r\n            labels: [{\r\n                attrs: {\r\n                    rect: {\r\n                        ref: 'text',\r\n                        width: 'calc(w+12)',\r\n                        height: 'calc(h+10)',\r\n                        x: 'calc(x-6)',\r\n                        y: 'calc(y-5)',\r\n                        stroke: '#D0D0CE',\r\n                        cursor: 'pointer',\r\n                    },\r\n                    text: {\r\n                        textAnchor: 'middle',\r\n                        textVerticalAnchor: 'middle',\r\n                        fill: 'black',\r\n                        fontSize: 14,\r\n                        fontFamily: '\"Open Sans\", sans-serif',\r\n                        fontWeight: 'bold',\r\n                        text: 'Physical',\r\n                    }\r\n                }\r\n            }]\r\n        }, joint.shapes.standard.Link.prototype.defaults);\r\n    }\r\n}\r\n\r\nexport class LegalLink extends joint.shapes.standard.Link {\r\n    defaults() {\r\n        return joint.util.defaultsDeep({\r\n            type: 'LegalLink',\r\n            color: '#99C13C', // custom attribute - metadata only\r\n            dashed: true, // custom attribute - metadata only\r\n            attrs: {\r\n                line: {\r\n                    stroke: '#99C13C',\r\n                    strokeWidth: 3,\r\n                    strokeDasharray: '6, 5',\r\n                    targetMarker: {\r\n                        d: 'M 10 -5 0 0 10 5 Z',\r\n                    }\r\n                },\r\n            },\r\n            labels: [{\r\n                attrs: {\r\n                    rect: {\r\n                        ref: 'text',\r\n                        width: 'calc(w+12)',\r\n                        height: 'calc(h+10)',\r\n                        x: 'calc(x-6)',\r\n                        y: 'calc(y-5)',\r\n                        stroke: '#D0D0CE',\r\n                        cursor: 'pointer',\r\n                    },\r\n                    text: {\r\n                        textAnchor: 'middle',\r\n                        textVerticalAnchor: 'middle',\r\n                        fill: 'black',\r\n                        fontSize: 14,\r\n                        fontFamily: '\"Open Sans\", sans-serif',\r\n                        fontWeight: 'bold',\r\n                        text: 'Legal Title',\r\n                    }\r\n                }\r\n            }]\r\n        }, joint.shapes.standard.Link.prototype.defaults);\r\n    }\r\n}\r\n\r\nexport class PaymentLink extends joint.shapes.standard.Link {\r\n    defaults() {\r\n        return joint.util.defaultsDeep({\r\n            type: 'PaymentLink',\r\n            color: '#9B9B9D', // custom attribute - metadata only\r\n            dashed: true, // custom attribute - metadata only\r\n            attrs: {\r\n                line: {\r\n                    stroke: '#9B9B9D',\r\n                    strokeWidth: 3,\r\n                    strokeDasharray: '6, 5',\r\n                    targetMarker: {\r\n                        d: 'M 10 -5 0 0 10 5 Z',\r\n                    }\r\n                },\r\n            },\r\n            labels: [{\r\n                attrs: {\r\n                    rect: {\r\n                        ref: 'text',\r\n                        width: 'calc(w+12)',\r\n                        height: 'calc(h+10)',\r\n                        x: 'calc(x-6)',\r\n                        y: 'calc(y-5)',\r\n                        stroke: '#D0D0CE',\r\n                        cursor: 'pointer',\r\n                    },\r\n                    text: {\r\n                        textAnchor: 'middle',\r\n                        textVerticalAnchor: 'middle',\r\n                        fill: 'black',\r\n                        fontSize: 14,\r\n                        fontFamily: '\"Open Sans\", sans-serif',\r\n                        fontWeight: 'bold',\r\n                        text: 'Payment',\r\n                    }\r\n                }\r\n            }]\r\n        }, joint.shapes.standard.Link.prototype.defaults);\r\n    }\r\n}\r\n\r\nclass ServiceLink extends joint.shapes.standard.Link {\r\n    defaults() {\r\n        return joint.util.defaultsDeep({\r\n            type: 'ServiceLink',\r\n            color: 'black', // custom attribute - metadata only\r\n            attrs: {\r\n                line: {\r\n                    stroke: 'black',\r\n                    strokeWidth: 3,\r\n                    targetMarker: {\r\n                        d: 'M 10 -5 0 0 10 5 Z',\r\n                    }\r\n                },\r\n            },\r\n            labels: [{\r\n                attrs: {\r\n                    rect: {\r\n                        ref: 'text',\r\n                        width: 'calc(w+12)',\r\n                        height: 'calc(h+10)',\r\n                        x: 'calc(x-6)',\r\n                        y: 'calc(y-5)',\r\n                        stroke: '#D0D0CE',\r\n                        cursor: 'pointer',\r\n                    },\r\n                    text: {\r\n                        textAnchor: 'middle',\r\n                        textVerticalAnchor: 'middle',\r\n                        fill: 'black',\r\n                        fontSize: 14,\r\n                        fontFamily: '\"Open Sans\", sans-serif',\r\n                        fontWeight: 'bold',\r\n                        text: 'Service',\r\n                    }\r\n                }\r\n            }]\r\n        }, joint.shapes.standard.Link.prototype.defaults);\r\n    }\r\n}\r\n\r\nclass IPTransferLink extends joint.shapes.standard.Link {\r\n    defaults() {\r\n        return joint.util.defaultsDeep({\r\n            type: 'IPTransferLink',\r\n            color: '#FFA500', // custom attribute - metadata only\r\n            attrs: {\r\n                line: {\r\n                    stroke: '#FFA500',\r\n                    strokeWidth: 3,\r\n                    targetMarker: {\r\n                        d: 'M 10 -5 0 0 10 5 Z',\r\n                    }\r\n                },\r\n            },\r\n            labels: [{\r\n                attrs: {\r\n                    rect: {\r\n                        ref: 'text',\r\n                        width: 'calc(w+12)',\r\n                        height: 'calc(h+10)',\r\n                        x: 'calc(x-6)',\r\n                        y: 'calc(y-5)',\r\n                        stroke: '#D0D0CE',\r\n                        cursor: 'pointer',\r\n                    },\r\n                    text: {\r\n                        textAnchor: 'middle',\r\n                        textVerticalAnchor: 'middle',\r\n                        fill: 'black',\r\n                        fontSize: 14,\r\n                        fontFamily: '\"Open Sans\", sans-serif',\r\n                        fontWeight: 'bold',\r\n                        text: 'IP Transfer',\r\n                    }\r\n                }\r\n            }]\r\n        }, joint.shapes.standard.Link.prototype.defaults);\r\n    }\r\n}\r\n\r\nclass IPLicenseLink extends joint.shapes.standard.Link {\r\n    defaults() {\r\n        return joint.util.defaultsDeep({\r\n            type: 'IPLicenseLink',\r\n            color: '#8E25AB', // custom attribute - metadata only\r\n            attrs: {\r\n                line: {\r\n                    stroke: '#8E25AB',\r\n                    strokeWidth: 3,\r\n                    targetMarker: {\r\n                        d: 'M 10 -5 0 0 10 5 Z',\r\n                    }\r\n                },\r\n            },\r\n            labels: [{\r\n                attrs: {\r\n                    rect: {\r\n                        ref: 'text',\r\n                        width: 'calc(w+12)',\r\n                        height: 'calc(h+10)',\r\n                        x: 'calc(x-6)',\r\n                        y: 'calc(y-5)',\r\n                        stroke: '#D0D0CE',\r\n                        cursor: 'pointer',\r\n                    },\r\n                    text: {\r\n                        textAnchor: 'middle',\r\n                        textVerticalAnchor: 'middle',\r\n                        fill: 'black',\r\n                        fontSize: 14,\r\n                        fontFamily: '\"Open Sans\", sans-serif',\r\n                        fontWeight: 'bold',\r\n                        text: 'IP License',\r\n                    }\r\n                }\r\n            }]\r\n        }, joint.shapes.standard.Link.prototype.defaults);\r\n    }\r\n}\r\n\r\nclass AgreementLink extends joint.shapes.standard.Link {\r\n    defaults() {\r\n        return joint.util.defaultsDeep({\r\n            type: 'AgreementLink',\r\n            color: '#256F8C', // custom attribute - metadata only\r\n            attrs: {\r\n                line: {\r\n                    stroke: '#256F8C',\r\n                    strokeWidth: 3,\r\n                    targetMarker: {\r\n                        d: 'M 10 -5 0 0 10 5 Z',\r\n                    },\r\n                    sourceMarker: {\r\n                        d: 'M 10 -5 0 0 10 5 Z',\r\n                    }\r\n                },\r\n            },\r\n            labels: [{\r\n                attrs: {\r\n                    rect: {\r\n                        ref: 'text',\r\n                        width: 'calc(w+12)',\r\n                        height: 'calc(h+10)',\r\n                        x: 'calc(x-6)',\r\n                        y: 'calc(y-5)',\r\n                        stroke: '#D0D0CE',\r\n                        cursor: 'pointer',\r\n                    },\r\n                    text: {\r\n                        textAnchor: 'middle',\r\n                        textVerticalAnchor: 'middle',\r\n                        fill: 'black',\r\n                        fontSize: 14,\r\n                        fontFamily: '\"Open Sans\", sans-serif',\r\n                        fontWeight: 'bold',\r\n                        text: 'Agreement',\r\n                    }\r\n                }\r\n            }]\r\n        }, joint.shapes.standard.Link.prototype.defaults);\r\n    }\r\n}\r\n\r\nclass MiscellaneousLink extends joint.shapes.standard.Link {\r\n    defaults() {\r\n        return joint.util.defaultsDeep({\r\n            type: 'MiscellaneousLink',\r\n            color: '#EB8100', // custom attribute - metadata only\r\n            dashed: true, // custom attribute - metadata only\r\n            attrs: {\r\n                line: {\r\n                    stroke: '#EB8100',\r\n                    strokeWidth: 3,\r\n                    strokeDasharray: '6, 5',\r\n                    targetMarker: {\r\n                        d: 'M 10 -5 0 0 10 5 Z',\r\n                    }\r\n                },\r\n            },\r\n            labels: [{\r\n                attrs: {\r\n                    rect: {\r\n                        ref: 'text',\r\n                        width: 'calc(w+12)',\r\n                        height: 'calc(h+10)',\r\n                        x: 'calc(x-6)',\r\n                        y: 'calc(y-5)',\r\n                        stroke: '#D0D0CE',\r\n                        cursor: 'pointer',\r\n                    },\r\n                    text: {\r\n                        textAnchor: 'middle',\r\n                        textVerticalAnchor: 'middle',\r\n                        fill: 'black',\r\n                        fontSize: 14,\r\n                        fontFamily: '\"Open Sans\", sans-serif',\r\n                        fontWeight: 'bold',\r\n                        text: 'Miscellaneous',\r\n                    }\r\n                }\r\n            }]\r\n        }, joint.shapes.standard.Link.prototype.defaults);\r\n    }\r\n}\r\n\r\nObject.assign(joint.shapes, { PhysicalLink, LegalLink, PaymentLink, ServiceLink, IPTransferLink, IPLicenseLink, AgreementLink, MiscellaneousLink });\r\n"],"names":["__webpack_require__","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","argsTag","arrayTag","boolTag","dateTag","errorTag","funcTag","mapTag","numberTag","objectTag","regexpTag","setTag","stringTag","symbolTag","weakMapTag","arrayBufferTag","dataViewTag","float32Tag","float64Tag","int8Tag","int16Tag","int32Tag","uint8Tag","uint8ClampedTag","uint16Tag","uint32Tag","CLONEABLE_TAGS","rsAstralRange","rsDingbatRange","rsLowerRange","rsUpperRange","rsBreakRange","rsMathOpRange","rsApos","rsBreak","rsCombo","rsDingbat","rsLower","rsMisc","rsFitz","rsNonAstral","rsRegional","rsSurrPair","rsUpper","rsMiscLower","rsMiscUpper","rsOptContrLower","rsOptContrUpper","reOptMod","rsOptVar","rsSeq","join","rsEmoji","reUnicodeWords","RegExp","HASH_UNDEFINED","reTypedTag","rsSymbol","reUnicode","reIsDeepProp","reIsPlainProp","charCodeOfDot","charCodeAt","reEscapeChar","rePropName","reIsUint","hasUnicodeWord","test","bind","reAsciiWord","hasUnicode","string","stringToArray","match","unicodeToArray","split","asciiToArray","values","object","keys","map","isArrayLike","arrayLikeKeys","inherited","isArr","Array","isArray","isArg","isObjectLike","getTag","isType","isTypedArray","skipIndexes","length","result","index","isIndex","push","assocIndexOf","array","eq","other","isIterateeCall","isObject","type","isPrototype","Ctor","constructor","assignValue","objValue","undefined","copyObject","source","props","isSymbol","copyArray","toString","cloneArrayBuffer","arrayBuffer","byteLength","Uint8Array","set","cloneTypedArray","typedArray","isDeep","buffer","byteOffset","initCloneObject","create","getPrototypeOf","getSymbols","getOwnPropertySymbols","filter","symbol","propertyIsEnumerable","getAllKeys","getSymbolsIn","getAllKeysIn","getMapData","__data__","data","isKeyable","baseIsEqual","stack","baseIsEqualDeep","equalFunc","objIsArr","othIsArr","objTag","othTag","objIsObj","othIsObj","isSameTag","Stack","equalArrays","equalByTag","objIsWrapped","othIsWrapped","objUnwrapped","othUnwrapped","objProps","objLength","objStacked","othStacked","skipCtor","othValue","objCtor","othCtor","equalObjects","compareUnordered","arrLength","arrStacked","seen","SetCache","compared","arrValue","some","othIndex","cacheHas","predicate","cache","has","compareArrayBufferTag","tag","name","message","convert","mapToArray","setToArray","size","stacked","valueOf","forEach","isKey","castPath","path","replace","expression","quote","subString","trim","stringToPath","toKey","compareAscending","valIsDefined","valIsNull","valIsReflexive","valIsSymbol","othIsDefined","othIsNull","othIsReflexive","othIsSymbol","diff","includes","indexOf","isCommon","valuesLength","outer","computed","valuesIndex","baseClone","isFlat","isFull","customizer","input","initCloneArray","isFunc","copySymbolsIn","copySymbols","assign","Constructor","dataView","cloneDataView","regexp","exec","lastIndex","cloneRegExp","initCloneByTag","isMap","subValue","isSet","add","keysIn","slice","nested","newValue","Number","MAX_SAFE_INTEGER","unset","lastSegment","safeGet","createAssigner","assigner","isMerge","sources","guard","a","b","baseMerge","srcIndex","srcValue","baseMergeDeep","assignMergeValue","mergeFunc","isTyped","isPlainObject","isArguments","toPlainObject","baseEach","collection","iteratee","keysFunc","iterable","baseFor","baseForOwn","createSet","Set","customDefaultsMerge","baseOrderBy","iteratees","orders","criteriaIndex","eachIndex","criteria","sort","objCriteria","othCriteria","ordersLength","order","compareMultiple","baseSortBy","isStrictComparable","matchesStrictComparable","hasIn","hasPath","baseHasIn","baseMatches","matchData","getMatchData","baseIsMatch","baseIteratee","val","basePropertyDeep","property","getIteratee","arguments","arrayReduce","accumulator","initAccum","baseReduce","eachFunc","isFlattenable","isConcatSpreadable","baseFlatten","depth","isStrict","hasFunc","upperFirst","strSymbols","chr","trailing","start","end","castSlice","entries","this","ListCache","clear","pairs","LARGE_ARRAY_SIZE","MapCache","entry","pop","splice","Hash","Map","isNumber","isString","defaults","propsLength","propsIndex","defaultsDeep","args","merge","apply","invoke","invokeProperty","func","last","sortedIndex","low","high","valIsNaN","valIsUndefined","setLow","mid","Math","floor","min","uniq","seenIndex","clone","cloneDeep","isEmpty","baseKeys","isEqual","proto","toArray","iterator","next","done","sortBy","flat","flattenDeep","Infinity","without","difference","union","arrays","defaultValue","paths","pick","basePickBy","basePick","camelCase","pattern","unicodeWords","asciiWords","words","reduce","word","toLowerCase","idCounter","uniqueId","prefix","WeakMap","remove","delete","dataPriv","dataUser","Event","src","originalEvent","isDefaultPrevented","defaultPrevented","returnTrue","returnFalse","target","currentTarget","relatedTarget","timeStamp","Date","now","envelope","isPropagationStopped","isImmediatePropagationStopped","preventDefault","evt","stopPropagation","stopImmediatePropagation","configurable","writable","addProp","window","document","documentElement","rTypeNamespace","rNotHtmlWhite","selector","Dom","fn","guid","first","second","len","i","j","parseHTML","context","implementation","createHTMLDocument","base","createElement","href","location","head","appendChild","body","innerHTML","scripts","getElementsByTagName","from","childNodes","pushStack","elements","ret","prevObject","find","el","nodeType","contains","querySelectorAll","newElements","prevElements","concat","addBack","matches","node","rQuickExpr","Error","$root","getElementById","event","special","elem","eventType","events","on","types","one","origFn","off","handler","elemData","handleObjIn","eventHandle","handle","e","dispatch","typesArr","origType","ns","namespaces","delegateType","bindType","handleObj","namespace","handlers","delegateCount","setup","addEventListener","mappedTypes","rNamespace","origCount","teardown","removeEventListener","nativeEvent","fix","delegateTarget","eventsData","preDispatch","handlerQueue","matched","origSpecial","postDispatch","button","cur","parentNode","disabled","matchedHandlers","matchedSelectors","sel","round","PI","scale","linear","domain","range","domainSpan","rangeSpan","normalizeAngle","angle","snapToGrid","gridSize","toDeg","rad","toRad","deg","over360","random","max","temp","cos","sin","atan2","bearing","p","q","lat1","y","lat2","lon1","x","lon2","dLon","parseInt","squaredLength","x0","y0","sqrt","Point","Line","Ellipse","Rect","Polyline","Polygon","Curve","Path","abs","pow","xy","parseFloat","fromPolar","distance","origin","x1","x2","y1","y2","chooseClosest","points","n","closest","minSqrDistance","sqrDistance","squaredDistance","adhereToRect","r","containsPoint","width","height","angleBetween","p1","p2","equals","NaN","theta","point","changeInAngle","dx","dy","ref","offset","cross","dot","lerp","t","magnitude","manhattanDistance","move","normalize","reflection","rotate","cosAngle","sinAngle","precision","f","sx","sy","gx","gy","toJSON","toPolar","serialize","update","vectorAngle","translate","horizontalPoint","bbox","left","top","right","bottom","closestPoint","pointAt","closestPointNormalizedLength","closestPointLength","product","vector","cpNormalizedLength","closestPointTangent","tangentAt","divideAt","ratio","dividerPoint","divideAtLength","pointAtLength","l","intersect","shape","opt","intersectionWithLine","intersection","line","pt1Dir","pt2Dir","det","deltaPt","alpha","beta","isDifferentiable","midpoint","parallel","eRef","sRef","fromStart","lineLength","pointOffset","setLength","currentLength","scaleFactor","tangentStart","tangentLine","tangentAtLength","tx","ty","c","fromRect","rect","center","normalizedDistance","ellipse","inflate","intersections","a1","a2","rx","ry","dir","mDir","mDiff","d","root","ta","tb","intersectionWithLineFromCenterToPoint","pointNearestToPoint","m","mSquared","aSquared","bSquared","tangentTheta","q1","q3","w","h","fromEllipse","fromPointUnion","minX","minY","maxX","maxY","fromRectUnion","rects","mX","mY","rotateAroundCenter","st","ct","bottomLeft","bottomLine","bottomRight","bottomMiddle","strict","containsRect","r0","r1","w0","h0","w1","h1","corner","mr","nr","myOrigin","myCorner","rOrigin","rCorner","pt","rectLines","topLine","rightLine","leftLine","dedupeArr","sides","connector","topLeft","leftMiddle","maxRectScaleToFit","sx1","sx2","sx3","sx4","sy1","sy2","sy3","sy4","ox","oy","p3","topRight","p4","maxRectUniformScaleToFit","moveAndExpand","newx","newy","newwidth","newheight","sideNearestToPoint","rightMiddle","distToLeft","distToRight","distToTop","side","topMiddle","parsePoints","svgString","trimmedString","coords","numCoords","clonePoints","numPoints","newPoints","convexHull","startPoint","sortedPointRecords","record1","record2","sortOutput","startPointRecord","unshift","currentPointRecord","currentPoint","lastHullPointRecord","lastHullPoint","secondLastHullPointRecord","secondLastHullPoint","lowestHullIndex","insidePoints","hullPointRecords","correctTurnFound","crossProduct","indexOfLowestHullIndexRecord","currentHullIndex","hullPointRecordsReordered","newFirstChunk","newSecondChunk","hullPoints","parse","cpLength","lengthPoints","startIndex","endIndex","numIntersections","segment","ray","rayEnd","xDifference","close","otherPoints","otherPoint","l2","int","simplify","threshold","currentIndex","middleIndex","firstPoint","middlePoint","lastPoint","lastValidLine","output","controlPoint1","controlPoint2","extend","child","inheritedProperty","getOwnPropertyDescriptor","throughPoints","getFirstControlPoints","rhs","tmp","controlPoints","knots","firstControlPoints","secondControlPoints","getCurveControlPoints","curves","t1","t2","b2ac","sqrtb2ac","x3","y3","tvalues","bounds","mt","jlen","X","Y","pointAtT","closestPointT","PRECISION","localOpt","subdivisions","getSubdivisions","lengthAtT","investigatedSubdivision","investigatedSubdivisionStartT","investigatedSubdivisionEndT","distFromStart","distFromEnd","chordLength","minSumDist","subdivisionSize","currentSubdivision","startDist","endDist","sumDist","precisionRatio","startPrecisionRatio","endPrecisionRatio","divided","divide","startDist1","endDist1","sumDist1","startDist2","endDist2","tangentAtT","toPolyline","divideAtT","tAt","tAtLength","dividerPoints","getSkeletonPoints","startControl1","startControlPoint1","startControl2","startControlPoint2","divider","dividerControl1","dividerControlPoint1","dividerControl2","dividerControlPoint2","endpointDistance","control1","control2","midpoint1","midpoint2","midpoint3","subControl1","subControl2","previousLength","minIterations","iteration","newSubdivisions","numSubdivisions","numNewSubdivisions","skeletonPoints","baselinePointDistFromStart","baselinePointDistFromEnd","curveLength","newBaselinePointDistFromStart","newBaselinePointDistFromEnd","baseline1Length","baseline2Length","toPoints","arg","segments","acc","isSegment","appendSegment","previousObj","createSegment","applyToNew","argsArray","Function","pathData","commands","numCommands","segmentConstructor","segmentTypes","currentSegment","numSegments","previousSegment","currentArg","prepareSegment","isVisible","segmentBBox","segmentSubdivisions","getSegmentSubdivisions","minSquaredDistance","segmentClosestPointT","segmentClosestPoint","segmentIndex","polylines","toPolylines","numPolylines","dividedSegmentIndex","lastValidSegment","lastValidSegmentIndex","getSegment","pathCopy","replaceSegment","divisionStartIndex","divisionMidIndex","divisionEndIndex","removeSegment","movetoEnd","insertSegment","secondPathSegmentIndexConversion","originalSegment","subpathStartSegment","convertedSegment","otherSegments","otherSegment","getSubpaths","validate","subpaths","isSubpathStart","nextSegment","polyline","polylineIntersection","isValid","tValue","precisison","lastVisibleSegment","updateSubpathStart","updateSubpathStartSegment","removedSegment","replacedSegment","segmentAt","segmentIndexAt","segmentAtLength","segmentIndexAtLength","lastVisibleSegmentIndex","partialPoints","currentSegmentSubdivisions","subdivisionPoints","curve","segmentPrototype","Lineto","outputArray","segmentPoint","segmentCoords","linetoPrototype","Curveto","segmentPoints","curvetoPrototype","c1","c2","Moveto","movetoPrototype","Closepath","closepathPrototype","L","C","M","Z","z","regexSupportedData","isDataSupported","bezier","curveThroughPoints","console","warn","getCurveDivider","p0","getInversionSolver","exists","shape1","shape2","shape1opt","shape2opt","lineWithLine","ellipseWithLine","ellipseWithEllipse","rectWithLine","rectWithEllipse","rectWithRect","polylineWithLine","polylineWithEllipse","polylineWithRect","polylineWithPolyline","polygonWithLine","polygonWithEllipse","polygonWithRect","polygonWithPolyline","polygonWithPolygon","pathWithLine","pathWithEllipse","pathWithRect","pathWithPolyline","pathWithPolygon","pathWithPath","line1","line2","s1x","s1y","s2x","s2y","s3x","s3y","s","rex","rey","xe","ye","rex_2","rey_2","A","B","D","ellipse1","ellipse2","e1","e2","sinW1","cosW1","sinW2","cosW2","sinW1s","cosW1s","sinCos1","sinW2s","cosW2s","sinCos2","a1s","b1s","a2s","b2s","A1","A2","B1","B2","C1","C2","D1","D2","E1","E2","F1","F2","l3","det3","l0","l1","delta1","det2","delta2","delta3","_ellipsesIntersection","rect1","rect2","_polylineWithLine","interior","_polylineWithEllipse","_polylineWithRect","polyline1","polyline2","_polylineWithPolyline","polygon","polygon1","polygon2","_polylineWithPolygon","pathOpt","subpath","_pathWithPolyline","path1","path2","pathOpt1","pathOpt2","thisPoints","thisPolyline","SVGAngle","svg","xmlns","xml","xlink","xhtml","math","V","attrs","children","isV","createSvgDocument","svgDoc","arrayOfVels","childNode","importNode","firstChild","createElementNS","ensureId","setAttributes","append","VPrototype","annotateTextLine","lineNode","lineAnnotations","includeAnnotationIndices","eol","lineHeight","baseSize","maxFontSize","fontMetrics","lastJ","annotation","fontSize","annotationAttrs","vTSpan","tspanNode","textContent","annotationClass","addClass","attr","annotations","isFinite","createTextNode","id","getTransformToElement","isSVGGraphicsElement","targetCTM","toNode","getScreenCTM","nodeCTM","inverse","multiply","createSVGMatrix","transform","matrix","isUndefined","transformStringToMatrix","absolute","matrixToTransformString","svgTransform","createSVGTransform","baseVal","appendItem","transformAttr","parseTransformString","newTranslate","cx","cy","newRotate","newScale","withoutTransformations","box","ownerSVGElement","getBBox","clientLeft","clientTop","clientWidth","clientHeight","transformRect","outputBBox","options","recursive","childBBox","currentChild","emRegex","convertEmToPx","em","numerical","text","content","sanitizeText","displayEmpty","textPath","verticalAnchor","textVerticalAnchor","namedVerticalAnchor","iai","defaultLineHeight","autoLineHeight","empty","containerNode","doc","vel","textPathElement","linkedPath","appendTo","defs","createTextPathNode","createDocumentFragment","annotatedY","lines","linesMetrics","lastI","lineMetrics","lineClassName","annotateString","iLineHeight","lineNodeStyle","style","fillOpacity","strokeOpacity","lineFontSize","findAnnotationsAtIndex","fs","setAttribute","className","alignment","baseSizePx","flMaxFont","rLineHeights","lineHeightPx","llMaxFont","calculateDY","rh","removeAttr","trueName","attributeNames","local","qualifyAttr","hasAttributeNS","removeAttributeNS","hasAttribute","removeAttribute","attributes","getAttribute","attrName","normalizePath","tagName","normalizePathData","removeChild","els","prepend","before","parent","insertBefore","SVGSVGElement","toUpperCase","defsNode","cloneNode","findOne","found","querySelector","vels","nodes","previousSibling","findParentByClass","terminator","hasClass","bup","compareDocumentPosition","toLocalPoint","createSVGPoint","globalPoint","matrixTransform","globalToLocalMatrix","translateCenterToPoint","translateAndAutoOrient","position","reference","translateToOrigin","setTranslate","rotateAroundOrigin","setRotate","translateFromOrigin","finalPosition","ctm","setMatrix","animateAlongPath","animateMotion","mpath","beginElement","animation","animators","animationID","id2anim","targets","getTargets","animator","Animator","register","noHTMLWhitespaceRegex","getTokenList","str","classList","removeClass","toggleClass","toAdd","tokens","toggle","sample","interval","getTotalLength","samples","getPointAtLength","convertToPath","convertToPathData","convertLineToPathData","convertPolygonToPathData","convertPolylineToPathData","convertEllipseToPathData","convertCircleToPathData","convertRectToPathData","toGeometryShape","getPointsFromSvgNode","findIntersection","spot","gRect","rectMatrix","rectMatrixComponents","decomposeMatrix","resetRotation","rotation","gp","refDistance","minDistance","closestSamples","setAttributeNS","XMLString","parseXML","async","createSVGStyle","stylesheet","createCDATASection","createDocument","nodeName","parser","DOMParser","parseFromString","error","_attributeNames","Proxy","supportCamelCaseAttributes","combinedKey","transformSeparatorRegex","transformRegex","transformFunctionRegex","transformTranslateRegex","transformRotateRegex","transformScaleRegex","transformationMatrix","transformMatches","numMatches","transformFunctionMatch","transformFunction","scaleNonUniform","skewX","skewY","separator","decomposedMatrix","translateX","translateY","scaleX","scaleY","transformations","translateMatch","rotateMatch","scaleMatch","deltaTransformPoint","px","py","matrixToScale","matrixToRotate","matrixToTranslate","isVElement","SVGElement","svgDocument","svgMatrix","component","SVGMatrix","createSVGTransformFromMatrix","corner1","corner2","corner3","corner4","transformPoint","transformLine","transformPolyline","inPoints","outPoints","styleToObject","styleString","styles","pair","createSlicePathData","innerRadius","outerRadius","startAngle","endAngle","svgArcMax","a0","da","df","c0","s0","s1","mergeAttrs","batch","item","prev","compacted","JSON","stringify","findAnnotationsBetweenIndexes","shiftAnnotations","svgPointsToPath","nodePoints","numberOfItems","getItem","KAPPA","circle","cd","cdx","cdy","rectToPath","topRx","bottomRx","topRy","bottomRy","spaces","pathCommand","pathValues","tan","asin","q2c","ax","ay","_13","_23","a2c","large_arc_flag","sweep_flag","_120","res","f1","f2","rx2","ry2","k","toFixed","f2old","x2old","y2old","s2","hx","hy","m1","m2","m3","m4","newres","ii","pathArray","pathString","paramCounts","v","String","params","parsePathString","pa0","mx","my","jj","pa","kk","pathToAbsolute","bx","by","qx","qy","processPath","pcom","nx","ny","T","Q","fixArc","pp","shift","pi","pcoms","pfirst","seg","seglen","g","cleanNodesData","cleanNodeData","removeNodes","detach","clones","html","prependTo","requireUnits","setCSSProperty","css","dataset","setNodesClass","method","closestEl","ancestorEl","getComputedStyle","offsetWidth","borderTopWidth","borderBottomWidth","paddingTop","paddingBottom","offsetHeight","borderLeftWidth","borderRightWidth","paddingLeft","paddingRight","offsetParent","$el","parentOffset","getBoundingClientRect","ownerDocument","$parentOffset","parentOffsetElementPosition","offsetParentStyles","marginTop","marginLeft","coordinates","getClientRects","scrollY","scrollX","currentStyle","currentOffset","topDifference","leftDifference","cssProp","animationKey","cssReset","animate","properties","stop","animateNode","duration","easing","delay","complete","delayId","setTimeout","fired","endEvent","cssValues","transitionProperties","wrappedCallback","callbackId","clearTimeout","propertySetters","outerWidth","outerHeight","innerWidth","innerHeight","scrollLeft","scrollTop","propertiesMap","methods","methodName","load","noBubble","orig","related","dbltap","targetData","getTime","delta","lastTouch","addClassNamePrefix","_className","substr","parseDOMJSON","json","selectors","groupSelectors","svgNamespace","fragment","parseNode","siblingsDef","nodeDef","textNode","namespaceURI","wrapperNode","nodeSelector","nodeGroups","groupSelector","nodeGroup","group","childrenDef","hashCode","hash","getByPath","delimiter","isGetSafe","setByPath","diver","unsetByPath","normalizeEvent","normalized","touch","changedTouches","useElement","correspondingUseElement","nextFrame","raf","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","oRequestAnimationFrame","msRequestAnimationFrame","lastTime","callback","currTime","timeToCall","rest","cancelFrame","client","caf","cancelAnimationFrame","webkitCancelAnimationFrame","webkitCancelRequestAnimationFrame","msCancelAnimationFrame","msCancelRequestAnimationFrame","oCancelAnimationFrame","oCancelRequestAnimationFrame","mozCancelAnimationFrame","mozCancelRequestAnimationFrame","isPercentage","parseCssNumeric","restrictUnits","number","isNaN","validUnitExp","unit","getUnit","splitWordWithEOL","eolWords","jl","replacement","getLineHeight","heightValue","textElement","breakText","textSpan","opacity","display","preserveSpaces","separatorChar","hyphen","maxLineCount","full","isEol","getComputedTextLength","partition","substring","nextWord","hyphenIndex","search","lastL","ellipsis","lastLine","lastLineWithOmission","lastChar","normalizeSides","vertical","horizontal","timing","quad","cubic","inout","t3","exponential","bounce","reverse","reflect","clamp","back","elastic","interpolate","hexColor","ca","cb","ra","rd","ga","gd","ba","bd","ma","mb","u","outline","margin","template","color","highlight","blur","stdDeviation","dropShadow","tpl","grayscale","amount","sepia","saturate","hueRotate","invert","amount2","brightness","contrast","regex","attrArray","_attr","findDifference","baseObj","currentDepth","maxDepth","baseValue","nestedDepth","nestedDiff","objectDifference","POSITIVE_INFINITY","_listening","Events","eventSplitter","eventsApi","opts","names","_events","onApi","ctx","listening","_listeners","interop","listenTo","_listenId","listeningTo","_listeningTo","Listening","tryCatchOn","count","offApi","listeners","stopListening","ids","remaining","_callback","cleanup","once","onceMap","listenToOnce","offer","onceInvoke","TypeError","trigger","triggerApi","objEvents","allEvents","all","triggerEvents","ev","a3","listener","unbind","protoProps","staticProps","__super__","instance","_isModel","modelMatcher","model","matcher","Model","preinitialize","cid","cidPrefix","attributeDefaults","changed","initialize","cloneCells","cells","cloneMap","cell","isLink","embeds","newEmbeds","embed","validationError","idAttribute","_validate","silent","changes","changing","_changing","_previousAttributes","current","prevId","_pending","hasChanged","changedAttributes","old","previous","previousAttributes","validProperties","qualify","_","option","selected","positionWrapper","axis","dimension","refBBox","valuePercentage","refOrigin","setWrapper","isValuePercentage","attrValue","legacyAttributesNS","widthFn","heightFn","rValue","diagonalLength","minimum","maximum","diagonal","propsList","numberPattern","findSpacesRegex","parseFormulaRegExp","throwInvalid","evalCalcFormula","formula","addExpression","sign","evalAddExpression","isCalcExpression","evalCalcExpression","startSearchIndex","calcIndex","calcEndIndex","calcStart","brackets","findClosingBracket","calcValue","isTextInUse","_value","_node","FONT_ATTRIBUTES","textAttributesNS","_text","textWrap","cacheName","textHash","pathSelector","pathNode","findNode","SVGPathElement","wrappedText","breakTextFn","computedStyles","wrapFontAttributes","paper","title","titleNode","firstElementChild","atConnectionWrapper","zeroVector","tangent","isLinkView","connectionAttributesNS","stubs","getConnectionLength","getConnection","getConnectionSubdivisions","sourceParts","targetParts","getSerializedConnection","shapeWrapper","shapeConstructor","resetOffset","cachedShape","shapeBBox","shapeOrigin","fitScale","dWrapper","pointsWrapper","shapeAttributesNS","contextMarker","marker","stroke","setPaintURL","def","definePattern","defineGradient","defineMarker","defineFilter","offsetWrapper","nodeBBox","setIfChangedWrapper","attribute","attributesNS","port","legacy","connection","attributesMerger","removeEmptyAttributes","Cell","mergeArrays","ignoreDefaults","ignoreEmptyAttributes","finalAttributes","defaultAttributes","getIdAttribute","generateId","_transitionIds","_scheduledTransitionIds","processPorts","previousPorts","ports","removedPorts","graph","getConnectedLinks","inbound","link","outbound","startBatch","parentCell","getParentCell","unembed","embeddedCells","getEmbeddedCells","stopBatch","toFront","foregroundEmbeds","deep","breadthFirst","sortSiblings","sortedCells","maxZIndex","shouldUpdate","toBack","minZIndex","canEmbed","reparent","_unembedCells","isEmbedded","_embedCells","every","isEmbeddedIn","batchName","parentId","getCell","getAncestors","ancestors","_getEmbeddedCellsBfs","_getEmbeddedCellsDfs","embeddedIds","queue","cellId","_isString","pathArrayLength","propertyPath","propertyValue","propertyPathArray","rewrite","initializer","prevProperty","pathItem","isArrayIndex","baseAttributes","changedValue","removeProp","dirty","nestedPath","transition","delim","timingFunction","valueFunction","interpolatingFunction","firstFrameTime","setter","runtime","progress","transitionId","initialId","stopPendingTransitions","getTransitions","stopScheduledTransitions","transitions","stopTransitions","addTo","addCell","findView","findViewByModel","isElement","getChangeFlag","flag","getPointFromConnectedLink","getPointRotatedAroundCenter","getAbsolutePointFromRelative","getRelativePointFromAbsolute","getAttributeDefinition","defNS","globalDefNS","define","joint","shapes","portTransformAttrs","trans","lineLayout","elBBox","argTransform","ellipseLayout","stepFn","compensateRotation","dr","argPoint","transformation","ellipseSpread","stepAngle","step","labelAttributes","opt1","opt2","getBBoxAngles","tl","bl","br","outsideLayout","portPosition","autoOrient","textAnchor","orientAngle","topLeftAngle","bottomLeftAngle","bottomRightAngle","topRightAngle","labelText","insideLayout","radialLayout","portCenterOffset","manual","_portPosition","_elBBox","outsideOriented","outside","insideOriented","inside","radial","radialOriented","PortData","clonedData","groups","portLayoutNamespace","portLabelLayoutNamespace","_init","getPorts","getGroup","getPortsByGroup","groupName","getGroupPortsMetrics","groupPosition","groupPositionName","groupArgs","portsArgs","groupPortTransformations","portTransformation","portId","labelTransformation","_getPortLabelLayout","portAttrs","portSize","labelSize","label","labelPosition","_evaluateGroup","items","_evaluatePort","_getPosition","_getLabel","evaluated","markup","_createPositionNode","_getZIndex","setDefault","positionName","setDefaults","elementPortPrototype","_initializePorts","_createPortData","_processRemovedPort","currentItemsMap","removed","hasPorts","hasPort","getPortIndex","getGroupPorts","groupPorts","getPort","getPortGroupNames","_portSettingsData","getPortsPositions","positions","metrics","_isValidPortId","findIndex","addPort","insertPort","portProp","_validatePorts","portsAttr","errorMessages","generatePortId","addPorts","removePort","removePorts","portsForRemoval","newPorts","cp","rp","rpId","prevPortData","err","curPortData","added","prevPort","curPort","elementViewPortPrototype","portContainerMarkup","portMarkup","portLabelMarkup","_portElementsCache","_cleanPortsCache","_refreshPorts","_removePorts","_renderPorts","elementReferences","_getContainerElement","portsGropsByZ","withoutZKey","portElement","_getPortElement","groupNames","_appendPorts","_updatePorts","rotatableNode","refs","containerElement","portElements","_createPortElement","findPortNodes","portCache","portContentElement","portRoot","portSelectors","findBySelector","findPortNode","_updatePortGroup","labelElement","labelSelectors","portContainerElement","_getPortMarkup","portDoc","portFragment","labelMarkupDef","_getPortLabelMarkup","childCount","portContainerSelectors","portRootSelector","labelRootSelector","labelTextSelector","labelNode","labelTextNode","portLabelElement","portLabelSelectors","portContentSelectors","elementBBox","portsMetrics","cached","updateDOMSubtreeAttributes","rootBBox","applyPortTransform","element","transformData","initialAngle","isSetter","parentRelative","restrictedArea","parentPosition","elementPosition","translateBy","newPosition","translatedPosition","currentSize","resize","direction","quadrant","fixedPoint","imageFixedPoint","radius","atan","scaledBBox","fitEmbeds","fitToChildren","childElements","_fitToElements","fitParent","parentElement","siblingElements","elementsBBox","getCellsBBox","expandOnly","shrinkOnly","padding","resultBBox","intersectionBBox","endType","endDef","portGroup","portsPositions","portCenter","Link","defaultLabel","labelMarkup","_builtins","fill","pointerEvents","disconnect","setSource","setOpt","setTarget","router","isRouterProvided","localRouter","isConnectorProvided","localConnector","idx","labels","hasLabels","insertLabel","appendLabel","removeLabel","vertex","vertices","setVertex","_normalizeVertex","setVertices","insertVertex","removeVertex","applyToPoints","getSourcePoint","sourceCell","getSourceCell","getTargetPoint","targetCell","getTargetCell","getPolyline","newParent","getSourceElement","getTargetElement","prevParent","getCommonAncestor","hasLoop","sourceId","targetId","loop","sourceElement","targetElement","visited","getRelationshipAncestor","connectionAncestor","isRelationshipEmbeddedIn","ancestor","_getDefaultLabel","endsEqual","portsEqual","env","_results","_tests","svgforeignobject","isSafari","navigator","userAgent","vendor","addTest","Rectangle","cursor","strokeWidth","Circle","Image","image","BorderedImage","border","background","EmbeddedImage","preserveAspectRatio","InscribedImage","HeaderedRectangle","header","headerText","bodyText","Cylinder","lateralArea","bodyAttrs","topAttrs","isPercentageSetter","kappa","xCenter","xRight","ySideTop","yCurveTop","ySideBottom","yCurveBottom","backgroundColor","textAlign","boxSizing","alignItems","justifyContent","TextBlock","foreignObject","HTMLElement","wrapValue","wrapAttrs","strokeLinejoin","targetMarker","wrapper","DoubleLink","ShadowLink","sourceMarker","shadow","Positions","TOP","RIGHT","BOTTOM","LEFT","TOP_LEFT","TOP_RIGHT","BOTTOM_LEFT","BOTTOM_RIGHT","CENTER","getRectPoint","Collection","models","comparator","_reset","reset","setOptions","addOptions","insert","at","tail","singular","_removeModels","merged","toMerge","toRemove","modelMap","sortable","sortAttr","existing","_prepareModel","_addReference","orderChanged","_removeReference","previousModels","_byId","modelId","CollectionIterator","ITERATOR_VALUES","ITERATOR_KEYS","ITERATOR_KEYSVALUES","each","initAcc","_onModelEvent","$$iterator","config","kind","_collection","_kind","_index","Class","defaultVal","addMethod","addMethodsUtil","wrappers","GraphCells","cellNamespace","ModelClass","dry","Graph","cellModel","_sortOnChangeZ","_out","_in","_nodes","_edges","_batches","_restructureOnAdd","_restructureOnRemove","_restructureOnReset","_restructureOnChangeSource","_restructureOnChangeTarget","_removeCell","prevSource","prevTarget","getOutboundEdges","getInboundEdges","cellAttributes","fromJSON","resetCells","_prepareCell","firstCell","lastCell","addCells","maxPosition","preparedCells","removeCells","disconnectLinks","removeLinks","transferCellEmbeds","transferCellConnectedLinks","getCells","getElements","getLinks","getFirstCell","getLastCell","indirect","links","edges","addOutbounds","edge","addInbounds","outCell","inCell","embeddedElements","edgeCell","includeEnclosed","getNeighbors","neighbors","cellsAncestors","commonAncestor","cellAncestors","getSuccessors","cloneSubgraph","subgraph","getSubgraph","cellMap","getPredecessors","bfs","dfs","neighbor","getSources","getSinks","sinks","isSource","isSink","isSuccessor","elementA","elementB","isPredecessor","isNeighbor","findElementsAtPoint","_filterAtPoint","findLinksAtPoint","findCellsAtPoint","findElementsInArea","area","_filterInArea","findLinksInArea","findCellsInArea","findElementsUnderElement","_filterCellsUnderElement","findLinksUnderElement","findCellsUnderElement","_isValidElementUnderElement","el1","el2","_isValidLinkUnderElement","_validateCellsUnderElement","_getFindUnderElementGeometry","searchBy","geometry","filteredCells","findModelsInArea","findModelsFromPoint","findModelsUnderElement","memo","resizeCells","hasActiveBatch","batches","validations","multiLinks","sourceModel","_link","_source","_target","linkPinning","_graph","wrapWith","ViewBase","viewOptions","_ensureElement","delegateEventSplitter","$","render","_removeElement","setElement","undelegateEvents","_setElement","delegateEvents","delegate","eventName","undelegate","_createElement","_setAttributes","views","View","theme","themeClassNamePrefix","requireSetThemeOverride","defaultTheme","DETACHABLE","UPDATE_PRIORITY","FLAG_INSERT","FLAG_REMOVE","FLAG_INIT","setTheme","init","unmount","svgElement","isMounted","renderChildren","isSVG","findAttributeNode","attributeName","currentNode","findAttribute","matchedNode","_setStyle","_ensureElClassName","prefixedClassName","onRender","confirmUpdate","override","removeThemeClassName","addThemeClassName","onSetTheme","oldTheme","newTheme","onRemove","undelegateDocumentEvents","getEventNamespace","delegateElementEvents","eventNS","undelegateElementEvents","delegateDocumentEvents","eventData","currentData","propagationStopped","renderFn","__render__","HighlighterView","HIGHLIGHT_FLAG","UPDATABLE","MOUNTABLE","cellView","updateRequested","postponedUpdate","transformGroup","detachedTransformGroup","requestUpdate","requestViewUpdate","mount","findLabelNode","getNodeMatrix","layer","nodeMatrix","getRootRotateMatrix","getNodeRotateMatrix","cellViewRoot","layerName","vGroup","getLayerView","insertSortedNode","nextSibling","translateMatrix","getRootTranslateMatrix","rotateMatrix","transformMatrix","prevNode","unhighlight","notify","_removeRef","_cellView","listenToUpdateAttributes","onCellAttributeChange","_views","hid","previousView","view","_addRef","getAll","removeAll","calcAttributes","positiveValueAttributes","evalAttributes","evalAttrs","evalAttribute","evalAttrValue","HighlightingTypes","DEFAULT","EMBEDDING","CONNECTING","MAGNET_AVAILABILITY","ELEMENT_AVAILABILITY","CellView","classNames","list","_presentationAttributes","_flags","setFlags","flags","presentationAttributes","initFlag","hasFlag","getFlag","removeFlag","cleanNodesCache","startListening","onAttributesChange","updateHandled","tool","rootSelector","can","feature","interactive","useCSSSelectors","findNodes","useModelGeometry","getNodeBBox","localToPaperRect","magnet","getNodeBoundingRect","magnetMatrix","getNodeUnrotatedBBox","_notifyHighlight","rootNode","partial","embedding","connecting","magnetAvailability","elementAvailability","findMagnet","magnetAttribute","isMagnetRoot","findProxyNode","proxyNode","getSelector","prevSelector","nthChild","addLinkFromMagnet","getDefaultLink","getLinkEnd","ui","portNode","customizeLinkEnd","connectionStrategy","strategy","getMagnetFromLinkEnd","dragLinkStart","linkView","notifyPointerdown","startArrowheadMove","whenNotAllowed","dragLink","pointermove","magnetThreshold","getEventTarget","targetMagnet","mousemoved","dragLinkEnd","pointerup","setNodeAttributes","processNodeAttributes","attrVal","normalAttrs","setAttrs","positionAttrs","offsetAttrs","relatives","rawAttrs","unsetAttrName","raw","normal","updateRelativeAttributes","nodeAttrs","nodeAttrName","setResult","translation","nodeTransform","nodePosition","nodeScale","getNodeScale","scalableNode","positioned","offseted","nodeBoundingRect","cleanNodeCache","nodeCache","getNodeData","boundingRect","getNodeShape","geometryShape","isNodeConnection","findNodesAttributes","selectorCache","nodeId","nodesAttrs","mergeIds","unique","prevNodeAttrs","selectedLength","sortIndex","clientX","clientY","fromPoint","hasPointerCapture","pointerId","elementFromPoint","nodeData","processedAttrs","bboxCache","relativeItems","relativeRefItems","roAttrs","roAttributes","nodesAllAttrs","refNode","nodeAllAttrs","refSelector","processedAttributes","allAttributes","itemIndex","refNodeId","getCommonAncestorNode","mergeProcessedAttributes","roProcessedAttrs","onMount","isInitialMount","mountTools","onDetach","unmountTools","removeTools","removeHighlighters","_toolsView","hasTools","toolsView","getName","addTools","configure","relatedView","onToolEvent","updateTools","hideTools","hide","showTools","show","updateHighlighters","transformHighlighters","preventDefaultInteraction","defaultInteractionPrevented","isDefaultInteractionPrevented","pointerdblclick","pointerclick","contextmenu","pointerdown","mouseover","mouseout","mouseenter","mouseleave","mousewheel","onevent","onmagnet","magnetpointerdblclick","magnetcontextmenu","checkMouseleave","isAsync","sourceView","dumpView","checkViewVisibility","targetView","setInteractivity","isIntersecting","geometryData","isEnclosedIn","geometryRect","isInArea","isAtPoint","Flags","TOOLS","Highlighting","addPresentationAttributes","node1","node2","localUse","UPDATE","TRANSLATE","RESIZE","PORTS","ROTATE","RENDER","DragActions","ElementView","renderingOnlyAttrs","modelAttrs","rotatableSelector","scalableSelector","renderMarkup","renderJSONMarkup","renderStringMarkup","updateTransformation","sgResize","rgTranslate","rgRotate","getTranslateString","rotateString","getRotateString","scalable","scalableBBox","rotatable","rotatableBBox","prepareEmbedding","initialZIndices","connectedLinks","maxZ","initialParentId","processEmbedding","findParentBy","frontParentOnly","validateEmbedding","candidates","newCandidateView","prevCandidateView","candidateEmbedView","candidate","clearEmbedding","candidateView","finalizeEmbedding","validateUnembedding","_disallowUnembed","initialPosition","getTargetParentView","getDelegatedView","proxyPortNode","notifyPointermove","notifyPointerup","dragStart","action","delegatedView","magnetpointermove","dragMagnet","drag","preventPointerEvents","magnetpointerup","dragMagnetEnd","dragEnd","magnetpointerclick","magnetpointerdown","dragMagnetStart","pointerOffset","getRestrictedArea","isPropagationAlreadyStopped","validateMagnet","grid","elX","elY","embeddingMode","clickThreshold","oneSide","coordinate","sourceBBox","targetBBox","sourcePoint","targetPoint","opposites","N","S","E","W","radians","freeJoin","getBBoxSize","getBearing","to","getPointBox","getPaddingBox","elementPadding","getSourceBBox","getTargetBBox","vertexVertex","d1","d2","opposite","elementVertex","fromBBox","vertexElement","toBBox","route","freePoints","freeBearingPoints","elementElement","fromBorder","toBorder","startRoute","endRoute","insideElement","boundary","reversed","orthogonal","sourceAnchor","getSourceAnchor","targetAnchor","getTargetAnchor","orthogonalVertices","isOrthogonal","isOrthogonalLoop","maximumLoops","maxAllowedDirectionChange","perpendicular","excludeEnds","excludeTypes","startDirections","endDirections","directionMap","cost","directions","offsetX","offsetY","penalties","paddingBox","isPointObstacle","fallbackRouter","fallbackRoute","draggingRoute","ObstacleMap","mapGridSize","SortedSet","OPEN","CLOSE","getDirectionAngle","numDirections","angleTheta","diffX","diffY","distanceX","distanceY","fixAngleEnd","normalizedAngle","getDirectionChange","angle1","angle2","directionChange","getGridDimension","absDiff","numSteps","align","snappedX","snappedY","getKey","normalizePoint","reconstructRoute","parents","tailPoint","prevDiff","currentKey","leadPoint","estimateCost","endPoints","getRectPoints","anchor","directionList","anchorCenterVector","dirList","rectPoints","farthestIntersectionDistance","endpoint","farthestIntersection","currentIntersection","findRoute","startPoints","openSet","costs","previousRouteDirectionAngle","previousDirectionAngle","isPathBeginning","gridOffsetX","gridOffsetY","getGridOffsets","endPointsKeys","endPoint","loopsRemaining","currentParent","currentCost","isRouteBeginning","isStart","samePoints","directionAngle","neighborPoint","neighborKey","isClose","costFromStart","isOpen","build","excludedEnds","excludedAncestors","isExcludedType","isExcludedEnd","excluded","isExcludedAncestor","gridKey","isPointAccessible","mapKey","obstacle","manhattan","point1","point2","resolveOptions","oldVertices","newVertices","partialRoute","dragFrom","dragTo","diagonalCost","ceil","intersectionPoint","directionFrom","metro","Directions","AUTO","ANCHOR_SIDE","MAGNET_SIDE","DEFINED_DIRECTIONS","OPPOSITE_DIRECTIONS","VERTICAL_DIRECTIONS","ANGLE_DIRECTION_MAP","getSegmentAngle","simplifyPoints","resolveSides","sx0","sy0","sourceDirection","tx0","ty0","targetDirection","sourceSide","targetSide","getDirectionForLinkConnection","sourceLinkAnchorBBox","targetLinkAnchorBBox","linkOrigin","connectionPoint","getTangentAtLength","getClosestPointLength","roundedAngle","pointDataFromAnchor","isPort","fallBackAnchor","getOutsidePoint","pointData","outsidePoint","createLoop","loopSegment","connectionSegmentAngle","loopRoute","secondCreatedPoint","loopEndSegment","continueDirection","moveAndExpandBBox","routeBetweenPoints","sourceWidth","sourceHeight","sourceMargin","targetWidth","targetHeight","targetMargin","targetInSourceBBox","tx1","ty1","smx0","smx1","smy0","smy1","tmx0","tmx1","tmy0","tmy1","sourceOutsidePoint","targetOutsidePoint","sox","soy","tox","toy","middleOfVerticalSides","middleOfHorizontalSides","inflatedSourceBBox","inflatedTargetBBox","sourceForDistance","targetForDistance","leftD","rightD","leftBoundary","rightBoundary","aboveShape","belowShape","boundaryDefiningShape","getHorizontalDistance","topD","bottomD","topBoundary","bottomBoundary","leftShape","rightShape","getVerticalDistance","isPointInsideSource","isPointInsideTarget","middleOfAnchors","isUpwardsShorter","isLeftShorter","anchorMiddleX","anchorMiddleY","getLoopCoordinates","isHorizontal","rightAngleRouter","useVertices","isSourcePort","isTargetPort","resultVertices","verticesData","pointDataFromVertex","firstVertex","resolvedSourceDirection","isVertexInside","firstPointOverlap","alignsVertically","alignsHorizontally","isVerticalAndAligns","isHorizontalAndAligns","firstSegment","isVertexOnSegment","isVertexAlignedAndInside","accessDirection","nextInLine","resolveForTopSourceSide","resolveForRightSourceSide","resolveForBottomSourceSide","resolveForLeftSourceSide","resolveInitialDirection","connectionDirection","simplifiedRoute","accessSegment","toDirection","fromDirection","resolveDirection","lastVertex","resolvedTargetDirection","simplified","simplifiedSegment","simplifiedSegmentAngle","definedDirection","lastPointOverlap","lastSegmentRoute","roundedLastSegmentAngle","lastSegmentDirection","isDirectionVertical","isToAbove","isToLeft","rightAngle","CornerTypes","POINT","CUBIC","LINE","GAP","DEFINED_CORNER_TYPES","CORNER_RADIUS","straight","routePoints","cornerType","cornerRadius","cornerPreserveAspectRatio","nextDistance","routePointsLength","curr","prevDistance","startMove","endMove","cornerStart","cornerEnd","JUMP_TYPES","IGNORED_CONNECTORS","sortPointsAscending","swap","createLines","resultLines","nextPoint","sortPoints","buildPath","jumpSize","jumpType","isJump","xAxisRotate","halfLine","centerLine","xOffset","yOffset","nextLine","roundedStart","roundedEnd","buildRoundedSegment","jumpover","jumpOverLinkView","updateList","_jumpOverUpdateList","updateFlag","CONNECTOR","updateJumpOver","setupUpdating","jump","ignoreConnectors","allLinks","thisModel","thisIndex","defaultConnector","linkViews","thisLines","linkLines","jumpingLines","thisLine","linkLinesToTest","overlapIndex","x4","y4","overlapExists","lineIntersections","crossCheckLines","crossCheckLine","findLineIntersections","skip","jumpStart","jumpEnd","jumpLine","createJumps","rounded","smooth","controlPointX","controlPointY","HORIZONTAL","VERTICAL","CLOSEST_POINT","OUTWARDS","TangentDirections","UP","DOWN","Boolean","coeff","distanceCoefficient","angleTangentCoefficient","tau","tension","sourceTangent","targetTangent","completeRoute","getAutoSourceDirection","getClosestPointSourceDirection","getOutwardsSourceDirection","unrotatedBBox","getHorizontalSourceDirection","getVerticalSourceDirection","getSourceTangentDirection","tangentLength","angleBetweenVectors","updatedLength","getAutoTargetDirection","getClosestPointTargetDirection","getOutwardsTargetDirection","getHorizontalTargetDirection","getVerticalTargetDirection","getTargetTangentDirection","catmullRomCurves","distances","tangents","tpPrev","tpNext","v1","v2","vAngle","rot","vectorDeterminant","determinant","pointsDeterminant","rotateVector","scaleFactor1","scaleFactor2","createCatmullRomCurves","bezierCurves","bcp1","bcp2","catmullRomToBezier","sourceCenter","targetCenter","acos","LABELS","SOURCE","TARGET","LinkView","_labelCache","_labelSelectors","_V","_dragData","decimalsRounding","EPSILON","updateEndProperties","isViewMounted","__fixSafariBug268376","updateLabels","onLabelsChange","updateAll","updateConnector","updatePath","updateDOM","updateLabelPositions","requestConnectionUpdate","isLabelsRenderRequired","previousLabels","pathLength","_labels","renderLabels","unmountLabels","_getLabelMarkup","_getLabelStringMarkup","_normalizeLabelMarkup","vNode","DocumentFragment","hasChildNodes","vLabels","labelCache","labelsCount","labelsLayer","builtinDefaultLabel","builtinDefaultLabelMarkup","defaultMarkup","mountLabels","findLabelNodes","labelIndex","labelRoot","_mergeLabelAttrs","hasCustomMarkup","labelAttrs","defaultLabelAttrs","builtinDefaultLabelAttrs","_mergeLabelSize","defaultLabelSize","labelLayer","canLabelMove","defaultLabelMarkup","removeRedundantLinearVertices","numRoutePoints","polylinePoints","numPolylinePoints","getEndView","getEndAnchor","getEndConnectionPoint","getEndMagnet","sourceMagnet","updateRoute","anchors","findAnchors","connectionPoints","findConnectionPoints","findPath","findAnchorsOrdered","firstEndType","firstRef","secondEndType","secondRef","firstAnchor","secondAnchor","firstAnchorRef","secondAnchorRef","firstDef","secondDef","firstView","secondView","firstMagnet","secondMagnet","getAnchor","priority","firstWaypoint","lastWaypoint","sourceDef","targetDef","paperOptions","sourceConnectionPointDef","defaultConnectionPoint","sourceLine","getConnectionPoint","targetConnectionPointDef","targetLine","anchorDef","anchorFn","isConnection","defaultLinkAnchor","defaultAnchor","anchorName","connectionPointDef","connectionPointFn","connectionPointName","connectionPointNamespace","_getDefaultLabelPositionProperty","builtinDefaultLabelPosition","defaultLabelPosition","_normalizeLabelPosition","_mergeLabelPositionProperty","normalizedLabelPosition","normalizedDefaultLabelPosition","_getLabelTransformationMatrix","_cleanLabelMatrices","endViewProperty","endId","updateEndMagnet","endModel","getModelById","endView","endMagnetProperty","connectedMagnet","_getLabelPositionProperty","_getLabelPositionAngle","_getLabelPositionArgs","_getDefaultLabelPositionArgs","_mergeLabelPositionArgs","labelPositionArgs","defaultLabelPositionArgs","addLabel","localX","localY","localAngle","positionArgs","getLabelPosition","addVertex","isPointProvided","getVertexIndex","sendToken","token","isReversed","animationAttributes","dur","repeatCount","calcMode","keyPoints","keyTimes","vToken","onAnimationEnd","routerNamespace","defaultRouter","routerFn","connectorNamespace","connectorFn","getPointAtRatio","getTangentAtRatio","getClosestPoint","getClosestPointRatio","labelOffset","isDistanceRelative","absoluteDistance","isDistanceAbsoluteReverse","reverseDistance","isOffsetAbsolute","absoluteOffset","labelPoint","labelDistance","labelOffsetDiff","labelAngle","labelOffsetCoordinates","positionOffset","isKeepGradient","keepGradient","isEnsureLegibility","ensureLegibility","getLabelCoordinates","vertexLength","currentVertex","dragData","dragLabel","dragArrowhead","dragLabelEnd","dragArrowheadEnd","onlabel","dragLabelStart","labelIdx","initialLabelPosition","positionAngle","delegateDragEvents","dragArrowheadStart","arrowheadType","ignoreBackwardsCompatibility","snapLabels","snapLinks","_snapArrowhead","snapLinksSelf","_snapArrowheadSelf","_connectArrowhead","_snapArrowheadEnd","_connectArrowheadEnd","linkAllowed","_finishEmbedding","_notifyConnectEvent","_disallow","_afterArrowheadMove","arrowhead","initialEnd","currentEnd","initialMagnet","magnetUnderPointer","_snapToPoints","snapPoint","closestPointX","closestDistanceX","closestPointY","closestDistanceY","distX","distY","localToClientPoint","isSnapped","viewsInArea","findElementViewsInArea","findInAreaOptions","prevClosestView","closestView","prevClosestMagnet","closestMagnet","prevMagnetProxy","magnetProxy","MAX_VALUE","pointer","validateConnection","validateConnectionArgs","newClosestMagnet","snapping","prevEnd","prevX","prevY","eventTarget","viewUnderPointer","_beforeArrowheadMove","markAvailable","_markAvailableMagnets","_unmarkAvailableMagnets","_createValidateConnectionArgs","oppositeArrowhead","isMagnetAvailable","marked","magnets","availableMagnets","markedMagnets","markedKeys","LayersNames","GRID","CELLS","BACK","FRONT","PaperLayer","pivotNodes","insertPivot","insertNode","pivotNode","createComment","neighborZ","currentZ","neighborPivot","removePivots","useFirstSubpath","getPathData","secondSubpathIndex","highlightConnection","highlightNode","highlightMatrix","paddingMatrix","nonScalingStroke","MASK_CLIP","mask","maskClip","VISIBLE","INVISIBLE","MASK_ROOT_ATTRIBUTE_BLACKLIST","MASK_CHILD_ATTRIBUTE_BLACKLIST","MASK_REPLACE_TAGS","MASK_REMOVE_TAGS","transformMaskChild","childEl","childTagName","originalChild","originalNode","transformMaskRoot","rootEl","getMaskShape","maskRoot","descendants","descendant","forEachDescendant","maskChild","getMaskId","getMask","hasNodeFill","magnetStrokeWidth","minStrokeWidth","maxStrokeWidth","maskEl","removeMask","maskNode","addMask","highlighterBBox","alphaValue","ROW","COLUMN","UPDATE_ATTRIBUTES","_prevItems","elementView","gap","normalizedSize","isRowDirection","itemWidth","prevItems","comparison","unchanged","prevEls","itemsEls","prevEl","itemEl","createListItem","itemsCount","listSize","connectionRatio","_magnet","_refPoint","connectionLength","resolveRef","Element","refPoint","refView","getPointAtLink","fixedAt","parsedValue","connectionPerpendicular","OFFSET","verticalLine","horizontalLine","verticalIntersections","horizontalIntersections","fallbackAt","connectionClosest","_opt","offsetPoint","bboxIntersection","BNDR_SUBDIVISIONS","BNDR_SHAPE_BBOX","_view","alignOffset","alignLine","rectangle","bboxWORotation","lineWORotation","nextElementSibling","findShapeNode","localShape","targetMatrix","localMatrix","localLine","localRef","insideout","extrapolate","sticky","cpOffset","bboxWrapper","dxPercentage","dyPercentage","midSide","modelCenter","GridLayer","_gridCache","_gridSettings","updateGrid","setGrid","drawGrid","getGridSettings","renderGrid","gridSettings","_resolveDrawGridOption","removeGrid","drawGridSize","_getGridRefs","gridLayerSetting","_getPatternId","vPattern","exist","patternUnits","vSvg","patterns","getArea","patternId","defsVEl","svgVEl","patternVEl","rectVEl","sortingTypes","NONE","APPROX","EXACT","UPDATE_BATCH_SIZE","MIN_PRIORITY","defaultHighlighting","defaultLayers","Paper","highlighting","preventContextMenu","preventDefaultBlankAction","preventDefaultViewAction","restrictTranslate","defaultLink","ctor","_evt","cellViewS","_magnetS","cellViewT","_magnetT","_linkView","childView","parentView","labelMove","allowLink","moveThreshold","sorting","frozen","autoFreeze","onViewUpdate","mounting","isolate","requestConnectedLinksUpdate","onViewPostponed","forcePostponedViewUpdate","beforeRender","afterRender","viewport","cellViewNamespace","highlighterNamespace","anchorNamespace","linkAnchorNamespace","overflow","documentEvents","tools","layers","_viewportMatrix","_viewportTransformString","_updates","_layers","SORT_DELAYING_BATCHES","UPDATE_DELAYING_BATCHES","FORM_CONTROL_TAG_NAMES","GUARDED_TAG_NAMES","MIN_SCALE","DEFAULT_FIND_BUFFER","cloneOptions","_setDimensions","_mw_evt_buffer","deltas","resetViews","isFrozen","updateViewsAsync","_resetUpdates","priorities","unmountedCids","mountedCids","unmounted","mounted","keyFrozen","freezeKey","idle","onCellAdded","onCellRemoved","onCellChange","onGraphReset","onGraphSort","onGraphBatchStop","onCellHighlight","onCellUnhighlight","renderView","freeze","unfreeze","resetLayers","sortViews","updateDelayingBatches","updateViews","sortDelayingBatches","inset","hasLayerView","getLayerNode","renderLayers","addStylesheet","drawBackground","createLayer","gridPatterns","removeLayers","sorted","layerView","cellsLayerView","toolsLayerView","labelsLayerView","webkitUserSelect","userSelect","_background","updateBackgroundImage","scaleUniformAtPoint","transformString","getCTM","currentTransformString","ctmString","clientMatrix","flagLabels","nextPriority","scheduleViewUpdate","dumpOptions","sourceFlag","targetFlag","stats","notifyAfterRender","updates","priorityUpdates","prevPriorityUpdates","currentType","viewUpdateFn","dumpViewUpdate","registerMountedView","shouldNotify","notifyBeforeRender","leftover","updateView","updated","removeView","isInitialInsert","insertView","requireView","registerUnmountedView","dumpViews","passingOpt","checkViewport","batchStats","updateCount","batchCount","updateViewsBatch","hasScheduledUpdates","priorityIndexes","_key","processed","mountBatchSize","unmountBatchSize","checkStats","unmountCount","mountCount","total","progressFn","beforeFn","afterFn","batchSize","postponeCount","maxPriority","viewportFn","postponeViewFn","main","currentFlag","isDetached","detachView","leftoverFlag","postponed","getUnmountedViews","unmountedViews","getMountedViews","mountedViews","checkUnmountedViews","checkMountedViews","visible","isUnmounted","unmountedCount","isExactSorting","removeViews","getComputedSize","setDimensions","currentWidth","currentHeight","computedSize","fitToContent","gridWidth","gridHeight","getFitToContentArea","minWidth","minHeight","maxWidth","maxHeight","newOrigin","allowNewOrigin","contentArea","getContentArea","calcWidth","calcHeight","allowNegativeBottomRight","transformToFitContent","contentBBox","contentLocalOrigin","getContentBBox","paperToLocalPoint","scaleGrid","minScale","maxScale","verticalAlign","horizontalAlign","minScaleX","maxScaleX","minScaleY","maxScaleY","fittingBBox","currentTranslate","newSx","newSy","scaleDiff","newOx","newOy","scaleContentToFit","paperToLocalRect","createViewForModel","optionalViewClass","defaultViewClass","namespaceViewClass","onImageDragStart","sortViewsExact","cellNodes","placements","sortElement","cellA","cellB","zA","zB","sortElements","findViewsFromPoint","findViewsInArea","plainArea","_filterViewsInArea","extArea","findOpt","findLinkViewsInArea","findCellViewsInArea","findElementViewsAtPoint","plainPoint","_filterViewsAtPoint","findLinkViewsAtPoint","findCellViewsAtPoint","_findInExtendedArea","findCellsFn","findCells","dispatchToolsEvent","clientToLocalPoint","localToPaperPoint","localPoint","localRect","paperPoint","paperRect","localToClientRect","clientPoint","clientToLocalRect","clientRect","localToPagePoint","pageOffset","localToPageRect","pageToLocalPoint","pageToLocalRect","clientOffset","resolveHighlighter","highlighter","highlighterDef","magnetEl","highlighterDescriptor","contextMenuFired","contextMenuTrigger","isContextMenu","isTargetFormNode","eventEvt","customEventTrigger","magnetNode","magnetEvt","contextmenuEvt","normalizedEvt","_processMouseWheelEvtBuf","wait","lastArgs","lastThis","maxWait","timerId","lastCallTime","lastInvokeTime","leading","maxing","useRaf","invokeFunc","time","thisArg","startTimer","pendingFunc","shouldInvoke","timeSinceLastCall","timerExpired","trailingEdge","timeSinceLastInvoke","timeWaiting","remainingWait","debounced","isInvoking","leadingEdge","cancel","cancelTimer","flush","pending","debounce","deltaY","deltaX","sX","sY","pX","pY","detail","wheelDelta","wheelDeltaY","wheelDeltaX","HORIZONTAL_AXIS","deltaMode","shiftKey","spinX","spinY","normalizeWheel","pinchHandlers","ctrlKey","eventNode","magnetEvent","magnetContextMenuFired","magnetContextMenuTrigger","getPointerArgs","guarded","setGridSize","backgroundPosition","backgroundSize","currentScale","drawBackgroundImage","img","HTMLImageElement","backgroundImage","backgroundRepeat","repeat","backgroundOpacity","backgroundQuality","quality","backgroundPattern","backgroundPatterns","canvas","HTMLCanvasElement","toDataURL","updateBackgroundColor","onload","isDefined","defId","filterId","filterSVGString","filterAttrs","filterUnits","gradient","stops","stopVEls","gradientVEl","markerUnits","markerVEl","orient","markerContentVEl","markupVEl","markerAttrs","markupValue","Layers","flipXy","imgWidth","imgHeight","getContext","drawImage","setTransform","flipX","flipY","watermark","watermarkAngle","stepX","stepY","thickness","fixedDot","mesh","doubleMesh","ToolView","_visible","_visibleExplicit","simulateRelatedView","updateVisibility","computeVisibility","isExplicitlyVisible","visibility","focus","focusOpacity","focusTool","blurTool","VertexHandle","mousedown","touchstart","dblclick","mousemove","touchmove","mouseup","touchend","touchcancel","onPointerDown","onPointerMove","onDoubleClick","onPointerUp","Vertices","handleClass","snapRadius","redundancyRemoval","vertexAdding","handles","interactiveLinkNode","linkEvents","delegateLinkEvents","resetHandles","renderHandles","undelegateLinkEvents","updateHandles","startHandleListening","vertexRemoving","vertexMoving","onHandleWillChange","onHandleChanging","onHandleChanged","onHandleRemove","getNeighborPoints","_handle","normalizedEvent","snapVertex","vertexAdded","onPathPointerDown","onLinkPointerDown","abs2rel","pin","relative","pinnedLinkEnd","pinnedElementEnd","totalLength","pinRelative","SegmentHandle","viewPoint","Segments","segmentLengthThreshold","snapHandle","nextVertex","renderHandle","updateHandle","onHandleChangeStart","onHandleChangeEnd","shiftHandleIndexes","resetAnchor","relatedModel","handleIndex","vertexPoints","indexOffset","originalVertices","isSingleVertex","origVIndex","additionalOffset","firstHandleShifted","nextVIndex","changeSourceAnchor","deleteSourceAnchor","sourceAnchorPosition","sourceAnchorDef","changeTargetAnchor","deleteTargetAnchor","targetAnchorPosition","targetAnchorDef","segmentLine","ToolsView","isRendered","wasRendered","ensureToolRendered","focusedTool","blurredTool","ShapeType","TransactionType","FlowType","Jurisdiction","PaymentType","DefaultValues","PrimaryColor","SecondaryColor","EmphasizedColor","ThirdPartyColor","linkTypeColors","Node","entityIds","isNewEntity","setColor","functions","setColorByJurisdiction","jurisdiction","US","NonUS","Mixed","setLabel","splitLabel","setSecondaryLabel","setFunctionIcon","iconName","iconPath","response","fetch","ok","status","svgContent","encodedSvg","encodeURIComponent","functionIcon","addFunctionIcons","debug","ToolMode","toolModesWithTargetSelection","AddFlow","AddTransaction","MoveExpense","MoveRevenue","MoveFunction","FlowEditor","getGraphJson","setGraphJson","graphJson","closeMenus","newMarkup","markupElement","svgPath","MiscellaneousLink","linkColor","matchingLink","lc","setRectangleMode","activeTool","DrawRectangle","drawRectangle","startRectangle","tempRectangleElement","DrawnRectangle","addTransaction","transactionType","ServiceFee","futureStateMode","addPaymentByDialog","Service","Royalty","IPLicense","IPTransfer","addIPTransferByDialog","addFlow","flowType","stepId","newLink","Physical","Legal","Payment","Agreement","Miscellaneous","sourceEntityIds","targetEntityIds","dotNetHelper","invokeMethod","invokeMethodAsync","addFlowBetweenEntities","sourceEntityId","targetEntityId","sourceNode","targetNode","removeFlowBetweenEntities","linkType","removeFlowByStepId","linksToRemove","toggleFlowElementVisibility","openMenu","menu","EmptyElement","EmptyThirdParty","changeElementPrimaryText","subMenu","beginAddTransaction","beginMoveRevenue","beginMoveExpense","EntityGroup","functionName","beginMoveFunction","beginAddFlow","addPnlByDialog","changeElementColor","changeElementSecondaryText","confirmDeleteElement","changeLinkText","confirmDeleteRelationship","menuOption","menuText","arrow","openSubMenu","divBottom","offsetTop","windowHeight","distanceToBottom","closeSubMenus","overflowY","divRight","offsetLeft","getElementsByClassName","selectedElement","transactionTypeToCreate","flowTypeToCreate","functionNameToMove","paymentType","sourceLabel","targetLabel","dialogResult","entityId","addEntityNode","entityIdsToExclude","results","container","newElement","CreateEntityNode","addThirdPartyNode","updateEntityFunctions","functionNames","entityNode","log","addEntityByEntityNodeOptions","overlappingPositionElement","replaceEntityNodeByEntityId","removeEntityNodeByEntityId","addFunctionToEntityNode","removeFunctionFromEntityNode","updatedFunctions","onMoveFunctionStepDelete","resetToolMode","oldText","newText","changeFunctionIcon","encodedSvgContent","refX","refY","oldColor","shapeType","CorporationCFC","BranchThirdParty","Partnership","HybridEntity","ReverseHybridEntity","ReverseHybrid","DRE","Disregarded","Group","hoveredElementClickDisabled","panStartPosition","linkMove","verticesTool","segmentsTool","pageX","pageY","oldscale","newscale","dispose","createFlowEditor","FlowPreview","createFlowPreview","class","fontFamily","fontWeight","label2","body2","PhysicalLink","LegalLink","dashed","strokeDasharray","PaymentLink","ServiceLink","IPTransferLink","IPLicenseLink","AgreementLink"],"sourceRoot":""}