diff --git a/docs/mammon-api.yml b/docs/mammon-api.yml index 23b4f60..fea33a0 100644 --- a/docs/mammon-api.yml +++ b/docs/mammon-api.yml @@ -449,6 +449,37 @@ paths: $ref: "#/components/schemas/MarketHistoryResponse" "400": description: The days parameter is not greater than 0 + /market/types: + get: + tags: + - market + summary: Return the static market type details for each requested type id + operationId: findTypes + parameters: + - name: ids + in: query + description: "Market type ids to look up, e.g. ids=34,35" + required: true + schema: + type: array + items: + type: integer + format: int64 + responses: + "200": + description: The market types found for the requested ids; unknown ids are + omitted + content: + '*/*': + schema: + type: array + items: + $ref: "#/components/schemas/MarketTypeResponse" + "400": + description: |- + Returned when: + - the ids parameter is missing + - an ids value is not a numeric id /market/scan: get: tags: @@ -916,6 +947,46 @@ components: - marketTypeId - orderCount - volume + MarketTypeResponse: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + groupId: + type: integer + format: int64 + marketGroupId: + type: integer + format: int64 + description: + type: string + published: + type: boolean + basePrice: + type: number + volume: + type: number + format: double + portionSize: + type: integer + format: int32 + iconId: + type: integer + format: int64 + required: + - basePrice + - description + - groupId + - iconId + - id + - marketGroupId + - name + - portionSize + - published + - volume MarketPriceResponse: type: object properties: diff --git a/src/generated/mammon/api.ts b/src/generated/mammon/api.ts index 5c0a074..ec97949 100644 --- a/src/generated/mammon/api.ts +++ b/src/generated/mammon/api.ts @@ -124,6 +124,18 @@ export interface MarketScanResponse { 'profit': number; 'score': number; } +export interface MarketTypeResponse { + 'id': number; + 'name': string; + 'groupId': number; + 'marketGroupId': number; + 'description': string; + 'published': boolean; + 'basePrice': number; + 'volume': number; + 'portionSize': number; + 'iconId': number; +} export interface RuleBookResponse { 'ruleBookId': string; 'name': string; @@ -1352,6 +1364,43 @@ export const MarketApiAxiosParamCreator = function (configuration?: Configuratio options: localVarRequestOptions, }; }, + /** + * + * @summary Return the static market type details for each requested type id + * @param {Array} ids Market type ids to look up, e.g. ids=34,35 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + findTypes: async (ids: Array, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'ids' is not null or undefined + assertParamExists('findTypes', 'ids', ids) + const localVarPath = `/market/types`; + // 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 (ids) { + localVarQueryParameter['ids'] = ids; + } + + 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 Scan every tracked market type, returning volume-weighted price quartiles for each @@ -1482,6 +1531,19 @@ export const MarketApiFp = function(configuration?: Configuration) { const localVarOperationServerBasePath = operationServerMap['MarketApi.findHistory']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, + /** + * + * @summary Return the static market type details for each requested type id + * @param {Array} ids Market type ids to look up, e.g. ids=34,35 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async findTypes(ids: Array, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { + const localVarAxiosArgs = await localVarAxiosParamCreator.findTypes(ids, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['MarketApi.findTypes']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, /** * * @summary Scan every tracked market type, returning volume-weighted price quartiles for each @@ -1543,6 +1605,16 @@ export const MarketApiFactory = function (configuration?: Configuration, basePat findHistory(marketTypeId: number, days?: number, options?: RawAxiosRequestConfig): AxiosPromise> { return localVarFp.findHistory(marketTypeId, days, options).then((request) => request(axios, basePath)); }, + /** + * + * @summary Return the static market type details for each requested type id + * @param {Array} ids Market type ids to look up, e.g. ids=34,35 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + findTypes(ids: Array, options?: RawAxiosRequestConfig): AxiosPromise> { + return localVarFp.findTypes(ids, options).then((request) => request(axios, basePath)); + }, /** * * @summary Scan every tracked market type, returning volume-weighted price quartiles for each @@ -1598,6 +1670,17 @@ export class MarketApi extends BaseAPI { return MarketApiFp(this.configuration).findHistory(marketTypeId, days, options).then((request) => request(this.axios, this.basePath)); } + /** + * + * @summary Return the static market type details for each requested type id + * @param {Array} ids Market type ids to look up, e.g. ids=34,35 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + public findTypes(ids: Array, options?: RawAxiosRequestConfig) { + return MarketApiFp(this.configuration).findTypes(ids, options).then((request) => request(this.axios, this.basePath)); + } + /** * * @summary Scan every tracked market type, returning volume-weighted price quartiles for each diff --git a/src/market/appraisal/appraisal.ts b/src/market/appraisal/appraisal.ts index 18ab28f..15db123 100644 --- a/src/market/appraisal/appraisal.ts +++ b/src/market/appraisal/appraisal.ts @@ -1,15 +1,15 @@ -import { defineStore } from 'pinia'; -import { RegionalMarketCache } from '../RegionalMarketCache'; -import { jitaId } from '../market'; -import { MarketType } from "../type"; -import { MarketTypePrice } from './MarketTypePrice'; -import { getMammonPrices } from './mammon'; +import {defineStore} from 'pinia'; +import {RegionalMarketCache} from '../RegionalMarketCache'; +import {jitaId} from '../market'; +import {MarketType} from "../type"; +import {MarketTypePrice} from './MarketTypePrice'; +import {getMammonPrices} from './mammon'; -const cacheDuration = 1000 * 60 * 5; // 5 minutes -const batchSize = 100; +const CACHE_DURATION = 1000 * 60 * 5; // 5 minutes +const BATCH_SIZE = 100; export const useApraisalStore = defineStore('appraisal', () => { - const cache: RegionalMarketCache = new RegionalMarketCache(cacheDuration); + const cache: RegionalMarketCache = new RegionalMarketCache(CACHE_DURATION); const getPricesUncached = getMammonPrices; @@ -32,8 +32,8 @@ export const useApraisalStore = defineStore('appraisal', () => { if (uncached.length > 0) { const batches: Promise[] = []; - for (let i = 0; i < uncached.length; i += batchSize) { - batches.push(getPricesUncached(uncached.slice(i, i + batchSize))); + for (let i = 0; i < uncached.length; i += BATCH_SIZE) { + batches.push(getPricesUncached(uncached.slice(i, i + BATCH_SIZE))); } const prices = (await Promise.all(batches)).flat(); diff --git a/src/market/type/MarketType.ts b/src/market/type/MarketType.ts index 1a8dd0a..bbd8505 100644 --- a/src/market/type/MarketType.ts +++ b/src/market/type/MarketType.ts @@ -1,30 +1,23 @@ -import {esiAxiosInstance} from '@/service'; +import {marketApi} from '@/mammon/mammonService'; +import type {MarketTypeResponse} from '@/generated/mammon'; -export type MarketType = { - id: number; - group_id: number; - market_group_id: number; - name: string; - published: boolean; - description: string; - base_price: number; - icon_id: number; - volume: number; - portion_size: number; -} +export type MarketType = MarketTypeResponse; const cache = new Map(); // TODO move to pinia store -const fetchType = (id: number): Promise => { - if (cache.has(id)) { - return Promise.resolve(cache.get(id)!); +const BATCH_SIZE = 100; + +const fetchTypes = async (ids: number[]): Promise => { + const missing = ids.filter(id => !cache.has(id)); + if (missing.length === 0) { + return; } - return esiAxiosInstance.get & { type_id: number }>(`/universe/types/${id}/`).then(r => { - const { type_id, ...rest } = r.data; - const marketType: MarketType = { id: type_id, ...rest }; - cache.set(id, marketType); - return marketType; - }); + const batches: Promise[] = []; + for (let i = 0; i < missing.length; i += BATCH_SIZE) { + batches.push(marketApi.findTypes(missing.slice(i, i + BATCH_SIZE)).then(r => r.data)); + } + const results = await Promise.all(batches); + results.flat().forEach(t => cache.set(t.id, t)); }; export const getMarketType = async (type: string | number): Promise => (await getMarketTypes([type]))[0]; @@ -33,28 +26,10 @@ export const getMarketTypes = async (types: (string | number)[]): Promise typeof t === 'number'); - return Promise.all(ids.map(fetchType)); + await fetchTypes(ids); + return ids.map(id => cache.get(id)).filter((t): t is MarketType => t !== undefined); } -const blueprintMarketGroups = [ // TODO add all groups - 2, - 2157, - 2159, - 2339, - 2160, - 211, - 1016, - 339, - 2290, - 357, - 1530, - 359, - 1531, - 1532, - 1533, - 358 -] - -export const searchMarketTypes = async (search: string): Promise => { +export const searchMarketTypes = async (_search: string): Promise => { return [] } \ No newline at end of file diff --git a/src/market/type/MarketTypeInput.vue b/src/market/type/MarketTypeInput.vue index 0163228..9d37962 100644 --- a/src/market/type/MarketTypeInput.vue +++ b/src/market/type/MarketTypeInput.vue @@ -89,7 +89,7 @@ watchEffect(async () => {