Skip to content

Commit

Permalink
Merge pull request #954 from the-hideout/feature/mix_fixes
Browse files Browse the repository at this point in the history
Better Interchange bounds and GP Coin barters
  • Loading branch information
Shebuka authored Jun 24, 2024
2 parents c9b84e4 + d56910e commit 528c742
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 42 deletions.
2 changes: 1 addition & 1 deletion scripts/cache-api-data.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
92 changes: 69 additions & 23 deletions src/components/barters-table/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 }) {
Expand All @@ -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(
() => [
Expand All @@ -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 <CostItemsCell costItems={value} allowAllSources={showAll} barters={useBarterIngredients ? barters : false} crafts={useCraftIngredients ? crafts : false} />;
},
Expand All @@ -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) {
Expand All @@ -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 (
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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'),
Expand All @@ -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,
};
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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
});
}

Expand Down Expand Up @@ -374,6 +418,8 @@ function BartersTable({ selectedTrader, nameFilter, itemFilter, showAll, useBart
selectedTrader,
barters,
crafts,
items,
meta,
itemFilter,
traders,
completedQuests,
Expand Down
21 changes: 12 additions & 9 deletions src/components/item-cost/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -51,14 +51,17 @@ function ItemCost({
let { displayPrice, tooltip, displayImage} = useMemo(() => {
let displayPrice = '';
let tooltip = false;
let displayImage = (
<img
alt={vendor.name}
className="item-cost-barter-icon"
src={`${process.env.PUBLIC_URL}/images/traders/${vendor.normalizedName}-icon.jpg`}
loading="lazy"
/>
);
let displayImage = '';
if (vendor.normalizedName !== 'unknown') {
displayImage = (
<img
alt={vendor.name}
className="item-cost-barter-icon"
src={`${process.env.PUBLIC_URL}/images/traders/${vendor.normalizedName}-icon.jpg`}
loading="lazy"
/>
);
}
if (priceType === 'cached') {
displayPrice = count;
displayImage = (
Expand Down
4 changes: 2 additions & 2 deletions src/data/maps.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion src/features/items/do-fetch-items.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ class ItemsQuery extends APIQuery {
priceRUB: 0,
currency: 'RUB',
vendor: {
name: 'unknown',
name: 'N/A',
normalizedName: 'unknown',
},
}
Expand Down
1 change: 1 addition & 0 deletions src/features/meta/do-fetch-meta.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class MetaQuery extends APIQuery {
minPlayerLevel
sellOfferFeeRate
sellRequirementFeeRate
foundInRaidRequired
}
armorMaterials(lang: ${language}) {
id
Expand Down
13 changes: 9 additions & 4 deletions src/modules/format-cost-items.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/item/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/pages/quest/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function Quest() {
factionName: 'Any',
trader: {
name: t('Loading...'),
normalizedName: 'flea-market'
normalizedName: 'unknown'
},
objectives: [],
startRewards: [],
Expand Down

0 comments on commit 528c742

Please sign in to comment.