1) The CubeCobra CSV headers have changed slightly, capitalizing some words. 2) Cards in the maybeboard should not be included in the averages, so this filters them out. 3) Minor simplifications made to the keyword and word count analysis files to make it a bit easier for amateurs like me to figure out how to run these scripts.
208 lines
No EOL
6.1 KiB
Python
208 lines
No EOL
6.1 KiB
Python
import json
|
|
|
|
from collections import defaultdict
|
|
|
|
import cube_json
|
|
import cubecobra_csv
|
|
|
|
|
|
def load_cube_from_txt(filename):
|
|
f_cube_list = open(filename)
|
|
cards = []
|
|
for line in f_cube_list:
|
|
cards += [line.strip()]
|
|
return cards
|
|
|
|
|
|
TEMP_JSON = 'cube_temp.json'
|
|
ALL_CARDS_CLEAN_JSON = 'oracle_cards_clean.json'
|
|
|
|
|
|
EXPECTED_HEADER = [
|
|
'Name',
|
|
'CMC',
|
|
'Type',
|
|
'Color',
|
|
'Set',
|
|
'Collector Number',
|
|
'Rarity',
|
|
'Color Category',
|
|
'Status',
|
|
'Finish',
|
|
'Maybeboard',
|
|
'Image URL',
|
|
'Image Back URL',
|
|
'Tags',
|
|
'Notes',
|
|
'MTGO ID'
|
|
]
|
|
COLUMNS = {column_name: i for i, column_name in enumerate(EXPECTED_HEADER)}
|
|
|
|
|
|
def is_actual_mtg_card(card_dict):
|
|
return card_dict['set_type'] not in {'memorabilia', 'funny', 'token'}
|
|
|
|
|
|
def create_all_cards_json():
|
|
with open('oracle_cards.json', encoding='utf8') as f_oracle_cards:
|
|
d = json.load(f_oracle_cards)
|
|
output_filename = ALL_CARDS_CLEAN_JSON
|
|
f_cube_json = open(output_filename, 'w+', encoding='utf8')
|
|
cube_data = []
|
|
for card in d:
|
|
if is_actual_mtg_card(card):
|
|
cube_data += [card]
|
|
string_data = json.dumps(cube_data)
|
|
f_cube_json.write(string_data)
|
|
f_cube_json.close()
|
|
return ALL_CARDS_CLEAN_JSON
|
|
|
|
|
|
def wc_fo(text):
|
|
# full oracle text word count
|
|
return len(text.split())
|
|
|
|
|
|
def wc_o(text):
|
|
# word count of oracle text without keyword explanation text
|
|
if "(" in text and ")" in text:
|
|
p1 = text.find("(")
|
|
p2 = text.find(")")
|
|
o = text[:p1] + text[p2 + 1:]
|
|
return wc_o(o)
|
|
else:
|
|
return len(text.split())
|
|
|
|
|
|
def word_count(card, *, full_oracle):
|
|
if full_oracle:
|
|
wc = wc_fo
|
|
else:
|
|
wc = wc_o
|
|
if 'card_faces' in card.keys():
|
|
total_count = 0
|
|
for face in card['card_faces']:
|
|
text = face['oracle_text']
|
|
total_count += wc(text)
|
|
return total_count
|
|
else:
|
|
text = card['oracle_text']
|
|
return wc(text)
|
|
|
|
|
|
def cube_word_count(filename, *, full_oracle):
|
|
with open(filename, encoding='utf8') as f:
|
|
d = json.load(f)
|
|
wc = []
|
|
for card in d:
|
|
words = word_count(card, full_oracle=full_oracle)
|
|
wc += [words]
|
|
mean = sum(wc) / len(wc)
|
|
if full_oracle:
|
|
metric = 'Avg Words/Card (full text)'
|
|
else:
|
|
metric = 'Avg Words/Card (no reminders)'
|
|
print(f"{metric}: {mean:.1f}")
|
|
return mean
|
|
|
|
|
|
def duplicate_count(filename):
|
|
with open(filename, encoding='utf8') as f:
|
|
d = json.load(f)
|
|
unique = []
|
|
for card in d:
|
|
if card['name'] not in unique:
|
|
unique += [card['name']]
|
|
print(f"{len(unique)} unique of {len(d)} total cards")
|
|
|
|
|
|
WHEEL = str.maketrans('WUBRG', '01234')
|
|
|
|
|
|
def wheel_order(colors):
|
|
return colors.translate(WHEEL)
|
|
|
|
|
|
def print_by_color(filename, *, rank_cards, full_oracle):
|
|
cards_by_color_identity = defaultdict(list)
|
|
with open(filename, encoding='utf8') as f:
|
|
d = json.load(f)
|
|
for card in d:
|
|
words = word_count(card, full_oracle=full_oracle)
|
|
if 'Land' in card['type_line'].split('//')[0]:
|
|
identity = 'Non-basic land'
|
|
elif len(card['color_identity']) > 1:
|
|
identity = 'Multicolor'
|
|
else:
|
|
identity = ''.join(card['color_identity'])
|
|
cards_by_color_identity[identity].append((card['name'], words))
|
|
# pp(cards_by_color_identity)
|
|
# sort first by fewest colors in identity, then by WUBRG order
|
|
for identity, card_tuples in sorted(cards_by_color_identity.items(), key=lambda t:(len(t[0]), wheel_order(t[0]))):
|
|
total_words = sum(words for _, words in card_tuples)
|
|
card_count = len(card_tuples)
|
|
average_words = total_words / card_count
|
|
identity_name = 'Non-land colorless' if not identity else identity
|
|
print(f"{identity_name }: average {average_words:.2f} [of {card_count} cards]")
|
|
if rank_cards:
|
|
for card_name, card_words in sorted(card_tuples, key=lambda t: t[1], reverse=True):
|
|
print(f'{card_name}: {card_words}')
|
|
print()
|
|
print()
|
|
|
|
|
|
def get_text(card):
|
|
if 'oracle_text' in card.keys():
|
|
return card['oracle_text']
|
|
elif 'card_faces' in card.keys():
|
|
text = ""
|
|
for face in card['card_faces']:
|
|
text += face['oracle_text'] + ' '
|
|
return text
|
|
|
|
if __name__ == '__main__':
|
|
################################################################################
|
|
|
|
full_oracle = False
|
|
|
|
################################################################################
|
|
# Use either option:
|
|
|
|
# 1. If you have your cube in Cube Cobra and want to filter per tag
|
|
# csv_path = cubecobra_csv.request_cube_csv('TheElegantCube_fetched', 'elegant')
|
|
# cube_list = cubecobra_csv.load_cube_names(csv_path)
|
|
|
|
# 2. If you have your cube in Cube Cobra and want to consider only cards with a certain tag
|
|
cube_id = 'jeskaicube'
|
|
csv_path = cubecobra_csv.request_cube_csv(cube_id, cube_id)
|
|
cube_list = cubecobra_csv.load_cube_names(csv_path, tag_filter=None)
|
|
|
|
# 3. If you have a .txt of your cube
|
|
# cube_list = cube_json.load_cube_from_txt('YourCubeHere.txt')
|
|
|
|
################################################################################
|
|
# Calculate average of a cube
|
|
cube_json_handle = cube_json.create_cube_json(cube_list)
|
|
|
|
# Summary of average words by color
|
|
print_by_color(cube_json_handle, rank_cards=False, full_oracle=full_oracle)
|
|
|
|
# Individual cards by color, ranked by word count
|
|
print_by_color(cube_json_handle, rank_cards=True, full_oracle=full_oracle)
|
|
|
|
# Average words excluding reminder text
|
|
cube_word_count(cube_json_handle, full_oracle=False)
|
|
|
|
# Average words in full oracle text
|
|
cube_word_count(cube_json_handle, full_oracle=True)
|
|
|
|
################################################################################
|
|
# Calculate average of all Magic cards
|
|
|
|
# card_db_json_handle = create_all_cards_json()
|
|
# print_by_color(card_db_json_handle, rank_cards=True, full_oracle=full_oracle)
|
|
# cube_word_count(card_db_json_handle, full_oracle=full_oracle)
|
|
|
|
################################################################################
|
|
|
|
pass |