|
|
|
@ -1,63 +1,88 @@ |
|
|
|
#!/usr/bin/python |
|
|
|
#!/usr/bin/python3 |
|
|
|
import argparse |
|
|
|
from string import ascii_lowercase |
|
|
|
import cmd2 |
|
|
|
import re |
|
|
|
import itertools |
|
|
|
from spellchecker import SpellChecker |
|
|
|
from concurrent.futures import ThreadPoolExecutor |
|
|
|
POOL = ThreadPoolExecutor() |
|
|
|
SPELL = None |
|
|
|
import os |
|
|
|
|
|
|
|
from candidates import candidates, filter_possibilities |
|
|
|
from dictionary import DEFAULT, ALTERNATE |
|
|
|
from word_remove_dialog import RemoveWordsActivity |
|
|
|
|
|
|
|
def init_spell_checker(): |
|
|
|
global SPELL |
|
|
|
SPELL = SpellChecker() |
|
|
|
SPELL.word_frequency.load_text_file('extra_words.txt') |
|
|
|
|
|
|
|
LOWERCASE = set(ascii_lowercase) |
|
|
|
DICTS = {"default": DEFAULT, "alt": ALTERNATE} |
|
|
|
# argparsers |
|
|
|
dictionary_manage_parser = argparse.ArgumentParser() |
|
|
|
commands = dictionary_manage_parser.add_mutually_exclusive_group() |
|
|
|
commands.add_argument( |
|
|
|
"-l", "--list", action="store_true", help="List available dictionaries" |
|
|
|
) |
|
|
|
commands.add_argument("-s", "--switch", help="Dictionary to swap to") |
|
|
|
|
|
|
|
future = POOL.submit(init_spell_checker) |
|
|
|
letter_set_manage = argparse.ArgumentParser() |
|
|
|
letter_set_manage.add_argument("letter", nargs="+") |
|
|
|
|
|
|
|
guessing = argparse.ArgumentParser() |
|
|
|
guessing.add_argument("pattern", help="Pattern to match") |
|
|
|
|
|
|
|
def canidates(letters, min=2): |
|
|
|
pos = [] |
|
|
|
for length in range(min, len(letters)+1): |
|
|
|
for comb in itertools.combinations(letters, length): |
|
|
|
for perm in itertools.permutations(comb): |
|
|
|
word = ''.join(perm) |
|
|
|
pos.append(word) |
|
|
|
return set(SPELL.known(pos)) |
|
|
|
|
|
|
|
class MainLoop(cmd2.Cmd): |
|
|
|
"""Loop for wordscape commands |
|
|
|
|
|
|
|
def filter_pos(pos, regex): |
|
|
|
pat = re.compile(regex + '$') |
|
|
|
return set(filter(pat.match, pos)) |
|
|
|
""" |
|
|
|
|
|
|
|
prompt = "<{}> $ " |
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
self.dict = "default" |
|
|
|
self.excludes = set() |
|
|
|
self.init_letters(input("Enter letters: ")) |
|
|
|
super().__init__() |
|
|
|
|
|
|
|
def init_letters(self, letters): |
|
|
|
if not isinstance(letters, str): |
|
|
|
letters = "".join(letters) |
|
|
|
letters = letters.lower() |
|
|
|
self.letters = [l for l in letters if l in LOWERCASE] |
|
|
|
self.prompt = MainLoop.prompt.format(", ".join(self.letters)) |
|
|
|
self.candidates = candidates(self.letters, DICTS[self.dict], self.excludes) |
|
|
|
|
|
|
|
@cmd2.with_argparser(dictionary_manage_parser) |
|
|
|
def do_dict(self, args): |
|
|
|
"""list/switch dict""" |
|
|
|
if args.list: |
|
|
|
print( |
|
|
|
"\n".join( |
|
|
|
( |
|
|
|
"{} {}".format("*" if key == self.dict else " ", key) |
|
|
|
for key in DICTS.keys() |
|
|
|
) |
|
|
|
) |
|
|
|
) |
|
|
|
else: |
|
|
|
DICTS[args.switch] |
|
|
|
self.dict = args.switch |
|
|
|
|
|
|
|
@cmd2.with_argparser(letter_set_manage) |
|
|
|
def do_change_letters(self, args): |
|
|
|
"""Change the letters on the board""" |
|
|
|
self.init_letters(args.letter) |
|
|
|
|
|
|
|
@cmd2.with_argparser(guessing) |
|
|
|
def do_find(self, args): |
|
|
|
"""Find words that match a pattern""" |
|
|
|
pattern = re.compile(args.pattern + "$") |
|
|
|
matching_words = filter_possibilities(self.candidates, pattern) |
|
|
|
app = RemoveWordsActivity(matching_words, self.excludes) |
|
|
|
if os.name == "nt": |
|
|
|
app.run(fork=False) |
|
|
|
else: |
|
|
|
app.run() |
|
|
|
was_canceled, new_exludes = app.get_results() |
|
|
|
if not was_canceled: |
|
|
|
self.excludes.update(new_exludes) |
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
while True: |
|
|
|
letters = input('Enter letters: ') |
|
|
|
if letters == ":quit:": |
|
|
|
break |
|
|
|
if SPELL is None: |
|
|
|
future.result() |
|
|
|
pos = canidates(letters) |
|
|
|
inp = None |
|
|
|
guessed = set() |
|
|
|
while inp not in (":quit:", ":new:"): |
|
|
|
if inp == ":enter:": |
|
|
|
inp = None |
|
|
|
while inp != ":done:": |
|
|
|
if inp is not None: |
|
|
|
guessed.add(inp) |
|
|
|
inp = input("Enter guessed word, :done: to exit: ") |
|
|
|
elif inp is not None: |
|
|
|
fpos = filter_pos(pos, inp) |
|
|
|
for word in fpos-guessed: |
|
|
|
print('>>>', word) |
|
|
|
print('Letters: ', ','.join(letters)) |
|
|
|
prompt = """\ |
|
|
|
Enter pattern, |
|
|
|
':new:' for new letters, |
|
|
|
':enter:' to fill in guessed words, or |
|
|
|
':quit:' to exit: """ |
|
|
|
inp = input(prompt) |
|
|
|
if inp == ":quit:": |
|
|
|
break |
|
|
|
MainLoop().cmdloop() |