mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-11 16:26:22 +00:00
* - Update the MTGDecksNet conversion and AI playability test toolchain to the latest version (Python 3 compatible). * - Make the input/output folders generic * - Make the input/output folders generic, part 2. * - Add the Scryfall all-prices.txt generator script. * - Minor code cleanup. * - Improve ConniveAi for Change of Plans. * - Check if the AI can draw cards for ConniveAI * - Improve the price generation script to account for the Scryfall set code to Forge set code mapping. - Tweak paths in some of the scripts. * - Fix scryfallPricesGenerator.
127 lines
5.4 KiB
Python
Executable File
127 lines
5.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import json, os
|
|
|
|
# Set this to the current Forge editions folder (under res)
|
|
EDITIONS_FOLDER = "../res/editions"
|
|
|
|
# Load the editions and map Scryfall codes to the set codes used in Forge
|
|
set_map = {}
|
|
for filename in os.listdir(EDITIONS_FOLDER):
|
|
if filename.endswith(".txt"):
|
|
ed_file = open(os.path.join(EDITIONS_FOLDER, filename), "r")
|
|
ed_data = ed_file.readlines()
|
|
ed_file.close()
|
|
forge_code = "????"
|
|
scryfall_code = "????"
|
|
for line in ed_data:
|
|
if line.startswith("[cards]"):
|
|
break
|
|
elif line.lower().startswith("code="):
|
|
forge_code = line.split("=")[1].strip()
|
|
elif line.lower().startswith("scryfallcode="):
|
|
scryfall_code = line.split("=")[1].strip()
|
|
set_map[scryfall_code] = forge_code
|
|
|
|
# Note: currently only loads the first json file found in the folder!
|
|
metadata_file = None
|
|
files = os.listdir(".")
|
|
for filename in files:
|
|
if filename.endswith(".json"):
|
|
metadata_filename = filename
|
|
break
|
|
|
|
if metadata_filename is None:
|
|
print("Please download the Default Cards bulk data json file from https://scryfall.com/docs/api/bulk-data and place it in the script folder.")
|
|
exit(1)
|
|
|
|
print(f"Loading {metadata_filename}...")
|
|
metadata_file = open(metadata_filename, "r")
|
|
metadata = json.load(metadata_file)
|
|
metadata_file.close()
|
|
|
|
prices = {}
|
|
art_indexes = {}
|
|
always_with_artindex = ["Plains", "Island", "Swamp", "Mountain", "Forest", "Wastes", "Snow-Covered Plains", "Snow-Covered Island", "Snow-Covered Swamp", "Snow-Covered Mountain", "Snow-Covered Forest", "Snow-Covered Wastes"]
|
|
|
|
for object in metadata:
|
|
obj_type = object["object"]
|
|
if obj_type == "card":
|
|
card_name = object["name"]
|
|
# split cards use //, other cards with two sides (e.g. DFC) use the front face in Forge
|
|
if card_name.find("//") != -1 and object["layout"] != "split":
|
|
card_name = card_name.split("//")[0].strip()
|
|
card_set = object["set"].upper()
|
|
card_cn = object["collector_number"]
|
|
card_foil_only = object["foil"] and not object["nonfoil"]
|
|
card_price = None
|
|
if object["prices"]["usd"] == None and object["prices"]["usd_foil"] == None and object["prices"]["usd_etched"] == None and object["prices"]["eur"] == None and object["prices"]["eur_foil"] == None and object["prices"]["tix"] == None:
|
|
continue
|
|
if not card_foil_only and object["prices"]["usd"] != None:
|
|
card_price = object["prices"]["usd"].replace(".", "")
|
|
elif object["prices"]["usd_foil"] != None:
|
|
card_price = object["prices"]["usd_foil"].replace(".", "")
|
|
elif object["prices"]["usd_etched"] != None:
|
|
card_price = object["prices"]["usd_etched"].replace(".", "")
|
|
elif object["prices"]["eur"] != None:
|
|
card_price = object["prices"]["eur"].replace(".", "")
|
|
elif object["prices"]["eur_foil"] != None:
|
|
card_price = object["prices"]["eur_foil"].replace(".", "")
|
|
elif object["prices"]["tix"] != None:
|
|
card_price = object["prices"]["tix"].replace(".", "")
|
|
if card_price == None:
|
|
continue
|
|
elif card_price.startswith("00"):
|
|
card_price = card_price[2:]
|
|
elif card_price.startswith("0"):
|
|
card_price = card_price[1:]
|
|
# tweak the card set to the Forge notation
|
|
if card_set in set_map:
|
|
card_set = set_map[card_set]
|
|
# add a key to the prices dictionary, per set
|
|
if not card_set in prices:
|
|
prices[card_set] = {}
|
|
if not card_set in art_indexes:
|
|
art_indexes[card_set] = {}
|
|
if card_name not in art_indexes[card_set]:
|
|
art_indexes[card_set][card_name] = 1
|
|
else:
|
|
art_indexes[card_set][card_name] += 1
|
|
if card_name in prices[card_set] or card_name in always_with_artindex:
|
|
card_name += f" ({art_indexes[card_set][card_name]})"
|
|
prices[card_set][card_name] = card_price
|
|
|
|
# Merge with the previous price list if appropriate
|
|
if os.path.exists("all-prices.prev"):
|
|
print()
|
|
merge = input("Would you like to merge the prices with all-prices.prev? ")
|
|
if merge.lower().startswith("y"):
|
|
prev = open("all-prices.prev", "r")
|
|
prev_data = prev.readlines()
|
|
prev.close()
|
|
for prev_price in prev_data:
|
|
if prev_price.find("=") == -1:
|
|
continue
|
|
data = prev_price.split("=")
|
|
old_price = data[1].strip()
|
|
old_name = data[0].split("|")[0]
|
|
if old_name.find("(") != -1: # unsafe to import a qualified name, we don't know how they'll match up
|
|
continue
|
|
old_set = data[0].split("|")[1]
|
|
if old_set in prices.keys() and old_name not in prices[old_set]:
|
|
prices[old_set][old_name] = old_price
|
|
|
|
# Generate the prices file
|
|
output = open("all-prices.txt", "w")
|
|
sorted_prices = {key: value for key, value in sorted(prices.items())}
|
|
for set in sorted_prices.keys():
|
|
sorted_cards = {key: value for key, value in sorted(prices[set].items())}
|
|
for name in sorted_cards.keys():
|
|
qualified_name = name
|
|
if name.find("(") == -1 and name in art_indexes[set] and art_indexes[set][name] > 1:
|
|
qualified_name += " (1)"
|
|
print(qualified_name + "|" + set + "=" + sorted_cards[name])
|
|
output.write(f"{qualified_name}|{set}={sorted_cards[name]}\n")
|
|
output.close()
|