Feat: Add Synergy and Details to commander cards

This commit is contained in:
zuma 2025-02-19 19:55:46 +01:00
parent d402c7f2d6
commit dcbab5c99f
12 changed files with 253 additions and 29 deletions

1
.gitignore vendored
View file

@ -22,6 +22,7 @@ app/next-env.d.ts
app/tools/data/*
app/data/misc/*
app/data/commander/*
app/data/card-commander/*
app/data/bset/*
app/tools/json/*
app/.pg

View file

@ -23,5 +23,6 @@ tools/data/*
tools/json
data/misc/*
data/commander/*
data/card-commander/*
data/bset/*
.pg/

View file

@ -2,7 +2,7 @@
import { useEffect, useState, useRef } from 'react'
import { CardGroup } from '@/components/ui/card-group'
import {PlaneswalkerIcon, SorceryIcon, InstantIcon, CreatureIcon, EnchantmentIcon, LandIcon, ArtifactIcon} from '@/components/ui/symbols-icons'
import {CommanderIcon, PlaneswalkerIcon, SorceryIcon, InstantIcon, CreatureIcon, EnchantmentIcon, LandIcon, ArtifactIcon} from '@/components/ui/symbols-icons'
interface PageContentProps {
bset: string
@ -69,7 +69,7 @@ export default function PageContent({bset}: PageContentProps) {
<div>
<div className="flex flex-col items-center w-full">
<div ref={CardListRef} className="flex flex-col items-center mt-24 gap-4 max-w-6xl">
<CardGroup className="scroll-mt-16" groupName={"Commandants"} id="commander" showPercent={false} cards={commanderList} />
<CardGroup className="scroll-mt-16" groupName={"Commandants"} Icon={CommanderIcon} id="commander" commanderUrl={true} showPercent={false} cards={commanderList} />
<CardGroup className="scroll-mt-16" groupName={"Planeswalker"} Icon={PlaneswalkerIcon} id="planeswalker" cards={planeswalkerList} />
<CardGroup className="scroll-mt-16" groupName={"Créatures"} Icon={CreatureIcon} id="creature" cards={creatureList} />
<CardGroup className="scroll-mt-16" groupName={"Rituels"} Icon={SorceryIcon} id="sorcery" cards={sorceryList} />
@ -80,7 +80,7 @@ export default function PageContent({bset}: PageContentProps) {
</div>
</div>
<div className="fixed top-80 ml-8 flex flex-col gap-2 text-stone-500">
<a href="#commander" className={ scrollState == "commander" ? "text-black text-2xl" : ""}>Commandants</a>
<a href="#commander" className={`${scrollState == "commander" ? "text-black text-2xl" : "neutral-svg-filter"} flex flex-row items-center gap-1`}><CommanderIcon className={scrollState == "commander" ? "h-5" : "h-4"} />Commandants</a>
<a href="#planeswalker" className={`${scrollState == "planeswalker" ? "text-black text-2xl" : "neutral-svg-filter"} flex flex-row items-center gap-1`}><PlaneswalkerIcon className={scrollState == "planeswalker" ? "h-5" : "h-4"} />Planeswalker</a>
<a href="#creature" className={`${scrollState == "creature" ? "text-black text-2xl" : "neutral-svg-filter"} flex flex-row items-center gap-1`}><CreatureIcon className={scrollState == "creature" ? "h-5" : "h-4"} />Créatures</a>
<a href="#sorcery" className={`${scrollState == "sorcery" ? "text-black text-2xl" : "neutral-svg-filter"} flex flex-row items-center gap-1`}><SorceryIcon className={scrollState == "sorcery" ? "h-5" : "h-4"} />Rituels</a>

View file

@ -17,7 +17,7 @@ export default function PageContent({color}: PageContentProps) {
fetch('/api/json/commander/'+color+'.json').then((res) => {
if(res.status == 200) {
res.json().then((data) => {
const limit = 20
const limit = 100
setCommanderCardList(data.slice(0,limit))
setLoading(false)
console.log(data)
@ -29,7 +29,7 @@ export default function PageContent({color}: PageContentProps) {
<div className="flex flex-col items-center w-full">
<div className="flex flex-col items-center mt-24 mb-24 max-w-6xl">
{ loading && ( <Spinner className='mt-36' /> )}
{ !loading && ( <CardGroup groupName={"Top commandants - " + color} showPercent={false} cards={commanderCardList} /> )}
{ !loading && ( <CardGroup groupName={"Top commandants - " + color} showPercent={false} commanderUrl={true} cards={commanderCardList} /> )}
</div>
</div>
);

View file

@ -0,0 +1,10 @@
'use server'
import PageContent from './page_content'
export default async function Home({ params }: { params: { card_name: string } } ) {
const card_name = (await params).card_name
return (
<PageContent card_name={card_name}/>
);
}

View file

@ -0,0 +1,118 @@
'use client'
import { useEffect, useRef, useState } from 'react'
import { CardGroup } from '@/components/ui/card-group'
import { Spinner } from '@/components/ui/spinner'
import {PlaneswalkerIcon, SorceryIcon, InstantIcon, CreatureIcon, EnchantmentIcon, LandIcon, ArtifactIcon} from '@/components/ui/symbols-icons'
import { MTGCard } from '@/components/ui/mtg-card'
interface PageContentProps {
card_name: string
}
interface commanderCardData {
name: string,
normal_image: string,
nbr_decks: number,
total_decks: number,
price: string,
cardmarket_uri: string,
}
export default function PageContent({card_name}: PageContentProps) {
const [highSynergyList, setHighSynergyList] = useState([])
const [creatureList, setCreatureList] = useState([])
const [planeswalkerList, setPlaneswalkerList] = useState([])
const [instantList, setInstantList] = useState([])
const [sorceryList, setSorceryList] = useState([])
const [artifactList, setArtifactList] = useState([])
const [enchantmentList, setEnchantmentList] = useState([])
const [landList, setLandList] = useState([])
const [commanderCard, setCommanderCard] = useState<commanderCardData | null>(null)
const [loading, setLoading] = useState(true)
const [scrollState, setScrollState] = useState("commander")
const CardListRef = useRef<HTMLDivElement>(null)
useEffect(() => {
fetch('/api/json/card-commander/'+card_name+'.json').then((res) => {
if(res.status == 200) {
res.json().then((data) => {
setCommanderCard(data["card_data"])
setHighSynergyList(data["high_synergy"])
setCreatureList(data["creature"])
setPlaneswalkerList(data["planeswalker"])
setSorceryList(data["sorcery"])
setInstantList(data["instant"])
setEnchantmentList(data["enchantment"])
setLandList(data["land"])
setArtifactList(data["artifact"])
setLoading(false)
console.log(data)
})
}
})
}, [])
useEffect(() => {
const handleScroll = () => {
const windowHeight = window.innerHeight
const TOP_MARGIN = 0.1
const BOTTOM_MARGIN = 0.2
const card_children = CardListRef.current?.children
if (card_children) {
for (const child of card_children){
const targetBounds = child.getBoundingClientRect()
if( targetBounds.bottom > windowHeight * TOP_MARGIN && targetBounds.top < windowHeight * ( 1 - BOTTOM_MARGIN ) ) {
setScrollState(child.id)
break
}
}
}
};
// Add event listener to the window
window.addEventListener('scroll', handleScroll);
// Remove event listener when the component is unmounted
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
return (
<div>
<div className="flex flex-col items-center w-full">
<div className="flex flex-col items-center mt-24 mb-24 max-w-6xl">
{ loading && ( <Spinner className='mt-36' /> )}
{ !loading && (
<div ref={CardListRef} className="flex flex-col items-center mt-24 gap-4 max-w-6xl">
<div className="w-full flex flex-col items-center">
<MTGCard className="w-64 h-auto" cardname={commanderCard!.name} imageURI={commanderCard!.normal_image} url={undefined} nbrDecks={commanderCard?.nbr_decks} totalDecks={commanderCard?.total_decks} price={commanderCard?.price} cardmarketURI={commanderCard?.cardmarket_uri}/>
</div>
<CardGroup className="scroll-mt-16" groupName={"Haute synergie"} Icon={undefined} id="highsynergy" cards={highSynergyList} />
<CardGroup className="scroll-mt-16" groupName={"Planeswalker"} Icon={PlaneswalkerIcon} id="planeswalker" cards={planeswalkerList} />
<CardGroup className="scroll-mt-16" groupName={"Créatures"} Icon={CreatureIcon} id="creature" cards={creatureList} />
<CardGroup className="scroll-mt-16" groupName={"Rituels"} Icon={SorceryIcon} id="sorcery" cards={sorceryList} />
<CardGroup className="scroll-mt-16" groupName={"Artefacts"} Icon={ArtifactIcon} id="artifact" cards={artifactList} />
<CardGroup className="scroll-mt-16" groupName={"Éphémères"} Icon={InstantIcon} id="instant" cards={instantList} />
<CardGroup className="scroll-mt-16" groupName={"Enchantements"} Icon={EnchantmentIcon} id="enchantment" cards={enchantmentList} />
<CardGroup className="scroll-mt-16" groupName={"Terrains"} Icon={LandIcon} id="land" cards={landList} />
</div>
)}
</div>
</div>
<div className="fixed top-80 ml-8 flex flex-col gap-2 text-stone-500">
<a href="#highsynergy" className={`${scrollState == "highsynergy" ? "text-black text-2xl" : "neutral-svg-filter"} flex flex-row items-center gap-1`}><PlaneswalkerIcon className={scrollState == "highsynergy" ? "h-5" : "h-4"} />Haute synergie</a>
<a href="#planeswalker" className={`${scrollState == "planeswalker" ? "text-black text-2xl" : "neutral-svg-filter"} flex flex-row items-center gap-1`}><PlaneswalkerIcon className={scrollState == "planeswalker" ? "h-5" : "h-4"} />Planeswalker</a>
<a href="#creature" className={`${scrollState == "creature" ? "text-black text-2xl" : "neutral-svg-filter"} flex flex-row items-center gap-1`}><CreatureIcon className={scrollState == "creature" ? "h-5" : "h-4"} />Créatures</a>
<a href="#sorcery" className={`${scrollState == "sorcery" ? "text-black text-2xl" : "neutral-svg-filter"} flex flex-row items-center gap-1`}><SorceryIcon className={scrollState == "sorcery" ? "h-5" : "h-4"} />Rituels</a>
<a href="#artifact" className={`${scrollState == "artifact" ? "text-black text-2xl" : "neutral-svg-filter"} flex flex-row items-center gap-1`}><ArtifactIcon className={scrollState == "artifact" ? "h-5" : "h-4"} />Artefacts</a>
<a href="#instant" className={`${scrollState == "instant" ? "text-black text-2xl" : "neutral-svg-filter"} flex flex-row items-center gap-1`}><InstantIcon className={scrollState == "instant" ? "h-5" : "h-4"} />Éphémères</a>
<a href="#enchantment" className={`${scrollState == "enchantment" ? "text-black text-2xl" : "neutral-svg-filter"} flex flex-row items-center gap-1`}><EnchantmentIcon className={scrollState == "enchantment" ? "h-5" : "h-4"} />Enchantements</a>
<a href="#land" className={`${scrollState == "land" ? "text-black text-2xl" : "neutral-svg-filter"} flex flex-row items-center gap-1`}><LandIcon className={scrollState == "land" ? "h-5" : "h-4"} />Terrains</a>
</div>
</div>
);
}

View file

@ -12,7 +12,7 @@ export default function Home() {
fetch('/api/json/commander/top.json').then((res) => {
if(res.status == 200) {
res.json().then((data) => {
const limit = 20
const limit = 100
setCommanderCardList(data.slice(0,limit))
setLoading(false)
console.log(data)
@ -24,7 +24,7 @@ export default function Home() {
<div className="flex flex-col items-center w-full">
<div className="flex flex-col items-center mt-24 mb-24 max-w-6xl">
{ loading && ( <Spinner className='mt-36' /> )}
{ !loading && ( <CardGroup groupName="Top commandants" showPercent={false} cards={commanderCardList} /> )}
{ !loading && ( <CardGroup groupName="Top commandants" commanderUrl={true} showPercent={false} cards={commanderCardList} /> )}
</div>
</div>
);

View file

@ -1,18 +1,19 @@
import * as React from "react"
import { cn } from "@/lib/utils"
import { MTGCardProps } from "@/components/ui/mtg-card"
import { MTGCard } from '@/components/ui/mtg-card'
interface carte_from_stats {
id: string,
name: string,
normal_image: string,
url: string,
sanitized_name: string,
nbr_decks: number,
total_decks: number,
percent_decks: number,
price: string,
synergy?: number
cardmarket_uri: string
}
@ -23,11 +24,12 @@ interface CardGroupProps {
showPrice?: boolean,
showStats?: boolean,
showPercent?: boolean,
commanderUrl?: boolean,
id?: string,
Icon?: any
}
const CardGroup = ({ className, groupName, cards, showPrice=true, showStats=true,showPercent=true, id, Icon}: CardGroupProps) => {
const CardGroup = ({ className, groupName, cards, showPrice=true, showStats=true,showPercent=true, commanderUrl=false, id, Icon}: CardGroupProps) => {
return (
<div id={id} className={cn('flex flex-col w-full items-start',className)}>
<div className="flex items-center flex-row gap-2 mb-2">
@ -39,9 +41,11 @@ const CardGroup = ({ className, groupName, cards, showPrice=true, showStats=true
<div
className="flex flex-row flex-wrap gap-4"
>
{cards.map((card: carte_from_stats) => (
<MTGCard key={card.id} cardname={card.name} imageURI={card.normal_image} url={"/card/" + card.sanitized_name} nbrDecks={card.nbr_decks} totalDecks={card.total_decks} percentDecks={showPercent ? card.percent_decks : undefined} price={card.price} cardmarketURI={card.cardmarket_uri}/>
{cards.length == 0 && (
<span>Pas de cartes...</span>
)}
{cards.length > 0 && cards.map((card: carte_from_stats) => (
<MTGCard key={card.id} cardname={card.name} imageURI={card.normal_image} url={commanderUrl ? "/commander/card/" + card.url : undefined} nbrDecks={card.nbr_decks} totalDecks={card.total_decks} percentDecks={showPercent ? card.percent_decks : undefined} price={card.price} synergy={card.synergy} cardmarketURI={card.cardmarket_uri}/>
))}
</div>
</div>

View file

@ -4,33 +4,35 @@ import { cn } from "@/lib/utils"
import { Spinner } from "./spinner"
interface MTGCardProps {
className?: string,
imageURI: string,
cardname: string,
url: string,
nbrDecks?: number,
totalDecks?: number,
percentDecks?: number,
price?: string,
className?: string,
imageURI: string,
cardname: string,
url?: string,
nbrDecks?: number,
totalDecks?: number,
percentDecks?: number,
synergy?: number,
price?: string,
cardmarketURI?: string
}
const MTGCard = ({ className, imageURI, cardname, url, nbrDecks, totalDecks, percentDecks, price, cardmarketURI }: MTGCardProps) => {
const MTGCard = ({ className, imageURI, cardname, url, nbrDecks, totalDecks, percentDecks, price, synergy, cardmarketURI }: MTGCardProps) => {
const [loaded, setLoaded] = React.useState(false)
return (
<div
<a
className={cn(
"flex flex-col w-48",
className
)}
href={url != undefined ? url : "#"}
>
{!loaded &&
<div className="flex flex-col items-center justify-center h-64 bg-stone-500 rounded-md">
<Spinner />
</div>
}
<img src={imageURI} className={ loaded ? "rounded h-64" : "absolute opacity-0" } onLoad={() => {setLoaded(true)}} loading="lazy" />
<img src={imageURI} className={ cn(loaded ? "rounded h-64" : "absolute opacity-0", className) } onLoad={() => {setLoaded(true)}} loading="lazy" />
<div className="flex flex-col items-center gap-0">
{ price != undefined && (
<a className="text-xs" href={cardmarketURI != undefined ? cardmarketURI : "#"} target={cardmarketURI != undefined ? "_blank" : "_self"}>{price}</a>
@ -42,8 +44,9 @@ const MTGCard = ({ className, imageURI, cardname, url, nbrDecks, totalDecks, per
{ percentDecks != undefined && ( <span> sur {totalDecks} ({percentDecks}%)</span>)}</span>
</>
)}
{ synergy != undefined && ( <span className="text-md">{synergy}% Synergie</span> )}
</div>
</div>
</a>
)}
MTGCard.displayName = "MTGCard"

View file

@ -4,6 +4,12 @@ interface SymbolsIconProps {
className: string
}
const CommanderIcon = ({ className }: SymbolsIconProps) => {
return (
<img className={cn("h-4",className)} src="/assets/commander.svg"></img>
)}
CommanderIcon.displayName = "CommanderIcon"
const PlaneswalkerIcon = ({ className }: SymbolsIconProps) => {
return (
<img className={cn("h-4",className)} src="/assets/planeswalker.svg"></img>
@ -46,4 +52,4 @@ const LandIcon = ({ className }: SymbolsIconProps) => {
)}
LandIcon.displayName = "LandIcon"
export { PlaneswalkerIcon, SorceryIcon, InstantIcon, CreatureIcon, ArtifactIcon, EnchantmentIcon, LandIcon }
export { CommanderIcon, PlaneswalkerIcon, SorceryIcon, InstantIcon, CreatureIcon, ArtifactIcon, EnchantmentIcon, LandIcon }

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg1"
width="196.8"
height="313.92001"
viewBox="0 0 196.8 313.92001"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<g
id="g1">
<path
style="display:inline;fill:#000000"
d="M 96.320001,313.40138 C 95.076773,312.62187 81.49991,295.60736 80.997053,294.19868 l -0.442949,-1.24086 17.681525,-48.57366 c 9.724841,-26.71552 17.628161,-48.62183 17.562951,-48.68071 -0.35562,-0.32102 -44.593783,-24.28395 -45.05205,-24.40379 -0.398576,-0.10423 -2.71562,2.38823 -8.526912,9.17245 -4.388789,5.12356 -8.019833,9.49241 -8.068986,9.70854 -0.04915,0.21614 2.218848,9.13697 5.040001,19.82407 2.821152,10.6871 5.129368,19.61729 5.129368,19.84486 0,0.67091 -7.611897,21.35883 -8.174903,22.21809 -0.516408,0.78813 -2.229594,1.69234 -3.206458,1.69234 -0.287054,0 -1.017772,-0.2353 -1.623817,-0.52289 -0.897986,-0.42612 -1.652705,-1.44763 -4.078312,-5.52 C 25.682028,211.52918 11.152081,171.83985 4.3462228,130.56001 1.6197832,114.02322 0,95.660031 0,81.28766 0,75.078203 0.04263351,74.592113 0.65559264,73.812862 1.6837009,72.505834 96.232205,0.60704129 97.390241,0.25162984 98.163133,0.01442256 98.703079,0.05252569 99.531845,0.40275926 101.46605,1.220148 195.61007,73.16182 196.26493,74.32291 c 0.53622,0.950725 0.56848,1.636703 0.38742,8.237094 -0.49091,17.895296 -1.92443,33.081656 -4.6518,49.280006 -1.50352,8.92965 -2.43272,13.11567 -3.11571,14.03627 -0.92574,1.2478 -2.81622,1.79919 -4.24473,1.23805 -1.65348,-0.6495 -42.83099,-35.30468 -43.40168,-36.52705 -0.25352,-0.543 -3.68019,-12.839587 -7.61482,-27.325745 -3.93463,-14.486158 -7.20557,-26.376247 -7.26874,-26.422419 -0.25098,-0.183427 -34.012768,-12.007881 -34.083517,-11.937132 -0.195052,0.195051 -37.639624,61.515706 -37.768065,61.850426 -0.08113,0.21142 25.483777,21.8881 57.317352,48.59981 31.60509,26.51999 57.62644,48.52205 57.82522,48.89347 0.74334,1.38895 0.37554,2.9055 -1.99701,8.23432 -9.99817,22.45617 -22.91518,44.41087 -38.02711,64.63366 -5.70912,7.63994 -28.06775,35.27685 -29.19434,36.08634 -1.1768,0.84557 -2.941955,0.93211 -4.107399,0.20137 z"
id="path1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -61,7 +61,19 @@ async function createJson() {
include: {
cards: {
include: {
decks: true,
decks: {
include: {
deck: {
include: {
commander: {
include: {
decks_as_commander: true,
}
},
},
},
}
},
decks_as_commander: true,
}
}
@ -88,6 +100,7 @@ async function createJson() {
commanderData[colorName] = []
}
let bset_cards_data_export = {}
let commander_details_export = {}
bsets.forEach((bset) => {
let icons = []
@ -124,6 +137,7 @@ async function createJson() {
let card_object = {
"name": card.name,
"sanitized_name": card.sanitized_name,
"url": card.set_code + "-" + card.sanitized_name,
"normal_image": card.normal_image,
"small_image": card.small_image,
"type": card.type,
@ -135,19 +149,46 @@ async function createJson() {
"color_identity": card.color_identity,
}
card_object.percent_decks = (card_object.total_decks != 0) ? parseInt(10000 * (card_object.nbr_decks / card_object.total_decks)) / 100 : 0
card_object.percent_decks = (card_object.total_decks != 0) ? parseInt(100 * (card_object.nbr_decks / card_object.total_decks)) : 0
bset_cards_data_export[bset.sanitized_name][card.type].push(card_object)
card.decks.forEach((deck) => {
const card_url_name = deck.deck.commander.set_code + "-" + deck.deck.commander.sanitized_name
if(!Object.keys(commander_details_export).includes(card_url_name)) {
commander_details_export[card_url_name] = {
"card_data": deck.deck.commander,
"creature": {},
"land": {},
"enchantment": {},
"sorcery": {},
"instant": {},
"planeswalker": {},
"artifact": {},
}
commander_details_export[card_url_name].card_data.nbr_decks = deck.deck.commander.decks_as_commander.length
}
if(!Object.keys(commander_details_export[card_url_name][card.type]).includes(card.sanitized_name)) {
let card_synergy_object = structuredClone(card_object)
card_synergy_object.commander_total = 0
commander_details_export[card_url_name][card.type][card.sanitized_name] = card_synergy_object
}
commander_details_export[card_url_name][card.type][card.sanitized_name].commander_total += 1
})
if(card.can_be_commander) {
let commander_card_object = structuredClone(card_object)
commander_card_object.total_decks = bset.decks.length
commander_card_object.nbr_decks = card.decks_as_commander != undefined ? card.decks_as_commander.length : 0
commander_card_object.percent_decks = (commander_card_object.total_decks != 0) ? parseInt(10000 * (commander_card_object.nbr_decks / commander_card_object.total_decks)) / 100 : 0
commander_card_object.percent_decks = (commander_card_object.total_decks != 0) ? parseInt(100 * (commander_card_object.nbr_decks / commander_card_object.total_decks)) : 0
bset_cards_data_export[bset.sanitized_name]["commander"].push(commander_card_object)
const colorName = getColorName(card.color_identity)
if(colorName != "") {
commanderData[colorName].push(commander_card_object)
commanderData["top"].push(commander_card_object)
@ -164,12 +205,31 @@ async function createJson() {
writeFileSync(import.meta.dirname + "/../data/commander/" + index + ".json",JSON.stringify(JSONToWrite), 'utf8')
}
for (const index of Object.keys(commander_details_export)) {
let JSONToWrite = structuredClone(commander_details_export[index])
JSONToWrite["high_synergy"] = []
for (const type of ["creature","land","enchantment","sorcery","instant","planeswalker","artifact"]) {
JSONToWrite[type] = []
for (const card_key of Object.keys(commander_details_export[index][type])) {
let card_object_synergy = commander_details_export[index][type][card_key]
card_object_synergy.synergy = parseInt(100 * (card_object_synergy.commander_total / commander_details_export[index].card_data.nbr_decks) - card_object_synergy.percent_decks)
JSONToWrite[type].push(card_object_synergy)
}
JSONToWrite[type].sort((a,b) => b.synergy - a.synergy || b.percent_decks - a.percent_decks || b.nbr_decks - a.nbr_decks)
JSONToWrite["high_synergy"] = [...JSONToWrite["high_synergy"], ...JSONToWrite[type]]
}
JSONToWrite["high_synergy"].sort((a,b) => b.synergy - a.synergy || b.percent_decks - a.percent_decks || b.nbr_decks - a.nbr_decks)
JSONToWrite["high_synergy"] = JSONToWrite["high_synergy"].slice(0,15)
writeFileSync(import.meta.dirname + "/../data/card-commander/" + index + ".json",JSON.stringify(JSONToWrite), 'utf8')
}
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 || b.nbr_decks - a.nbr_decks)
}
writeFileSync(import.meta.dirname + "/../data/bset/" + index + ".json",JSON.stringify(JSONToWrite), 'utf8')
writeFileSync(import.meta.dirname + "/../data/bset/" + index + ".json",JSON.stringify(JSONToWrite), 'utf8')
}
const end = performance.now()
console.log(`Time taken to generate stats is ${(end - start)/1000}s.`);