Feat: Add commander and Bset stats

This commit is contained in:
globuzma 2025-01-27 12:40:17 +01:00
parent b2010dae41
commit 64a4c5fb87
24 changed files with 626 additions and 977 deletions

View file

@ -4,8 +4,12 @@ const db = new PrismaClient()
const Bsets = [
{"name": "Wild of Eldraine", sets: ["woe"]},
{"name": "Bloomburrow", sets: ["blb"]},
{"name": "Duskmourn", sets: ["dsk"]},
{"name": "Phyrexia", sets: ["one"]},
{"name": "The Brothers' War", sets: ["bro"]},
{"name": "Murders at Karlov Manor", sets: ["mkm"]},
{"name": "The lost caverns of Ixalan", sets: ["lci"]},
{"name": "Dominaria United", sets: ["dmu"]},
{"name": "New Capenna", sets: ["snc"]},
{"name": "Kamigawa", sets: ["neo"]},
@ -19,6 +23,7 @@ const Bsets = [
{"name": "War of the Spark", sets: ["war"]},
{"name": "Dominaria", sets: ["dom"]},
{"name": "March of the machine", sets: ["mom","mat"]},
{"name": "Outlaws", sets: ["otj","big"]},
{"name": "Innistrad Midnight Hunt", sets: ["vow","mid"]},
{"name": "Guilds of Ravnica", sets: ["rna","grn"]},
{"name": "Ixalan", sets: ["rix","xln"]},

49
app/tools/createDecks.mjs Normal file
View file

@ -0,0 +1,49 @@
import { readFileSync, readdirSync } from "fs"
const base_api_url = "http://localhost:3000"
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9.eyJ1c2VybmFtZSI6Imdsb2J1em1hIiwiYWRtaW4iOnRydWUsImlkIjoiMDc4YWViYTYtNzZlNC00YzRkLTg3NjYtNjA0N2JhNjkxM2Y5IiwibWF4QWdlIjo2MDQ4MDB9.acd6b0fab88719f708fa0553f18a6b034b2c3a84659e3a63b32e87f22c611d3e"
let bsets_sanitized_names = readdirSync(import.meta.dirname + "/data/bsets/")
function get_line_data(line) {
let data = line.split(" ")
let amount = parseInt(data[0])
let name = data.slice(1).join(" ").split("/")[0].replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase()
return {"sanitized_name":name, "amount":amount}
}
for(const sanitized_name of bsets_sanitized_names) {
let path = import.meta.dirname + "/data/bsets/" + sanitized_name + "/"
let deck_files = readdirSync(path)
for( const deck_file of deck_files) {
let api_object = {
"selected_bset": sanitized_name,
"name": deck_file.split(".txt")[0],
"commander_name": "",
"cards": []
}
let data = readFileSync(path + deck_file, 'utf8')
let lines = data.split(/\n/)
lines = lines.filter((line) => line.match(/[0-9]+\s[\w]+/) != undefined)
let commander_line = lines[lines.length - 1]
api_object["commander_name"] = get_line_data(commander_line).sanitized_name
for(const card of lines.slice(0, lines.length - 1)){
api_object.cards.push(get_line_data(card))
}
fetch(base_api_url + '/api/account/decks/create', {
method: "POST",
headers: {Authorization: 'Bearer ' + token},
body: JSON.stringify(api_object)
}).then((res) => {
if(res.status == 200) {
console.log("Deck created")
} else {
console.log("Problem with : " + deck_file)
}
})
}
}

View file

@ -4,11 +4,11 @@ import { writeFileSync } from 'fs'
const db = new PrismaClient()
const color_names = {
"mono-white": ["W"],
"mono-black": ["B"],
"mono-blue": ["U"],
"mono-green": ["G"],
"mono-red": ["R"],
"white": ["W"],
"black": ["B"],
"blue": ["U"],
"green": ["G"],
"red": ["R"],
"colorless": [],
"azorius": ["W","U"],
"dimir": ["U","B"],
@ -49,6 +49,15 @@ function getColorName(colorArray) {
}
// I need to create
//
// Commanders
// top all
// top by colors
//
// bsets
// Commanders
//
//
// Lands
// lands.json
// All jsons lands from colors
@ -63,21 +72,38 @@ async function createJson() {
include: {
cards: {
include: {
decks: true
decks: true,
decks_as_commander: true,
}
}
}
},
decks: true
decks: {
include: {
commander: {
include: {
decks_as_commander: true
}
}
}
}
}
})
let bsets_export = []
let bsets_list_export = []
let all_cards = []
const commanderData = {"top": []}
for (const colorName of Object.keys(color_names)) {
commanderData[colorName] = []
}
let bset_cards_data_export = {}
bsets.forEach((bset) => {
let icons = []
let set_codes = []
let bset_cards = []
bset.sets.forEach((set) => {
icons.push(set.icon_svg_uri)
set_codes.push(set.code)
@ -85,76 +111,78 @@ async function createJson() {
for(let i = 0; i < cards_temp.length; i++){
cards_temp[i].bset_id = bset.id
}
bset_cards = [...bset_cards, ...cards_temp]
all_cards = [...all_cards, ...cards_temp]
})
bsets_export.push({name: bset.name, sanitized_name: bset.sanitized_name, icons, set_codes})
})
writeFileSync(import.meta.dirname + "/json/misc/bsets.json",JSON.stringify(bsets_export), 'utf8')
const landsData = {}
for (const colorName of Object.keys(color_names)) {
landsData[colorName] = []
}
const type_dict = {"creature": [],"land": [],"instant": [],"sorcery": [], "planeswalker": [], "artifact": [], "enchantment": []}
const colorsData = {"mono-white": structuredClone(type_dict),"mono-black": structuredClone(type_dict),"mono-blue": structuredClone(type_dict),"mono-green": structuredClone(type_dict),"mono-red": structuredClone(type_dict),"colorless": structuredClone(type_dict),"multicolor": structuredClone(type_dict)}
for (const card of all_cards) {
let card_object = {
"name": card.name,
"sanitized_name": card.sanitized_name,
"normal_image": card.normal_image,
"small_image": card.small_image,
"type": card.type,
"layout": card.layout,
"price": card.price,
"cardmarket_uri": card.cardmarket_uri,
"nbr_decks": card.decks.length,
"total_decks": bsets.find((bset) => bset.id == card.bset_id).decks.length,
"colors": card.colors,
bsets_list_export.push({name: bset.name, sanitized_name: bset.sanitized_name, icons, set_codes})
// BSETS CARDS STATS
bset_cards_data_export[bset.sanitized_name] = {
"commander": [],
"creature": [],
"land": [],
"enchantment": [],
"sorcery": [],
"instant": [],
"planeswalker": [],
"artifact": [],
}
card_object.percent_decks = (card_object.total_decks != 0) ? parseInt(10000 * (card_object.nbr_decks / card_object.total_decks)) / 100 : 0
for (const card of bset_cards) {
let card_object = {
"name": card.name,
"sanitized_name": card.sanitized_name,
"normal_image": card.normal_image,
"small_image": card.small_image,
"type": card.type,
"layout": card.layout,
"price": card.price,
"cardmarket_uri": card.cardmarket_uri,
"nbr_decks": card.decks.length,
"total_decks": bset.decks.filter((deck) => card.color_identity.every(color => deck.color_identity.includes(color))).length,
"color_identity": card.color_identity,
}
const colorName = getColorName(card.colors)
if (card.type == "land") {
if (colorName != "") {
landsData[colorName].push(card_object)
card_object.percent_decks = (card_object.total_decks != 0) ? parseInt(10000 * (card_object.nbr_decks / card_object.total_decks)) / 100 : 0
bset_cards_data_export[bset.sanitized_name][card.type].push(card_object)
if(card.can_be_commander) {
card_object.total_decks = bset.decks.length
card_object.nbr_decks = card.decks_as_commander != undefined ? card.decks_as_commander.length : 0
card_object.percent_decks = (card_object.total_decks != 0) ? parseInt(10000 * (card_object.nbr_decks / card_object.total_decks)) / 100 : 0
bset_cards_data_export[bset.sanitized_name]["commander"].push(card_object)
const colorName = getColorName(card.color_identity)
if(colorName != "") {
commanderData[colorName].push(card_object)
commanderData["top"].push(card_object)
}
}
}
})
if (card.colors.length <= 1) {
colorsData[colorName][card.type].push(card_object)
} else {
colorsData["multicolor"][card.type].push(card_object)
}
writeFileSync(import.meta.dirname + "/json/misc/bsets.json",JSON.stringify(bsets_list_export), 'utf8')
//for (const card of all_cards) {
//}
for (const index of Object.keys(commanderData)) {
let JSONToWrite = commanderData[index].sort((a,b) => b.percent_decks - a.percent_decks)
writeFileSync(import.meta.dirname + "/json/commander/" + index + ".json",JSON.stringify(JSONToWrite), 'utf8')
}
for (const index of Object.keys(colorsData)) {
let JSONToWrite = colorsData[index]
for (const key of Object.keys(JSONToWrite)){
JSONToWrite[key].sort((a,b) => b.percent_decks - a.percent_decks)
for (const index of Object.keys(bset_cards_data_export)) {
let JSONToWrite = bset_cards_data_export[index]
for (const type of Object.keys(JSONToWrite)) {
JSONToWrite[type] = JSONToWrite[type].sort((a,b) => b.percent_decks - a.percent_decks)
}
writeFileSync(import.meta.dirname + "/json/top/" + index + ".json",JSON.stringify(JSONToWrite), 'utf8')
writeFileSync(import.meta.dirname + "/json/bset/" + index + ".json",JSON.stringify(JSONToWrite), 'utf8')
}
const landsJsonRoot = [[],[],[],[]]
for (const colorName of Object.keys(color_names)){
if(color_names[colorName].length <= 3){
let index = color_names[colorName].length - 1
if(index < 0) { index = 0 }
landsJsonRoot[index].push({ "name": colorName, "count": landsData[colorName].length})
} else {
landsJsonRoot[3].push({ "name": colorName, "count": landsData[colorName].length})
}
let JSONToWrite = landsData[colorName]
JSONToWrite.sort((a,b) => b.percent_decks - a.percent_decks)
writeFileSync(import.meta.dirname + "/json/lands/" + colorName + ".json",JSON.stringify(JSONToWrite), 'utf8')
}
writeFileSync(import.meta.dirname + "/json/lands/lands.json",JSON.stringify(landsJsonRoot), 'utf8')
}
createJson()

View file

@ -54,11 +54,16 @@ try {
// For each card check if we need to upload it to the database
for (const carte of scryfallData) {
if(!preUpdateCardsIds.includes(carte.id) && carte.layout != "art_series"){
if(!preUpdateCardsIds.includes(carte.id) && carte.legalities.commander != "not_legal"){
let type = ""
const layout = carte.layout
const card_type = (carte.type_line == undefined) ? carte.card_faces[0].type_line.toLowerCase() : carte.type_line.toLowerCase()
let promo = (carte.promo_types == undefined) ? false : true
let can_be_commander = (card_type.includes("legendary") && (card_type.includes("creature") || card_type.includes("planeswalker"))) ? true : false
if(card_type.includes("creature")){
type = "creature"
} else if (card_type.includes("planeswalker")) {
@ -77,10 +82,10 @@ try {
try {
if(two_faced_layouts.includes(layout)) {
const addingCardsQuery = await client.query('INSERT INTO carte(id, name, released_at, small_image, small_image_back, normal_image, normal_image_back, type_line, colors, set_id, rarity, cardmarket_uri, price, type, sanitized_name, set_code, layout) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)', [carte.id, carte.name, carte.released_at, carte.card_faces[0].image_uris.small, carte.card_faces[1].image_uris.small, carte.card_faces[0].image_uris.normal, carte.card_faces[0].image_uris.normal, carte.type_line, carte.color_identity, carte.set_id, carte.rarity, carte.purchase_uris?.cardmarket, carte.prices.eur, type, carte.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase(), carte.set, layout])
const addingCardsQuery = await client.query('INSERT INTO carte(id, name, released_at, small_image, small_image_back, normal_image, normal_image_back, type_line, color_identity, set_id, rarity, cardmarket_uri, price, type, sanitized_name, set_code, layout, is_promo, can_be_commander) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)', [carte.id, carte.name, carte.released_at, carte.card_faces[0].image_uris.small, carte.card_faces[1].image_uris.small, carte.card_faces[0].image_uris.normal, carte.card_faces[0].image_uris.normal, carte.type_line, carte.color_identity, carte.set_id, carte.rarity, carte.purchase_uris?.cardmarket, carte.prices.eur, type, carte.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase(), carte.set, layout, promo, can_be_commander])
} else {
const addingCardsQuery = await client.query('INSERT INTO carte(id, name, released_at, small_image, normal_image, type_line, colors, set_id, rarity, cardmarket_uri, price, type, sanitized_name, set_code, layout) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)', [carte.id, carte.name, carte.released_at, carte.image_uris.small, carte.image_uris.normal, carte.type_line, carte.color_identity, carte.set_id, carte.rarity, carte.purchase_uris?.cardmarket, carte.prices.eur, type, carte.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase(), carte.set, layout])
const addingCardsQuery = await client.query('INSERT INTO carte(id, name, released_at, small_image, normal_image, type_line, color_identity, set_id, rarity, cardmarket_uri, price, type, sanitized_name, set_code, layout, is_promo, can_be_commander) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)', [carte.id, carte.name, carte.released_at, carte.image_uris.small, carte.image_uris.normal, carte.type_line, carte.color_identity, carte.set_id, carte.rarity, carte.purchase_uris?.cardmarket, carte.prices.eur, type, carte.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase(), carte.set, layout, promo, can_be_commander])
}
total_inserted = total_inserted + 1
@ -94,6 +99,7 @@ try {
// Add the card to the database
} else {
total_skipped = total_skipped + 1
}
}