Skip to content

Commit

Permalink
Merge pull request #10109 from DestinyItemManager/bg-opt-search-query
Browse files Browse the repository at this point in the history
  • Loading branch information
robojumper authored Nov 17, 2023
2 parents a2208f6 + 486311d commit 7350986
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 32 deletions.
6 changes: 3 additions & 3 deletions config/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -866,9 +866,9 @@
"Name": "Wrong Stat Tiers",
"Description": "Loadout Optimizer settings for this Loadout specify stat tiers, but the Loadout does not reach them."
},
"LoadoutHasSearchQuery": {
"Name": "Has Search Query",
"Description": "This loadout was created with a search query in Loadout Optimizer."
"InvalidSearchQuery": {
"Name": "Invalid Search Query",
"Description": "This loadout was created with a search query in Loadout Optimizer that is no longer valid, or does not include the armor in this loadout."
}
},
"Manifest": {
Expand Down
17 changes: 7 additions & 10 deletions src/app/loadout-analyzer/analysis.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { armorStats } from 'app/search/d2-known-values';
import { BucketHashes, StatHashes } from 'data/d2/generated-enums';
import { normalToReducedMod } from 'data/d2/reduced-cost-mod-mappings';
import { produce } from 'immer';
import _ from 'lodash';
import _, { stubTrue } from 'lodash';
import {
DestinyClass,
DestinyProfileResponse,
Expand Down Expand Up @@ -93,6 +93,9 @@ beforeAll(async () => {
},
autoModDefs: getAutoMods(defs, unlockedPlugs),
unlockedPlugs,
// No idea how to test this
filterFactory: () => stubTrue,
validateQuery: () => ({ valid: true }),
};
});

Expand Down Expand Up @@ -158,16 +161,10 @@ describe('basic loadout analysis finding tests', () => {
expect(resultsWithEmptyFragmentSlots.findings).not.toContain(LoadoutFinding.TooManyFragments);
});

it('finds HasSearchQuery', async () => {
it('finds InvalidSearchQuery', async () => {
const results = await analyze(equippedLoadout);
expect(results.findings).not.toContain(LoadoutFinding.LoadoutHasSearchQuery);

const loadoutWithParameters: Loadout = {
...equippedLoadout,
parameters: { ...equippedLoadout.parameters, query: '-is:inloadout' },
};
const results2 = await analyze(loadoutWithParameters);
expect(results2.findings).toContain(LoadoutFinding.LoadoutHasSearchQuery);
expect(results.findings).not.toContain(LoadoutFinding.InvalidSearchQuery);
// FIXME more tests
});

it('finds UsesSeasonalMods/ModsDontFit', async () => {
Expand Down
29 changes: 26 additions & 3 deletions src/app/loadout-analyzer/analysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { isLoadoutBuilderItem } from 'app/loadout/item-utils';
import { ModMap, categorizeArmorMods, fitMostMods } from 'app/loadout/mod-assignment-utils';
import { getTotalModStatChanges } from 'app/loadout/stats';
import { MAX_ARMOR_ENERGY_CAPACITY } from 'app/search/d2-known-values';
import { ItemFilter } from 'app/search/filter-types';
import { count } from 'app/utils/collections';
import { errorLog } from 'app/utils/log';
import { delay } from 'app/utils/promises';
Expand All @@ -53,6 +54,8 @@ export async function analyzeLoadout(
savedLoStatConstraintsByClass,
itemCreationContext,
unlockedPlugs,
validateQuery,
filterFactory,
}: LoadoutAnalysisContext,
storeId: string,
classType: DestinyClass,
Expand Down Expand Up @@ -177,9 +180,15 @@ export async function analyzeLoadout(
// We just did some heavy mod assignment stuff, give the event loop a chance
await delay(0);

let itemFilter: ItemFilter;
if (loadoutParameters.query) {
findings.add(LoadoutFinding.LoadoutHasSearchQuery);
if (validateQuery(loadoutParameters.query).valid) {
itemFilter = filterFactory(loadoutParameters.query);
} else {
findings.add(LoadoutFinding.InvalidSearchQuery);
}
}
itemFilter ??= stubTrue;

if (loadoutArmor.length === 5) {
const statProblems = getStatProblems(
Expand Down Expand Up @@ -245,9 +254,23 @@ export async function analyzeLoadout(
unassignedMods: [],
lockedExoticHash: loadoutParameters.exoticArmorHash,
armorEnergyRules,
// We also reject loadouts with a search filter
searchFilter: stubTrue,
searchFilter: itemFilter,
});
// If the item filter loadout armor that was previously included,
// this is due to the search filter since we've previously established
// that mods fit and the exotic matches.
if (
loadoutParameters.query &&
loadoutArmor.some(
(item) =>
armorForThisClass.some((allItem) => allItem === item) &&
!Object.values(filteredItems)
.flat()
.some((filteredItem) => filteredItem === item),
)
) {
findings.add(LoadoutFinding.InvalidSearchQuery);
}

const modStatChanges = getTotalModStatChanges(
defs,
Expand Down
8 changes: 4 additions & 4 deletions src/app/loadout-analyzer/finding-display.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ export const findingDisplays: Record<LoadoutFinding, FindingDisplay> = {
description: tl('LoadoutAnalysis.DoesNotSatisfyStatConstraints.Description'),
icon: infoIcon,
},
[LoadoutFinding.LoadoutHasSearchQuery]: {
name: tl('LoadoutAnalysis.LoadoutHasSearchQuery.Name'),
description: tl('LoadoutAnalysis.LoadoutHasSearchQuery.Description'),
icon: undefined,
[LoadoutFinding.InvalidSearchQuery]: {
name: tl('LoadoutAnalysis.InvalidSearchQuery.Name'),
description: tl('LoadoutAnalysis.InvalidSearchQuery.Description'),
icon: faExclamationTriangle,
},
};
7 changes: 7 additions & 0 deletions src/app/loadout-analyzer/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { loVendorItemsSelector } from 'app/loadout-builder/loadout-builder-vendo
import { getAutoMods } from 'app/loadout-builder/process/mappers';
import { Loadout } from 'app/loadout-drawer/loadout-types';
import { d2ManifestSelector } from 'app/manifest/selectors';
import { filterFactorySelector, validateQuerySelector } from 'app/search/search-filter';
import { currySelector } from 'app/utils/selectors';
import { useLoadVendors } from 'app/vendors/hooks';
import { noop } from 'lodash';
Expand Down Expand Up @@ -47,13 +48,17 @@ const autoOptimizationContextSelector = currySelector(
autoModSelector,
allItemsSelector,
loVendorItemsSelector.selector,
filterFactorySelector,
validateQuerySelector,
(
itemCreationContext,
unlockedPlugs,
savedLoStatConstraintsByClass,
autoModDefs,
inventoryItems,
vendorItems,
filterFactory,
validateQuery,
) => {
const allItems = inventoryItems.concat(vendorItems);
return (
Expand All @@ -65,6 +70,8 @@ const autoOptimizationContextSelector = currySelector(
savedLoStatConstraintsByClass,
autoModDefs,
allItems,
filterFactory,
validateQuery,
} satisfies LoadoutAnalysisContext)
);
},
Expand Down
2 changes: 1 addition & 1 deletion src/app/loadout-analyzer/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ export class LoadoutBackgroundAnalyzer {
[LoadoutFinding.ModsDontFit]: new Set(),
[LoadoutFinding.UsesSeasonalMods]: new Set(),
[LoadoutFinding.DoesNotSatisfyStatConstraints]: new Set(),
[LoadoutFinding.LoadoutHasSearchQuery]: new Set(),
[LoadoutFinding.InvalidSearchQuery]: new Set(),
},
};

Expand Down
13 changes: 5 additions & 8 deletions src/app/loadout-analyzer/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { LoadoutParameters, Settings } from '@destinyitemmanager/dim-api-types';
import { DimItem } from 'app/inventory/item-types';
import { ItemCreationContext } from 'app/inventory/store/d2-item-factory';
import { AutoModDefs, ResolvedStatConstraint } from 'app/loadout-builder/types';
import { ItemFilter } from 'app/search/filter-types';

/** The analysis results for a single loadout. */
export interface LoadoutAnalysisResult {
Expand Down Expand Up @@ -61,21 +62,15 @@ export const enum LoadoutFinding {
ModsDontFit,
/** The armor set does not match the saved stat constraints. */
DoesNotSatisfyStatConstraints,
/**
* The loadout has a search query which complicates analysis.
* Maybe we could but it's difficult and probably a niche case.
* But whether an item matches a query can change often (tags, or
* imagine creating a Loadout from `-is:inloadout` items...)
*/
LoadoutHasSearchQuery,
/** The loadout parameters search query is invalid or the items don't match them */
InvalidSearchQuery,
}

/** These aren't problems per se but they do block further analysis */
export const blockAnalysisFindings: LoadoutFinding[] = [
LoadoutFinding.NotAFullArmorSet,
LoadoutFinding.ModsDontFit,
LoadoutFinding.DoesNotRespectExotic,
LoadoutFinding.LoadoutHasSearchQuery,
];

/**
Expand All @@ -88,4 +83,6 @@ export interface LoadoutAnalysisContext {
savedLoStatConstraintsByClass: Settings['loStatConstraintsByClass'];
allItems: DimItem[];
autoModDefs: AutoModDefs;
validateQuery: (query: string) => { valid: boolean };
filterFactory: (query: string) => ItemFilter;
}
6 changes: 3 additions & 3 deletions src/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -583,9 +583,9 @@
"Description": "Some mods in this loadout are deprecated or do not otherwise fit into any of your armor pieces.",
"Name": "Deprecated Mods"
},
"LoadoutHasSearchQuery": {
"Description": "This loadout was created with a search query in Loadout Optimizer.",
"Name": "Has Search Query"
"InvalidSearchQuery": {
"Description": "This loadout was created with a search query in Loadout Optimizer that is no longer valid, or does not include the armor in this loadout.",
"Name": "Invalid Search Query"
},
"MissingItems": {
"Description": "Some of the items in this loadout are no longer in your inventory.",
Expand Down

0 comments on commit 7350986

Please sign in to comment.