rework hierarchy

This commit is contained in:
2023-09-19 11:57:48 +02:00
parent a483580906
commit cd75aa5b13
16 changed files with 138 additions and 100 deletions

View File

@@ -4,10 +4,13 @@ import App from './App.vue';
import './style.css';
const routes = [
{ path: '/', component: () => import('@/Index.vue') },
{ path: '/reprocess', component: () => import('@/reprocess/Reprocess.vue') },
{ path: '/market', component: () => import('@/market/Market.vue') },
{ path: '/tools', component: () => import('@/tools/Tools.vue') },
{ path: '/', component: () => import('@/pages/Index.vue') },
{ path: '/reprocess', component: () => import('@/pages/Reprocess.vue') },
{ path: '/market', component: () => import('@/pages/Market.vue'), children: [
{ path: '', redirect: '/market/scan' },
{ path: 'scan', component: () => import('@/pages/market/Scan.vue') },
] },
{ path: '/tools', component: () => import('@/pages/Tools.vue') },
];
const router = createRouter({

View File

@@ -0,0 +1,13 @@
import { esiAxiosInstance } from "@/service";
export type MarketOrderHistory = {
average: number;
date: string;
highest: number;
lowest: number;
order_count: number;
volume: number;
}
export const getHistory = async (regionId: number, tyeId: number): Promise<MarketOrderHistory[]> => (await esiAxiosInstance.get(`/markets/${regionId}/history/`, { params: { type_id: tyeId } })).data;

View File

@@ -1,2 +1,4 @@
export * from './MarketOrderHistory';
export * from './market';
export * from './type';

View File

@@ -1,80 +1,3 @@
import { esiAxiosInstance } from "@/service";
import { MarketType } from "./type";
export const jitaId = 10000002;
export type MarketOrderHistory = {
average: number;
date: string;
highest: number;
lowest: number;
order_count: number;
volume: number;
}
export type MarketResult = {
type: MarketType;
history: MarketOrderHistory[];
buy: number,
sell: number
}
export type HistoryQuartils = {
totalVolume: number,
q1: number,
median: number,
q3: number,
}
export const getHistory = async (regionId: number, tyeId: number): Promise<MarketOrderHistory[]> => (await esiAxiosInstance.get(`/markets/${regionId}/history/`, { params: { type_id: tyeId } })).data;
export const getHistoryQuartils = (history: MarketOrderHistory[], days?: number): HistoryQuartils => {
const now = Date.now();
const volumes = history
.flatMap(h => {
const volume = h.volume;
if (volume === 0 || (days && new Date(h.date).getTime() < now - days * 24 * 60 * 60 * 1000)) {
return [];
}
const e = estimateVolume(h);
return [[h.highest, e], [h.lowest, volume - e]];
})
.filter(h => h[1] > 0)
.sort((a, b) => a[0] - b[0]);
const totalVolume = volumes.reduce((acc, [_, v]) => acc + v, 0);
const quartilVolume = totalVolume / 4;
const quartils: [number, number, number] = [0, 0, 0];
let currentVolume = 0;
let quartil = 0;
for (const [price, volume] of volumes) {
currentVolume += volume;
if (currentVolume >= quartilVolume * (quartil + 1)) {
quartils[quartil] = price;
if (quartil === 2) {
break;
}
quartil++;
}
}
return {
totalVolume,
q1: quartils[0],
median: quartils[1],
q3: quartils[2],
};
}
const estimateVolume = (history: MarketOrderHistory): number => {
if (history.volume === 0) {
return 0;
}
return Math.max(1, Math.round(history.volume * ((history.average - history.lowest) / (history.highest - history.lowest))));
}

View File

@@ -0,0 +1,59 @@
import { MarketOrderHistory } from "@/market";
export type HistoryQuartils = {
totalVolume: number,
q1: number,
median: number,
q3: number,
}
export const getHistoryQuartils = (history: MarketOrderHistory[], days?: number): HistoryQuartils => {
const now = Date.now();
const volumes = history
.flatMap(h => {
const volume = h.volume;
if (volume === 0 || (days && new Date(h.date).getTime() < now - days * 24 * 60 * 60 * 1000)) {
return [];
}
const e = estimateVolume(h);
return [[h.highest, e], [h.lowest, volume - e]];
})
.filter(h => h[1] > 0)
.sort((a, b) => a[0] - b[0]);
const totalVolume = volumes.reduce((acc, [_, v]) => acc + v, 0);
const quartilVolume = totalVolume / 4;
const quartils: [number, number, number] = [0, 0, 0];
let currentVolume = 0;
let quartil = 0;
for (const [price, volume] of volumes) {
currentVolume += volume;
if (currentVolume >= quartilVolume * (quartil + 1)) {
quartils[quartil] = price;
if (quartil === 2) {
break;
}
quartil++;
}
}
return {
totalVolume,
q1: quartils[0],
median: quartils[1],
q3: quartils[2],
};
}
const estimateVolume = (history: MarketOrderHistory): number => {
if (history.volume === 0) {
return 0;
}
return Math.max(1, Math.round(history.volume * ((history.average - history.lowest) / (history.highest - history.lowest))));
}

View File

@@ -1,11 +1,11 @@
<script setup lang="ts">
import { formatIsk, percentFormater } from '@/formaters';
import { MarketType, MarketTypeLabel } from "@/market";
import { SortableHeader, useSort } from '@/table';
import { ArrowPathIcon } from '@heroicons/vue/24/outline';
import { useStorage } from '@vueuse/core';
import { computed, ref } from 'vue';
import { MarketResult, getHistoryQuartils } from ".";
import { MarketType, MarketTypeLabel } from "./type";
import { ScanResult, getHistoryQuartils } from '.';
type Result = {
type: MarketType;
@@ -20,7 +20,7 @@ type Result = {
}
interface Props {
items?: MarketResult[];
items?: ScanResult[];
}
interface Emits {

4
src/market/scan/index.ts Normal file
View File

@@ -0,0 +1,4 @@
export * from './HistoryQuartils';
export * from './scan';
export { default as ScanResultTable } from './ScanResultTable.vue';

9
src/market/scan/scan.ts Normal file
View File

@@ -0,0 +1,9 @@
import { MarketOrderHistory, MarketType } from "@/market";
export type ScanResult = {
type: MarketType;
history: MarketOrderHistory[];
buy: number,
sell: number
}

27
src/pages/Market.vue Normal file
View File

@@ -0,0 +1,27 @@
<script setup lang="ts">
import { RouterLink, RouterView } from 'vue-router';
</script>
<template>
<div class="mt-4">
<div class="flex border-b-2">
<RouterLink to="/market/scan" class="tab">
<span>Scan</span>
</RouterLink>
<RouterLink to="/market/track" class="tab">
<span>Tracking</span>
</RouterLink>
</div>
<RouterView />
</div>
</template>
<style scoped>
a.tab {
@apply flex items-center p-2 me-2 rounded-t-md bg-slate-600 hover:bg-slate-700;
&.router-link-active {
@apply bg-emerald-500 hover:bg-emerald-700;
}
}
</style>

View File

@@ -1,9 +1,7 @@
<script setup lang="ts">
import { ReprocessInput, ReprocessItemValues, ReprocessResultTable, reprocess } from '@/reprocess';
import { useStorage } from '@vueuse/core';
import { ref } from 'vue';
import ReprocessInput from './ReprocessInput.vue';
import ReprocessResultTable from './ReprocessResultTable.vue';
import { ReprocessItemValues, reprocess } from './reprocess';
const items = ref("");
const minerals = ref("");

View File

@@ -1,9 +1,5 @@
<script setup lang="ts">
import HaulerTank from './HaulerTank.vue';
import ModuleDamage from './ModuleDamage.vue';
import { HaulerTank, ModuleDamage } from '@/tools';
</script>
<template>

View File

@@ -1,10 +1,9 @@
<script setup lang="ts">
import { MarketOrderHistory, MarketType, getHistory, getMarketType, getMarketTypes, jitaId } from "@/market";
import { ScanResult, ScanResultTable } from '@/market/scan';
import { evepraisalAxiosInstance } from '@/service';
import { useStorage } from '@vueuse/core';
import { onMounted, ref, watch } from 'vue';
import { MarketOrderHistory, MarketResult, getHistory, jitaId } from ".";
import MarketReultTable from "./MarketResultTable.vue";
import { MarketType, getMarketType, getMarketTypes } from "./type";
type MarketItemStorage = {
typeID: number;
@@ -19,7 +18,7 @@ const item = ref("");
*/
const oldStorage = useStorage<MarketItemStorage[]>('market-items', []);
const itemsStorage = useStorage<MarketItemStorage[]>('market-scan-items', []);
const items = ref<MarketResult[]>([]);
const items = ref<ScanResult[]>([]);
const addOrRelaod = async (type: MarketType) => {
const typeID = type.id;
const [history, price] = await Promise.all([
@@ -89,6 +88,6 @@ onMounted(async () => {
</div>
<template v-if="items.length > 0">
<hr />
<MarketReultTable :items="items" @relaod="type => addOrRelaod(type)" @relaodAll="reloadAll" />
<ScanResultTable :items="items" @relaod="type => addOrRelaod(type)" @relaodAll="reloadAll" />
</template>
</template>

View File

@@ -1,2 +1,5 @@
export * from './reprocess';
export { default as ReprocessInput } from './ReprocessInput.vue';
export { default as ReprocessResultTable } from './ReprocessResultTable.vue';

View File

@@ -12,7 +12,7 @@
}
button {
@apply py-0.5 px-2 border rounded bg-slate-600 hover:bg-slate-800;
@apply py-0.5 px-2 border rounded bg-slate-600 hover:bg-slate-700;
}
input {
@apply border bg-slate-500 rounded px-1;
@@ -52,7 +52,7 @@
@apply bg-slate-500;
}
::-webkit-scrollbar-thumb {
@apply bg-slate-600 hover:bg-slate-800;
@apply bg-slate-600 hover:bg-slate-700;
border-radius: 5px;
}
input[type=search] {
@@ -61,7 +61,7 @@
.btn-icon {
@apply p-0 border-none bg-transparent hover:text-slate-400 hover:bg-transparent;
> svg {
@apply w-6 h-6 hover:text-slate-400;
@apply w-6 h-6;
}
}
.btn-icon-stroke {

2
src/tools/index.ts Normal file
View File

@@ -0,0 +1,2 @@
export { default as HaulerTank } from './HaulerTank.vue';
export { default as ModuleDamage } from './ModuleDamage.vue';