1a4965fd83
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.
173 lines
6.4 KiB
Python
173 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
|