1
0
mirror of https://github.com/tcgdex/cards-database.git synced 2025-04-22 10:52:10 +00:00
Signed-off-by: Avior <git@avior.me>
This commit is contained in:
Florian Bouillon 2025-01-30 22:25:14 +01:00
parent a33629e883
commit a22e89b3f2
7 changed files with 185 additions and 1 deletions

View File

@ -19,6 +19,62 @@ const set: Set = {
official: 226
},
boosters: {
charizard: {
en: 'Charizard',
fr: 'Dracaufeu'
},
mewtwo: {
en: 'Mewtwo',
fr: 'Mewtwo'
},
pikachu: {
en: 'Pikachu',
fr: 'Pikachu'
}
},
// data fetched from the Pokemon TCG Pocket app
pullRates: {
'normal': {
rate: 99.95,
slots: [
{ 'One Diamond': 100 },
{ 'One Diamond': 100 },
{ 'One Diamond': 100 },
{
'Crown': 0.04,
'Three Star': 0.222,
'Two Star': 0.5,
'One Star': 2.572,
'Four Diamond': 1.666,
'Three Diamond': 5,
'Two Diamond': 90
},
{
'Crown': 0.16,
'Three Star': 0.888,
'Two Star': 2,
'One Star': 10.288,
'Four Diamond': 6.664,
'Three Diamond': 20,
'Two Diamond': 60
}
]
},
godpack: {
rate: 0.05,
slots: [
{
'Crown': 5,
'Three Star': 5,
'Two Star': 50,
'One Star': 40
}
]
}
},
releaseDate: "2024-10-30"
}

View File

@ -8,6 +8,10 @@ const card: Card = {
en: "Bulbasaur"
},
boosters: [
'mewtwo'
],
illustrator: "Narumi Sato",
category: "Pokemon",
hp: 70,

View File

@ -19,6 +19,47 @@ const set: Set = {
official: 68
},
// data fetched from the Pokemon TCG Pocket app
pullRates: {
'normal': {
rate: 99.95,
slots: [
{ 'One Diamond': 100 },
{ 'One Diamond': 100 },
{ 'One Diamond': 100 },
{
'Crown': 0.04,
'Three Star': 0.222,
'Two Star': 0.5,
'One Star': 2.572,
'Four Diamond': 1.666,
'Three Diamond': 5,
'Two Diamond': 90
},
{
'Crown': 0.16,
'Three Star': 0.888,
'Two Star': 2,
'One Star': 10.288,
'Four Diamond': 6.664,
'Three Diamond': 20,
'Two Diamond': 60
}
]
},
godpack: {
rate: 0.05,
slots: [
{
'Crown': 5,
'Three Star': 5,
'Two Star': 50,
'One Star': 40
}
]
}
},
releaseDate: "2024-12-17"
}

21
interfaces.d.ts vendored
View File

@ -74,9 +74,25 @@ export interface Set {
official: number
}
/**
* the names of the booster packs the set has
*/
boosters?: Record<string, Languages>
/**
* list of pull rates by slot (from frontmost card to backmost card)
*/
pullRates?: Partial<Record<'normal' | 'godpack', Pull>>
releaseDate: ISODate | Languages<ISODate>
}
interface Pull {
slots: Array<Partial<Record<Card['rarity'], number>>>
rate: number
}
export interface Card {
/**
* Card Name (Including the suffix if next to card name)
@ -88,6 +104,11 @@ export interface Card {
*/
illustrator?: string
/**
* indicate in which booster pack the card can be pulled
*/
boosters?: Array<string>
/**
* Card Rarity
*

View File

@ -95,6 +95,11 @@ export interface Set extends SetResume {
*/
firstEd?: number;
};
boosters?: Array<string>
pullRates?: Partial<Record<'normal' | 'godpack', {
slots: Array<Partial<Record<Card['rarity'], number>>>
rate: number
}>>
cards: Array<CardResume>;
abbreviation: { official: string, localized: string };
}
@ -113,6 +118,26 @@ export interface CardResume {
* /sets/:set/:localId
*/
export interface Card extends CardResume {
/**
* indicate in which booster the card is openable from
*
* note1: if boosters is empty (`length == 0`) the card is unobtainable from boosters (ex: `A1` Mew that is obtainable from an hidden mission)
*
* note2: if boosters is not set, the card is available in every boosters
*/
boosters?: Array<string>
pullRates?: Record<string, {
rate: number
/**
* raw rate ignoring the type rate
*/
slots: Array<number>
/**
* rate including the base rate
*/
total_slots: Array<number>
}>
/**
* Card illustrator
*/

View File

@ -5,6 +5,7 @@ import { CardResume, Card as CardSingle } from '../../../meta/definitions/api'
import { getSet, setToSetSimple } from './setUtil'
import translate from './translationUtil'
import { DB_PATH, cardIsLegal, fetchRemoteFile, getDataFolder, getLastEdit, smartGlob } from './util'
import { objectRemap, objectSize } from '@dzeio/object-util'
export async function getCardPictures(cardId: string, card: Card, lang: SupportedLanguages): Promise<string | undefined> {
try {
@ -41,6 +42,21 @@ export async function cardToCardSingle(localId: string, card: Card, lang: Suppor
throw new Error(`Card (${localId}) dont exist in (${lang})`)
}
const set = card.set
const pullRates: CardSingle['pullRates'] = {}
if (set.pullRates) {
for (const type of Object.keys(set.pullRates)) {
const value = set.pullRates[type]
pullRates[type] = {
rate: value.rate,
slots: await Promise.all(value.slots.map(async (it) => it[card.rarity] ? await getPullRate(set, card, it[card.rarity], lang) : 0)),
total_slots: await Promise.all(value.slots.map(async (it) => it[card.rarity] ? await getPullRate(set, card, it[card.rarity] * (value.rate / 100), lang) : 0)),
}
}
}
return {
category: translate('category', card.category, lang) as any,
id: `${card.set.id}-${localId}`,
@ -59,6 +75,8 @@ export async function cardToCardSingle(localId: string, card: Card, lang: Suppor
wPromo: typeof card.variants?.wPromo === 'boolean' ? card.variants.wPromo : false
},
boosters: card.boosters,
pullRates: objectSize(pullRates) > 0 ? pullRates : undefined,
dexId: card.dexId,
hp: card.hp,
@ -126,6 +144,23 @@ export async function getCard(set: Set, id: string, lang: SupportedLanguages): P
}
}
function arrayIntersect(first: Array<string>, second: Array<string>) {
return !!first.find((it) => second.includes(it))
}
async function getPullRate(set: Set, card: Card, totalRate: number, lang: SupportedLanguages) {
const otherCards = await getCards(lang, set)
.then((cards) => cards
.map((it) => it[1])
// filter cards with same rarity
// exclude cards that is only avialable in other boosters
.filter((it) => it.rarity === card.rarity && (!it.boosters || !card.boosters || arrayIntersect(card.boosters, it.boosters)))
)
const count = otherCards.length // remove one to exclude current card as it ill match itself
return 1 * (totalRate / 100) / count * 100
}
/**
* Get cards filtered by the language they are available in
* @param lang the language of the cards

View File

@ -1,4 +1,4 @@
import { objectKeys } from '@dzeio/object-util'
import { objectKeys, objectMap } from '@dzeio/object-util'
import { Set, SupportedLanguages } from '../../../interfaces'
import { SetResume, Set as SetSingle } from '../../../meta/definitions/api'
import { cardToCardSimple, getCards } from './cardUtil'
@ -101,6 +101,8 @@ export async function setToSetSingle(set: Set, lang: SupportedLanguages): Promis
id: set.serie.id,
name: set.serie.name[lang] as string
},
boosters: set.boosters ? objectMap(set.boosters, (v, k) => v[lang]) : undefined,
pullRates: set.pullRates,
symbol: pics[1],
tcgOnline: set.tcgOnline,
abbreviation: (set.abbreviations?.official || set.abbreviations?.[lang]) ? {