diff --git a/renderer/specs/web/price-check/filters/create-stat-filters.test.ts b/renderer/specs/web/price-check/filters/create-stat-filters.test.ts new file mode 100644 index 00000000..76bea13b --- /dev/null +++ b/renderer/specs/web/price-check/filters/create-stat-filters.test.ts @@ -0,0 +1,120 @@ +import { ItemRarity, ParsedItem } from "@/parser/ParsedItem"; +import { __testExports } from "@/web/price-check/filters/create-stat-filters"; +import { describe, expect, it } from "vitest"; +import { createTestItem } from "@specs/helper"; +import { StatFilterRoll } from "@/web/price-check/filters/interfaces"; + +describe("item mod count tests", () => { + it.each([ + [ItemRarity.Normal, 0], + [ItemRarity.Magic, 1], + [ItemRarity.Rare, 3], + ])("%#. Should return correct base for %s", (rarity, expected) => { + const item: ParsedItem = { + ...createTestItem(), + rarity, + }; + + const res = __testExports.itemMaxModifiersBySlot(item, []); + + expect(res).toEqual([expected * 2, expected, expected]); + }); + + function createTestStatByRef( + ref: string, + roll: number, + ): { statRef: string; roll: StatFilterRoll } { + return { + statRef: ref, + roll: { + value: roll, + } as unknown as StatFilterRoll, + }; + } + + it.each([ + [ItemRarity.Rare, [], 3, 3], + [ItemRarity.Rare, [{ ref: "# to all Attributes", roll: 1 }], 3, 3], + [ItemRarity.Magic, [{ ref: "# Suffix Modifier allowed", roll: 2 }], 1, 3], + [ItemRarity.Magic, [{ ref: "# Prefix Modifier allowed", roll: -1 }], 0, 1], + [ItemRarity.Rare, [{ ref: "# Suffix Modifier allowed", roll: 2 }], 3, 5], + [ItemRarity.Rare, [{ ref: "# Suffix Modifier allowed", roll: 1 }], 3, 4], + [ItemRarity.Rare, [{ ref: "# Suffix Modifier allowed", roll: -1 }], 3, 2], + [ItemRarity.Rare, [{ ref: "# Suffix Modifier allowed", roll: -2 }], 3, 1], + [ItemRarity.Rare, [{ ref: "# Suffix Modifier allowed", roll: -3 }], 3, 0], + [ItemRarity.Rare, [{ ref: "# Prefix Modifier allowed", roll: 2 }], 5, 3], + [ItemRarity.Rare, [{ ref: "# Prefix Modifier allowed", roll: 1 }], 4, 3], + [ItemRarity.Rare, [{ ref: "# Prefix Modifier allowed", roll: -1 }], 2, 3], + [ItemRarity.Rare, [{ ref: "# Prefix Modifier allowed", roll: -2 }], 1, 3], + [ItemRarity.Rare, [{ ref: "# Prefix Modifier allowed", roll: -3 }], 0, 3], + [ + ItemRarity.Rare, + [ + { ref: "# Prefix Modifier allowed", roll: 1 }, + { ref: "# Suffix Modifier allowed", roll: 1 }, + ], + 4, + 4, + ], + [ + ItemRarity.Rare, + [ + { ref: "# Prefix Modifier allowed", roll: 2 }, + { ref: "# Suffix Modifier allowed", roll: -1 }, + ], + 5, + 2, + ], + [ + ItemRarity.Rare, + [ + { ref: "# Prefix Modifier allowed", roll: -1 }, + { ref: "# Suffix Modifier allowed", roll: 2 }, + ], + 2, + 5, + ], + [ + ItemRarity.Rare, + [ + { ref: "# Prefix Modifier allowed", roll: -2 }, + { ref: "# Suffix Modifier allowed", roll: -2 }, + ], + 1, + 1, + ], + [ + ItemRarity.Rare, + [ + { ref: "# Prefix Modifier allowed", roll: -3 }, + { ref: "# Suffix Modifier allowed", roll: 2 }, + ], + 0, + 5, + ], + ])( + "%#. should change amount for items with stats that modify max mods", + ( + rarity: ItemRarity, + stats: Array<{ ref: string; roll: number }>, + expectedPrefix, + expectedSuffix, + ) => { + const item: ParsedItem = { + ...createTestItem(), + rarity, + }; + + const res = __testExports.itemMaxModifiersBySlot( + item, + stats.map((stat) => createTestStatByRef(stat.ref, stat.roll)), + ); + + expect(res).toEqual([ + expectedPrefix + expectedSuffix, + expectedPrefix, + expectedSuffix, + ]); + }, + ); +}); diff --git a/renderer/src/web/price-check/filters/create-stat-filters.ts b/renderer/src/web/price-check/filters/create-stat-filters.ts index 00c02f8c..0a968dea 100644 --- a/renderer/src/web/price-check/filters/create-stat-filters.ts +++ b/renderer/src/web/price-check/filters/create-stat-filters.ts @@ -788,9 +788,6 @@ function hideAllAugments(filters: StatFilter[]) { } } -// TODO -// +1 Prefix Modifier allowed -// -1 Suffix Modifier allowed function showHasEmptyModifier(ctx: FiltersCreationContext): | { empty: ItemHasEmptyModifier; @@ -803,41 +800,12 @@ function showHasEmptyModifier(ctx: FiltersCreationContext): return false; } - if (item.rarity === ItemRarity.Magic) { - const { prefixes: magicPrefixes, suffixes: magicSuffixes } = - explicitModifierCount(item); - if (magicPrefixes && magicSuffixes) { - return false; - } - if (magicPrefixes > 0) { - return { - empty: ItemHasEmptyModifier.Suffix, - counts: { - [ItemHasEmptyModifier.Prefix]: 0, - [ItemHasEmptyModifier.Suffix]: 1, - [ItemHasEmptyModifier.Any]: 1, - }, - }; - } else if (magicSuffixes > 0) { - return { - empty: ItemHasEmptyModifier.Prefix, - counts: { - [ItemHasEmptyModifier.Prefix]: 1, - [ItemHasEmptyModifier.Suffix]: 0, - [ItemHasEmptyModifier.Any]: 1, - }, - }; - } - // magic but has no explicit mods (annulled to 0) - return false; - } - - if (item.rarity !== ItemRarity.Rare) { + if (item.rarity !== ItemRarity.Rare && item.rarity !== ItemRarity.Magic) { return false; } const { prefixes, suffixes, total } = explicitModifierCount(item); - const maxAmount = itemMaxModifiersBySlot(item); + const maxAmount = itemMaxModifiersBySlot(item, ctx.filters); if (total !== maxAmount[ItemHasEmptyModifier.Any] && total !== 0) { const empty = @@ -887,47 +855,66 @@ function enableGoodRolledFilters(filters: StatFilter[], abovePct: number) { } } -function itemMaxModifiersBySlot(item: ParsedItem) { +function itemBaseMaxModifiersOfType( + category: ItemCategory | undefined, + rarity: ItemRarity | undefined, +) { let base; - switch (item.category) { - case ItemCategory.Jewel: - case ItemCategory.Tablet: - case ItemCategory.Relic: - case ItemCategory.SanctumRelic: - base = 2; + switch (rarity) { + case ItemRarity.Normal: + base = 0; break; + case ItemRarity.Magic: + base = 1; + break; + default: - base = 3; + switch (category) { + case ItemCategory.Jewel: + case ItemCategory.Tablet: + case ItemCategory.Relic: + case ItemCategory.SanctumRelic: + base = 2; + break; + default: + base = 3; + break; + } break; } + return base; +} +function itemMaxModifiersBySlot( + item: ParsedItem, + statsAndRolls: Array<{ statRef: string; roll?: StatFilterRoll }>, +) { + const base = itemBaseMaxModifiersOfType(item.category, item.rarity); const maxAmount = [2 * base, base, base]; - // TODO: change this to be programmatic based on implicits - if ( - item.info.refName === "Dusk Amulet" || - item.info.refName === "Dusk Ring" - ) { - maxAmount[ItemHasEmptyModifier.Prefix] += 1; - maxAmount[ItemHasEmptyModifier.Suffix] -= 1; - } else if ( - item.info.refName === "Gloam Amulet" || - item.info.refName === "Gloam Ring" - ) { - maxAmount[ItemHasEmptyModifier.Prefix] -= 1; - maxAmount[ItemHasEmptyModifier.Suffix] += 1; - } else if ( - item.info.refName === "Penumbra Amulet" || - item.info.refName === "Penumbra Ring" - ) { - maxAmount[ItemHasEmptyModifier.Prefix] += 2; - maxAmount[ItemHasEmptyModifier.Suffix] -= 2; - } else if ( - item.info.refName === "Tenebrous Amulet" || - item.info.refName === "Tenebrous Ring" - ) { - maxAmount[ItemHasEmptyModifier.Prefix] -= 2; - maxAmount[ItemHasEmptyModifier.Suffix] += 2; + for (const { statRef, roll } of statsAndRolls) { + if (statRef === "# Prefix Modifier allowed") { + maxAmount[ItemHasEmptyModifier.Prefix] += roll?.value ?? 0; + } else if (statRef === "# Suffix Modifier allowed") { + maxAmount[ItemHasEmptyModifier.Suffix] += roll?.value ?? 0; + } } + if (maxAmount[ItemHasEmptyModifier.Prefix] < 0) { + maxAmount[ItemHasEmptyModifier.Prefix] = 0; + } + if (maxAmount[ItemHasEmptyModifier.Suffix] < 0) { + maxAmount[ItemHasEmptyModifier.Suffix] = 0; + } + + maxAmount[ItemHasEmptyModifier.Any] = + maxAmount[ItemHasEmptyModifier.Prefix] + + maxAmount[ItemHasEmptyModifier.Suffix]; + return maxAmount; } + +// Disable since this is export for tests +// eslint-disable-next-line @typescript-eslint/naming-convention +export const __testExports = { + itemMaxModifiersBySlot, +};