refactor: make match-collector export its types, and consume them in frontend
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { debounce, isEmpty } from '~/utils/helpers'
|
||||
|
||||
import type { ChampionSummary, LaneData, ChampionData } from 'match_collector'
|
||||
// Constants
|
||||
const CHAMPIONS_API_URL = '/api/champions'
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { CDRAGON_BASE, mapPath } from '~/utils/cdragon'
|
||||
|
||||
import type { Perk, Item } from '~/types/cdragon'
|
||||
|
||||
const props = defineProps<{
|
||||
keystoneId: number
|
||||
itemId: number
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { CDRAGON_BASE, mapPath } from '~/utils/cdragon'
|
||||
|
||||
import type { PerkStyle, Perk } from '~/types/cdragon'
|
||||
|
||||
interface RuneBuild {
|
||||
count: number
|
||||
primaryStyle: number
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { FirstBackGroup } from 'match_collector'
|
||||
import type { Item } from '~/types/cdragon'
|
||||
|
||||
defineProps<{
|
||||
firstBacks: FirstBackGroup[]
|
||||
itemMap: Map<number, Item>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import type { Item } from '~/types/cdragon'
|
||||
|
||||
interface ItemData {
|
||||
data: number
|
||||
count: number
|
||||
|
||||
@@ -5,8 +5,10 @@ import CompactRuneSelector from '~/components/build/CompactRuneSelector.vue'
|
||||
import ItemRow from '~/components/build/ItemRow.vue'
|
||||
import FirstBack from '~/components/build/FirstBack.vue'
|
||||
|
||||
import type { Build } from 'match_collector'
|
||||
|
||||
const props = defineProps<{
|
||||
builds: Builds
|
||||
builds: Array<Build>
|
||||
}>()
|
||||
|
||||
// State
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { CDRAGON_BASE, mapPath } from '~/utils/cdragon'
|
||||
|
||||
import type { Item } from '~/types/cdragon'
|
||||
import type { ItemTag } from 'match_collector'
|
||||
|
||||
interface Props {
|
||||
item: Item
|
||||
size?: number
|
||||
|
||||
@@ -7,6 +7,9 @@ import {
|
||||
type ParsedDescription
|
||||
} from 'dragon-item-parser'
|
||||
|
||||
import type { Item } from '~/types/cdragon'
|
||||
import type { ItemTag } from 'match_collector'
|
||||
|
||||
interface Props {
|
||||
item: Item | null
|
||||
show: boolean
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { LinePath as svgdomarrowsLinePath } from 'svg-dom-arrows'
|
||||
|
||||
import type { ItemTree } from 'match_collector'
|
||||
import type { Item } from '~/types/cdragon'
|
||||
|
||||
defineProps<{
|
||||
tree: ItemTree
|
||||
parentCount?: number
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
import { CDRAGON_BASE } from '~/utils/cdragon'
|
||||
import MatchupSpectrum from './Spectrum.vue'
|
||||
|
||||
import type { MatchupData } from 'match_collector'
|
||||
|
||||
defineProps<{
|
||||
matchups?: Array<MatchupData>
|
||||
championId: number
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
import { ref } from 'vue'
|
||||
import { CDRAGON_BASE } from '~/utils/cdragon'
|
||||
|
||||
import type { MatchupData } from 'match_collector'
|
||||
|
||||
defineProps<{
|
||||
matchups?: Array<MatchupData>
|
||||
championId: number
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import type { LaneData } from 'match_collector'
|
||||
|
||||
defineProps<{
|
||||
championName?: string
|
||||
championLanes?: Array<LaneData>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { LANE_IMAGES, lanePositionToIndex, POSITIONS_STR } from '~/utils/cdragon'
|
||||
|
||||
import type { LaneData } from 'match_collector'
|
||||
|
||||
defineProps<{
|
||||
championName?: string
|
||||
championLanes?: Array<LaneData>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { LANE_IMAGES, lanePositionToIndex, POSITIONS_STR } from '~/utils/cdragon'
|
||||
|
||||
import type { LaneData } from 'match_collector'
|
||||
|
||||
defineProps<{
|
||||
championName?: string
|
||||
championLanes?: Array<LaneData>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import type { PerkStyle, Perk } from '~/types/cdragon'
|
||||
|
||||
const props = defineProps<{
|
||||
primaryStyleId: number
|
||||
secondaryStyleId: number
|
||||
@@ -8,13 +10,14 @@ const props = defineProps<{
|
||||
const primaryStyle: Ref<PerkStyle> = ref({ id: 0, name: '', iconPath: '', slots: [] })
|
||||
const secondaryStyle: Ref<PerkStyle> = ref({ id: 0, name: '', iconPath: '', slots: [] })
|
||||
|
||||
const { data: perks_data }: PerksResponse = await useFetch('/api/cdragon/perks')
|
||||
const { data: perks_data }: { data: Ref<Array<Perk>> } = await useFetch('/api/cdragon/perks')
|
||||
const perks = reactive(new Map())
|
||||
for (const perk of perks_data.value) {
|
||||
perks.set(perk.id, perk)
|
||||
}
|
||||
|
||||
const { data: stylesData }: PerkStylesResponse = await useFetch('/api/cdragon/perkstyles')
|
||||
const { data: stylesData }: { data: Ref<{ styles: Array<PerkStyle> }> } =
|
||||
await useFetch('/api/cdragon/perkstyles')
|
||||
watch(
|
||||
() => props.primaryStyleId,
|
||||
async (_newP, _oldP) => {
|
||||
|
||||
@@ -10,6 +10,9 @@ import {
|
||||
} from 'chart.js'
|
||||
import { Bar } from 'vue-chartjs'
|
||||
|
||||
import type { Champion } from '~/types/cdragon'
|
||||
import type { LaneData } from 'match_collector'
|
||||
|
||||
// Register
|
||||
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { LaneData } from 'match_collector'
|
||||
import type { Champion } from '~/types/cdragon'
|
||||
|
||||
defineProps<{
|
||||
title: string
|
||||
tier: Array<{ champion: Champion; lane: LaneData }>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { Builds } from 'match_collector'
|
||||
|
||||
/**
|
||||
* Composable for managing build data
|
||||
*/
|
||||
|
||||
@@ -17,26 +17,7 @@ export default withNuxt([
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.node,
|
||||
// Add global types from our API definitions
|
||||
ChampionSummary: 'readonly',
|
||||
LaneData: 'readonly',
|
||||
ChampionData: 'readonly',
|
||||
ItemTree: 'readonly',
|
||||
ItemTag: 'readonly',
|
||||
Builds: 'readonly',
|
||||
PerkStyle: 'readonly',
|
||||
PerksResponse: 'readonly',
|
||||
PerkStylesResponse: 'readonly',
|
||||
Champion: 'readonly',
|
||||
ChampionsResponse: 'readonly',
|
||||
ChampionResponse: 'readonly',
|
||||
ItemResponse: 'readonly',
|
||||
MatchupData: 'readonly',
|
||||
Item: 'readonly',
|
||||
SummonerSpell: 'readonly',
|
||||
Perk: 'readonly',
|
||||
FirstBackGroup: 'readonly'
|
||||
...globals.node
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
|
||||
83
frontend/package-lock.json
generated
83
frontend/package-lock.json
generated
@@ -14,6 +14,7 @@
|
||||
"chart.js": "^4.5.0",
|
||||
"dotenv": "^17.2.3",
|
||||
"dragon-item-parser": "file:../dragon-item-parser",
|
||||
"match_collector": "file:../match_collector",
|
||||
"mongodb": "^6.10.0",
|
||||
"nuxt": "^3.17.5",
|
||||
"nuxt-umami": "^3.2.1",
|
||||
@@ -9909,6 +9910,88 @@
|
||||
"resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz",
|
||||
"integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ=="
|
||||
},
|
||||
"node_modules/match_collector": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "file:../match_collector",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"dragon-item-parser": "file:../dragon-item-parser",
|
||||
"mongodb": "^7.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/match_collector/node_modules/@types/whatwg-url": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-13.0.0.tgz",
|
||||
"integrity": "sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==",
|
||||
"dependencies": {
|
||||
"@types/webidl-conversions": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/match_collector/node_modules/bson": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/bson/-/bson-7.2.0.tgz",
|
||||
"integrity": "sha512-YCEo7KjMlbNlyHhz7zAZNDpIpQbd+wOEHJYezv0nMYTn4x31eIUM2yomNNubclAt63dObUzKHWsBLJ9QcZNSnQ==",
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/match_collector/node_modules/mongodb": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-7.2.0.tgz",
|
||||
"integrity": "sha512-F/2+BMZtLVhY30ioZp0dAmZ+IRZMBqI+nrv6t5+9/1AIwCa8sMRC3jBf81lpxMhnZgqq8CoUD503Z1oZWq1/sw==",
|
||||
"dependencies": {
|
||||
"@mongodb-js/saslprep": "^1.3.0",
|
||||
"bson": "^7.2.0",
|
||||
"mongodb-connection-string-url": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@aws-sdk/credential-providers": "^3.806.0",
|
||||
"@mongodb-js/zstd": "^7.0.0",
|
||||
"gcp-metadata": "^7.0.1",
|
||||
"kerberos": "^7.0.0",
|
||||
"mongodb-client-encryption": ">=7.0.0 <7.1.0",
|
||||
"snappy": "^7.3.2",
|
||||
"socks": "^2.8.6"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@aws-sdk/credential-providers": {
|
||||
"optional": true
|
||||
},
|
||||
"@mongodb-js/zstd": {
|
||||
"optional": true
|
||||
},
|
||||
"gcp-metadata": {
|
||||
"optional": true
|
||||
},
|
||||
"kerberos": {
|
||||
"optional": true
|
||||
},
|
||||
"mongodb-client-encryption": {
|
||||
"optional": true
|
||||
},
|
||||
"snappy": {
|
||||
"optional": true
|
||||
},
|
||||
"socks": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/match_collector/node_modules/mongodb-connection-string-url": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-7.0.1.tgz",
|
||||
"integrity": "sha512-h0AZ9A7IDVwwHyMxmdMXKy+9oNlF0zFoahHiX3vQ8e3KFcSP3VmsmfvtRSuLPxmyv2vjIDxqty8smTgie/SNRQ==",
|
||||
"dependencies": {
|
||||
"@types/whatwg-url": "^13.0.0",
|
||||
"whatwg-url": "^14.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mdn-data": {
|
||||
"version": "2.27.1",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"format:check": "prettier --check ."
|
||||
},
|
||||
"dependencies": {
|
||||
"match_collector": "file:../match_collector",
|
||||
"dragon-item-parser": "file:../dragon-item-parser",
|
||||
"@nuxt/eslint": "^1.12.1",
|
||||
"@nuxt/fonts": "^0.11.3",
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
import type { ChampionData } from 'match_collector'
|
||||
|
||||
const route = useRoute()
|
||||
const championAlias = route.params.alias as string
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import { LANE_IMAGES, lanePositionToIndex, POSITIONS_STR } from '~/utils/cdragon'
|
||||
|
||||
import type { LaneData, ChampionData, Champion } from 'match_collector'
|
||||
|
||||
const route = useRoute()
|
||||
const lane = route.params.lane as string
|
||||
|
||||
const { data: championsData }: ChampionsResponse = await useFetch('/api/cdragon/champion-summary')
|
||||
const { data: championsData }: { data: Ref<Array<Champion>> } = await useFetch(
|
||||
'/api/cdragon/champion-summary'
|
||||
)
|
||||
|
||||
const { data: championsLanes }: { data: Ref<Array<ChampionData>> } =
|
||||
await useFetch('/api/champions')
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { MongoClient } from 'mongodb'
|
||||
import type { ChampionData } from 'match_collector'
|
||||
import { connectToDatabase, fetchLatestPatch } from '../../utils/mongo'
|
||||
|
||||
async function championInfos(client: MongoClient, patch: string, championAlias: string) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { MongoClient } from 'mongodb'
|
||||
import type { ChampionData } from 'match_collector'
|
||||
import { connectToDatabase, fetchLatestPatch } from '../utils/mongo'
|
||||
|
||||
async function champions(client: MongoClient, patch: string) {
|
||||
@@ -11,7 +12,6 @@ async function champions(client: MongoClient, patch: string) {
|
||||
if (x.lanes != undefined && x.lanes != null) {
|
||||
for (const lane of x.lanes) {
|
||||
delete lane.builds
|
||||
delete lane.runes
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
declare global {
|
||||
/**
|
||||
* Item tags derived from purchase patterns
|
||||
*/
|
||||
type ItemTag = 'ahead' | 'behind' | 'region_euw' | 'region_eun' | 'region_na' | 'region_kr'
|
||||
|
||||
/**
|
||||
* Represents an item in the build tree
|
||||
*/
|
||||
interface ItemTree {
|
||||
count: number
|
||||
data: number
|
||||
children: ItemTree[]
|
||||
tags: ItemTag[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a complete build with runes and items
|
||||
*/
|
||||
interface Build {
|
||||
runeKeystone: number
|
||||
runes: Rune[]
|
||||
items: ItemTree
|
||||
bootsFirst: number
|
||||
count: number
|
||||
boots: Array<{ count: number; data: number }>
|
||||
suppItems: Array<{ count: number; data: number }>
|
||||
startItems: Array<{ count: number; data: number }>
|
||||
pickrate: number
|
||||
firstBacks?: FirstBackGroup[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents champion build information (array of builds)
|
||||
*/
|
||||
type Builds = Array<Build>
|
||||
|
||||
/**
|
||||
* Represents a rune configuration
|
||||
*/
|
||||
interface Rune {
|
||||
count: number
|
||||
primaryStyle: number
|
||||
secondaryStyle: number
|
||||
selections: number[]
|
||||
pickrate: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents counter data for a champion
|
||||
*/
|
||||
interface MatchupData {
|
||||
championId: number
|
||||
winrate: number
|
||||
games: number
|
||||
championName: string
|
||||
championAlias: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an item in a first back item set
|
||||
*/
|
||||
interface FirstBackItemSetEntry {
|
||||
itemId: number
|
||||
count: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an item set (combination of items)
|
||||
*/
|
||||
interface ItemSet {
|
||||
items: FirstBackItemSetEntry[]
|
||||
totalGold: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a grouped first back by item set
|
||||
*/
|
||||
interface FirstBackGroup {
|
||||
itemSet: ItemSet
|
||||
count: number
|
||||
pickrate: number
|
||||
avgTimestamp: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents lane-specific champion data
|
||||
*/
|
||||
interface LaneData {
|
||||
data: string
|
||||
count: number
|
||||
winningMatches: number
|
||||
losingMatches: number
|
||||
winrate: number
|
||||
pickrate: number
|
||||
builds?: Builds
|
||||
summonerSpells: Array<{ id: number; count: number; pickrate: number }>
|
||||
matchups?: MatchupData[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents complete champion data
|
||||
*/
|
||||
interface ChampionData {
|
||||
id: number
|
||||
name: string
|
||||
alias: string
|
||||
gameCount: number
|
||||
winrate: number
|
||||
pickrate: number
|
||||
lanes: LaneData[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Champion summary from CDragon
|
||||
*/
|
||||
interface ChampionSummary {
|
||||
id: number
|
||||
name: string
|
||||
alias: string
|
||||
squarePortraitPath: string
|
||||
// Add other relevant fields as needed
|
||||
}
|
||||
}
|
||||
|
||||
export {}
|
||||
@@ -1,60 +1,43 @@
|
||||
import type { ItemStats } from 'dragon-item-parser'
|
||||
|
||||
declare global {
|
||||
type ChampionsResponse = {
|
||||
data: Ref<Array<Champion>>
|
||||
}
|
||||
type ChampionResponse = {
|
||||
data: Ref<ChampionFull>
|
||||
}
|
||||
type Champion = {
|
||||
name: string
|
||||
alias: string
|
||||
squarePortraitPath: string
|
||||
}
|
||||
type ChampionFull = {
|
||||
name: string
|
||||
alias: string
|
||||
squarePortraitPath: string
|
||||
title: string
|
||||
}
|
||||
type ItemResponse = {
|
||||
data: Ref<Array<Item>>
|
||||
}
|
||||
type Item = {
|
||||
id: number
|
||||
iconPath: string
|
||||
name?: string
|
||||
description?: string
|
||||
plaintext?: string
|
||||
into?: number[]
|
||||
from?: number[]
|
||||
price?: number
|
||||
priceTotal?: number
|
||||
stats?: ItemStats
|
||||
}
|
||||
type SummonerSpell = {
|
||||
id: number
|
||||
iconPath: string
|
||||
name: string
|
||||
}
|
||||
type PerksResponse = {
|
||||
data: Ref<Array<Perk>>
|
||||
}
|
||||
type Perk = {
|
||||
id: number
|
||||
name: string
|
||||
iconPath: string
|
||||
}
|
||||
type PerkStylesResponse = {
|
||||
data: Ref<{ styles: Array<PerkStyle> }>
|
||||
}
|
||||
type PerkStyle = {
|
||||
id: number
|
||||
name: string
|
||||
iconPath: string
|
||||
slots: Array<{ perks: Array<number> }>
|
||||
}
|
||||
type Champion = {
|
||||
name: string
|
||||
alias: string
|
||||
squarePortraitPath: string
|
||||
}
|
||||
type ChampionFull = {
|
||||
name: string
|
||||
alias: string
|
||||
squarePortraitPath: string
|
||||
title: string
|
||||
}
|
||||
type Item = {
|
||||
id: number
|
||||
iconPath: string
|
||||
name?: string
|
||||
description?: string
|
||||
plaintext?: string
|
||||
into?: number[]
|
||||
from?: number[]
|
||||
price?: number
|
||||
priceTotal?: number
|
||||
stats?: ItemStats
|
||||
}
|
||||
type SummonerSpell = {
|
||||
id: number
|
||||
iconPath: string
|
||||
name: string
|
||||
}
|
||||
type Perk = {
|
||||
id: number
|
||||
name: string
|
||||
iconPath: string
|
||||
}
|
||||
type PerkStyle = {
|
||||
id: number
|
||||
name: string
|
||||
iconPath: string
|
||||
slots: Array<{ perks: Array<number> }>
|
||||
}
|
||||
|
||||
export {}
|
||||
export type { Champion, ChampionFull, Item, SummonerSpell, Perk, PerkStyle }
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { Build, ItemTree } from 'match_collector'
|
||||
|
||||
/**
|
||||
* Gets all late game items from the item tree (items beyond first level)
|
||||
* Returns a flat array of unique items with their counts
|
||||
@@ -55,7 +57,9 @@ function trimTreeDepth(tree: ItemTree, maxDepth: number, currentDepth: number =
|
||||
count: tree.count,
|
||||
data: tree.data,
|
||||
children: [],
|
||||
tags: tree.tags
|
||||
tags: tree.tags,
|
||||
boughtWhen: tree.boughtWhen,
|
||||
platformCount: tree.platformCount
|
||||
}
|
||||
|
||||
// If we haven't reached maxDepth, include children
|
||||
|
||||
Reference in New Issue
Block a user