|
{"version":3,"file":"main.js","mappings":";;;;;AAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA,aAAa,oBAAoB;AACjC,aAAa,oBAAoB;AACjC;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA,aAAa,oBAAoB;AACjC;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA,aAAa,oBAAoB;AACjC;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,GAAG;;AAEH;AACA,aAAa,oBAAoB;AACjC,aAAa,oBAAoB;AACjC;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA,aAAa,oBAAoB;AACjC,aAAa,oBAAoB;AACjC;AACA;AACA;AACA;AACA,gBAAgB,oBAAoB;AACpC,eAAe,oBAAoB;AACnC,eAAe,oBAAoB;AACnC,cAAc,oBAAoB;AAClC,cAAc,oBAAoB;AAClC,KAAK;AACL;AACA;;AAEA;;AAEA,4BAA4B,sBAAsB;;AAElD,gDAAe,SAAS,EAAC;;;AClLc;;AAEvC;;AAEA;AACA;AACA,GAAG;;AAEH;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA,KAAK;AACL,GAAG;;AAEH;AACA;AACA;AACA,GAAG;;AAEH;AACA,6BAA6B,qBAAqB,EAAE,kBAAkB;AACtE,GAAG;;AAEH;AACA,6BAA6B,qBAAqB,EAAE,kBAAkB;AACtE,GAAG;;AAEH;AACA,8BAA8B,mBAAmB;AACjD,oBAAoB,mBAAmB;AACvC,QAAQ,qBAAqB;AAC7B;AACA,GAAG;;AAEH;AACA;AACA,qCAAqC,mBAAmB,CAAC;AACzD;AACA;AACA,GAAG;;AAEH;AACA;AACA,GAAG;;;AAGH;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC,MAAM,EAAE,YAAY,EAAE,WAAW;AACpE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,QAAQ;AACR;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;;AAEA,6CAA6C,qBAAqB,CAAC,UAAU,KAAK;AAClF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA,GAAG;;AAEH;;;AAGA,gDAAe,KAAK,EAAC;;;AC5FkB;AACR;;AAE/B;AACA;AACA;AACA;AACA;;AAEA,oBAAoB,iBAAa;AACjC;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA,aAAa,qBAAqB,EAAE,IAAI,UAAU,IAAI,IAAI;AAC1D;AACA;AACA;AACA,0CAA0C;AAC1C,UAAU;AACV,8BAA8B;AAC9B;AACA;AACA;AACA;AACA,yCAAyC;AACzC,UAAU;AACV,6BAA6B;AAC7B;AACA;AACA;AACA;AACA,yCAAyC;AACzC,UAAU;AACV,6BAA6B;AAC7B;AACA;AACA;AACA;AACA,0CAA0C;AAC1C,UAAU;AACV,8BAA8B;AAC9B;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA,GAAG;;AAEH;AACA;AACA,GAAG;;AAEH;AACA;AACA,GAAG;;AAEH;AACA;AACA,GAAG;AACH;AACA,iDAAe,MAAM,EAAC;;;ACrFtB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACO;AACP,IAAI,iDAAiD;AACrD,IAAI,4CAA4C;AAChD,IAAI,oEAAoE;AACxE,IAAI,8DAA8D;AAClE,IAAI,mDAAmD;AACvD,IAAI,6DAA6D;AACjE,IAAI,qEAAqE;AACzE,IAAI,uEAAuE;AAC3E,IAAI,kFAAkF;AACtF,IAAI,oFAAoF;AACxF,IAAI,sFAAsF;AAC1F,IAAI,gEAAgE;AACpE,IAAI,oFAAoF;AACxF,IAAI,mEAAmE;AACvE,IAAI,2DAA2D;AAC/D,IAAI,kEAAkE;AACtE,IAAI,kEAAkE;AACtE,IAAI,oFAAoF;AACxF,IAAI,+EAA+E;AACnF,IAAI,6EAA6E;AACjF,IAAI,mFAAmF;AACvF,IAAI,iFAAiF;AACrF,IAAI,0DAA0D;AAC9D,IAAI,6DAA6D;AACjE,IAAI,2CAA2C;AAC/C,IAAI,wDAAwD;AAC5D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoB,wBAAwB,UAAU,GAAG,SAAS,uBAAuB;AACzF;AACA;AACA;AACA;;;AAGO;AACP;AACA;AACA;;;AAGA;AACO;AACP;AACA;;AAEO;AACP;AACA;;;AChEA;;AAEgC;;AAEhC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,MAAM,cAAK;AACX;AACA;AACA;AACA;;AAEA;AACA,IAAI,uDAAuD;AAC3D,IAAI,gEAAgE;AACpE,IAAI,gEAAgE;AACpE,IAAI,qDAAqD;AACzD,IAAI,uDAAuD;AAC3D,IAAI,iEAAiE;AACrE,IAAI,kEAAkE;AACtE,IAAI,mDAAmD;AACvD,IAAI,kEAAkE;AACtE,IAAI,oDAAoD;AACxD,IAAI,yDAAyD;AAC7D,IAAI,6CAA6C;AACjD,IAAI,uEAAuE;AAC3E,IAAI,oEAAoE;AACxE,IAAI,8CAA8C;AAClD,IAAI,kEAAkE;AACtE,IAAI,iEAAiE;AACrE,IAAI,yDAAyD;AAC7D,IAAI,mFAAmF;AACvF,IAAI,iFAAiF;AACrF,IAAI,+EAA+E;AACnF,IAAI,qFAAqF;AACzF,IAAI,+EAA+E;AACnF,IAAI,2FAA2F;AAC/F,IAAI,2DAA2D;AAC/D,IAAI,kEAAkE;AACtE,IAAI,6DAA6D;AACjE,IAAI,0EAA0E;AAC9E,IAAI,iEAAiE;AACrE,IAAI,kDAAkD;AACtD,IAAI,wDAAwD;AAC5D,IAAI,gEAAgE;AACpE,IAAI,+EAA+E;AACnF,IAAI,6EAA6E;AACjF,IAAI,mEAAmE;AACvE,IAAI,kEAAkE;AACtE,IAAI,oEAAoE;AACxE,IAAI,wDAAwD;AAC5D,IAAI,8CAA8C;AAClD,IAAI,gDAAgD;AACpD,IAAI,uEAAuE;AAC3E,IAAI,gDAAgD;AACpD,IAAI,sDAAsD;AAC1D,IAAI,oEAAoE;AACxE,IAAI,8EAA8E;AAClF,IAAI,oDAAoD;AACxD,IAAI,sDAAsD;AAC1D,IAAI,oEAAoE;AACxE,IAAI,kEAAkE;AACtE,IAAI,oDAAoD;AACxD,IAAI,8CAA8C;AAClD,IAAI,mFAAmF;AACvF,IAAI,oEAAoE;AACxE,IAAI,gEAAgE;AACpE,IAAI,wDAAwD;AAC5D,IAAI,kEAAkE;AACtE,IAAI,+FAA+F;AACnG,IAAI,gEAAgE;AACpE,IAAI,4DAA4D;AAChE,IAAI,8DAA8D;AAClE,IAAI,mFAAmF;AACvF,IAAI,gDAAgD;AACpD,IAAI,uDAAuD;AAC3D,IAAI,wDAAwD;AAC5D,IAAI,yDAAyD;AAC7D,IAAI,6DAA6D;AACjE,IAAI,2DAA2D;AAC/D,IAAI,8DAA8D;AAClE,IAAI,0DAA0D;AAC9D,IAAI,gDAAgD;AACpD,IAAI,yDAAyD;AAC7D,IAAI,8CAA8C;AAClD,IAAI,kDAAkD;AACtD,IAAI,sEAAsE;AAC1E,IAAI,oDAAoD;AACxD,IAAI,qDAAqD;AACzD,IAAI,+CAA+C;AACnD,IAAI,6DAA6D;AACjE,IAAI,4DAA4D;AAChE,IAAI,4EAA4E;AAChF,IAAI,kDAAkD;AACtD,IAAI,kDAAkD;AACtD,IAAI,kDAAkD;AACtD,IAAI,wEAAwE;AAC5E,IAAI,wEAAwE;AAC5E,IAAI,+DAA+D;AACnE,IAAI,+DAA+D;AACnE,IAAI,uFAAuF;AAC3F,IAAI,uEAAuE;AAC3E,IAAI,4DAA4D;AAChE,IAAI,wEAAwE;AAC5E,IAAI,gEAAgE;AACpE,IAAI,6DAA6D;AACjE,IAAI,6DAA6D;AACjE,IAAI,6EAA6E;AACjF,IAAI,iDAAiD;AACrD,IAAI,uDAAuD;AAC3D,IAAI,0DAA0D;AAC9D,IAAI,wEAAwE;AAC5E,IAAI,kEAAkE;AACtE,IAAI,kDAAkD;AACtD,IAAI,gDAAgD;AACpD,IAAI,gDAAgD;AACpD,IAAI,yFAAyF;AAC7F,IAAI,yDAAyD;AAC7D,IAAI,yDAAyD;AAC7D;AACA,IAAI,8CAA8C;AAClD,IAAI,8CAA8C;AAClD,IAAI,gDAAgD;AACpD,IAAI,4CAA4C;AAChD,IAAI,gDAAgD;AACpD,IAAI,8CAA8C;AAClD,IAAI,0CAA0C;AAC9C,IAAI,8CAA8C;AAClD,IAAI,wDAAwD;AAC5D,IAAI,kDAAkD;AACtD,IAAI,gDAAgD;AACpD,IAAI,8CAA8C;AAClD,IAAI,0CAA0C;AAC9C,IAAI,gDAAgD;AACpD,IAAI,8CAA8C;AAClD,IAAI,sDAAsD;AAC1D,IAAI,gDAAgD;AACpD,IAAI,0CAA0C;AAC9C,IAAI,4CAA4C;AAChD,IAAI,8CAA8C;AAClD;AACA,IAAI,sCAAsC;AAC1C,IAAI,oCAAoC;AACxC;AACA,IAAI,qFAAqF;AACzF,IAAI,qFAAqF;AACzF;;AAEA,SAAS,6BAAoB;AAC7B;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoB,kDAAkD;AACtE;AACA;AACA;AACA;AACA;AACA,oBAAoB,kDAAkD;AACtE;AACA;AACA;AACA;AACA;AACA,oBAAoB,kDAAkD;AACtE;AACA;AACA;AACA;AACA;AACA,oBAAoB,kDAAkD;AACtE;AACA;AACA,oBAAoB,cAAK;AACzB;AACA;AACA,oBAAoB,wBAAwB,UAAU,GAAG,SAAS,uBAAuB;AACzF;AACA;AACA;AACA;;AAEO;AACP,gCAAgC,6BAAoB;AACpD;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEO;AACP;AACA;AACA;;AAEO;AACP,sBAAsB,iBAAa;AACnC;AACA;;AAEO;AACP;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC1RO;AACP,IAAI,yIAAyI;AAC7I,IAAI,0IAA0I;AAC9I,IAAI,qIAAqI;AACzI,IAAI,mIAAmI;AACvI,IAAI,iJAAiJ;AACrJ,IAAI,2HAA2H;AAC/H,IAAI,iFAAiF;AACrF;;AAEA;AACA,IAAI,sDAAsD;AAC1D,IAAI,sDAAsD;AAC1D,IAAI,8CAA8C;AAClD,IAAI,0DAA0D;AAC9D,IAAI,iEAAiE;AACrE,IAAI,qDAAqD;AACzD,IAAI,mEAAmE;AACvE,IAAI,sDAAsD;AAC1D,IAAI,4DAA4D;AAChE,IAAI,uDAAuD;AAC3D,IAAI,yDAAyD;AAC7D,IAAI,mDAAmD;AACvD,IAAI,wDAAwD;AAC5D,IAAI,qDAAqD;AACzD,IAAI,sDAAsD;AAC1D,IAAI,0DAA0D;AAC9D,IAAI,uDAAuD;AAC3D,IAAI,kDAAkD;AACtD,IAAI,wDAAwD;AAC5D,IAAI,iDAAiD;AACrD,IAAI,qDAAqD;AACzD,IAAI,2DAA2D;AAC/D,IAAI,gDAAgD;AACpD,IAAI,kDAAkD;AACtD,IAAI,sDAAsD;AAC1D,IAAI,sDAAsD;AAC1D,IAAI,8CAA8C;AAClD,IAAI,mDAAmD;AACvD;;AAEO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACjDqG;AACd;AACjC;;AAEtD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;;AAEP;AACA;AACA;AACA;;AAEA;AACA;AACA,6CAA6C,oBAAoB;AACjE;;AAEA;AACA,WAAW,eAAe;AAC1B;;AAEA;AACA,WAAW,oBAAoB;AAC/B;;AAEA;AACA,WAAW,sBAAsB;AACjC;;AAEA;AACA;AACA;;AAEA;AACA;AACA,yBAAyB;AACzB;;AAEA;AACA,WAAW,oBAAoB;AAC/B;;AAEA;AACA;AACA,WAAW,aAAa;AACxB;;AAEA;AACA,WAAW,gBAAgB;AAC3B;;AAEA;AACA,WAAW,iBAAiB;AAC5B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;;AAEA;AACA;AACA,yBAAyB,qBAAqB;AAC9C,MAAM;AACN,sBAAsB,qBAAqB;AAC3C,MAAM;AACN,sBAAsB,qBAAqB;AAC3C,MAAM;AACN,wBAAwB,qBAAqB;AAC7C,MAAM;AACN,sBAAsB,qBAAqB;AAC3C,MAAM;AACN,0BAA0B,qBAAqB;AAC/C,MAAM,sDAAsD;AAC5D;AACA,MAAM;AACN;AACA;AACA;;AAEA;AACA,cAAc,MAAM,GAAG,UAAU;AACjC;;AAEA;AACA,cAAc,MAAM,GAAG,cAAc;AACrC;;AAEA;AACA,cAAc,MAAM,GAAG,aAAa;AACpC;;AAEA;AACA,cAAc,MAAM,GAAG,aAAa;AACpC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;;;ACjJA;AACwC;AACN;AACF;AACW;;AAEpC;;AAEP,gBAAgB,uEAAuE,IAAI;AAC3F;AACA;AACA;;AAEA;AACA;AACA,QAAQ,iBAAa;AACrB,UAAU,iBAAa;AACvB,UAAU,kCAAkC;AAC5C;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;;AAEA;;AAEA;;AAEA;AACA;AACA,uDAAuD,0BAA0B;AACjF;AACA;;;AAGA;AACA;AACA,sBAAsB;AACtB;;AAEA;AACA;AACA;AACA;;AAEA;AACA,QAAQ,gBAAY,4CAA4C,QAAQ,GAAG,YAAY,OAAO,UAAU,UAAU,eAAe;AACjI,iBAAiB;AACjB;AACA;AACA;AACA;;AAEA;AACA;AACA,MAAM,gBAAY,0CAA0C,QAAQ,GAAG,YAAY,OAAO,SAAS;AACnG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,6DAA6D,cAAc,cAAc,cAAc;AACvG,+CAA+C,cAAc,cAAc,cAAc;;AAEzF;AACA,QAAQ,gBAAY,6CAA6C,QAAQ,GAAG,YAAY,OAAO,UAAU,UAAU,eAAe;AAClI,iBAAiB;AACjB;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,0DAA0D;AAC1D;AACA,MAAM,gBAAY,0CAA0C,QAAQ,GAAG,YAAY,OAAO,SAAS;AACnG;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,2BAA2B,cAAc,cAAc,cAAc;AACrE;AACA;AACA,6BAA6B,cAAc,cAAc,cAAc;AACvE;AACA;;AAEA;AACA,QAAQ,gBAAY,kCAAkC,QAAQ,GAAG,YAAY,OAAO,UAAU,UAAU,eAAe;AACvH,iBAAiB;AACjB;AACA;;AAEA;AACA;;;AAGA;;;ACjIwC;AACR;;AAEzB;AACP;AACA;AACA,mBAAmB,iBAAa;AAChC;AACA;AACA;AACA,iBAAiB,6BAA6B,kBAAkB,GAAG,uBAAuB;AAC1F,OAAO;AACP;AACA,gCAAgC,iBAAa;AAC7C;;AAEA;AACA;AACA;AACA,mBAAmB,cAAc,CAAC;AAClC;AACA;AACA,mCAAmC,mBAAmB,CAAC;AACvD;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA,qCAAqC,mBAAmB,CAAC,oBAAoB,IAAI;AACjF,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,qBAAqB,8BAA8B;AACnD,4BAA4B,6CAA6C;AACzE,UAAU,uBAAmB;AAC7B;AACA;AACA;;AAEA;AACA;AACA,UAAU,uBAAmB;AAC7B;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;;AAEA,IAAI,uBAAmB;AACvB;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACxJA;AACA;AACwC;AACqB;AACb;AACd;AACF;AAC2B;AAChB;;AAEpC;AACP;AACA;AACA,QAAQ,sDAAsD,yBAAyB,wBAAwB,IAAI;AACnH,QAAQ,sDAAsD,oBAAgB,wCAAwC,IAAI;AAC1H,QAAQ,sDAAsD,oBAAgB,4CAA4C,IAAI;AAC9H,QAAQ,gEAAgE,kBAAkB,IAAI;AAC9F,QAAQ,gEAAgE,sBAAsB,IAAI;AAClG,QAAQ,gEAAgE,oBAAgB,yCAAyC,UAAU;AAC3I,QAAQ,gEAAgE,oBAAgB,6CAA6C,UAAU;AAC/I;AACA,WAAW,yBAAyB;AACpC;;AAEA;AACA;AACA,sBAAsB;AACtB;;AAEA,uBAAuB;AACvB;AACA;AACA,4BAA4B;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe;AACf,oBAAoB;AACpB,kBAAkB;AAClB;AACA;AACA;AACA;AACA;AACA,0BAA0B;AAC1B,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,yBAAyB;AACrC,YAAY,wBAAwB;AACpC,YAAY,iCAAiC;AAC7C,YAAY,sBAAsB;AAClC,YAAY,0BAA0B;AACtC,YAAY,uBAAuB;AACnC,YAAY,2BAA2B;AACvC;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,iBAAa;AAC5C,QAAQ,iBAAa;AACrB,QAAQ,kCAAkC;AAC1C;AACA,0CAA0C,iBAAiB,GAAG,MAAM;AACpE;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,oBAAoB,kBAAc;AAClC;AACA;AACA;AACA;AACA,qDAAqD,cAAc;AACnE;AACA;AACA;AACA,QAAQ;AACR;AACA,8BAA8B,mBAAmB,CAAC,qCAAqC,eAAe;AACtG;AACA;AACA,MAAM;AACN,mDAAmD,mBAAmB,CAAC;AACvE;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,uBAAuB,gCAAgC;AACvD;AACA;AACA;AACA,QAAQ;AACR,QAAQ,gBAAY,4BAA4B,2CAA2C;AAC3F;AACA;AACA;AACA;AACA,UAAU;AACV,kDAAkD,cAAc;AAChE;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,+BAA+B,2CAA2C;AAC1E;AACA,MAAM;AACN;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,IAAI,gBAAY;AAChB;AACA;AACA;AACA,qBAAqB,iCAAiC;AACtD;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,qBAAqB,iCAAiC;AACtD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,OAAO;AACP;AACA;AACA;AACA,qBAAqB,iCAAiC;AACtD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,OAAO;AACP,IAAI,gBAAY;;AAEhB;AACA,IAAI,gBAAY;AAChB,oCAAoC,sBAAsB;AAC1D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gDAAgD,0BAA0B;AAC1E,sCAAsC,sFAAsF;AAC5H;AACA;AACA,OAAO;AACP,IAAI,gBAAY;;AAEhB;AACA,IAAI,gBAAY;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,IAAI,gBAAY;AAChB,IAAI,gBAAY;AAChB;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,yBAAyB,uBAAuB;AAChD;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,sBAAsB,wBAAwB;AAC9C,QAAQ;AACR,sBAAsB,oBAAoB;AAC1C,QAAQ;AACR,sBAAsB,eAAe;AACrC;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,QAAQ,eAAW;AACnB;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA,MAAM,eAAW;AACjB;AACA,OAAO;AACP;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,IAAI,gBAAY,eAAe,gBAAgB;;AAE/C,oBAAoB,YAAY,IAAI,eAAe;AACnD;AACA;AACA;AACA,uBAAuB,sBAAsB;AAC7C;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,wBAAwB,gCAAgC,IAAI,oCAAoC;AAChG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA,wCAAwC,gCAAgC,EAAE,mCAAmC;;AAE7G;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA,IAAI,gBAAY,0CAA0C,MAAM,GAAG,OAAO,uBAAuB,KAAK;AACtG;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,oCAAoC,kEAAkE;AACtG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8CAA8C,uCAAuC;AACrF;AACA,MAAM;AACN,sBAAsB,uCAAuC,QAAQ;AACrE;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA,8CAA8C,sDAAsD,IAAI;AACxG,sCAAsC,MAAM,KAAK,KAAK,iBAAiB,YAAY;AACnF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB,cAAc;AACnC,sBAAsB,cAAc,CAAC,8CAA8C;AACnF,sBAAsB,cAAc,CAAC,iDAAiD;AACtF,sBAAsB,cAAc,CAAC,iDAAiD;AACtF,sBAAsB,cAAc;AACpC,sBAAsB,cAAc,CAAC,8CAA8C;AACnF;AACA,gBAAgB,cAAc,CAAC,iDAAiD;AAChF;AACA,gBAAgB,cAAc,CAAC,iDAAiD;AAChF;AACA;AACA,kBAAkB,cAAc,CAAC,kDAAkD;AACnF;AACA,oBAAoB,cAAc;AAClC,kBAAkB,kDAAkD;AACpE;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,SAAS,cAAc,sCAAsC,cAAc;AAC3E,SAAS,cAAc;AACvB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,kFAAkF,cAAc;AAChG;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,yCAAyC,sDAAsD,IAAI;AACnG,0EAA0E,uBAAuB;AACjG;AACA,gFAAgF,4BAA4B;AAC5G;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,yCAAyC,+CAA+C,IAAI;AAC5F,IAAI,gBAAY,iCAAiC,eAAe,UAAU,YAAY,qBAAqB,WAAW,iCAAiC,kBAAkB;AACzK,sBAAsB,eAAe;AACrC,iDAAiD,UAAU,KAAK,sCAAsC;AACtG,oDAAoD,qCAAqC;AACzF;AACA;AACA,2BAA2B;AAC3B;AACA,oEAAoE,cAAc;AAClF;AACA,8CAA8C,cAAc;AAC5D;;AAEA;AACA,MAAM,gBAAY,4BAA4B,cAAc,KAAK,cAAc;AAC/E;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAM,eAAW;AACjB,mEAAmE,cAAc;AACjF,UAAU;AACV;AACA;;;AAGA;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,cAAc;AACxB;AACA,YAAY,cAAc;AAC1B;AACA,oEAAoE,mCAAmC;AACvG;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA,yDAAyD,cAAc;AACvE;AACA;AACA;AACA,0EAA0E,aAAa;AACvF;AACA;AACA;AACA;AACA,MAAM,gBAAY,wBAAwB,8CAA8C;AACxF;AACA,MAAM;AACN;AACA;AACA;;AAEA;AACA;AACA;AACA,4EAA4E,wCAAwC;AACpH;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA,kFAAkF,wCAAwC;AAC1H;AACA;AACA;AACA;AACA;AACA,MAAM,gBAAY,gCAAgC,iEAAiE;AACnH;AACA,MAAM;AACN;AACA;AACA;;AAEA;AACA;AACA;AACA,QAAQ,eAAe;AACvB;;AAEA;AACA,IAAI,gBAAY,2BAA2B,cAAc,KAAK,iCAAiC;AAC/F;AACA;AACA;AACA;AACA;AACA,wEAAwE,cAAc;AACtF;AACA;AACA;AACA;AACA;;AAEA,MAAM,gBAAY;AAClB;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;AACA;AACA,QAAQ,gBAAY,mBAAmB,kCAAkC;AACzE;;AAEA,MAAM,gBAAY;AAClB;AACA,MAAM,gBAAY;AAClB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,MAAM,gBAAY,mCAAmC,cAAc,KAAK,iDAAiD;AACzH,uCAAuC,6DAA6D;AACpG;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA,QAAQ,gBAAY;AACpB;AACA;AACA;AACA;AACA;AACA;AACA,8BAA8B,eAAe;AAC7C,2DAA2D,UAAU;AACrE;AACA;AACA,aAAa;AACb,wEAAwE,uCAAuC;AAC/G,4CAA4C,sCAAsC;AAClF;AACA;AACA;AACA;AACA,MAAM;AACN,MAAM,gBAAY;AAClB;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,MAAM;AACN;AACA;;AAEA,IAAI,gBAAY,8BAA8B,mDAAmD;AACjG;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wEAAwE,cAAc;AACtF;AACA;AACA,iFAAiF,aAAa;;AAE9F,MAAM,gBAAY;AAClB;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,MAAM;AACN,MAAM,gBAAY;AAClB;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,MAAM;AACN;AACA;;AAEA,IAAI,gBAAY,2BAA2B,mDAAmD;AAC9F;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qEAAqE,cAAc;AACnF;AACA;AACA,qEAAqE,cAAc;AACnF;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,MAAM,gBAAY;AAClB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,MAAM;AACN,MAAM,gBAAY;AAClB;AACA;AACA;AACA,OAAO;AACP;AACA,MAAM;AACN;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qEAAqE,cAAc;AACnF;AACA;AACA,qEAAqE,cAAc;AACnF;AACA;;AAEA;AACA;AA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ACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yDAAyD,cAAc;AACvE;;AAEA;AACA,MAAM;AACN;AACA;AACA;AACA,iEAAiE,IAAI;AACrE,SAAS;AACT,QAAQ;AACR;AACA;AACA,iEAAiE,IAAI;AACrE,SAAS;AACT;;AAEA;;AAEA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,gBAAgB,sBAAsB;AACtC;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,sCAAsC,cAAc;AACpD;AACA,mBAAmB,cAAc;AACjC,sBAAsB,cAAc,CAAC,8CAA8C;AACnF,sBAAsB,cAAc,CAAC,iDAAiD;AACtF,sBAAsB,cAAc,CAAC,iDAAiD;AACtF;AACA,wBAAwB,cAAc,CAAC,kDAAkD;AACzF;AACA,OAAO;AACP;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,+BAA+B;AAC/B;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA,UAAU;AACV;AACA;AACA,QAAQ;AACR;AACA,QAAQ;AACR;AACA,QAAQ;AACR;AACA,QAAQ;AACR,wBAAwB,+BAA+B;AACvD,wBAAwB,+BAA+B;AACvD;AACA;AACA,UAAU;AACV;AACA,UAAU;AACV;AACA;AACA,QAAQ;AACR;AACA;AACA,KAAK;AACL;;AAEA,mCAAmC,uCAAuC,IAAI;AAC9E,IAAI,gBAAY,4BAA4B,MAAM,kBAAkB,SAAS,gBAAgB,aAAa;;AAE1G;AACA;AACA;AACA;AACA;AACA,QAAQ,gBAAY;;AAEpB;AACA;AACA;AACA,UAAU,gBAAY,yBAAyB,YAAY;AAC3D;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA,4CAA4C,eAAe,EAAE,gBAAgB;AAC7E,UAAU,gBAAY,+CAA+C,2BAA2B;AAChG,kCAAkC,eAAe,GAAG,gBAAgB;AACpE;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAM,gBAAY;AAClB;AACA;AACA,QAAQ,gBAAY,4BAA4B,aAAa,KAAK,6BAA6B;AAC/F;AACA;AACA;AACA,qBAAqB,4FAA4F;AACjH;AACA;AACA;AACA;AACA;AACA,0CAA0C,eAAe,EAAE,gBAAgB;AAC3E,QAAQ,gBAAY,kDAAkD,6BAA6B;AACnG,iCAAiC,eAAe,GAAG,gBAAgB;AACnE;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,6CAA6C,yBAAyB;AACtE;AACA;;AAEA;AACA,QAAQ,4BAA4B;AACpC;AACA;AACA;AACA;;AAEA;AACA;AACA,qDAAqD,yCAAyC;;;AAG9F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,gBAAY,yCAAyC,aAAa;AAC5E;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,mBAAmB,iCAAiC;AACpD;AACA;AACA;AACA;AACA,8BAA8B,4CAA4C,IAAI,iBAAiB;AAC/F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAU,2BAA2B;AACrC;AACA;AACA;AACA;AACA,MAAM,gBAAY;AAClB;AACA;AACA,QAAQ,gBAAY,oBAAoB,SAAS;AACjD,wBAAwB,gDAAgD,KAAK;AAC7E;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,mEAAmE,eAAe;AAClF,mEAAmE,eAAe;AAClF,mEAAmE,eAAe;AAClF,mEAAmE,eAAe;AAClF;AACA;AACA,+CAA+C,eAAe;AAC9D,oDAAoD,0BAA0B;AAC9E;AACA;;AAEA;AACA;AACA,UAAU,2BAA2B;AACrC;AACA;AACA;AACA;AACA,MAAM,gBAAY;AAClB;AACA;AACA,QAAQ,gBAAY,gCAAgC,OAAO;AAC3D,wBAAwB,6CAA6C,KAAK;AAC1E;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAU,2BAA2B;AACrC;AACA;AACA;AACA;AACA,MAAM,gBAAY;AAClB,0EAA0E,UAAU;AACpF;AACA,QAAQ,gBAAY,mCAAmC,OAAO;AAC9D,wBAAwB,4CAA4C,KAAK;AACzE;AACA;;AAEA;AACA;AACA;AACA;AACA,WAAW,8BAA8B;AACzC;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAK;;AAEL,oBAAoB,SAAS;AAC7B;AACA;AACA;AACA,MAAM,gBAAY,0CAA0C,wEAAwE,EAAE,QAAQ;AAC9I,sCAAsC,EAAE;AACxC,sCAAsC,EAAE;AACxC;AACA;;AAEA;AACA;AACA;AACA;AACA,4BAA4B;;AAE5B,8BAA8B,oBAAgB,kBAAkB,EAAE,YAAY;;AAE9E;AACA;AACA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,OAAO;AACP,eAAe;AACf,8BAA8B,aAAa;AAC3C,4BAA4B,aAAa;AACzC;;AAEA;AACA,oBAAoB,SAAS;;AAE7B,sCAAsC,EAAE;AACxC;AACA,oBAAoB;AACpB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,eAAe,oBAAgB,aAAa;AAC5C;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,SAAS;AACT;AACA;AACA,SAAS;AACT;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,SAAS;AACT,gCAAgC,aAAa;AAC7C,OAAO;AACP;AACA;AACA;AACA;;AAEA;AACA,sBAAsB,WAAW;AACjC,IAAI,gBAAY,0BAA0B,6BAA6B;;AAEvE;AACA;AACA;AACA,MAAM,gBAAY,gCAAgC,MAAM,KAAK,6BAA6B;AAC1F,sBAAsB,yCAAyC,mDAAmD;AAClH;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,QAAQ,gBAAY,sBAAsB,GAAG,YAAY,MAAM,KAAK,OAAO;AAC3E;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,gBAAY,oBAAoB,eAAe,YAAY,MAAM,KAAK,OAAO;AACzF;AACA,yCAAyC,MAAM,+BAA+B;AAC9E;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA;AACA;AACA;;AAEA,UAAU,gBAAY,oBAAoB,eAAe,YAAY,MAAM,KAAK,kBAAkB;AAClG;AACA,uCAAuC,MAAM,+BAA+B;AAC5E;AACA,UAAU;AACV,UAAU,eAAW,yBAAyB,MAAM;AACpD;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,iCAAiC,iBAAiB;AAClD;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAM,gBAAY,0BAA0B,+BAA+B;;AAE3E;AACA;AACA,QAAQ,gBAAY,iCAAiC,OAAO,KAAK,sCAAsC;AACvG,wBAAwB,0CAA0C,0CAA0C;AAC5G;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,MAAM,gBAAY;AAClB;AACA;AACA,MAAM,gBAAY;AAClB,gCAAgC,0CAA0C;AAC1E;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,QAAQ,gBAAY,YAAY,aAAa,oBAAoB,qBAAqB;AACtF;AACA;AACA;AACA;AACA;;AAEA;AACA,8DAA8D,UAAU;AACxE,MAAM,gBAAY,iCAAiC,UAAU;AAC7D;AACA;AACA;AACA,QAAQ,gBAAY,iCAAiC,WAAW,eAAe,QAAQ;AACvF;AACA,QAAQ,gBAAY,qCAAqC,mCAAmC;AAC5F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA,WAAW;AACX;AACA;AACA,WAAW;AACX,SAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA,8CAA8C,yCAAyC;AACvF;AACA,QAAQ,qCAAqC;AAC7C,QAAQ,iCAAiC;AACzC,QAAQ,mCAAmC;AAC3C,QAAQ,mCAAmC;AAC3C;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAU,gBAAY,4BAA4B,YAAY,KAAK,kCAAkC;AACrG,0BAA0B,iDAAiD,oCAAoC;AAC/G;AACA;AACA;AACA,qBAAqB,gBAAgB;AACrC;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,6CAA6C,+BAA+B;AAC5E,6CAA6C,4BAA4B;AACzE,6CAA6C,4BAA4B;;AAEzE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,oCAAoC,mBAAmB;AACvD,iCAAiC,2BAA2B;AAC5D;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,uDAAuD;AACvD;AACA,WAAW;AACX;AACA;AACA;AACA,WAAW;;AAEX;AACA;AACA;AACA;AACA;AACA,aAAa;AACb,WAAW;AACX;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2EAA2E,kBAAc;AACzF;AACA;AACA;AACA;AACA;AACA,wFAAwF;AACxF;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,aAAa;AACb;AACA;AACA,mBAAmB,kBAAc,eAAe,kBAAc;AAC9D;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY;AACZ;AACA,UAAU;;AAEV;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,2DAA2D,cAAc;AACzE;AACA;;AAEA;AACA;AACA;AACA,kBAAkB,IAAI;AACtB;AACA;AACA,WAAW;AACX,SAAS;AACT;;AAEA;AACA;;AAEA,MAAM,gBAAY;AAClB,MAAM;AACN,MAAM,gBAAY;AAClB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,IAAI,gBAAY;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,IAAI,gBAAY;AAChB;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb,WAAW;AACX,SAAS;AACT;AACA;AACA;AACA;AACA,qEAAqE,kBAAc;AACnF;AACA,WAAW;AACX;AACA;AACA,mBAAmB,kBAAc,eAAe,kBAAc;AAC9D;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;;AAEA,IAAI,gBAAY;AAChB,iEAAiE,cAAc;AAC/E,IAAI,gBAAY;AAChB;AACA;;AAEA;AACA,IAAI,gBAAY,aAAa,KAAK;AAClC;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,oCAAoC,UAAU;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAI,gBAAY,sBAAsB,qCAAqC;AAC3E;AACA;AACA;AACA;AACA,kBAAkB,IAAI;AACtB;AACA;AACA,WAAW;AACX,SAAS;AACT;AACA;AACA;AACA,IAAI,gBAAY;AAChB;;AAEA;AACA;AACA,KAAK;AACL;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,iEAAiE,SAAS,GAAG,QAAQ;AACrF;AACA;AACA;AACA;AACA,oBAAoB,QAAQ;AAC5B,aAAa;AACb;AACA;AACA,qDAAqD,SAAS;AAC9D,OAAO;AACP;;AAEA,IAAI,gBAAY;AAChB;AACA;AACA;AACA;;AAEA;AACA;AACA,qEAAqE,+CAA+C,IAAI,SAAS;AACjI;AACA;AACA,wEAAwE,kDAAkD,IAAI,SAAS;AACvI;AACA;AACA,wEAAwE,kDAAkD,IAAI,SAAS;AACvI;AACA;AACA,0EAA0E,oDAAoD,IAAI,SAAS;AAC3I;AACA;AACA,+FAA+F,+CAA+C,IAAI,SAAS;AAC3J;AACA;AACA,oEAAoE,+CAA+C,IAAI,SAAS;AAChI;AACA;AACA;AACA;AACA;AACA,0BAA0B,+CAA+C,IAAI,eAAe;AAC5F;AACA;AACA;AACA;AACA;AACA,0BAA0B,kDAAkD,IAAI,eAAe;AAC/F;AACA;AACA,yEAAyE,mDAAmD,IAAI,SAAS;AACzI;AACA;AACA,uEAAuE,iDAAiD,IAAI,SAAS;AACrI;AACA;AACA,qEAAqE,+CAA+C,IAAI,SAAS;AACjI;AACA;AACA,4EAA4E,sDAAsD,IAAI,SAAS;AAC/I;AACA;AACA,sEAAsE,gDAAgD,IAAI,SAAS;AACnI;AACA;AACA,yEAAyE,mDAAmD,IAAI,SAAS;AACzI;AACA;AACA,wEAAwE,kDAAkD,IAAI,SAAS;AACvI;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,uBAAuB,uEAAuE,UAAU,oBAAoB;AAC5H;;AAEA,IAAI,gBAAY;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX,SAAS;AACT;AACA,OAAO;AACP,MAAM;AACN;AACA;AACA;AACA;;;AC3nFA;AACA;;AAEwC;AACN;AACF;;AAEhC;AACA;AACA;AACO;;;AAGP,iBAAiB,6CAA6C,IAAI;AAClE;AACA;AACA;;AAEA;AACA;AACA,kBAAkB;AAClB;;AAEA;AACA;AACA;;;AAGA;AACA,6CAA6C,mBAAmB,CAAC,WAAW,KAAK;AACjF,+BAA+B,2BAAuB;AACtD;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,8CAA8C,yCAAyC;AACvF;AACA;;AAEA;AACA;AACA;AACA,QAAQ,eAAW,gCAAgC,YAAY,KAAK,8BAA8B;AAClG,iCAAiC,iDAAiD,gCAAgC;AAClH;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,WAAW,iBAAiB,KAAK,UAAU;AAC3C;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,wDAAwD,iBAAiB;AACzE;AACA,uFAAuF,cAAc;AACrG;AACA;;AAEA;AACA;AACA;AACA;AACA,4BAA4B,oBAAgB;AAC5C;AACA;AACA;;AAEA;;AAEA,IAAI,gBAAY;AAChB;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;ACrIwC;AACN;AACF;AACe;AACR;;AAEhC;;AAEP;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,0CAA0C,mBAAmB,CAAC;AAC9D,0BAA0B,cAAc,CAAC;AACzC;AACA;AACA;AACA;AACA,sBAAsB,kEAAkE;AACxF;AACA;;AAEA;AACA;AACA,kBAAkB,kBAAc;;AAEhC;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;;AAEA;AACA,mEAAmE,KAAK;AACxE;AACA,iCAAiC,kCAAkC;AACnE,qCAAqC,yCAAyC,YAAY,IAAI,GAAG,cAAc;AAC/G;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,gBAAY;;AAEhB,UAAU,kBAAc;;AAExB;AACA;;AAEA,4BAA4B,WAAW;AACvC;AACA;AACA,MAAM;AACN;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA;;AAEA,IAAI,gBAAY;AAChB;AACA,IAAI,gBAAY;AAChB;AACA,IAAI,gBAAY;AAChB;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA,0BAA0B,OAAO;AACjC;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;;AAEA;;;AC/HgE;AACE;AACd;AACgB;AACxB;AACI;AACR;AAC0C;AAC5B;AACtB;;AAEzB;AACP,mBAAmB,qBAAqB;AACxC,eAAe;AACf,uBAAuB;AACvB,WAAW;AACX,qBAAqB;AACrB,aAAa;AACb,sBAAsB;AACtB;AACA,uBAAuB,eAAe;AACtC,iBAAiB,oBAAoB;AACrC,2BAA2B,oBAAoB;AAC/C,aAAa,eAAe;AAC5B,KAAK;AACL,WAAW,SAAK;AAChB,aAAa;AACb;AACA;;;AC5BkE;AAC1B;;AAExC;AACA,4CAA4C,8BAA8B;AAC1E;AACA,4BAA4B,qBAAqB;AACjD;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,mCAAmC,mBAAmB,CAAC;AACvD,4BAA4B,mBAAmB,CAAC,qBAAqB;AACrE,WAAW,mBAAmB,CAAC;AAC/B,QAAQ;AACR;AACA;AACA;AACA,uCAAuC,mBAAmB,CAAC;AAC3D;AACA;AACA,WAAW;AACX,SAAS;AACT;AACA;AACA,uCAAuC,mBAAmB,CAAC;AAC3D,SAAS;AACT,OAAO;AACP;AACA,KAAK;AACL;AACA;;AAEO;AACP,6BAA6B,qBAAqB;AAClD,aAAa,mBAAmB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,aAAa,mBAAmB,CAAC;AACjC;AACA;AACA;AACA,GAAG;;AAEH,4CAA4C,8BAA8B;AAC1E,2BAA2B,qBAAqB;AAChD;;AAEA,6BAA6B,qBAAqB;AAClD,aAAa,mBAAmB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,aAAa,mBAAmB,CAAC;AACjC;AACA,UAAU,kBAAkB;AAC5B;AACA,GAAG;;AAEH;;;AC7DoE;AAC5B;AACR;;AAEzB;;AAEP,2BAA2B,iBAAa;AACxC;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,6DAA6D,0BAA0B,CAAC,sCAAsC,0BAA0B,CAAC;;AAEzJ;AACA;AACA,8BAA8B,mBAAmB,CAAC,kCAAkC;AACpF;AACA,UAAU;AACV,sDAAsD,mBAAmB,CAAC,0CAA0C,iBAAiB;AACrI;AACA,OAAO;;AAEP;AACA;AACA;AACA,KAAK;AACL,GAAG;;AAEH;;;ACtC6C;AACU;AACC;;AAExD;AACA,EAAE,gBAAgB;AAClB,CAAC;;AAED;AACA,EAAE,mBAAmB;AACrB,EAAE,WAAW;AACb,CAAC","sources":["webpack://pathmuncher/./src/constants.js","webpack://pathmuncher/./src/utils.js","webpack://pathmuncher/./src/logger.js","webpack://pathmuncher/./src/data/equipment.js","webpack://pathmuncher/./src/data/features.js","webpack://pathmuncher/./src/data/spells.js","webpack://pathmuncher/./src/app/Seasoning.js","webpack://pathmuncher/./src/app/CompendiumMatcher.js","webpack://pathmuncher/./src/app/CompendiumSelector.js","webpack://pathmuncher/./src/app/Pathmuncher.js","webpack://pathmuncher/./src/app/PetShop.js","webpack://pathmuncher/./src/app/PathmuncherImporter.js","webpack://pathmuncher/./src/hooks/api.js","webpack://pathmuncher/./src/hooks/settings.js","webpack://pathmuncher/./src/hooks/sheets.js","webpack://pathmuncher/./src/module.js"],"sourcesContent":["const debouncedReload = foundry.utils.debounce(() => window.location.reload(), 100);\n\nconst CONSTANTS = {\n MODULE_NAME: \"pathmuncher\",\n MODULE_FULL_NAME: \"Pathmuncher\",\n FLAG_NAME: \"pathmuncher\",\n SETTINGS: {\n // Enable options\n LOG_LEVEL: \"log-level\",\n RESTRICT_TO_TRUSTED: \"restrict-to-trusted\",\n ADD_VISION_FEATS: \"add-vision-feats\",\n USE_CUSTOM_COMPENDIUM_MAPPINGS: \"use-custom-compendium-mappings\",\n CUSTOM_COMPENDIUM_MAPPINGS: \"custom-compendium-mappings\",\n USE_IMMEDIATE_DEEP_DIVE: \"use-immediate-deep-dive\",\n },\n\n FEAT_PRIORITY: [\n \"Heritage\",\n \"Heritage Feat\",\n \"Ancestry\",\n \"Ancestry Feat\",\n \"Background\",\n \"Background Feat\",\n \"Class Feat\",\n \"Skill Feat\",\n \"General Feat\",\n \"Awarded Feat\",\n ],\n\n ACTOR_FLAGS: {\n pathbuilderId: undefined,\n addFeats: true,\n addEquipment: true,\n addBackground: true,\n addHeritage: true,\n addAncestry: true,\n addSpells: true,\n adjustBlendedSlots: true,\n addMoney: true,\n addTreasure: true,\n addLores: true,\n addWeapons: true,\n addArmor: true,\n addDeity: true,\n addName: true,\n addClass: true,\n addFamiliars: true,\n addFormulas: true,\n },\n\n CORE_COMPENDIUM_MAPPINGS: {\n feats: [\"pf2e.feats-srd\"],\n ancestryFeatures: [\"pf2e.ancestryfeatures\"],\n classFeatures: [\"pf2e.classfeatures\"],\n actions: [\"pf2e.actionspf2e\"],\n spells: [\"pf2e-psychic-amps.psychic-psi-cantrips\", \"pf2e.spells-srd\"],\n classes: [\"pf2e.classes\",],\n ancestries: [\"pf2e.ancestries\",],\n heritages: [\"pf2e.heritages\"],\n equipment: [\"pf2e.equipment-srd\"],\n formulas: [\"pf2e.equipment-srd\"],\n deities: [\"pf2e.deities\"],\n backgrounds: [\"pf2e.backgrounds\"],\n },\n\n GET_DEFAULT_SETTINGS() {\n return foundry.utils.deepClone(CONSTANTS.DEFAULT_SETTINGS);\n },\n};\n\nCONSTANTS.DEFAULT_SETTINGS = {\n // Enable options\n [CONSTANTS.SETTINGS.RESTRICT_TO_TRUSTED]: {\n name: `${CONSTANTS.FLAG_NAME}.Settings.RestrictToTrusted.Name`,\n hint: `${CONSTANTS.FLAG_NAME}.Settings.RestrictToTrusted.Hint`,\n scope: \"world\",\n config: true,\n type: Boolean,\n default: false,\n onChange: debouncedReload,\n },\n\n [CONSTANTS.SETTINGS.USE_CUSTOM_COMPENDIUM_MAPPINGS]: {\n name: `${CONSTANTS.FLAG_NAME}.Settings.UseCustomCompendiumMappings.Name`,\n scope: \"world\",\n config: false,\n type: Boolean,\n default: false,\n },\n\n [CONSTANTS.SETTINGS.USE_IMMEDIATE_DEEP_DIVE]: {\n name: `${CONSTANTS.FLAG_NAME}.Settings.UseImmediateDeepDive.Name`,\n scope: \"world\",\n config: false,\n type: Boolean,\n default: true,\n },\n\n [CONSTANTS.SETTINGS.CUSTOM_COMPENDIUM_MAPPINGS]: {\n scope: \"world\",\n config: false,\n type: Object,\n default: {\n feats: [\n \"battlezoo-ancestries-dragons-pf2e.pf2e-battlezoo-dragon-feats\",\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-features\",\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-feats\",\n \"clerics.clerics-feats\",\n \"clerics.clerics-features\",\n \"pf2e.feats-srd\"\n ],\n ancestryFeatures: [\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-features\",\n \"pf2e.ancestryfeatures\",\n ],\n classFeatures: [\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-features\",\n \"battlezoo-ancestries-dragons-pf2e.pf2e-battlezoo-dragon-feats\",\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-feats\",\n \"clerics.clerics-doctrines\",\n \"clerics.clerics-feats\",\n \"clerics.clerics-features\",\n \"pf2e.classfeatures\",\n ],\n actions: [\"pf2e.actionspf2e\"],\n spells: [\"pf2e-psychic-amps.psychic-psi-cantrips\", \"pf2e.spells-srd\"],\n classes: [\"clerics.clerics-features\", \"pf2e.classes\",],\n ancestries: [\n \"battlezoo-ancestries-dragons-pf2e.pf2e-battlezoo-dragon-ancestry\",\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-ancestries\",\n \"pf2e.ancestries\",\n ],\n heritages: [\n \"battlezoo-ancestries-dragons-pf2e.pf2e-battlezoo-dragon-heritages\",\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-heritages\",\n \"pf2e.heritages\",\n ],\n equipment: [\n \"battlezoo-ancestries-dragons-pf2e.pf2e-battlezoo-dragon-equipment\",\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-equipment\",\n \"pf2e.equipment-srd\"\n ],\n formulas: [\"pf2e.equipment-srd\"],\n deities: [\"clerics.clerics-deities\", \"pf2e.deities\"],\n backgrounds: [\"pf2e.backgrounds\"],\n },\n },\n\n [CONSTANTS.SETTINGS.ADD_VISION_FEATS]: {\n name: `${CONSTANTS.FLAG_NAME}.Settings.AddVisionFeats.Name`,\n hint: `${CONSTANTS.FLAG_NAME}.Settings.AddVisionFeats.Hint`,\n scope: \"player\",\n config: true,\n type: Boolean,\n default: true,\n },\n\n // debug\n [CONSTANTS.SETTINGS.LOG_LEVEL]: {\n name: `${CONSTANTS.FLAG_NAME}.Settings.LogLevel.Name`,\n hint: `${CONSTANTS.FLAG_NAME}.Settings.LogLevel.Hint`,\n scope: \"world\",\n config: true,\n type: String,\n choices: {\n DEBUG: `${CONSTANTS.FLAG_NAME}.Settings.LogLevel.debug`,\n INFO: `${CONSTANTS.FLAG_NAME}.Settings.LogLevel.info`,\n WARN: `${CONSTANTS.FLAG_NAME}.Settings.LogLevel.warn`,\n ERR: `${CONSTANTS.FLAG_NAME}.Settings.LogLevel.error`,\n OFF: `${CONSTANTS.FLAG_NAME}.Settings.LogLevel.off`,\n },\n default: \"WARN\",\n }\n\n};\n\nCONSTANTS.PATH = `modules/${CONSTANTS.MODULE_NAME}`;\n\nexport default CONSTANTS;\n","import CONSTANTS from \"./constants.js\";\n\nconst utils = {\n\n isObject: (obj) => {\n return typeof obj === 'object' && !Array.isArray(obj) && obj !== null;\n },\n\n isString: (str) => {\n return typeof str === 'string' || str instanceof String;\n },\n\n wait: async (ms) => {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n },\n\n capitalize: (s) => {\n if (typeof s !== \"string\") return \"\";\n return s.charAt(0).toUpperCase() + s.slice(1);\n },\n\n setting: (key) => {\n return game.settings.get(CONSTANTS.MODULE_NAME, CONSTANTS.SETTINGS[key]);\n },\n\n updateSetting: async (key, value) => {\n return game.settings.set(CONSTANTS.MODULE_NAME, CONSTANTS.SETTINGS[key], value);\n },\n\n getFlags: (actor) => {\n const flags = actor.flags[CONSTANTS.FLAG_NAME]\n ? actor.flags[CONSTANTS.FLAG_NAME]\n : CONSTANTS.ACTOR_FLAGS;\n return flags;\n },\n\n setFlags: async (actor, flags) => {\n let updateData = {};\n setProperty(updateData, `flags.${CONSTANTS.FLAG_NAME}`, flags);\n await actor.update(updateData);\n return actor;\n },\n\n resetFlags: async (actor) => {\n return utils.setFlags(actor, null);\n },\n\n\n getOrCreateFolder: async (root, entityType, folderName, folderColor = \"\") => {\n let folder = game.folders.contents.find((f) =>\n f.type === entityType && f.name === folderName\n // if a root folder we want to match the root id for the parent folder\n && (root ? root.id : null) === (f.folder?.id ?? null)\n );\n // console.warn(`Looking for ${root} ${entityType} ${folderName}`);\n // console.warn(folder);\n if (folder) return folder;\n folder = await Folder.create(\n {\n name: folderName,\n type: entityType,\n color: folderColor,\n parent: (root) ? root.id : null,\n },\n { displaySheet: false }\n );\n return folder;\n },\n\n // eslint-disable-next-line no-unused-vars\n getFolder: async (kind, subFolder = \"\", baseFolderName = \"Pathmuncher\", baseColor = \"#6f0006\", subColor = \"#98020a\", typeFolder = true) => {\n let entityTypes = new Map();\n entityTypes.set(\"pets\", \"Pets\");\n\n const folderName = game.i18n.localize(`${CONSTANTS.MODULE_NAME}.labels.${kind}`);\n const entityType = entityTypes.get(kind);\n const baseFolder = await utils.getOrCreateFolder(null, entityType, baseFolderName, baseColor);\n const entityFolder = typeFolder ? await utils.getOrCreateFolder(baseFolder, entityType, folderName, subColor) : baseFolder;\n if (subFolder !== \"\") {\n const subFolderName = subFolder.charAt(0).toUpperCase() + subFolder.slice(1);\n const typeFolder = await utils.getOrCreateFolder(entityFolder, entityType, subFolderName, subColor);\n return typeFolder;\n } else {\n return entityFolder;\n }\n },\n\n};\n\n\nexport default utils;\n","import CONSTANTS from \"./constants.js\";\nimport utils from \"./utils.js\";\n\nconst logger = {\n _showMessage: (logLevel, data) => {\n if (!logLevel || !data || typeof logLevel !== \"string\") {\n return false;\n }\n\n const setting = utils.setting(\"LOG_LEVEL\");\n const logLevels = [\"DEBUG\", \"INFO\", \"WARN\", \"ERR\", \"OFF\"];\n const logLevelIndex = logLevels.indexOf(logLevel.toUpperCase());\n if (setting == \"OFF\" || logLevelIndex === -1 || logLevelIndex < logLevels.indexOf(setting)) {\n return false;\n }\n return true;\n },\n log: (logLevel, ...data) => {\n if (!logger._showMessage(logLevel, data)) {\n return;\n }\n\n logLevel = logLevel.toUpperCase();\n\n let msg = \"No logging message provided. Please see the payload for more information.\";\n let payload = data.slice();\n if (data[0] && typeof (data[0] == \"string\")) {\n msg = data[0];\n if (data.length > 1) {\n payload = data.slice(1);\n } else {\n payload = null;\n }\n }\n msg = `${CONSTANTS.MODULE_NAME} | ${logLevel} > ${msg}`;\n switch (logLevel) {\n case \"DEBUG\":\n if (payload) {\n console.debug(msg, ...payload); // eslint-disable-line no-console\n } else {\n console.debug(msg); // eslint-disable-line no-console\n }\n break;\n case \"INFO\":\n if (payload) {\n console.info(msg, ...payload); // eslint-disable-line no-console\n } else {\n console.info(msg); // eslint-disable-line no-console\n }\n break;\n case \"WARN\":\n if (payload) {\n console.warn(msg, ...payload); // eslint-disable-line no-console\n } else {\n console.warn(msg); // eslint-disable-line no-console\n }\n break;\n case \"ERR\":\n if (payload) {\n console.error(msg, ...payload); // eslint-disable-line no-console\n } else {\n console.error(msg); // eslint-disable-line no-console\n }\n break;\n default:\n break;\n }\n },\n\n debug: (...data) => {\n logger.log(\"DEBUG\", ...data);\n },\n\n info: (...data) => {\n logger.log(\"INFO\", ...data);\n },\n\n warn: (...data) => {\n logger.log(\"WARN\", ...data);\n },\n\n error: (...data) => {\n logger.log(\"ERR\", ...data);\n },\n};\nexport default logger;\n","const SWAPS = [\n /^(Greater) (.*)/,\n /^(Lesser) (.*)/,\n /^(Major) (.*)/,\n /^(Moderate) (.*)/,\n /^(Standard) (.*)/,\n];\n\n// this equipment is named differently in foundry vs pathbuilder\nexport const EQUIPMENT_RENAME_STATIC_MAP = [\n { pbName: \"Chain\", foundryName: \"Chain (10 feet)\" },\n { pbName: \"Oil\", foundryName: \"Oil (1 pint)\" },\n { pbName: \"Bracelets of Dashing\", foundryName: \"Bracelet of Dashing\" },\n { pbName: \"Fingerprinting Kit\", foundryName: \"Fingerprint Kit\" },\n { pbName: \"Ladder\", foundryName: \"Ladder (10-foot)\" },\n { pbName: \"Mezmerizing Opal\", foundryName: \"Mesmerizing Opal\" },\n { pbName: \"Explorer's Clothing\", foundryName: \"Clothing (Explorer's)\" },\n { pbName: \"Flaming Star (Greater)\", foundryName: \"Greater Flaming Star\" },\n { pbName: \"Potion of Lesser Darkvision\", foundryName: \"Darkvision Elixir (Lesser)\" },\n { pbName: \"Potion of Greater Darkvision\", foundryName: \"Darkvision Elixir (Greater)\" },\n { pbName: \"Potion of Moderate Darkvision\", foundryName: \"Darkvision Elixir (Moderate)\" },\n { pbName: \"Bottled Sunlight\", foundryName: \"Formulated Sunlight\" },\n { pbName: \"Magazine (Repeating Hand Crossbow)\", foundryName: \"Magazine with 5 Bolts\" },\n { pbName: \"Astrolabe (Standard)\", foundryName: \"Standard Astrolabe\" },\n { pbName: \"Skinitch Salve\", foundryName: \"Skinstitch Salve\" },\n { pbName: \"Flawless Scale\", foundryName: \"Abadar's Flawless Scale\" },\n { pbName: \"Construct Key\", foundryName: \"Cordelia's Construct Key\" },\n { pbName: \"Construct Key (Greater)\", foundryName: \"Cordelia's Greater Construct Key\" },\n { pbName: \"Lesser Swapping Stone\", foundryName: \"Lesser Bonmuan Swapping Stone\" },\n { pbName: \"Major Swapping Stone\", foundryName: \"Major Bonmuan Swapping Stone\" },\n { pbName: \"Moderate Swapping Stone\", foundryName: \"Moderate Bonmuan Swapping Stone\" },\n { pbName: \"Greater Swapping Stone\", foundryName: \"Greater Bonmuan Swapping Stone\" },\n { pbName: \"Heartstone\", foundryName: \"Skarja's Heartstone\" },\n { pbName: \"Bullets (10 rounds)\", foundryName: \"Sling Bullets\" },\n { pbName: \"Hide\", foundryName: \"Hide Armor\" },\n { pbName: \"Soverign Glue\", foundryName: \"Sovereign Glue\" },\n];\n\nfunction generateDynamicNames(pbName) {\n const result = [];\n // if we have a hardcoded map, don't return here\n for (const reg of SWAPS) {\n const match = pbName.match(reg);\n if (match) {\n result.push({ pbName, foundryName: `${match[2]} (${match[1]})`, details: match[2] });\n }\n }\n return result;\n}\n\n\nexport function EQUIPMENT_RENAME_MAP(pbName = null) {\n const postfixNames = pbName ? generateDynamicNames(pbName) : [];\n return postfixNames.concat(EQUIPMENT_RENAME_STATIC_MAP);\n}\n\n\n// this is equipment is special and shouldn't have the transformations applied to it\nexport const RESTRICTED_EQUIPMENT = [\n \"Bracers of Armor\",\n];\n\nexport const IGNORED_EQUIPMENT = [\n \"Unarmored\"\n];\n","// these are features which are named differently in pathbuilder to foundry\n\nimport utils from \"../utils.js\";\n\nconst POSTFIX_PB_REMOVALS = [\n /(.*) (Racket)$/,\n /(.*) (Style)$/,\n /(.*) (Initiate Benefit)$/,\n // Cleric +\n /(.*) (Doctrine)$/,\n /(.*) (Element)$/,\n /(.*) (Impulse Junction)$/,\n /(.*) (Gate Junction:).*$/,\n];\n\nconst PREFIX_PB_REMOVALS = [\n /^(Arcane Thesis): (.*)/,\n /^(Arcane School): (.*)/,\n /^(The) (.*)/,\n // Cleric +\n /^(Blessing): (.*)/,\n];\n\nconst POSTFIX_PB_SPLIT_AND_KEEP = [\n /(.*) (Impulse Junction)$/,\n /(.*) Gate Junction: (.*)$/,\n];\n\nconst PARENTHESIS = [\n /^(.*) \\((.*)\\)$/,\n];\n\nconst SPLITS = [\n /^(.*): (.*)/,\n];\n\nconst SWAPS = [\n /^(Greater) (.*)/,\n /^(Lesser) (.*)/,\n /^(Major) (.*)/,\n];\n\nconst FEAT_RENAME_STATIC_MAP = [\n { pbName: \"Academic\", foundryName: \"Ustalavic Academic\" },\n { pbName: \"Academic (Arcana)\", foundryName: \"Magaambya Academic\" },\n { pbName: \"Academic (Nature)\", foundryName: \"Magaambya Academic\" },\n { pbName: \"Aerialist\", foundryName: \"Shory Aerialist\" },\n { pbName: \"Aeromancer\", foundryName: \"Shory Aeromancer\" },\n { pbName: \"Ancient-Blooded\", foundryName: \"Ancient-Blooded Dwarf\" },\n { pbName: \"Antipaladin [Chaotic Evil]\", foundryName: \"Antipaladin\" },\n { pbName: \"Ape\", foundryName: \"Ape Animal Instinct\" },\n { pbName: \"Aquatic Eyes (Darkvision)\", foundryName: \"Aquatic Eyes\" },\n { pbName: \"Astrology\", foundryName: \"Saoc Astrology\" },\n { pbName: \"Battle Ready\", foundryName: \"Battle-Ready Orc\" },\n { pbName: \"Bite (Gnoll)\", foundryName: \"Bite\" },\n { pbName: \"Bloodline: Genie (Efreeti)\", foundryName: \"Bloodline: Genie\" },\n { pbName: \"Bloody Debilitations\", foundryName: \"Bloody Debilitation\" },\n { pbName: \"Canoneer\", foundryName: \"Cannoneer\" },\n { pbName: \"Cave Climber Kobold\", foundryName: \"Caveclimber Kobold\" },\n { pbName: \"Child of Squalor\", foundryName: \"Child of the Puddles\" },\n { pbName: \"Chosen One\", foundryName: \"Chosen of Lamashtu\" },\n { pbName: \"Cognative Mutagen (Greater)\", foundryName: \"Cognitive Mutagen (Greater)\" },\n { pbName: \"Cognative Mutagen (Lesser)\", foundryName: \"Cognitive Mutagen (Lesser)\" },\n { pbName: \"Cognative Mutagen (Major)\", foundryName: \"Cognitive Mutagen (Major)\" },\n { pbName: \"Cognative Mutagen (Moderate)\", foundryName: \"Cognitive Mutagen (Moderate)\" },\n { pbName: \"Cognitive Crossover\", foundryName: \"Kreighton's Cognitive Crossover\" },\n { pbName: \"Collegiate Attendant Dedication\", foundryName: \"Magaambyan Attendant Dedication\" },\n { pbName: \"Construct Carver\", foundryName: \"Tupilaq Carver\" },\n { pbName: \"Cunning Stance\", foundryName: \"Devrin's Cunning Stance\" },\n { pbName: \"Constructed (Android)\", foundryName: \"Constructed\" },\n { pbName: \"Dazzling Diversion\", foundryName: \"Devrin's Dazzling Diversion\" },\n { pbName: \"Deadly Hair\", foundryName: \"Syu Tak-nwa's Deadly Hair\" },\n { pbName: \"Deepvision\", foundryName: \"Deep Vision\" },\n { pbName: \"Deflect Arrows\", foundryName: \"Deflect Arrow\" },\n { pbName: \"Desecrator [Neutral Evil]\", foundryName: \"Desecrator\" },\n { pbName: \"Detective Dedication\", foundryName: \"Edgewatch Detective Dedication\" },\n { pbName: \"Duelist Dedication (LO)\", foundryName: \"Aldori Duelist Dedication\" },\n { pbName: \"Dwarven Hold Education\", foundryName: \"Dongun Education\" },\n { pbName: \"Ember's Eyes (Darkvision)\", foundryName: \"Ember's Eyes\" },\n { pbName: \"Enhanced Familiar Feat\", foundryName: \"Enhanced Familiar\" },\n { pbName: \"Enhanced Fire\", foundryName: \"Artokus's Fire\" },\n { pbName: \"Enigma\", foundryName: \"Enigma Muse\" },\n { pbName: \"Escape\", foundryName: \"Fane's Escape\" },\n { pbName: \"Eye of the Arcane Lords\", foundryName: \"Eye of the Arclords\" },\n { pbName: \"Flip\", foundryName: \"Farabellus Flip\" },\n { pbName: \"Fourberie\", foundryName: \"Fane's Fourberie\" },\n { pbName: \"Ganzi Gaze (Low-Light Vision)\", foundryName: \"Ganzi Gaze\" },\n { pbName: \"Guild Agent Dedication\", foundryName: \"Pathfinder Agent Dedication\" },\n { pbName: \"Harmful Font\", foundryName: \"Divine Font\" },\n { pbName: \"Green Watcher\", foundryName: \"Greenwatcher\" },\n { pbName: \"Green Watch Initiate\", foundryName: \"Greenwatch Initiate\" },\n { pbName: \"Green Watch Veteran\", foundryName: \"Greenwatch Veteran\" },\n { pbName: \"Healing Font\", foundryName: \"Divine Font\" },\n { pbName: \"Heatwave\", foundryName: \"Heat Wave\" },\n { pbName: \"Heavenseeker Dedication\", foundryName: \"Jalmeri Heavenseeker Dedication\" },\n { pbName: \"Heir of the Astrologers\", foundryName: \"Heir of the Saoc\" },\n { pbName: \"High Killer Training\", foundryName: \"Vernai Training\" },\n { pbName: \"Ice-Witch\", foundryName: \"Irriseni Ice-Witch\" },\n { pbName: \"Impeccable Crafter\", foundryName: \"Impeccable Crafting\" },\n { pbName: \"Incredible Beastmaster's Companion\", foundryName: \"Incredible Beastmaster Companion\" },\n { pbName: \"Interrogation\", foundryName: \"Bolera's Interrogation\" },\n { pbName: \"Katana\", foundryName: \"Katana Weapon Familiarity\" },\n { pbName: \"Liberator [Chaotic Good]\", foundryName: \"Liberator\" },\n { pbName: \"Lumberjack Dedication\", foundryName: \"Turpin Rowe Lumberjack Dedication\" },\n { pbName: \"Maestro\", foundryName: \"Maestro Muse\" },\n { pbName: \"Major Lesson I\", foundryName: \"Major Lesson\" },\n { pbName: \"Major Lesson II\", foundryName: \"Major Lesson\" },\n { pbName: \"Major Lesson III\", foundryName: \"Major Lesson\" },\n { pbName: \"Mantis God's Grip\", foundryName: \"Achaekek's Grip\" },\n { pbName: \"Marked for Death\", foundryName: \"Mark for Death\" },\n { pbName: \"Miraculous Spells\", foundryName: \"Miraculous Spell\" },\n { pbName: \"Multifarious\", foundryName: \"Multifarious Muse\" },\n { pbName: \"Mystic\", foundryName: \"Nexian Mystic\" },\n { pbName: \"Paladin [Lawful Good]\", foundryName: \"Paladin\" },\n { pbName: \"Parry\", foundryName: \"Aldori Parry\" },\n { pbName: \"Polymath\", foundryName: \"Polymath Muse\" },\n { pbName: \"Precise Debilitation\", foundryName: \"Precise Debilitations\" },\n { pbName: \"Prodigy\", foundryName: \"Merabite Prodigy\" },\n { pbName: \"Quick Climber\", foundryName: \"Quick Climb\" },\n { pbName: \"Raider\", foundryName: \"Ulfen Raider\" },\n { pbName: \"Recognise Threat\", foundryName: \"Recognize Threat\" },\n { pbName: \"Redeemer [Neutral Good]\", foundryName: \"Redeemer\" },\n { pbName: \"Revivification Protocall\", foundryName: \"Revivification Protocol\" },\n { pbName: \"Riposte\", foundryName: \"Aldori Riposte\" },\n { pbName: \"Rkoan Arts\", foundryName: \"Rokoan Arts\" },\n { pbName: \"Saberteeth\", foundryName: \"Saber Teeth\" },\n { pbName: \"Scholarly Recollection\", foundryName: \"Uzunjati Recollection\" },\n { pbName: \"Scholarly Storytelling\", foundryName: \"Uzunjati Storytelling\" },\n { pbName: \"Shamanic Adherent\", foundryName: \"Rivethun Adherent\" },\n { pbName: \"Shamanic Disciple\", foundryName: \"Rivethun Disciple\" },\n { pbName: \"Shamanic Spiritual Attunement\", foundryName: \"Rivethun Spiritual Attunement\" },\n { pbName: \"Skysage Dedication\", foundryName: \"Oatia Skysage Dedication\" },\n { pbName: \"Secret Lesson\", foundryName: \"Janatimo's Lessons\" },\n { pbName: \"Sentry Dedication\", foundryName: \"Lastwall Sentry Dedication\" },\n { pbName: \"Stab and Snag\", foundryName: \"Stella's Stab and Snag\" },\n { pbName: \"Tenets of Evil\", foundryName: \"The Tenets of Evil\" },\n { pbName: \"Tenets of Good\", foundryName: \"The Tenets of Good\" },\n { pbName: \"Tongue of the Sun and Moon\", foundryName: \"Tongue of Sun and Moon\" },\n { pbName: \"Tribal Bond\", foundryName: \"Quah Bond\" },\n { pbName: \"Tyrant [Lawful Evil]\", foundryName: \"Tyrant\" },\n { pbName: \"Vestigal Wings\", foundryName: \"Vestigial Wings\" },\n { pbName: \"Virtue-Forged Tattooed\", foundryName: \"Virtue-Forged Tattoos\" },\n { pbName: \"Wakizashi\", foundryName: \"Wakizashi Weapon Familiarity\" },\n { pbName: \"Warden\", foundryName: \"Lastwall Warden\" },\n { pbName: \"Warrior\", foundryName: \"Warrior Muse\" },\n { pbName: \"Wary Eye\", foundryName: \"Eye of Ozem\" },\n { pbName: \"Wayfinder Resonance Infiltrator\", foundryName: \"Westyr's Wayfinder Repository\" },\n { pbName: \"Wind God's Fan\", foundryName: \"Wind God’s Fan\" },\n { pbName: \"Wind God’s Fan\", foundryName: \"Wind God's Fan\" },\n // dragons\n { pbName: \"Black\", foundryName: \"Black Dragon\" },\n { pbName: \"Brine\", foundryName: \"Brine Dragon\" },\n { pbName: \"Copper\", foundryName: \"Copper Dragon\" },\n { pbName: \"Blue\", foundryName: \"Blue Dragon\" },\n { pbName: \"Bronze\", foundryName: \"Bronze Dragon\" },\n { pbName: \"Cloud\", foundryName: \"Cloud Dragon\" },\n { pbName: \"Sky\", foundryName: \"Sky Dragon\" },\n { pbName: \"Brass\", foundryName: \"Brass Dragon\" },\n { pbName: \"Underworld\", foundryName: \"Underworld Dragon\" },\n { pbName: \"Crystal\", foundryName: \"Crystal Dragon\" },\n { pbName: \"Forest\", foundryName: \"Forest Dragon\" },\n { pbName: \"Green\", foundryName: \"Green Dragon\" },\n { pbName: \"Sea\", foundryName: \"Sea Dragon\" },\n { pbName: \"Silver\", foundryName: \"Silver Dragon\" },\n { pbName: \"White\", foundryName: \"White Dragon\" },\n { pbName: \"Sovereign\", foundryName: \"Sovereign Dragon\" },\n { pbName: \"Umbral\", foundryName: \"Umbral Dragon\" },\n { pbName: \"Red\", foundryName: \"Red Dragon\" },\n { pbName: \"Gold\", foundryName: \"Gold Dragon\" },\n { pbName: \"Magma\", foundryName: \"Magma Dragon\" },\n // sizes for fleshwarp\n { pbName: \"Medium\", foundryName: \"med\" },\n { pbName: \"Small\", foundryName: \"sm\" },\n // Cleric +\n { pbName: \"Decree of the Warsworn Ecstacy\", foundryName: \"Decree of Warsworn Ecstacy\" },\n { pbName: \"Decree of Warsworn Ecstacy\", foundryName: \"Decree of the Warsworn Ecstacy\" },\n];\n\nfunction generateDynamicNames(pbName) {\n const result = [];\n // if we have a hardcoded map, don't return here\n if (FEAT_RENAME_STATIC_MAP.some((e) => e.pbName === pbName)) return result;\n for (const reg of POSTFIX_PB_REMOVALS) {\n const match = pbName.match(reg);\n if (match) {\n result.push({ pbName, foundryName: match[1], details: match[2] });\n }\n }\n for (const reg of PREFIX_PB_REMOVALS) {\n const match = pbName.match(reg);\n if (match) {\n result.push({ pbName, foundryName: match[2], details: match[1] });\n }\n }\n for (const reg of SPLITS) {\n const match = pbName.match(reg);\n if (match) {\n result.push({ pbName, foundryName: match[2], details: match[1] });\n }\n }\n for (const reg of PARENTHESIS) {\n const match = pbName.match(reg);\n if (match) {\n result.push({ pbName, foundryName: match[1], details: match[2] });\n }\n }\n for (const reg of SWAPS) {\n const match = pbName.match(reg);\n if (match) {\n result.push({ pbName, foundryName: `${match[2]} (${match[1]})`, details: match[2] });\n }\n }\n return result;\n}\n\nexport function FEAT_RENAME_MAP(pbName = null) {\n const postfixNames = pbName ? generateDynamicNames(pbName) : [];\n return postfixNames.concat(FEAT_RENAME_STATIC_MAP);\n}\n\nconst SHARED_IGNORE_LIST = [\n \"Draconic Rage\", // just handled by effects on Draconic Instinct\n \"Mirror Initiate Benefit\",\n \"Spellstrike Specifics\",\n \"Unarmored\",\n \"Simple Weapon Expertise\",\n \"Spellbook\",\n \"Energy Emanation\", // pathbuilder does not pass through a type for this\n \"Imprecise Sense\", // this gets picked up and added by granted features\n \"Imprecise Scent\", // this gets picked up and added by granted features\n];\n\nconst IGNORED_FEATS_LIST = [\n // ignore skills listed as feats\n \"Acrobatics\",\n \"Athletics\",\n \"Deception\",\n \"Intimidation\",\n \"Nature\",\n \"Performance\",\n \"Society\",\n \"Survival\",\n \"Arcana\",\n \"Crafting\",\n \"Diplomacy\",\n \"Medicine\",\n \"Occultism\",\n \"Religion\",\n \"Stealth\",\n \"Thievery\",\n\n // sizes\n // \"Medium\",\n // \"Small\",\n];\n\nconst IGNORED_SPECIALS_LIST = [\n\n];\n\nexport function IGNORED_FEATS() {\n // const visionFeats = utils.setting(\"ADD_VISION_FEATS\") ? [] : [\"Low-Light Vision\", \"Darkvision\"];\n return IGNORED_FEATS_LIST.concat(SHARED_IGNORE_LIST);\n}\n\nexport function IGNORED_SPECIALS() {\n const visionFeats = utils.setting(\"ADD_VISION_FEATS\") ? [] : [\"Low-Light Vision\", \"Darkvision\"];\n return IGNORED_SPECIALS_LIST.concat(SHARED_IGNORE_LIST, visionFeats);\n}\n\nexport function SPECIAL_NAME_ADDITIONS(specials) {\n const newSpecials = [];\n\n for (const special of specials) {\n for (const reg of POSTFIX_PB_SPLIT_AND_KEEP) {\n const match = special.match(reg);\n if (match) {\n newSpecials.push(match[2]);\n }\n }\n }\n return newSpecials;\n}\n","export const FEAT_SPELLCASTING = [\n { name: \"Kitsune Spell Familiarity\", showSlotless: false, knownSpells: [\"Daze\", \"Forbidding Ward\", \"Ghost Sound\"], preparePBSpells: true, },\n { name: \"Kitsune Spell Expertise\", showSlotless: false, knownSpells: [\"Confusion\", \"Death Ward\", \"Illusory Scene\"], preparePBSpells: true, },\n { name: \"Kitsune Spell Mysteries\", showSlotless: false, knownSpells: [\"Bane\", \"Illusory Object\", \"Sanctuary\"], preparePBSpells: true, },\n { name: \"Nagaji Spell Familiarity\", showSlotless: false, knownSpells: [\"Daze\", \"Detect Magic\", \"Mage Hand\"], preparePBSpells: true, },\n { name: \"Nagaji Spell Expertise\", showSlotless: false, knownSpells: [\"Blink\", \"Control Water\", \"Subconscious Suggestion\"], preparePBSpells: true, },\n { name: \"Nagaji Spell Mysteries\", showSlotless: false, knownSpells: [\"Charm\", \"Fleet Step\", \"Heal\"], preparePBSpells: true, },\n { name: \"Rat Magic\", showSlotless: false, knownSpells: [], preparePBSpells: true, },\n];\n\nconst REMASTER_NAMES = [\n { pbName: \"Scorching Ray\", foundryName: \"Blazing Bolt\" },\n { pbName: \"Burning Hands\", foundryName: \"Breathe Fire\" },\n { pbName: \"Calm Emotions\", foundryName: \"Calm\" },\n { pbName: \"Comprehend Languages\", foundryName: \"Translate\" },\n { pbName: \"Purify Food and Drink\", foundryName: \"Cleanse Cuisine\" },\n { pbName: \"Entangle\", foundryName: \"Entangling Flora\" },\n { pbName: \"Endure Elements\", foundryName: \"Environmental Endurance\" },\n { pbName: \"Meteor Swarm\", foundryName: \"Falling Stars\" },\n { pbName: \"Plane Shift\", foundryName: \"Interplanar Teleport\" },\n { pbName: \"Know Direction\", foundryName: \"Know the Way\" },\n { pbName: \"Stoneskin\", foundryName: \"Mountain Resilience\" },\n { pbName: \"Mage Armor\", foundryName: \"Mystic Armor\" },\n { pbName: \"Tree Stride\", foundryName: \"Nature's Pathway\" },\n { pbName: \"Barkskin\", foundryName: \"Oaken Resilience\" },\n { pbName: \"Tree Shape\", foundryName: \"One with Plants\" },\n { pbName: \"Meld into Stone\", foundryName: \"One with Stone\" },\n { pbName: \"Gentle Repose\", foundryName: \"Peaceful Rest\" },\n { pbName: \"Flesh to Stone\", foundryName: \"Petrify\" },\n { pbName: \"Dimensional Lock\", foundryName: \"Planar Seal\" },\n { pbName: \"Magic Fang\", foundryName: \"Runic Body\" },\n { pbName: \"Magic Weapon\", foundryName: \"Runic Weapon\" },\n { pbName: \"See Invisibility\", foundryName: \"See the Unseen\" },\n { pbName: \"Longstrider\", foundryName: \"Tailwind\" },\n { pbName: \"Tanglefoot\", foundryName: \"Tangle Vine\" },\n { pbName: \"Mage Hand\", foundryName: \"Telekinetic Hand\" },\n { pbName: \"Dimension Door\", foundryName: \"Translocate\" },\n { pbName: \"Tongues\", foundryName: \"Truespeech\" },\n { pbName: \"Gaseous Form\", foundryName: \"Vapor Form\" },\n];\n\nexport function spellRename(spellName) {\n if (foundry.utils.isNewerVersion(game.system.version, \"5.3.0\")) {\n const remasterName = REMASTER_NAMES.find((remaster) => remaster.pbName === spellName);\n if (remasterName) {\n return remasterName.foundryName;\n }\n }\n return spellName;\n}\n","import { EQUIPMENT_RENAME_MAP, RESTRICTED_EQUIPMENT, IGNORED_EQUIPMENT } from \"../data/equipment.js\";\nimport { FEAT_RENAME_MAP, IGNORED_FEATS, IGNORED_SPECIALS } from \"../data/features.js\";\nimport { FEAT_SPELLCASTING } from \"../data/spells.js\";\n\n/**\n * This class acts as a wrapper around the renaming data,\n * and the changing of names for foundry\n *\n * When Munching we refer to this as Seasoning the data to taste.\n *\n * It's split out just to make it more manageable\n */\nexport class Seasoning {\n\n // sluggify\n static slug(name) {\n return game.pf2e.system.sluggify(name);\n }\n\n // sluggify with dromedary casing\n static slugD(name) {\n return game.pf2e.system.sluggify(name, { camel: \"dromedary\" });\n }\n\n static FEAT_RENAME_MAP(name) {\n return FEAT_RENAME_MAP(name);\n }\n\n static EQUIPMENT_RENAME_MAP(name) {\n return EQUIPMENT_RENAME_MAP(name);\n }\n\n static getSpellCastingFeatureAdjustment(name) {\n return FEAT_SPELLCASTING.find((f) => f.name === name);\n }\n\n static getFoundryEquipmentName(pbName) {\n return Seasoning.EQUIPMENT_RENAME_MAP(pbName).find((map) => map.pbName == pbName)?.foundryName ?? pbName;\n }\n\n // static getFoundryFeatureName(pbName) {\n // const match = Seasoning.FEAT_RENAME_MAP(pbName).find((map) => map.pbName == pbName);\n // return match ?? { pbName, foundryName: pbName, details: undefined };\n // }\n\n static RESTRICTED_EQUIPMENT() {\n return RESTRICTED_EQUIPMENT;\n }\n\n // specials that are handled by Foundry and shouldn't be added\n static IGNORED_FEATS() {\n return IGNORED_FEATS();\n };\n\n static IGNORED_SPECIALS() {\n return IGNORED_SPECIALS();\n }\n\n static IGNORED_EQUIPMENT() {\n return IGNORED_EQUIPMENT;\n };\n\n static getSizeValue(size) {\n switch (size) {\n case 0:\n return \"tiny\";\n case 1:\n return \"sm\";\n case 3:\n return \"lg\";\n default:\n return \"med\";\n }\n }\n\n static PHYSICAL_ITEM_TYPES = new Set([\n \"armor\",\n \"backpack\",\n \"book\",\n \"consumable\",\n \"equipment\",\n \"treasure\",\n \"weapon\"\n ]);\n\n static isPhysicalItemType(type) {\n return Seasoning.PHYSICAL_ITEM_TYPES.has(type);\n }\n\n static getMaterialGrade(material) {\n if (material.toLowerCase().includes(\"high-grade\")) {\n return \"high\";\n } else if (material.toLowerCase().includes(\"standard-grade\")) {\n return \"standard\";\n }\n return \"low\";\n }\n\n static getFoundryFeatLocation(pathbuilderFeatType, pathbuilderFeatLevel) {\n if (pathbuilderFeatType === \"Ancestry Feat\") {\n return `ancestry-${pathbuilderFeatLevel}`;\n } else if (pathbuilderFeatType === \"Class Feat\") {\n return `class-${pathbuilderFeatLevel}`;\n } else if (pathbuilderFeatType === \"Skill Feat\") {\n return `skill-${pathbuilderFeatLevel}`;\n } else if (pathbuilderFeatType === \"General Feat\") {\n return `general-${pathbuilderFeatLevel}`;\n } else if (pathbuilderFeatType === \"Background Feat\") {\n return `skill-${pathbuilderFeatLevel}`;\n } else if (pathbuilderFeatType === \"Archetype Feat\") {\n return `archetype-${pathbuilderFeatLevel}`;\n } else if (pathbuilderFeatType === \"Kineticist Feat\") { // return as null for now\n return null;\n } else {\n return null;\n }\n }\n\n static getClassAdjustedSpecialNameLowerCase(name, className) {\n return `${name} (${className})`.toLowerCase();\n }\n\n static getDualClassAdjustedSpecialNameLowerCase(name, dualClassName) {\n return `${name} (${dualClassName})`.toLowerCase();\n }\n\n static getAncestryAdjustedSpecialNameLowerCase(name, ancestryName) {\n return `${name} (${ancestryName})`.toLowerCase();\n }\n\n static getHeritageAdjustedSpecialNameLowerCase(name, heritageName) {\n return `${name} (${heritageName})`.toLowerCase();\n }\n\n static getChampionType(alignment) {\n if (alignment == \"LG\") return \"Paladin\";\n else if (alignment == \"CG\") return \"Liberator\";\n else if (alignment == \"NG\") return \"Redeemer\";\n else if (alignment == \"LE\") return \"Tyrant\";\n else if (alignment == \"CE\") return \"Antipaladin\";\n else if (alignment == \"NE\") return \"Desecrator\";\n return \"Unknown\";\n }\n\n\n}\n","/* eslint-disable no-await-in-loop */\nimport CONSTANTS from \"../constants.js\";\nimport logger from \"../logger.js\";\nimport utils from \"../utils.js\";\nimport { Seasoning } from \"./Seasoning.js\";\n\nexport class CompendiumMatcher {\n\n constructor({ type, mappings = null, indexFields = [\"name\", \"type\", \"system.slug\"] } = {}) {\n this.type = type;\n this.indexFields = indexFields;\n this.packs = {};\n\n const packMappings = mappings !== null\n ? mappings\n : utils.setting(\"USE_CUSTOM_COMPENDIUM_MAPPINGS\")\n ? utils.setting(\"CUSTOM_COMPENDIUM_MAPPINGS\")\n : CONSTANTS.CORE_COMPENDIUM_MAPPINGS;\n packMappings[type].forEach((name) => {\n const compendium = game.packs.get(name);\n if (compendium) {\n this.packs[name] = compendium;\n }\n });\n\n this.indexes = {\n\n };\n\n }\n\n async loadCompendiums() {\n for (const [name, compendium] of Object.entries(this.packs)) {\n this.indexes[name] = await compendium.getIndex({ fields: this.indexFields });\n }\n }\n\n\n getFoundryFeatureName(pbName) {\n const match = this.FEAT_RENAME_MAP(pbName).find((map) => map.pbName == pbName);\n return match ?? { pbName, foundryName: pbName, details: undefined };\n }\n\n getNameMatch(pbName, foundryName) {\n for (const [packName, index] of Object.entries(this.indexes)) {\n const indexMatch = index.find((i) => i.name === foundryName)\n ?? index.find((i) => i.name === pbName);\n\n if (indexMatch) {\n logger.debug(`Found name only compendium document for ${pbName} (${foundryName}) in ${packName} with id ${indexMatch._id}`);\n return { i: indexMatch, pack: this.packs[packName] };\n }\n }\n return undefined;\n }\n\n getSlugMatch(pbName, foundryName) {\n for (const [packName, index] of Object.entries(this.indexes)) {\n logger.debug(`Checking for compendium documents for ${pbName} (${foundryName}) in ${packName}`, {\n pbName,\n foundryName,\n packName,\n // index,\n // foundrySlug: Seasoning.slug(foundryName),\n // pbSlug: Seasoning.slug(pbName),\n // foundryMatch: index.find((i) => (i.system.slug ?? Seasoning.slug(i.name)) === Seasoning.slug(foundryName)),\n // pbMatch: index.find((i) => (i.system.slug ?? Seasoning.slug(i.name)) === Seasoning.slug(pbName)),\n // pbSlugMatch: (null ?? Seasoning.slug(\"Phase Bolt (Psychic)\")) === Seasoning.slug(\"Phase Bolt (Psychic)\"),\n });\n const indexMatch = index.find((i) => (i.system.slug ?? Seasoning.slug(i.name)) === Seasoning.slug(foundryName))\n ?? index.find((i) => (i.system.slug ?? Seasoning.slug(i.name)) === Seasoning.slug(pbName));\n\n if (indexMatch) {\n logger.debug(`Found slug based compendium document for ${pbName} (${foundryName}) in ${packName} with id ${indexMatch._id}`);\n return { i: indexMatch, pack: this.packs[packName] };\n }\n }\n return undefined;\n }\n\n getMatch(pbName, foundryName, forceName = false) {\n\n if (forceName) {\n const nameOnlyMatch = this.getNameMatch(pbName, foundryName);\n if (nameOnlyMatch) return nameOnlyMatch;\n }\n\n const slugMatch = this.getSlugMatch(pbName, foundryName);\n if (slugMatch) return slugMatch;\n\n return undefined;\n }\n\n static checkForFilters(i, filters) {\n for (const [key, value] of Object.entries(filters)) {\n if (getProperty(i, key) !== value) {\n return false;\n }\n }\n return true;\n }\n\n getNameMatchWithFilter(pbName, foundryName, filters = {}) {\n for (const [packName, index] of Object.entries(this.indexes)) {\n logger.debug(`Checking for compendium documents for ${pbName} (${foundryName}) in ${packName}`, {\n pbName,\n foundryName,\n filters,\n packName,\n // index,\n });\n const indexMatch = index.find((i) =>\n ((i.system.slug ?? Seasoning.slug(i.name)) === Seasoning.slug(foundryName))\n && CompendiumMatcher.checkForFilters(i, filters))\n ?? index.find((i) =>\n ((i.system.slug ?? Seasoning.slug(i.name)) === Seasoning.slug(pbName)\n && CompendiumMatcher.checkForFilters(i, filters))\n );\n\n if (indexMatch) {\n logger.debug(`Found compendium document for ${pbName} (${foundryName}) in ${packName} with id ${indexMatch._id}`);\n return { i: indexMatch, pack: this.packs[packName] };\n }\n }\n\n return undefined;\n }\n\n\n}\n","import CONSTANTS from \"../constants.js\";\nimport utils from \"../utils.js\";\n\nexport class CompendiumSelector extends FormApplication {\n constructor() {\n super();\n this.lookups = utils.setting(\"CUSTOM_COMPENDIUM_MAPPINGS\");\n this.packs = game.packs\n .filter((p) => p.metadata.type === \"Item\")\n .map((p) => {\n return { id: p.metadata.id, label: `${p.metadata.label} (${p.metadata.packageName})` };\n });\n this.currentType = null;\n this.useCustomCompendiums = utils.setting(\"USE_CUSTOM_COMPENDIUM_MAPPINGS\");\n }\n\n static get defaultOptions() {\n return mergeObject(super.defaultOptions, {\n id: \"pathmuncher-compendium-selector\",\n template: `${CONSTANTS.PATH}/templates/compendium-selector.hbs`,\n width: 722,\n height: 275,\n title: game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Dialogs.CompendiumSelector.Title`),\n resizable: true,\n classes: ['pathmuncher-compendium-selector'],\n });\n }\n\n getData() {\n const lookups = [];\n for (const key in this.lookups) {\n lookups.push({\n key,\n label: game.i18n.localize(`${CONSTANTS.FLAG_NAME}.CompendiumGroups.${key}`),\n });\n }\n return {\n lookups,\n title: this.options.title,\n sourceItems: [],\n compendiumItems: [],\n useCustomCompendiums: this.useCustomCompendiums,\n };\n }\n\n async reset() {\n const defaults = CONSTANTS.GET_DEFAULT_SETTINGS();\n this.lookups = defaults[CONSTANTS.SETTINGS.CUSTOM_COMPENDIUM_MAPPINGS].default;\n await utils.updateSetting(\"CUSTOM_COMPENDIUM_MAPPINGS\", this.lookups);\n this.currentType = null;\n this.render(true);\n }\n\n async enableCustomCompendiums() {\n this.useCustomCompendiums = !this.useCustomCompendiums;\n await utils.updateSetting(\"USE_CUSTOM_COMPENDIUM_MAPPINGS\", this.useCustomCompendiums);\n }\n\n filterList(event) {\n const compendiumType = event.srcElement.value;\n const sourceList = document.getElementById(\"sourceList\");\n const compendiumList = document.getElementById(\"compendiumList\");\n\n const sourceOptions = this.packs.filter((p) => !this.lookups[compendiumType].includes(p.id));\n const compendiumOptions = this.packs.filter((p) => this.lookups[compendiumType].includes(p.id));\n\n sourceList.innerHTML = \"\";\n compendiumList.innerHTML = \"\";\n\n sourceOptions.forEach((option) => {\n const sourceListItem = document.createElement(\"option\");\n sourceListItem.value = option.id;\n sourceListItem.appendChild(document.createTextNode(option.label));\n sourceList.appendChild(sourceListItem);\n });\n\n compendiumOptions.forEach((option) => {\n const compendiumListItem = document.createElement(\"option\");\n compendiumListItem.value = option.id;\n compendiumListItem.appendChild(document.createTextNode(option.label));\n compendiumList.appendChild(compendiumListItem);\n });\n\n this.currentType = compendiumType;\n }\n\n async updateCompendiums() {\n const compendiumList = document.getElementById(\"compendiumList\");\n const compendiumOptions = Array.from(compendiumList.options);\n const compendiumIds = compendiumOptions.map((option) => {\n return option.value;\n });\n\n this.lookups[this.currentType] = compendiumIds;\n\n utils.updateSetting(\"CUSTOM_COMPENDIUM_MAPPINGS\", this.lookups);\n }\n\n async addCompendium() {\n const sourceList = document.getElementById(\"sourceList\");\n const compendiumList = document.getElementById(\"compendiumList\");\n const selectedOptions = Array.from(sourceList.selectedOptions);\n\n selectedOptions.forEach((option) => {\n compendiumList.appendChild(option);\n });\n\n await this.updateCompendiums();\n }\n\n async removeCompendium() {\n const sourceList = document.getElementById(\"sourceList\");\n const compendiumList = document.getElementById(\"compendiumList\");\n const selectedOptions = Array.from(compendiumList.selectedOptions);\n\n selectedOptions.forEach((option) => {\n sourceList.appendChild(option);\n });\n await this.updateCompendiums();\n }\n\n async moveUp() {\n const compendiumList = document.getElementById(\"compendiumList\");\n const selectedOption = compendiumList.selectedOptions[0];\n\n if (selectedOption && selectedOption.previousElementSibling) {\n compendiumList.insertBefore(selectedOption, selectedOption.previousElementSibling);\n }\n await this.updateCompendiums();\n }\n\n async moveDown() {\n const compendiumList = document.getElementById(\"compendiumList\");\n const selectedOption = compendiumList.selectedOptions[0];\n\n if (selectedOption && selectedOption.nextElementSibling) {\n compendiumList.insertBefore(selectedOption.nextElementSibling, selectedOption);\n }\n await this.updateCompendiums();\n }\n\n activateListeners(html) {\n super.activateListeners(html);\n\n document.getElementById(\"addButton\").addEventListener(\"click\", this.addCompendium.bind(this));\n document.getElementById(\"removeButton\").addEventListener(\"click\", this.removeCompendium.bind(this));\n document.getElementById(\"upButton\").addEventListener(\"click\", this.moveUp.bind(this));\n document.getElementById(\"downButton\").addEventListener(\"click\", this.moveDown.bind(this));\n document.getElementById(\"compSelector\").addEventListener(\"change\", this.filterList.bind(this));\n document.getElementById(\"resetButton\").addEventListener(\"click\", this.reset.bind(this));\n document.getElementById(\"enableCustomCompendiums\").addEventListener(\"change\", this.enableCustomCompendiums.bind(this));\n }\n}\n","/* eslint-disable no-await-in-loop */\n/* eslint-disable no-continue */\nimport CONSTANTS from \"../constants.js\";\nimport { SPECIAL_NAME_ADDITIONS } from \"../data/features.js\";\nimport { spellRename } from \"../data/spells.js\";\nimport logger from \"../logger.js\";\nimport utils from \"../utils.js\";\nimport { CompendiumMatcher } from \"./CompendiumMatcher.js\";\nimport { Seasoning } from \"./Seasoning.js\";\n\nexport class Pathmuncher {\n FEAT_RENAME_MAP(name) {\n const dynamicItems = [\n { pbName: \"Shining Oath\", foundryName: `Shining Oath (${Seasoning.getChampionType(this.source.alignment)})` },\n { pbName: \"Counterspell\", foundryName: `Counterspell (${utils.capitalize(this.getClassSpellCastingType() ?? \"\")})` },\n { pbName: \"Counterspell\", foundryName: `Counterspell (${utils.capitalize(this.getClassSpellCastingType(true) ?? \"\")})` },\n { pbName: \"Cantrip Expansion\", foundryName: `Cantrip Expansion (${this.source.class})` },\n { pbName: \"Cantrip Expansion\", foundryName: `Cantrip Expansion (${this.source.dualClass})` },\n { pbName: \"Cantrip Expansion\", foundryName: `Cantrip Expansion (${utils.capitalize(this.getClassSpellCastingType() ?? \"\")} Caster)` },\n { pbName: \"Cantrip Expansion\", foundryName: `Cantrip Expansion (${utils.capitalize(this.getClassSpellCastingType(true) ?? \"\")} Caster)` },\n ];\n return Seasoning.FEAT_RENAME_MAP(name).concat(dynamicItems);\n }\n\n getFoundryFeatureName(pbName) {\n const match = this.FEAT_RENAME_MAP(pbName).find((map) => map.pbName == pbName);\n return match ?? { pbName, foundryName: pbName, details: undefined };\n }\n\n constructor(actor, { addFeats = true, addEquipment = true, addSpells = true, adjustBlendedSlots = true,\n addMoney = true, addLores = true, addWeapons = true, addArmor = true, addTreasure = true, addDeity = true,\n addName = true, addClass = true, addBackground = true, addHeritage = true, addAncestry = true,\n statusCallback = null } = {}\n ) {\n this.actor = actor;\n // note not all these options do anything yet!\n this.options = {\n addTreasure,\n addMoney,\n addFeats,\n addSpells,\n adjustBlendedSlots,\n addEquipment,\n addLores,\n addWeapons,\n addArmor,\n addDeity,\n addName,\n addClass,\n addBackground,\n addHeritage,\n addAncestry,\n };\n this.source = null;\n this.parsed = {\n specials: [],\n feats: [],\n equipment: [],\n armor: [],\n weapons: [],\n };\n this.usedLocations = new Set();\n this.usedLocationsAlternateRules = new Set();\n this.autoAddedFeatureIds = new Set();\n this.autoAddedFeatureItems = {};\n this.promptRules = {};\n this.allFeatureRules = {};\n this.autoAddedFeatureRules = {};\n this.grantItemLookUp = {};\n this.autoFeats = [];\n this.keyAbility = null;\n this.boosts = {\n custom: false,\n class: {},\n background: {},\n ancestry: {},\n };\n this.size = \"med\";\n this.result = {\n character: {\n _id: this.actor.id,\n prototypeToken: {},\n },\n class: [],\n deity: [],\n heritage: [],\n ancestry: [],\n background: [],\n casters: [],\n spells: [],\n feats: [],\n weapons: [],\n armor: [],\n equipment: [],\n lores: [],\n money: [],\n treasure: [],\n adventurersPack: {\n item: null,\n contents: [\n { slug: \"bedroll\", qty: 1 },\n { slug: \"chalk\", qty: 10 },\n { slug: \"flint-and-steel\", qty: 1 },\n { slug: \"rope\", qty: 1 },\n { slug: \"rations\", qty: 14 },\n { slug: \"torch\", qty: 5 },\n { slug: \"waterskin\", qty: 1 },\n ],\n },\n focusPool: 0,\n };\n this.check = {};\n this.bad = [];\n this.statusCallback = statusCallback;\n this.compendiumMatchers = {};\n const compendiumMappings = utils.setting(\"USE_CUSTOM_COMPENDIUM_MAPPINGS\")\n ? utils.setting(\"CUSTOM_COMPENDIUM_MAPPINGS\")\n : CONSTANTS.CORE_COMPENDIUM_MAPPINGS;\n for (const type of Object.keys(compendiumMappings)) {\n this.compendiumMatchers[type] = new CompendiumMatcher({ type });\n }\n }\n\n async #loadCompendiumMatchers() {\n for (const matcher of Object.values(this.compendiumMatchers)) {\n await matcher.loadCompendiums();\n }\n }\n\n #statusUpdate(total, count, type, prefixLabel) {\n if (this.statusCallback) this.statusCallback(total, count, type, prefixLabel);\n }\n\n async fetchPathbuilder(pathbuilderId) {\n if (!pathbuilderId) {\n const flags = utils.getFlags(this.actor);\n pathbuilderId = flags?.pathbuilderId;\n }\n if (pathbuilderId) {\n const jsonData = await foundry.utils.fetchJsonWithTimeout(\n `https://www.pathbuilder2e.com/json.php?id=${pathbuilderId}`\n );\n if (jsonData.success) {\n this.source = jsonData.build;\n } else {\n ui.notifications.warn(\n game.i18n.format(`${CONSTANTS.FLAG_NAME}.Dialogs.Pathmuncher.FetchFailed`, { pathbuilderId })\n );\n }\n } else {\n ui.notifications.error(game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Dialogs.Pathmuncher.NoId`));\n }\n }\n\n #generateFoundryFeatLocation(document, feature) {\n if (feature.type && feature.level) {\n const ancestryParagonVariant = game.settings.get(\"pf2e\", \"ancestryParagonVariant\");\n const dualClassVariant = game.settings.get(\"pf2e\", \"dualClassVariant\");\n // const freeArchetypeVariant = game.settings.get(\"pf2e\", \"freeArchetypeVariant\");\n const location = Seasoning.getFoundryFeatLocation(feature.type, feature.level);\n if (location && !this.usedLocations.has(location)) {\n document.system.location = location;\n this.usedLocations.add(location);\n } else if (location && this.usedLocations.has(location)) {\n logger.debug(\"Variant feat location\", { ancestryParagonVariant, location, feature });\n // eslint-disable-next-line max-depth\n if (ancestryParagonVariant && feature.type === \"Ancestry Feat\") {\n document.system.location = \"ancestry-bonus\";\n this.usedLocationsAlternateRules.add(location);\n } else if (dualClassVariant && feature.type === \"Class Feat\") {\n document.system.location = `dualclass-${feature.level}`;\n this.usedLocationsAlternateRules.add(location);\n }\n }\n }\n }\n\n #processSpecialData(name) {\n if (name.includes(\"Domain: \")) {\n const domainName = name.split(\" \")[1];\n this.parsed.feats.push({ name: \"Deity's Domain\", extra: domainName });\n return true;\n } else {\n return false;\n }\n }\n\n #getContainerData(key) {\n return {\n id: key,\n containerName: this.source.equipmentContainers[key].containerName,\n bagOfHolding: this.source.equipmentContainers[key].bagOfHolding,\n backpack: this.source.equipmentContainers[key].backpack,\n };\n }\n\n #nameMap() {\n logger.debug(\"Starting Equipment Rename\");\n this.source.equipment\n .filter((e) => e[0] && e[0] !== \"undefined\")\n .forEach((e) => {\n const name = Seasoning.getFoundryEquipmentName(e[0]);\n const containerKey = Object.keys(this.source.equipmentContainers)\n .find((key) => this.source.equipmentContainers[key].containerName === name);\n\n const container = containerKey ? this.#getContainerData(containerKey) : null;\n const foundryId = foundry.utils.randomID();\n\n if (container) {\n this.source.equipmentContainers[containerKey].foundryId = foundryId;\n }\n\n const item = {\n pbName: name,\n qty: e[1],\n added: false,\n addedId: null,\n addedAutoId: null,\n inContainer: e[2] !== \"Invested\" ? e[2] : null,\n container,\n foundryId,\n invested: e[2] === \"Invested\",\n };\n this.parsed.equipment.push(item);\n });\n this.source.armor\n .filter((e) => e && e !== \"undefined\")\n .forEach((e) => {\n const name = Seasoning.getFoundryEquipmentName(e.name);\n const item = mergeObject({\n pbName: name,\n originalName: e.name,\n added: false,\n addedId: null,\n addedAutoId: null,\n }, e);\n this.parsed.armor.push(item);\n });\n this.source.weapons\n .filter((e) => e && e !== \"undefined\")\n .forEach((e) => {\n const name = Seasoning.getFoundryEquipmentName(e.name);\n const item = mergeObject({\n pbName: name,\n originalName:\n e.name,\n added: false,\n addedId: null,\n addedAutoId: null,\n }, e);\n this.parsed.weapons.push(item);\n });\n logger.debug(\"Finished Equipment Rename\");\n\n let i = 0;\n logger.debug(\"Starting Special Rename\");\n [].concat(this.source.specials, SPECIAL_NAME_ADDITIONS(this.source.specials))\n .filter((special) =>\n special\n && special !== \"undefined\"\n && special !== \"Not Selected\"\n && special !== this.source.heritage\n )\n .forEach((special) => {\n const name = this.getFoundryFeatureName(special).foundryName;\n if (!this.#processSpecialData(name) && !Seasoning.IGNORED_SPECIALS().includes(name)) {\n this.parsed.specials.push({ name, originalName: special, added: false, addedId: null, addedAutoId: null, rank: i });\n i++;\n }\n });\n logger.debug(\"Finished Special Rename\");\n\n let y = 0;\n logger.debug(\"Starting Feat Rename\");\n this.source.feats\n .filter((feat) =>\n feat[0]\n && feat[0] !== \"undefined\"\n && feat[0] !== \"Not Selected\"\n // && feat[0] !== this.source.heritage\n )\n .forEach((feat) => {\n const name = this.getFoundryFeatureName(feat[0]).foundryName;\n const data = {\n name,\n extra: feat[1],\n added: feat[0] === this.source.heritage,\n addedId: null,\n addedAutoId: null,\n type: feat[2],\n level: feat[3],\n originalName: feat[0],\n rank: y,\n };\n this.parsed.feats.push(data);\n y++;\n });\n logger.debug(\"Finished Feat Rename\");\n logger.debug(\"Name remapping results\", {\n parsed: this.parsed,\n });\n }\n\n #fixUps() {\n if (this.source.ancestry === \"Dwarf\" && !this.parsed.feats.some((f) => f.name === \"Clan Pistol\")) {\n const clanDagger = {\n name: \"Clan Dagger\",\n originalName: \"Clan Dagger\",\n added: false,\n addedId: null,\n addedAutoId: null,\n isChoice: true,\n rank: 0,\n };\n this.parsed.specials.push(clanDagger);\n }\n\n const match = this.source.background.match(/(Magical Experiment) \\((.*)\\)$/);\n if (match) {\n this.parsed.specials.push({\n name: match[2],\n originalName: `${this.source.background}`,\n added: false,\n addedId: null,\n addedAutoId: null,\n isChoice: true,\n rank: 0,\n });\n this.source.background = match[1];\n }\n }\n\n async #prepare() {\n await this.#loadCompendiumMatchers();\n this.#nameMap();\n this.#fixUps();\n }\n\n async #processSenses() {\n const senses = [];\n this.source.specials.forEach((special) => {\n if (special === \"Low-Light Vision\") {\n senses.push({ type: \"lowLightVision\" });\n } else if (special === \"Darkvision\") {\n senses.push({ type: \"darkvision\" });\n } else if (special === \"Scent\") {\n senses.push({ type: \"scent\" });\n }\n });\n setProperty(this.result.character, \"system.traits.senses\", senses);\n }\n\n async #addDualClass(klass) {\n if (!game.settings.get(\"pf2e\", \"dualClassVariant\")) {\n if (this.source.dualClass && this.source.dualClass !== \"\") {\n logger.warn(`Imported character is dual class but system is not configured for dual class`, {\n class: this.source.class,\n dualClass: this.source.dualClass,\n });\n ui.notifications.warn(`Imported character is dual class but system is not configured for dual class`);\n }\n return;\n }\n if (!this.source.dualClass || this.source.dualClass === \"\") {\n logger.warn(`Imported character not dual class but system is configured for dual class`, {\n class: this.source.class,\n });\n ui.notifications.warn(`Imported character not dual class but system is configured for dual class`);\n return;\n }\n\n // find the dual class\n const foundryName = this.getFoundryFeatureName(this.source.dualClass).foundryName;\n const indexMatch = this.compendiumMatchers[\"classes\"].getMatch(this.source.dualClass, foundryName);\n\n if (!indexMatch) return;\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n const dualClass = doc.toObject();\n\n logger.debug(`Dual Class ${dualClass.name} found, squashing things together.`);\n\n klass.name = `${klass.name} - ${dualClass.name}`;\n const ruleEntry = {\n domain: \"all\",\n key: \"RollOption\",\n option: `class:${dualClass.system.slug}`,\n };\n\n // Attacks\n [\"advanced\", \"martial\", \"simple\", \"unarmed\"].forEach((key) => {\n if (dualClass.system.attacks[key] > klass.system.attacks[key]) {\n klass.system.attacks[key] = dualClass.system.attacks[key];\n }\n });\n if (klass.system.attacks.martial <= dualClass.system.attacks.other.rank) {\n if (dualClass.system.attacks.other.rank === klass.system.attacks.other.rank) {\n let mashed = `${klass.system.attacks.other.name}, ${dualClass.system.attacks.other.name}`;\n mashed = mashed.replace(\"and \", \"\");\n klass.system.attacks.other.name = [...new Set(mashed.split(\",\"))].join(\",\");\n }\n if (dualClass.system.attacks.other.rank > klass.system.attacks.other.rank) {\n klass.system.attacks.other.name = dualClass.system.attacks.other.name;\n klass.system.attacks.other.rank = dualClass.system.attacks.other.rank;\n }\n }\n if (\n klass.system.attacks.martial >= dualClass.system.attacks.other.rank\n && klass.system.attacks.martial >= klass.system.attacks.other.rank\n ) {\n klass.system.attacks.other.rank = 0;\n klass.system.attacks.other.name = \"\";\n }\n\n // Class DC\n if (dualClass.system.classDC > klass.system.classDC) {\n klass.system.classDC = dualClass.system.classDC;\n }\n\n // Defenses\n [\"heavy\", \"light\", \"medium\", \"unarmored\"].forEach((key) => {\n if (dualClass.system.defenses[key] > klass.system.defenses[key]) {\n klass.system.defenses[key] = dualClass.system.defenses[key];\n }\n });\n\n // Description\n klass.system.description.value = `${klass.system.description.value} ${dualClass.system.description.value}`;\n\n // HP\n if (dualClass.system.hp > klass.system.hp) {\n klass.system.hp = dualClass.system.hp;\n }\n\n // Items\n Object.entries(dualClass.system.items).forEach((i) => {\n if (Object.values(klass.system.items).some((x) => x.uuid === i[1].uuid && x.level > i[1].level)) {\n Object.values(klass.system.items).find((x) => x.uuid === i[1].uuid).level = i[1].level;\n } else if (!Object.values(klass.system.items).some((x) => x.uuid === i[1].uuid && x.level <= i[1].level)) {\n klass.system.items[i[0]] = i[1];\n }\n });\n\n // Key Ability\n dualClass.system.keyAbility.value.forEach((v) => {\n if (!klass.system.keyAbility.value.includes(v)) {\n klass.system.keyAbility.value.push(v);\n }\n });\n\n // Perception\n if (dualClass.system.perception > klass.system.perception) klass.system.perception = dualClass.system.perception;\n\n // Rules\n klass.system.rules.push(ruleEntry);\n dualClass.system.rules.forEach((r) => {\n if (!klass.system.rules.includes(r)) {\n klass.system.rules.push(r);\n }\n });\n klass.system.rules.forEach((r, i) => {\n if (r.path !== undefined) {\n const check = r.path.split(\".\");\n if (\n check.includes(\"data\")\n && check.includes(\"martial\")\n && check.includes(\"rank\")\n && klass.system.attacks.martial >= r.value\n ) {\n klass.system.rules.splice(i, 1);\n }\n }\n });\n\n // Saving Throws\n [\"fortitude\", \"reflex\", \"will\"].forEach((key) => {\n if (dualClass.system.savingThrows[key] > klass.system.savingThrows[key]) {\n klass.system.savingThrows[key] = dualClass.system.savingThrows[key];\n }\n });\n\n // Skill Feat Levels\n dualClass.system.skillFeatLevels.value.forEach((v) => {\n klass.system.skillFeatLevels.value.push(v);\n });\n klass.system.skillFeatLevels.value = [...new Set(klass.system.skillFeatLevels.value)].sort((a, b) => {\n return a - b;\n });\n\n // Skill Increase Levels\n dualClass.system.skillIncreaseLevels.value.forEach((v) => {\n klass.system.skillIncreaseLevels.value.push(v);\n });\n klass.system.skillIncreaseLevels.value = [...new Set(klass.system.skillIncreaseLevels.value)].sort((a, b) => {\n return a - b;\n });\n\n // Trained Skills\n if (dualClass.system.trainedSkills.additional > klass.system.trainedSkills.additional) {\n klass.system.trainedSkills.additional = dualClass.system.trainedSkills.additional;\n }\n dualClass.system.trainedSkills.value.forEach((v) => {\n if (!klass.system.trainedSkills.value.includes(v)) {\n klass.system.trainedSkills.value.push(v);\n }\n });\n\n this.result.dualClass = dualClass;\n }\n\n // eslint-disable-next-line class-methods-use-this\n async #processGenericCompendiumLookup(type, name, target) {\n logger.debug(`Checking for compendium documents for ${name} (${target}) in compendiums for ${type}`);\n const foundryName = this.getFoundryFeatureName(name).foundryName;\n const indexMatch = this.compendiumMatchers[type].getMatch(name, foundryName);\n\n if (indexMatch) {\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n const itemData = doc.toObject();\n if (name.includes(\"(\")) {\n const extra = name.split(\")\")[0].split(\"(\").pop();\n this.parsed.specials.push({ name: doc.name, originalName: name, added: true, extra, rank: 99 });\n }\n if (target === \"class\") {\n itemData.system.keyAbility.selected = this.keyAbility;\n await this.#addDualClass(itemData);\n }\n itemData._id = foundry.utils.randomID();\n // this.#generateGrantItemData(itemData);\n this.result[target].push(itemData);\n await this.#addGrantedItems(itemData, { applyFeatLocation: target !== \"class\" });\n return true;\n } else {\n this.bad.push({ pbName: name, type: target, details: { name } });\n return false;\n }\n }\n\n // for grants, e.g. ont he champion \"Deity and Cause\" where there are choices.\n // how do we determine and match these? should we?\n // \"pf2e\": {\n // \"itemGrants\": {\n // \"adanye\": {\n // \"id\": \"4GHcp3iaREfj2ZgN\",\n // \"onDelete\": \"detach\"\n // },\n // \"paladin\": {\n // \"id\": \"HGWkTEatliHgDaEu\",\n // \"onDelete\": \"detach\"\n // }\n // }\n // }\n\n // \"Paladin\" (granted by deity and casue)\n // \"pf2e\": {\n // \"grantedBy\": {\n // \"id\": \"xnrkrJa2YE1UOAVy\",\n // \"onDelete\": \"cascade\"\n // },\n // \"itemGrants\": {\n // \"retributiveStrike\": {\n // \"id\": \"WVHbj9LljCTovdsv\",\n // \"onDelete\": \"detach\"\n // }\n // }\n // }\n\n // retributive strike\n // \"pf2e\": {\n // \"grantedBy\": {\n // \"id\": \"HGWkTEatliHgDaEu\",\n // \"onDelete\": \"cascade\"\n // }\n\n #parsedFeatureMatch(type, document, slug, { ignoreAdded, isChoiceMatch = false, featType = null } = {}) {\n // console.warn(`Trying to find ${slug} in ${type}, ignoreAdded? ${ignoreAdded}`, this.parsed[type]);\n const parsedMatch = this.parsed[type].find((f) =>\n (!ignoreAdded || (ignoreAdded && !f.added))\n && (\n featType === null\n || f.type === featType\n )\n && !f.isChoice\n && (slug === Seasoning.slug(f.name)\n || slug === Seasoning.slug(Seasoning.getClassAdjustedSpecialNameLowerCase(f.name, this.source.class))\n || slug === Seasoning.slug(Seasoning.getAncestryAdjustedSpecialNameLowerCase(f.name, this.source.ancestry))\n || slug === Seasoning.slug(Seasoning.getHeritageAdjustedSpecialNameLowerCase(f.name, this.source.heritage))\n || slug === Seasoning.slug(f.originalName)\n || slug === Seasoning.slug(Seasoning.getClassAdjustedSpecialNameLowerCase(f.originalName, this.source.class))\n || slug\n === Seasoning.slug(Seasoning.getAncestryAdjustedSpecialNameLowerCase(f.originalName, this.source.ancestry))\n || slug\n === Seasoning.slug(Seasoning.getHeritageAdjustedSpecialNameLowerCase(f.originalName, this.source.heritage))\n || (game.settings.get(\"pf2e\", \"dualClassVariant\")\n && (slug\n === Seasoning.slug(Seasoning.getDualClassAdjustedSpecialNameLowerCase(f.name, this.source.dualClass))\n || slug\n === Seasoning.slug(\n Seasoning.getDualClassAdjustedSpecialNameLowerCase(f.originalName, this.source.dualClass)\n ))))\n );\n if (parsedMatch || !document) return parsedMatch;\n\n const extraMatch = this.parsed[type].find((f) =>\n // (!ignoreAdded || (ignoreAdded && !f.added))\n f.extra\n && f.added\n && !f.isChoice\n && Seasoning.slug(f.name) === (document.system.slug ?? Seasoning.slug(document.name))\n && Seasoning.slug(f.extra) === slug\n );\n if (extraMatch) return extraMatch;\n\n if (isChoiceMatch) {\n // console.warn(\"Specials check\", {\n // document,\n // type,\n // slug,\n // });\n const choiceMatch = this.parsed[type].find((f) => f.isChoice && !f.added && Seasoning.slug(f.name) === slug);\n return choiceMatch;\n }\n return undefined;\n }\n\n #generatedResultMatch(type, slug) {\n const featMatch = this.result[type].find((f) => slug === f.system.slug);\n return featMatch;\n }\n\n #findAllFeatureMatch(document, slug, { ignoreAdded, isChoiceMatch = false, featType = null } = {}) {\n const featMatch = this.#parsedFeatureMatch(\"feats\", document, slug, { ignoreAdded, featType });\n if (featMatch) return featMatch;\n const specialMatch = this.#parsedFeatureMatch(\"specials\", document, slug, { ignoreAdded, isChoiceMatch });\n if (specialMatch) return specialMatch;\n const deityMatch = this.#generatedResultMatch(\"deity\", slug);\n return deityMatch;\n // const classMatch = this.#generatedResultMatch(\"class\", slug);\n // return classMatch;\n // const equipmentMatch = this.#generatedResultMatch(\"equipment\", slug);\n // return equipmentMatch;\n }\n\n #createGrantedItem(document, parent, { originType = null, applyFeatLocation = false } = {}) {\n logger.debug(`Adding granted item flags to ${document.name} (parent ${parent.name}) with originType \"${originType}\", and will applyFeatLocation? ${applyFeatLocation}`);\n const camelCase = Seasoning.slugD(document.system.slug ?? document.name);\n setProperty(parent, `flags.pf2e.itemGrants.${camelCase}`, { id: document._id, onDelete: \"detach\" });\n setProperty(document, \"flags.pf2e.grantedBy\", { id: parent._id, onDelete: \"cascade\" });\n this.autoFeats.push(document);\n this.result.feats.push(document);\n const matchOptions = { ignoreAdded: true, featType: originType };\n const featureMatch\n = this.#findAllFeatureMatch(document, document.system.slug ?? Seasoning.slug(document.name), matchOptions)\n ?? (document.name.includes(\"(\")\n ? this.#findAllFeatureMatch(document, Seasoning.slug(document.name.split(\"(\")[0].trim()), matchOptions)\n : undefined);\n\n if (featureMatch) {\n logger.debug(`Found feature match for ${document.name}`, { featureMatch });\n if (hasProperty(featureMatch, \"added\")) {\n featureMatch.added = true;\n featureMatch.addedId = document._id;\n if (applyFeatLocation) this.#generateFoundryFeatLocation(document, featureMatch);\n }\n\n return;\n }\n if (document.type !== \"action\")\n logger.warn(\n `Unable to find parsed feature match for granted feature ${document.name}. This might not be an issue, but might indicate feature duplication.`,\n { document, parent }\n );\n }\n\n\n static #getLowestChoiceRank(choices) {\n return choices.reduce((p, c) => {\n return p.rank > c.rank ? c : p;\n });\n }\n\n async #featureChoiceMatch(document, choices, ignoreAdded, adjustName, choiceHint = null) {\n const matches = [];\n for (const choice of choices) {\n const doc = adjustName ? game.i18n.localize(choice.label) : await fromUuid(choice.value);\n if (!doc) continue;\n const slug = adjustName\n ? Seasoning.slug(doc)\n : doc.system.slug === null\n ? Seasoning.slug(doc.name)\n : doc.system.slug;\n const featMatch = this.#findAllFeatureMatch(document, slug, { ignoreAdded, isChoiceMatch: false });\n if (featMatch) {\n matches.push({\n slug,\n rank: featMatch.rank,\n choice,\n });\n }\n }\n if (matches.length > 0) {\n if (choiceHint) {\n const hintMatch = matches.find((m) => m.slug === Seasoning.slug(choiceHint));\n if (hintMatch) return hintMatch;\n }\n const match = Pathmuncher.#getLowestChoiceRank(matches);\n const featMatch = this.#findAllFeatureMatch(document, match.slug, { ignoreAdded });\n if (adjustName && hasProperty(featMatch, \"added\")) {\n featMatch.added = true;\n featMatch.addedId = document._id;\n }\n logger.debug(\"Choices evaluated\", { choices, document, featMatch, match, matches });\n return match.choice;\n } else {\n return undefined;\n }\n }\n\n async #featureChoiceMatchNoUUID(document, choices, cleansedChoiceSet) {\n const matches = [];\n for (const choice of choices) {\n const featMatch = this.#findAllFeatureMatch(document, choice.value, { ignoreAdded: true, isChoiceMatch: true });\n if (featMatch) {\n matches.push({\n rank: featMatch.rank,\n choice,\n });\n }\n }\n if (matches.length > 0) {\n const match = Pathmuncher.#getLowestChoiceRank(matches);\n const featMatch = this.#findAllFeatureMatch(document, match.choice.value, { ignoreAdded: true, isChoiceMatch: true });\n if (featMatch) {\n featMatch.added = true;\n featMatch.addedId = document._id;\n match.choice.nouuid = true;\n }\n logger.debug(\"No UUID Choices evaluated\", { choices, cleansedChoiceSet, document, featMatch, match, matches });\n return match.choice;\n } else {\n return undefined;\n }\n }\n\n static getFlag(document, ruleSet) {\n return typeof ruleSet.flag === \"string\" && ruleSet.flag.length > 0\n ? ruleSet.flag.replace(/[^-a-z0-9]/gi, \"\")\n : Seasoning.slugD(document.system.slug ?? document.system.name);\n }\n\n async #evaluateChoices(document, choiceSet, choiceHint) {\n logger.debug(`Evaluating choices for ${document.name}`, { document, choiceSet, choiceHint });\n const tempActor = await this.#generateTempActor([document], false, false, true);\n const cleansedChoiceSet = deepClone(choiceSet);\n try {\n const item = tempActor.getEmbeddedDocument(\"Item\", document._id);\n const choiceSetRules = isNewerVersion(game.version, 11)\n ? new game.pf2e.RuleElements.all.ChoiceSet(cleansedChoiceSet, { parent: item })\n : new game.pf2e.RuleElements.all.ChoiceSet(cleansedChoiceSet, item);\n const rollOptions = [tempActor.getRollOptions(), item.getRollOptions(\"item\")].flat();\n const choices = isNewerVersion(game.version, 11)\n ? await choiceSetRules.inflateChoices(rollOptions, [])\n : (await choiceSetRules.inflateChoices()).filter((c) => c.predicate?.test(rollOptions) ?? true);\n\n logger.debug(\"Starting choice evaluation\", {\n document,\n choiceSet,\n item,\n choiceSetRules,\n rollOptions,\n choices,\n });\n\n if (cleansedChoiceSet.choices?.query) {\n const nonFilteredChoices = isNewerVersion(game.version, 11)\n ? await choiceSetRules.inflateChoices(rollOptions, [item])\n : await choiceSetRules.inflateChoices();\n const queryResults = await choiceSetRules.queryCompendium(cleansedChoiceSet.choices, rollOptions, [item]);\n logger.debug(\"Query Result\", { queryResults, nonFilteredChoices });\n }\n\n logger.debug(\"Evaluating choiceset\", cleansedChoiceSet);\n const choiceMatch = await this.#featureChoiceMatch(document, choices, true, cleansedChoiceSet.adjustName, choiceHint);\n logger.debug(\"choiceMatch result\", choiceMatch);\n if (choiceMatch) {\n choiceMatch.choiceQueryResults = deepClone(choices);\n return choiceMatch;\n }\n\n if (typeof cleansedChoiceSet.choices === \"string\" || Array.isArray(choices)) {\n const featureMatch = await this.#featureChoiceMatchNoUUID(document, choices, cleansedChoiceSet);\n if (featureMatch) {\n return featureMatch;\n }\n }\n\n let tempSet = deepClone(choiceSet);\n logger.debug(`Starting dynamic selection for ${document.name}`, { document, choiceSet, tempSet, Pathmuncher: this });\n await choiceSetRules.preCreate({ itemSource: item, ruleSource: tempSet, pendingItems: [item] });\n // console.warn(\"chociesetdata\", {\n // choiceSetRules,\n // selection: choiceSetRules.selection,\n // choiceSet: deepClone(choiceSet),\n // tempSet: deepClone(tempSet),\n // });\n if (tempSet.selection) {\n const lookedUpChoice = choices.find((c) => c.value === tempSet.selection);\n logger.debug(\"lookedUpChoice\", lookedUpChoice);\n if (lookedUpChoice) lookedUpChoice.choiceQueryResults = deepClone(choices);\n // set some common lookups here, e.g. deities are often not set!\n if (lookedUpChoice && cleansedChoiceSet.flag === \"deity\") {\n if (lookedUpChoice.label && lookedUpChoice.label !== \"\") {\n setProperty(this.result.character, \"system.details.deity.value\", lookedUpChoice.label);\n await this.#processGenericCompendiumLookup(\"deities\", lookedUpChoice.label, \"deity\");\n const camelCase = Seasoning.slugD(this.result.deity[0].system.slug);\n setProperty(document, `flags.pf2e.itemGrants.${camelCase}`, {\n id: this.result.deity[0]._id,\n onDelete: \"detach\",\n });\n setProperty(this.result.deity[0], \"flags.pf2e.grantedBy\", { id: document._id, onDelete: \"cascade\" });\n this.autoAddedFeatureIds.add(`${lookedUpChoice.value.split(\".\").pop()}deity`);\n }\n }\n return lookedUpChoice;\n }\n } catch (err) {\n logger.error(\"Whoa! Something went major bad wrong during choice evaluation\", {\n err,\n tempActor: tempActor.toObject(),\n document: duplicate(document),\n choiceSet: duplicate(cleansedChoiceSet),\n });\n throw err;\n } finally {\n await Actor.deleteDocuments([tempActor._id]);\n }\n\n logger.debug(\"Evaluate Choices failed\", { choiceSet: cleansedChoiceSet, tempActor, document });\n return undefined;\n }\n\n async #resolveInjectedUuid(document, ruleEntry) {\n const tempActor = await this.#generateTempActor([document], false, false);\n const cleansedRuleEntry = deepClone(ruleEntry);\n try {\n const item = tempActor.getEmbeddedDocument(\"Item\", document._id);\n // console.warn(\"creating grant item\");\n const grantItemRule = isNewerVersion(game.version, 11)\n ? new game.pf2e.RuleElements.all.GrantItem(cleansedRuleEntry, { parent: item })\n : new game.pf2e.RuleElements.all.GrantItem(cleansedRuleEntry, item);\n // console.warn(\"Begining uuid resovle\");\n const uuid = grantItemRule.resolveInjectedProperties(grantItemRule.uuid, { warn: false });\n\n logger.debug(\"uuid selection\", {\n document,\n choiceSet: ruleEntry,\n item,\n grantItemRule,\n uuid,\n });\n if (uuid) return uuid;\n } catch (err) {\n logger.error(\"Whoa! Something went major bad wrong during uuid evaluation\", {\n err,\n tempActor: tempActor.toObject(),\n document: duplicate(document),\n ruleEntry: duplicate(cleansedRuleEntry),\n });\n throw err;\n } finally {\n await Actor.deleteDocuments([tempActor._id]);\n }\n\n logger.debug(\"Evaluate UUID failed\", { choiceSet: cleansedRuleEntry, tempActor, document });\n return undefined;\n }\n\n async #checkRule(document, rule) {\n const tempActor = await this.#generateTempActor([document], true);\n const cleansedRule = deepClone(rule);\n try {\n const item = tempActor.getEmbeddedDocument(\"Item\", document._id);\n const ruleElement = cleansedRule.key === \"ChoiceSet\"\n ? isNewerVersion(game.version, 11)\n ? new game.pf2e.RuleElements.all.ChoiceSet(cleansedRule, { parent: item })\n : new game.pf2e.RuleElements.all.ChoiceSet(cleansedRule, item)\n : isNewerVersion(game.version, 11)\n ? new game.pf2e.RuleElements.all.GrantItem(cleansedRule, { parent: item })\n : new game.pf2e.RuleElements.all.GrantItem(cleansedRule, item);\n const rollOptions = [tempActor.getRollOptions(), item.getRollOptions(\"item\")].flat();\n\n if (rule.predicate) {\n const predicate = ruleElement.resolveInjectedProperties(ruleElement.predicate);\n if (!predicate.test(rollOptions)) return false;\n }\n\n const choices = cleansedRule.key === \"ChoiceSet\"\n ? isNewerVersion(game.version, 11)\n ? await ruleElement.inflateChoices(rollOptions, [item])\n : (await ruleElement.inflateChoices()).filter((c) => !c.predicate || c.predicate.test(rollOptions))\n : [ruleElement.resolveValue()];\n\n const isGood = cleansedRule.key === \"ChoiceSet\"\n ? (await this.#featureChoiceMatch(document, choices, false)) !== undefined\n : ruleElement.test(rollOptions);\n\n logger.debug(\"Checking rule\", {\n tempActor,\n cleansedRule,\n item,\n ruleElement,\n rollOptions,\n choices,\n isGood,\n });\n return isGood;\n } catch (err) {\n logger.error(\"Something has gone most wrong during rule checking\", {\n document,\n rule: cleansedRule,\n tempActor,\n });\n throw err;\n } finally {\n await Actor.deleteDocuments([tempActor._id]);\n }\n }\n\n async #checkRulePredicate(document, rule) {\n const tempActor = await this.#generateTempActor([document], true);\n const cleansedRule = deepClone(rule);\n try {\n const item = tempActor.getEmbeddedDocument(\"Item\", document._id);\n const ruleElement = cleansedRule.key === \"ChoiceSet\"\n ? isNewerVersion(game.version, 11)\n ? new game.pf2e.RuleElements.all.ChoiceSet(cleansedRule, { parent: item })\n : new game.pf2e.RuleElements.all.ChoiceSet(cleansedRule, item)\n : isNewerVersion(game.version, 11)\n ? new game.pf2e.RuleElements.all.GrantItem(cleansedRule, { parent: item })\n : new game.pf2e.RuleElements.all.GrantItem(cleansedRule, item);\n const rollOptions = [tempActor.getRollOptions(), item.getRollOptions(\"item\")].flat();\n\n if (rule.predicate) {\n const predicate = ruleElement.resolveInjectedProperties(ruleElement.predicate);\n return predicate.test(rollOptions);\n } else {\n return true;\n }\n } catch (err) {\n logger.error(\"Something has gone most wrong during rule predicate checking\", {\n document,\n rule: cleansedRule,\n tempActor,\n });\n throw err;\n } finally {\n await Actor.deleteDocuments([tempActor._id]);\n }\n }\n\n static adjustDocumentName(featureName, label) {\n const localLabel = game.i18n.localize(label);\n if (featureName.trim().toLowerCase() === localLabel.trim().toLowerCase()) return featureName;\n const name = `${featureName} (${localLabel})`;\n const pattern = (() => {\n const escaped = RegExp.escape(localLabel);\n return new RegExp(`\\\\(${escaped}\\\\) \\\\(${escaped}\\\\)$`);\n })();\n return name.replace(pattern, `(${localLabel})`);\n }\n\n // eslint-disable-next-line complexity, no-unused-vars\n async #addGrantedRules(document, originType = null, choiceHint = null) {\n if (document.system.rules.length === 0) return;\n logger.debug(`addGrantedRules for ${document.name}`, duplicate(document));\n\n if (\n hasProperty(document, \"system.level.value\")\n && document.system.level.value > this.result.character.system.details.level.value\n ) {\n return;\n }\n\n const rulesToKeep = [];\n this.allFeatureRules[document._id] = deepClone(document.system.rules);\n this.autoAddedFeatureRules[document._id] = [];\n this.promptRules[document._id] = [];\n let featureRenamed = false;\n\n for (const ruleEntry of document.system.rules) {\n logger.debug(`Ping ${document.name} rule key: ${ruleEntry.key}`, ruleEntry);\n if (![\"ChoiceSet\", \"GrantItem\"].includes(ruleEntry.key)) {\n // size work around due to Pathbuilder not always adding the right size to json\n if (ruleEntry.key === \"CreatureSize\") this.size = ruleEntry.value;\n this.autoAddedFeatureRules[document._id].push(ruleEntry);\n rulesToKeep.push(ruleEntry);\n continue;\n }\n logger.debug(`Checking ${document.name} rule key: ${ruleEntry.key}`, {\n ruleEntry,\n docRules: deepClone(document.system.rules),\n document: deepClone(document),\n });\n\n if (ruleEntry.key === \"ChoiceSet\" && ruleEntry.predicate) {\n logger.debug(`Checking for predicates`, {\n ruleEntry,\n document,\n });\n const testResult = await this.#checkRulePredicate(duplicate(document), ruleEntry);\n if (!testResult) {\n const data = { document, ruleEntry, testResult };\n logger.debug(\n `The test failed for ${document.name} rule key: ${ruleEntry.key} (This is probably not a problem).`,\n data\n );\n rulesToKeep.push(ruleEntry);\n continue;\n }\n }\n\n const choice = ruleEntry.key === \"ChoiceSet\" ? await this.#evaluateChoices(document, ruleEntry, choiceHint) : undefined;\n const uuid = ruleEntry.key === \"GrantItem\" ? await this.#resolveInjectedUuid(document, ruleEntry) : choice?.value;\n\n if (choice?.choiceQueryResults) {\n ruleEntry.choiceQueryResults = choice.choiceQueryResults;\n }\n\n const flagName = Pathmuncher.getFlag(document, ruleEntry);\n if (flagName && choice?.value && !hasProperty(document, `flags.pf2e.rulesSelections.${flagName}`)) {\n setProperty(document, `flags.pf2e.rulesSelections.${flagName}`, choice.value);\n }\n\n logger.debug(`UUID for ${document.name}: \"${uuid}\"`, { document, ruleEntry, choice, uuid });\n const ruleFeature = uuid && typeof uuid === \"string\" ? await fromUuid(uuid) : undefined;\n // console.warn(\"ruleFeature\", ruleFeature);\n if (ruleFeature) {\n const featureDoc = ruleFeature.toObject();\n featureDoc._id = foundry.utils.randomID();\n if (featureDoc.system.rules) this.allFeatureRules[featureDoc._id] = deepClone(featureDoc.system.rules);\n setProperty(featureDoc, \"flags.pathmuncher.origin.uuid\", uuid);\n logger.debug(`Found rule feature ${featureDoc.name} for ${document.name} for`, ruleEntry);\n\n if (choice) ruleEntry.selection = choice.value;\n\n if (ruleEntry.predicate && ruleEntry.key === \"GrantItem\") {\n logger.debug(`Checking for grantitem predicates`, {\n ruleEntry,\n document,\n featureDoc,\n });\n const testResult = await this.#checkRule(featureDoc, ruleEntry);\n if (!testResult) {\n const data = { document, ruleEntry, featureDoc, testResult };\n logger.debug(\n `The test failed for ${document.name} rule key: ${ruleEntry.key} (This is probably not a problem).`,\n data\n );\n rulesToKeep.push(ruleEntry);\n // this.autoAddedFeatureRules[document._id].push(ruleEntry);\n continue;\n } else {\n logger.debug(`The test passed for ${document.name} rule key: ${ruleEntry.key}`, ruleEntry);\n // this.autoAddedFeatureRules[document._id].push(ruleEntry);\n // eslint-disable-next-line max-depth\n // if (!ruleEntry.flag) ruleEntry.flag = Seasoning.slugD(document.name);\n ruleEntry.pathmuncherImport = true;\n rulesToKeep.push(ruleEntry);\n }\n }\n\n // setProperty(ruleEntry, `preselectChoices.${ruleEntry.flag}`, ruleEntry.selection ?? ruleEntry.uuid);\n\n if (this.autoAddedFeatureIds.has(`${ruleFeature.id}${ruleFeature.type}`)) {\n logger.debug(`Feature ${featureDoc.name} found for ${document.name}, but has already been added (${ruleFeature.id})`, ruleFeature);\n // this.autoAddedFeatureRules[document._id].push(ruleEntry);\n // rulesToKeep.push(ruleEntry);\n continue;\n } else {\n logger.debug(`Feature ${featureDoc.name} not found for ${document.name}, adding (${ruleFeature.id})`, ruleFeature);\n if (ruleEntry.selection || ruleEntry.flag) {\n rulesToKeep.push(ruleEntry);\n }\n this.autoAddedFeatureIds.add(`${ruleFeature.id}${ruleFeature.type}`);\n featureDoc._id = foundry.utils.randomID();\n this.#createGrantedItem(featureDoc, document, { applyFeatLocation: false });\n if (hasProperty(featureDoc, \"system.rules\")) await this.#addGrantedRules(featureDoc);\n }\n } else if (getProperty(choice, \"nouuid\")) {\n logger.debug(\"Parsed no id rule\", { choice, uuid, ruleEntry });\n if (!ruleEntry.flag) ruleEntry.flag = Seasoning.slugD(document.name);\n ruleEntry.selection = choice.value;\n if (choice.label) document.name = `${document.name} (${choice.label})`;\n rulesToKeep.push(ruleEntry);\n } else if (choice && uuid && !hasProperty(ruleEntry, \"selection\")) {\n logger.debug(\"Parsed odd choice rule\", { choice, uuid, ruleEntry });\n // if (!ruleEntry.flag) ruleEntry.flag = Seasoning.slugD(document.name);\n ruleEntry.selection = choice.value;\n if (\n ((!ruleEntry.adjustName && choice.label && typeof uuid === \"object\")\n || (!choice.adjustName && choice.label))\n && !featureRenamed\n ) {\n document.name = Pathmuncher.adjustDocumentName(document.name, choice.label);\n featureRenamed = true;\n }\n rulesToKeep.push(ruleEntry);\n } else {\n logger.debug(`Final rule fallback for ${document.name}`, ruleEntry);\n const data = {\n uuid: ruleEntry.uuid,\n document,\n ruleEntry,\n choice,\n };\n if (\n ruleEntry.key === \"GrantItem\"\n && (ruleEntry.flag || ruleEntry.selection || ruleEntry.uuid.startsWith(\"Compendium\"))\n ) {\n rulesToKeep.push(ruleEntry);\n } else if (ruleEntry.key === \"ChoiceSet\" && !hasProperty(ruleEntry, \"flag\")) {\n logger.debug(\"Prompting user for choices\", ruleEntry);\n this.promptRules[document._id].push(ruleEntry);\n rulesToKeep.push(ruleEntry);\n } else if (ruleEntry.key === \"ChoiceSet\" && !choice && !uuid) {\n logger.warn(\"Unable to determine choice asking\", data);\n rulesToKeep.push(ruleEntry);\n this.promptRules[document._id].push(ruleEntry);\n }\n logger.warn(\"Unable to determine granted rule feature, needs better parser\", data);\n }\n if (ruleEntry.adjustName && choice?.label && !featureRenamed) {\n document.name = Pathmuncher.adjustDocumentName(document.name, choice.label);\n }\n this.autoAddedFeatureRules[document._id].push(ruleEntry);\n\n logger.debug(`End result for ${document.name} for a ${ruleEntry.key}`, {\n document: deepClone(document),\n rulesToKeep: deepClone(rulesToKeep),\n ruleEntry: deepClone(ruleEntry),\n choice: deepClone(choice),\n uuid: deepClone(uuid),\n });\n }\n // eslint-disable-next-line require-atomic-updates\n document.system.rules = rulesToKeep;\n\n logger.debug(`Final status for ${document.name}`, {\n document: deepClone(document),\n rulesToKeep: deepClone(rulesToKeep),\n });\n }\n\n async #addGrantedItems(document, { originType = null, applyFeatLocation = false, choiceHint = null } = {}) {\n const immediateDiveAdd = utils.setting(\"USE_IMMEDIATE_DEEP_DIVE\");\n const subRuleDocuments = [];\n if (hasProperty(document, \"system.items\")) {\n logger.debug(`addGrantedItems for ${document.name}`, duplicate(document));\n if (!this.autoAddedFeatureItems[document._id]) {\n this.autoAddedFeatureItems[document._id] = duplicate(document.system.items);\n }\n const failedFeatureItems = {};\n for (const [key, grantedItemFeature] of Object.entries(document.system.items).sort(([, a], [, b]) => a.level - b.level)) {\n logger.debug(`Checking ${document.name} granted item ${grantedItemFeature.name}, level(${grantedItemFeature.level}) with key: ${key}`, grantedItemFeature);\n if (grantedItemFeature.level > getProperty(this.result.character, \"system.details.level.value\")) continue;\n const feature = await fromUuid(grantedItemFeature.uuid);\n if (!feature) {\n const data = { uuid: grantedItemFeature.uuid, grantedFeature: grantedItemFeature, feature };\n logger.warn(\"Unable to determine granted item feature, needs better parser\", data);\n failedFeatureItems[key] = grantedItemFeature;\n continue;\n }\n this.autoAddedFeatureIds.add(`${feature.id}${feature.type}`);\n const featureDoc = feature.toObject();\n featureDoc._id = foundry.utils.randomID();\n setProperty(featureDoc.system, \"location\", document._id);\n this.#createGrantedItem(featureDoc, document, { originType, applyFeatLocation });\n if (hasProperty(featureDoc, \"system.rules\")) {\n logger.debug(`Processing granted rules for granted item document ${featureDoc.name}`, duplicate(featureDoc));\n if (immediateDiveAdd) {\n await this.#addGrantedItems(featureDoc, { originType, applyFeatLocation });\n } else {\n subRuleDocuments.push(featureDoc);\n }\n }\n }\n // eslint-disable-next-line require-atomic-updates\n document.system.items = failedFeatureItems;\n\n if (!immediateDiveAdd) {\n for (const subRuleDocument of subRuleDocuments) {\n logger.debug(\n `Processing granted rules for granted item document ${subRuleDocument.name}`,\n duplicate(subRuleDocument)\n );\n await this.#addGrantedItems(subRuleDocument, { originType, applyFeatLocation, choiceHint });\n }\n }\n }\n\n if (hasProperty(document, \"system.rules\")) {\n logger.debug(`Processing granted rules for core document ${document.name}`, duplicate(document));\n await this.#addGrantedRules(document, originType, choiceHint);\n }\n }\n\n #determineAbilityBoosts() {\n const boostLocation = foundry.utils.isNewerVersion(game.system.version, \"5.3.0\")\n ? \"attributes\"\n : \"abilities\";\n const breakdown = getProperty(this.source, \"abilities.breakdown\");\n const useCustomStats\n = breakdown\n && breakdown.ancestryFree.length === 0\n && breakdown.ancestryBoosts.length === 0\n && breakdown.ancestryFlaws.length === 0\n && breakdown.backgroundBoosts.length === 0\n && breakdown.classBoosts.length === 0;\n if (breakdown && !useCustomStats) {\n this.boosts.custom = false;\n const classBoostMap = {};\n for (const [key, boosts] of Object.entries(this.source.abilities.breakdown.mapLevelledBoosts)) {\n if (key <= this.source.level) {\n classBoostMap[key] = boosts.map((ability) => ability.toLowerCase());\n }\n }\n setProperty(this.result.character, `system.build.${boostLocation}.boosts`, classBoostMap);\n this.boosts.class = classBoostMap;\n\n // ancestry\n } else {\n this.boosts.custom = true;\n if (foundry.utils.isNewerVersion(\"5.3.0\", game.system.version)) {\n [\"str\", \"dex\", \"con\", \"int\", \"wis\", \"cha\"].forEach((key) => {\n setProperty(this.result.character, `system.abilities.${key}.value`, this.source.abilities[key]);\n });\n } else {\n [\"str\", \"dex\", \"con\", \"int\", \"wis\", \"cha\"].forEach((key) => {\n const mod = Math.min(Math.max(Math.trunc((this.source.abilities[key] - 10) / 2), -5), 10) || 0;\n setProperty(this.result.character, `system.abilities.${key}.mod`, mod);\n });\n }\n\n }\n\n if (breakdown?.classBoosts.length > 0) {\n this.keyAbility = breakdown.classBoosts[0].toLowerCase();\n } else {\n this.keyAbility = this.source.keyability;\n }\n setProperty(this.result.character, \"system.details.keyability.value\", this.keyAbility);\n }\n\n #generateBackgroundAbilityBoosts() {\n if (!this.result.background[0]) return;\n const breakdown = getProperty(this.source, \"abilities.breakdown\");\n for (const boost of breakdown.backgroundBoosts) {\n for (const [key, boostSet] of Object.entries(this.result.background[0].system.boosts)) {\n if (this.result.background[0].system.boosts[key].selected) continue;\n if (boostSet.value.includes(boost.toLowerCase())) {\n this.result.background[0].system.boosts[key].selected = boost.toLowerCase();\n break;\n }\n }\n }\n }\n\n #generateAncestryAbilityBoosts() {\n if (!this.result.ancestry[0]) return;\n const breakdown = getProperty(this.source, \"abilities.breakdown\");\n const boosts = [];\n breakdown.ancestryBoosts.concat(breakdown.ancestryFree).forEach((boost) => {\n for (const [key, boostSet] of Object.entries(this.result.ancestry[0].system.boosts)) {\n if (this.result.ancestry[0].system.boosts[key].selected) continue;\n if (boostSet.value.includes(boost.toLowerCase())) {\n this.result.ancestry[0].system.boosts[key].selected = boost.toLowerCase();\n boosts.push(boost.toLowerCase());\n break;\n }\n }\n });\n if (breakdown.ancestryBoosts.length === 0) {\n setProperty(this.result.ancestry[0], \"system.alternateAncestryBoosts\", boosts);\n }\n }\n\n #setAbilityBoosts() {\n if (this.boosts.custom) return;\n this.#generateBackgroundAbilityBoosts();\n this.#generateAncestryAbilityBoosts();\n\n this.result.class[0].system.boosts = this.boosts.class;\n }\n\n #setSkills() {\n setProperty(this.result.character, \"system.skills.acr.rank\", this.source.proficiencies.acrobatics / 2);\n setProperty(this.result.character, \"system.skills.arc.rank\", this.source.proficiencies.arcana / 2);\n setProperty(this.result.character, \"system.skills.ath.rank\", this.source.proficiencies.athletics / 2);\n setProperty(this.result.character, \"system.skills.cra.rank\", this.source.proficiencies.crafting / 2);\n setProperty(this.result.character, \"system.skills.dec.rank\", this.source.proficiencies.deception / 2);\n setProperty(this.result.character, \"system.skills.dip.rank\", this.source.proficiencies.diplomacy / 2);\n setProperty(this.result.character, \"system.skills.itm.rank\", this.source.proficiencies.intimidation / 2);\n setProperty(this.result.character, \"system.skills.med.rank\", this.source.proficiencies.medicine / 2);\n setProperty(this.result.character, \"system.skills.nat.rank\", this.source.proficiencies.nature / 2);\n setProperty(this.result.character, \"system.skills.occ.rank\", this.source.proficiencies.occultism / 2);\n setProperty(this.result.character, \"system.skills.prf.rank\", this.source.proficiencies.performance / 2);\n setProperty(this.result.character, \"system.skills.rel.rank\", this.source.proficiencies.religion / 2);\n setProperty(this.result.character, \"system.skills.soc.rank\", this.source.proficiencies.society / 2);\n setProperty(this.result.character, \"system.skills.ste.rank\", this.source.proficiencies.stealth / 2);\n setProperty(this.result.character, \"system.skills.sur.rank\", this.source.proficiencies.survival / 2);\n setProperty(this.result.character, \"system.skills.thi.rank\", this.source.proficiencies.thievery / 2);\n }\n\n #setSaves() {\n setProperty(this.result.character, \"system.saves.fortitude.tank\", this.source.proficiencies.fortitude / 2);\n setProperty(this.result.character, \"system.saves.reflex.value\", this.source.proficiencies.reflex / 2);\n setProperty(this.result.character, \"system.saves.will.value\", this.source.proficiencies.will / 2);\n }\n\n #setMartials() {\n setProperty(this.result.character, \"system.martial.advanced.rank\", this.source.proficiencies.advanced / 2);\n setProperty(this.result.character, \"system.martial.heavy.rank\", this.source.proficiencies.heavy / 2);\n setProperty(this.result.character, \"system.martial.light.rank\", this.source.proficiencies.light / 2);\n setProperty(this.result.character, \"system.martial.medium.rank\", this.source.proficiencies.medium / 2);\n setProperty(this.result.character, \"system.martial.unarmored.rank\", this.source.proficiencies.unarmored / 2);\n setProperty(this.result.character, \"system.martial.martial.rank\", this.source.proficiencies.martial / 2);\n setProperty(this.result.character, \"system.martial.simple.rank\", this.source.proficiencies.simple / 2);\n setProperty(this.result.character, \"system.martial.unarmed.rank\", this.source.proficiencies.unarmed / 2);\n\n }\n\n async #processCore() {\n setProperty(this.result.character, \"name\", this.source.name);\n setProperty(this.result.character, \"prototypeToken.name\", this.source.name);\n setProperty(this.result.character, \"system.details.level.value\", this.source.level);\n if (this.source.age !== \"Not set\") setProperty(this.result.character, \"system.details.age.value\", this.source.age);\n if (this.source.gender !== \"Not set\") setProperty(this.result.character, \"system.details.gender.value\", this.source.gender);\n setProperty(this.result.character, \"system.details.alignment.value\", this.source.alignment);\n\n if (this.source.deity !== \"Not set\") setProperty(this.result.character, \"system.details.deity.value\", this.source.deity);\n this.size = Seasoning.getSizeValue(this.source.size);\n setProperty(this.result.character, \"system.traits.size.value\", this.size);\n setProperty(this.result.character, \"system.traits.languages.value\", this.source.languages.map((l) => l.toLowerCase()));\n\n this.#processSenses();\n\n this.#determineAbilityBoosts();\n this.#setSaves();\n this.#setMartials();\n\n setProperty(this.result.character, \"system.attributes.perception.rank\", this.source.proficiencies.perception / 2);\n setProperty(this.result.character, \"system.attributes.classDC.rank\", this.source.proficiencies.classDC / 2);\n }\n\n #indexFind(index, arrayOfNameMatches) {\n for (const name of arrayOfNameMatches) {\n const indexMatch = index.find((i) => {\n const slug = i.system.slug ?? Seasoning.slug(i.name);\n return (\n slug === Seasoning.slug(name)\n || slug === Seasoning.slug(Seasoning.getClassAdjustedSpecialNameLowerCase(name, this.source.class))\n || slug === Seasoning.slug(Seasoning.getAncestryAdjustedSpecialNameLowerCase(name, this.source.ancestry))\n || slug === Seasoning.slug(Seasoning.getHeritageAdjustedSpecialNameLowerCase(name, this.source.heritage))\n || (game.settings.get(\"pf2e\", \"dualClassVariant\")\n && slug === Seasoning.slug(Seasoning.getDualClassAdjustedSpecialNameLowerCase(name, this.source.dualClass)))\n );\n });\n if (indexMatch) return indexMatch;\n }\n return undefined;\n }\n\n #findInPackIndexes(type, arrayOfNameMatches) {\n const matcher = this.compendiumMatchers[type];\n for (const [packName, index] of Object.entries(matcher.indexes)) {\n const indexMatch = this.#indexFind(index, arrayOfNameMatches);\n if (indexMatch) return { i: indexMatch, pack: matcher.packs[packName] };\n }\n return undefined;\n }\n\n #sortParsedFeats() {\n // eslint-disable-next-line complexity\n this.parsed.feats.sort((f1, f2) => {\n const f1RefUndefined = !(typeof f1.type === \"string\" || f1.type instanceof String);\n const f2RefUndefined = !(typeof f2.type === \"string\" || f2.type instanceof String);\n if (f1RefUndefined || f2RefUndefined) {\n if (f1RefUndefined && f2RefUndefined) {\n return 0;\n } else if (f1RefUndefined) {\n return 1;\n } else {\n return -1;\n }\n } else if (f1.type === \"Awarded Feat\" && f2.type === \"Awarded Feat\") {\n return (f1.level ?? 20) - (f2.level ?? 20);\n } else if (f1.type === \"Awarded Feat\") {\n return 1;\n } else if (f2.type === \"Awarded Feat\") {\n return -1;\n } else if ((f1.level ?? 20) === (f2.level ?? 20)) {\n const f1Index = CONSTANTS.FEAT_PRIORITY.indexOf(f1.type);\n const f2Index = CONSTANTS.FEAT_PRIORITY.indexOf(f2.type);\n if (f1Index > f2Index) {\n return 1;\n } else if (f1Index < f2Index) {\n return -1;\n } else {\n return 0;\n }\n } else {\n return (f1.level ?? 20) - (f2.level ?? 20);\n }\n });\n }\n\n async #generateFeatItems(type, { levelCap = null, parsedFilter = null } = {}) {\n logger.debug(`Generate feat items for ${type} with level cap \"${levelCap}\" and filter \"${parsedFilter}\"`);\n\n for (const featArray of [this.parsed.feats, this.parsed.specials]) {\n for (const pBFeat of featArray) {\n if (pBFeat.added) continue;\n if (levelCap && (pBFeat.level ?? 20) > levelCap) continue;\n if (parsedFilter && pBFeat.type !== parsedFilter) continue;\n logger.debug(\"Generating feature for\", pBFeat);\n\n const indexMatch = this.#findInPackIndexes(type, [pBFeat.name, pBFeat.originalName]);\n const displayName = pBFeat.extra ? Pathmuncher.adjustDocumentName(pBFeat.name, pBFeat.extra) : pBFeat.name;\n if (!indexMatch) {\n logger.debug(`Unable to match feat ${displayName}`, {\n displayName,\n name: pBFeat.name,\n extra: pBFeat.extra,\n pBFeat,\n type,\n });\n this.check[pBFeat.originalName] = {\n name: displayName,\n type: \"feat\",\n details: {\n displayName,\n name: pBFeat.name,\n originalName: pBFeat.originalName,\n extra: pBFeat.extra,\n pBFeat,\n type,\n },\n };\n continue;\n }\n if (this.check[pBFeat.originalName]) delete this.check[pBFeat.originalName];\n pBFeat.added = true;\n if (this.autoAddedFeatureIds.has(`${indexMatch._id}${indexMatch.type}`)) {\n logger.debug(\"Feat included in class features auto add\", { displayName, pBFeat, type });\n pBFeat.addedAutoId = `${indexMatch._id}_${indexMatch.type}`;\n continue;\n }\n\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n const docData = doc.toObject();\n docData._id = foundry.utils.randomID();\n pBFeat.addedId = docData._id;\n // docData.name = displayName;\n\n this.#generateFoundryFeatLocation(docData, pBFeat);\n this.result.feats.push(docData);\n const options = {\n originType: parsedFilter,\n applyFeatLocation: false,\n choiceHint: pBFeat.extra && pBFeat.extra !== \"\" ? pBFeat.extra : null,\n };\n await this.#addGrantedItems(docData, \"feat\", options);\n }\n }\n }\n\n async #generateSpecialItems(type) {\n for (const special of this.parsed.specials) {\n if (special.added) continue;\n logger.debug(\"Generating special for\", special);\n const indexMatch = this.#findInPackIndexes(type, [special.name, special.originalName]);\n if (!indexMatch) {\n logger.debug(`Unable to match special ${special.name}`, { special: special.name, type });\n this.check[special.originalName] = {\n name: special.name,\n type: \"special\",\n details: { displayName: special.name, name: special.name, originalName: special.originalName, special },\n };\n continue;\n }\n special.added = true;\n if (this.check[special.originalName]) delete this.check[special.originalName];\n if (this.autoAddedFeatureIds.has(`${indexMatch._id}${indexMatch.type}`)) {\n logger.debug(\"Special included in class features auto add\", { special: special.name, type });\n special.addedAutoId = `${indexMatch._id}_${indexMatch.type}`;\n continue;\n }\n\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n const docData = doc.toObject();\n docData._id = foundry.utils.randomID();\n special.addedId = docData._id;\n this.result.feats.push(docData);\n await this.#addGrantedItems(docData, { applyFeatLocation: true });\n }\n }\n\n #resizeItem(item) {\n if (Seasoning.isPhysicalItemType(item.type)) {\n const resizeItem = item.type !== \"treasure\" && ![\"med\", \"sm\"].includes(this.size);\n if (resizeItem) item.system.size = this.size;\n }\n }\n\n async #generateAdventurersPack() {\n const defaultCompendium = game.packs.get(\"pf2e.equipment-srd\");\n const index = await defaultCompendium.getIndex({ fields: [\"name\", \"type\", \"system.slug\"] });\n\n\n const adventurersPack = this.parsed.equipment.find((e) => e.pbName === \"Adventurer's Pack\");\n if (adventurersPack) {\n const compendiumBackpack = await defaultCompendium.getDocument(\"3lgwjrFEsQVKzhh7\");\n const backpackInstance = compendiumBackpack.toObject();\n adventurersPack.added = true;\n backpackInstance._id = foundry.utils.randomID();\n adventurersPack.addedId = backpackInstance._id;\n this.result.adventurersPack.item = adventurersPack;\n this.result.equipment.push(backpackInstance);\n for (const content of this.result.adventurersPack.contents) {\n const indexMatch = index.find((i) => i.system.slug === content.slug);\n if (!indexMatch) {\n logger.error(`Unable to match adventurers kit item ${content.name}`, content);\n continue;\n }\n\n const doc = await defaultCompendium.getDocument(indexMatch._id);\n const itemData = doc.toObject();\n itemData._id = foundry.utils.randomID();\n itemData.system.quantity = content.qty;\n itemData.system.containerId = backpackInstance?._id;\n this.#resizeItem(itemData);\n this.result.equipment.push(itemData);\n }\n }\n }\n\n async #generateContainers() {\n for (const [key, data] of Object.entries(this.source.equipmentContainers)) {\n if (data.foundryId) continue;\n const name = Seasoning.getFoundryEquipmentName(data.containerName);\n const indexMatch = this.compendiumMatchers[\"equipment\"].getMatch(data.containerName, name);\n const id = foundry.utils.randomID();\n const doc = indexMatch\n ? await indexMatch.pack.getDocument(indexMatch.i._id)\n : await Item.create({ name: data.containerName, type: \"backpack\" }, { temporary: true });\n const itemData = doc.toObject();\n itemData._id = id;\n this.#resizeItem(itemData);\n this.result[\"equipment\"].push(itemData);\n this.parsed.equipment.push({\n pbName: data.containerName,\n name,\n qty: 1,\n added: true,\n inContainer: undefined,\n container: this.#getContainerData(key),\n foundryId: id,\n });\n }\n }\n\n async #generateEquipmentItems() {\n for (const e of this.parsed.equipment) {\n if (e.pbName === \"Adventurer's Pack\") continue;\n if (e.added) continue;\n if (Seasoning.IGNORED_EQUIPMENT().includes(e.pbName)) {\n e.added = true;\n e.addedAutoId = \"ignored\";\n continue;\n }\n logger.debug(\"Generating item for\", e);\n const indexMatch = this.compendiumMatchers[\"equipment\"].getMatch(e.pbName, e.pbName);\n if (!indexMatch) {\n logger.error(`Unable to match ${e.pbName}`, e);\n this.bad.push({ pbName: e.pbName, type: \"equipment\", details: { e } });\n continue;\n }\n\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n if (doc.type != \"kit\") {\n const itemData = doc.toObject();\n itemData._id = e.foundryId || foundry.utils.randomID();\n itemData.system.quantity = e.qty;\n const type = doc.type === \"treasure\" ? \"treasure\" : \"equipment\";\n if (e.inContainer) {\n const containerMatch = this.parsed.equipment.find((con) => con.container?.id === e.inContainer);\n if (containerMatch) {\n itemData.system.containerId = containerMatch.foundryId;\n itemData.system.equipped.carryType = \"stowed\";\n }\n }\n if (e.invested) {\n itemData.system.equipped.carryType = \"worn\";\n itemData.system.equipped.invested = true;\n itemData.system.equipped.inSlot = true;\n itemData.system.equipped.handsHeld = 0;\n }\n this.#resizeItem(itemData);\n this.result[type].push(itemData);\n e.addedId = itemData._id;\n }\n // eslint-disable-next-line require-atomic-updates\n e.added = true;\n }\n }\n\n async #processEquipmentItems() {\n // just in case it's in the equipment, pathbuilder should have translated this to items\n await this.#generateAdventurersPack();\n await this.#generateContainers();\n await this.#generateEquipmentItems();\n }\n\n static applyRunes(parsedItem, itemData, type) {\n itemData.system.potencyRune.value = parsedItem.pot;\n if (type === \"weapon\") {\n itemData.system.strikingRune.value = parsedItem.str;\n } else if (type === \"armor\") {\n itemData.system.resiliencyRune.value = parsedItem.res;\n }\n\n if (type === \"armor\" && parsedItem.worn\n && ((Number.isInteger(parsedItem.pot) && parsedItem.pot > 0)\n || (parsedItem.res && parsedItem.res !== \"\")\n )\n ) {\n itemData.system.equipped.invested = true;\n }\n\n if (parsedItem.runes[0]) itemData.system.propertyRune1.value = Seasoning.slugD(parsedItem.runes[0]);\n if (parsedItem.runes[1]) itemData.system.propertyRune2.value = Seasoning.slugD(parsedItem.runes[1]);\n if (parsedItem.runes[2]) itemData.system.propertyRune3.value = Seasoning.slugD(parsedItem.runes[2]);\n if (parsedItem.runes[3]) itemData.system.propertyRune4.value = Seasoning.slugD(parsedItem.runes[3]);\n if (parsedItem.mat) {\n const material = parsedItem.mat.split(\" (\")[0];\n itemData.system.preciousMaterial.value = Seasoning.slugD(material);\n itemData.system.preciousMaterialGrade.value = Seasoning.getMaterialGrade(parsedItem.mat);\n }\n }\n\n async #generateWeaponItems() {\n for (const w of this.parsed.weapons) {\n if (Seasoning.IGNORED_EQUIPMENT().includes(w.pbName)) {\n w.added = true;\n w.addedAutoId = \"ignored\";\n continue;\n }\n logger.debug(\"Generating weapon for\", w);\n const indexMatch = this.compendiumMatchers[\"equipment\"].getMatch(w.pbName, w.pbName);\n if (!indexMatch) {\n logger.error(`Unable to match weapon item ${w.name}`, w);\n this.bad.push({ pbName: w.pbName, type: \"weapon\", details: { w } });\n continue;\n }\n\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n const itemData = doc.toObject();\n itemData._id = foundry.utils.randomID();\n itemData.system.quantity = w.qty;\n // because some shields don't have damage dice, but come in as weapons on pathbuilder\n if (itemData.type === \"weapon\") {\n itemData.system.damage.die = w.die;\n Pathmuncher.applyRunes(w, itemData, \"weapon\");\n }\n\n if (w.display) itemData.name = w.display;\n\n this.#resizeItem(itemData);\n this.result.weapons.push(itemData);\n w.added = true;\n w.addedId = itemData._id;\n }\n }\n\n async #generateArmorItems() {\n for (const a of this.parsed.armor) {\n if (Seasoning.IGNORED_EQUIPMENT().includes(a.pbName)) {\n a.added = true;\n a.addedAutoId = \"ignored\";\n continue;\n }\n logger.debug(\"Generating armor for\", a);\n const indexMatch = this.compendiumMatchers[\"equipment\"].getMatch(`${a.pbName} Armor`, a.pbName);\n if (!indexMatch) {\n logger.error(`Unable to match armor kit item ${a.name}`, a);\n this.bad.push({ pbName: a.pbName, type: \"armor\", details: { a } });\n continue;\n }\n\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n const itemData = doc.toObject();\n itemData._id = foundry.utils.randomID();\n itemData.system.equipped.value = a.worn ?? false;\n if (!Seasoning.RESTRICTED_EQUIPMENT().some((i) => itemData.name.startsWith(i))) {\n itemData.system.equipped.inSlot = a.worn ?? false;\n itemData.system.quantity = a.qty;\n itemData.system.category = a.prof;\n\n const isShield = itemData.system.category === \"shield\";\n itemData.system.equipped.handsHeld = isShield && a.worn ? 1 : 0;\n itemData.system.equipped.carryType = isShield && a.worn ? \"held\" : \"worn\";\n\n Pathmuncher.applyRunes(a, itemData, \"armor\");\n }\n if (a.display) itemData.name = a.display;\n\n this.#resizeItem(itemData);\n this.result.armor.push(itemData);\n // eslint-disable-next-line require-atomic-updates\n a.added = true;\n a.addedId = itemData._id;\n }\n }\n\n getClassSpellCastingType(dual = false) {\n const classCaster = dual\n ? this.source.spellCasters.find((caster) => caster.name === this.source.dualClass)\n : this.source.spellCasters.find((caster) => caster.name === this.source.class);\n const type = classCaster?.spellcastingType;\n if (type || this.source.spellCasters.length === 0) return type ?? \"spontaneous\";\n // if no type and multiple spell casters, then return the first spell casting type\n return this.source.spellCasters[0].spellcastingType ?? \"spontaneous\";\n }\n\n // aims to determine the class magic tradition for a spellcasting block\n getClassMagicTradition(caster) {\n const classCaster = [this.source.class, this.source.dualClass].includes(caster.name);\n const tradition = classCaster ? caster?.magicTradition : undefined;\n // if a caster tradition or no spellcasters, return divine\n if (tradition || this.source.spellCasters.length === 0) return tradition ?? \"divine\";\n\n // not a focus traditions\n if (caster.magicTradition !== \"focus\" && [\"divine\", \"occult\", \"primal\", \"arcane\"].includes(caster.magicTradition)) {\n return caster.magicTradition;\n }\n\n // this spell caster type is not a class, determine class tradition based on ability\n const abilityTradition = this.source.spellCasters.find((c) =>\n [this.source.class, this.source.dualClass].includes(c.name)\n && c.ability === caster.ability\n );\n if (abilityTradition) return abilityTradition.magicTradition;\n // if no type and multiple spell casters, then return the first spell casting type\n return this.source.spellCasters[0].magicTradition && this.source.spellCasters[0].magicTradition !== \"focus\"\n ? this.source.spellCasters[0].magicTradition\n : \"divine\";\n }\n\n #applySpellBlending(spellcastingEntity, caster) {\n if (caster.blendedSpells.length === 0) return;\n\n const remove = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n const add = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n\n // find adjustments\n caster.blendedSpells.forEach((slot) => {\n remove[slot.levelFrom]++;\n add[slot.LevelTo]++;\n });\n\n for (let i = 0; i <= 10; i++) {\n const toAdd = this.options.adjustBlendedSlots ? 0 : Math.floor(add[i] / 2);\n const toRemove = this.options.adjustBlendedSlots ? remove[i] : 0;\n const adjustment = 0 - toRemove - toAdd;\n logger.debug(\"Adjusting spells for spell blending\", { i, adjustment, add, remove, toAdd, max: spellcastingEntity.slots[`slot${i}`].max });\n spellcastingEntity.slots[`slot${i}`].max += adjustment;\n spellcastingEntity.slots[`slot${i}`].value += adjustment;\n }\n }\n\n #generateSpellCaster(caster) {\n const isFocus = caster.magicTradition === \"focus\";\n const magicTradition = this.getClassMagicTradition(caster);\n const spellcastingType = isFocus ? \"focus\" : caster.spellcastingType;\n const flexible = false; // placeholder\n\n const name = isFocus ? `${utils.capitalize(magicTradition)} ${caster.name}` : caster.name;\n\n const spellcastingEntity = {\n ability: {\n value: caster.ability,\n },\n proficiency: {\n value: caster.proficiency / 2,\n },\n spelldc: {\n item: 0,\n },\n tradition: {\n value: magicTradition,\n },\n prepared: {\n value: spellcastingType,\n flexible,\n },\n slots: {},\n showUnpreparedSpells: { value: true },\n showSlotlessLevels: { value: true },\n };\n\n // apply slot data\n for (let i = 0; i <= 10; i++) {\n\n spellcastingEntity.slots[`slot${i}`] = {\n max: caster.perDay[i],\n prepared: {},\n value: caster.perDay[i],\n };\n }\n // adjust slots for spell blended effects\n this.#applySpellBlending(spellcastingEntity, caster);\n\n const data = {\n _id: foundry.utils.randomID(),\n name,\n type: \"spellcastingEntry\",\n system: spellcastingEntity,\n };\n this.result.casters.push(data);\n return data;\n }\n\n #generateFocusSpellCaster(proficiency, ability, tradition) {\n const data = {\n _id: foundry.utils.randomID(),\n name: `${utils.capitalize(tradition)} Focus Tradition`,\n type: \"spellcastingEntry\",\n system: {\n ability: {\n value: ability,\n },\n proficiency: {\n value: proficiency / 2,\n },\n spelldc: {\n item: 0,\n },\n tradition: {\n value: tradition,\n },\n prepared: {\n value: \"focus\",\n flexible: false,\n },\n showUnpreparedSpells: { value: true },\n },\n };\n this.result.casters.push(data);\n return data;\n }\n\n async #loadSpell(spell, casterId, debugData) {\n const spellName = spellRename(spell.split(\"(\")[0].trim());\n logger.debug(\"focus spell details\", { spell, spellName, debugData });\n\n const indexMatch = this.compendiumMatchers[\"spells\"].getMatch(spell, spellName, true);\n if (!indexMatch) {\n if (debugData.psychicAmpSpell) return undefined;\n logger.error(`Unable to match focus spell ${spell}`, { spell, spellName, debugData });\n this.bad.push({ pbName: spell, type: \"spell\", details: { originalName: spell, name: spellName, debugData } });\n return undefined;\n }\n\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n const itemData = doc.toObject();\n itemData._id = foundry.utils.randomID();\n itemData.system.location.value = casterId;\n\n return itemData;\n }\n\n // eslint-disable-next-line complexity\n async #processCasterSpells(instance, caster, spellEnhancements, forcePrepare = false) {\n const spellNames = {};\n for (const spellSelection of caster.spells) {\n const level = spellSelection.spellLevel;\n const preparedAtLevel = caster.prepared?.length > 0\n ? (caster.prepared.find((p) => p.spellLevel === level)?.list ?? [])\n : [];\n let preparedValue = 0;\n\n // const preparedMap = preparedAtLevel.reduce((acc, e) => acc.set(e, (acc.get(e) || 0) + 1), new Map());\n\n for (const [i, spell] of spellSelection.list.entries()) {\n logger.debug(`Checking spell at ${i} for level ${level}`, { spell });\n const itemData = await this.#loadSpell(spell, instance._id, {\n spellSelection,\n list: spellSelection.list,\n level,\n instance,\n });\n if (itemData) {\n itemData.system.location.heightenedLevel = level;\n spellNames[spell] = itemData._id;\n this.result.spells.push(itemData);\n\n // if the caster is prepared we don't prepare spells as all known spells come through in JSON\n if (instance.system.prepared.value !== \"prepared\"\n || spellEnhancements?.preparePBSpells\n || forcePrepare\n || (caster.spellcastingType === \"prepared\"\n && preparedAtLevel.length === 0 && spellSelection.list.length <= caster.perDay[level])\n ) {\n logger.debug(`Preparing spell ${itemData.name} for level ${level}`, { spell });\n // eslint-disable-next-line require-atomic-updates\n instance.system.slots[`slot${level}`].prepared[preparedValue] = { id: itemData._id };\n preparedValue++;\n }\n }\n }\n\n for (const spell of preparedAtLevel) {\n // if (spellNames.includes(spellName)) continue;\n const parsedSpell = getProperty(spellNames, spell);\n const itemData = parsedSpell\n ? this.result.spells.find((s) => s._id === parsedSpell)\n : await this.#loadSpell(spell, instance._id, {\n spellSelection,\n level,\n instance,\n });\n if (itemData) {\n itemData.system.location.heightenedLevel = level;\n if (itemData && !parsedSpell) {\n spellNames[spell] = itemData._id;\n this.result.spells.push(itemData);\n }\n\n logger.debug(`Preparing spell ${itemData.name} for level ${level}`, { spellName: spell });\n // eslint-disable-next-line require-atomic-updates\n instance.system.slots[`slot${level}`].prepared[preparedValue] = { id: itemData._id };\n preparedValue++;\n } else {\n logger.warn(`Unable to find spell ${spell}`);\n }\n }\n\n if (spellEnhancements?.knownSpells) {\n for (const spell of spellEnhancements.knownSpells) {\n const itemData = await this.#loadSpell(spell, instance._id, {\n spellEnhancements,\n instance,\n });\n if (itemData && !hasProperty(spellNames, itemData.name)) {\n itemData.system.location.heightenedLevel = level;\n spellNames[spell] = itemData._id;\n this.result.spells.push(itemData);\n }\n }\n }\n }\n }\n\n async #processFocusSpells(instance, spells) {\n for (const spell of spells) {\n const itemData = await this.#loadSpell(spell, instance._id, {\n instance,\n spells,\n spell,\n });\n if (itemData) this.result.spells.push(itemData);\n if (spell.endsWith(\"(Amped)\")) {\n const psychicSpell = spell.replace(\"(Amped)\", \"(Psychic)\");\n const psychicItemData = await this.#loadSpell(psychicSpell, instance._id, {\n instance,\n spells,\n spell: psychicSpell,\n psychicAmpSpell: true,\n });\n if (psychicItemData) {\n this.result.spells.push(psychicItemData);\n }\n }\n }\n }\n\n async #processRituals() {\n if (!this.source.rituals) return;\n const ritualCompendium = new CompendiumMatcher({\n type: \"spells\",\n indexFields: [\"name\", \"type\", \"system.slug\", \"system.category.value\"],\n });\n await ritualCompendium.loadCompendiums();\n\n const ritualFilters = {\n \"system.category.value\": \"ritual\",\n };\n for (const ritual of this.source.rituals) {\n const ritualName = ritual.split(\"(\")[0].trim();\n logger.debug(\"focus spell details\", { ritual, spellName: ritualName });\n\n const indexMatch = this.compendiumMatchers[\"spells\"].getNameMatchWithFilter(ritualName, ritualName, ritualFilters);\n if (!indexMatch) {\n logger.error(`Unable to match ritual spell ${ritual}`, { spell: ritual, spellName: ritualName });\n this.bad.push({ pbName: ritual, type: \"spell\", details: { originalName: ritual, name: ritualName } });\n continue;\n }\n\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n const itemData = doc.toObject();\n itemData._id = foundry.utils.randomID();\n\n this.result.spells.push(itemData);\n }\n }\n\n async #processSpells() {\n for (const caster of this.source.spellCasters) {\n logger.debug(\"Generating caster for\", caster);\n if (Number.isInteger(parseInt(caster.focusPoints))) this.result.focusPool += caster.focusPoints;\n const instance = this.#generateSpellCaster(caster);\n logger.debug(\"Generated caster instance\", instance);\n const spellEnhancements = Seasoning.getSpellCastingFeatureAdjustment(caster.name);\n let forcePrepare = false;\n if (hasProperty(spellEnhancements, \"showSlotless\")) {\n instance.system.showSlotlessLevels.value = getProperty(spellEnhancements, \"showSlotless\");\n } else if (\n caster.spellcastingType === \"prepared\"\n && ![this.source.class, this.source.dualClass].includes(caster.name)\n ) {\n const slotToPreparedMatch = caster.spells.every((spellBlock) => {\n const spellCount = spellBlock.list.length;\n const perDay = caster.perDay[spellBlock.spellLevel];\n return perDay === spellCount;\n });\n logger.debug(`Setting ${caster.name} show all slots to ${!slotToPreparedMatch}`);\n instance.system.showSlotlessLevels.value = !slotToPreparedMatch;\n forcePrepare = slotToPreparedMatch;\n }\n await this.#processCasterSpells(instance, caster, spellEnhancements, forcePrepare);\n }\n\n for (const tradition of [\"occult\", \"primal\", \"divine\", \"arcane\"]) {\n const traditionData = getProperty(this.source, `focus.${tradition}`);\n logger.debug(`Checking for focus tradition ${tradition}`);\n if (!traditionData) continue;\n for (const ability of [\"str\", \"dex\", \"con\", \"int\", \"wis\", \"cha\"]) {\n const abilityData = getProperty(traditionData, ability);\n logger.debug(`Checking for focus tradition ${tradition} with ability ${ability}`);\n if (!abilityData) continue;\n logger.debug(\"Generating focus spellcasting \", { tradition, traditionData, ability });\n const instance = this.#generateFocusSpellCaster(abilityData.proficiency, ability, tradition);\n if (abilityData.focusCantrips && abilityData.focusCantrips.length > 0) {\n await this.#processFocusSpells(instance, abilityData.focusCantrips);\n }\n if (abilityData.focusSpells && abilityData.focusSpells.length > 0) {\n await this.#processFocusSpells(instance, abilityData.focusSpells);\n }\n }\n }\n\n setProperty(this.result.character, \"system.resources.focus.max\", this.source.focusPoints);\n setProperty(this.result.character, \"system.resources.focus.value\", this.source.focusPoints);\n }\n\n async #generateLores() {\n for (const lore of this.source.lores) {\n const data = {\n name: lore[0],\n type: \"lore\",\n system: {\n proficient: {\n value: lore[1] / 2,\n },\n featType: \"\",\n mod: {\n value: 0,\n },\n item: {\n value: 0,\n },\n },\n };\n this.result.lores.push(data);\n }\n }\n\n async #generateMoney() {\n const compendium = game.packs.get(\"pf2e.equipment-srd\");\n const index = await compendium.getIndex({ fields: [\"name\", \"type\", \"system.slug\"] });\n const moneyLookup = [\n { slug: \"platinum-pieces\", type: \"pp\" },\n { slug: \"gold-pieces\", type: \"gp\" },\n { slug: \"silver-pieces\", type: \"sp\" },\n { slug: \"copper-pieces\", type: \"cp\" },\n ];\n\n for (const lookup of moneyLookup) {\n const indexMatch = index.find((i) => i.system.slug === lookup.slug);\n if (indexMatch) {\n const doc = await compendium.getDocument(indexMatch._id);\n const itemData = doc.toObject();\n itemData._id = foundry.utils.randomID();\n itemData.system.quantity = this.source.money[lookup.type];\n this.result.money.push(itemData);\n }\n }\n }\n\n async #processFormulas() {\n const uuids = [];\n\n for (const formulaSource of this.source.formula) {\n for (const formulaName of formulaSource.known) {\n const indexMatch = this.compendiumMatchers[\"formulas\"].getMatch(formulaName, formulaName);\n if (!indexMatch) {\n logger.error(`Unable to match formula ${formulaName}`, { formulaSource, name: formulaName });\n this.bad.push({ pbName: formulaName, type: \"formula\", details: { formulaSource, name: formulaName } });\n continue;\n }\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n uuids.push({ uuid: doc.uuid });\n }\n }\n setProperty(this.result.character, \"system.crafting.formulas\", uuids);\n }\n\n async #processFeats() {\n this.#sortParsedFeats();\n // pre pass\n await this.#generateFeatItems(\"feats\", { parsedFilter: \"Ancestry Feat\" });\n await this.#generateFeatItems(\"feats\", { parsedFilter: \"Skill Feat\" });\n await this.#generateFeatItems(\"feats\", { parsedFilter: \"Class Feat\" });\n\n this.#statusUpdate(1, 5, \"Feats\");\n await this.#generateFeatItems(\"feats\");\n this.#statusUpdate(2, 5, \"Feats\");\n await this.#generateFeatItems(\"ancestryFeatures\");\n this.#statusUpdate(3, 5, \"Feats\");\n await this.#generateSpecialItems(\"ancestryFeatures\");\n this.#statusUpdate(4, 5, \"Feats\");\n await this.#generateSpecialItems(\"classFeatures\");\n this.#statusUpdate(5, 5, \"Feats\");\n await this.#generateSpecialItems(\"actions\");\n }\n\n async #processEquipment() {\n this.#statusUpdate(1, 4, \"Equipment\");\n await this.#processEquipmentItems();\n this.#statusUpdate(2, 4, \"Weapons\");\n await this.#generateWeaponItems();\n this.#statusUpdate(3, 4, \"Armor\");\n await this.#generateArmorItems();\n this.#statusUpdate(2, 4, \"Money\");\n await this.#generateMoney();\n }\n\n async #generateTempActor(documents = [], includePassedDocumentsRules = false, includeGrants = false, includeFlagsOnly = false) {\n const actorData = mergeObject({ type: \"character\" }, this.result.character);\n actorData.name = `Mr Temp (${this.result.character.name})`;\n if (documents.map((d) => d.name.split(\"(\")[0].trim().toLowerCase()).includes(\"skill training\")) {\n delete actorData.system.skills;\n }\n\n const actor = await Actor.create(actorData);\n const currentState = duplicate(this.result);\n\n // console.warn(\"Initial temp actor\", deepClone(actor));\n\n const currentItems = [\n ...currentState.deity,\n ...currentState.ancestry,\n ...currentState.heritage,\n ...currentState.background,\n ...currentState.class,\n ...currentState.lores,\n ...currentState.feats,\n ...currentState.casters,\n // ...currentState.spells,\n // ...currentState.equipment,\n // ...currentState.weapons,\n // ...currentState.armor,\n // ...currentState.treasure,\n // ...currentState.money,\n ];\n for (const doc of documents) {\n if (!currentItems.some((d) => d._id === doc._id)) {\n currentItems.push(deepClone(doc));\n }\n }\n try {\n // if the rule selected is an object, id doesn't take on import\n const ruleUpdates = [];\n for (const i of deepClone(currentItems)) {\n if (!i.system.rules || i.system.rules.length === 0) continue;\n const isPassedDocument = documents.some((d) => d._id === i._id);\n if (isPassedDocument && !includePassedDocumentsRules && !includeFlagsOnly) continue;\n\n const objectSelectionRules = i.system.rules\n .filter((r) => {\n const evaluateRules = [\"RollOption\", \"ChoiceSet\"].includes(r.key) && r.selection;\n return !includeFlagsOnly || evaluateRules; // && [\"RollOption\", \"GrantItem\", \"ChoiceSet\", \"ActiveEffectLike\"].includes(r.key);\n // || ([\"ChoiceSet\"].includes(r.key) && r.selection);\n })\n .map((r) => {\n r.ignored = false;\n return r;\n });\n\n if (objectSelectionRules.length > 0) {\n ruleUpdates.push({\n _id: i._id,\n system: {\n rules: objectSelectionRules,\n },\n });\n }\n }\n\n // console.warn(\"Rule updates\", duplicate(ruleUpdates));\n\n const items = duplicate(currentItems).map((i) => {\n if (i.system.items) i.system.items = [];\n if (i.system.rules) {\n i.system.rules = i.system.rules\n .filter((r) => {\n const isPassedDocument = documents.some((d) => d._id === i._id);\n const isChoiceSetSelection = [\"ChoiceSet\"].includes(r.key) && r.selection;\n // const choiceSetSelectionObject = isChoiceSetSelection && utils.isObject(r.selection);\n const choiceSetSelectionNotObject = isChoiceSetSelection && !utils.isObject(r.selection);\n // const grantRuleWithFlag = includeGrants && [\"GrantItem\"].includes(r.key) && r.flag;\n const grantRuleWithoutFlag = includeGrants && [\"GrantItem\"].includes(r.key) && !r.flag;\n // const genericDiscardRule = [\"ChoiceSet\", \"GrantItem\", \"ActiveEffectLike\", \"Resistance\", \"Strike\", \"AdjustModifier\"].includes(r.key);\n const genericDiscardRule = [\"ChoiceSet\", \"GrantItem\"].includes(r.key);\n const grantRuleFromItemFlag\n = includeGrants && [\"GrantItem\"].includes(r.key) && r.uuid.startsWith(\"{item|flags\");\n const rollOptionsRule = [\"RollOption\"].includes(r.key);\n\n const notPassedDocumentRules\n = !isPassedDocument\n && (choiceSetSelectionNotObject\n // || grantRuleWithFlag\n || grantRuleWithoutFlag\n || !genericDiscardRule);\n\n const passedDocumentRules\n = isPassedDocument\n && includePassedDocumentsRules\n && (isChoiceSetSelection || grantRuleWithoutFlag || grantRuleFromItemFlag || rollOptionsRule);\n\n return notPassedDocumentRules || passedDocumentRules;\n })\n .map((r) => {\n // if choices is a string or an object then we replace with the query string results\n if ((utils.isString(r.choices) || utils.isObject(r.choices)) && r.choiceQueryResults) {\n r.choices = r.choiceQueryResults;\n }\n r.ignored = false;\n return r;\n });\n }\n return i;\n });\n\n // const items2 = duplicate(currentItems).map((i) => {\n // if (i.system.items) i.system.items = [];\n // if (i.system.rules) i.system.rules = i.system.rules.filter((r) =>\n // (!documents.some((d) => d._id === i._id)\n // && (([\"ChoiceSet\",].includes(r.key) && r.selection)\n // // || ([\"GrantItem\"].includes(r.key) && r.flag)\n // || ![\"ChoiceSet\", \"GrantItem\"].includes(r.key)\n // ))\n // || (includePassedDocumentsRules && documents.some((d) => d._id === i._id) && [\"ChoiceSet\",].includes(r.key) && r.selection)\n // ).map((r) => {\n // if ((typeof r.choices === 'string' || r.choices instanceof String)\n // || (typeof r.choices === 'object' && !Array.isArray(r.choices) && r.choices !== null && r.choiceQueryResults)\n // ) {\n // r.choices = r.choiceQueryResults;\n // }\n // r.ignored = false;\n // return r;\n // });\n // return i;\n // });\n\n // console.warn(\"temp items\", {\n // documents: deepClone(currentItems),\n // items: deepClone(items),\n // // items2: deepClone(items2),\n // // diff: diffObject(items, items2),\n // includePassedDocumentsRules,\n // includeGrants,\n // });\n await actor.createEmbeddedDocuments(\"Item\", items, { keepId: true });\n // console.warn(\"restoring selection rules to temp items\", ruleUpdates);\n await actor.updateEmbeddedDocuments(\"Item\", ruleUpdates);\n\n const itemUpdates = [];\n for (const [key, value] of Object.entries(this.autoAddedFeatureItems)) {\n itemUpdates.push({\n _id: `${key}`,\n system: {\n items: deepClone(value),\n },\n });\n }\n\n // console.warn(\"restoring feature items to temp items\", itemUpdates);\n await actor.updateEmbeddedDocuments(\"Item\", itemUpdates);\n\n logger.debug(\"Final temp actor\", actor);\n } catch (err) {\n logger.error(\"Temp actor creation failed\", {\n actor,\n documents,\n thisData: deepClone(this.result),\n actorData,\n err,\n currentItems,\n this: this,\n });\n }\n return actor;\n }\n\n async processCharacter() {\n if (!this.source) return;\n await this.#prepare();\n this.#statusUpdate(1, 12, \"Character\");\n await this.#processCore();\n this.#statusUpdate(2, 12, \"Formula\");\n await this.#processFormulas();\n this.#statusUpdate(3, 12, \"Deity\");\n await this.#processGenericCompendiumLookup(\"deities\", this.source.deity, \"deity\");\n\n this.#statusUpdate(4, 12, \"Ancestry\");\n await this.#processGenericCompendiumLookup(\"ancestries\", this.source.ancestry, \"ancestry\");\n this.#statusUpdate(5, 12, \"Heritage\");\n await this.#processGenericCompendiumLookup(\"heritages\", this.source.heritage, \"heritage\");\n this.#statusUpdate(6, 12, \"Background\");\n await this.#processGenericCompendiumLookup(\"backgrounds\", this.source.background, \"background\");\n\n this.#setSkills();\n\n this.#statusUpdate(7, 12, \"Class\");\n await this.#processGenericCompendiumLookup(\"classes\", this.source.class, \"class\");\n\n this.#setAbilityBoosts();\n\n this.#statusUpdate(8, 12, \"FeatureRec\");\n await this.#processFeats();\n this.#statusUpdate(10, 12, \"Equipment\");\n await this.#processEquipment();\n this.#statusUpdate(11, 12, \"Spells\");\n await this.#processSpells();\n this.#statusUpdate(11, 12, \"Rituals\");\n await this.#processRituals();\n this.#statusUpdate(12, 12, \"Lores\");\n await this.#generateLores();\n }\n\n async #removeDocumentsToBeUpdated() {\n const moneyIds = this.actor.items.filter((i) =>\n i.type === \"treasure\"\n && [\"Platinum Pieces\", \"Gold Pieces\", \"Silver Pieces\", \"Copper Pieces\"].includes(i.name)\n );\n const classIds = this.actor.items.filter((i) => i.type === \"class\").map((i) => i._id);\n const deityIds = this.actor.items.filter((i) => i.type === \"deity\").map((i) => i._id);\n const backgroundIds = this.actor.items.filter((i) => i.type === \"background\").map((i) => i._id);\n const heritageIds = this.actor.items.filter((i) => i.type === \"heritage\").map((i) => i._id);\n const ancestryIds = this.actor.items.filter((i) => i.type === \"ancestry\").map((i) => i._id);\n const treasureIds = this.actor.items\n .filter((i) => i.type === \"treasure\" && !moneyIds.includes(i.id))\n .map((i) => i._id);\n const featIds = this.actor.items.filter((i) => i.type === \"feat\").map((i) => i._id);\n const actionIds = this.actor.items.filter((i) => i.type === \"action\").map((i) => i._id);\n const equipmentIds = this.actor.items\n .filter((i) => i.type === \"equipment\" || i.type === \"backpack\" || i.type === \"consumable\")\n .map((i) => i._id);\n const weaponIds = this.actor.items.filter((i) => i.type === \"weapon\").map((i) => i._id);\n const armorIds = this.actor.items.filter((i) => i.type === \"armor\").map((i) => i._id);\n const loreIds = this.actor.items.filter((i) => i.type === \"lore\").map((i) => i._id);\n const spellIds = this.actor.items\n .filter((i) => i.type === \"spell\" || i.type === \"spellcastingEntry\")\n .map((i) => i._id);\n const formulaIds = this.actor.system.formulas;\n\n logger.debug(\"ids\", {\n moneyIds,\n deityIds,\n classIds,\n backgroundIds,\n heritageIds,\n ancestryIds,\n treasureIds,\n featIds,\n actionIds,\n equipmentIds,\n weaponIds,\n armorIds,\n loreIds,\n spellIds,\n formulaIds,\n });\n // eslint-disable-next-line complexity\n const keepIds = this.actor.items.filter((i) =>\n (!this.options.addMoney && moneyIds.includes(i._id))\n || (!this.options.addClass && classIds.includes(i._id))\n || (!this.options.addDeity && deityIds.includes(i._id))\n || (!this.options.addBackground && backgroundIds.includes(i._id))\n || (!this.options.addHeritage && heritageIds.includes(i._id))\n || (!this.options.addAncestry && ancestryIds.includes(i._id))\n || (!this.options.addTreasure && treasureIds.includes(i._id))\n || (!this.options.addFeats && (featIds.includes(i._id) || actionIds.includes(i._id)))\n || (!this.options.addEquipment && equipmentIds.includes(i._id))\n || (!this.options.addWeapons && weaponIds.includes(i._id))\n || (!this.options.addArmor && armorIds.includes(i._id))\n || (!this.options.addLores && loreIds.includes(i._id))\n || (!this.options.addSpells && spellIds.includes(i._id))\n ).map((i) => i._id);\n\n const deleteIds = this.actor.items.filter((i) => !keepIds.includes(i._id)).map((i) => i._id);\n logger.debug(\"ids\", {\n deleteIds,\n keepIds,\n });\n await this.actor.deleteEmbeddedDocuments(\"Item\", deleteIds);\n }\n\n async #createAndUpdateItemsWithRuleRestore(items) {\n const ruleUpdates = [];\n\n const newItems = deepClone(items);\n\n for (const item of newItems) {\n if (item.system.rules?.length > 0) {\n ruleUpdates.push({\n _id: item._id,\n system: {\n rules: deepClone(item.system.rules).map((r) => {\n delete r.choiceQueryResults;\n return r;\n }),\n },\n });\n item.system.rules = item.system.rules\n .filter((r) => {\n const excludedKeys = [\"ActiveEffectLike\", \"AdjustModifier\", \"Resistance\", \"Strike\"].includes(r.key);\n const grantItemWithFlags = [\"GrantItem\"].includes(r.key) && (hasProperty(r, \"flag\") || getProperty(r, \"pathmuncherImport\"));\n const objectSelection = [\"ChoiceSet\"].includes(r.key) && utils.isObject(r.selection);\n return !excludedKeys && !grantItemWithFlags && !objectSelection;\n })\n .map((r) => {\n if (r.key === \"ChoiceSet\") {\n if ((utils.isString(r.choices) || utils.isObject(r.choices)) && r.choiceQueryResults) {\n r.choices = r.choiceQueryResults;\n }\n }\n if (r.pathmuncherImport) delete r.pathmuncherImport;\n return r;\n });\n }\n }\n\n logger.debug(\"Creating items\", newItems);\n await this.actor.createEmbeddedDocuments(\"Item\", newItems, { keepId: true });\n logger.debug(\"Rule updates\", ruleUpdates);\n await this.actor.updateEmbeddedDocuments(\"Item\", ruleUpdates);\n }\n\n async #updateItems(type) {\n logger.debug(`Updating ${type}`, this.result[type]);\n await this.actor.updateEmbeddedDocuments(\"Item\", this.result[type]);\n }\n\n async #createActorEmbeddedDocuments() {\n this.#statusUpdate(1, 12, \"Character\", \"Eating\");\n if (this.options.addDeity) await this.#createAndUpdateItemsWithRuleRestore(this.result.deity);\n if (this.options.addAncestry) await this.#createAndUpdateItemsWithRuleRestore(this.result.ancestry);\n if (this.options.addHeritage) await this.#createAndUpdateItemsWithRuleRestore(this.result.heritage);\n if (this.options.addBackground) await this.#createAndUpdateItemsWithRuleRestore(this.result.background);\n if (this.options.addClass) await this.#createAndUpdateItemsWithRuleRestore(this.result.class);\n if (this.options.addLores) await this.#createAndUpdateItemsWithRuleRestore(this.result.lores);\n\n const featNums = this.result.feats.length;\n if (this.options.addFeats) {\n for (const [i, feat] of this.result.feats.entries()) {\n // console.warn(`creating ${feat.name}`, feat);\n this.#statusUpdate(i, featNums, \"Feats\", \"Eating\");\n await this.#createAndUpdateItemsWithRuleRestore([feat]);\n }\n }\n // if (this.options.addFeats) await this.#createAndUpdateItemsWithRuleRestore(this.result.feats);\n if (this.options.addSpells) {\n this.#statusUpdate(3, 12, \"Spells\", \"Eating\");\n await this.#createAndUpdateItemsWithRuleRestore(this.result.casters);\n await this.#createAndUpdateItemsWithRuleRestore(this.result.spells);\n }\n this.#statusUpdate(4, 12, \"Equipment\", \"Eating\");\n if (this.options.addEquipment) {\n await this.#createAndUpdateItemsWithRuleRestore(this.result.equipment);\n await this.#updateItems(\"equipment\");\n }\n if (this.options.addWeapons) await this.#createAndUpdateItemsWithRuleRestore(this.result.weapons);\n if (this.options.addArmor) {\n await this.#createAndUpdateItemsWithRuleRestore(this.result.armor);\n await this.actor.updateEmbeddedDocuments(\"Item\", this.result.armor);\n }\n if (this.options.addTreasure) await this.#createAndUpdateItemsWithRuleRestore(this.result.treasure);\n if (this.options.addMoney) await this.#createAndUpdateItemsWithRuleRestore(this.result.money);\n }\n\n async #restoreEmbeddedRuleLogic() {\n const importedItems = this.actor.items.map((i) => i._id);\n // Loop back over items and add rule and item progression data back in.\n logger.debug(\"Restoring logic\", { currentActor: duplicate(this.actor) });\n const itemUpdates = [];\n for (const [key, value] of Object.entries(this.autoAddedFeatureItems)) {\n if (importedItems.includes(key)) {\n itemUpdates.push({\n _id: `${key}`,\n system: {\n items: deepClone(value),\n },\n });\n }\n }\n this.#statusUpdate(1, 12, \"Feats\", \"Clearing\");\n logger.debug(\"Restoring granted item logic\", itemUpdates);\n await this.actor.updateEmbeddedDocuments(\"Item\", itemUpdates);\n\n await this.actor.update({\n \"system.resources.focus\": this.result.character.system.resources.focus,\n });\n }\n\n async updateActor() {\n await this.#removeDocumentsToBeUpdated();\n\n if (!this.options.addName) {\n delete this.result.character.name;\n delete this.result.character.prototypeToken.name;\n }\n if (!this.options.addFormulas) {\n delete this.result.character.system.formulas;\n }\n\n if (!this.boosts.custom) {\n [\"abilities\"].forEach((location) => {\n const abilityTargets = [\"str\", \"dex\", \"con\", \"int\", \"wis\", \"cha\"]\n .filter((ability) => hasProperty(this.actor, `system.${location}.${ability}`));\n const abilityDeletions = abilityTargets\n .reduce(\n (accumulated, ability) => ({\n ...accumulated,\n [`-=${ability}`]: null,\n }),\n {}\n );\n setProperty(this.result.character, `system.${location}`, abilityDeletions);\n });\n }\n\n logger.debug(\"Generated result\", this.result);\n await this.actor.update(this.result.character);\n await this.#createActorEmbeddedDocuments();\n await this.#restoreEmbeddedRuleLogic();\n }\n\n async postImportCheck() {\n const badClass = this.options.addClass\n ? this.bad.filter((b) => b.type === \"class\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Class\")}: ${b.pbName}</li>`)\n : [];\n const badHeritage = this.options.addHeritage\n ? this.bad.filter((b) => b.type === \"heritage\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Heritage\")}: ${b.pbName}</li>`)\n : [];\n const badAncestry = this.options.addAncestry\n ? this.bad.filter((b) => b.type === \"ancestry\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Ancestry\")}: ${b.pbName}</li>`)\n : [];\n const badBackground = this.options.addBackground\n ? this.bad.filter((b) => b.type === \"background\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Background\")}: ${b.pbName}</li>`)\n : [];\n const badDeity = this.options.addDeity\n ? this.bad.filter((b) => b.type === \"deity\" && b.pbName !== \"Not set\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Deity\")}: ${b.pbName}</li>`)\n : [];\n const badFeats = this.options.addFeats\n ? this.bad.filter((b) => b.type === \"feat\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Feats\")}: ${b.pbName}</li>`)\n : [];\n const badFeats2 = this.options.addFeats\n ? Object.values(this.check).filter((b) =>\n b.type === \"feat\"\n && this.parsed.feats.some((f) => f.name === b.details.name && !f.added)\n ).map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Feats\")}: ${b.details.name}</li>`)\n : [];\n const badSpecials = this.options.addFeats\n ? Object.values(this.check).filter((b) =>\n (b.type === \"special\")\n && this.parsed.specials.some((f) => f.name === b.details.name && !f.added)\n ).map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Specials\")}: ${b.details.name}</li>`)\n : [];\n const badEquipment = this.options.addEquipment\n ? this.bad.filter((b) => b.type === \"equipment\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Equipment\")}: ${b.pbName}</li>`)\n : [];\n const badWeapons = this.options.addWeapons\n ? this.bad.filter((b) => b.type === \"weapons\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Weapons\")}: ${b.pbName}</li>`)\n : [];\n const badArmor = this.options.addArmor\n ? this.bad.filter((b) => b.type === \"armor\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Armor\")}: ${b.pbName}</li>`)\n : [];\n const badSpellcasting = this.options.addSpells\n ? this.bad.filter((b) => b.type === \"spellcasting\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Spellcasting\")}: ${b.pbName}</li>`)\n : [];\n const badSpells = this.options.addSpells\n ? this.bad.filter((b) => b.type === \"spells\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Spells\")}: ${b.pbName}</li>`)\n : [];\n const badFamiliars = this.options.addFamiliars\n ? this.bad.filter((b) => b.type === \"familiars\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Familiars\")}: ${b.pbName}</li>`)\n : [];\n const badFormulas = this.options.addFormulas\n ? this.bad.filter((b) => b.type === \"formulas\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Formulas\")}: ${b.pbName}</li>`)\n : [];\n const totalBad = [\n ...badClass,\n ...badAncestry,\n ...badHeritage,\n ...badBackground,\n ...badDeity,\n ...badFeats,\n ...badFeats2,\n ...badSpecials,\n ...badEquipment,\n ...badWeapons,\n ...badArmor,\n ...badSpellcasting,\n ...badSpells,\n ...badFamiliars,\n ...badFormulas,\n ];\n\n let warning = \"\";\n\n if (totalBad.length > 0) {\n warning += `<p>${game.i18n.localize(\"pathmuncher.Dialogs.Pathmuncher.MissingItemsOpen\")}</p><ul>${totalBad.join(\"\\n\")}</ul><br>`;\n }\n\n logger.debug(\"Bad thing check\", {\n badClass,\n badAncestry,\n badHeritage,\n badBackground,\n badDeity,\n badFeats,\n badFeats2,\n badSpecials,\n badEquipment,\n badWeapons,\n badArmor,\n badSpellcasting,\n badSpells,\n badFamiliars,\n badFormulas,\n totalBad,\n count: totalBad.length,\n focusPool: this.result.focusPool,\n warning,\n });\n\n if (totalBad.length > 0) {\n ui.notifications.warn(game.i18n.localize(\"pathmuncher.Dialogs.Pathmuncher.CompletedWithNotes\"));\n new Dialog({\n title: game.i18n.localize(\"pathmuncher.Dialogs.Pathmuncher.ImportNotes\"),\n content: warning,\n buttons: {\n yes: {\n icon: \"<i class='fas fa-check'></i>\",\n label: game.i18n.localize(\"pathmuncher.Labels.Finished\"),\n },\n },\n default: \"yes\",\n }).render(true);\n } else {\n ui.notifications.info(game.i18n.localize(\"pathmuncher.Dialogs.Pathmuncher.CompletedSuccess\"));\n }\n }\n}\n","/* eslint-disable no-await-in-loop */\n/* eslint-disable no-continue */\n\nimport CONSTANTS from \"../constants.js\";\nimport logger from \"../logger.js\";\nimport utils from \"../utils.js\";\n\n/**\n * The PetShop class looks for familiars in a Pathmunch data set and creates/updates as appropriate.\n */\nexport class PetShop {\n\n\n constructor ({ type = \"familiar\", parent, pathbuilderJson } = {}) {\n this.parent = parent;\n this.pathbuilderJson = pathbuilderJson;\n this.type = type;\n\n this.result = {\n pets: [],\n features: {},\n };\n\n this.bad = {};\n this.folders = {};\n }\n\n\n async ensureFolder(type) {\n const folderName = game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Folders.${type}`);\n this.folders[type] = await utils.getOrCreateFolder(this.parent.folder, \"Actor\", folderName);\n }\n\n async #existingPetCheck(petName, type) {\n const existingPet = game.actors.find((a) =>\n a.type === type.toLowerCase()\n && a.name === petName\n && a.system.master.id === this.parent._id\n );\n\n if (existingPet) return existingPet.toObject();\n\n const actorData = {\n type: type.toLowerCase(),\n name: petName,\n system: {\n master: {\n id: this.parent._id,\n ability: this.parent.system.details.keyability.value,\n },\n },\n prototypeToken: {\n name: petName,\n },\n folder: this.folders[type].id,\n };\n const actor = await Actor.create(actorData);\n return actor.toObject();\n\n }\n\n #buildCore(petData) {\n setProperty(petData, \"system.attributes.value\", this.parent.system.details.level.value * 5);\n return petData;\n }\n\n async #generatePetFeatures(pet, json) {\n const compendium = game.packs.get(\"pf2e.familiar-abilities\");\n const index = await compendium.getIndex({ fields: [\"name\", \"type\", \"system.slug\"] });\n this.result.features[pet._id] = [];\n this.bad[pet._id] = [];\n\n for (const featureName of json.abilities) {\n const indexMatch = index.find((i) => i.system.slug === game.pf2e.system.sluggify(featureName));\n if (!indexMatch) {\n logger.warn(`Unable to match pet feature ${featureName}`, { pet, json, name: featureName });\n this.bad[pet._id].push({ pbName: featureName, type: \"feature\", details: { pet, json, name: featureName } });\n continue;\n }\n const doc = (await compendium.getDocument(indexMatch._id)).toObject();\n doc._id = foundry.utils.randomID();\n this.result.features[pet._id].push(doc);\n }\n }\n\n async buildPet(json) {\n const name = json.name === json.type || !json.name.includes(\"(\")\n ? `${this.parent.name}'s ${json.type}`\n : json.name.split(\"(\")[1].split(\")\")[0];\n const petData = await this.#existingPetCheck(name, json.type);\n const pet = this.#buildCore(petData);\n await this.#generatePetFeatures(pet, json);\n this.result.pets.push(pet);\n }\n\n async updatePets() {\n for (const petData of this.result.pets) {\n const actor = game.actors.get(petData._id);\n await actor.deleteEmbeddedDocuments(\"Item\", [], { deleteAll: true });\n await actor.update(petData);\n await actor.createEmbeddedDocuments(\"Item\", this.result.features[petData._id], { keepId: true });\n }\n }\n\n async processPets() {\n const petData = this.type === \"familiar\" && this.pathbuilderJson.familiars\n ? this.pathbuilderJson.familiars\n : this.pathbuilderJson.pets.filter((p) => this.type === p.type.toLowerCase());\n await this.ensureFolder(utils.capitalize(this.type));\n for (const petJson of petData) {\n await this.buildPet(petJson);\n }\n\n await this.updatePets();\n\n logger.debug(\"Pets\", {\n results: this.results,\n bad: this.bad,\n });\n }\n\n async addPetEffects() {\n const features = [];\n for (const petData of this.result.pets) {\n for (const feature of this.result.features[petData._id].filter((f) => f.system.rules?.some((r) => r.key === \"ActiveEffectLike\"))) {\n if (!this.parent.items.some((i) => i.type === \"effect\" && i.system.slug === feature.system.slug)) {\n features.push(feature);\n }\n }\n }\n await this.parent.createEmbeddedDocuments(\"Item\", features);\n }\n\n}\n","import CONSTANTS from \"../constants.js\";\nimport logger from \"../logger.js\";\nimport utils from \"../utils.js\";\nimport { Pathmuncher } from \"./Pathmuncher.js\";\nimport { PetShop } from \"./PetShop.js\";\n\nexport class PathmuncherImporter extends FormApplication {\n\n constructor(options, actor) {\n super(options);\n this.actor = game.actors.get(actor.id ? actor.id : actor._id);\n this.backup = duplicate(this.actor);\n this.mode = \"number\";\n }\n\n static get defaultOptions() {\n const options = super.defaultOptions;\n options.title = game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Dialogs.PathmuncherImporter.Title`);\n options.template = `${CONSTANTS.PATH}/templates/pathmuncher.hbs`;\n options.classes = [\"pathmuncher\"];\n options.id = \"pathmuncher\";\n options.width = 400;\n options.closeOnSubmit = false;\n options.tabs = [{ navSelector: \".tabs\", contentSelector: \"form\", initial: \"number\" }];\n return options;\n }\n\n /** @override */\n async getData() {\n const flags = utils.getFlags(this.actor);\n\n return {\n flags,\n id: flags?.pathbuilderId ?? \"\",\n actor: this.actor,\n };\n }\n\n /** @override */\n activateListeners(html) {\n super.activateListeners(html);\n $(\"#pathmuncher\").css(\"height\", \"auto\");\n\n $(html)\n .find('.item')\n .on(\"click\", (event) => {\n if (!event.target?.dataset?.tab) return;\n this.mode = event.target.dataset.tab;\n });\n }\n\n static _updateProgress(total, count, type, prefixLabel = \"Cooking\") {\n const localizedType = game.i18n.localize(`pathmuncher.Labels.${type}`);\n const progressBar = document.getElementById(\"pathmuncher-status\");\n progressBar.style.width = `${Math.trunc((count / total) * 100)}%`;\n progressBar.innerHTML = `<span>${game.i18n.localize(`pathmuncher.Labels.${prefixLabel}`)} (${localizedType})...</span>`;\n }\n\n async _updateObject(event, formData) {\n document.getElementById(\"pathmuncher-button\").disabled = true;\n const pathbuilderId = formData.textBoxBuildID;\n const options = {\n pathbuilderId,\n addMoney: formData.checkBoxMoney,\n addFeats: formData.checkBoxFeats,\n addSpells: formData.checkBoxSpells,\n adjustBlendedSlots: formData.checkBoxBlendedSlots,\n addEquipment: formData.checkBoxEquipment,\n addTreasure: formData.checkBoxTreasure,\n addLores: formData.checkBoxLores,\n addWeapons: formData.checkBoxWeapons,\n addArmor: formData.checkBoxArmor,\n addDeity: formData.checkBoxDeity,\n addName: formData.checkBoxName,\n addClass: formData.checkBoxClass,\n addBackground: formData.checkBoxBackground,\n addHeritage: formData.checkBoxHeritage,\n addAncestry: formData.checkBoxAncestry,\n addFamiliars: formData.checkBoxFamiliars,\n addFormulas: formData.checkBoxFormulas,\n statusCallback: PathmuncherImporter._updateProgress.bind(this),\n };\n logger.debug(\"Pathmuncher options\", options);\n\n await utils.setFlags(this.actor, options);\n\n const statusBar = document.getElementById(\"pathmuncher-import-progress\");\n statusBar.classList.toggle(\"import-hidden\");\n\n const pathmuncher = new Pathmuncher(this.actor, options);\n if (this.mode === \"number\") {\n await pathmuncher.fetchPathbuilder(pathbuilderId);\n } else if (this.mode === \"json\") {\n try {\n const jsonData = JSON.parse(formData.textBoxBuildJSON.trim());\n pathmuncher.source = jsonData.build;\n } catch (err) {\n ui.notifications.error(\"Unable to parse JSON data\");\n return;\n }\n }\n\n logger.debug(\"Pathmuncher Source\", pathmuncher.source);\n await pathmuncher.processCharacter();\n logger.debug(\"Post processed character\", pathmuncher);\n await pathmuncher.updateActor();\n logger.debug(\"Final import details\", {\n actor: this.actor,\n pathmuncher,\n options,\n pathbuilderSource: pathmuncher.source,\n pathbuilderId,\n });\n\n if (options.addFamiliars) {\n const petShop = new PetShop({\n type: \"familiar\",\n parent: this.actor,\n pathbuilderJson: pathmuncher.source\n });\n await petShop.processPets();\n await petShop.addPetEffects();\n }\n this.close();\n await pathmuncher.postImportCheck();\n }\n\n}\n","import { CompendiumMatcher } from \"../app/CompendiumMatcher.js\";\nimport { CompendiumSelector } from \"../app/CompendiumSelector.js\";\nimport { Pathmuncher } from \"../app/Pathmuncher.js\";\nimport { PathmuncherImporter } from \"../app/PathmuncherImporter.js\";\nimport { PetShop } from \"../app/PetShop.js\";\nimport { Seasoning } from \"../app/Seasoning.js\";\nimport CONSTANTS from \"../constants.js\";\nimport { EQUIPMENT_RENAME_MAP, RESTRICTED_EQUIPMENT } from \"../data/equipment.js\";\nimport { FEAT_RENAME_MAP } from \"../data/features.js\";\nimport utils from \"../utils.js\";\n\nexport function registerAPI() {\n game.modules.get(CONSTANTS.MODULE_NAME).api = {\n Pathmuncher,\n PathmuncherImporter,\n PetShop,\n CompendiumMatcher,\n Seasoning,\n CompendiumSelector,\n data: {\n generateFeatMap: FEAT_RENAME_MAP,\n equipment: EQUIPMENT_RENAME_MAP,\n restrictedEquipment: RESTRICTED_EQUIPMENT,\n feats: FEAT_RENAME_MAP(),\n },\n utils: utils,\n CONSTANTS,\n };\n}\n","import { CompendiumSelector } from \"../app/CompendiumSelector.js\";\nimport CONSTANTS from \"../constants.js\";\n\nasync function resetSettings() {\n for (const [name, data] of Object.entries(CONSTANTS.GET_DEFAULT_SETTINGS())) {\n // eslint-disable-next-line no-await-in-loop\n await game.settings.set(CONSTANTS.MODULE_NAME, name, data.default);\n }\n window.location.reload();\n}\n\nclass ResetSettingsDialog extends FormApplication {\n constructor(...args) {\n super(...args);\n // eslint-disable-next-line no-constructor-return\n return new Dialog({\n title: game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Dialogs.ResetSettings.Title`),\n content: `<p class=\"${CONSTANTS.FLAG_NAME}-dialog-important\">${game.i18n.localize(\n `${CONSTANTS.FLAG_NAME}.Dialogs.ResetSettings.Content`\n )}</p>`,\n buttons: {\n confirm: {\n icon: '<i class=\"fas fa-check\"></i>',\n label: game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Dialogs.ResetSettings.Confirm`),\n callback: () => {\n resetSettings();\n },\n },\n cancel: {\n icon: '<i class=\"fas fa-times\"></i>',\n label: game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Dialogs.ResetSettings.Cancel`),\n },\n },\n default: \"cancel\",\n });\n }\n}\n\nexport function registerSettings() {\n game.settings.registerMenu(CONSTANTS.MODULE_NAME, \"resetToDefaults\", {\n name: `${CONSTANTS.FLAG_NAME}.Settings.Reset.Title`,\n label: `${CONSTANTS.FLAG_NAME}.Settings.Reset.Label`,\n hint: `${CONSTANTS.FLAG_NAME}.Settings.Reset.Hint`,\n icon: \"fas fa-refresh\",\n type: ResetSettingsDialog,\n restricted: true,\n });\n\n for (const [name, data] of Object.entries(CONSTANTS.GET_DEFAULT_SETTINGS())) {\n game.settings.register(CONSTANTS.MODULE_NAME, name, data);\n }\n\n game.settings.registerMenu(CONSTANTS.MODULE_NAME, \"selectCustomCompendiums\", {\n name: `${CONSTANTS.FLAG_NAME}.Settings.UseCustomCompendiumMappings.Title`,\n label: `${CONSTANTS.FLAG_NAME}.Settings.UseCustomCompendiumMappings.Label`,\n hint: `${CONSTANTS.FLAG_NAME}.Settings.UseCustomCompendiumMappings.Hint`,\n icon: \"fas fa-book\",\n type: CompendiumSelector,\n restricted: true,\n });\n\n}\n","import { PathmuncherImporter } from \"../app/PathmuncherImporter.js\";\nimport CONSTANTS from \"../constants.js\";\nimport utils from \"../utils.js\";\n\nexport function registerSheetButton() {\n\n const trustedUsersOnly = utils.setting(\"RESTRICT_TO_TRUSTED\");\n if (trustedUsersOnly && !game.user.isTrusted) return;\n\n /**\n * Character sheets\n */\n const pcSheetNames = Object.values(CONFIG.Actor.sheetClasses.character)\n .map((sheetClass) => sheetClass.cls)\n .map((sheet) => sheet.name);\n\n pcSheetNames.forEach((sheetName) => {\n Hooks.on(\"render\" + sheetName, (app, html, data) => {\n // only for GMs or the owner of this character\n if (!data.owner || !data.actor) return;\n\n const button = $(`<a class=\"pathmuncher-open\" title=\"${CONSTANTS.MODULE_FULL_NAME}\"><i class=\"fas fa-hat-wizard\"></i> ${CONSTANTS.MODULE_FULL_NAME}</a>`);\n\n button.click(() => {\n if (game.user.can(\"ACTOR_CREATE\")) {\n const muncher = new PathmuncherImporter(PathmuncherImporter.defaultOptions, data.actor);\n muncher.render(true);\n } else {\n ui.notifications.warn(game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Notifications.CreateActorPermission`), { permanent: true });\n }\n });\n\n html.closest('.app').find('.pathmuncher-open').remove();\n let titleElement = html.closest('.app').find('.window-title');\n if (!app._minimized) button.insertAfter(titleElement);\n });\n });\n\n}\n","import { registerAPI } from \"./hooks/api.js\";\nimport { registerSettings } from \"./hooks/settings.js\";\nimport { registerSheetButton } from \"./hooks/sheets.js\";\n\nHooks.once(\"init\", () => {\n registerSettings();\n});\n\nHooks.once(\"ready\", () => {\n registerSheetButton();\n registerAPI();\n});\n"],"names":[],"sourceRoot":""}
|