Refactored InsuranceController for Better Attachment Handling

Made several improvements to the `InsuranceController` to ensure a more reliable and logical handling of insured items and their attachments.

- Updates `parentAttachmentsMap` declaration to `let` for mutability, enabling dynamic updates during processing.
- Updates `parentAttachmentsMap` to initially include all attachments (including attachments that should not be in-raid moddable).
- Updates `processRegularItems` logic to include `parentAttachmentsMap` in its parameters and logic. Now better ensures that attachments are correctly identified and processed alongside their parent items.
- Adds `removeNonModdableAttachments` method to filter out non-moddable attachments from processing.
- Updates deletion logic to better handle cases where items, such as armour vests and their non-removable plates, are processed to prevent orphaned items post-deletion.

Resolves #401
This commit is contained in:
Refringe 2024-02-07 01:16:46 -05:00
parent 2aa0054833
commit ebbc3e2029
No known key found for this signature in database
GPG Key ID: 64E03E5F892C6F9E

View File

@ -183,7 +183,7 @@ export class InsuranceController
// Populate a Map object of items for quick lookup by their ID and use it to populate a Map of main-parent items // Populate a Map object of items for quick lookup by their ID and use it to populate a Map of main-parent items
// and each of their attachments. For example, a gun mapped to each of its attachments. // and each of their attachments. For example, a gun mapped to each of its attachments.
const itemsMap = this.populateItemsMap(insured); const itemsMap = this.populateItemsMap(insured);
const parentAttachmentsMap = this.populateParentAttachmentsMap(insured, itemsMap); let parentAttachmentsMap = this.populateParentAttachmentsMap(insured, itemsMap);
// Check to see if any regular items are present. // Check to see if any regular items are present.
const hasRegularItems = Array.from(itemsMap.values()).some((item) => const hasRegularItems = Array.from(itemsMap.values()).some((item) =>
@ -193,12 +193,16 @@ export class InsuranceController
// Process all items that are not attached, attachments. Those are handled separately, by value. // Process all items that are not attached, attachments. Those are handled separately, by value.
if (hasRegularItems) if (hasRegularItems)
{ {
this.processRegularItems(insured, toDelete); this.processRegularItems(insured, toDelete, parentAttachmentsMap);
} }
// Process attached, attachments, by value, only if there are any. // Process attached, attachments, by value, only if there are any.
if (parentAttachmentsMap.size > 0) if (parentAttachmentsMap.size > 0)
{ {
// Remove attachments that can not be moddable in-raid from the parentAttachmentsMap. We only want to
// process moddable attachments from here on out.
parentAttachmentsMap = this.removeNonModdableAttachments(parentAttachmentsMap, itemsMap);
this.processAttachments(parentAttachmentsMap, itemsMap, insured.traderId, toDelete); this.processAttachments(parentAttachmentsMap, itemsMap, insured.traderId, toDelete);
} }
@ -256,9 +260,12 @@ export class InsuranceController
// Check if this is an attachment currently attached to its parent. // Check if this is an attachment currently attached to its parent.
if (this.itemHelper.isAttachmentAttached(insuredItem)) if (this.itemHelper.isAttachmentAttached(insuredItem))
{ {
// Filter out items not in the database or not raid moddable. // Make sure the template for the item exists.
if (!this.itemHelper.isRaidModdable(insuredItem, parentItem)) if (!this.itemHelper.getItem(insuredItem._tpl)[0])
{ {
this.logger.warning(
`Could not find insured attachment in the database - ID: ${insuredItem._id}, Template: ${insuredItem._tpl}`,
);
continue; continue;
} }
@ -287,6 +294,42 @@ export class InsuranceController
return mainParentToAttachmentsMap; return mainParentToAttachmentsMap;
} }
/**
* Remove attachments that can not be moddable in-raid from the parentAttachmentsMap. If no moddable attachments
* remain, the parent is removed from the map as well.
*
* @param parentAttachmentsMap - A Map object containing parent item IDs to arrays of their attachment items.
* @param itemsMap - A Map object for quick item look-up by item ID.
* @returns A Map object containing parent item IDs to arrays of their attachment items which are not moddable in-raid.
*/
protected removeNonModdableAttachments(
parentAttachmentsMap: Map<string, Item[]>,
itemsMap: Map<string, Item>,
): Map<string, Item[]>
{
const updatedMap = new Map<string, Item[]>();
for (const [parentId, attachmentItems] of parentAttachmentsMap)
{
const parentItem = itemsMap.get(parentId);
const moddableAttachments = [];
for (const attachment of attachmentItems)
{
if (this.itemHelper.isRaidModdable(attachment, parentItem))
{
moddableAttachments.push(attachment);
}
}
// Only set the parentId and its attachments in the updatedMap if there are moddable attachments.
if (moddableAttachments.length > 0)
{
updatedMap.set(parentId, moddableAttachments);
}
}
return updatedMap;
}
/** /**
* Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular"
* item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so,
@ -294,9 +337,14 @@ export class InsuranceController
* *
* @param insured The insurance object containing the items to evaluate. * @param insured The insurance object containing the items to evaluate.
* @param toDelete A Set to keep track of items marked for deletion. * @param toDelete A Set to keep track of items marked for deletion.
* @param parentAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items.
* @returns void * @returns void
*/ */
protected processRegularItems(insured: Insurance, toDelete: Set<string>): void protected processRegularItems(
insured: Insurance,
toDelete: Set<string>,
parentAttachmentsMap: Map<string, Item[]>,
): void
{ {
for (const insuredItem of insured.items) for (const insuredItem of insured.items)
{ {
@ -306,28 +354,32 @@ export class InsuranceController
continue; continue;
} }
// Check if the item has any children
const itemAndChildren = this.itemHelper.findAndReturnChildrenAsItems(insured.items, insuredItem._id);
// Roll for item deletion // Roll for item deletion
const itemRoll = this.rollForDelete(insured.traderId, insuredItem); const itemRoll = this.rollForDelete(insured.traderId, insuredItem);
if (itemRoll) if (itemRoll)
{ {
// Mark the item for deletion // Check to see if this item is a parent in the parentAttachmentsMap. If so, do a look-up for *all* of
toDelete.add(insuredItem._id); // its children and mark them for deletion as well. Additionally remove the parent (and its children)
// from the parentAttachmentsMap so that it's children are not rolled for later in the process.
// Check if the item has any children and mark those for deletion as well, but only if those if (parentAttachmentsMap.has(insuredItem._id))
// children are currently attached attachments.
const directChildren = insured.items.filter((item) => item.parentId === insuredItem._id);
const allChildrenAreAttachments = directChildren.every((child) =>
this.itemHelper.isAttachmentAttached(child)
);
if (allChildrenAreAttachments)
{ {
// This call will also return the parent item itself, queueing it for deletion as well.
const itemAndChildren = this.itemHelper.findAndReturnChildrenAsItems(
insured.items,
insuredItem._id,
);
for (const item of itemAndChildren) for (const item of itemAndChildren)
{ {
toDelete.add(item._id); toDelete.add(item._id);
} }
// Remove the parent (and its children) from the parentAttachmentsMap.
parentAttachmentsMap.delete(insuredItem._id);
}
else
{
// This item doesn't have any children. Simply mark it for deletion.
toDelete.add(insuredItem._id);
} }
} }
} }
@ -377,7 +429,7 @@ export class InsuranceController
this.logAttachmentsDetails(sortedAttachments); this.logAttachmentsDetails(sortedAttachments);
const successfulRolls = this.countSuccessfulRolls(sortedAttachments, traderId); const successfulRolls = this.countSuccessfulRolls(sortedAttachments, traderId);
this.logger.debug(`Number of successful rolls: ${successfulRolls}`); this.logger.debug(`Number of deletion rolls: ${successfulRolls}`);
this.attachmentDeletionByValue(sortedAttachments, successfulRolls, toDelete); this.attachmentDeletionByValue(sortedAttachments, successfulRolls, toDelete);
} }