Skip to content

Commit

Permalink
Merge branch 'xlsx_all_cards_page'
Browse files Browse the repository at this point in the history
  • Loading branch information
gwax committed Mar 16, 2016
2 parents 5314ec5 + 1fded01 commit dc10aca
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 90 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ script: |
else
error_without_calling_exit;
fi
# - pandoc --from=markdown --to=rst README.md | diff DESCRIPTION.rst -
after_success: |
if [ "${TEST_SUITE}" = "test" ]; then
Expand Down
118 changes: 76 additions & 42 deletions mtg_ssm/serialization/xlsx.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,11 @@
'count',
]

ALL_SETS_SHEET_TOTALS = [
'Total',
None,
None,
None,
None,
'=SUM(F3:F65535)',
'=SUM(G3:G65535)',
'=SUM(H3:H65535)',
'=SUM(I3:I65535)',
]
ALL_SETS_SHEET_TOTALS = (
['Total'] +
[None] * 4 +
['=SUM({c}3:{c}65535)'.format(c=c) for c in 'FGHI']
)


def create_all_sets(sheet, collection):
Expand Down Expand Up @@ -74,23 +68,6 @@ def style_all_sets(sheet):
cdim.hidden = hidden


SET_SHEET_HEADER = [
'have',
'name',
'id',
'multiverseid',
'number',
'artist',
] + [ct.name for ct in models.CountTypes] + [
'others',
]
COUNT_COLS = [
string.ascii_uppercase[SET_SHEET_HEADER.index(ct.name)]
for ct in models.CountTypes]
HAVE_TMPL = '=' + '+'.join(c + '{0}' for c in COUNT_COLS)
ROW_OFFSET = 2


def create_haverefs(printings):
"""Create a reference to the have cells for printings in a single set."""
card_set = printings[0].set
Expand All @@ -101,26 +78,80 @@ def create_haverefs(printings):
return '+'.join(haverefs)


def get_other_print_references(printing):
"""Get an xlsx formula to list counts of a card from other sets."""
if printing.card.strict_basic:
def get_references(card, exclude_sets=None):
"""Get an equation for the references to a card."""
if card.strict_basic:
return None # Basics are so prolific that they overwhelm Excel

set_to_others = collections.defaultdict(list)
for other in printing.card.printings:
if other.set_code != printing.set_code:
set_to_others[other.set].append(other)
if exclude_sets is None:
exclude_sets = set()

set_to_haveref = {k: create_haverefs(v) for k, v in set_to_others.items()}
set_to_prints = collections.defaultdict(list)
for printing in card.printings:
if printing.set not in exclude_sets:
set_to_prints[printing.set].append(printing)

set_to_haveref = {k: create_haverefs(v) for k, v in set_to_prints.items()}
if not set_to_haveref:
return None

other_references = []
references = []
for card_set in sorted(set_to_haveref, key=lambda cset: cset.release_date):
other_reference = 'IF({count}>0,"{setcode}: "&{count}&", ","")'.format(
reference = 'IF({count}>0,"{setcode}: "&{count}&", ","")'.format(
setcode=card_set.code, count=set_to_haveref[card_set])
other_references.append(other_reference)
return '=' + '&'.join(other_references)
references.append(reference)
return '=' + '&'.join(references)


ALL_CARDS_SHEET_HEADER = [
'name',
'have',
]


def create_all_cards(sheet, collection):
"""Create all cards sheet from collection."""
sheet.title = 'All Cards'
sheet.append(ALL_CARDS_SHEET_HEADER)
# Should this be done in the collection class indexes?
# Should card_sets not be done in the collection indexes?
cards = sorted(collection.name_to_card.values(), key=lambda c: c.name)
for card in cards:
row = [
card.name,
get_references(card),
]
sheet.append(row)


def style_all_cards(sheet):
"""Apply styles to the all cards sheet."""
sheet.freeze_panes = sheet['B2']
col_width_hidden = [
('A', 24, False),
('B', 32, False),
]
for col, width, hidden in col_width_hidden:
cdim = sheet.column_dimensions[col]
cdim.width = width
cdim.hidden = hidden


SET_SHEET_HEADER = [
'have',
'name',
'id',
'multiverseid',
'number',
'artist',
] + [ct.name for ct in models.CountTypes] + [
'others',
]
COUNT_COLS = [
string.ascii_uppercase[SET_SHEET_HEADER.index(ct.name)]
for ct in models.CountTypes]
HAVE_TMPL = '=' + '+'.join(c + '{0}' for c in COUNT_COLS)
ROW_OFFSET = 2


def create_set_sheet(sheet, card_set):
Expand All @@ -139,7 +170,7 @@ def create_set_sheet(sheet, card_set):
]
for counttype in models.CountTypes:
row.append(printing.counts.get(counttype))
row.append(get_other_print_references(printing))
row.append(get_references(printing.card, exclude_sets={card_set}))
sheet.append(row)


Expand Down Expand Up @@ -184,6 +215,9 @@ def write_to_file(self, filename: str) -> None:
all_sets_sheet = workbook.create_sheet()
create_all_sets(all_sets_sheet, self.collection)
style_all_sets(all_sets_sheet)
all_cards_sheet = workbook.create_sheet()
create_all_cards(all_cards_sheet, self.collection)
style_all_cards(all_cards_sheet)
for card_set in self.collection.card_sets:
set_sheet = workbook.create_sheet()
create_set_sheet(set_sheet, card_set)
Expand All @@ -196,7 +230,7 @@ def read_from_file(self, filename: str) -> None:
workbook = openpyxl.load_workbook(filename=filename, read_only=True)
for sheet in workbook.worksheets:
if sheet.title not in self.collection.code_to_card_set:
if sheet.title in ['Sets', 'All Sets']:
if sheet.title in {'Sets', 'All Sets', 'All Cards'}:
continue
raise interface.DeserializationError(
'No known set with code {}'.format(sheet.title))
Expand Down
112 changes: 65 additions & 47 deletions tests/serialization/test_xlsx.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ class XlsxSerializerTest(mtgjson_testcase.MtgJsonTestCase):

def setUp(self):
super().setUp()
self.collection = collection.Collection(self.mtg_data)
set_data = {
k: v for k, v in self.mtg_data.items()
if k in {'LEA', 'FEM', 'S00', 'ICE', 'HOP'}}
self.collection = collection.Collection(set_data)

def test_create_all_sets(self):
# Setup
Expand All @@ -35,20 +38,9 @@ def test_create_all_sets(self):
['Total', None, None, None, None, '=SUM(F3:F65535)', '=SUM(G3:G65535)', '=SUM(H3:H65535)', '=SUM(I3:I65535)'],
['LEA', 'Limited Edition Alpha', dt.datetime(1993, 8, 5), None, 'core', 4, '=COUNTIF(\'LEA\'!A:A,">0")', '=COUNTIF(\'LEA\'!A:A,">=4")', "=SUM('LEA'!A:A)"],
['FEM', 'Fallen Empires', dt.datetime(1994, 11, 1), None, 'expansion', 4, '=COUNTIF(\'FEM\'!A:A,">0")', '=COUNTIF(\'FEM\'!A:A,">=4")', "=SUM('FEM'!A:A)"],
['pMEI', 'Media Inserts', dt.datetime(1995, 1, 1), None, 'promo', 1, '=COUNTIF(\'pMEI\'!A:A,">0")', '=COUNTIF(\'pMEI\'!A:A,">=4")', "=SUM('pMEI'!A:A)"],
['ICE', 'Ice Age', dt.datetime(1995, 6, 1), 'Ice Age', 'expansion', 5, '=COUNTIF(\'ICE\'!A:A,">0")', '=COUNTIF(\'ICE\'!A:A,">=4")', "=SUM('ICE'!A:A)"],
['HML', 'Homelands', dt.datetime(1995, 10, 1), None, 'expansion', 2, '=COUNTIF(\'HML\'!A:A,">0")', '=COUNTIF(\'HML\'!A:A,">=4")', "=SUM('HML'!A:A)"],
['S00', 'Starter 2000', dt.datetime(2000, 4, 1), None, 'starter', 1, '=COUNTIF(\'S00\'!A:A,">0")', '=COUNTIF(\'S00\'!A:A,">=4")', "=SUM('S00'!A:A)"],
['PLS', 'Planeshift', dt.datetime(2001, 2, 5), 'Invasion', 'expansion', 2, '=COUNTIF(\'PLS\'!A:A,">0")', '=COUNTIF(\'PLS\'!A:A,">=4")', "=SUM('PLS'!A:A)"],
['CHK', 'Champions of Kamigawa', dt.datetime(2004, 10, 1, 0, 0), 'Kamigawa', 'expansion', 2, '=COUNTIF(\'CHK\'!A:A,">0")', '=COUNTIF(\'CHK\'!A:A,">=4")', "=SUM('CHK'!A:A)"],
['PLC', 'Planar Chaos', dt.datetime(2007, 2, 2, 0, 0), 'Time Spiral', 'expansion', 2, '=COUNTIF(\'PLC\'!A:A,">0")', '=COUNTIF(\'PLC\'!A:A,">=4")', "=SUM('PLC'!A:A)"],
['pMGD', 'Magic Game Day', dt.datetime(2007, 7, 14), None, 'promo', 1, '=COUNTIF(\'pMGD\'!A:A,">0")', '=COUNTIF(\'pMGD\'!A:A,">=4")', "=SUM('pMGD'!A:A)"],
['HOP', 'Planechase', dt.datetime(2009, 9, 4), None, 'planechase', 3, '=COUNTIF(\'HOP\'!A:A,">0")', '=COUNTIF(\'HOP\'!A:A,">=4")', "=SUM('HOP'!A:A)"],
['ARC', 'Archenemy', dt.datetime(2010, 6, 18), None, 'archenemy', 2, '=COUNTIF(\'ARC\'!A:A,">0")', '=COUNTIF(\'ARC\'!A:A,">=4")', "=SUM('ARC'!A:A)"],
['ISD', 'Innistrad', dt.datetime(2011, 9, 30), 'Innistrad', 'expansion', 6, '=COUNTIF(\'ISD\'!A:A,">0")', '=COUNTIF(\'ISD\'!A:A,">=4")', "=SUM('ISD'!A:A)"],
['PC2', 'Planechase 2012 Edition', dt.datetime(2012, 6, 1), None, 'planechase', 4, '=COUNTIF(\'PC2\'!A:A,">0")', '=COUNTIF(\'PC2\'!A:A,">=4")', "=SUM('PC2'!A:A)"],
['MMA', 'Modern Masters', dt.datetime(2013, 6, 7, 0, 0), None, 'reprint', 1, '=COUNTIF(\'MMA\'!A:A,">0")', '=COUNTIF(\'MMA\'!A:A,">=4")', "=SUM('MMA'!A:A)"],
['OGW', 'Oath of the Gatewatch', dt.datetime(2016, 1, 22, 0, 0), 'Battle for Zendikar', 'expansion', 4, '=COUNTIF(\'OGW\'!A:A,">0")', '=COUNTIF(\'OGW\'!A:A,">=4")', "=SUM('OGW'!A:A)"],
]
self.assertEqual(expected, rows)
self.assertEqual('All Sets', sheet.title)
Expand All @@ -72,48 +64,91 @@ def test_create_haverefs(self):

def test_get_refs_basic_land(self):
# Setup
lea_forest = self.collection.id_to_printing[
'5ede9781b0c5d157c28a15c3153a455d7d6180fa']
forest = self.collection.name_to_card['Forest']
# Execute
print_refs = xlsx.get_other_print_references(lea_forest)
print_refs = xlsx.get_references(forest)
# Verify
self.assertIsNone(print_refs)

def test_get_refs_no_others(self):
def test_get_refs_singular(self):
# Setup
rhox = self.collection.id_to_printing[
'536d407161fa03eddee7da0e823c2042a8fa0262']
rhox = self.collection.name_to_card['Rhox']
# Execute
print_refs = xlsx.get_other_print_references(rhox)
print_refs = xlsx.get_references(rhox)
# Verify
self.assertIsNone(print_refs)
expected = '=IF(\'S00\'!A2>0,"S00: "&\'S00\'!A2&", ","")'
self.assertEqual(expected, print_refs)

def test_ref_refs_multiple_sets(self):
def test_get_refs_exclude_only(self):
# Setup
lea_dark_rit = self.collection.id_to_printing[
'fff0b8e8fea06ee1ac5c35f048a0a459b1222673']
rhox = self.collection.name_to_card['Rhox']
s00 = self.collection.code_to_card_set['S00']
# Execute
print_refs = xlsx.get_other_print_references(lea_dark_rit)
print_refs = xlsx.get_references(rhox, exclude_sets={s00})
# Verify'
self.assertFalse(print_refs)

def test_get_refs_multiple_sets(self):
# Setup
dark_rit = self.collection.name_to_card['Dark Ritual']
lea = self.collection.code_to_card_set['LEA']
# Execute
print_refs = xlsx.get_references(dark_rit, exclude_sets={lea})
# Verify
expected = (
'=IF(\'ICE\'!A2>0,"ICE: "&\'ICE\'!A2&", ","")'
'&IF(\'HOP\'!A4>0,"HOP: "&\'HOP\'!A4&", ","")')
self.assertEqual(expected, print_refs)

def test_get_refs_multiple_variants(self):
def test_get_refs_exclude_multiple(self):
# Setup
mma_thallid = self.collection.id_to_printing[
'fc46a4b72d216117a352f59217a84d0baeaaacb7']

dark_rit = self.collection.name_to_card['Dark Ritual']
lea = self.collection.code_to_card_set['LEA']
ice = self.collection.code_to_card_set['ICE']
# Execute
print_refs = xlsx.get_other_print_references(mma_thallid)
print_refs = xlsx.get_references(dark_rit, exclude_sets={lea, ice})
# Verify
expected = '=IF(\'HOP\'!A4>0,"HOP: "&\'HOP\'!A4&", ","")'
self.assertEqual(expected, print_refs)

def test_get_refs_multiple_variants(self):
# Setup
thallid = self.collection.name_to_card['Thallid']
# Execute
print_refs = xlsx.get_references(thallid)
# Verify
expected = (
'=IF(\'FEM\'!A2+\'FEM\'!A3+\'FEM\'!A4+\'FEM\'!A5>0,'
'"FEM: "&\'FEM\'!A2+\'FEM\'!A3+\'FEM\'!A4+\'FEM\'!A5&", ","")')
self.assertEqual(expected, print_refs)

def test_create_all_cards_sheet(self):
# Setup
book = openpyxl.Workbook()
sheet = book.create_sheet()

# Execute
xlsx.create_all_cards(sheet, self.collection)

# Verify
rows = [[cell.value for cell in row] for row in sheet.rows]
expected = [
# pylint: disable=line-too-long
['name', 'have'],
['Academy at Tolaria West', '=IF(\'HOP\'!A2>0,"HOP: "&\'HOP\'!A2&", ","")'],
['Air Elemental', '=IF(\'LEA\'!A3>0,"LEA: "&\'LEA\'!A3&", ","")'],
["Akroma's Vengeance", '=IF(\'HOP\'!A3>0,"HOP: "&\'HOP\'!A3&", ","")'],
['Dark Ritual', '=IF(\'LEA\'!A2>0,"LEA: "&\'LEA\'!A2&", ","")&'
'IF(\'ICE\'!A2>0,"ICE: "&\'ICE\'!A2&", ","")&'
'IF(\'HOP\'!A4>0,"HOP: "&\'HOP\'!A4&", ","")'],
['Forest', None],
['Rhox', '=IF(\'S00\'!A2>0,"S00: "&\'S00\'!A2&", ","")'],
['Snow-Covered Forest', '=IF(\'ICE\'!A6>0,"ICE: "&\'ICE\'!A6&", ","")'],
['Thallid', '=IF(\'FEM\'!A2+\'FEM\'!A3+\'FEM\'!A4+\'FEM\'!A5>0,"FEM: "&\'FEM\'!A2+\'FEM\'!A3+\'FEM\'!A4+\'FEM\'!A5&", ","")'],
]
self.assertEqual(expected, rows)
self.assertEqual('All Cards', sheet.title)

def test_create_set_sheet(self):
# Setup
forest1 = self.collection.id_to_printing[
Expand Down Expand Up @@ -164,24 +199,7 @@ def test_write_to_file(self):
# Verify
workbook = openpyxl.load_workbook(filename=xlsxfilename)
expected_sheetnames = [
'All Sets',
'LEA',
'FEM',
'pMEI',
'ICE',
'HML',
'S00',
'PLS',
'CHK',
'PLC',
'pMGD',
'HOP',
'ARC',
'ISD',
'PC2',
'MMA',
'OGW',
]
'All Sets', 'All Cards', 'LEA', 'FEM', 'ICE', 'S00', 'HOP']
self.assertEqual(expected_sheetnames, workbook.sheetnames)

s00_rows = [[cell.value for cell in row] for row in workbook['S00']]
Expand Down

0 comments on commit dc10aca

Please sign in to comment.