def test_correct_path(database_dir): for pid in PuzzleManager.getPuzzleIds(): p_cls = PuzzleManager.getPuzzleClass(pid) for variant in p_cls.test_variants: s_cls = PuzzleManager.getSolverClass(pid, test=True) solver = s_cls(p_cls.generateStartPosition(variant), dir_path=database_dir) puzzle = p_cls.generateStartPosition(variant) solver.solve() if puzzle.numPositions: assert puzzle.numPositions >= len( solver._remoteness ), "{} defined numPositions to be {} but solver calculated {}".format( puzzle.name, puzzle.numPositions, len(solver)) while puzzle.primitive() != PuzzleValue.SOLVABLE: assert (solver.getValue(puzzle) == PuzzleValue.SOLVABLE ), "{} not SOLVABLE".format( puzzle.toString(mode="minimal")) positions = generateMovePositions(puzzle) prev_remote = solver.getRemoteness(puzzle) b = False for pos in positions: next_remote = solver.getRemoteness(pos[1]) if (next_remote != PuzzleValue.UNSOLVABLE and next_remote < prev_remote): puzzle = pos[1] b = True if not b: raise AssertionError( "Puzzle {} has {} has no moves to reach solution". format(puzzle.__class__.name, puzzle.toString(mode="minimal")))
def testValidation(): tests = [("", "6_2"), ("0_1-2-3-4-5", "6_2"), ("2_3-1-4-5-20", "6_2"), ("4_5-6-1-2-2", "6_2"), ("123456----", "6_2")] for test in tests: pytest.raises(PuzzleException, PuzzleManager.validate, TopSpin.puzzleid, test[0], test[1]) PuzzleManager.validate(TopSpin.puzzleid, "6_2", "2_1-5-3-6-4")
def testValidation(): tests = [("", "Triangle"), ("111_0_11_22_22_11011", "Triangle"), ("1_11_111_1111_11111_", "Triangle"), ("1_11_000_0111_11111_", "Not Triangle")] for test in tests: pytest.raises(PuzzleException, PuzzleManager.validate, Peg.id, test[1], test[0]) PuzzleManager.validate(Peg.id, "Triangle", "1_11_000_0111_11111_")
def testValidation(): tests = [("", "2"), ("123---", "2"), ("1-2-3-3", "2"), ("1-2-3-0", "3")] for test in tests: pytest.raises(PuzzleException, PuzzleManager.validate, Npuzzle.puzzleid, test[1], test[0]) PuzzleManager.validate(Npuzzle.puzzleid, "2", "1-2-3-0")
def testValidation(): tests = [("", "10"), ("xxxyx_ooo--oo", "10"), ("xxxoo-ooooo", "10"), ("xxxoo-ooooo", "10")] for test in tests: pytest.raises(PuzzleException, PuzzleManager.validate, Chairs.puzzleid, test[1], test[0]) PuzzleManager.validate(Chairs.puzzleid, "10", "oooxx-ooxxx")
def puzzles(): response = [ { "gameId": puzzle_id, "name" : PuzzleManager.getPuzzleClass(puzzle_id).name, "status": check_available(puzzle_id) } for puzzle_id in PuzzleManager.getPuzzleIds() ] return format_response(response)
def testValidation(): """Tests four different serializations and checks if it matches the expected response.""" # Four invalid serializations tests = [("", "3_3"), ("15-0-0", "4_3"), ("7-0-0", "3_4"), ("7-0-0-", "3_3")] for test in tests: pytest.raises(PuzzleException, PuzzleManager.validate, Hanoi.id, test[1], test[0]) PuzzleManager.validate(Hanoi.id, "3_3", "7-0-0")
def init_data(): for p_cls in PuzzleManager.getPuzzleClasses(): if data["TESTING"]: variants = p_cls.test_variants else: variants = p_cls.variants for variant in variants: s_cls = PuzzleManager.getSolverClass(p_cls.id, variant) puzzle = p_cls.generateStartPosition(variant) solver = s_cls(puzzle, dir_path=data['DATABASE_DIR']) solver.solve(verbose=True)
def testValidation(): """Tests four different serializations and checks if it matches the expected response.""" # Four invalid serializations tests = [("", "2x5"), ("2-5-a1_c1-a5_c5", "2x5"), ("2_5_a5_a1-c1", "2x5"), ("2_5_a5-c5_a1-c1", "3x7")] # Four exceptions raised for test in tests: pytest.raises(PuzzleException, PuzzleManager.validate, Bishop.puzzleid, test[1], test[0]) PuzzleManager.validate(Bishop.puzzleid, "2x5", "2_5_a5-c5_a1-c1")
def validate(puzzleid=None, variantid=None, position=None): if puzzleid == None: raise ValueError("Nothing to validate") if not PuzzleManager.hasPuzzleId(puzzleid): abort(404, description="PuzzleId not found") if variantid != None: variants = PuzzleManager.getPuzzleClass(puzzleid).variants if variantid not in variants: abort(404, description="VariantId not found") if position != None: try: PuzzleManager.validate(puzzleid, variantid, position) except PuzzleException as e: abort(404, description=str(e))
def testValidation(): """Tests four different serializations and checks if it matches the expected response.""" # Four invalid serializations tests = [("", "3"), ("R_A_3_3_-*-*-*-*-", "2"), ("R_A_2_2_-*-*-*-*-", "3"), ("R_A_2_2_-*-*", "3")] for test in tests: try: PuzzleManager.validate(p_cls.id, test[1], test[0]) except PuzzleException: pass else: print("Validation: {}".format(test)) raise Exception
def server_start(): # Check which Puzzles have been solved or not solved for p_cls in PuzzleManager.getPuzzleClasses(): if p_cls.id not in puzzle_solved_variants: puzzle_solved_variants[p_cls.id] = {} variants = p_cls.variants for variant in variants: p_cls = PuzzleManager.getPuzzleClass(p_cls.id) s_cls = PuzzleManager.getSolverClass(p_cls.id, variant) puzzle = p_cls.generateStartPosition(variant) solver = s_cls(puzzle, dir_path=app.config['DATABASE_DIR']) if os.path.exists(solver.path): puzzle_solved_variants[p_cls.id][variant] = solver
def database_dir(tmpdir): global db_dir if not db_dir is None: return db_dir for p_cls in PuzzleManager.getPuzzleClasses(): variants = p_cls.test_variants if not variants: warnings.warn( UserWarning( "{} does not have any test variants. It's correctness may vary." .format(p_cls.name))) for variant in variants: s_cls = PuzzleManager.getSolverClass(p_cls.id, variant) puzzle = p_cls.generateStartPosition(variant) solver = s_cls(puzzle, dir_path=tmpdir) solver.solve() db_dir = tmpdir return db_dir
def test_attributes(): output = True for p_cls in PuzzleManager.getPuzzleClasses(): attrs = ["id", "auth", "name", "desc", "date"] for a in attrs: if not hasattr(p_cls, a) or getattr(p_cls, a) is None: print("%s doesn't have attr %s" % (p_cls.__name__, a)) output = False if not output: raise Exception
def puzzle_variant(puzzle_id, variant_id): validate(puzzle_id, variant_id) puzzle = PuzzleManager.getPuzzleClass(puzzle_id).generateStartPosition(variant_id) response = { "description": variant_id, "startPosition": puzzle.toString(mode="minimal"), "status": check_available(puzzle_id, variant_id), "variantId": variant_id } return format_response(response)
def puzzle(puzzle_id): validate(puzzle_id) puzzlecls = PuzzleManager.getPuzzleClass(puzzle_id) response = { "puzzle_id": puzzle_id, "puzzle_name": puzzlecls.name, "author": puzzlecls.author, "description": puzzlecls.description, "date_created": puzzlecls.date_created, "variants": list(puzzlecls.variants) } return format_response(response)
def puzzle_position(puzzle_id, variant_id, position): validate(puzzle_id, variant_id, position) puzzle = PuzzleManager.getPuzzleClass(puzzle_id).fromString(position) solver_cls = PuzzleManager.getSolverClass(puzzle_id, variant_id, app.config['TESTING']) s = solver_cls(puzzle, dir_path=app.config['DATABASE_DIR']) moves = generateMovePositions(puzzle) response = { "position": puzzle.toString(), "remoteness": s.getRemoteness(puzzle), "value": s.getValue(puzzle), "moves": { str(move[0]): { "position": move[1].toString(), "remoteness": s.getRemoteness(move[1]), "value": s.getValue(move[1]) } for move in moves } } return format_response(response)
def check_available(puzzle_id, variant=None): if puzzle_id not in puzzle_solved_variants: puzzle_solved_variants[puzzle_id] = {} if variant is None: return "unknown" elif len(puzzle_solved_variants[puzzle_id]) == 0: return "unavailable" elif variant is None or variant in puzzle_solved_variants[puzzle_id]: return "available" p_cls = PuzzleManager.getPuzzleClass(puzzle_id) s_cls = PuzzleManager.getSolverClass(p_cls.id, variant) puzzle = p_cls.generateStartPosition(variant) solver = s_cls(puzzle, dir_path=app.config['DATABASE_DIR']) import os if os.path.exists(solver.path): puzzle_solved_variants[puzzle_id][variant] = solver return "available" return "not available"
def test_solution_are_solved(): string = "{} puzzle with variant {} has a solution {} that is not SOLVABLE." for p_cls in PuzzleManager.getPuzzleClasses(): for variantid in p_cls.variants: puzzle = p_cls.generateStartPosition(variantid) solutions = puzzle.generateSolutions() if solutions is not None: for sol in solutions: assert sol.primitive( ) == PuzzleValue.SOLVABLE, string.format( p_cls.name, variantid, sol.toString(mode="minimal")) # Add an additional test for undo moves
def puzzle(puzzle_id): validate(puzzle_id) puzzlecls = PuzzleManager.getPuzzleClass(puzzle_id) response = { "gameId": puzzle_id, "name": puzzlecls.name, "author": puzzlecls.auth, "description": puzzlecls.desc, "date_created": puzzlecls.date, "variants": [{ "description": variant_id, "startPosition": puzzlecls.generateStartPosition(variant_id).toString(), "status": check_available(puzzle_id, variant_id), "variantId": variant_id } for variant_id in puzzlecls.variants] } return format_response(response)
def puzzle_position(puzzle_id, variant_id, position): validate(puzzle_id, variant_id, position) puzzle = PuzzleManager.getPuzzleClass(puzzle_id).fromString(position) s = puzzle_solved_variants[puzzle_id][variant_id] moves = generateMovePositions(puzzle) this_remoteness = s.getRemoteness(puzzle) response = { "position": puzzle.toString(mode="minimal"), "remoteness": this_remoteness if this_remoteness != PuzzleValue.MAX_REMOTENESS else -1, "positionValue": s.getValue(puzzle), } move_attr = [] for move in moves: next_remoteness = s.getRemoteness(move[1]) move_attr.append( { "position": move[1].toString(mode="minimal"), "positionValue": s.getValue(move[1]), "move": str(move[0]), "moveValue": PuzzleValue.SOLVABLE if this_remoteness > next_remoteness else PuzzleValue.UNDECIDED if this_remoteness == next_remoteness else PuzzleValue.UNSOLVABLE, "deltaRemoteness": this_remoteness - next_remoteness, "remoteness": next_remoteness if next_remoteness != PuzzleValue.MAX_REMOTENESS else -1, } ) response["moves"] = move_attr return format_response(response)
def puzzle_variant(puzzle_id, variant_id): validate(puzzle_id, variant_id) puzzle = PuzzleManager.getPuzzleClass(puzzle_id).generateStartPosition( variant_id) response = {"starting_pos": puzzle.toString()} return format_response(response)
def test_default_path(client): rv = client.get('/') d = json.loads(rv.data) for puzzle in d['response']: assert PuzzleManager.hasPuzzleId(puzzle["gameId"])
parser.add_argument("-i", "--info", action="store_true", help="Solver reveals some helpful info") parser.add_argument("-a", "--auto", action="store_true", help="Puzzle plays itself") parser.add_argument("-l", "--list", action="store_true", help="Lists puzzles and their ids") args = parser.parse_args() if not PuzzleManager.hasPuzzleId(args.puzzleid): print("Possible puzzles:") print("\n".join(PuzzleManager.getPuzzleIds())) raise Exception("Puzzleid is not recorded in PuzzleList") p_cls = PuzzleManager.getPuzzleClass(args.puzzleid) puzzle = None if args.variant: puzzle = p_cls.generateStartPosition(args.variant) if args.position: puzzle = p_cls.deserialize(args.position) if not puzzle: puzzle = p_cls() if args.info or args.auto:
def puzzles(): response = {"puzzles": list(PuzzleManager.getPuzzleIds())} return format_response(response)
def test_serialize(): for p_cls in PuzzleManager.getPuzzleClasses(): for variantid in p_cls.variants: puzzle = p_cls.generateStartPosition(variantid) p_str = puzzle.toString(mode="minimal") puzzle = p_cls.fromString(p_str)