159 lines
5.2 KiB
Python
Executable file
159 lines
5.2 KiB
Python
Executable file
#!/usr/bin/env python
|
|
import sys
|
|
import os
|
|
import random
|
|
import zipfile
|
|
import shutil
|
|
|
|
libdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../lib')
|
|
sys.path.append(libdir)
|
|
datadir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../data')
|
|
import utils
|
|
import jdecode
|
|
import ngrams
|
|
import analysis
|
|
import mtg_validate
|
|
|
|
from cbow import CBOW
|
|
|
|
separate_lines=True
|
|
|
|
def select_card(cards, stats, i):
|
|
card = cards[i]
|
|
nearest = stats['dists']['cbow'][i]
|
|
perp = stats['ngram']['perp'][i]
|
|
perp_per = stats['ngram']['perp_per'][i]
|
|
perp_max = stats['ngram']['perp_max'][i]
|
|
|
|
if nearest > 0.9 or perp_per > 2.0 or perp_max > 10.0:
|
|
return None
|
|
|
|
((_, total_good, _, _), _) = mtg_validate.process_props([card])
|
|
if not total_good == 1:
|
|
return False
|
|
|
|
# print '===='
|
|
# print nearest
|
|
# print perp
|
|
# print perp_per
|
|
# print perp_max
|
|
# print '----'
|
|
# print card.format()
|
|
|
|
return True
|
|
|
|
def compare_to_real(card, realcard):
|
|
ctypes = ' '.join(sorted(card.types))
|
|
rtypes = ' '.join(sorted(realcard.types))
|
|
return ctypes == rtypes and realcard.cost.check_colors(card.cost.get_colors())
|
|
|
|
def writecard(card, name, writer):
|
|
gatherer = False
|
|
for_forum = True
|
|
vdump = True
|
|
fmt = card.format(gatherer = gatherer, for_forum = for_forum, vdump = vdump)
|
|
oldname = card.name
|
|
# alter name used in image
|
|
card.name = name
|
|
writer.write(card.to_mse().encode('utf-8'))
|
|
card.name = oldname
|
|
fstring = ''
|
|
if card.json:
|
|
fstring += 'JSON:\n' + card.json + '\n'
|
|
if card.raw:
|
|
fstring += 'raw:\n' + card.raw + '\n'
|
|
fstring += '\n'
|
|
fstring += fmt + '\n'
|
|
fstring = fstring.replace('<', '(').replace('>', ')')
|
|
writer.write(('\n' + fstring[:-1]).replace('\n', '\n\t\t').encode('utf-8'))
|
|
writer.write('\n'.encode('utf-8'))
|
|
|
|
def main(fname, oname, n=20, verbose=False):
|
|
cbow = CBOW()
|
|
realcards = jdecode.mtg_open_file(str(os.path.join(datadir, 'output.txt')), verbose=verbose)
|
|
real_by_name = {c.name: c for c in realcards}
|
|
lm = ngrams.build_ngram_model(realcards, 3, separate_lines=separate_lines, verbose=verbose)
|
|
cards = jdecode.mtg_open_file(fname, verbose=verbose)
|
|
stats = analysis.get_statistics(fname, lm=lm, sep=separate_lines, verbose=verbose)
|
|
|
|
selected = []
|
|
for i in range(0, len(cards)):
|
|
if select_card(cards, stats, i):
|
|
selected += [(i, cards[i])]
|
|
|
|
limit = 3000
|
|
|
|
random.shuffle(selected)
|
|
#selected = selected[:limit]
|
|
|
|
if verbose:
|
|
print('computing nearest cards for ' + str(len(selected)) + ' candindates...')
|
|
cbow_nearest = cbow.nearest_par(map(lambda (i, c): c, selected))
|
|
for i in range(0, len(selected)):
|
|
(j, card) = selected[i]
|
|
selected[i] = (j, card, cbow_nearest[i])
|
|
if verbose:
|
|
print('...done')
|
|
|
|
final = []
|
|
for (i, card, nearest) in selected:
|
|
for dist, rname in nearest:
|
|
realcard = real_by_name[rname]
|
|
if compare_to_real(card, realcard):
|
|
final += [(i, card, realcard, dist)]
|
|
break
|
|
|
|
for (i, card, realcard, dist) in final:
|
|
print '-- real --'
|
|
print realcard.format()
|
|
print '-- fake --'
|
|
print card.format()
|
|
print '-- stats --'
|
|
perp_per = stats['ngram']['perp_per'][i]
|
|
perp_max = stats['ngram']['perp_max'][i]
|
|
print dist
|
|
print perp_per
|
|
print perp_max
|
|
print '----'
|
|
|
|
if not oname is None:
|
|
with open(oname, 'wt') as ofile:
|
|
ofile.write(utils.mse_prepend)
|
|
for (i, card, realcard, dist) in final:
|
|
name = realcard.name
|
|
writecard(realcard, name, ofile)
|
|
writecard(card, name, ofile)
|
|
ofile.write('version control:\n\ttype: none\napprentice code: ')
|
|
# 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')
|
|
|
|
if __name__ == '__main__':
|
|
|
|
import argparse
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument('infile', #nargs='?'. default=None,
|
|
help='encoded card file or json corpus to process')
|
|
parser.add_argument('outfile', nargs='?', default=None,
|
|
help='output file, defaults to none')
|
|
parser.add_argument('-n', '--n', action='store',
|
|
help='number of cards to consider for each pairing')
|
|
parser.add_argument('-v', '--verbose', action='store_true',
|
|
help='verbose output')
|
|
|
|
args = parser.parse_args()
|
|
main(args.infile, args.outfile, n=args.n, verbose=args.verbose)
|
|
exit(0)
|