feat: handle costs of recipes

- Resources and credits are deducted when starting a recipe
- Resources and credits are refunded when cancelling the recipe
- The recipe is consumed if it is not reusable
This commit is contained in:
Sainan 2024-06-19 05:17:50 +02:00
parent 7313d35ed9
commit acd0b90256
2 changed files with 39 additions and 46 deletions

View File

@ -7,7 +7,7 @@ import { getRecipe } from "@/src/services/itemDataService";
import { IOid } from "@/src/types/commonTypes"; import { IOid } from "@/src/types/commonTypes";
import { getJSONfromString } from "@/src/helpers/stringHelpers"; import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory, updateCurrency, addItem } from "@/src/services/inventoryService"; import { getInventory, updateCurrency, addItem, addMiscItems, addRecipes } from "@/src/services/inventoryService";
export interface IClaimCompletedRecipeRequest { export interface IClaimCompletedRecipeRequest {
RecipeIds: IOid[]; RecipeIds: IOid[];
@ -44,20 +44,43 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
} }
if (req.query.cancel) { if (req.query.cancel) {
// TODO: Refund items const currencyChanges = await updateCurrency(recipe.buildPrice * -1, false, accountId);
res.json({});
const inventory = await getInventory(accountId);
addMiscItems(inventory, recipe.ingredients);
await inventory.save();
// Not a bug: In the specific case of cancelling a recipe, InventoryChanges are expected to be the root.
res.json({
...currencyChanges,
MiscItems: recipe.ingredients
});
} else { } else {
logger.debug("Claiming Recipe", { recipe, pendingRecipe }); logger.debug("Claiming Recipe", { recipe, pendingRecipe });
let InventoryChanges = {};
if (recipe.consumeOnUse) { if (recipe.consumeOnUse) {
// TODO: Remove one instance of this recipe, and include that in InventoryChanges. const recipeChanges = [
{
ItemType: pendingRecipe.ItemType,
ItemCount: -1
} }
let currencyChanges = {}; ];
if (req.query.rush && recipe.skipBuildTimePrice) {
currencyChanges = await updateCurrency(recipe.skipBuildTimePrice, true, accountId); InventoryChanges = { ...InventoryChanges, Recipes: recipeChanges };
const inventory = await getInventory(accountId);
addRecipes(inventory, recipeChanges);
await inventory.save();
}
if (req.query.rush) {
InventoryChanges = {
...InventoryChanges,
...(await updateCurrency(recipe.skipBuildTimePrice, true, accountId))
};
} }
res.json({ res.json({
InventoryChanges: { InventoryChanges: {
...currencyChanges, ...InventoryChanges,
...(await addItem(accountId, recipe.resultType, recipe.num)).InventoryChanges ...(await addItem(accountId, recipe.resultType, recipe.num)).InventoryChanges
} }
}); });

View File

@ -1,31 +1,9 @@
import { unixTimesInMs } from "@/src/constants/timeConstants"; import { unixTimesInMs } from "@/src/constants/timeConstants";
import { getInventory } from "@/src/services/inventoryService"; import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService";
import { getRecipe } from "@/src/services/itemDataService"; import { getRecipe } from "@/src/services/itemDataService";
import { logger } from "@/src/utils/logger"; import { logger } from "@/src/utils/logger";
import { Types } from "mongoose"; import { Types } from "mongoose";
export interface IResource {
uniqueName: string;
count: number;
}
// export const updateResources = async (accountId: string, components: IResource[]) => {
// const inventory = await getInventory(accountId);
// for (const component of components) {
// const category = getItemCategoryByUniqueName(component.uniqueName) as keyof typeof inventory;
// //validate category
// console.log(component.uniqueName);
// console.log("cate", category);
// const invItem = inventory[category];
// console.log("invItem", invItem);
// inventory["MiscItems"];
// }
// };
export const startRecipe = async (recipeName: string, accountId: string) => { export const startRecipe = async (recipeName: string, accountId: string) => {
const recipe = getRecipe(recipeName); const recipe = getRecipe(recipeName);
@ -34,27 +12,19 @@ export const startRecipe = async (recipeName: string, accountId: string) => {
throw new Error(`unknown recipe ${recipeName}`); throw new Error(`unknown recipe ${recipeName}`);
} }
const componentsNeeded = recipe.ingredients.map(component => ({ await updateCurrency(recipe.buildPrice, false, accountId);
uniqueName: component.ItemType,
count: component.ItemCount const ingredientsInverse = recipe.ingredients.map(component => ({
ItemType: component.ItemType,
ItemCount: component.ItemCount * -1
})); }));
if (!componentsNeeded) { const inventory = await getInventory(accountId);
logger.error(`recipe ${recipeName} has no components`); addMiscItems(inventory, ingredientsInverse);
throw new Error(`recipe ${recipeName} has no components`);
}
//TODO: consume components used
//await updateResources(accountId, componentsNeeded);
if (!recipe.buildTime) {
logger.error(`recipe ${recipeName} has no build time`);
throw new Error(`recipe ${recipeName} has no build time`);
}
//buildtime is in seconds //buildtime is in seconds
const completionDate = new Date(Date.now() + recipe.buildTime * unixTimesInMs.second); const completionDate = new Date(Date.now() + recipe.buildTime * unixTimesInMs.second);
const inventory = await getInventory(accountId);
inventory.PendingRecipes.push({ inventory.PendingRecipes.push({
ItemType: recipeName, ItemType: recipeName,
CompletionDate: completionDate, CompletionDate: completionDate,