From 8541e5f028646458490c7a4afec632139ba7367f Mon Sep 17 00:00:00 2001 From: Refringe Date: Tue, 24 Oct 2023 09:27:46 +0000 Subject: [PATCH] Refactor Currency Handling in `PaymentService.payMoney()` Method (!159) This commit includes a series of changes aimed at improving the logic and readability of the `payMoney` method in the PaymentService class. The method is pivotal for handling in-game payments, specifically in cases involving multiple types of currencies and barter trades. The changes resolve an issue that prevented barter payments that included both a currency and another item. ## Changes: - Replaced `barterPrice` variable with a `currencyAmounts` mapping that efficiently tracks each type of currency involved in the trade. - Updated how the `costOfPurchaseInCurrency` variable is calculated to factor in multiple currencies. - Introduced a new variable `totalCurrencyAmount` to sum up the total amount of all currencies, which is checked to determine whether any (non)currency payment is necessary. - Added some inline comments for readability. Resolves #176 Co-authored-by: Refringe Reviewed-on: https://dev.sp-tarkov.com/SPT-AKI/Server/pulls/159 Co-authored-by: Refringe Co-committed-by: Refringe --- project/src/services/PaymentService.ts | 64 +++++++++++++++----------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/project/src/services/PaymentService.ts b/project/src/services/PaymentService.ts index a02fc845..09e022c6 100644 --- a/project/src/services/PaymentService.ts +++ b/project/src/services/PaymentService.ts @@ -42,62 +42,72 @@ export class PaymentService public payMoney(pmcData: IPmcData, request: IProcessBuyTradeRequestData, sessionID: string, output: IItemEventRouterResponse): IItemEventRouterResponse { const trader = this.traderHelper.getTrader(request.tid, sessionID); - let currencyTpl = this.paymentHelper.getCurrency(trader.currency); - // Delete barter items(not money) from inventory + // Track the amounts of each type of currency involved in the trade. + const currencyAmounts: { [key: string]: number } = {}; + + // Delete barter items and track currencies if the action is "TradingConfirm". if (request.Action === "TradingConfirm") { for (const index in request.scheme_items) { + // Find the corresponding item in the player's inventory. const item = pmcData.Inventory.items.find(i => i._id === request.scheme_items[index].id); if (item !== undefined) { if (!this.paymentHelper.isMoneyTpl(item._tpl)) { + // If the item is not money, remove it from the inventory. output = this.inventoryHelper.removeItem(pmcData, item._id, sessionID, output); request.scheme_items[index].count = 0; } else { - currencyTpl = item._tpl; - break; + // If the item is money, add its count to the currencyAmounts object. + currencyAmounts[item._tpl] = (currencyAmounts[item._tpl] || 0) + request.scheme_items[index].count; } } } } - // prepare a price for barter - let barterPrice = 0; - barterPrice = request.scheme_items.reduce((accumulator, item) => accumulator + item.count, 0); + // Track the total amount of all currencies. + let totalCurrencyAmount = 0; - // Nothing to do here, since we dont need to pay money. - if (barterPrice === 0) + // Loop through each type of currency involved in the trade. + for (const currencyTpl in currencyAmounts) { - this.logger.debug(this.localisationService.getText("payment-zero_price_no_payment")); - } + const currencyAmount = currencyAmounts[currencyTpl]; + totalCurrencyAmount += currencyAmount; - // Only perform if paying with currency (not barters) - if (barterPrice > 0) - { - output = this.addPaymentToOutput(pmcData, currencyTpl, barterPrice, sessionID, output); - if (output.warnings.length > 0) + if (currencyAmount > 0) { - // Something failed - return output; + output = this.addPaymentToOutput(pmcData, currencyTpl, currencyAmount, sessionID, output); + + // If there are warnings, exit early. + if (output.warnings.length > 0) + { + return output; + } + + // Convert the amount to the trader's currency and update the sales sum. + const costOfPurchaseInCurrency = this.handbookHelper.fromRUB(this.handbookHelper.inRUB(currencyAmount, currencyTpl), this.paymentHelper.getCurrency(trader.currency)); + pmcData.TradersInfo[request.tid].salesSum += costOfPurchaseInCurrency; } } - // set current sale sum - // convert barterPrice itemTpl into RUB then convert RUB into trader currency - const costOfPurchaseInCurrency = (barterPrice === 0) - ? this.handbookHelper.fromRUB(this.getTraderItemHandbookPriceRouble(request.item_id, request.tid), this.paymentHelper.getCurrency(trader.currency)) - : this.handbookHelper.fromRUB(this.handbookHelper.inRUB(barterPrice, currencyTpl), this.paymentHelper.getCurrency(trader.currency)); + // If no currency-based payment is involved, handle it separately + if (totalCurrencyAmount === 0) + { + this.logger.debug(this.localisationService.getText("payment-zero_price_no_payment")); + + // Convert the handbook price to the trader's currency and update the sales sum. + const costOfPurchaseInCurrency = this.handbookHelper.fromRUB(this.getTraderItemHandbookPriceRouble(request.item_id, request.tid), this.paymentHelper.getCurrency(trader.currency)); + pmcData.TradersInfo[request.tid].salesSum += costOfPurchaseInCurrency; + } - pmcData.TradersInfo[request.tid].salesSum += costOfPurchaseInCurrency; this.traderHelper.lvlUp(request.tid, pmcData); - - this.logger.debug("Item(s) taken. Status OK."); + this.logger.debug("Item(s) taken. Status OK."); return output; } @@ -369,4 +379,4 @@ export class PaymentService return false; } -} \ No newline at end of file +}