mirror of
https://github.com/Kvan7/Exiled-Exchange-2.git
synced 2025-10-30 06:08:00 +00:00
Fully add support for multiple currencies?
This commit is contained in:
@@ -228,7 +228,7 @@
|
||||
"currency_only_chaos": "Chaos Orb",
|
||||
"currency_only_div": "Divine Orb",
|
||||
"currency_chaos_div": "Both Orbs",
|
||||
"currency_exalted_div": "Both Orbs",
|
||||
"currency_exalted_div": "Ex/Div Orbs",
|
||||
"currency_only_exalted": "Exalted Orbs",
|
||||
"ratio_tooltip": "Ratio used for sorting locally\nDefault on trade site is 7.5:1"
|
||||
},
|
||||
|
||||
BIN
renderer/public/images/annul.png
Normal file
BIN
renderer/public/images/annul.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
@@ -28,8 +28,8 @@ export interface CurrencyValue {
|
||||
currency: "chaos" | "exalted" | "div";
|
||||
}
|
||||
|
||||
interface CoreCurrency {
|
||||
id: string;
|
||||
export interface CoreCurrency {
|
||||
id: "exalted" | "chaos";
|
||||
abbrev: string;
|
||||
ref: string;
|
||||
text: string;
|
||||
@@ -79,10 +79,20 @@ export const usePoeninja = createGlobalState(() => {
|
||||
return listed;
|
||||
});
|
||||
|
||||
/**
|
||||
* core/div
|
||||
*/
|
||||
const xchgRate = shallowRef<number | undefined>(undefined);
|
||||
/**
|
||||
* Current core currency
|
||||
*/
|
||||
const xchgRateCurrency = shallowRef<"chaos" | "exalted" | undefined>(
|
||||
undefined,
|
||||
);
|
||||
/**
|
||||
* exalted/div
|
||||
*/
|
||||
const exaltXchgRate = shallowRef<number | undefined>(undefined);
|
||||
|
||||
const isLoading = shallowRef(false);
|
||||
let PRICES_DB: PriceDatabase = [];
|
||||
@@ -150,24 +160,24 @@ export const usePoeninja = createGlobalState(() => {
|
||||
ns: "ITEM",
|
||||
name: "Divine Orb",
|
||||
});
|
||||
const preferred =
|
||||
AppConfig<PriceCheckWidget>("price-check")!.coreCurrency;
|
||||
const preferred = selectedCoreCurrency.value;
|
||||
|
||||
if (divine && divine.exalted >= 30) {
|
||||
if (preferred === "exalted") {
|
||||
exaltXchgRate.value = divine.exalted;
|
||||
if (!preferred || preferred.id === "exalted") {
|
||||
xchgRate.value = divine.exalted;
|
||||
xchgRateCurrency.value = "exalted";
|
||||
} else {
|
||||
const ex = divine.exalted;
|
||||
if (preferred === "chaos") {
|
||||
const chaos = findPriceByQuery({
|
||||
ns: "ITEM",
|
||||
name: "Chaos Orb",
|
||||
});
|
||||
if (chaos && ex / chaos.exalted >= 5) {
|
||||
xchgRate.value = ex / chaos.exalted;
|
||||
xchgRateCurrency.value = "chaos";
|
||||
}
|
||||
const ninjaPreferred = findPriceByQuery({
|
||||
ns: "ITEM",
|
||||
name: preferred.ref,
|
||||
});
|
||||
if (
|
||||
ninjaPreferred &&
|
||||
exaltXchgRate.value / ninjaPreferred.exalted >= 5
|
||||
) {
|
||||
xchgRate.value = exaltXchgRate.value / ninjaPreferred.exalted;
|
||||
xchgRateCurrency.value = preferred.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -230,34 +240,69 @@ export const usePoeninja = createGlobalState(() => {
|
||||
return null;
|
||||
}
|
||||
|
||||
function autoCurrency(value: number | [number, number]): CurrencyValue {
|
||||
/**
|
||||
* Converts item value from exalts to stable or current core currency
|
||||
* @param value item value in exalts
|
||||
* @returns Value in stable or core currency
|
||||
*/
|
||||
function autoCurrency(
|
||||
value: number | [number, number],
|
||||
useOnlyCore: boolean = false,
|
||||
): CurrencyValue {
|
||||
if (Array.isArray(value)) {
|
||||
if (value[1] > (xchgRate.value || 9999)) {
|
||||
if (value[1] > (exaltXchgRate.value || 9999) && !useOnlyCore) {
|
||||
return {
|
||||
min: exaltedToStable(value[0]),
|
||||
max: exaltedToStable(value[1]),
|
||||
min: exaltToStable(value[0]),
|
||||
max: exaltToStable(value[1]),
|
||||
currency: "div",
|
||||
};
|
||||
}
|
||||
if (selectedCoreCurrency.value?.id) {
|
||||
// NOTE: This if should catch everything
|
||||
return {
|
||||
min: exaltToCore(value[0]),
|
||||
max: exaltToCore(value[1]),
|
||||
currency: selectedCoreCurrency.value.id,
|
||||
};
|
||||
}
|
||||
// this should never run, assuming we have loaded a currency
|
||||
return { min: value[0], max: value[1], currency: "exalted" };
|
||||
}
|
||||
if (value > (xchgRate.value || 9999) * 0.94) {
|
||||
if (value < (xchgRate.value || 9999) * 1.06) {
|
||||
if (value > (exaltXchgRate.value || 9999) * 0.94 && !useOnlyCore) {
|
||||
if (value < (exaltXchgRate.value || 9999) * 1.06) {
|
||||
return { min: 1, max: 1, currency: "div" };
|
||||
} else {
|
||||
return {
|
||||
min: exaltedToStable(value),
|
||||
max: exaltedToStable(value),
|
||||
min: exaltToStable(value),
|
||||
max: exaltToStable(value),
|
||||
currency: "div",
|
||||
};
|
||||
}
|
||||
}
|
||||
if (selectedCoreCurrency.value?.id) {
|
||||
// NOTE: This if should catch everything
|
||||
return {
|
||||
min: exaltToCore(value),
|
||||
max: exaltToCore(value),
|
||||
currency: selectedCoreCurrency.value.id,
|
||||
};
|
||||
}
|
||||
// this should never run, assuming we have loaded a currency
|
||||
return { min: value, max: value, currency: "exalted" };
|
||||
}
|
||||
|
||||
function exaltedToStable(count: number) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
function coreToStable(count: number) {
|
||||
return count / (xchgRate.value || 9999);
|
||||
}
|
||||
function exaltToStable(count: number) {
|
||||
return count / (exaltXchgRate.value || 9999);
|
||||
}
|
||||
function exaltToCore(count: number) {
|
||||
// ex -> core
|
||||
// ex => ex * (div/ex) * (core/div) = core
|
||||
return (count / (exaltXchgRate.value || 9999)) * (xchgRate.value || 9999);
|
||||
}
|
||||
|
||||
function cachedCurrencyByQuery(query: DbQuery, count: number) {
|
||||
const key = { ns: query.ns, name: query.name, count };
|
||||
@@ -265,7 +310,8 @@ export const usePoeninja = createGlobalState(() => {
|
||||
return priceCache.get(key)!;
|
||||
}
|
||||
|
||||
const price = findPriceByQuery(query);
|
||||
const price = // since ex aren't currently in db
|
||||
query.name === "Exalted Orb" ? { exalted: 1 } : findPriceByQuery(query);
|
||||
if (!price) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
:title="title"
|
||||
>
|
||||
<ui-popover
|
||||
v-if="stableOrbCost"
|
||||
v-if="stableOrbCost && xchgRateCurrency?.id"
|
||||
trigger="click"
|
||||
boundary="#price-window"
|
||||
>
|
||||
@@ -65,13 +65,14 @@
|
||||
:price="{
|
||||
min: stableOrbCost,
|
||||
max: stableOrbCost,
|
||||
currency: 'exalted',
|
||||
currency: xchgRateCurrency.id,
|
||||
}"
|
||||
item-img="/images/divine.png"
|
||||
/>
|
||||
<div v-for="i in 9" :key="i">
|
||||
<div class="pl-1">
|
||||
{{ i / 10 }} div ⇒ {{ Math.round((stableOrbCost * i) / 10) }} c
|
||||
{{ i / 10 }} div ⇒ {{ Math.round((stableOrbCost * i) / 10) }}
|
||||
{{ xchgRateCurrency.abbrev }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -271,6 +272,7 @@ export default defineComponent({
|
||||
const wm = inject<WidgetManager>("wm")!;
|
||||
const {
|
||||
xchgRate,
|
||||
xchgRateCurrency,
|
||||
initialLoading: xchgRateLoading,
|
||||
queuePricesFetch,
|
||||
} = usePoeninja();
|
||||
@@ -452,6 +454,7 @@ export default defineComponent({
|
||||
closePriceCheck,
|
||||
title,
|
||||
stableOrbCost,
|
||||
xchgRateCurrency,
|
||||
xchgRateLoading,
|
||||
showCheckPos,
|
||||
checkPosition,
|
||||
|
||||
@@ -42,14 +42,10 @@ export default defineComponent({
|
||||
function getPriceFor(n: number) {
|
||||
const one = findPriceByQuery(getDetailsId(props.item)!)!;
|
||||
|
||||
const price =
|
||||
props.item.info.refName === "Divine Orb"
|
||||
? {
|
||||
min: n * one.exalted,
|
||||
max: n * one.exalted,
|
||||
currency: "exalted" as const,
|
||||
}
|
||||
: autoCurrency(n * one.exalted);
|
||||
const price = autoCurrency(
|
||||
n * one.exalted,
|
||||
props.item.info.refName === "Divine Orb",
|
||||
);
|
||||
|
||||
return `${displayRounding(price.min)} ${price.currency}`;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ const MIN_TTL = 300;
|
||||
|
||||
export class Cache {
|
||||
private cached = new Map<string, unknown>();
|
||||
private currency = "";
|
||||
|
||||
get<T = unknown>(key: unknown): T | undefined {
|
||||
const _key = hash.sha1(JSON.parse(JSON.stringify(key)));
|
||||
@@ -20,6 +21,13 @@ export class Cache {
|
||||
}, ttl * 1000);
|
||||
}
|
||||
|
||||
purgeIfDifferentCurrency(currency: string | undefined) {
|
||||
if (!currency || this.currency === currency) return;
|
||||
this.currency = currency;
|
||||
this.cached.clear();
|
||||
console.log("Purged cache");
|
||||
}
|
||||
|
||||
static deriveTtl(...limits: RateLimiter[]): number {
|
||||
return Math.max(MIN_TTL, ...limits.map((limit) => limit.window));
|
||||
}
|
||||
|
||||
@@ -84,9 +84,9 @@
|
||||
<ui-radio v-model="filters.trade.currency" value="exalted">{{
|
||||
t(":currency_only_exalted")
|
||||
}}</ui-radio>
|
||||
<!-- <ui-radio v-model="filters.trade.currency" value="chaos">{{
|
||||
<ui-radio v-model="filters.trade.currency" value="chaos">{{
|
||||
t(":currency_only_chaos")
|
||||
}}</ui-radio> -->
|
||||
}}</ui-radio>
|
||||
<ui-radio v-model="filters.trade.currency" value="divine">{{
|
||||
t(":currency_only_div")
|
||||
}}</ui-radio>
|
||||
|
||||
@@ -12,16 +12,11 @@
|
||||
}"
|
||||
>{{ result.priceAmount }} {{ result.priceCurrency
|
||||
}}{{
|
||||
result.priceCurrency !== "exalted" &&
|
||||
result.normalizedPriceCurrency &&
|
||||
result.priceCurrency !== result.normalizedPriceCurrency.id &&
|
||||
result.priceCurrency !== "divine" &&
|
||||
result.normalizedPrice
|
||||
? ` (${result.normalizedPrice} ${
|
||||
result.normalizedPriceCurrency! === "exalted"
|
||||
? "ex"
|
||||
: result.normalizedPriceCurrency! === "chaos"
|
||||
? "c"
|
||||
: result.normalizedPriceCurrency!
|
||||
})`
|
||||
? ` (${result.normalizedPrice} ${result.normalizedPriceCurrency.abbrev})`
|
||||
: ""
|
||||
}}</span
|
||||
>
|
||||
@@ -31,18 +26,6 @@
|
||||
><span class="font-sans">×</span> {{ result.listedTimes }}</span
|
||||
><i v-else-if="!result.hasNote" class="fas fa-question" />
|
||||
</td>
|
||||
<!-- <td class="px-2">
|
||||
<div v-if="result.priceCurrencyRank" class="my-2 flex flex-row">
|
||||
<div
|
||||
v-for="i in result.priceCurrencyRank"
|
||||
class="account-status mr-1"
|
||||
:class="{
|
||||
'rank-2': result.priceCurrencyRank === 2,
|
||||
'rank-3': result.priceCurrencyRank === 3,
|
||||
}"
|
||||
></div>
|
||||
</div>
|
||||
</td> -->
|
||||
<td v-if="item.stackSize" class="px-2 text-right">
|
||||
{{ result.stackSize }}
|
||||
</td>
|
||||
|
||||
@@ -310,7 +310,13 @@ export interface PricingResult {
|
||||
priceCurrency: string;
|
||||
priceCurrencyRank?: number;
|
||||
normalizedPrice?: string;
|
||||
normalizedPriceCurrency?: string;
|
||||
normalizedPriceCurrency?: {
|
||||
id: "exalted" | "chaos";
|
||||
abbrev: string;
|
||||
ref: string;
|
||||
text: string;
|
||||
icon: string;
|
||||
};
|
||||
isMine: boolean;
|
||||
hasNote: boolean;
|
||||
isInstantBuyout: boolean;
|
||||
@@ -953,8 +959,11 @@ export async function requestResults(
|
||||
resultIds: string[],
|
||||
opts: { accountName: string },
|
||||
): Promise<PricingResult[]> {
|
||||
const { cachedCurrencyByQuery, xchgRateCurrency } = usePoeninja();
|
||||
// Solves cached results showing random incorrect values
|
||||
cache.purgeIfDifferentCurrency(xchgRateCurrency.value?.id);
|
||||
|
||||
let data = cache.get<FetchResult[]>(resultIds);
|
||||
const { cachedCurrencyByQuery } = usePoeninja();
|
||||
|
||||
if (!data) {
|
||||
await RateLimiter.waitMulti(RATE_LIMIT_RULES.FETCH);
|
||||
@@ -1053,21 +1062,15 @@ export async function requestResults(
|
||||
const query = getCurrencyDetailsId(
|
||||
result.listing.price?.currency ?? "no price",
|
||||
);
|
||||
const normalizedCurrency =
|
||||
result.listing.price?.currency === "exalted"
|
||||
? // exalts aren't in db since they are the stable currency
|
||||
{
|
||||
min: result.listing.price.amount,
|
||||
max: result.listing.price.amount,
|
||||
currency: "exalted",
|
||||
}
|
||||
: // otherwise convert to stable
|
||||
cachedCurrencyByQuery(query, result.listing.price?.amount ?? 0);
|
||||
const normalizedCurrency = cachedCurrencyByQuery(
|
||||
query,
|
||||
result.listing.price?.amount ?? 0,
|
||||
);
|
||||
const normalizedPrice =
|
||||
normalizedCurrency !== undefined
|
||||
? displayRounding(normalizedCurrency.min)
|
||||
: undefined;
|
||||
const normalizedPriceCurrency = normalizedCurrency?.currency;
|
||||
const normalizedPriceCurrency = xchgRateCurrency.value;
|
||||
|
||||
return {
|
||||
id: result.id,
|
||||
|
||||
@@ -40,6 +40,11 @@
|
||||
src="/images/chaos.png"
|
||||
class="max-w-full max-h-full"
|
||||
/>
|
||||
<img
|
||||
v-else-if="price?.currency === 'annul'"
|
||||
src="/images/annul.png"
|
||||
class="max-w-full max-h-full"
|
||||
/>
|
||||
<img v-else src="/images/exa.png" class="max-w-full max-h-full" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -56,7 +61,7 @@ export default defineComponent({
|
||||
type: Object as PropType<{
|
||||
min: number;
|
||||
max: number;
|
||||
currency: "chaos" | "div" | "exalted";
|
||||
currency: string;
|
||||
}>,
|
||||
default: undefined,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user