https://github.com/taw/magic-preconstructed-decks-data
This repository contains machine readable decklist data generated from:
Files
decks.jsonhas traditional cards + sideboard structure, with commanders reusing sideboard.
decks_v2.jsonhas cards + sideboard + commander structure. You should use this one.Data format
Data file i a JSON array, with every element representing one deck.
Fields for each deck:
- name - deck name
- type - deck type
- set_code - mtgjson set code
- set_name - set name
- release_date - deck release date (many decks are released much after their set)
- cards - list of cards in the deck's mainboard
- sideboard - list of cards in the deck's sideboard
- commander - any commanders deck has (can be multiple for partners)
Each card is:
- name - card name
- set_code - mtgjson set card is from (decks often have cards from multiple sets)
- number - card collector number
- foil - is this a foil version
- count - how many of given card
- mtgjson_uuid - mtgjson uuid
- multiverseid - Gatherer multiverseid of card if cards is on Gatherer (optional field)
Data Limitations
All precons ever released by Wizards of the Coast should be present, and decklists should always contain right cards, with correct number and foiling, and mainboard/sideboard/commander status.
Source decklists generally do not say which printing (set and card number) each card is from, so we need to use heuristics to figure that out.
We use a script to infer most likely set for each card based on some heuristics, and as far as I know, it always matches perfectly.
That just leaves situation where there are multiple printings of same card in same set.
If some of the printings are special (full art basics, Jumpstart basics, showcase frames etc.), these have been manually chosen to match every product.
If you see any errors for anything mentioned above, please report them, so they can be fixed.
That just leaves the case of multiple non-special printings of same card in same set - most commonly basic lands. In such case one of them is chosen arbitrarily, even though in reality a core set deck with 16 Forests would likely have 4 of each Forest in that core set, not 16 of one of them.
Feel free to create issue with data on exact priting if you want, but realistically we'll never get them all, and it's not something most people care about much.
Here are step-by-step instructions to migrate
decks_v2.jsonto.dckfiles with the desired structure, assuming no prior knowledge of the command line:migrate_decks.py.import json import os import re from typing import List, Dict DECKS_FOLDER = 'Preconstructed Decks' def load_decks(file_path: str) -> List[Dict]: with open(file_path, 'r') as f: return json.load(f) def format_deck_name(name: str) -> str: name = name.lower().replace(' ', '_').replace('-', '_') return re.sub(r'[^a-z0-9_]', '', name) def get_deck_info(deck: Dict) -> Dict: return { 'name': format_deck_name(deck['name']), 'type': deck['type'], 'set_code': deck['set_code'].upper(), 'set_name': deck['set_name'], 'release_date': deck['release_date'], 'deck_folder': DECKS_FOLDER, 'cards': deck['cards'], 'sideboard': deck['sideboard'] } def build_deck_text(deck_info: Dict) -> str: lines = [ f'// {deck_info["name"]}', f'// Set: {deck_info["set_name"]} ({deck_info["set_code"]})', f'// Release Date: {deck_info["release_date"]}', '', ] for card in deck_info['cards']: lines.append(f'{card["count"]} [{card["set_code"]}:{card["number"]}] {card["name"]}') lines.append('') lines.append('SB:') for card in deck_info['sideboard']: lines.append(f'{card["count"]} [{card["set_code"]}:{card["number"]}] {card["name"]}') return '\n'.join(lines) def build_deck_path(deck_info: Dict) -> str: return os.path.join(deck_info['deck_folder'], deck_info['type'], deck_info['set_code']) def write_deck_file(deck_info: Dict, deck_text: str) -> None: deck_path = build_deck_path(deck_info) os.makedirs(deck_path, exist_ok=True) filename = f"{deck_info['name']}.dck" file_path = os.path.join(deck_path, filename) with open(file_path, 'w') as f: f.write(deck_text) def migrate_decks(input_file: str, error_file: str) -> None: decks = load_decks(input_file) error_decks: List[Dict] = [] for deck in decks: try: deck_info = get_deck_info(deck) deck_text = build_deck_text(deck_info) write_deck_file(deck_info, deck_text) except KeyError: error_decks.append(deck) if error_decks: with open(error_file, 'w') as f: json.dump(error_decks, f) if __name__ == '__main__': migrate_decks('decks_v2.json', 'error_decks.json')decks_v2.jsonfile and themigrate_decks.pyfile are located. You can do this by typingcdfollowed by the path to the folder, such ascd C:\Users\YourName\Downloads\magic-preconstructed-decks-master.python migrate_decks.pyand press Enter to run the Python script..dckfile for each deck in thedecks_v2.jsonfile, with the desired structure.Note: If you don't have Python installed on your computer, you can download it from the official website: https://www.python.org/downloads/. Choose the latest version for your operating system and follow the installation instructions.