Performance and 0.9.0 prep (#24)
* significant performance improvements * added notes to change log * spelling mistake 1 * spelling mistake 2features_update
parent
71d9fd7584
commit
ef024fbb89
|
@ -41,6 +41,11 @@
|
||||||
0.4.5b Show compendium source in results issue#11
|
0.4.5b Show compendium source in results issue#11
|
||||||
Try showing compendium in the image mouseover
|
Try showing compendium in the image mouseover
|
||||||
12-Jun-2021 0.5.0 Test for Foundry 0.8.x in which creature type is now data.details.type.value
|
12-Jun-2021 0.5.0 Test for Foundry 0.8.x in which creature type is now data.details.type.value
|
||||||
|
9-Spt-2021 CHANGES Removed functions that are disabled in Foundry 0.9.0
|
||||||
|
Speed up on spells by using queries
|
||||||
|
Stops already in progress searches if a new one is started
|
||||||
|
Handles monster types from older revisions
|
||||||
|
Uses some built-ins for minor performance improvement
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const CMPBrowser = {
|
const CMPBrowser = {
|
||||||
|
@ -49,6 +54,8 @@ const CMPBrowser = {
|
||||||
MAXLOAD : 500, //Default for the maximum number to load before displaying a message that you need to filter to see more
|
MAXLOAD : 500, //Default for the maximum number to load before displaying a message that you need to filter to see more
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const STOP_SEARCH = 'StopSearchException';
|
||||||
|
|
||||||
class CompendiumBrowser extends Application {
|
class CompendiumBrowser extends Application {
|
||||||
|
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
|
@ -149,7 +156,7 @@ class CompendiumBrowser extends Application {
|
||||||
let itemId = $(ev.currentTarget).parents("li").attr("data-entry-id");
|
let itemId = $(ev.currentTarget).parents("li").attr("data-entry-id");
|
||||||
let compendium = $(ev.currentTarget).parents("li").attr("data-entry-compendium");
|
let compendium = $(ev.currentTarget).parents("li").attr("data-entry-compendium");
|
||||||
let pack = game.packs.find(p => p.collection === compendium);
|
let pack = game.packs.find(p => p.collection === compendium);
|
||||||
pack.getEntity(itemId).then(entity => {
|
pack.getDocument(itemId).then(entity => {
|
||||||
entity.sheet.render(true);
|
entity.sheet.render(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -469,6 +476,10 @@ class CompendiumBrowser extends Application {
|
||||||
console.time("loadAndFilterItems");
|
console.time("loadAndFilterItems");
|
||||||
await this.checkListsLoaded();
|
await this.checkListsLoaded();
|
||||||
|
|
||||||
|
const seachNumber = Date.now();
|
||||||
|
|
||||||
|
this.CurrentSeachNumber = seachNumber;
|
||||||
|
|
||||||
const maxLoad = game.settings.get(CMPBrowser.MODULE_NAME, "maxload") ?? CMPBrowser.MAXLOAD;
|
const maxLoad = game.settings.get(CMPBrowser.MODULE_NAME, "maxload") ?? CMPBrowser.MAXLOAD;
|
||||||
|
|
||||||
//0.4.1: Load and filter just one of spells, feats, and items (specified by browserTab)
|
//0.4.1: Load and filter just one of spells, feats, and items (specified by browserTab)
|
||||||
|
@ -476,72 +487,124 @@ class CompendiumBrowser extends Application {
|
||||||
let numItemsLoaded = 0;
|
let numItemsLoaded = 0;
|
||||||
let compactItems = {};
|
let compactItems = {};
|
||||||
|
|
||||||
|
try{
|
||||||
//Filter the full list, but only save the core compendium information + displayed info
|
//Filter the full list, but only save the core compendium information + displayed info
|
||||||
for (let pack of game.packs) {
|
for (let pack of game.packs) {
|
||||||
if (pack['metadata']['entity'] === "Item" && this.settings.loadedSpellCompendium[pack.collection].load) {
|
if (pack['metadata']['entity'] === "Item" && this.settings.loadedSpellCompendium[pack.collection].load) {
|
||||||
|
//can query just for spells since there is only 1 type
|
||||||
|
let query = {};
|
||||||
|
if (browserTab === "spell"){
|
||||||
|
query = {type: "spell"};
|
||||||
|
}
|
||||||
|
|
||||||
//FIXME: How much could we do with the loaded index rather than all content?
|
//FIXME: How much could we do with the loaded index rather than all content?
|
||||||
//OR filter the content up front for the decoratedItem.type??
|
//OR filter the content up front for the decoratedItem.type??
|
||||||
await pack.getContent().then(content => {
|
await pack.getDocuments(query).then(content => {
|
||||||
for (let item5e of content) {
|
|
||||||
let compactItem = null;
|
if (browserTab == "spell"){
|
||||||
|
|
||||||
|
content.reduce(function(itemsList, item5e){
|
||||||
|
if (this.CurrentSeachNumber != seachNumber) throw STOP_SEARCH;
|
||||||
|
|
||||||
|
numItemsLoaded = Object.keys(itemsList).length;
|
||||||
|
|
||||||
|
if (maxLoad <= numItemsLoaded) {
|
||||||
|
if (updateLoading) {updateLoading(numItemsLoaded);}
|
||||||
|
throw STOP_SEARCH;
|
||||||
|
}
|
||||||
|
|
||||||
const decoratedItem = this.decorateItem(item5e);
|
const decoratedItem = this.decorateItem(item5e);
|
||||||
if (decoratedItem) {
|
|
||||||
switch (browserTab) {
|
if(decoratedItem && this.passesFilter(decoratedItem, this.spellFilters.activeFilters)){
|
||||||
case "spell":
|
itemsList[item5e.id] = {
|
||||||
if ((decoratedItem.type === "spell") && this.passesFilter(decoratedItem, this.spellFilters.activeFilters)) {
|
|
||||||
compactItem = {
|
|
||||||
compendium : pack.collection,
|
compendium : pack.collection,
|
||||||
name : decoratedItem.name,
|
name : decoratedItem.name,
|
||||||
img: decoratedItem.img,
|
img: decoratedItem.img,
|
||||||
data : {
|
data : {
|
||||||
level : decoratedItem.data?.level,
|
level : decoratedItem.data?.level,
|
||||||
components : decoratedItem.data?.components
|
components : decoratedItem.data?.components
|
||||||
|
},
|
||||||
|
id: item5e.id
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "feat":
|
return itemsList;
|
||||||
if (["feat","class"].includes(decoratedItem.type) && this.passesFilter(decoratedItem, this.featFilters.activeFilters)) {
|
}.bind(this), compactItems);
|
||||||
compactItem = {
|
|
||||||
|
}
|
||||||
|
else if(browserTab == "feat"){
|
||||||
|
|
||||||
|
content.reduce(function(itemsList, item5e){
|
||||||
|
if (this.CurrentSeachNumber != seachNumber) throw STOP_SEARCH;
|
||||||
|
|
||||||
|
numItemsLoaded = Object.keys(itemsList).length;
|
||||||
|
|
||||||
|
if (maxLoad <= numItemsLoaded) {
|
||||||
|
if (updateLoading) {updateLoading(numItemsLoaded);}
|
||||||
|
throw STOP_SEARCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
const decoratedItem = this.decorateItem(item5e);
|
||||||
|
|
||||||
|
if(decoratedItem && ["feat","class"].includes(decoratedItem.type) && this.passesFilter(decoratedItem, this.featFilters.activeFilters)){
|
||||||
|
itemsList[item5e.id] = {
|
||||||
compendium : pack.collection,
|
compendium : pack.collection,
|
||||||
name : decoratedItem.name,
|
name : decoratedItem.name,
|
||||||
img: decoratedItem.img,
|
img: decoratedItem.img,
|
||||||
classRequirementString : decoratedItem.classRequirementString
|
classRequirementString : decoratedItem.classRequirementString
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "item":
|
return itemsList;
|
||||||
//0.4.5: Itm type for true items could be many things (weapon, consumable, etc) so we just look for everything except spells, feats, classes
|
}.bind(this), compactItems);
|
||||||
if (!["spell","feat","class"].includes(decoratedItem.type) && this.passesFilter(decoratedItem, this.itemFilters.activeFilters)) {
|
|
||||||
compactItem = {
|
}
|
||||||
|
else if(browserTab == "item"){
|
||||||
|
|
||||||
|
content.reduce(function(itemsList, item5e){
|
||||||
|
if (this.CurrentSeachNumber != seachNumber) throw STOP_SEARCH;
|
||||||
|
|
||||||
|
numItemsLoaded = Object.keys(itemsList).length;
|
||||||
|
|
||||||
|
if (maxLoad <= numItemsLoaded) {
|
||||||
|
if (updateLoading) {updateLoading(numItemsLoaded);}
|
||||||
|
throw STOP_SEARCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
const decoratedItem = this.decorateItem(item5e);
|
||||||
|
|
||||||
|
if(decoratedItem && !["spell","feat","class"].includes(decoratedItem.type) && this.passesFilter(decoratedItem, this.itemFilters.activeFilters)){
|
||||||
|
itemsList[item5e.id] = {
|
||||||
compendium : pack.collection,
|
compendium : pack.collection,
|
||||||
name : decoratedItem.name,
|
name : decoratedItem.name,
|
||||||
img: decoratedItem.img,
|
img: decoratedItem.img,
|
||||||
type : decoratedItem.type
|
type : decoratedItem.type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
return itemsList;
|
||||||
break;
|
}.bind(this), compactItems);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compactItem) { //Indicates it passed the filters
|
numItemsLoaded = Object.keys(compactItems).length;
|
||||||
compactItems[decoratedItem._id] = compactItem;
|
|
||||||
if (numItemsLoaded++ >= maxLoad) break;
|
|
||||||
//0.4.2e: Update the UI (e.g. "Loading 142 spells")
|
|
||||||
if (updateLoading) {updateLoading(numItemsLoaded);}
|
if (updateLoading) {updateLoading(numItemsLoaded);}
|
||||||
}
|
|
||||||
}
|
|
||||||
}//for item5e of content
|
|
||||||
});
|
});
|
||||||
}//end if pack entity === Item
|
}//end if pack entity === Item
|
||||||
if (numItemsLoaded >= maxLoad) break;
|
|
||||||
}//for packs
|
}//for packs
|
||||||
|
}
|
||||||
|
catch(e){
|
||||||
|
if (e === STOP_SEARCH){
|
||||||
|
//stopping search early
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this.removeDuplicates(compactItems);
|
||||||
/*
|
/*
|
||||||
|
|
||||||
if (unfoundSpells !== '') {
|
if (unfoundSpells !== '') {
|
||||||
console.log(`Load and Fliter Items | List of Spells that don't have a class associated to them:`);
|
console.log(`Load and Fliter Items | List of Spells that don't have a class associated to them:`);
|
||||||
console.log(unfoundSpells);
|
console.log(unfoundSpells);
|
||||||
|
@ -553,150 +616,12 @@ class CompendiumBrowser extends Application {
|
||||||
return compactItems;
|
return compactItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadItems(numToPreload=CMPBrowser.PRELOAD) {
|
|
||||||
console.log('Item Browser | Started loading items');
|
|
||||||
console.time("loadItems");
|
|
||||||
await this.checkListsLoaded();
|
|
||||||
|
|
||||||
this.itemsLoaded = false;
|
|
||||||
|
|
||||||
|
|
||||||
let unfoundSpells = '';
|
|
||||||
let numSpellsLoaded = 0;
|
|
||||||
let numFeatsLoaded = 0;
|
|
||||||
let numItemsLoaded = 0;
|
|
||||||
let items = {
|
|
||||||
spells: {},
|
|
||||||
feats: {},
|
|
||||||
items: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
for (let pack of game.packs) {
|
|
||||||
if (pack['metadata']['entity'] === "Item" && this.settings.loadedSpellCompendium[pack.collection].load) {
|
|
||||||
await pack.getContent().then(content => {
|
|
||||||
for (let item5e of content) {
|
|
||||||
let item = item5e.data;
|
|
||||||
if (item.type === 'spell') {
|
|
||||||
//0.4.1 Only preload a limited number and fill more in as needed
|
|
||||||
if (numSpellsLoaded++ > numToPreload) continue;
|
|
||||||
|
|
||||||
item.compendium = pack.collection;
|
|
||||||
|
|
||||||
// determining classes that can use the spell
|
|
||||||
let cleanSpellName = item.name.toLowerCase().replace(/[^一-龠ぁ-ゔァ-ヴーa-zA-Z0-9a-zA-Z0-9々〆〤]/g, '').replace("'", '').replace(/ /g, '');
|
|
||||||
//let cleanSpellName = spell.name.toLowerCase().replace(/[^a-zA-Z0-9\s:]/g, '').replace("'", '').replace(/ /g, '');
|
|
||||||
if (this.classList[cleanSpellName]) {
|
|
||||||
let classes = this.classList[cleanSpellName];
|
|
||||||
item.data.classes = classes.split(',');
|
|
||||||
} else {
|
|
||||||
unfoundSpells += cleanSpellName + ',';
|
|
||||||
}
|
|
||||||
|
|
||||||
// getting damage types
|
|
||||||
item.damageTypes = [];
|
|
||||||
if (item.data.damage && item.data.damage.parts.length > 0) {
|
|
||||||
for (let part of item.data.damage.parts) {
|
|
||||||
let type = part[1];
|
|
||||||
if (item.damageTypes.indexOf(type) === -1) {
|
|
||||||
item.damageTypes.push(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
items.spells[(item._id)] = item;
|
|
||||||
} else if (item.type === 'feat' || item.type === 'class') {
|
|
||||||
//0.4.1 Only preload a limited number and fill more in as needed
|
|
||||||
if (numFeatsLoaded++ > numToPreload) continue;
|
|
||||||
|
|
||||||
item.compendium = pack.collection;
|
|
||||||
// getting damage types
|
|
||||||
item.damageTypes = [];
|
|
||||||
if (item.data.damage && item.data.damage.parts.length > 0) {
|
|
||||||
for (let part of item.data.damage.parts) {
|
|
||||||
let type = part[1];
|
|
||||||
if (item.damageTypes.indexOf(type) === -1) {
|
|
||||||
item.damageTypes.push(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getting class
|
|
||||||
let reqString = item.data.requirements?.replace(/[0-9]/g, '').trim();
|
|
||||||
let matchedClass = [];
|
|
||||||
for (let c in this.subClasses) {
|
|
||||||
if (reqString && reqString.toLowerCase().indexOf(c) !== -1) {
|
|
||||||
matchedClass.push(c);
|
|
||||||
} else {
|
|
||||||
for (let subClass of this.subClasses[c]) {
|
|
||||||
if (reqString && reqString.indexOf(subClass) !== -1) {
|
|
||||||
matchedClass.push(c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
item.classRequirement = matchedClass;
|
|
||||||
item.classRequirementString = matchedClass.join(', ');
|
|
||||||
|
|
||||||
// getting uses/ressources status
|
|
||||||
item.usesRessources = item5e.hasLimitedUses;
|
|
||||||
|
|
||||||
item.hasSave = item5e.hasSave;
|
|
||||||
|
|
||||||
items.feats[(item._id)] = item;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
//0.4.1 Only preload a limited number and fill more in as needed
|
|
||||||
if (numItemsLoaded++ > numToPreload) continue;
|
|
||||||
|
|
||||||
item.compendium = pack.collection;
|
|
||||||
// getting damage types
|
|
||||||
item.damageTypes = [];
|
|
||||||
if (item.data.damage && item.data.damage.parts.size > 0) {
|
|
||||||
for (let part of item.data.damage.parts) {
|
|
||||||
let type = part[1];
|
|
||||||
if (item.damageTypes.indexOf(type) === -1) {
|
|
||||||
item.damageTypes.push(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getting pack
|
|
||||||
let matchedPacks = [];
|
|
||||||
for (let pack of Object.keys(this.packList)) {
|
|
||||||
for (let packItem of this.packList[pack]) {
|
|
||||||
if (item.name.toLowerCase() === packItem.toLowerCase()) {
|
|
||||||
matchedPacks.push(pack);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
item.matchedPacks = matchedPacks;
|
|
||||||
item.matchedPacksString = matchedPacks.join(', ');
|
|
||||||
|
|
||||||
// getting uses/ressources status
|
|
||||||
item.usesRessources = item5e.hasLimitedUses
|
|
||||||
|
|
||||||
items.items[(item._id)] = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
}//for item5e of content
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if ((numSpellsLoaded >= numToPreload) && (numFeatsLoaded >= numToPreload) && (numItemsLoaded >= numToPreload)) break;
|
|
||||||
}//for packs
|
|
||||||
if (unfoundSpells !== '') {
|
|
||||||
console.log(`Item Browser | List of Spells that don't have a class associated to them:`);
|
|
||||||
console.log(unfoundSpells);
|
|
||||||
}
|
|
||||||
this.itemsLoaded = true;
|
|
||||||
console.timeEnd("loadItems");
|
|
||||||
console.log(`Item Browser | Finished loading items: ${Object.keys(items.spells).length} spells, ${Object.keys(items.feats).length} features, ${Object.keys(items.items).length} items `);
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
async loadAndFilterNpcs(updateLoading=null) {
|
async loadAndFilterNpcs(updateLoading=null) {
|
||||||
console.log('NPC Browser | Started loading NPCs');
|
console.log('NPC Browser | Started loading NPCs');
|
||||||
|
|
||||||
|
const seachNumber = Date.now();
|
||||||
|
this.CurrentSeachNumber = seachNumber;
|
||||||
|
|
||||||
console.time("loadAndFilterNpcs");
|
console.time("loadAndFilterNpcs");
|
||||||
let npcs = {};
|
let npcs = {};
|
||||||
|
|
||||||
|
@ -704,38 +629,57 @@ class CompendiumBrowser extends Application {
|
||||||
|
|
||||||
let numNpcsLoaded = 0;
|
let numNpcsLoaded = 0;
|
||||||
this.npcsLoaded = false;
|
this.npcsLoaded = false;
|
||||||
|
|
||||||
|
try{
|
||||||
for (let pack of game.packs) {
|
for (let pack of game.packs) {
|
||||||
if (pack['metadata']['entity'] == "Actor" && this.settings.loadedNpcCompendium[pack.collection].load) {
|
if (pack['metadata']['entity'] == "Actor" && this.settings.loadedNpcCompendium[pack.collection].load) {
|
||||||
await pack.getContent().then(async content => {
|
await pack.getDocuments().then(async content => {
|
||||||
|
|
||||||
|
content.reduce(function(actorsList, npc5e){
|
||||||
|
if (this.CurrentSeachNumber != seachNumber) {throw STOP_SEARCH;}
|
||||||
|
|
||||||
|
numNpcsLoaded = Object.keys(npcs).length;
|
||||||
|
|
||||||
|
if (maxLoad <= numNpcsLoaded) {
|
||||||
|
if (updateLoading) {updateLoading(numNpcsLoaded);}
|
||||||
|
throw STOP_SEARCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
const decoratedNpc = this.decorateNpc(npc5e);
|
||||||
|
|
||||||
for (let npc of content) {
|
|
||||||
let compactNpc = null;
|
|
||||||
const decoratedNpc = this.decorateNpc(npc);
|
|
||||||
if (decoratedNpc && this.passesFilter(decoratedNpc, this.npcFilters.activeFilters)){
|
if (decoratedNpc && this.passesFilter(decoratedNpc, this.npcFilters.activeFilters)){
|
||||||
//0.4.2: Don't store all the details - just the display elements
|
|
||||||
compactNpc = {
|
actorsList[npc5e.id] = {
|
||||||
compendium : pack.collection,
|
compendium : pack.collection,
|
||||||
name : decoratedNpc.name,
|
name : decoratedNpc.name,
|
||||||
img: decoratedNpc.img,
|
img: decoratedNpc.img,
|
||||||
displayCR : decoratedNpc.displayCR,
|
displayCR : decoratedNpc.displayCR,
|
||||||
displaySize : decoratedNpc.displaySize,
|
displaySize : decoratedNpc.displaySize,
|
||||||
displayType: decoratedNpc.data?.details?.type,
|
displayType: this.getNPCType(decoratedNpc.data?.details?.type),
|
||||||
orderCR : decoratedNpc.data.details.cr,
|
orderCR : decoratedNpc.data.details.cr,
|
||||||
orderSize : decoratedNpc.filterSize
|
orderSize : decoratedNpc.filterSize
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (compactNpc) {
|
|
||||||
npcs[decoratedNpc._id] = compactNpc;
|
return actorsList;
|
||||||
//0.4.2 Don't load more than maxLoad; display a message to filter
|
}.bind(this), npcs);
|
||||||
if (numNpcsLoaded++ > maxLoad) break;
|
|
||||||
//0.4.2e: Update the UI (e.g. "Loading 142 NPCs")
|
numNpcsLoaded = Object.keys(npcs).length;
|
||||||
if (updateLoading) {updateLoading(numNpcsLoaded);}
|
if (updateLoading) {updateLoading(numNpcsLoaded);}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//0.4.1 Only preload a limited number and fill more in as needed
|
//0.4.1 Only preload a limited number and fill more in as needed
|
||||||
if (numNpcsLoaded >= maxLoad) break;
|
}
|
||||||
|
}
|
||||||
|
catch(e){
|
||||||
|
if (e == STOP_SEARCH){
|
||||||
|
//breaking out
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
console.timeEnd("loadAndFilterNpcs");
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.npcsLoaded = true;
|
this.npcsLoaded = true;
|
||||||
|
@ -1119,9 +1063,22 @@ class CompendiumBrowser extends Application {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//handle poorly constructed npc
|
||||||
|
if (decoratedNpc.data?.details?.type && !(decoratedNpc.data?.details?.type instanceof Object)){
|
||||||
|
decoratedNpc.data.details.type = {value: decoratedNpc.data?.details?.type};
|
||||||
|
}
|
||||||
|
|
||||||
return decoratedNpc;
|
return decoratedNpc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getNPCType(type){
|
||||||
|
if (type instanceof Object){
|
||||||
|
return type.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
filterElements(list, subjects, filters) {
|
filterElements(list, subjects, filters) {
|
||||||
for (let element of list) {
|
for (let element of list) {
|
||||||
let subject = subjects[element.dataset.entryId];
|
let subject = subjects[element.dataset.entryId];
|
||||||
|
@ -1189,6 +1146,29 @@ class CompendiumBrowser extends Application {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//incomplete removal of duplicate items
|
||||||
|
removeDuplicates(spellList){
|
||||||
|
//sort at n log n
|
||||||
|
let sortedList = Object.values(spellList).sort((a, b) => a.name.localeCompare(b.name));
|
||||||
|
|
||||||
|
//search through sorted list for duplicates
|
||||||
|
for (let index = 0; index < sortedList.length - 1;){
|
||||||
|
|
||||||
|
//all duplicates will be next to eachother
|
||||||
|
if (sortedList[index].name == sortedList[index + 1].name){
|
||||||
|
//duplicate something is getting removed
|
||||||
|
//TODO choose what to remove rather then the second
|
||||||
|
let remove = index + 1;
|
||||||
|
|
||||||
|
delete spellList[sortedList[remove].id];
|
||||||
|
sortedList.splice(remove, 1);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clearObject(obj) {
|
clearObject(obj) {
|
||||||
let newObj = {};
|
let newObj = {};
|
||||||
for (let key in obj) {
|
for (let key in obj) {
|
||||||
|
|
Loading…
Reference in New Issue