mtgencode/lib/manalib.py
Bill Zorn 1a4965fd83 EVERYTHING HAS CHANGED
Added lib and script subdirs to organize things; the biggest change is that now
we have a really powerful Card class that can handle all of the decoding and
encoding for us. encode.py has been written to take advantage of this, other
things have not yet. Coming soon! As a side note the changes to output.txt
are purely cosemtic, though the order should be stable now.
2015-07-14 00:07:25 -07:00

174 lines
6.4 KiB
Python

# representation for mana costs and text with embedded mana costs
# data aggregating classes
import random
import re
import utils
class Manacost:
'''mana cost representation with data'''
# hardcoded to be dependent on the symbol structure... ah well
def get_colors(self):
colors = ''
for sym in self.symbols:
if self.symbols[sym] > 0:
symcolors = re.sub(r'2|P|S|X', '', sym)
for symcolor in symcolors:
if symcolor not in colors:
colors += symcolor
# sort so the order is always consistent
return ''.join(sorted(colors))
def check_colors(self, symbolstring):
for sym in symbolstring:
if not sym in self.colors:
return False
return True
def __init__(self, src, fmt = ''):
# source fields, exactly one will be set
self.raw = None
self.json = None
# flags
self.parsed = True
self.valid = True
self.none = False
# default values for all fields
self.inner = None
self.cmc = 0
self.colorless = 0
self.sequence = []
self.symbols = {sym : 0 for sym in utils.mana_syms}
self.allsymbols = {sym : 0 for sym in utils.mana_symall}
self.colors = ''
if fmt == 'json':
self.json = src
text = utils.mana_translate(self.json.upper())
else:
self.raw = src
text = self.raw
if text == '':
self.inner = ''
self.none = True
elif not (len(text) >= 2 and text[0] == '{' and text[-1] == '}'):
self.parsed = False
self.valid = False
else:
self.inner = text[1:-1]
# structure mirrors the decoding in utils, but we pull out different data here
idx = 0
while idx < len(self.inner):
# taking this branch is an infinite loop if unary_marker is empty
if (len(utils.mana_unary_marker) > 0 and
self.inner[idx:idx+len(utils.mana_unary_marker)] == utils.mana_unary_marker):
idx += len(utils.mana_unary_marker)
self.sequence += [utils.mana_unary_marker]
elif self.inner[idx:idx+len(utils.mana_unary_counter)] == utils.mana_unary_counter:
idx += len(utils.mana_unary_counter)
self.sequence += [utils.mana_unary_counter]
self.colorless += 1
self.cmc += 1
else:
old_idx = idx
for symlen in range(utils.mana_symlen_min, utils.mana_symlen_max + 1):
encoded_sym = self.inner[idx:idx+symlen]
if encoded_sym in utils.mana_symall_decode:
idx += symlen
# leave the sequence encoded for convenience
self.sequence += [encoded_sym]
sym = utils.mana_symall_decode[encoded_sym]
self.allsymbols[sym] += 1
if sym in utils.mana_symalt:
self.symbols[utils.mana_alt(sym)] += 1
else:
self.symbols[sym] += 1
if sym == utils.mana_X:
self.cmc += 0
elif utils.mana_2 in sym:
self.cmc += 2
else:
self.cmc += 1
break
# otherwise we'll go into an infinite loop if we see a symbol we don't know
if idx == old_idx:
idx += 1
self.valid = False
self.colors = self.get_colors()
def __str__(self):
return utils.mana_untranslate(utils.mana_open_delimiter + ''.join(self.sequence)
+ utils.mana_close_delimiter)
def format(self, for_forum = False):
return utils.mana_untranslate(utils.mana_open_delimiter + ''.join(self.sequence, for_forum)
+ utils.mana_close_delimiter)
def encode(self, randomize = False):
if self.none:
return ''
elif randomize:
# so this won't work very well if mana_unary_marker isn't empty
return (utils.mana_open_delimiter
+ ''.join(random.sample(self.sequence, len(self.sequence)))
+ utils.mana_close_delimiter)
else:
return utils.mana_open_delimiter + ''.join(self.sequence) + utils.mana_close_delimiter
class Manatext:
'''text representation with embedded mana costs'''
def __init__(self, src, fmt = ''):
# source fields
self.raw = None
self.json = None
# flags
self.valid = True
# default values for all fields
self.text = src
self.costs = []
if fmt == 'json':
self.json = src
manastrs = re.findall(utils.mana_json_regex, src)
else:
self.raw = src
manastrs = re.findall(utils.mana_regex, src)
for manastr in manastrs:
cost = Manacost(manastr, fmt)
if not cost.valid:
self.valid = False
self.costs += [cost]
self.text = self.text.replace(manastr, utils.reserved_mana_marker, 1)
if (utils.mana_open_delimiter in self.text
or utils.mana_close_delimiter in self.text
or utils.mana_json_open_delimiter in self.text
or utils.mana_json_close_delimiter in self.text):
self.valid = False
def __str__(self):
text = self.text
for cost in self.costs:
text = text.replace(utils.reserved_mana_marker, str(cost), 1)
return text
def format(self, for_forum = False):
text = self.text
for cost in self.costs:
text = text.replace(utils.reserved_mana_marker, cost.format(for_forum = for_forum), 1)
return text
def encode(self, randomize = False):
text = self.text
for cost in self.costs:
text = text.replace(utils.reserved_mana_marker, cost.encode(randomize = randomize), 1)
return text