chore: simplify rngService #1073

Merged
OrdisPrime merged 1 commits from simplify-rngService into main 2025-03-03 12:48:47 -08:00
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 { getJSONfromString } from "@/src/helpers/stringHelpers";
import { addMods, getInventory } from "@/src/services/inventoryService"; import { addMods, getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService"; 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 { logger } from "@/src/utils/logger";
import { RequestHandler } from "express"; import { RequestHandler } from "express";
import { ExportUpgrades } from "warframe-public-export-plus"; 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]) Required: getRandomInt(challenge.countRange[0], challenge.countRange[1])
}; };
if (Math.random() < challenge.complicationChance) { if (Math.random() < challenge.complicationChance) {
const complicationsAsRngResults: IRngResult[] = []; const complications: { type: string; probability: number }[] = [];
for (const complication of challenge.complications) { for (const complication of challenge.complications) {
complicationsAsRngResults.push({ complications.push({
type: complication.fullName, type: complication.fullName,
itemCount: 1,
probability: complication.weight probability: complication.weight
}); });
} }
fingerprintChallenge.Complication = getRandomReward(complicationsAsRngResults)!.type; fingerprintChallenge.Complication = getRandomReward(complications)!.type;
logger.debug( logger.debug(
`riven rolled challenge ${fingerprintChallenge.Type} with complication ${fingerprintChallenge.Complication}` `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 { config } from "@/src/services/configService";
import { addMiscItems, getInventory } from "@/src/services/inventoryService"; import { addMiscItems, getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService"; 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 { IMongoDate, IOid } from "@/src/types/commonTypes";
import { IDroneClient } from "@/src/types/inventoryTypes/inventoryTypes"; import { IDroneClient } from "@/src/types/inventoryTypes/inventoryTypes";
import { IInventoryChanges } from "@/src/types/purchaseTypes"; import { IInventoryChanges } from "@/src/types/purchaseTypes";
@ -56,7 +56,7 @@ export const dronesController: RequestHandler = async (req, res) => {
Math.random() < system.damageChance Math.random() < system.damageChance
? getRandomInt(system.droneDamage.minValue, system.droneDamage.maxValue) ? getRandomInt(system.droneDamage.minValue, system.droneDamage.maxValue)
: 0; : 0;
const resource = getRandomWeightedReward3(system.resources, droneMeta.probabilities)!; const resource = getRandomWeightedRewardUc(system.resources, droneMeta.probabilities)!;
//logger.debug(`drone rolled`, resource); //logger.debug(`drone rolled`, resource);
drone.ResourceType = "/Lotus/" + resource.StoreItem.substring(18); drone.ResourceType = "/Lotus/" + resource.StoreItem.substring(18);
const resourceMeta = ExportResources[drone.ResourceType]; const resourceMeta = ExportResources[drone.ResourceType];

View File

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

View File

@ -8,7 +8,7 @@ import {
updateCurrency, updateCurrency,
updateSlots updateSlots
} from "@/src/services/inventoryService"; } from "@/src/services/inventoryService";
import { getRandomWeightedReward } from "@/src/services/rngService"; import { getRandomWeightedRewardUc } from "@/src/services/rngService";
import { getVendorManifestByOid } from "@/src/services/serversideVendorsService"; import { getVendorManifestByOid } from "@/src/services/serversideVendorsService";
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes"; import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
import { IPurchaseRequest, IPurchaseResponse, SlotPurchase, IInventoryChanges } from "@/src/types/purchaseTypes"; import { IPurchaseRequest, IPurchaseResponse, SlotPurchase, IInventoryChanges } from "@/src/types/purchaseTypes";
@ -325,14 +325,14 @@ const handleBoosterPackPurchase = async (
}; };
for (let i = 0; i != quantity; ++i) { for (let i = 0; i != quantity; ++i) {
for (const weights of pack.rarityWeightsPerRoll) { for (const weights of pack.rarityWeightsPerRoll) {
const result = getRandomWeightedReward(pack.components, weights); const result = getRandomWeightedRewardUc(pack.components, weights);
if (result) { if (result) {
logger.debug(`booster pack rolled`, result); logger.debug(`booster pack rolled`, result);
purchaseResponse.BoosterPackItems += purchaseResponse.BoosterPackItems +=
result.type.split("/Lotus/").join("/Lotus/StoreItems/") + ',{"lvl":0};'; result.Item.split("/Lotus/").join("/Lotus/StoreItems/") + ',{"lvl":0};';
combineInventoryChanges( combineInventoryChanges(
purchaseResponse.InventoryChanges, 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?"); throw new Error("What the fuck?");
}; };
export const getRandomWeightedReward = ( export const getRandomWeightedReward = <T extends { rarity: TRarity }>(
pool: { Item: string; Rarity: TRarity }[], pool: T[],
weights: Record<TRarity, number> weights: Record<TRarity, number>
): IRngResult | undefined => { ): (T & { probability: number }) | undefined => {
const resultPool: IRngResult[] = []; 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.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[] = [];
const rarityCounts: Record<TRarity, number> = { COMMON: 0, UNCOMMON: 0, RARE: 0, LEGENDARY: 0 }; const rarityCounts: Record<TRarity, number> = { COMMON: 0, UNCOMMON: 0, RARE: 0, LEGENDARY: 0 };
for (const entry of pool) { for (const entry of pool) {
++rarityCounts[entry.rarity]; ++rarityCounts[entry.rarity];
} }
for (const entry of pool) { for (const entry of pool) {
resultPool.push({ resultPool.push({
type: entry.type, ...entry,
itemCount: entry.itemCount,
probability: weights[entry.rarity] / rarityCounts[entry.rarity] probability: weights[entry.rarity] / rarityCounts[entry.rarity]
}); });
} }
return getRandomReward(resultPool); return getRandomReward(resultPool);
}; };
export const getRandomWeightedReward3 = <T extends { Rarity: TRarity }>( export const getRandomWeightedRewardUc = <T extends { Rarity: TRarity }>(
pool: T[], pool: T[],
weights: Record<TRarity, number> weights: Record<TRarity, number>
): (T & { probability: number }) | undefined => { ): (T & { probability: number }) | undefined => {