From 706a4ec77e250ae4fa1c515a5a1066419ad71067 Mon Sep 17 00:00:00 2001 From: Shebuka Date: Wed, 19 Jun 2024 14:26:39 +0200 Subject: [PATCH 1/9] Better Interchange svg bounds --- src/data/maps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/maps.json b/src/data/maps.json index a780c2cf..538eb0e5 100644 --- a/src/data/maps.json +++ b/src/data/maps.json @@ -965,8 +965,8 @@ "transform": [0.265, 150.6, 0.265, 134.6], "coordinateRotation": 180, "bounds": [ - [530, -439], - [-364, 452] + [532.75, -442.75], + [-364, 453.5] ], "author": "Tarkov.dev", "authorLink": "https://tarkov.dev", From 4bcd1b20e7a0c83805d9cfdaaf724d12c5d0fea9 Mon Sep 17 00:00:00 2001 From: Shebuka Date: Wed, 19 Jun 2024 18:59:52 +0200 Subject: [PATCH 2/9] Fixing getCheapestCashPrice to be able to get 'none' when you can't sell item to anyone --- src/modules/format-cost-items.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/modules/format-cost-items.js b/src/modules/format-cost-items.js index 391d23d8..3941d89a 100644 --- a/src/modules/format-cost-items.js +++ b/src/modules/format-cost-items.js @@ -23,18 +23,23 @@ function getCheapestCashPrice(item, settings = {}, allowAllSources = false) { }); if (!buySource || buySource.length === 0) { let sellToTrader = item.sellFor.filter(sellFor => { - if (sellFor.vendor.normalizedName === 'flea-market') return false; - if (!allowAllSources && sellFor.vendor.normalizedName === 'jaeger' && !settings.jaeger) return false; + if (sellFor.vendor.normalizedName === 'flea-market') + return false; + if (!allowAllSources && sellFor.vendor.normalizedName === 'jaeger' && !settings.jaeger) + return false; return true; }); + let sourceType = 'cash-sell'; if (sellToTrader.length > 1) { sellToTrader = sellToTrader.reduce((prev, current) => { return prev.priceRUB > current.priceRUB ? prev : current; }, {priceRUB: 0}); - } else { + } else if (sellToTrader.length === 1) { sellToTrader = sellToTrader[0]; + } else { + sourceType = 'none'; } - return {...sellToTrader, type: 'cash-sell', pricePerUnit: sellToTrader?.priceRUB}; + return {...sellToTrader, type: sourceType, pricePerUnit: sellToTrader?.priceRUB}; } else { if (buySource.length > 1) { buySource = buySource.reduce((prev, current) => { From 5daca91225f56c4b5cfcd105c74ad2b01150b260 Mon Sep 17 00:00:00 2001 From: Shebuka Date: Wed, 19 Jun 2024 19:00:07 +0200 Subject: [PATCH 3/9] Refactoring --- src/pages/item/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/item/index.js b/src/pages/item/index.js index c9c0ca8d..54cb24cc 100644 --- a/src/pages/item/index.js +++ b/src/pages/item/index.js @@ -122,7 +122,7 @@ function Item() { const { data: quests } = useQuestsData(); - const {data: maps } = useMapsData(); + const { data: maps } = useMapsData(); const currentItemData = useMemo(() => { let item = items.find(i => i.normalizedName === itemName); From ab1e4dcf1a0f788eb697f32b2228a2c8b42a63ca Mon Sep 17 00:00:00 2001 From: Shebuka Date: Wed, 19 Jun 2024 19:00:44 +0200 Subject: [PATCH 4/9] Allow item cost to have no vendor --- src/components/item-cost/index.js | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/components/item-cost/index.js b/src/components/item-cost/index.js index 0c9cffa2..3a785411 100644 --- a/src/components/item-cost/index.js +++ b/src/components/item-cost/index.js @@ -22,7 +22,7 @@ function ItemCost({ itemId, count, price = 0, - vendor = {name: 'Flea Market', normalizedName: 'flea-market'}, + vendor = {name: 'N/A', normalizedName: 'unknown'}, priceType = 'cash', priceDetails, isTool, @@ -51,14 +51,17 @@ function ItemCost({ let { displayPrice, tooltip, displayImage} = useMemo(() => { let displayPrice = ''; let tooltip = false; - let displayImage = ( - {vendor.name} - ); + let displayImage = ''; + if (vendor.normalizedName !== 'unknown') { + displayImage = ( + {vendor.name} + ); + } if (priceType === 'cached') { displayPrice = count; displayImage = ( From 3e83a45b7ddf6bf967b049c71d53dde9dfa80da5 Mon Sep 17 00:00:00 2001 From: Shebuka Date: Wed, 19 Jun 2024 19:12:43 +0200 Subject: [PATCH 5/9] Fix sort for costItem when comparing two GP Coin as sosts; More consistent sort for instaProfit with secondary sort for savings; Using normalizedName to filter out dogtags; If we have an ammo container let's look inside to calculate the reward item value; Calculating the GP Coin value based on the reward item value; --- src/components/barters-table/index.js | 87 ++++++++++++++++++++------- 1 file changed, 65 insertions(+), 22 deletions(-) diff --git a/src/components/barters-table/index.js b/src/components/barters-table/index.js index 1be876c3..76f8def3 100644 --- a/src/components/barters-table/index.js +++ b/src/components/barters-table/index.js @@ -5,16 +5,21 @@ import { Link } from 'react-router-dom'; import 'tippy.js/dist/tippy.css'; // optional import DataTable from '../../components/data-table/index.js'; + import useBartersData from '../../features/barters/index.js'; import useCraftsData from '../../features/crafts/index.js'; +import useItemsData from '../../features/items/index.js'; import { selectAllTraders } from '../../features/settings/settingsSlice.js'; + import ValueCell from '../value-cell/index.js'; import CostItemsCell from '../cost-items-cell/index.js'; -import { formatCostItems, getCheapestCashPrice, getCheapestBarter } from '../../modules/format-cost-items.js'; import RewardCell from '../reward-cell/index.js'; -import { isAnyDogtag, isBothDogtags } from '../../modules/dogtags.js'; + import FleaMarketLoadingIcon from '../FleaMarketLoadingIcon.jsx'; +import { formatCostItems, getCheapestCashPrice, getCheapestBarter } from '../../modules/format-cost-items.js'; +import { isAnyDogtag, isBothDogtags } from '../../modules/dogtags.js'; + import './index.css'; function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBarterIngredients, useCraftIngredients }) { @@ -28,6 +33,7 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart const { data: barters } = useBartersData(); const { data: crafts } = useCraftsData(); + const { data: items } = useItemsData(); const columns = useMemo( () => [ @@ -43,6 +49,19 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart Header: t('Cost'), id: 'costItems', accessor: 'costItems', + sortType: (a, b, columnId, desc) => { + if (a.values.costItems[0].id === '5d235b4d86f7742e017bc88a' && a.values.costItems[0].id === '5d235b4d86f7742e017bc88a') { + const aGPCost = a.values.costItems[0].price || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); + const bGPCost = b.values.costItems[0].price || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); + + return aGPCost - bGPCost; + } + + const aCost = a.values.cost || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); + const bCost = b.values.cost || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); + + return aCost - bCost; + }, Cell: ({ value }) => { return ; }, @@ -67,10 +86,10 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart id: 'savings', accessor: (d) => Number(d.savings), sortType: (a, b, columnId, desc) => { - const aSell = a.values.savings || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); - const bSell = b.values.savings || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); + const aSave = a.values.savings || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); + const bSave = b.values.savings || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); - return aSell - bSell; + return aSave - bSave; }, Cell: (props) => { if (props.row.original.cached) { @@ -87,7 +106,18 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart Header: t('InstaProfit'), id: 'instaProfit', accessor: 'instaProfit', - sortType: 'basic', + sortType: (a, b, columnId, desc) => { + const aProf = a.values.instaProfit || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); + const bProf = b.values.instaProfit || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); + if (aProf === bProf) { + const aSave = a.values.savings || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); + const bSave = b.values.savings || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); + + return aSave - bSave; + } + + return aProf - bProf; + }, Cell: (props) => { if (props.row.original.cached) { return ( @@ -190,12 +220,7 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart continue; } - if ( - requiredItem.item.name - .toLowerCase() - .replace(/\s/g, '') - .includes('dogtag') - ) { + if (requiredItem.item.normalizedName.includes('dogtag')) { setSkippedBySettings(true); return false; } @@ -251,8 +276,15 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart costItems.forEach((costItem) => (cost += costItem.pricePerUnit * costItem.count)); const barterRewardItem = barterRow.rewardItems[0].item; + let barterRewardContainedItem; + + if (barterRewardItem.bsgCategoryId === '543be5cb4bdc2deb348b4568') { // "ammo-container" + barterRewardContainedItem = items.find(i => i.id === barterRewardItem.containsItems[0]?.item.id); + } - const bestSellTo = barterRewardItem.sellFor.reduce( + const whatWeSell = barterRewardContainedItem ? barterRewardContainedItem : barterRewardItem; + const howManyWeSell = barterRewardContainedItem ? barterRewardItem.containsItems[0].count : barterRow.rewardItems[0].count; + const bestSellTo = whatWeSell.sellFor.reduce( (previousSellFor, currentSellFor) => { if (currentSellFor.vendor.normalizedName === 'flea-market') { return previousSellFor; @@ -274,15 +306,23 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart }, ); + if (isNaN(cost) && costItems.length === 1 && costItems[0].id === '5d235b4d86f7742e017bc88a') { // "gp-coin" + cost = bestSellTo.priceRUB * howManyWeSell; + const GPCoinPrice = cost / costItems[0].count; + costItems[0].price = GPCoinPrice; + costItems[0].priceRUB = GPCoinPrice; + costItems[0].pricePerUnit = GPCoinPrice; + } + const tradeData = { costItems: costItems, cost: cost, - instaProfit: (bestSellTo.priceRUB * barterRow.rewardItems[0].count) - cost, + instaProfit: (bestSellTo.priceRUB * howManyWeSell) - cost, instaProfitSource: bestSellTo, instaProfitDetails: [ { name: bestSellTo.vendor.name, - value: bestSellTo.priceRUB * barterRow.rewardItems[0].count, + value: bestSellTo.priceRUB * howManyWeSell, }, { name: t('Barter cost'), @@ -291,13 +331,13 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart ], reward: { item: barterRewardItem, + count: barterRow.rewardItems[0].count, source: `${barterRow.trader.name} ${t('LL{{level}}', { level: barterRow.level })}`, sellTo: bestSellTo.vendor.name, sellToNormalized: bestSellTo.vendor.normalizedName, sellValue: bestSellTo.priceRUB, taskUnlock: barterRow.taskUnlock, isFIR: false, - count: barterRow.rewardItems[0].count, }, cached: barterRow.cached || barterRewardItem.cached, }; @@ -306,13 +346,15 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart tradeData.reward.sellValue = barterRewardItem.priceCustom; tradeData.reward.sellType = 'custom'; } - - //tradeData.reward.sellTo = t(tradeData.reward.sellTo) + + if (barterRewardItem.bsgCategoryId === '543be5cb4bdc2deb348b4568') { // "ammo-container" + tradeData.reward.sellNote = t('Unpacked'); + } tradeData.savingsParts = []; const cheapestPrice = getCheapestCashPrice(barterRewardItem, settings, showAll); const cheapestBarter = getCheapestBarter(barterRewardItem, {barters, crafts: useCraftIngredients ? crafts : false, settings, allowAllSources: showAll}); - if (cheapestPrice.type === 'cash-sell'){ + if (cheapestPrice.type === 'cash-sell') { //this item cannot be purchased for cash if (cheapestBarter) { if (cheapestBarter.priceRUB !== cost) { @@ -323,7 +365,7 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart } tradeData.savings = cheapestBarter.priceRUB - cost; } - } else { + } else if (cheapestPrice.type !== 'none') { // savings based on cheapest cash price let sellerName = cheapestPrice.vendor.name; if (cheapestPrice.vendor.minTraderLevel) { @@ -333,12 +375,12 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart name: sellerName, value: cheapestPrice.priceRUB, }); - tradeData.savings = cheapestPrice.priceRUB - Math.round(cost / barterRow.rewardItems[0].count); + tradeData.savings = cheapestPrice.priceRUB - Math.round(cost / howManyWeSell); } if (tradeData.savingsParts.length > 0) { tradeData.savingsParts.push({ name: t('Barter cost'), - value: Math.round(cost / barterRow.rewardItems[0].count) * -1 + value: Math.round(cost / howManyWeSell) * -1 }); } @@ -374,6 +416,7 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart selectedTrader, barters, crafts, + items, itemFilter, traders, completedQuests, From 26deedb8d535e3e8b8af1302ea281f5d4142f1a2 Mon Sep 17 00:00:00 2001 From: Shebuka Date: Thu, 20 Jun 2024 01:16:34 +0200 Subject: [PATCH 6/9] Refactoring --- scripts/cache-api-data.mjs | 2 +- src/features/items/do-fetch-items.mjs | 2 +- src/pages/quest/index.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/cache-api-data.mjs b/scripts/cache-api-data.mjs index 77b15756..1c98b732 100644 --- a/scripts/cache-api-data.mjs +++ b/scripts/cache-api-data.mjs @@ -177,7 +177,7 @@ try { item.lastLowPrice = 0; item.avg24hPrice = 0; item.buyFor = item.buyFor.filter(buyFor => buyFor.vendor.normalizedName !== 'flea-market'); - item.sellFor = item.sellFor.filter(buyFor => buyFor.vendor.normalizedName !== 'flea-market'); + item.sellFor = item.sellFor.filter(sellFor => sellFor.vendor.normalizedName !== 'flea-market'); item.cached = true; } fs.writeFileSync('./src/data/items.json', JSON.stringify(filteredItems)); diff --git a/src/features/items/do-fetch-items.mjs b/src/features/items/do-fetch-items.mjs index 666df286..50091361 100644 --- a/src/features/items/do-fetch-items.mjs +++ b/src/features/items/do-fetch-items.mjs @@ -627,7 +627,7 @@ class ItemsQuery extends APIQuery { priceRUB: 0, currency: 'RUB', vendor: { - name: 'unknown', + name: 'N/A', normalizedName: 'unknown', }, } diff --git a/src/pages/quest/index.js b/src/pages/quest/index.js index f1cf9969..f38cf696 100644 --- a/src/pages/quest/index.js +++ b/src/pages/quest/index.js @@ -40,7 +40,7 @@ function Quest() { factionName: 'Any', trader: { name: t('Loading...'), - normalizedName: 'flea-market' + normalizedName: 'unknown' }, objectives: [], startRewards: [], From b3af7f86fdf802dc8117210d663be836a07168c4 Mon Sep 17 00:00:00 2001 From: Shebuka Date: Thu, 20 Jun 2024 01:16:55 +0200 Subject: [PATCH 7/9] Added new foundInRaidRequired to meat query --- src/features/meta/do-fetch-meta.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/features/meta/do-fetch-meta.mjs b/src/features/meta/do-fetch-meta.mjs index 90eed002..cea97cb2 100644 --- a/src/features/meta/do-fetch-meta.mjs +++ b/src/features/meta/do-fetch-meta.mjs @@ -14,6 +14,7 @@ class MetaQuery extends APIQuery { minPlayerLevel sellOfferFeeRate sellRequirementFeeRate + foundInRaidRequired } armorMaterials(lang: ${language}) { id From d704c513be6d7012936dedf88d547f48dc438593 Mon Sep 17 00:00:00 2001 From: Shebuka Date: Thu, 20 Jun 2024 01:17:56 +0200 Subject: [PATCH 8/9] Using new foundInRaidRequired to enable flea-market as possible buyer of the barters; Fix sorting --- src/components/barters-table/index.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/components/barters-table/index.js b/src/components/barters-table/index.js index 76f8def3..601c7763 100644 --- a/src/components/barters-table/index.js +++ b/src/components/barters-table/index.js @@ -9,6 +9,7 @@ import DataTable from '../../components/data-table/index.js'; import useBartersData from '../../features/barters/index.js'; import useCraftsData from '../../features/crafts/index.js'; import useItemsData from '../../features/items/index.js'; +import useMetaData from '../../features/meta/index.js'; import { selectAllTraders } from '../../features/settings/settingsSlice.js'; import ValueCell from '../value-cell/index.js'; @@ -34,6 +35,7 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart const { data: barters } = useBartersData(); const { data: crafts } = useCraftsData(); const { data: items } = useItemsData(); + const { data: meta } = useMetaData(); const columns = useMemo( () => [ @@ -51,14 +53,14 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart accessor: 'costItems', sortType: (a, b, columnId, desc) => { if (a.values.costItems[0].id === '5d235b4d86f7742e017bc88a' && a.values.costItems[0].id === '5d235b4d86f7742e017bc88a') { - const aGPCost = a.values.costItems[0].price || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); - const bGPCost = b.values.costItems[0].price || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); + const aGPCost = a.values.costItems[0].price || 0; + const bGPCost = b.values.costItems[0].price || 0; return aGPCost - bGPCost; } - const aCost = a.values.cost || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); - const bCost = b.values.cost || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); + const aCost = a.values.cost || 0; + const bCost = b.values.cost || 0; return aCost - bCost; }, @@ -107,11 +109,11 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart id: 'instaProfit', accessor: 'instaProfit', sortType: (a, b, columnId, desc) => { - const aProf = a.values.instaProfit || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); - const bProf = b.values.instaProfit || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); + const aProf = a.values.instaProfit || 0; + const bProf = b.values.instaProfit || 0; if (aProf === bProf) { - const aSave = a.values.savings || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); - const bSave = b.values.savings || (desc ? Number.MIN_SAFE_INTEGER : Number.MAX_SAFE_INTEGER); + const aSave = a.values.savings || 0; + const bSave = b.values.savings || 0; return aSave - bSave; } @@ -286,7 +288,7 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart const howManyWeSell = barterRewardContainedItem ? barterRewardItem.containsItems[0].count : barterRow.rewardItems[0].count; const bestSellTo = whatWeSell.sellFor.reduce( (previousSellFor, currentSellFor) => { - if (currentSellFor.vendor.normalizedName === 'flea-market') { + if (currentSellFor.vendor.normalizedName === 'flea-market' && meta.flea.foundInRaidRequired) { return previousSellFor; } if (currentSellFor.vendor.normalizedName === 'jaeger' && !hasJaeger) { From d56910ea7eccb46e11effa9b6a60aeebd0e46bdb Mon Sep 17 00:00:00 2001 From: Shebuka Date: Thu, 20 Jun 2024 01:21:34 +0200 Subject: [PATCH 9/9] Fix missing dependancy --- src/components/barters-table/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/barters-table/index.js b/src/components/barters-table/index.js index 601c7763..151738b0 100644 --- a/src/components/barters-table/index.js +++ b/src/components/barters-table/index.js @@ -419,6 +419,7 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart barters, crafts, items, + meta, itemFilter, traders, completedQuests,