diff --git a/docs/mammon-api.yml b/docs/mammon-api.yml index aacbbb2..53108cc 100644 --- a/docs/mammon-api.yml +++ b/docs/mammon-api.yml @@ -445,6 +445,32 @@ paths: $ref: "#/components/schemas/MarketScanResponse" "400": description: The days parameter is not greater than 0 + /market/prices: + get: + tags: + - market + summary: "Return the current Jita order book (highest buy, lowest sell, order\ + \ count) for each requested market type" + operationId: currentPrices + parameters: + - name: types + in: query + description: "Market type ids to price, e.g. types=34,35" + required: true + schema: + type: array + items: + type: integer + format: int64 + responses: + "200": + description: "The order book for each requested type, one entry per type" + content: + '*/*': + schema: + type: array + items: + $ref: "#/components/schemas/MarketPriceResponse" /ledgers: get: tags: @@ -827,6 +853,24 @@ components: - q3 - score - totalVolume + MarketPriceResponse: + type: object + properties: + marketTypeId: + type: integer + format: int64 + buy: + type: number + sell: + type: number + orderCount: + type: integer + format: int64 + required: + - buy + - marketTypeId + - orderCount + - sell LedgerResponse: discriminator: propertyName: type diff --git a/src/generated/mammon/api.ts b/src/generated/mammon/api.ts index 2c2425d..02c9a4e 100644 --- a/src/generated/mammon/api.ts +++ b/src/generated/mammon/api.ts @@ -107,6 +107,12 @@ export interface MarketHistoryResponse { 'orderCount': number; 'volume': number; } +export interface MarketPriceResponse { + 'marketTypeId': number; + 'buy': number; + 'sell': number; + 'orderCount': number; +} export interface MarketScanResponse { 'marketTypeId': number; 'q1': number; @@ -1268,6 +1274,43 @@ export class LedgerApi extends BaseAPI { */ export const MarketApiAxiosParamCreator = function (configuration?: Configuration) { return { + /** + * + * @summary Return the current Jita order book (highest buy, lowest sell, order count) for each requested market type + * @param {Array} types Market type ids to price, e.g. types=34,35 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + currentPrices: async (types: Array, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'types' is not null or undefined + assertParamExists('currentPrices', 'types', types) + const localVarPath = `/market/prices`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + if (types) { + localVarQueryParameter['types'] = types; + } + + localVarHeaderParameter['Accept'] = '*/*'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * * @summary Find the market history of a type, most recent first @@ -1361,6 +1404,19 @@ export const MarketApiAxiosParamCreator = function (configuration?: Configuratio export const MarketApiFp = function(configuration?: Configuration) { const localVarAxiosParamCreator = MarketApiAxiosParamCreator(configuration) return { + /** + * + * @summary Return the current Jita order book (highest buy, lowest sell, order count) for each requested market type + * @param {Array} types Market type ids to price, e.g. types=34,35 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async currentPrices(types: Array, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { + const localVarAxiosArgs = await localVarAxiosParamCreator.currentPrices(types, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['MarketApi.currentPrices']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, /** * * @summary Find the market history of a type, most recent first @@ -1399,6 +1455,16 @@ export const MarketApiFp = function(configuration?: Configuration) { export const MarketApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { const localVarFp = MarketApiFp(configuration) return { + /** + * + * @summary Return the current Jita order book (highest buy, lowest sell, order count) for each requested market type + * @param {Array} types Market type ids to price, e.g. types=34,35 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + currentPrices(types: Array, options?: RawAxiosRequestConfig): AxiosPromise> { + return localVarFp.currentPrices(types, options).then((request) => request(axios, basePath)); + }, /** * * @summary Find the market history of a type, most recent first @@ -1429,6 +1495,17 @@ export const MarketApiFactory = function (configuration?: Configuration, basePat * MarketApi - object-oriented interface */ export class MarketApi extends BaseAPI { + /** + * + * @summary Return the current Jita order book (highest buy, lowest sell, order count) for each requested market type + * @param {Array} types Market type ids to price, e.g. types=34,35 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + public currentPrices(types: Array, options?: RawAxiosRequestConfig) { + return MarketApiFp(this.configuration).currentPrices(types, options).then((request) => request(this.axios, this.basePath)); + } + /** * * @summary Find the market history of a type, most recent first diff --git a/src/market/appraisal/appraisal.ts b/src/market/appraisal/appraisal.ts index 9521356..048d81a 100644 --- a/src/market/appraisal/appraisal.ts +++ b/src/market/appraisal/appraisal.ts @@ -3,19 +3,14 @@ import { RegionalMarketCache } from '../RegionalMarketCache'; import { jitaId } from '../market'; import { MarketType } from "../type"; import { MarketTypePrice } from './MarketTypePrice'; -import { getEvepraisalPrices } from './evepraisal'; -import { getfuzzworkPrices } from './fuzzwork'; +import { getMammonPrices } from './mammon'; const cacheDuration = 1000 * 60 * 5; // 5 minutes -const priceGetters = { - evepraisal: getEvepraisalPrices, - fuzzwork: getfuzzworkPrices -} export const useApraisalStore = defineStore('appraisal', () => { const cache: RegionalMarketCache = new RegionalMarketCache(cacheDuration); - const getPricesUncached = priceGetters.fuzzwork; + const getPricesUncached = getMammonPrices; const getPrice = async (type: MarketType, regionId?: number): Promise => (await getPrices([type], regionId))[0]; const getPrices = async (types: MarketType[], regionId?: number): Promise => { diff --git a/src/market/appraisal/evepraisal.ts b/src/market/appraisal/evepraisal.ts index b03df7b..57c02b3 100644 --- a/src/market/appraisal/evepraisal.ts +++ b/src/market/appraisal/evepraisal.ts @@ -1,7 +1,5 @@ -import { logResource } from '@/service'; +import {logResource} from '@/service'; import axios from 'axios'; -import { MarketType } from "../type"; -import { PriceGetter } from './MarketTypePrice'; export const evepraisalAxiosInstance = axios.create({ baseURL: import.meta.env.VITE_EVEPRAISAL_URL, @@ -11,21 +9,3 @@ export const evepraisalAxiosInstance = axios.create({ }, }) logResource(evepraisalAxiosInstance) - -const batchSize = 100; - -export const getEvepraisalPrices: PriceGetter = async types => { - const batches = []; - - for (let i = 0; i < types.length; i += batchSize) { - batches.push(evepraisalAxiosInstance.post(`/appraisal.json?market=jita&persist=no&raw_textarea=${types.slice(i, i + batchSize).map(t => t.name).join("%0A")}`)); - } - return (await Promise.all(batches)) - .flatMap(b => b.data.appraisal.items) - .map((item: any) => ({ - type: types.find(t => t.name === item.typeName) as MarketType, - buy: item.prices.buy.max, - sell: item.prices.sell.min, - orderCount: item.prices.all.order_count - })); -}; \ No newline at end of file diff --git a/src/market/appraisal/fuzzwork.ts b/src/market/appraisal/fuzzwork.ts deleted file mode 100644 index ffac172..0000000 --- a/src/market/appraisal/fuzzwork.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { logResource } from '@/service'; -import axios from 'axios'; -import { MarketType } from "../type"; -import { PriceGetter } from './MarketTypePrice'; - -export const fuzzworkAxiosInstance = axios.create({ - baseURL: import.meta.env.VITE_FUZZWORK_URL, - headers: { - 'accept': 'application/json', - "Content-Type": "application/json" - }, -}) -logResource(fuzzworkAxiosInstance) - -const batchSize = 100; - -export const getfuzzworkPrices: PriceGetter = async types => { - const batches = []; - - for (let i = 0; i < types.length; i += batchSize) { - batches.push(fuzzworkAxiosInstance.post(`/aggregates/?station=60003760&types=${types.slice(i, i + batchSize).map(t => t.id).join(",")}`)); - } - return (await Promise.all(batches)) - .flatMap(b => Object.entries(b.data)) - .map(entry => { - const id = doParseInt(entry[0]); - const prices = entry[1] as any; - - return { - type: types.find(t => t.id === id) as MarketType, - buy: doParseFloat(prices?.buy?.max), - sell: doParseFloat(prices?.sell?.min), - orderCount: doParseInt(prices?.buy?.order_count) + doParseInt(prices?.sell?.order_count) - } - }); -}; - -const doParseInt = (s?: string) => s ? parseInt(s) : 0; -const doParseFloat = (s?: string) => s ? parseFloat(s) : 0; diff --git a/src/market/appraisal/mammon.ts b/src/market/appraisal/mammon.ts new file mode 100644 index 0000000..dbb6d4b --- /dev/null +++ b/src/market/appraisal/mammon.ts @@ -0,0 +1,20 @@ +import {marketApi} from '@/mammon/mammonService'; +import {MarketTypePrice, PriceGetter} from './MarketTypePrice'; + +export const getMammonPrices: PriceGetter = async types => { + if (types.length === 0) { + return []; + } + + const typesById = new Map(types.map(t => [t.id, t])); + const response = await marketApi.currentPrices(types.map(t => t.id)); + + return response.data.reduce((prices, p) => { + const type = typesById.get(p.marketTypeId); + + if (type) { + prices.push({ type, buy: p.buy, sell: p.sell, orderCount: p.orderCount }); + } + return prices; + }, []); +};