diff --git a/scripts/cache-api-data.mjs b/scripts/cache-api-data.mjs index 77b15756c..1c98b732d 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/components/barters-table/index.js b/src/components/barters-table/index.js index 1be876c33..151738b0b 100644 --- a/src/components/barters-table/index.js +++ b/src/components/barters-table/index.js @@ -5,16 +5,22 @@ 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 useMetaData from '../../features/meta/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 +34,8 @@ 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( () => [ @@ -43,6 +51,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 || 0; + const bGPCost = b.values.costItems[0].price || 0; + + return aGPCost - bGPCost; + } + + const aCost = a.values.cost || 0; + const bCost = b.values.cost || 0; + + return aCost - bCost; + }, Cell: ({ value }) => { return ; }, @@ -67,10 +88,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 +108,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 || 0; + const bProf = b.values.instaProfit || 0; + if (aProf === bProf) { + const aSave = a.values.savings || 0; + const bSave = b.values.savings || 0; + + return aSave - bSave; + } + + return aProf - bProf; + }, Cell: (props) => { if (props.row.original.cached) { return ( @@ -190,12 +222,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,10 +278,17 @@ 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') { + if (currentSellFor.vendor.normalizedName === 'flea-market' && meta.flea.foundInRaidRequired) { return previousSellFor; } if (currentSellFor.vendor.normalizedName === 'jaeger' && !hasJaeger) { @@ -274,15 +308,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 +333,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 +348,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 +367,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 +377,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 +418,8 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart selectedTrader, barters, crafts, + items, + meta, itemFilter, traders, completedQuests, diff --git a/src/components/item-cost/index.js b/src/components/item-cost/index.js index 0c9cffa28..3a7854116 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 = ( diff --git a/src/data/maps.json b/src/data/maps.json index a780c2cf5..538eb0e59 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", diff --git a/src/features/items/do-fetch-items.mjs b/src/features/items/do-fetch-items.mjs index 666df286c..500913619 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/features/meta/do-fetch-meta.mjs b/src/features/meta/do-fetch-meta.mjs index 90eed002a..cea97cb28 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 diff --git a/src/modules/format-cost-items.js b/src/modules/format-cost-items.js index 391d23d8e..3941d89a9 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) => { diff --git a/src/pages/item/index.js b/src/pages/item/index.js index c9c0ca8d8..54cb24cc6 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); diff --git a/src/pages/quest/index.js b/src/pages/quest/index.js index f1cf99698..f38cf6964 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: [],