chore: simplify rngService (#1073)

getRandomWeightedReward now takes any object with lowercase 'rarity', and the only alternative to it is the 'uc' variant which takes any object with uppercase 'Rarity'
usage of IRngResult is now also optional

Reviewed-on: OpenWF/SpaceNinjaServer#1073
Co-authored-by: Sainan <sainan@calamity.inc>
Co-committed-by: Sainan <sainan@calamity.inc>
This commit is contained in:
Sainan 2025-03-03 12:48:46 -08:00 committed by OrdisPrime
parent 67a275a009
commit f3f1bfc890
5 changed files with 18 additions and 39 deletions

View File

@ -3,7 +3,7 @@ import { IRivenChallenge } from "@/src/helpers/rivenFingerprintHelper";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { addMods, getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { getRandomElement, getRandomInt, getRandomReward, IRngResult } from "@/src/services/rngService";
import { getRandomElement, getRandomInt, getRandomReward } from "@/src/services/rngService";
import { logger } from "@/src/utils/logger";
import { RequestHandler } from "express";
import { ExportUpgrades } from "warframe-public-export-plus";
@ -26,15 +26,14 @@ export const activateRandomModController: RequestHandler = async (req, res) => {
Required: getRandomInt(challenge.countRange[0], challenge.countRange[1])
};
if (Math.random() < challenge.complicationChance) {
const complicationsAsRngResults: IRngResult[] = [];
const complications: { type: string; probability: number }[] = [];
for (const complication of challenge.complications) {
complicationsAsRngResults.push({
complications.push({
type: complication.fullName,
itemCount: 1,
probability: complication.weight
});
}
fingerprintChallenge.Complication = getRandomReward(complicationsAsRngResults)!.type;
fingerprintChallenge.Complication = getRandomReward(complications)!.type;
logger.debug(
`riven rolled challenge ${fingerprintChallenge.Type} with complication ${fingerprintChallenge.Complication}`
);

View File

@ -2,7 +2,7 @@ import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
import { config } from "@/src/services/configService";
import { addMiscItems, getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { getRandomInt, getRandomWeightedReward3 } from "@/src/services/rngService";
import { getRandomInt, getRandomWeightedRewardUc } from "@/src/services/rngService";
import { IMongoDate, IOid } from "@/src/types/commonTypes";
import { IDroneClient } from "@/src/types/inventoryTypes/inventoryTypes";
import { IInventoryChanges } from "@/src/types/purchaseTypes";
@ -56,7 +56,7 @@ export const dronesController: RequestHandler = async (req, res) => {
Math.random() < system.damageChance
? getRandomInt(system.droneDamage.minValue, system.droneDamage.maxValue)
: 0;
const resource = getRandomWeightedReward3(system.resources, droneMeta.probabilities)!;
const resource = getRandomWeightedRewardUc(system.resources, droneMeta.probabilities)!;
//logger.debug(`drone rolled`, resource);
drone.ResourceType = "/Lotus/" + resource.StoreItem.substring(18);
const resourceMeta = ExportResources[drone.ResourceType];

View File

@ -1,7 +1,7 @@
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
import { IVoidTearParticipantInfo } from "@/src/types/requestTypes";
import { ExportRelics, ExportRewards, TRarity } from "warframe-public-export-plus";
import { getRandomWeightedReward2, IRngResult } from "@/src/services/rngService";
import { getRandomWeightedReward, IRngResult } from "@/src/services/rngService";
import { logger } from "@/src/utils/logger";
import { addMiscItems } from "@/src/services/inventoryService";
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
@ -13,7 +13,7 @@ export const crackRelic = async (
const relic = ExportRelics[participant.VoidProjection];
const weights = refinementToWeights[relic.quality];
logger.debug(`opening a relic of quality ${relic.quality}; rarity weights are`, weights);
const reward = getRandomWeightedReward2(
const reward = getRandomWeightedReward(
ExportRewards[relic.rewardManifest][0] as { type: string; itemCount: number; rarity: TRarity }[], // rarity is nullable in PE+ typings, but always present for relics
weights
)!;

View File

@ -8,7 +8,7 @@ import {
updateCurrency,
updateSlots
} from "@/src/services/inventoryService";
import { getRandomWeightedReward } from "@/src/services/rngService";
import { getRandomWeightedRewardUc } from "@/src/services/rngService";
import { getVendorManifestByOid } from "@/src/services/serversideVendorsService";
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
import { IPurchaseRequest, IPurchaseResponse, SlotPurchase, IInventoryChanges } from "@/src/types/purchaseTypes";
@ -325,14 +325,14 @@ const handleBoosterPackPurchase = async (
};
for (let i = 0; i != quantity; ++i) {
for (const weights of pack.rarityWeightsPerRoll) {
const result = getRandomWeightedReward(pack.components, weights);
const result = getRandomWeightedRewardUc(pack.components, weights);
if (result) {
logger.debug(`booster pack rolled`, result);
purchaseResponse.BoosterPackItems +=
result.type.split("/Lotus/").join("/Lotus/StoreItems/") + ',{"lvl":0};';
result.Item.split("/Lotus/").join("/Lotus/StoreItems/") + ',{"lvl":0};';
combineInventoryChanges(
purchaseResponse.InventoryChanges,
(await addItem(inventory, result.type, result.itemCount)).InventoryChanges
(await addItem(inventory, result.Item, 1)).InventoryChanges
);
}
}

View File

@ -34,45 +34,25 @@ export const getRandomReward = <T extends { probability: number }>(pool: T[]): T
throw new Error("What the fuck?");
};
export const getRandomWeightedReward = (
pool: { Item: string; Rarity: TRarity }[],
export const getRandomWeightedReward = <T extends { rarity: TRarity }>(
pool: T[],
weights: Record<TRarity, number>
): IRngResult | undefined => {
const resultPool: IRngResult[] = [];
const rarityCounts: Record<TRarity, number> = { COMMON: 0, UNCOMMON: 0, RARE: 0, LEGENDARY: 0 };
for (const entry of pool) {
++rarityCounts[entry.Rarity];
}
for (const entry of pool) {
resultPool.push({
type: entry.Item,
itemCount: 1,
probability: weights[entry.Rarity] / rarityCounts[entry.Rarity]
});
}
return getRandomReward(resultPool);
};
export const getRandomWeightedReward2 = (
pool: { type: string; itemCount: number; rarity: TRarity }[],
weights: Record<TRarity, number>
): IRngResult | undefined => {
const resultPool: IRngResult[] = [];
): (T & { probability: number }) | undefined => {
const resultPool: (T & { probability: number })[] = [];
const rarityCounts: Record<TRarity, number> = { COMMON: 0, UNCOMMON: 0, RARE: 0, LEGENDARY: 0 };
for (const entry of pool) {
++rarityCounts[entry.rarity];
}
for (const entry of pool) {
resultPool.push({
type: entry.type,
itemCount: entry.itemCount,
...entry,
probability: weights[entry.rarity] / rarityCounts[entry.rarity]
});
}
return getRandomReward(resultPool);
};
export const getRandomWeightedReward3 = <T extends { Rarity: TRarity }>(
export const getRandomWeightedRewardUc = <T extends { Rarity: TRarity }>(
pool: T[],
weights: Record<TRarity, number>
): (T & { probability: number }) | undefined => {