diff --git a/.gitignore b/.gitignore index 0c34accb1..93d6c7b79 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ cards/en/v1/ +.vscode/ +.DS_Store \ No newline at end of file diff --git a/scripts/hardcodedshinylist.json b/scripts/hardcodedshinylist.json new file mode 100644 index 000000000..b8e904692 --- /dev/null +++ b/scripts/hardcodedshinylist.json @@ -0,0 +1,80 @@ +[ + "hsp-HGSS19", + "hsp-HGSS20", + "hsp-HGSS21", + + "bwp-BW99", + "bwp-BW101", + + "xyp-XY166", + "xyp-XY34", + "xyp-XY35", + "xyp-XY69", + "xyp-XY106", + "xyp-XY143", + "xyp-XY149", + "xyp-XY150", + + "xy7-54", + "xy7-96", + "xy7-97", + "xy7-98", + + "xy9-26", + "xy9-27", + "xy9-101", + "xy9-114", + "xy9-115", + "xy9-123", + + "g1-RC31", + + "xy11-11", + "xy11-15", + "xy11-42", + "xy11-64", + "xy11-68", + "xy11-77", + "xy11-79", + + "smp-SM91", + "smp-SM122", + "smp-SM30a", + "smp-SM50", + + "swsh2-204", + "swsh2-205", + + "swsh3-197", + "swsh3-198", + + "swsh35-79", + + "swsh4-198", + "swsh4-199", + + "swsh5-178", + "swsh5-179", + + "swsh6-222", + "swsh6-223", + "swsh6-224", + + "swsh7-226", + "swsh7-227", + "swsh7-228", + + "cel25-25", + + "swsh8-280", + + "swshp-SWSH292", + "swshp-SWSH293", + + "sv4pt5-224", + "sv4pt5-225", + "sv4pt5-226", + "sv4pt5-232", + "sv4pt5-233", + "sv4pt5-234" +] \ No newline at end of file diff --git a/scripts/shinies.json b/scripts/shinies.json new file mode 100644 index 000000000..f22b75012 --- /dev/null +++ b/scripts/shinies.json @@ -0,0 +1,510 @@ +[ + "neo3-65", + "neo3-66", + "neo4-106", + "neo4-107", + "neo4-108", + "neo4-109", + "neo4-110", + "neo4-111", + "neo4-112", + "neo4-113", + "ex7-107", + "ex7-108", + "ex7-109", + "ex8-105", + "ex8-106", + "ex8-107", + "ex10-113", + "ex10-114", + "ex10-115", + "ex11-111", + "ex11-112", + "ex11-113", + "ex12-90", + "ex12-91", + "ex12-92", + "ex13-102", + "ex13-103", + "ex13-104", + "ex14-99", + "ex14-100", + "ex15-100", + "ex15-101", + "ex16-100", + "ex16-101", + "ex16-102", + "pop5-16", + "pop5-17", + "dp7-SH1", + "dp7-SH2", + "dp7-SH3", + "pl1-SH4", + "pl1-SH5", + "pl1-SH6", + "pl3-SH7", + "pl3-SH8", + "pl3-SH9", + "pl4-SH10", + "pl4-SH11", + "pl4-SH12", + "hsp-HGSS19", + "hsp-HGSS20", + "hsp-HGSS21", + "col1-SL1", + "col1-SL2", + "col1-SL3", + "col1-SL4", + "col1-SL5", + "col1-SL6", + "col1-SL7", + "col1-SL8", + "col1-SL9", + "col1-SL10", + "col1-SL11", + "bwp-BW99", + "bwp-BW101", + "bw4-100", + "bw4-101", + "bw4-102", + "bw4-103", + "bw5-109", + "bw5-110", + "bw6-125", + "bw6-126", + "bw6-127", + "bw6-128", + "bw7-150", + "bw7-151", + "bw7-152", + "bw8-136", + "bw8-137", + "bw9-117", + "bw9-118", + "bw9-119", + "bw9-120", + "bw10-102", + "bw10-103", + "bw10-104", + "xyp-XY166", + "xyp-XY34", + "xyp-XY35", + "xyp-XY69", + "xyp-XY106", + "xyp-XY143", + "xyp-XY149", + "xyp-XY150", + "xy7-54", + "xy7-96", + "xy7-97", + "xy7-98", + "xy9-26", + "xy9-27", + "xy9-101", + "xy9-114", + "xy9-115", + "xy9-123", + "g1-RC31", + "xy11-11", + "xy11-15", + "xy11-42", + "xy11-64", + "xy11-68", + "xy11-77", + "xy11-79", + "smp-SM91", + "smp-SM122", + "smp-SM30a", + "smp-SM50", + "smp-SM70", + "smp-SM79", + "smp-SM82", + "sm35-9", + "sm35-27", + "sm35-40", + "sm35-42", + "sm35-56", + "sm35-57", + "sma-SV1", + "sma-SV2", + "sma-SV3", + "sma-SV4", + "sma-SV5", + "sma-SV6", + "sma-SV7", + "sma-SV8", + "sma-SV9", + "sma-SV10", + "sma-SV11", + "sma-SV12", + "sma-SV13", + "sma-SV14", + "sma-SV15", + "sma-SV16", + "sma-SV17", + "sma-SV18", + "sma-SV19", + "sma-SV20", + "sma-SV21", + "sma-SV22", + "sma-SV23", + "sma-SV24", + "sma-SV25", + "sma-SV26", + "sma-SV27", + "sma-SV28", + "sma-SV29", + "sma-SV30", + "sma-SV31", + "sma-SV32", + "sma-SV33", + "sma-SV34", + "sma-SV35", + "sma-SV36", + "sma-SV37", + "sma-SV38", + "sma-SV39", + "sma-SV40", + "sma-SV41", + "sma-SV42", + "sma-SV43", + "sma-SV44", + "sma-SV45", + "sma-SV46", + "sma-SV47", + "sma-SV48", + "sma-SV49", + "sma-SV50", + "sma-SV51", + "sma-SV52", + "sma-SV53", + "sma-SV54", + "sma-SV55", + "sma-SV56", + "sma-SV57", + "sma-SV58", + "sma-SV59", + "sma-SV60", + "sma-SV61", + "sma-SV62", + "sma-SV63", + "sma-SV64", + "sma-SV65", + "sma-SV66", + "sma-SV67", + "sma-SV68", + "sma-SV69", + "sma-SV70", + "sma-SV71", + "sma-SV72", + "sma-SV73", + "sma-SV74", + "sma-SV75", + "sma-SV76", + "sma-SV77", + "sma-SV78", + "sma-SV79", + "sma-SV80", + "sma-SV91", + "sma-SV92", + "sma-SV93", + "sma-SV94", + "swshp-SWSH292", + "swshp-SWSH293", + "swshp-SWSH144", + "swshp-SWSH230", + "swsh2-204", + "swsh2-205", + "swsh3-197", + "swsh3-198", + "swsh35-79", + "swsh4-198", + "swsh4-199", + "swsh45sv-SV001", + "swsh45sv-SV002", + "swsh45sv-SV003", + "swsh45sv-SV004", + "swsh45sv-SV005", + "swsh45sv-SV006", + "swsh45sv-SV007", + "swsh45sv-SV008", + "swsh45sv-SV009", + "swsh45sv-SV010", + "swsh45sv-SV011", + "swsh45sv-SV012", + "swsh45sv-SV013", + "swsh45sv-SV014", + "swsh45sv-SV015", + "swsh45sv-SV016", + "swsh45sv-SV017", + "swsh45sv-SV018", + "swsh45sv-SV019", + "swsh45sv-SV020", + "swsh45sv-SV021", + "swsh45sv-SV022", + "swsh45sv-SV023", + "swsh45sv-SV024", + "swsh45sv-SV025", + "swsh45sv-SV026", + "swsh45sv-SV027", + "swsh45sv-SV028", + "swsh45sv-SV029", + "swsh45sv-SV030", + "swsh45sv-SV031", + "swsh45sv-SV032", + "swsh45sv-SV033", + "swsh45sv-SV034", + "swsh45sv-SV035", + "swsh45sv-SV036", + "swsh45sv-SV037", + "swsh45sv-SV038", + "swsh45sv-SV039", + "swsh45sv-SV040", + "swsh45sv-SV041", + "swsh45sv-SV042", + "swsh45sv-SV043", + "swsh45sv-SV044", + "swsh45sv-SV045", + "swsh45sv-SV046", + "swsh45sv-SV047", + "swsh45sv-SV048", + "swsh45sv-SV049", + "swsh45sv-SV050", + "swsh45sv-SV051", + "swsh45sv-SV052", + "swsh45sv-SV053", + "swsh45sv-SV054", + "swsh45sv-SV055", + "swsh45sv-SV056", + "swsh45sv-SV057", + "swsh45sv-SV058", + "swsh45sv-SV059", + "swsh45sv-SV060", + "swsh45sv-SV061", + "swsh45sv-SV062", + "swsh45sv-SV063", + "swsh45sv-SV064", + "swsh45sv-SV065", + "swsh45sv-SV066", + "swsh45sv-SV067", + "swsh45sv-SV068", + "swsh45sv-SV069", + "swsh45sv-SV070", + "swsh45sv-SV071", + "swsh45sv-SV072", + "swsh45sv-SV073", + "swsh45sv-SV074", + "swsh45sv-SV075", + "swsh45sv-SV076", + "swsh45sv-SV077", + "swsh45sv-SV078", + "swsh45sv-SV079", + "swsh45sv-SV080", + "swsh45sv-SV081", + "swsh45sv-SV082", + "swsh45sv-SV083", + "swsh45sv-SV084", + "swsh45sv-SV085", + "swsh45sv-SV086", + "swsh45sv-SV087", + "swsh45sv-SV088", + "swsh45sv-SV089", + "swsh45sv-SV090", + "swsh45sv-SV091", + "swsh45sv-SV092", + "swsh45sv-SV093", + "swsh45sv-SV094", + "swsh45sv-SV095", + "swsh45sv-SV096", + "swsh45sv-SV097", + "swsh45sv-SV098", + "swsh45sv-SV099", + "swsh45sv-SV100", + "swsh45sv-SV101", + "swsh45sv-SV102", + "swsh45sv-SV103", + "swsh45sv-SV104", + "swsh45sv-SV105", + "swsh45sv-SV106", + "swsh45sv-SV107", + "swsh45sv-SV108", + "swsh45sv-SV109", + "swsh45sv-SV110", + "swsh45sv-SV111", + "swsh45sv-SV112", + "swsh45sv-SV113", + "swsh45sv-SV114", + "swsh45sv-SV115", + "swsh45sv-SV116", + "swsh45sv-SV117", + "swsh45sv-SV118", + "swsh45sv-SV119", + "swsh45sv-SV120", + "swsh45sv-SV121", + "swsh45sv-SV122", + "swsh5-178", + "swsh5-179", + "swsh6-222", + "swsh6-223", + "swsh6-224", + "swsh7-226", + "swsh7-227", + "swsh7-228", + "cel25-25", + "cel25c-66_A", + "cel25c-17_A", + "swsh8-280", + "swsh10-27", + "swsh10-46", + "swsh10-81", + "pgo-4", + "pgo-11", + "pgo-18", + "swsh11-69", + "swsh11-123", + "swsh11-124", + "swsh12-16", + "swsh12-59", + "swsh12-120", + "swsh12pt5-20", + "swsh12pt5-51", + "swsh12pt5-105", + "sv4pt5-224", + "sv4pt5-225", + "sv4pt5-226", + "sv4pt5-232", + "sv4pt5-233", + "sv4pt5-234", + "sv4pt5-92", + "sv4pt5-93", + "sv4pt5-94", + "sv4pt5-95", + "sv4pt5-96", + "sv4pt5-97", + "sv4pt5-98", + "sv4pt5-99", + "sv4pt5-100", + "sv4pt5-101", + "sv4pt5-102", + "sv4pt5-103", + "sv4pt5-104", + "sv4pt5-105", + "sv4pt5-106", + "sv4pt5-107", + "sv4pt5-108", + "sv4pt5-109", + "sv4pt5-110", + "sv4pt5-111", + "sv4pt5-112", + "sv4pt5-113", + "sv4pt5-114", + "sv4pt5-115", + "sv4pt5-116", + "sv4pt5-117", + "sv4pt5-118", + "sv4pt5-119", + "sv4pt5-120", + "sv4pt5-121", + "sv4pt5-122", + "sv4pt5-123", + "sv4pt5-124", + "sv4pt5-125", + "sv4pt5-126", + "sv4pt5-127", + "sv4pt5-128", + "sv4pt5-129", + "sv4pt5-130", + "sv4pt5-131", + "sv4pt5-132", + "sv4pt5-133", + "sv4pt5-134", + "sv4pt5-135", + "sv4pt5-136", + "sv4pt5-137", + "sv4pt5-138", + "sv4pt5-139", + "sv4pt5-140", + "sv4pt5-141", + "sv4pt5-142", + "sv4pt5-143", + "sv4pt5-144", + "sv4pt5-145", + "sv4pt5-146", + "sv4pt5-147", + "sv4pt5-148", + "sv4pt5-149", + "sv4pt5-150", + "sv4pt5-151", + "sv4pt5-152", + "sv4pt5-153", + "sv4pt5-154", + "sv4pt5-155", + "sv4pt5-156", + "sv4pt5-157", + "sv4pt5-158", + "sv4pt5-159", + "sv4pt5-160", + "sv4pt5-161", + "sv4pt5-162", + "sv4pt5-163", + "sv4pt5-164", + "sv4pt5-165", + "sv4pt5-166", + "sv4pt5-167", + "sv4pt5-168", + "sv4pt5-169", + "sv4pt5-170", + "sv4pt5-171", + "sv4pt5-172", + "sv4pt5-173", + "sv4pt5-174", + "sv4pt5-175", + "sv4pt5-176", + "sv4pt5-177", + "sv4pt5-178", + "sv4pt5-179", + "sv4pt5-180", + "sv4pt5-181", + "sv4pt5-182", + "sv4pt5-183", + "sv4pt5-184", + "sv4pt5-185", + "sv4pt5-186", + "sv4pt5-187", + "sv4pt5-188", + "sv4pt5-189", + "sv4pt5-190", + "sv4pt5-191", + "sv4pt5-192", + "sv4pt5-193", + "sv4pt5-194", + "sv4pt5-195", + "sv4pt5-196", + "sv4pt5-197", + "sv4pt5-198", + "sv4pt5-199", + "sv4pt5-200", + "sv4pt5-201", + "sv4pt5-202", + "sv4pt5-203", + "sv4pt5-204", + "sv4pt5-205", + "sv4pt5-206", + "sv4pt5-207", + "sv4pt5-208", + "sv4pt5-209", + "sv4pt5-210", + "sv4pt5-211", + "sv4pt5-212", + "sv4pt5-213", + "sv4pt5-214", + "sv4pt5-215", + "sv4pt5-216", + "sv4pt5-217", + "sv4pt5-218", + "sv4pt5-219", + "sv4pt5-220", + "sv4pt5-221", + "sv4pt5-222", + "sv4pt5-223" +] \ No newline at end of file diff --git a/scripts/shinyhunter.js b/scripts/shinyhunter.js new file mode 100644 index 000000000..42020d518 --- /dev/null +++ b/scripts/shinyhunter.js @@ -0,0 +1,238 @@ +var fs = require('fs'); + +var carddir = "../cards/en/" + + +var CARD_HOLDER = {}; +var SET_HOLDER = {}; +var SHINY_SETS = {}; + +var readSetData = () => { + fs.readFile("../sets/en.json", 'utf-8', function(err, content) { + if (err) { + console.log(err); + return; + } + var setList = JSON.parse(content); + for(var i = 0; i < setList.length; i++){ + var set = setList[i]; + SET_HOLDER[set.id] = set; + } + }) + fs.readFile("shinysets.json", 'utf-8', function(err, content) { + if (err) { + console.log(err); + return; + } + var setList = JSON.parse(content); + for(var i = 0; i < setList.length; i++){ + var setName = setList[i]; + SHINY_SETS[setName] = true; + } + }) +} + +readSetData(); + +// card modifier should return a card, either modified or not +var cardIterate = (cardModifier, finalCallback) => { + fs.readdir(carddir, function(err, filenames) { + if (err) { + console.log(err); + return; + } + for(var i = 0; i < filenames.length; i++) { + var filename = filenames[i]; + console.log(`Reading ${filename} (${i})`); + var last = (i == (filenames.length-1)); + fs.readFile(carddir + filename, 'utf-8', function(err, content) { + if (err) { + console.log(err); + return; + } + var cards = JSON.parse(content); + var newCards = []; + for(var i = 0; i < cards.length; i++) { + var newCard = cardModifier(cards[i]); + CARD_HOLDER[newCard.id] = newCard; + newCards.push(newCard); + } + var oldCardString = JSON.stringify(cards, null, 2); + var newCardString = JSON.stringify(newCards, null, 2); + if(oldCardString != newCardString) { + fs.writeFile(carddir + filename, newCardString, function(err) { + if (err) { + console.log(err); + return; + } + }); + } + if(this.last){ + finalCallback(); + } + }.bind({"last": last})); + }; + }); +} + +const shinyNameRegex = /(★|radiant|shining)/i; // check easy ones with shiny indicator in name +const shinyRarityRegex = /(shining|shiny|radiant)/i; // more recently shiny is indicated in rarity +const shinyFlavorTextRegex = /(this extremely rare)/i; // bw era shinies have this as their flavor text +const shinyIdRegex = /-(SH|SL)/i; // catches some DP era shinies + +var heuristicallyShiny = (card) => { + if(card.supertype != "Pokémon"){ return false} // there might be some shiny trainer cards ? + if(shinyNameRegex.test(card.name)){ + return true; + } + if(shinyRarityRegex.test(card.rarity)){ + return true; + } + if(shinyFlavorTextRegex.test(card.flavorText)){ + return true; + } + if(shinyIdRegex.test(card.id)){ + return true; + } + if(SHINY_SETS[card.id.split("-")[0]]){ + return true; + } + // TODO: check if it's in an all-shiny set + return false; +} + +var makePreviewPage = (shinyCards) => { + var html = "Shiny List"; + html += `

Shiny Cards Preview (${shinyCards.length} Cards Listed)

`; + html += "

Make sure everything looks fine here

"; + html += "
"; + + shinyCards.sort((a, b)=>{ + return (new Date(SET_HOLDER[a.id.split("-")[0]].releaseDate) - new Date(SET_HOLDER[b.id.split("-")[0]].releaseDate)); + }) + + for(var i = 0; i < shinyCards.length; i++){ + var cardID = shinyCards[i].id; + html += `` + } + html += "
"; + html += `` + fs.writeFile("shinylist.html", html, () => {}); +} + +// so that we can quickly open a page displaying all the cards +var openPage = (url) => { + var start = (process.platform == 'darwin'? 'open': process.platform == 'win32'? 'start': 'xdg-open'); + require('child_process').exec(start + ' ' + url); +} + +// bulbapedia lists 369 shinies but hasn't been updated for paldean fates (https://bulbapedia.bulbagarden.net/wiki/List_of_cards_featuring_Shiny_Pok%C3%A9mon) + +// finds them heuristically - returns a list of the cards +var findShinies = (verbose) => { + return new Promise((resolve, reject) => { + var shinies = []; + cardIterate((card) => { + if(heuristicallyShiny(card)){ + shinies.push(card); + if(verbose) + console.log(`${card.name} [${card.id}] is shiny!`) + } + return card; + }, () => { + if(verbose) + console.log(`Found ${shinies.length} shiny cards!`); + resolve(shinies); + }); + }) +} + +var getHardcodedShinyIDs = () => { + return new Promise((resolve, reject) => { + fs.readFile("hardcodedshinylist.json", 'utf-8', function(err, content) { + if (err) { + console.log(err); + return; + } + resolve(JSON.parse(content)); + }) + }); +} + +var huntCommand = () => { + findShinies(true); +}; + +var previewCommand = () => { + findShinies(false).then((shinies) => { + getHardcodedShinyIDs().then((hardcodedShinies) => { + for(var i = 0; i < hardcodedShinies.length; i++){ + shinies.push(CARD_HOLDER[hardcodedShinies[i]]); + } + makePreviewPage(shinies); + openPage("shinylist.html"); + }); + }); +} + +var printCommand = () => { + findShinies(false).then((shinies) => { + getHardcodedShinyIDs().then((hardcodedShinies) => { + var shinyIDs = []; + for(var i = 0; i < hardcodedShinies.length; i++){ + shinyIDs.push(hardcodedShinies[i]); + } + for(var i = 0; i < shinies.length; i++){ + shinyIDs.push(shinies[i].id); + } + shinyIDs.sort((a,b) => { + return (new Date(SET_HOLDER[a.split("-")[0]].releaseDate) - new Date(SET_HOLDER[b.split("-")[0]].releaseDate)); + }) + fs.writeFile("shinies.json", JSON.stringify(shinyIDs, null, 2), () => {}); + }); + }); +} + +var updateCommand = () => { + // TODO: figure out what format should there be for shinies in the data +} + +var commands = {}; + +var addCommand = (name, description, callback) => { + commands[name] = { + "description": description, + "callback": callback + } +} + +var helpCommand = () => { + // print help + console.log("Usage: node shinyhunter.js \nAvailable Commands:"); + var longestCommand = 0; + for(var key in commands){ + if(key.length > longestCommand) { + longestCommand = key.length; + } + } + for(var key in commands){ + console.log(`${key.padEnd(longestCommand)} -- ${commands[key].description}`); + } +} + +addCommand("hunt", "Finds and logs shiny cards heuristically", huntCommand); +addCommand("preview", "Opens a page showing all the shiny cards, found heuristically and hardcoded", previewCommand); +addCommand("print", "Prints a list of all known shiny card IDs to \"shinies.json\"", printCommand); +addCommand("update", "Updates the actual card data with shiny information [not yet implemented]", printCommand); +addCommand("help", "Prints this screen", helpCommand); + + + +if(process.argv.length > 2){ + if(commands[process.argv[2]]){ + commands[process.argv[2]].callback(); + } +} else { + helpCommand(); +} + diff --git a/scripts/shinylist.html b/scripts/shinylist.html new file mode 100644 index 000000000..fd658da04 --- /dev/null +++ b/scripts/shinylist.html @@ -0,0 +1 @@ +Shiny List

Shiny Cards Preview (508 Cards Listed)

Make sure everything looks fine here

\ No newline at end of file diff --git a/scripts/shinysets.json b/scripts/shinysets.json new file mode 100644 index 000000000..f5ce2c682 --- /dev/null +++ b/scripts/shinysets.json @@ -0,0 +1,4 @@ +[ + "swsh45sv", + "sma" +] \ No newline at end of file