Merge branch 'PAK90-master'
This commit is contained in:
commit
77835f9f08
3 changed files with 171 additions and 8 deletions
42
decode.py
42
decode.py
|
@ -1,6 +1,8 @@
|
|||
#!/usr/bin/env python
|
||||
import sys
|
||||
import os
|
||||
import zipfile
|
||||
import shutil
|
||||
|
||||
libdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'lib')
|
||||
sys.path.append(libdir)
|
||||
|
@ -14,7 +16,8 @@ def exclude_sets(cardset):
|
|||
return cardset == 'Unglued' or cardset == 'Unhinged' or cardset == 'Celebration'
|
||||
|
||||
def main(fname, oname = None, verbose = True,
|
||||
gatherer = False, for_forum = False, creativity = False, norarity = False):
|
||||
gatherer = False, for_forum = False, for_mse = False,
|
||||
creativity = False, norarity = False):
|
||||
cards = []
|
||||
valid = 0
|
||||
invalid = 0
|
||||
|
@ -107,9 +110,19 @@ def main(fname, oname = None, verbose = True,
|
|||
namediff = Namediff()
|
||||
|
||||
def writecards(writer):
|
||||
if for_mse:
|
||||
# have to prepend a massive chunk of formatting info
|
||||
writer.write(utils.mse_prepend)
|
||||
for card in cards:
|
||||
writer.write((card.format(gatherer = gatherer, for_forum = for_forum)).encode('utf-8'))
|
||||
if for_mse:
|
||||
writer.write(card.to_mse().encode('utf-8'))
|
||||
else:
|
||||
writer.write(card.format(gatherer = gatherer,
|
||||
for_forum = for_forum).encode('utf-8'))
|
||||
|
||||
if creativity:
|
||||
if for_mse:
|
||||
writer.write('\tnotes:\n\t\t'.encode('utf-8'))
|
||||
writer.write('~~ closest cards ~~\n'.encode('utf-8'))
|
||||
nearest = cbow.nearest(card)
|
||||
for dist, cardname in nearest:
|
||||
|
@ -126,11 +139,31 @@ def main(fname, oname = None, verbose = True,
|
|||
writer.write((cardname + ': ' + str(dist) + '\n').encode('utf-8'))
|
||||
writer.write('\n'.encode('utf-8'))
|
||||
|
||||
if for_mse:
|
||||
# more formatting info
|
||||
writer.write('version control:\n\ttype: none\napprentice code: ')
|
||||
|
||||
if oname:
|
||||
if verbose:
|
||||
print 'Writing output to: ' + oname
|
||||
with open(oname, 'w') as ofile:
|
||||
writecards(ofile)
|
||||
if for_mse:
|
||||
# Copy whatever output file is produced, name the copy 'set' (yes, no extension).
|
||||
if os.path.isfile('set'):
|
||||
print 'ERROR: tried to overwrite existing file "set" - aborting.'
|
||||
return
|
||||
shutil.copyfile(oname, 'set')
|
||||
# Use the freaky mse extension instead of zip.
|
||||
with zipfile.ZipFile(oname+'.mse-set', mode='w') as zf:
|
||||
try:
|
||||
# Zip up the set file into oname.mse-set.
|
||||
zf.write('set')
|
||||
finally:
|
||||
if verbose:
|
||||
print 'Made an MSE set file called ' + oname + '.mse-set.'
|
||||
# The set file is useless outside the .mse-set, delete it.
|
||||
os.remove('set')
|
||||
else:
|
||||
writecards(sys.stdout)
|
||||
sys.stdout.flush()
|
||||
|
@ -154,9 +187,10 @@ if __name__ == '__main__':
|
|||
help='the card format has no rarity field; use for legacy input')
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
help='verbose output')
|
||||
parser.add_argument('-mse', '--mse', action='store_true', help='use Magic Set Editor 2 encoding; will output as .mse-set file')
|
||||
|
||||
args = parser.parse_args()
|
||||
main(args.infile, args.outfile, verbose = args.verbose,
|
||||
gatherer = args.gatherer, for_forum = args.forum, creativity = args.creativity,
|
||||
norarity = args.norarity)
|
||||
gatherer = args.gatherer, for_forum = args.forum, for_mse = args.mse,
|
||||
creativity = args.creativity, norarity = args.norarity)
|
||||
exit(0)
|
||||
|
|
134
lib/cardlib.py
134
lib/cardlib.py
|
@ -17,6 +17,11 @@ try:
|
|||
import textwrap
|
||||
import nltk.data
|
||||
sent_tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')
|
||||
# This could me made smarter - MSE will capitalize for us after :,
|
||||
# but we still need to capitalize the first english component of an activation
|
||||
# cost that starts with symbols, such as {2U}, *R*emove a +1/+1 counter from @: etc.
|
||||
def cap(s):
|
||||
return s[:1].capitalize() + s[1:]
|
||||
# This crazy thing is actually invoked as an unpass, so newlines are still
|
||||
# encoded.
|
||||
def sentencecase(s):
|
||||
|
@ -26,11 +31,26 @@ try:
|
|||
for line in lines:
|
||||
if line:
|
||||
sentences = sent_tokenizer.tokenize(line)
|
||||
clines += [' '.join([sent.capitalize() for sent in sentences])]
|
||||
clines += [' '.join([cap(sent) for sent in sentences])]
|
||||
return utils.newline.join(clines).replace(utils.reserved_marker, utils.x_marker)
|
||||
except ImportError:
|
||||
# non-nltk implementation provided by PAK90
|
||||
def uppercaseNewLineAndFullstop(string):
|
||||
# ok, let's capitalize every letter after a full stop and newline.
|
||||
# first let's find all indices of '.' and '\n'
|
||||
indices = [0] # initialise with 0, since we always want to capitalise the first letter.
|
||||
newlineIndices = [0] # also need to keep track of pure newlines (for planeswalkers).
|
||||
for i in range (len(string)):
|
||||
if string[i] == '\\':
|
||||
indices.append(i + 1) # we want the index of the letter after the \n, so add one.
|
||||
newlineIndices.append(i + 1)
|
||||
if string[i] == '.' or string[i] == "=": # also handle the choice bullets.
|
||||
indices.append(i + 2) # we want the index of the letter after the ., so we need to count the space as well.
|
||||
indexSet = set(indices) # convert it to a set for the next part; the capitalisation.
|
||||
return "".join(c.upper() if i in indexSet else c for i, c in enumerate(string))
|
||||
|
||||
def sentencecase(s):
|
||||
return s
|
||||
return uppercaseNewLineAndFullstop(s)
|
||||
|
||||
# These are used later to determine what the fields of the Card object are called.
|
||||
# Define them here because they have nothing to do with the actual format.
|
||||
|
@ -109,6 +129,7 @@ def fields_check_valid(fields):
|
|||
else:
|
||||
return not field_pt in fields
|
||||
|
||||
|
||||
# These functions take a bunch of source data in some format and turn
|
||||
# it into nicely labeled fields that we know how to initialize a card from.
|
||||
# Both return a dict that maps field names to lists of possible values,
|
||||
|
@ -141,7 +162,7 @@ def fields_check_valid(fields):
|
|||
# layout - string
|
||||
# rarity - string
|
||||
# flavor - string
|
||||
# artis - string
|
||||
# artist - string
|
||||
# number - string
|
||||
# multiverseid - number
|
||||
# variations - list
|
||||
|
@ -530,7 +551,7 @@ class Card:
|
|||
|
||||
return outstr
|
||||
|
||||
def format(self, gatherer = False, for_forum = False):
|
||||
def format(self, gatherer = False, for_forum = False, for_mse = False):
|
||||
outstr = ''
|
||||
if gatherer:
|
||||
cardname = titlecase(self.__dict__[field_name])
|
||||
|
@ -663,6 +684,111 @@ class Card:
|
|||
|
||||
return outstr
|
||||
|
||||
def to_mse(self):
|
||||
outstr = ''
|
||||
|
||||
# need a 'card' string first
|
||||
outstr += 'card:\n'
|
||||
|
||||
cardname = titlecase(self.__dict__[field_name])
|
||||
outstr += '\tname: ' + cardname + '\n'
|
||||
|
||||
if self.__dict__[field_rarity]:
|
||||
if self.__dict__[field_rarity] in utils.json_rarity_unmap:
|
||||
rarity = utils.json_rarity_unmap[self.__dict__[field_rarity]]
|
||||
else:
|
||||
rarity = self.__dict__[field_rarity]
|
||||
outstr += '\trarity: ' + rarity.lower() + '\n'
|
||||
#if not self.parsed:
|
||||
# outstr += ' _UNPARSED_'
|
||||
#if not self.valid:
|
||||
# outstr += ' _INVALID_'
|
||||
|
||||
if not self.__dict__[field_cost].none:
|
||||
outstr += '\tcasting cost: ' + self.__dict__[field_cost].format().replace('{','').replace('}','')
|
||||
outstr += '\n'
|
||||
|
||||
outstr += '\tsuper type: ' + ' '.join(self.__dict__[field_supertypes]
|
||||
+ self.__dict__[field_types]).title() + '\n'
|
||||
if self.__dict__[field_subtypes]:
|
||||
outstr += '\tsub type: ' + ' '.join(self.__dict__[field_subtypes]).title() + '\n'
|
||||
|
||||
if self.__dict__[field_text].text:
|
||||
mtext = self.__dict__[field_text].text
|
||||
mtext = transforms.text_unpass_1_choice(mtext, delimit = False)
|
||||
mtext = transforms.text_unpass_2_counters(mtext)
|
||||
mtext = transforms.text_unpass_3_unary(mtext)
|
||||
mtext = transforms.text_unpass_4_symbols(mtext, False)
|
||||
mtext = sentencecase(mtext)
|
||||
# I don't really want these MSE specific passes in transforms,
|
||||
# but they could be pulled out separately somewhere else in here.
|
||||
mtext = mtext.replace(utils.this_marker, '<atom-cardname><nospellcheck>'
|
||||
+ utils.this_marker + '</nospellcheck></atom-cardname>')
|
||||
mtext = transforms.text_unpass_5_cardname(mtext, cardname)
|
||||
mtext = transforms.text_unpass_6_newlines(mtext)
|
||||
newtext = Manatext('')
|
||||
newtext.text = mtext
|
||||
newtext.costs = self.__dict__[field_text].costs
|
||||
newtext = newtext.format()
|
||||
|
||||
#NOT NEEDED newtext = newtext.replace(utils.this_marker, cardname) # first let's put the cardname where all the @s are.
|
||||
|
||||
|
||||
# newtext = newtext.replace(utils.counter_rename + ".", "countered.") # then replace any 'uncast' at the end of a sentence with 'countered'.
|
||||
# newtext = newtext.replace(utils.dash_marker, u'\u2014') # also replace the ~ with a u2014 for choices.
|
||||
# newtext = newtext.replace(utils.counter_rename, "counter") # then replace all the mid-sentence 'uncast' with 'counter'.
|
||||
# newtext = newtext.replace('{','<sym-auto>').replace('}','</sym-auto>') # now we encase mana/tap symbols with the correct tags for mse.
|
||||
# linecount = newtext.count('\n') + 1 # adding 1 because no newlines means 1 line, 1 newline means 2 lines etc.
|
||||
|
||||
# newtext = sentencecase(newtext) # make all the things uppercase!
|
||||
|
||||
# # done after uppercasing everything because string[i] == u2022 doesn't work apparently.
|
||||
# newtext = newtext.replace(utils.bullet_marker, u'\u2022') # replace the = with a u2022.
|
||||
|
||||
# used later
|
||||
linecount = newtext.count('\n') + 1 # adding 1 because no newlines means 1 line, 1 newline means 2 lines etc.
|
||||
|
||||
# actually really important
|
||||
newtext = newtext.replace('{','<sym-auto>').replace('}','</sym-auto>') # now we encase mana/tap symbols with the correct tags for mse.
|
||||
|
||||
newlineIndices = [0] # also need to keep track of pure newlines (for planeswalkers).
|
||||
for i in range (len(newtext)):
|
||||
if newtext[i] == '\n':
|
||||
newlineIndices.append(i + 1)
|
||||
|
||||
# need to do Special Things if it's a planeswalker.
|
||||
if "planeswalker" in str(self.__dict__[field_types]): # for some reason this is in types, not supertypes...
|
||||
outstr += '\tstylesheet: m15-planeswalker\n' # set the proper card style for a 3-line walker.
|
||||
|
||||
# set up the loyalty cost fields using regex to find how many there are.
|
||||
i = 0
|
||||
lcost_regex = r'[-+]?\d+: ' # 1+ figures, might be 0.
|
||||
for costs in re.findall(lcost_regex, newtext):
|
||||
i += 1
|
||||
outstr += '\tloyalty cost ' + str(i) + ': ' + costs + '\n'
|
||||
# sub out the loyalty costs.
|
||||
newtext = re.sub(lcost_regex, '', newtext)
|
||||
|
||||
#newtext = sentencecase(newtext) # we need to uppercase again; previous uppercase call didn't work due to loyalty costs being there.
|
||||
|
||||
if self.__dict__[field_loyalty]:
|
||||
outstr += '\tloyalty: ' + utils.from_unary(self.__dict__[field_loyalty]) + '\n'
|
||||
|
||||
newtext = newtext.replace('\n','\n\t\t')
|
||||
outstr += '\trule text:\n\t\t' + newtext + '\n'
|
||||
|
||||
if self.__dict__[field_pt]:
|
||||
ptstring = utils.from_unary(self.__dict__[field_pt]).split('/')
|
||||
if (len(ptstring) > 1): #really don't want to be accessing anything nonexistent.
|
||||
outstr += '\tpower: ' + ptstring[0] + '\n'
|
||||
outstr += '\ttoughness: ' + ptstring[1] + '\n'
|
||||
#outstr += '\n'
|
||||
|
||||
# now append all the other useless fields that the setfile expects.
|
||||
outstr += '\thas styling: false\n\tnotes:\n\ttime created:2015-07-20 22:53:07\n\ttime modified:2015-07-20 22:53:08\n\textra data:\n\timage:\n\tcard code text:\n\tcopyright:\n\timage 2:\n\tcopyright 2: '
|
||||
|
||||
return outstr
|
||||
|
||||
def vectorize(self):
|
||||
ld = '('
|
||||
rd = ')'
|
||||
|
|
|
@ -6,6 +6,9 @@ import re
|
|||
|
||||
import config
|
||||
|
||||
# special chunk of text that Magic Set Editor 2 requires at the start of all set files.
|
||||
mse_prepend = 'mse version: 0.3.8\ngame: magic\nstylesheet: m15\nset info:\n\tsymbol:\nstyling:\n\tmagic-m15:\n\t\ttext box mana symbols: magic-mana-small.mse-symbol-font\n\t\toverlay:\n\tmagic-m15-clear:\n\t\ttext box mana symbols: magic-mana-small.mse-symbol-font\n\t\toverlay: \n\tmagic-m15-extra-improved:\n\t\ttext box mana symbols: magic-mana-small.mse-symbol-font\n\t\tpt box symbols: magic-pt-symbols-extra.mse-symbol-font\n\t\toverlay: \n\tmagic-m15-planeswalker:\n\t\ttext box mana symbols: magic-mana-small.mse-symbol-font\n\t\toverlay: \n\tmagic-m15-planeswalker-promo-black:\n\t\ttext box mana symbols: magic-mana-small.mse-symbol-font\n\t\toverlay: \n\tmagic-m15-promo-dka:\n\t\ttext box mana symbols: magic-mana-small.mse-symbol-font\n\t\toverlay: \n\tmagic-m15-token-clear:\n\t\ttext box mana symbols: magic-mana-small.mse-symbol-font\n\t\toverlay: \n\tmagic-new-planeswalker:\n\t\ttext box mana symbols: magic-mana-small.mse-symbol-font\n\t\toverlay: \n\tmagic-new-planeswalker-4abil:\n\t\ttext box mana symbols: magic-mana-small.mse-symbol-font\n\t\toverlay: \n\tmagic-new-planeswalker-clear:\n\t\ttext box mana symbols: magic-mana-small.mse-symbol-font\n\t\toverlay: \n\tmagic-new-planeswalker-promo-black:\n\t\ttext box mana symbols: magic-mana-small.mse-symbol-font\n\t\toverlay: \n'
|
||||
|
||||
# separators
|
||||
cardsep = config.cardsep
|
||||
fieldsep = config.fieldsep
|
||||
|
|
Loading…
Reference in a new issue