# Path: pycryptics/solve_clue.py
# class CrypticClueSolver(object):
#     def __init__(self):
#         self.answers_with_clues = None
#         self.clue_text = None
#         self.quiet = False
# 
#     def __enter__(self):
#         # self.start_go_server()
#         return self
# 
#     def __exit__(self, type, value, traceback):
#         self.stop()
#         # self.stop_go_server()
# 
#     def stop(self):
#         pass
# 
#     def setup(self, clue_text):
#         self.clue_text = clue_text
# 
#     def run(self):
#         self.clue_text = self.clue_text.encode('ascii', 'ignore')
#         constraints = parse_clue_text(self.clue_text)
#         return self.solve_all_phrasings(constraints)
#         # all_phrasings, lengths, pattern, answer = parse_clue_text(self.clue_text)
# 
#     def solve_all_phrasings(self, constraints):
#         all_phrasings = phrasings(constraints.phrases)
# 
#         self.answers_with_clues = []
# 
#         for p in all_phrasings:
#             constraints = constraints._replace(phrases=p)
#             # constraints = Constraints(p, lengths, pattern, answer)
#             if not self.quiet:
#                 print p
#             for ann_ans in self.solve_constraints(constraints):
#                 self.answers_with_clues.append(ann_ans)
#         if len(self.answers_with_clues) == 0 and constraints.pattern.replace('.', '') != "":
#             self.answers_with_clues = [PatternAnswer(x, all_phrasings[0]) for x in SYNONYMS if matches_pattern(x, constraints.pattern, constraints.lengths)]
#         self.answers_with_clues.sort(reverse=True)
#         return self.answers_with_clues
# 
#     def solve_constraints(self, constraints):
#         answers_with_clues = []
#         possible_clues = generate_clues(constraints)
# 
#         for i, clue in enumerate(possible_clues):
#             # print "solving:", clue
#             try:
#                 answers = clue.answers
#             except ClueUnsolvableError:
#                 answers = []
#             for answer in answers:
#                 answers_with_clues.append(AnnotatedAnswer(answer, clue))
#         return sorted(answers_with_clues, reverse=True)
# 
#     def collect_answers(self):
#         if self.answers_with_clues is not None:
#             return ClueSolutions(self.answers_with_clues)
# 
# def split_clue_text(clue_text):
#     clue_text = clue_text.encode('ascii', 'ignore')
#     if '|' not in clue_text:
#         clue_text += ' |'
#     clue_text = clue_text.lower()
#     clue, paren, rest = clue_text.rpartition('(')
#     lengths, rest = rest.split(')')
#     lengths = lengths.replace('-', ',')
#     lengths = tuple(int(x) for x in lengths.split(','))
#     pattern, answer = rest.split('|')
#     pattern = pattern.strip()
#     clue = re.sub('-', '_', clue)
#     clue = re.sub(r'[^a-zA-Z\ _0-9]', '', clue)
#     clue = re.sub(r'\ +', ' ', clue)
#     phrases = clue.split(' ')
#     phrases = [p for p in phrases if p.strip() != '' and p.strip() != '_']
#     return phrases, lengths, pattern, answer


import web
import re
from pycryptics.solve_clue import CrypticClueSolver, split_clue_text

SERVER = "http://cryptic-solver.appspot.com/solve/"

class index:
    def GET(self):
        return render.index(SERVER)


class solve:
    def GET(self, clue):
        clue = clue.strip()
        if clue != "":
            if not re.match(r"[^\(\)]*\([0-9]+ *[,[0-9 ]*]*\)[ \.a-zA-Z]*", clue):
                return render.solver(None, clue, "I don't quite understand the formatting of that clue. Please make sure that the clue is of the form: <br>clue text (length)<br>or<br>clue text (length) pattern<br> as in the examples above.")
            try:
                phrases, lengths, pattern, answer = split_clue_text(clue)
                if sum(lengths) != len(pattern) and pattern != '':
                    print "length mismatch"
                    return render.solver(None, clue, "The length of the pattern must exactly match the number of letters in the answer, or you can just leave it blank. Here are some allowable patterns:<br>(5) ....s<br>(3,2) a.e..<br>(9)<br>")
                assert len(pattern) == 0 or len(pattern) == sum(lengths), "Answer lengths and length of pattern string must match: sum(%s) != %d" % (lengths, len(pattern))
            except Exception as e:
                raise e
                print e

# Path: pycryptics/solve_clue.py
# class CrypticClueSolver(object):
#     def __init__(self):
#         self.answers_with_clues = None
#         self.clue_text = None
#         self.quiet = False
# 
#     def __enter__(self):
#         # self.start_go_server()
#         return self
# 
#     def __exit__(self, type, value, traceback):
#         self.stop()
#         # self.stop_go_server()
# 
#     def stop(self):
#         pass
# 
#     def setup(self, clue_text):
#         self.clue_text = clue_text
# 
#     def run(self):
#         self.clue_text = self.clue_text.encode('ascii', 'ignore')
#         constraints = parse_clue_text(self.clue_text)
#         return self.solve_all_phrasings(constraints)
#         # all_phrasings, lengths, pattern, answer = parse_clue_text(self.clue_text)
# 
#     def solve_all_phrasings(self, constraints):
#         all_phrasings = phrasings(constraints.phrases)
# 
#         self.answers_with_clues = []
# 
#         for p in all_phrasings:
#             constraints = constraints._replace(phrases=p)
#             # constraints = Constraints(p, lengths, pattern, answer)
#             if not self.quiet:
#                 print p
#             for ann_ans in self.solve_constraints(constraints):
#                 self.answers_with_clues.append(ann_ans)
#         if len(self.answers_with_clues) == 0 and constraints.pattern.replace('.', '') != "":
#             self.answers_with_clues = [PatternAnswer(x, all_phrasings[0]) for x in SYNONYMS if matches_pattern(x, constraints.pattern, constraints.lengths)]
#         self.answers_with_clues.sort(reverse=True)
#         return self.answers_with_clues
# 
#     def solve_constraints(self, constraints):
#         answers_with_clues = []
#         possible_clues = generate_clues(constraints)
# 
#         for i, clue in enumerate(possible_clues):
#             # print "solving:", clue
#             try:
#                 answers = clue.answers
#             except ClueUnsolvableError:
#                 answers = []
#             for answer in answers:
#                 answers_with_clues.append(AnnotatedAnswer(answer, clue))
#         return sorted(answers_with_clues, reverse=True)
# 
#     def collect_answers(self):
#         if self.answers_with_clues is not None:
#             return ClueSolutions(self.answers_with_clues)
# 
# def split_clue_text(clue_text):
#     clue_text = clue_text.encode('ascii', 'ignore')
#     if '|' not in clue_text:
#         clue_text += ' |'
#     clue_text = clue_text.lower()
#     clue, paren, rest = clue_text.rpartition('(')
#     lengths, rest = rest.split(')')
#     lengths = lengths.replace('-', ',')
#     lengths = tuple(int(x) for x in lengths.split(','))
#     pattern, answer = rest.split('|')
#     pattern = pattern.strip()
#     clue = re.sub('-', '_', clue)
#     clue = re.sub(r'[^a-zA-Z\ _0-9]', '', clue)
#     clue = re.sub(r'\ +', ' ', clue)
#     phrases = clue.split(' ')
#     phrases = [p for p in phrases if p.strip() != '' and p.strip() != '_']
#     return phrases, lengths, pattern, answer


# Path: app/gae_app.py
import web
import re
from pycryptics.solve_clue import CrypticClueSolver, split_clue_text


SERVER = "http://cryptic-solver.appspot.com/solve/"

class index:
    def GET(self):
        return render.index(SERVER)


class solve:
    def GET(self, clue):
        clue = clue.strip()
        if clue != "":
            if not re.match(r"[^\(\)]*\([0-9]+ *[,[0-9 ]*]*\)[ \.a-zA-Z]*", clue):
                return render.solver(None, clue, "I don't quite understand the formatting of that clue. Please make sure that the clue is of the form: <br>clue text (length)<br>or<br>clue text (length) pattern<br> as in the examples above.")
            try:
                phrases, lengths, pattern, answer = split_clue_text(clue)
                if sum(lengths) != len(pattern) and pattern != '':
                    print "length mismatch"
                    return render.solver(None, clue, "The length of the pattern must exactly match the number of letters in the answer, or you can just leave it blank. Here are some allowable patterns:<br>(5) ....s<br>(3,2) a.e..<br>(9)<br>")
                assert len(pattern) == 0 or len(pattern) == sum(lengths), "Answer lengths and length of pattern string must match: sum(%s) != %d" % (lengths, len(pattern))
            except Exception as e:
                raise e
                print e

                return render.solver(None, clue, "Something went wrong that I don't know how to handle. Here's python's attempt at an explanation:<br>" + str(e))