Skip to content

Commit 0cf2990

Browse files
committed
Cleaning up for card leality post compilation / pre-writting
1 parent 5642f4a commit 0cf2990

7 files changed

Lines changed: 87 additions & 171 deletions

File tree

server/compiler/endpoints/cards.ts

Lines changed: 4 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -2,99 +2,12 @@ import { SupportedLanguages } from '../../../interfaces'
22
import { FileFunction } from '../compilerInterfaces'
33
import { cardToCardSingle, getCards } from '../utils/cardUtil'
44

5-
// Cache to track Trainer card names and their legality status
6-
interface TrainerLegalityCache {
7-
[cardName: string]: {
8-
standard: boolean
9-
expanded: boolean
10-
}
11-
}
12-
135
const fn: FileFunction = async (lang: SupportedLanguages) => {
146
const common = await getCards(lang)
15-
const trainerCache: TrainerLegalityCache = {}
16-
17-
// Separate cards into Trainers and non-Trainers
18-
const trainerCards: Array<[string, typeof common[0][1]]> = []
19-
const otherCards: Array<[string, typeof common[0][1]]> = []
20-
21-
for (const [localId, card] of common) {
22-
if (card.category === 'Trainer') {
23-
trainerCards.push([localId, card])
24-
} else {
25-
otherCards.push([localId, card])
26-
}
27-
}
28-
29-
console.log(`[DEBUG] Total cards: ${common.length}, Trainers: ${trainerCards.length}, Others: ${otherCards.length}`)
30-
if (trainerCards.length > 0) {
31-
console.log(`[DEBUG] First trainer card: ${trainerCards[0][1].name.en} (${trainerCards[0][1].set.id})`)
32-
}
33-
34-
// Process Trainer cards sequentially to build the cache
35-
const trainerResults = []
36-
for (const [localId, card] of trainerCards) {
37-
try {
38-
const compiledCard = await cardToCardSingle(localId, card, lang, trainerCache)
39-
trainerResults.push(compiledCard)
40-
41-
// Update cache for Trainer cards using English name as key
42-
const cardNameEn = card.name.en
43-
if (cardNameEn) {
44-
trainerCache[cardNameEn] = {
45-
standard: compiledCard.legal.standard,
46-
expanded: compiledCard.legal.expanded
47-
}
48-
if (trainerResults.length < 5) {
49-
console.log(`[DEBUG] Cached trainer: ${cardNameEn} - standard: ${compiledCard.legal.standard}, expanded: ${compiledCard.legal.expanded}`)
50-
}
51-
}
52-
} catch (e) {
53-
console.error('error compiling card', `${card.set.id}-${localId}`, e)
54-
throw e
55-
}
56-
}
57-
58-
// Process other cards in parallel (they don't need the cache)
59-
const otherResults = await Promise.all(
60-
otherCards.map(([localId, card]) =>
61-
cardToCardSingle(localId, card, lang).catch((e) => {
62-
console.error('error compiling card', `${card.set.id}-${localId}`, e)
63-
throw e
64-
})
65-
)
66-
)
67-
68-
const allResults = new Map<string, typeof trainerResults[0]>()
69-
70-
// Add trainer results
71-
for (const result of trainerResults) {
72-
allResults.set(result.id, result)
73-
}
74-
75-
// Add other results
76-
for (const result of otherResults) {
77-
allResults.set(result.id, result)
78-
}
79-
80-
const results = common.map(([localId, card]) => {
81-
const cardId = `${card.set.id}-${localId}`
82-
const result = allResults.get(cardId)
83-
if (!result) {
84-
throw new Error(`Missing compiled card: ${cardId}`)
85-
}
86-
return result
87-
})
88-
89-
return results.sort((a, b) => {
90-
const dateA = typeof a.set.releaseDate === 'object'
91-
? Object.values(a.set.releaseDate)[0]
92-
: a.set.releaseDate
93-
const dateB = typeof b.set.releaseDate === 'object'
94-
? Object.values(b.set.releaseDate)[0]
95-
: b.set.releaseDate
96-
return dateA > dateB ? 1 : -1
97-
})
7+
return await Promise.all(common.map((card) => cardToCardSingle(card[0], card[1], lang).catch((e) => {
8+
console.error('error compiling card', `${card[1].set.id}-${card[0]}`, e)
9+
throw e
10+
})))
9811
}
9912

10013
export default fn

server/compiler/endpoints/series.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,7 @@ import { getSeries, serieToSerieSingle } from '../utils/serieUtil'
44

55
const fn: FileFunction = async (lang: SupportedLanguages) => {
66
const common = await getSeries(lang)
7-
const results = await Promise.all(common.map((val) => serieToSerieSingle(val, lang)))
8-
9-
return results.sort((a, b) => {
10-
const dateA = typeof a.releaseDate === 'object'
11-
? Object.values(a.releaseDate)[0]
12-
: a.releaseDate
13-
const dateB = typeof b.releaseDate === 'object'
14-
? Object.values(b.releaseDate)[0]
15-
: b.releaseDate
16-
return dateA > dateB ? 1 : -1
17-
})
7+
return await Promise.all(common.map((val) => serieToSerieSingle(val, lang)))
188
}
199

2010
export default fn

server/compiler/endpoints/sets.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,7 @@ import { FileFunction } from '../compilerInterfaces'
55

66
const fn: FileFunction = async (lang: SupportedLanguages) => {
77
const common = await getSets(undefined, lang)
8-
const results = await Promise.all(common.map((set) => setToSetSingle(set, lang)))
9-
10-
return results.sort((a, b) => {
11-
const dateA = typeof a.releaseDate === 'object'
12-
? Object.values(a.releaseDate)[0]
13-
: a.releaseDate
14-
const dateB = typeof b.releaseDate === 'object'
15-
? Object.values(b.releaseDate)[0]
16-
: b.releaseDate
17-
return dateA > dateB ? 1 : -1
18-
})
8+
return await Promise.all(common.map((set) => setToSetSingle(set, lang)))
199
}
2010

2111
export default fn

server/compiler/index.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
/* eslint-disable max-statements */
2-
import { existsSync, promises as fs } from 'fs'
2+
import { promises as fs } from 'fs'
33
import { SupportedLanguages } from '../../interfaces'
44
import { FileFunction } from './compilerInterfaces'
55
import { fetchRemoteFile, loadLastEdits } from './utils/util'
6+
import { enhanceTrainerLegality, getCards } from './utils/cardUtil'
7+
import { Card as CardSingle } from '../../meta/definitions/api'
68

79
const LANGS: Array<SupportedLanguages> = [
810
'en', 'fr', 'es', 'es-mx', 'it', 'pt', 'pt-br', 'pt-pt', 'de', 'nl', 'pl', 'ru',
@@ -54,7 +56,14 @@ const DIST_FOLDER = './generated'
5456

5557
// Run the function
5658
console.log(' ', 'Compiling', lang, file)
57-
const item = await fn(lang)
59+
let item = await fn(lang)
60+
61+
// Post-process Trainer legality after compilation but before writing JSON
62+
if (file === 'cards.ts' && Array.isArray(item)) {
63+
console.log(' ', 'Post-processing Trainer legality', lang)
64+
const originalCards = await getCards(lang)
65+
item = enhanceTrainerLegality(item as Array<CardSingle>, originalCards)
66+
}
5867

5968
// Write to file
6069
await fs.writeFile(`${folder}/${file.replace('.ts', '')}.json`, JSON.stringify(

server/compiler/utils/cardUtil.ts

Lines changed: 65 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,66 @@ import { DB_PATH, cardIsLegal, fetchRemoteFile, getDataFolder, getLastEdit, reso
88
import { objectMap, objectPick } from '@dzeio/object-util'
99
import { variant_detailed } from "../../public/v2/api";
1010

11+
/**
12+
* Post-processes compiled cards to enhance Trainer legality based on reprints.
13+
* If any reprint of a Trainer card is legal, all cards with the same English name are marked as legal.
14+
*/
15+
export function enhanceTrainerLegality(
16+
compiledCards: Array<CardSingle>,
17+
originalCards: Array<[string, Card]>
18+
): Array<CardSingle> {
19+
const originalCardMap = new Map<string, Card>()
20+
for (const [localId, card] of originalCards) {
21+
const cardId = `${card.set.id}-${localId}`
22+
originalCardMap.set(cardId, card)
23+
}
24+
25+
const trainerCardsByName = new Map<string, Array<{ compiled: CardSingle; original: Card; localId: string }>>()
26+
27+
for (const compiledCard of compiledCards) {
28+
const originalCard = originalCardMap.get(compiledCard.id)
29+
if (!originalCard || originalCard.category !== 'Trainer') {
30+
continue
31+
}
32+
33+
const cardNameEn = originalCard.name.en
34+
if (!cardNameEn) {
35+
continue
36+
}
37+
38+
if (!trainerCardsByName.has(cardNameEn)) {
39+
trainerCardsByName.set(cardNameEn, [])
40+
}
41+
42+
trainerCardsByName.get(cardNameEn)!.push({
43+
compiled: compiledCard,
44+
original: originalCard,
45+
localId: compiledCard.localId
46+
})
47+
}
48+
49+
for (const [cardNameEn, cardsWithName] of trainerCardsByName) {
50+
let hasLegalStandard = false
51+
let hasLegalExpanded = false
52+
53+
for (const { compiled } of cardsWithName) {
54+
if (compiled.legal.standard) {
55+
hasLegalStandard = true
56+
}
57+
if (compiled.legal.expanded) {
58+
hasLegalExpanded = true
59+
}
60+
}
61+
62+
for (const { compiled } of cardsWithName) {
63+
compiled.legal.standard = hasLegalStandard || compiled.legal.standard
64+
compiled.legal.expanded = hasLegalExpanded || compiled.legal.expanded
65+
}
66+
}
67+
68+
return compiledCards
69+
}
70+
1171
export async function getCardPictures(cardId: string, card: Card, lang: SupportedLanguages): Promise<string | undefined> {
1272
try {
1373
const file = await fetchRemoteFile('https://assets.tcgdex.net/datas.json')
@@ -76,8 +136,7 @@ function variantsToVariantsDetailed(variants: CardSingle['variants'],lang: Suppo
76136
export async function cardToCardSingle(
77137
localId: string,
78138
card: Card,
79-
lang: SupportedLanguages,
80-
trainerCache?: { [cardName: string]: { standard: boolean; expanded: boolean } }
139+
lang: SupportedLanguages
81140
): Promise<CardSingle> {
82141
const image = await getCardPictures(localId, card, lang)
83142

@@ -162,39 +221,10 @@ export async function cardToCardSingle(
162221
energyType: translate('energyType', card.energyType, lang) as any,
163222
regulationMark: card.regulationMark,
164223

165-
legal: (() => {
166-
// For Trainer cards, check if there's already a compiled card with the same name that is legal
167-
// Use English name as key to optimize cache size
168-
if (card.category === 'Trainer' && trainerCache) {
169-
const cardNameEn = card.name.en
170-
if (cardNameEn && trainerCache[cardNameEn]) {
171-
// If a card with the same name is already legal, mark this card as legal too
172-
const cachedLegal = trainerCache[cardNameEn]
173-
const normalStandard = cardIsLegal('standard', card, localId)
174-
const normalExpanded = cardIsLegal('expanded', card, localId)
175-
const finalStandard = cachedLegal.standard ? true : normalStandard
176-
const finalExpanded = cachedLegal.expanded ? true : normalExpanded
177-
178-
// Debug: log when cache is used and changes the result
179-
if (cachedLegal.standard && !normalStandard) {
180-
console.log(`[DEBUG] Trainer cache override: ${cardNameEn} (${card.set.id}-${localId}) - standard: ${normalStandard} -> ${finalStandard}`)
181-
}
182-
if (cachedLegal.expanded && !normalExpanded) {
183-
console.log(`[DEBUG] Trainer cache override: ${cardNameEn} (${card.set.id}-${localId}) - expanded: ${normalExpanded} -> ${finalExpanded}`)
184-
}
185-
186-
return {
187-
standard: finalStandard,
188-
expanded: finalExpanded
189-
}
190-
}
191-
}
192-
// Default behavior for non-Trainer cards or if no cache match
193-
return {
194-
standard: cardIsLegal('standard', card, localId),
195-
expanded: cardIsLegal('expanded', card, localId)
196-
}
197-
})(),
224+
legal: {
225+
standard: cardIsLegal('standard', card, localId),
226+
expanded: cardIsLegal('expanded', card, localId)
227+
},
198228
boosters: card.boosters ? objectMap(objectPick(card.set.boosters, ...card.boosters), (booster, id) => ({
199229
id: `boo_${card.set.id}-${id}`,
200230
name: resolveText(booster.name, lang),

server/compiler/utils/serieUtil.ts

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,13 @@ export async function getSeries(lang: SupportedLanguages): Promise<Array<Serie>>
4242
.reduce<Set | undefined>((p, c) => p ? p.releaseDate < c.releaseDate ? p : c : c, undefined) as Set
4343
] as [Serie, Set]))
4444

45-
return tmp.sort((a, b) => {
46-
if (!a[1] || !b[1]) return 0
47-
const dateA = typeof a[1].releaseDate === 'object' ? Object.values(a[1].releaseDate)[0] : a[1].releaseDate
48-
const dateB = typeof b[1].releaseDate === 'object' ? Object.values(b[1].releaseDate)[0] : b[1].releaseDate
49-
return dateA > dateB ? -1 : 1
50-
}).map((it) => it[0])
45+
return tmp.sort((a, b) => (a[1] ? a[1].releaseDate : '0') > (b[1] ? b[1].releaseDate : '0') ? 1 : -1).map((it) => it[0])
5146
}
5247

5348
export async function serieToSerieSimple(serie: Serie, lang: SupportedLanguages): Promise<SerieResume> {
5449
const setsTmp = await getSets(getSerieIdenti(serie,lang), lang)
5550
const sets = await Promise.all(setsTmp
56-
.sort((a, b) => {
57-
const dateA = typeof a.releaseDate === 'object' ? Object.values(a.releaseDate)[0] : a.releaseDate
58-
const dateB = typeof b.releaseDate === 'object' ? Object.values(b.releaseDate)[0] : b.releaseDate
59-
return dateA > dateB ? -1 : 1
60-
})
51+
.sort((a, b) => a.releaseDate > b.releaseDate ? 1 : -1)
6152
.map((el) => setToSetSimple(el, lang)))
6253
const logo = sets.find((set) => set.logo)?.logo
6354
return {
@@ -69,11 +60,7 @@ export async function serieToSerieSimple(serie: Serie, lang: SupportedLanguages)
6960

7061
export async function serieToSerieSingle(serie: Serie, lang: SupportedLanguages): Promise<SerieSingle> {
7162
const setsTmp = await getSets(getSerieIdenti(serie,lang), lang)
72-
const sortedSetsTmp = setsTmp.sort((a, b) => {
73-
const dateA = typeof a.releaseDate === 'object' ? Object.values(a.releaseDate)[0] : a.releaseDate
74-
const dateB = typeof b.releaseDate === 'object' ? Object.values(b.releaseDate)[0] : b.releaseDate
75-
return dateA > dateB ? -1 : 1
76-
})
63+
const sortedSetsTmp = setsTmp.sort((a, b) => a.releaseDate > b.releaseDate ? 1 : -1)
7764
const sets = await Promise.all(sortedSetsTmp.map((el) => setToSetSimple(el, lang)))
7865
const logo = (
7966
// find the set named after the serie

server/compiler/utils/setUtil.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,8 @@ export async function getSets(serie = '*', lang: SupportedLanguages): Promise<Ar
4646
const sets = (await Promise.all(rawSets.map((set) => getSet(set, serie, lang))))
4747
// Filter sets
4848
.filter((set) => isSetAvailable(set, lang))
49-
.sort((a, b) => {
50-
const dateA = typeof a.releaseDate === 'object' ? Object.values(a.releaseDate)[0] : a.releaseDate
51-
const dateB = typeof b.releaseDate === 'object' ? Object.values(b.releaseDate)[0] : b.releaseDate
52-
return dateA > dateB ? -1 : 1
53-
})
49+
// Sort sets by release date
50+
.sort((a, b) => a.releaseDate > b.releaseDate ? 1 : -1)
5451
return sets
5552
}
5653

0 commit comments

Comments
 (0)