Example #1
0
def start_puzzle_from(filename, index=None):
    if filename.lower().endswith(".pgn"):
        if filename.startswith("lichess_study"):
            chessfile = PGNFile(protoopen(addDataPrefix("learn/puzzles/%s" % filename), encoding="utf-8"))
        else:
            chessfile = PGNFile(protoopen(addDataPrefix("learn/puzzles/%s" % filename)))
        chessfile.limit = 1000
        chessfile.init_tag_database()
    elif filename.lower().endswith(".olv"):
        chessfile = OLVFile(protoopen(addDataPrefix("learn/puzzles/%s" % filename), encoding="utf-8"))

    records, plys = chessfile.get_records()

    progress = puzzles_solving_progress.get(filename, [0] * chessfile.count)

    if index is None:
        index = progress.index(0)

    rec = records[index]

    timemodel = TimeModel(0, 0)
    gamemodel = LearnModel(timemodel)

    chessfile.loadToModel(rec, 0, gamemodel)

    start_puzzle_game(gamemodel, filename, records, index, rec)
Example #2
0
    def setUp(self):
        self.f1 = protoopen('gamefiles/3fold.pgn')
        self.PgnFile1 = pgn.load(self.f1)

        self.f2 = protoopen('gamefiles/bilbao.pgn')
        self.PgnFile2 = pgn.load(self.f2)

        self.f3 = protoopen('gamefiles/material.pgn')
        self.PgnFile3 = pgn.load(self.f3)
Example #3
0
 def get_count(self, filename):
     subdir = "puzzles" if self.progress_file.endswith("puzzles.json") else "lessons"
     if filename.lower().endswith(".pgn"):
         chessfile = PGNFile(protoopen(addDataPrefix("learn/%s/%s" % (subdir, filename))))
         chessfile.limit = 1000
         chessfile.init_tag_database()
     elif filename.lower().endswith(".olv"):
         chessfile = OLVFile(protoopen(addDataPrefix("learn/%s/%s" % (subdir, filename)), encoding="utf-8"))
     chessfile.close()
     count = chessfile.count
     return count
Example #4
0
    def setUp(self):
        self.f1 = protoopen('gamefiles/3fold.pgn')
        self.PgnFile1 = pgn.load(self.f1)
        self.PgnFile1.get_records()

        self.f2 = protoopen('gamefiles/bilbao.pgn')
        self.PgnFile2 = pgn.load(self.f2)
        self.PgnFile2.get_records()

        self.f3 = protoopen('gamefiles/material.pgn')
        self.PgnFile3 = pgn.load(self.f3)
        self.PgnFile3.get_records()
Example #5
0
    def setUpClass(cls):
        cls.f1 = protoopen('gamefiles/3fold.pgn')
        cls.PgnFile1 = pgn.load(cls.f1)
        cls.PgnFile1.get_records()

        cls.f2 = protoopen('gamefiles/bilbao.pgn')
        cls.PgnFile2 = pgn.load(cls.f2)
        cls.PgnFile2.get_records()

        cls.f3 = protoopen('gamefiles/material.pgn')
        cls.PgnFile3 = pgn.load(cls.f3)
        cls.PgnFile3.get_records()
Example #6
0
def start_lesson_from(filename, index=None):
    if filename.startswith("lichess_study"):
        chessfile = PGNFile(
            protoopen(addDataPrefix("learn/lessons/%s" % filename),
                      encoding="utf-8"))
    else:
        chessfile = PGNFile(
            protoopen(addDataPrefix("learn/lessons/%s" % filename)))
    chessfile.limit = 1000
    chessfile.init_tag_database()
    records, plys = chessfile.get_records()

    progress = lessons_solving_progress.get(filename, [0] * chessfile.count)

    if index is None:
        index = progress.index(0)

    rec = records[index]

    timemodel = TimeModel(0, 0)
    gamemodel = LearnModel(timemodel)
    gamemodel.set_learn_data(LESSON, filename, index, len(records))

    chessfile.loadToModel(rec, -1, gamemodel)

    color = gamemodel.boards[0].color
    player_name = conf.get("firstName", _("You"))

    w_name = player_name if color == WHITE else "PyChess"
    b_name = "PyChess" if color == WHITE else player_name

    p0 = (LOCAL, Human, (WHITE, w_name), w_name)
    p1 = (LOCAL, Human, (BLACK, b_name), b_name)

    def learn_success(gamemodel):
        chessfile.loadToModel(rec, -1, gamemodel)
        progress = lessons_solving_progress[gamemodel.source]
        progress[gamemodel.current_index] = 1
        lessons_solving_progress[gamemodel.source] = progress
        asyncio. async (gamemodel.restart_analyzer(HINT))

    gamemodel.connect("learn_success", learn_success)

    def on_game_started(gamemodel):
        perspective.activate_panel("annotationPanel")
        asyncio. async (gamemodel.start_analyzer(
            HINT, force_engine=discoverer.getEngineLearn()))

    gamemodel.connect("game_started", on_game_started)

    gamemodel.status = WAITING_TO_START
    perspective = perspective_manager.get_perspective("games")
    asyncio. async (perspective.generalStart(gamemodel, p0, p1))
Example #7
0
        def opening():
            if filename.endswith(".pgn"):
                chessfile = pgn.load(protoopen(filename), self.progressbar1)
            elif filename.endswith(".epd"):
                chessfile = epd.load(protoopen(filename))
            elif filename.endswith(".fen"):
                chessfile = fen.load(protoopen(filename))
            else:
                chessfile = None

            GLib.idle_add(self.spinner.stop)
            GLib.idle_add(self.progress_dialog.hide)
            if chessfile is not None:
                GLib.idle_add(self.emit, "chessfile_opened", chessfile)
Example #8
0
        def opening():
            if filename.endswith(".pgn"):
                chessfile = pgn.load(protoopen(filename), self.progressbar1)
            elif filename.endswith(".epd"):
                chessfile = epd.load(protoopen(filename))
            elif filename.endswith(".fen"):
                chessfile = fen.load(protoopen(filename))
            else:
                chessfile = None

            GLib.idle_add(self.spinner.stop)
            GLib.idle_add(self.progress_dialog.hide)
            if chessfile is not None:
                self.chessfile = chessfile
                self.chessfiles.append(chessfile)
                GLib.idle_add(self.emit, "chessfile_opened0", chessfile)
Example #9
0
    def pgn_test(self, name):
        pgnfile = load(protoopen("gamefiles/%s.pgn" % name))
        pgnfile.limit = 1000
        pgnfile.init_tag_database()
        games, plys = pgnfile.get_records()

        for i, game in enumerate(games):
            print("%s/%s" % (i + 1, pgnfile.get_count()))
            orig_moves_text = normalize(pgnfile.get_movetext(game))

            model = pgnfile.loadToModel(game)
            print(model.tags["Site"])
            new_moves = []
            walk(model.boards[0].board, new_moves, model)
            new_moves_text = normalize(" ".join(new_moves))

            for orig, new in zip(orig_moves_text.split(), new_moves_text.split()):
                # Seems most .PGN unnecessary contains unambiguous notation
                # when second move candidate is invalid (leaves king in check)
                # f.e.: 1.e4 e5 2.d4 Nf6 3.Nc3 Bb4 Nge2
                if len(orig) == len(new) + 1 and orig[0] == new[0] and orig[2:] == new[1:]:
                    continue

                elif orig[-1] in "?!" and new[-1] not in "?!":
                    # pgn export format uses nag
                    break

                elif (orig == "0-0" and new == "O-O") or (orig == "0-0-0" and new == "O-O-O"):
                    continue

                self.assertEqual(orig, new)

        pgnfile.close()
Example #10
0
    def row_activated(self, widget, path, col):
        if path is None:
            return
        filename = addDataPrefix("lectures/%s" % LESSONS[path[0]][0])

        chessfile = PGNFile(protoopen(filename))
        self.importer = PgnImport(chessfile)
        chessfile.init_tag_database(self.importer)
        records, plys = chessfile.get_records()

        rec = records[random.randrange(0, len(records))]
        print(rec)

        timemodel = TimeModel(0, 0)
        gamemodel = GameModel(timemodel)
        gamemodel.set_lesson_game()

        chessfile.loadToModel(rec, -1, gamemodel)

        name = conf.get("firstName", _("You"))
        p0 = (LOCAL, Human, (WHITE, name), name)
        name = "pychessbot"
        p1 = (LOCAL, Human, (BLACK, name), name)

        gamemodel.status = WAITING_TO_START
        perspective = perspective_manager.get_perspective("games")
        asyncio. async (perspective.generalStart(gamemodel, p0, p1))
 def on_file_activated (self, *args):
     filename = self._retrieve_filename()
     if filename:
         if filename == self.get_filename():
             return
         self.set_filename(filename)
     elif self.get_filename():
         filename = self.get_filename()
     else:
         return
     if os.path.isdir(filename):
         return
     
     ending = filename[filename.rfind(".")+1:]
     loader = self.enddir[ending]
     self.chessfile = chessfile = loader.load(protoopen(filename))
     
     self.list.get_model().clear()
     for gameno in range(len(chessfile)):
         names = chessfile.get_player_names (gameno)
         names = [ellipsize (name, 9) for name in names]
         result = reprResult[chessfile.get_result (gameno)]
         result = result.replace("1/2","½")
         self.list.get_model().append (names+[result])
     
     self.lastSel = -1 # The row that was last selected
     self.list.set_cursor((0,))
Example #12
0
    def onFileActivated(self, filename):
        # filename is None if a non-existent file is passed as command line argument
        if filename is None:
            return
        self.set_filename(filename)
        if os.path.isdir(filename):
            return

        ending = filename[filename.rfind(".") + 1:]
        loader = self.enddir[ending]
        self.chessfile = chessfile = loader.load(protoopen(filename))

        self.list.get_model().clear()
        for gameno in range(len(chessfile)):
            names = chessfile.get_player_names(gameno)
            names = [ellipsize(name, 9) for name in names]
            result = reprResult[chessfile.get_result(gameno)]
            result = result.replace("1/2", "½")
            self.list.get_model().append(["%s." % (gameno + 1)] + names +
                                         [result])

        self.last_sel = -1  # The row that was last selected
        self.list.set_cursor((0, ))

        self.widgets["whitePlayerCombobox"].set_active(0)
        self.widgets["blackPlayerCombobox"].set_active(0)
Example #13
0
def start_lesson_from(filename, index=None):
    chessfile = PGNFile(protoopen(addDataPrefix("learn/lessons/%s" %
                                                filename)))
    chessfile.limit = 1000
    chessfile.init_tag_database()
    records, plys = chessfile.get_records()

    progress = lessons_solving_progress.get(filename, [0] * chessfile.count)

    if index is None:
        index = progress.index(0)

    rec = records[index]

    timemodel = TimeModel(0, 0)
    gamemodel = LearnModel(timemodel)

    chessfile.loadToModel(rec, -1, gamemodel)

    if len(gamemodel.moves) > 0:
        start_lesson_game(gamemodel, filename, chessfile, records, index, rec)
    else:
        start_puzzle_game(gamemodel,
                          filename,
                          records,
                          index,
                          rec,
                          from_lesson=True)
Example #14
0
    def on_file_activated(self, *args):
        filename = self._retrieve_filename()
        if filename:
            if filename == self.get_filename():
                return
            self.set_filename(filename)
        elif self.get_filename():
            filename = self.get_filename()
        else:
            return
        if os.path.isdir(filename):
            return

        ending = filename[filename.rfind(".") + 1:]
        loader = self.enddir[ending]
        self.chessfile = chessfile = loader.load(protoopen(filename))

        self.list.get_model().clear()
        for gameno in range(len(chessfile)):
            names = chessfile.get_player_names(gameno)
            names = [ellipsize(name, 9) for name in names]
            result = reprResult[chessfile.get_result(gameno)]
            result = result.replace("1/2", "½")
            self.list.get_model().append(names + [result])

        self.lastSel = -1  # The row that was last selected
        self.list.set_cursor((0, ))
Example #15
0
    def onFileActivated(self, filename):
        # filename is None if a non-existent file is passed as command line argument
        if filename is None:
            return
        self.set_filename(filename)
        if os.path.isdir(filename):
            return

        ending = filename[filename.rfind(".") + 1:]
        loader = self.enddir[ending]
        self.chessfile = chessfile = loader.load(protoopen(filename))

        self.list.get_model().clear()
        for gameno in range(len(chessfile)):
            names = chessfile.get_player_names(gameno)
            names = [ellipsize(name, 9) for name in names]
            result = reprResult[chessfile.get_result(gameno)]
            result = result.replace("1/2", "½")
            self.list.get_model().append(["%s." % (gameno + 1)] + names +
                                         [result])

        self.last_sel = -1  # The row that was last selected
        self.list.set_cursor((0, ))

        self.widgets["whitePlayerCombobox"].set_active(0)
        self.widgets["blackPlayerCombobox"].set_active(0)
Example #16
0
        def opening():
            # Redirection of the PGN file
            nonlocal filename
            for ext in [".sqlite", ".bin", ".scout"]:
                if filename.endswith(ext):
                    filename = filename[:len(filename) - len(ext)] + ".pgn"

            # Processing by file extension
            if filename.endswith(".pgn"):
                GLib.idle_add(self.progressbar.show)
                GLib.idle_add(self.progressbar.set_text,
                              _("Opening chessfile..."))
                chessfile = PGNFile(protoopen(filename), self.progressbar)
                self.importer = chessfile.init_tag_database()
                if self.importer is not None and self.importer.cancel:
                    chessfile.tag_database.close()
                    if os.path.isfile(chessfile.sqlite_path):
                        os.remove(chessfile.sqlite_path)
                    chessfile = None
                else:
                    chessfile.init_scoutfish()
                    chessfile.init_chess_db()
            elif filename.endswith(".epd"):
                self.importer = None
                chessfile = epd.load(protoopen(filename))
            elif filename.endswith(".olv"):
                self.importer = None
                chessfile = olv.load(protoopen(filename, encoding="utf-8"))
            elif filename.endswith(".fen"):
                self.importer = None
                chessfile = fen.load(protoopen(filename))
            else:
                self.importer = None
                chessfile = None

            GLib.idle_add(self.spinner.stop)
            GLib.idle_add(self.spinner.hide)
            GLib.idle_add(self.progress_dialog.hide)

            if chessfile is not None:
                self.chessfile = chessfile
                self.chessfiles.append(chessfile)
                GLib.idle_add(self.emit, "chessfile_opened0", chessfile)
            else:
                if self.chessfile is None:
                    self.close(None)
Example #17
0
    def open_chessfile(self, filename):
        if filename.endswith(".pdb"):
            chessfile = database.load(filename)
        elif filename.endswith(".pgn"):
            chessfile = pgn.load(protoopen(filename))
        elif filename.endswith(".epd"):
            chessfile = epd.load(protoopen(filename))
        elif filename.endswith(".fen"):
            chessfile = fen.load(protoopen(filename))
        else:
            return

        if self.gamelist is None:
            self.init_layout()

        perspective_manager.activate_perspective("database")
        self.emit("chessfile_opened", chessfile)
Example #18
0
    def loadAndStart(self, uri, loader, gameno, position, first_time=True):
        if first_time:
            assert self.status == WAITING_TO_START

        uriIsFile = not isinstance(uri, str)
        if not uriIsFile:
            chessfile = loader.load(protoopen(uri))
        else:
            chessfile = loader.load(uri)

        self.gameno = gameno
        self.emit("game_loading", uri)
        try:
            chessfile.loadToModel(gameno, -1, self)
        # Postpone error raising to make games loadable to the point of the
        # error
        except LoadingError as e:
            error = e
        else:
            error = None
        if self.players:
            self.players[WHITE].setName(self.tags["White"])
            self.players[BLACK].setName(self.tags["Black"])
        self.emit("game_loaded", uri)

        self.needsSave = False
        if not uriIsFile:
            self.uri = uri
        else:
            self.uri = None

        # Even if the game "starts ended", the players should still be moved
        # to the last position, so analysis is correct, and a possible "undo"
        # will work as expected.
        for spectator in self.spectators.values():
            spectator.setOptionInitialBoard(self)
        for player in self.players:
            player.setOptionInitialBoard(self)
        if self.timed:
            self.timemodel.setMovingColor(self.boards[-1].color)

        if first_time:
            if self.status == RUNNING:
                if self.timed:
                    self.timemodel.start()

            # Store end status from Result tag
            if self.status in (DRAW, WHITEWON, BLACKWON):
                self.endstatus = self.status
            self.status = WAITING_TO_START
            self.start()

        if error:
            raise error
Example #19
0
    def loadAndStart(self, uri, loader, gameno, position, first_time=True):
        if first_time:
            assert self.status == WAITING_TO_START

        uriIsFile = not isinstance(uri, str)
        if not uriIsFile:
            chessfile = loader.load(protoopen(uri))
        else:
            chessfile = loader.load(uri)

        self.gameno = gameno
        self.emit("game_loading", uri)
        try:
            chessfile.loadToModel(gameno, -1, self)
        # Postpone error raising to make games loadable to the point of the
        # error
        except LoadingError as e:
            error = e
        else:
            error = None
        if self.players:
            self.players[WHITE].setName(self.tags["White"])
            self.players[BLACK].setName(self.tags["Black"])
        self.emit("game_loaded", uri)

        self.needsSave = False
        if not uriIsFile:
            self.uri = uri
        else:
            self.uri = None

        # Even if the game "starts ended", the players should still be moved
        # to the last position, so analysis is correct, and a possible "undo"
        # will work as expected.
        for spectator in self.spectators.values():
            spectator.setOptionInitialBoard(self)
        for player in self.players:
            player.setOptionInitialBoard(self)
        if self.timed:
            self.timemodel.setMovingColor(self.boards[-1].color)

        if first_time:
            if self.status == RUNNING:
                if self.timed:
                    self.timemodel.start()

            # Store end status from Result tag
            if self.status in (DRAW, WHITEWON, BLACKWON):
                self.endstatus = self.status
            self.status = WAITING_TO_START
            self.start()

        if error:
            raise error
Example #20
0
        def opening():
            if filename.endswith(".pgn"):
                GLib.idle_add(self.progressbar.show)
                GLib.idle_add(self.progressbar.set_text,
                              _("Opening chessfile..."))
                chessfile = PGNFile(protoopen(filename), self.progressbar)
                self.importer = chessfile.init_tag_database()
                if self.importer is not None and self.importer.cancel:
                    chessfile.tag_database.close()
                    if os.path.isfile(chessfile.sqlite_path):
                        os.remove(chessfile.sqlite_path)
                    chessfile = None
                else:
                    chessfile.init_scoutfish()
                    chessfile.init_chess_db()
            elif filename.endswith(".epd"):
                self.importer = None
                chessfile = epd.load(protoopen(filename))
            elif filename.endswith(".olv"):
                self.importer = None
                chessfile = olv.load(protoopen(filename, encoding="utf-8"))
            elif filename.endswith(".fen"):
                self.importer = None
                chessfile = fen.load(protoopen(filename))
            else:
                self.importer = None
                chessfile = None

            GLib.idle_add(self.spinner.stop)
            GLib.idle_add(self.spinner.hide)
            GLib.idle_add(self.progress_dialog.hide)

            if chessfile is not None:
                self.chessfile = chessfile
                self.chessfiles.append(chessfile)
                GLib.idle_add(self.emit, "chessfile_opened0", chessfile)
            else:
                if self.chessfile is None:
                    self.close(None)
Example #21
0
        def opening():
            if filename.endswith(".pgn"):
                GLib.idle_add(self.progressbar.show)
                GLib.idle_add(self.progressbar.set_text, _("Opening chessfile..."))
                chessfile = PGNFile(protoopen(filename), self.progressbar)
                self.importer = chessfile.init_tag_database()
                if self.importer is not None and self.importer.cancel:
                    chessfile.tag_database.close()
                    if os.path.isfile(chessfile.sqlite_path):
                        os.remove(chessfile.sqlite_path)
                    chessfile = None
                else:
                    chessfile.init_scoutfish()
                    chessfile.init_chess_db()
            elif filename.endswith(".epd"):
                self.importer = None
                chessfile = epd.load(protoopen(filename))
            elif filename.endswith(".olv"):
                self.importer = None
                chessfile = olv.load(protoopen(filename, encoding="utf-8"))
            elif filename.endswith(".fen"):
                self.importer = None
                chessfile = fen.load(protoopen(filename))
            else:
                self.importer = None
                chessfile = None

            GLib.idle_add(self.spinner.stop)
            GLib.idle_add(self.spinner.hide)
            GLib.idle_add(self.progress_dialog.hide)

            if chessfile is not None:
                self.chessfile = chessfile
                self.chessfiles.append(chessfile)
                GLib.idle_add(self.emit, "chessfile_opened0", chessfile)
            else:
                if self.chessfile is None:
                    self.close(None)
Example #22
0
def start_puzzle_from(filename, index=None):
    if filename.lower().endswith(".pgn"):
        chessfile = PGNFile(protoopen(addDataPrefix("learn/puzzles/%s" % filename)))
        chessfile.limit = 1000
        chessfile.init_tag_database()
    elif filename.lower().endswith(".olv"):
        chessfile = OLVFile(protoopen(addDataPrefix("learn/puzzles/%s" % filename), encoding="utf-8"))

    records, plys = chessfile.get_records()

    progress = puzzles_solving_progress.get(filename, [0] * chessfile.count)

    if index is None:
        index = progress.index(0)

    rec = records[index]

    timemodel = TimeModel(0, 0)
    gamemodel = LearnModel(timemodel)

    chessfile.loadToModel(rec, 0, gamemodel)

    start_puzzle_game(gamemodel, filename, records, index, rec)
Example #23
0
    def loadAndStart(self, uri, loader, gameno, position):
        assert self.status == WAITING_TO_START

        uriIsFile = type(uri) != str
        if not uriIsFile:
            chessfile = loader.load(protoopen(uri))
        else:
            chessfile = loader.load(uri)

        self.emit("game_loading", uri)
        try:
            chessfile.loadToModel(gameno, position, self)
        #Postpone error raising to make games loadable to the point of the error
        except LoadingError, e:
            error = e
    def loadAndStart (self, uri, loader, gameno, position):
        assert self.status == WAITING_TO_START

        uriIsFile = type(uri) != str
        if not uriIsFile:
            chessfile = loader.load(protoopen(uri))
        else: 
            chessfile = loader.load(uri)
        
        self.emit("game_loading", uri)
        try:
            chessfile.loadToModel(gameno, position, self)
        #Postpone error raising to make games loadable to the point of the error
        except LoadingError, e:
            error = e
Example #25
0
    def feed(pgnfile, lang):
        cf = load(protoopen(pgnfile))
        rows = []
        old_eco = ""
        ply_max = 0
        for i, game in enumerate(cf.games):
            model = cf.loadToModel(i)

            eco = cf._getTag(i, "ECO")[:3]

            opening = cf._getTag(i, "Opening")
            if opening is None:
                opening = ""

            variation = cf._getTag(i, "Variation")
            if variation is None:
                variation = ""

            base = int(old_eco != eco)

            ply = len(model.moves)
            ply_max = max(ply_max, ply)
            if ply == 0:
                cu = conn.cursor()
                cu.execute(
                    "select * from openings where eco=? and lang='en' and base=1",
                    (eco, ))
                res = cu.fetchone()
                if res is not None:
                    hash = res[0]
            else:
                hash = memoryview(hash_struct.pack(
                    model.boards[-1].board.hash))

            if opening:
                rows.append((hash, base, unicode(eco), unicode(lang),
                             unicode(opening), unicode(variation)))

            old_eco = eco

        c.executemany(
            "insert into openings(hash, base, eco, lang, opening, variation) values (?, ?, ?, ?, ?, ?)",
            rows)
        conn.commit()

        print("Max ply was %s" % ply_max)
Example #26
0
    def feed(pgnfile, lang):
        cf = load(protoopen(pgnfile))
        cf.limit = 5000
        importer = PgnImport(cf)
        cf.init_tag_database(importer)
        records, plys = cf.get_records()

        rows = []
        old_eco = ""
        for rec in records:
            model = cf.loadToModel(rec)

            eco = rec["ECO"]

            opening = rec["White"]
            if opening is None:
                opening = ""

            variation = rec["Black"]
            if variation is None:
                variation = ""

            base = int(old_eco != eco)

            ply = len(model.moves)
            if ply == 0:
                cu = conn.cursor()
                cu.execute(
                    "select * from openings where eco=? and lang='en' and base=1",
                    (eco, ))
                res = cu.fetchone()
                if res is not None:
                    hash = res[0]
            else:
                hash = memoryview(hash_struct.pack(
                    model.boards[-1].board.hash))

            if opening:
                rows.append((hash, base, eco, lang, opening, variation))

            old_eco = eco

        c.executemany(
            "insert into openings(hash, base, eco, lang, opening, variation) values (?, ?, ?, ?, ?, ?)",
            rows)
        conn.commit()
Example #27
0
def start_lesson_from(filename, index=None):
    chessfile = PGNFile(protoopen(addDataPrefix("learn/lessons/%s" % filename)))
    chessfile.limit = 1000
    chessfile.init_tag_database()
    records, plys = chessfile.get_records()

    progress = lessons_solving_progress.get(filename, [0] * chessfile.count)

    if index is None:
        index = progress.index(0)

    rec = records[index]

    timemodel = TimeModel(0, 0)
    gamemodel = LearnModel(timemodel)
    gamemodel.set_learn_data(LESSON, filename, index, len(records))

    chessfile.loadToModel(rec, -1, gamemodel)

    color = gamemodel.boards[0].color
    player_name = conf.get("firstName", _("You"))

    w_name = player_name if color == WHITE else "PyChess"
    b_name = "PyChess" if color == WHITE else player_name

    p0 = (LOCAL, Human, (WHITE, w_name), w_name)
    p1 = (LOCAL, Human, (BLACK, b_name), b_name)

    def learn_success(gamemodel):
        progress = lessons_solving_progress[gamemodel.source]
        progress[gamemodel.current_index] = 1
        lessons_solving_progress[gamemodel.source] = progress
        asyncio.async(gamemodel.restart_analyzer(HINT))
    gamemodel.connect("learn_success", learn_success)

    def start_analyzer(gamemodel):
        asyncio.async(gamemodel.start_analyzer(HINT, force_engine=discoverer.getEngineLearn()))
    gamemodel.connect("game_started", start_analyzer)

    gamemodel.status = WAITING_TO_START
    perspective = perspective_manager.get_perspective("games")
    asyncio.async(perspective.generalStart(gamemodel, p0, p1))
Example #28
0
def queryGameno(path):
    pgnfile = pgn.load(protoopen(path))
    print "Selected file %s" % path
    if len(pgnfile) == 0:
        print "The file is empty."
        sys.exit()
    print

    print "The file contains the following games:"
    for i in xrange(len(pgnfile)):
        name1, name2 = pgnfile.get_player_names(i)
        print "[%d] %s vs. %s" % (i, name1, name2)
    print
    if len(pgnfile) == 1:
        print "Autoselecting game 0."
        gameno = 0
    else:
        gameno = int(raw_input("What engine should be your analyzer? [n] "))
    print

    return pgnfile, gameno
def queryGameno(path):
    pgnfile = pgn.load(protoopen(path))
    print "Selected file %s" % path
    if len(pgnfile) == 0:
        print "The file is empty."
        sys.exit()
    print
    
    print "The file contains the following games:"
    for i in xrange(len(pgnfile)):
        name1, name2 = pgnfile.get_player_names(i)
        print "[%d] %s vs. %s" % (i, name1, name2)
    print
    if len(pgnfile) == 1:
        print "Autoselecting game 0."
        gameno = 0
    else:
        gameno = int(raw_input("What engine should be your analyzer? [n] "))
    print
    
    return pgnfile, gameno
Example #30
0
def queryGameno(path):
    pgnfile = pgn.load(protoopen(path))
    print("Selected file %s" % path)
    if len(pgnfile) == 0:
        print("The file is empty.")
        sys.exit()
    print()
    
    print("The file contains the following games:")
    for i in range(len(pgnfile)):
        name1, name2 = pgnfile.get_player_names(i)
        print("[%d] %s vs. %s" % (i, name1, name2))
    print()
    if len(pgnfile) == 1:
        print("Autoselecting game 0.")
        gameno = 0
    else:
        gameno = int(raw_input("Select game number to be analyzed. [n]: "))
    print()
    
    return pgnfile, gameno
Example #31
0
def queryGameno(path):
    pgnfile = pgn.load(protoopen(path))
    print("Selected file %s" % path)
    if len(pgnfile) == 0:
        print("The file is empty.")
        sys.exit()
    print()

    print("The file contains the following games:")
    for i in range(len(pgnfile)):
        name1, name2 = pgnfile.get_player_names(i)
        print("[%d] %s vs. %s" % (i, name1, name2))
    print()
    if len(pgnfile) == 1:
        print("Autoselecting game 0.")
        gameno = 0
    else:
        gameno = int(raw_input("Select game number to be analyzed. [n]: "))
    print()

    return pgnfile, gameno
Example #32
0
def start_puzzle_from(filename):
    chessfile = PGNFile(protoopen(addDataPrefix("lectures/%s" % filename)))
    chessfile.limit = 1000
    importer = PgnImport(chessfile)
    chessfile.init_tag_database(importer)
    records, plys = chessfile.get_records()

    rec = records[random.randrange(0, len(records))]

    timemodel = TimeModel(0, 0)
    gamemodel = GameModel(timemodel)
    gamemodel.set_practice_game()
    gamemodel.practice = ("puzzle", filename)

    chessfile.loadToModel(rec, 0, gamemodel)

    # TODO: change colors according to FEN!
    name = rec["White"]
    p0 = (LOCAL, Human, (WHITE, name), name)

    engine = discoverer.getEngineByName(stockfish_name)
    name = rec["Black"]
    ponder_off = True
    p1 = (ARTIFICIAL, discoverer.initPlayerEngine,
          (engine, BLACK, 20, variants[NORMALCHESS], 60, 0, 0,
           ponder_off), name)

    def fix_name(gamemodel, name):
        asyncio. async (gamemodel.start_analyzer(HINT,
                                                 force_engine=stockfish_name))
        gamemodel.players[1].name = name
        gamemodel.emit("players_changed")

    gamemodel.connect("game_started", fix_name, name)

    gamemodel.variant.need_initial_board = True
    gamemodel.status = WAITING_TO_START

    perspective = perspective_manager.get_perspective("games")
    asyncio. async (perspective.generalStart(gamemodel, p0, p1))
Example #33
0
    def feed(pgnfile, lang):
        cf = load(protoopen(pgnfile))
        cf.limit = 5000
        cf.init_tag_database()
        records, plys = cf.get_records()

        rows = []
        old_eco = ""
        for rec in records:
            model = cf.loadToModel(rec)

            eco = rec["ECO"]

            opening = rec["White"]
            if opening is None:
                opening = ""

            variation = rec["Black"]
            if variation is None:
                variation = ""

            base = int(old_eco != eco)

            ply = len(model.moves)
            if ply == 0:
                cu = conn.cursor()
                cu.execute("select * from openings where eco=? and lang='en' and base=1", (eco,))
                res = cu.fetchone()
                if res is not None:
                    hash = res[0]
            else:
                hash = memoryview(hash_struct.pack(model.boards[-1].board.hash))

            if opening:
                rows.append((hash, base, eco, lang, opening, variation))

            old_eco = eco

        c.executemany("insert into openings(hash, base, eco, lang, opening, variation) values (?, ?, ?, ?, ?, ?)", rows)
        conn.commit()
Example #34
0
    def feed(pgnfile, lang):
        cf = load(protoopen(pgnfile))
        rows = []
        old_eco = ""
        ply_max = 0
        for i, game in enumerate(cf.games):
            model = cf.loadToModel(i)

            eco = cf._getTag(i, "ECO")[:3]
            
            opening = cf._getTag(i, "Opening")
            if opening is None:
                opening = ""

            variation = cf._getTag(i, "Variation")
            if variation is None:
                variation = ""
            
            base = int(old_eco != eco)
            
            ply = len(model.moves)
            ply_max = max(ply_max, ply)
            if ply == 0:
                cu = conn.cursor()
                cu.execute("select * from openings where eco=? and lang='en' and base=1", (eco,))
                res = cu.fetchone()
                if res is not None:
                    hash = res[0]
            else:
                hash = memoryview(hash_struct.pack(model.boards[-1].board.hash))
                
            if opening:
                rows.append((hash, base, unicode(eco), unicode(lang), unicode(opening), unicode(variation)))
                
            old_eco = eco
                
        c.executemany("insert into openings(hash, base, eco, lang, opening, variation) values (?, ?, ?, ?, ?, ?)", rows)
        conn.commit()

        print("Max ply was %s" % ply_max)
Example #35
0
def start_lesson_from(filename, index=None):
    chessfile = PGNFile(protoopen(addDataPrefix("learn/lessons/%s" % filename)))
    chessfile.limit = 1000
    chessfile.init_tag_database()
    records, plys = chessfile.get_records()

    progress = lessons_solving_progress.get(filename, [0] * chessfile.count)

    if index is None:
        index = progress.index(0)

    rec = records[index]

    timemodel = TimeModel(0, 0)
    gamemodel = LearnModel(timemodel)

    chessfile.loadToModel(rec, -1, gamemodel)

    if len(gamemodel.moves) > 0:
        start_lesson_game(gamemodel, filename, chessfile, records, index, rec)
    else:
        start_puzzle_game(gamemodel, filename, records, index, rec, from_lesson=True)
Example #36
0
    def feed(pgnfile, lang):
        # Check the existence of the file
        if not os.path.isfile(pgnfile):
            return

        # Load the ECO file first
        print('  - Parsing')
        cf = load(protoopen(pgnfile))
        cf.limit = 5000
        cf.init_tag_database()
        records, plys = cf.get_records()

        # Cache the content
        entries = []
        plyMax = 0
        old_eco = ""
        for rec in records:
            model = cf.loadToModel(rec)
            eco = '' if rec['ECO'] is None else rec['ECO']
            entry = {
                'h': [],  # Hashes
                'f': '',  # Final hash of the line
                'n': [],  # FENs
                'm': old_eco !=
                eco,  # Main line = shortest sequence of moves for the ECO code. The 'EN' ECO file is specially crafted
                'e': eco,  # ECO
                'o': '' if rec['White'] is None else rec['White'],  # Opening
                'v': '' if rec['Black'] is None else rec['Black'],  # Variation
                'p': len(model.moves)
            }  # Number of plies
            plyMax = max(plyMax, entry['p'])

            # No move means that we are translating the name of the ECO code, so we need to find all the related positions from another language
            if entry['p'] == 0:
                if lang == ECO_MAIN_LANG:
                    continue
                c.execute(
                    "select hash, endline, fen from openings where eco=? and lang=? and mainline=1",
                    (eco, ECO_MAIN_LANG))
                rows = c.fetchall()
                for row in rows:
                    entry['h'].append(row[0])
                    if (row[1] == int(True)):
                        entry['f'] = row[0]
                    entry['n'].append(row[2])
            else:
                # Find the Polyglot hash for each position of the opening
                for i in range(entry['p']):
                    nextboard = model.getBoardAtPly(i, 0).board.next
                    h = hex(nextboard.hash)[2:]
                    entry['h'].append(h)
                    entry['f'] = h
                    entry['n'].append(nextboard.asFen())
            entries.append(entry)
            old_eco = entry['e']
        print('  - Max ply : %d' % plyMax)

        # Process all the data in reverse order
        for depth in reversed(range(plyMax + 1)):
            sys.stdout.write(
                "\r  - Loading into the database (%d remaining)  " % depth)
            sys.stdout.flush()
            for i in reversed(range(len(
                    entries))):  # Long lines are overwritten by short lines
                entry = entries[i]
                if entry['p'] != depth:
                    continue
                for i in range(len(entry['h'])):
                    h = entry['h'][i]
                    hkey = int(h[-2:], 16)
                    c.execute(
                        "select endline from openings where hash=? and hkey=? and lang=?",
                        (h, hkey, lang))
                    r = c.fetchone()
                    if r is not None and r[0] == int(True):
                        continue
                    c.execute(
                        "delete from openings where hash=? and hkey=? and lang=?",
                        (h, hkey, lang))
                    c.execute(
                        "insert into openings (hash, hkey, mainline, endline, eco, lang, opening, variation, fen) values (?, ?, ?, ?, ?, ?, ?, ?, ?)",
                        (h, hkey, int(
                            entry['m']), int(h == entry['f']), entry['e'],
                         lang, entry['o'], entry['v'], entry['n'][i]))
        conn.commit()
        print('\n  - Processed %d openings' % len(entries))
Example #37
0
    def do_import(self, filename, info=None, progressbar=None):
        DB_MAXINT_SHIFT = get_maxint_shift(self.engine)
        self.progressbar = progressbar

        orig_filename = filename
        count_source = self.conn.execute(
            self.count_source.where(source.c.name == orig_filename)).scalar()
        if count_source > 0:
            print("%s is already imported" % filename)
            return

        # collect new names not in they dict yet
        self.event_data = []
        self.site_data = []
        self.player_data = []
        self.annotator_data = []
        self.source_data = []

        # collect new games and commit them in big chunks for speed
        self.game_data = []
        self.bitboard_data = []
        self.stat_ins_data = []
        self.stat_upd_data = []
        self.tag_game_data = []

        if filename.startswith("http"):
            filename = download_file(filename, progressbar=progressbar)
            if filename is None:
                return
        else:
            if not os.path.isfile(filename):
                print("Can't open %s" % filename)
                return

        if filename.lower().endswith(".zip") and zipfile.is_zipfile(filename):
            zf = zipfile.ZipFile(filename, "r")
            files = [f for f in zf.namelist() if f.lower().endswith(".pgn")]
        else:
            zf = None
            files = [filename]

        for pgnfile in files:
            basename = os.path.basename(pgnfile)
            if progressbar is not None:
                GLib.idle_add(progressbar.set_text,
                              "Reading %s ..." % basename)
            else:
                print("Reading %s ..." % pgnfile)

            if zf is None:
                size = os.path.getsize(pgnfile)
                handle = protoopen(pgnfile)
            else:
                size = zf.getinfo(pgnfile).file_size
                handle = io.TextIOWrapper(zf.open(pgnfile),
                                          encoding=PGN_ENCODING,
                                          newline='')

            cf = PgnBase(handle, [])

            # estimated game count
            all_games = max(size / 840, 1)
            self.CHUNK = 1000 if all_games > 5000 else 100

            get_id = self.get_id
            # use transaction to avoid autocommit slowness
            trans = self.conn.begin()
            try:
                i = 0
                for tagtext, movetext in read_games(handle):
                    tags = defaultdict(str, tagre.findall(tagtext))
                    if not tags:
                        print("Empty game #%s" % (i + 1))
                        continue

                    if self.cancel:
                        trans.rollback()
                        return

                    fenstr = tags.get("FEN")

                    variant = tags.get("Variant")
                    if variant:
                        if "fischer" in variant.lower() or "960" in variant:
                            variant = "Fischerandom"
                        else:
                            variant = variant.lower().capitalize()

                    # Fixes for some non statndard Chess960 .pgn
                    if fenstr and variant == "Fischerandom":
                        parts = fenstr.split()
                        parts[0] = parts[0].replace(".", "/").replace("0", "")
                        if len(parts) == 1:
                            parts.append("w")
                            parts.append("-")
                            parts.append("-")
                        fenstr = " ".join(parts)

                    if variant:
                        if variant not in name2variant:
                            print("Unknown variant: %s" % variant)
                            continue
                        variant = name2variant[variant].variant
                        if variant == NORMALCHESS:
                            # lichess uses tag [Variant "Standard"]
                            variant = 0
                            board = START_BOARD.clone()
                        else:
                            board = LBoard(variant)
                    elif fenstr:
                        variant = 0
                        board = LBoard()
                    else:
                        variant = 0
                        board = START_BOARD.clone()

                    if fenstr:
                        try:
                            board.applyFen(fenstr)
                        except SyntaxError as e:
                            print(
                                _("The game #%s can't be loaded, because of an error parsing FEN"
                                  ) % (i + 1), e.args[0])
                            continue
                    elif variant:
                        board.applyFen(FEN_START)

                    movelist = array("H")
                    comments = []
                    cf.error = None

                    # First we try to use simple_parse_movetext()
                    # assuming most games in .pgn contains only moves
                    # without any comments/variations
                    simple = False
                    if not fenstr and not variant:
                        bitboards = []
                        simple = cf.simple_parse_movetext(
                            movetext, board, movelist, bitboards)

                        if cf.error is not None:
                            print("ERROR in %s game #%s" % (pgnfile, i + 1),
                                  cf.error.args[0])
                            continue

                    # If simple_parse_movetext() find any comments/variations
                    # we restart parsing with full featured parse_movetext()
                    if not simple:
                        movelist = array("H")
                        bitboards = None

                        # in case simple_parse_movetext failed we have to reset our lboard
                        if not fenstr and not variant:
                            board = START_BOARD.clone()

                        # parse movetext to create boards tree structure
                        boards = [board]
                        boards = cf.parse_movetext(movetext,
                                                   boards[0],
                                                   -1,
                                                   pgn_import=True)

                        if cf.error is not None:
                            print("ERROR in %s game #%s" % (pgnfile, i + 1),
                                  cf.error.args[0])
                            continue

                        # create movelist and comments from boards tree
                        walk(boards[0], movelist, comments)

                    white = tags.get('White')
                    black = tags.get('Black')

                    if not movelist:
                        if (not comments) and (not white) and (not black):
                            print("Empty game #%s" % (i + 1))
                            continue

                    event_id = get_id(tags.get('Event'), event, EVENT)

                    site_id = get_id(tags.get('Site'), site, SITE)

                    game_date = tags.get('Date').strip()
                    try:
                        if game_date and '?' not in game_date:
                            ymd = game_date.split('.')
                            if len(ymd) == 3:
                                game_year, game_month, game_day = map(int, ymd)
                            else:
                                game_year, game_month, game_day = int(
                                    game_date[:4]), None, None
                        elif game_date and '?' not in game_date[:4]:
                            game_year, game_month, game_day = int(
                                game_date[:4]), None, None
                        else:
                            game_year, game_month, game_day = None, None, None
                    except:
                        game_year, game_month, game_day = None, None, None

                    game_round = tags.get('Round')

                    white_fide_id = tags.get('WhiteFideId')
                    black_fide_id = tags.get('BlackFideId')

                    white_id = get_id(unicode(white),
                                      player,
                                      PLAYER,
                                      fide_id=white_fide_id)
                    black_id = get_id(unicode(black),
                                      player,
                                      PLAYER,
                                      fide_id=black_fide_id)

                    result = tags.get("Result")
                    if result in pgn2Const:
                        result = pgn2Const[result]
                    else:
                        print("Invalid Result tag in game #%s: %s" %
                              (i + 1, result))
                        continue

                    white_elo = tags.get('WhiteElo')
                    white_elo = int(
                        white_elo
                    ) if white_elo and white_elo.isdigit() else None

                    black_elo = tags.get('BlackElo')
                    black_elo = int(
                        black_elo
                    ) if black_elo and black_elo.isdigit() else None

                    time_control = tags.get("TimeControl")

                    eco = tags.get("ECO")
                    eco = eco[:3] if eco else None

                    fen = tags.get("FEN")

                    board_tag = tags.get("Board")

                    annotator_id = get_id(tags.get("Annotator"), annotator,
                                          ANNOTATOR)

                    source_id = get_id(unicode(orig_filename),
                                       source,
                                       SOURCE,
                                       info=info)

                    game_id = self.next_id[GAME]
                    self.next_id[GAME] += 1

                    # annotated game
                    if bitboards is None:
                        for ply, board in enumerate(boards):
                            if ply == 0:
                                continue
                            bb = board.friends[0] | board.friends[1]
                            # Avoid to include mate in x .pgn collections and similar in opening tree
                            if fen and "/pppppppp/8/8/8/8/PPPPPPPP/" not in fen:
                                ply = -1
                            self.bitboard_data.append({
                                'game_id':
                                game_id,
                                'ply':
                                ply,
                                'bitboard':
                                bb - DB_MAXINT_SHIFT,
                            })

                            if ply <= STAT_PLY_MAX:
                                self.stat_ins_data.append({
                                    'ply': ply,
                                    'bitboard': bb - DB_MAXINT_SHIFT,
                                    'count': 0,
                                    'whitewon': 0,
                                    'blackwon': 0,
                                    'draw': 0,
                                    'white_elo_count': 0,
                                    'black_elo_count': 0,
                                    'white_elo': 0,
                                    'black_elo': 0,
                                })
                                self.stat_upd_data.append({
                                    '_ply':
                                    ply,
                                    '_bitboard':
                                    bb - DB_MAXINT_SHIFT,
                                    '_count':
                                    1,
                                    '_whitewon':
                                    1 if result == WHITEWON else 0,
                                    '_blackwon':
                                    1 if result == BLACKWON else 0,
                                    '_draw':
                                    1 if result == DRAW else 0,
                                    '_white_elo_count':
                                    1 if white_elo is not None else 0,
                                    '_black_elo_count':
                                    1 if black_elo is not None else 0,
                                    '_white_elo':
                                    white_elo if white_elo is not None else 0,
                                    '_black_elo':
                                    black_elo if black_elo is not None else 0,
                                })

                    # simple game
                    else:
                        for ply, bb in enumerate(bitboards):
                            if ply == 0:
                                continue
                            self.bitboard_data.append({
                                'game_id':
                                game_id,
                                'ply':
                                ply,
                                'bitboard':
                                bb - DB_MAXINT_SHIFT,
                            })

                            if ply <= STAT_PLY_MAX:
                                self.stat_ins_data.append({
                                    'ply': ply,
                                    'bitboard': bb - DB_MAXINT_SHIFT,
                                    'count': 0,
                                    'whitewon': 0,
                                    'blackwon': 0,
                                    'draw': 0,
                                    'white_elo_count': 0,
                                    'black_elo_count': 0,
                                    'white_elo': 0,
                                    'black_elo': 0,
                                })
                                self.stat_upd_data.append({
                                    '_ply':
                                    ply,
                                    '_bitboard':
                                    bb - DB_MAXINT_SHIFT,
                                    '_count':
                                    1,
                                    '_whitewon':
                                    1 if result == WHITEWON else 0,
                                    '_blackwon':
                                    1 if result == BLACKWON else 0,
                                    '_draw':
                                    1 if result == DRAW else 0,
                                    '_white_elo_count':
                                    1 if white_elo is not None else 0,
                                    '_black_elo_count':
                                    1 if black_elo is not None else 0,
                                    '_white_elo':
                                    white_elo if white_elo is not None else 0,
                                    '_black_elo':
                                    black_elo if black_elo is not None else 0,
                                })

                    ply_count = tags.get("PlyCount")
                    if not ply_count and not fen:
                        ply_count = len(
                            bitboards) if bitboards is not None else len(
                                boards)

                    self.game_data.append({
                        'event_id':
                        event_id,
                        'site_id':
                        site_id,
                        'date_year':
                        game_year,
                        'date_month':
                        game_month,
                        'date_day':
                        game_day,
                        'round':
                        game_round,
                        'white_id':
                        white_id,
                        'black_id':
                        black_id,
                        'result':
                        result,
                        'white_elo':
                        white_elo,
                        'black_elo':
                        black_elo,
                        'ply_count':
                        ply_count,
                        'eco':
                        eco,
                        'fen':
                        fen,
                        'variant':
                        variant,
                        'board':
                        board_tag,
                        'time_control':
                        time_control,
                        'annotator_id':
                        annotator_id,
                        'source_id':
                        source_id,
                        'movelist':
                        movelist.tostring(),
                        'comments':
                        unicode("|".join(comments)),
                    })

                    i += 1

                    if len(self.game_data) >= self.CHUNK:
                        if self.event_data:
                            self.conn.execute(self.ins_event, self.event_data)
                            self.event_data = []

                        if self.site_data:
                            self.conn.execute(self.ins_site, self.site_data)
                            self.site_data = []

                        if self.player_data:
                            self.conn.execute(self.ins_player,
                                              self.player_data)
                            self.player_data = []

                        if self.annotator_data:
                            self.conn.execute(self.ins_annotator,
                                              self.annotator_data)
                            self.annotator_data = []

                        if self.source_data:
                            self.conn.execute(self.ins_source,
                                              self.source_data)
                            self.source_data = []

                        self.conn.execute(self.ins_game, self.game_data)
                        self.game_data = []

                        if self.bitboard_data:
                            self.conn.execute(self.ins_bitboard,
                                              self.bitboard_data)
                            self.bitboard_data = []

                            self.conn.execute(self.ins_stat,
                                              self.stat_ins_data)
                            self.conn.execute(self.upd_stat,
                                              self.stat_upd_data)
                            self.stat_ins_data = []
                            self.stat_upd_data = []

                        if progressbar is not None:
                            GLib.idle_add(progressbar.set_fraction,
                                          i / float(all_games))
                            GLib.idle_add(
                                progressbar.set_text,
                                "%s games from %s imported" % (i, basename))
                        else:
                            print(pgnfile, i)

                if self.event_data:
                    self.conn.execute(self.ins_event, self.event_data)
                    self.event_data = []

                if self.site_data:
                    self.conn.execute(self.ins_site, self.site_data)
                    self.site_data = []

                if self.player_data:
                    self.conn.execute(self.ins_player, self.player_data)
                    self.player_data = []

                if self.annotator_data:
                    self.conn.execute(self.ins_annotator, self.annotator_data)
                    self.annotator_data = []

                if self.source_data:
                    self.conn.execute(self.ins_source, self.source_data)
                    self.source_data = []

                if self.game_data:
                    self.conn.execute(self.ins_game, self.game_data)
                    self.game_data = []

                if self.bitboard_data:
                    self.conn.execute(self.ins_bitboard, self.bitboard_data)
                    self.bitboard_data = []

                    self.conn.execute(self.ins_stat, self.stat_ins_data)
                    self.conn.execute(self.upd_stat, self.stat_upd_data)
                    self.stat_ins_data = []
                    self.stat_upd_data = []

                if progressbar is not None:
                    GLib.idle_add(progressbar.set_fraction,
                                  i / float(all_games))
                    GLib.idle_add(progressbar.set_text,
                                  "%s games from %s imported" % (i, basename))
                else:
                    print(pgnfile, i)
                trans.commit()

            except SQLAlchemyError as e:
                trans.rollback()
                print("Importing %s failed! \n%s" % (pgnfile, e))
Example #38
0
def start_puzzle_from(filename, index=None):
    if filename.lower().endswith(".pgn"):
        chessfile = PGNFile(protoopen(addDataPrefix("learn/puzzles/%s" % filename)))
        chessfile.limit = 1000
        chessfile.init_tag_database()
    elif filename.lower().endswith(".olv"):
        chessfile = OLVFile(protoopen(addDataPrefix("learn/puzzles/%s" % filename), encoding="utf-8"))

    records, plys = chessfile.get_records()

    progress = puzzles_solving_progress.get(filename, [0] * chessfile.count)

    if index is None:
        index = progress.index(0)

    rec = records[index]

    timemodel = TimeModel(0, 0)
    gamemodel = LearnModel(timemodel)

    chessfile.loadToModel(rec, 0, gamemodel)
    gamemodel.set_learn_data(PUZZLE, filename, index, len(records))

    engine = discoverer.getEngineByName(discoverer.getEngineLearn())
    ponder_off = True

    color = gamemodel.boards[0].color

    w_name = "" if rec["White"] is None else rec["White"]
    b_name = "" if rec["Black"] is None else rec["Black"]

    player_name = conf.get("firstName", _("You"))
    engine_name = discoverer.getName(engine)

    if rec["Event"].startswith("Lichess Practice"):
        w_name = player_name if color == WHITE else engine_name
        b_name = engine_name if color == WHITE else player_name

    opp_name = engine_name if rec["Event"].startswith("Lichess Practice") else b_name

    if color == WHITE:
        p0 = (LOCAL, Human, (WHITE, w_name), w_name)
        p1 = (ARTIFICIAL, discoverer.initPlayerEngine,
              (engine, BLACK, 20, variants[NORMALCHESS], 20, 0, 0, ponder_off), b_name)
    else:
        p0 = (ARTIFICIAL, discoverer.initPlayerEngine,
              (engine, WHITE, 20, variants[NORMALCHESS], 20, 0, 0, ponder_off), w_name)
        p1 = (LOCAL, Human, (BLACK, b_name), b_name)

    def start_analyzer(gamemodel, name, color):
        asyncio.async(gamemodel.start_analyzer(HINT, force_engine=discoverer.getEngineLearn()))
        gamemodel.players[1 - color].name = name
        gamemodel.emit("players_changed")
    gamemodel.connect("game_started", start_analyzer, opp_name, color)

    def goal_checked(gamemodle):
        if gamemodel.reason == PRACTICE_GOAL_REACHED:
            progress = puzzles_solving_progress[gamemodel.source]
            progress[gamemodel.current_index] = 1
            puzzles_solving_progress[gamemodel.source] = progress
    gamemodel.connect("goal_checked", goal_checked)

    gamemodel.variant.need_initial_board = True
    gamemodel.status = WAITING_TO_START

    perspective = perspective_manager.get_perspective("games")
    asyncio.async(perspective.generalStart(gamemodel, p0, p1))
Example #39
0
    def do_import(self, filename, info=None, progressbar=None):
        self.progressbar = progressbar

        orig_filename = filename
        count_source = self.conn.execute(
            self.count_source.where(source.c.name == orig_filename)).scalar()
        if count_source > 0:
            log.info("%s is already imported" % filename)
            return

        # collect new names not in they dict yet
        self.event_data = []
        self.site_data = []
        self.player_data = []
        self.annotator_data = []
        self.source_data = []

        # collect new games and commit them in big chunks for speed
        self.game_data = []
        self.tag_game_data = []

        if filename.startswith("http"):
            filename = download_file(filename, progressbar=progressbar)
            if filename is None:
                return
        else:
            if not os.path.isfile(filename):
                log.info("Can't open %s" % filename)
                return

        if filename.lower().endswith(".zip") and zipfile.is_zipfile(filename):
            with zipfile.ZipFile(filename, "r") as zf:
                path = os.path.dirname(filename)
                files = [
                    os.path.join(path, f) for f in zf.namelist()
                    if f.lower().endswith(".pgn")
                ]
                zf.extractall(path)
        else:
            files = [filename]

        for pgnfile in files:
            base_offset = self.chessfile.size if self.append_pgn else 0

            basename = os.path.basename(pgnfile)
            if progressbar is not None:
                GLib.idle_add(progressbar.set_text,
                              _("Reading %s ..." % basename))
            else:
                log.info("Reading %s ..." % pgnfile)

            size = os.path.getsize(pgnfile)
            handle = protoopen(pgnfile)

            # estimated game count
            all_games = max(size / 840, 1)

            get_id = self.get_id

            # use transaction to avoid autocommit slowness
            # and to let undo importing (rollback) if self.cancel was set
            trans = self.conn.begin()
            try:
                i = 0
                for tags in read_games(handle):
                    if not tags:
                        log.info("Empty game #%s" % (i + 1))
                        continue

                    if self.cancel:
                        trans.rollback()
                        return

                    fenstr = tags["FEN"]

                    variant = tags["Variant"]
                    if variant:
                        if "fischer" in variant.lower() or "960" in variant:
                            variant = "Fischerandom"
                        else:
                            variant = variant.lower().capitalize()

                    # Fixes for some non statndard Chess960 .pgn
                    if fenstr and variant == "Fischerandom":
                        parts = fenstr.split()
                        parts[0] = parts[0].replace(".", "/").replace("0", "")
                        if len(parts) == 1:
                            parts.append("w")
                            parts.append("-")
                            parts.append("-")
                        fenstr = " ".join(parts)

                    if variant:
                        if variant not in name2variant:
                            log.info("Unknown variant: %s" % variant)
                            continue
                        variant = name2variant[variant].variant
                        if variant == NORMALCHESS:
                            # lichess uses tag [Variant "Standard"]
                            variant = 0
                    else:
                        variant = 0

                    if basename == "eco.pgn":
                        white = tags["Opening"]
                        black = tags["Variation"]
                    else:
                        white = tags["White"]
                        black = tags["Black"]

                    event_id = get_id(tags["Event"], event, EVENT)

                    site_id = get_id(tags["Site"], site, SITE)

                    date = tags["Date"]

                    game_round = tags['Round']

                    white_id = get_id(white, player, PLAYER)
                    black_id = get_id(black, player, PLAYER)

                    result = tags["Result"]
                    if result in pgn2Const:
                        result = pgn2Const[result]
                    else:
                        result = RUNNING

                    white_elo = tags['WhiteElo']
                    black_elo = tags['BlackElo']

                    time_control = tags["TimeControl"]

                    eco = tags["ECO"][:3]

                    fen = tags["FEN"]

                    board_tag = int(tags["Board"]) if "Board" in tags else 0

                    annotator_id = get_id(tags["Annotator"], annotator,
                                          ANNOTATOR)

                    source_id = get_id(orig_filename,
                                       source,
                                       SOURCE,
                                       info=info)

                    ply_count = tags["PlyCount"] if "PlyCount" in tags else 0

                    offset = base_offset + int(tags["offset"])

                    self.game_data.append({
                        'offset': offset,
                        'offset8': (offset >> 3) << 3,
                        'event_id': event_id,
                        'site_id': site_id,
                        'date': date,
                        'round': game_round,
                        'white_id': white_id,
                        'black_id': black_id,
                        'result': result,
                        'white_elo': white_elo,
                        'black_elo': black_elo,
                        'ply_count': ply_count,
                        'eco': eco,
                        'fen': fen,
                        'variant': variant,
                        'board': board_tag,
                        'time_control': time_control,
                        'annotator_id': annotator_id,
                        'source_id': source_id,
                    })

                    for tag in tags:
                        if tag not in dedicated_tags and tag not in other_game_tags and tags[
                                tag]:
                            self.tag_game_data.append({
                                'game_id':
                                self.next_id[GAME],
                                'tag_name':
                                tag,
                                'tag_value':
                                tags[tag],
                            })

                    self.next_id[GAME] += 1
                    i += 1

                    if len(self.game_data) >= self.CHUNK:
                        if self.event_data:
                            self.conn.execute(self.ins_event, self.event_data)
                            self.event_data = []

                        if self.site_data:
                            self.conn.execute(self.ins_site, self.site_data)
                            self.site_data = []

                        if self.player_data:
                            self.conn.execute(self.ins_player,
                                              self.player_data)
                            self.player_data = []

                        if self.annotator_data:
                            self.conn.execute(self.ins_annotator,
                                              self.annotator_data)
                            self.annotator_data = []

                        if self.source_data:
                            self.conn.execute(self.ins_source,
                                              self.source_data)
                            self.source_data = []

                        if self.tag_game_data:
                            self.conn.execute(self.ins_tag_game,
                                              self.tag_game_data)
                            self.tag_game_data = []

                        self.conn.execute(self.ins_game, self.game_data)
                        self.game_data = []

                        if progressbar is not None:
                            GLib.idle_add(progressbar.set_fraction,
                                          i / float(all_games))
                            GLib.idle_add(
                                progressbar.set_text,
                                _("%(counter)s game headers from %(filename)s imported"
                                  % ({
                                      "counter": i,
                                      "filename": basename
                                  })))
                        else:
                            log.info("From %s imported %s" % (pgnfile, i))

                if self.event_data:
                    self.conn.execute(self.ins_event, self.event_data)
                    self.event_data = []

                if self.site_data:
                    self.conn.execute(self.ins_site, self.site_data)
                    self.site_data = []

                if self.player_data:
                    self.conn.execute(self.ins_player, self.player_data)
                    self.player_data = []

                if self.annotator_data:
                    self.conn.execute(self.ins_annotator, self.annotator_data)
                    self.annotator_data = []

                if self.source_data:
                    self.conn.execute(self.ins_source, self.source_data)
                    self.source_data = []

                if self.tag_game_data:
                    self.conn.execute(self.ins_tag_game, self.tag_game_data)
                    self.tag_game_data = []

                if self.game_data:
                    self.conn.execute(self.ins_game, self.game_data)
                    self.game_data = []

                if progressbar is not None:
                    GLib.idle_add(progressbar.set_fraction,
                                  i / float(all_games))
                    GLib.idle_add(
                        progressbar.set_text,
                        _("%(counter)s game headers from %(filename)s imported"
                          % ({
                              "counter": i,
                              "filename": basename
                          })))
                else:
                    log.info("From %s imported %s" % (pgnfile, i))
                trans.commit()

                if self.append_pgn:
                    # reopen database to write
                    self.db_handle.close()
                    with protosave(self.chessfile.path,
                                   self.append_pgn) as self.db_handle:
                        log.info("Append from %s to %s" %
                                 (pgnfile, self.chessfile.path))
                        handle.seek(0)
                        self.db_handle.writelines(handle)
                        handle.close()

                    if self.chessfile.scoutfish is not None:
                        # create new .scout from pgnfile we are importing
                        from pychess.Savers.pgn import scoutfish_path
                        args = [
                            scoutfish_path, "make", pgnfile,
                            "%s" % base_offset
                        ]
                        output = subprocess.check_output(
                            args, stderr=subprocess.STDOUT).decode()

                        # append it to our existing one
                        if output.find("Processing...done") > 0:
                            old_scout = self.chessfile.scoutfish.db
                            new_scout = os.path.splitext(pgnfile)[0] + '.scout'

                            with open(old_scout,
                                      "ab") as file1, open(new_scout,
                                                           "rb") as file2:
                                file1.write(file2.read())

                self.chessfile.handle = protoopen(self.chessfile.path)

            except SQLAlchemyError as e:
                trans.rollback()
                log.info("Importing %s failed! \n%s" % (pgnfile, e))
Example #40
0
def normalize(text):
    text = text.splitlines()
    text = " ".join(text)
    text = text.replace('.   ', '. ').replace('.  ', '. ')
    text = text.replace('  )', ')').replace(' )', ')')
    text = text.replace('(  ', '(').replace('( ', '(')
    text = text.replace('  }', '}').replace(' }', '}')
    text = text.replace('{  ', '{').replace('{ ', '{')
    return text

filenames = ("atomic", "chess960rwch", "world_matches", "zh")

for filename in filenames:
    print("Creating test methods for %s" % filename)
    pgnfile = load(protoopen('gamefiles/%s.pgn' % filename))
    pgnfile.get_records()
    for i, game in enumerate(pgnfile.games):
        print("%s/%s" % (i + 1, len(pgnfile.games)))
        if i > 100:
            break

        orig = normalize(pgnfile.get_movetext(game))

        model = pgnfile.loadToModel(game)
        new = []
        walk(model.boards[0].board, new, model)
        new = normalize(" ".join(new))

        # create test method
        test_method = create_test(orig, new)
Example #41
0
import unittest

from pychess.Savers.pgn import load, walk, pattern, MOVE
from pychess.System.protoopen import protoopen

file_names = ("atomic", "chess960rwch", "world_matches", "zh")
file_handles = []
for name in file_names:
    file_handles.append(protoopen("gamefiles/%s.pgn" % name))


class PgnTestCase(unittest.TestCase):
    @classmethod
    def tearDownClass(cls):
        for handle in file_handles:
            handle.close()

    def test_movre(self):
        """Testing SAN pattern regexp"""
        moves = "e4 fxg7 g8=Q gxh8=N a2+ axb1# c1=Q+ exd8=N# " + \
            "0-0-0 O-O-O 0-0 O-O Ka1 Kxf8 Kxd4+ " + \
            "Qc3 Rxh8 B1xg7 Nhxg2 Qe4xd5 Rb7+ Bxg4# N8xb2+ Qaxb7# Qd5xe4+"
        matches = [m[MOVE - 1] for m in pattern.findall(moves)]
        self.assertEqual(' '.join(matches), ' '.join(moves.split()))


def create_test(o, n):
    def test_expected(self):
        for orig, new in zip(o.split(), n.split()):
            # Seems most .PGN unnecessary contains unambiguous notation
            # when second move candidate is invalid (leaves king in check)
Example #42
0
def normalize(text):
    text = text.splitlines()
    text = " ".join(text)
    text = text.replace('.   ', '. ').replace('.  ', '. ')
    text = text.replace('  )', ')').replace(' )', ')')
    text = text.replace('(  ', '(').replace('( ', '(')
    text = text.replace('  }', '}').replace(' }', '}')
    text = text.replace('{  ', '{').replace('{ ', '{')
    return text


filenames = ("atomic", "chess960rwch", "world_matches", "zh")

for filename in filenames:
    print("Creating test methods for %s" % filename)
    pgnfile = load(protoopen('gamefiles/%s.pgn' % filename))
    pgnfile.get_records()
    for i, game in enumerate(pgnfile.games):
        print("%s/%s" % (i + 1, len(pgnfile.games)))
        if i > 100:
            break

        orig = normalize(pgnfile.get_movetext(game))

        model = pgnfile.loadToModel(game)
        new = []
        walk(model.boards[0].board, new, model)
        new = normalize(" ".join(new))

        # create test method
        test_method = create_test(orig, new)
Example #43
0
def start_puzzle_from(filename, index=None):
    if filename.lower().endswith(".pgn"):
        if filename.startswith("lichess_study"):
            chessfile = PGNFile(
                protoopen(addDataPrefix("learn/puzzles/%s" % filename),
                          encoding="utf-8"))
        else:
            chessfile = PGNFile(
                protoopen(addDataPrefix("learn/puzzles/%s" % filename)))
        chessfile.limit = 1000
        chessfile.init_tag_database()
    elif filename.lower().endswith(".olv"):
        chessfile = OLVFile(
            protoopen(addDataPrefix("learn/puzzles/%s" % filename),
                      encoding="utf-8"))

    records, plys = chessfile.get_records()

    progress = puzzles_solving_progress.get(filename, [0] * chessfile.count)

    if index is None:
        index = progress.index(0)

    rec = records[index]

    timemodel = TimeModel(0, 0)
    gamemodel = LearnModel(timemodel)
    gamemodel.set_learn_data(PUZZLE, filename, index, len(records))

    chessfile.loadToModel(rec, 0, gamemodel)

    engine = discoverer.getEngineByName(discoverer.getEngineLearn())
    ponder_off = True

    color = gamemodel.boards[0].color

    w_name = "" if rec["White"] is None else rec["White"]
    b_name = "" if rec["Black"] is None else rec["Black"]

    player_name = conf.get("firstName", _("You"))
    engine_name = discoverer.getName(engine)

    if rec["Event"].startswith("Lichess Practice"):
        w_name = player_name if color == WHITE else engine_name
        b_name = engine_name if color == WHITE else player_name

    opp_name = engine_name if rec["Event"].startswith(
        "Lichess Practice") else b_name

    if color == WHITE:
        p0 = (LOCAL, Human, (WHITE, w_name), w_name)
        p1 = (ARTIFICIAL, discoverer.initPlayerEngine,
              (engine, BLACK, 20, variants[NORMALCHESS], 20, 0, 0,
               ponder_off), b_name)
    else:
        p0 = (ARTIFICIAL, discoverer.initPlayerEngine,
              (engine, WHITE, 20, variants[NORMALCHESS], 20, 0, 0,
               ponder_off), w_name)
        p1 = (LOCAL, Human, (BLACK, b_name), b_name)

    def on_game_started(gamemodel, name, color):
        perspective.activate_panel("annotationPanel")
        asyncio. async (gamemodel.start_analyzer(
            HINT, force_engine=discoverer.getEngineLearn()))
        gamemodel.players[1 - color].name = name
        gamemodel.emit("players_changed")

    gamemodel.connect("game_started", on_game_started, opp_name, color)

    def goal_checked(gamemodle):
        if gamemodel.reason == PRACTICE_GOAL_REACHED:
            progress = puzzles_solving_progress[gamemodel.source]
            progress[gamemodel.current_index] = 1
            puzzles_solving_progress[gamemodel.source] = progress

    gamemodel.connect("goal_checked", goal_checked)

    gamemodel.variant.need_initial_board = True
    gamemodel.status = WAITING_TO_START

    perspective = perspective_manager.get_perspective("games")
    asyncio. async (perspective.generalStart(gamemodel, p0, p1))
Example #44
0
else:
    DATA_FILES += [("share/pychess/sounds", glob('sounds/*.ogg'))]
DATA_FILES += [('share/icons/hicolor/24x24/apps', ['pychess.png'])]
DATA_FILES += [('share/gtksourceview-3.0/language-specs',
                ['gtksourceview-3.0/language-specs/pgn.lang'])]

# Piece sets
DATA_FILES += [("share/pychess/pieces", glob('pieces/*.png'))]

if not isfile(os.path.abspath("learn/puzzles/mate_in_4.sqlite")):
    from pychess.Savers.pgn import PGNFile
    from pychess.System.protoopen import protoopen

    # Lectures, puzzles, lessons
    for filename in glob('learn/puzzles/*.pgn'):
        chessfile = PGNFile(protoopen(filename))
        chessfile.init_tag_database()

    for filename in glob('learn/lessons/*.pgn'):
        chessfile = PGNFile(protoopen(filename))
        chessfile.init_tag_database()

DATA_FILES += [("share/pychess/learn/puzzles", glob('learn/puzzles/*.olv'))]
DATA_FILES += [("share/pychess/learn/puzzles", glob('learn/puzzles/*.pgn'))]
DATA_FILES += [("share/pychess/learn/puzzles", glob('learn/puzzles/*.sqlite'))]
DATA_FILES += [("share/pychess/learn/lessons", glob('learn/lessons/*.pgn'))]
DATA_FILES += [("share/pychess/learn/lessons", glob('learn/lessons/*.sqlite'))]
DATA_FILES += [("share/pychess/learn/lectures", glob('learn/lectures/*.txt'))]

for dir in [d for d in listdir('pieces') if isdir(os.path.join('pieces', d))]:
    DATA_FILES += [("share/pychess/pieces/" + dir,
Example #45
0
    def do_import(self, filename, info=None, progressbar=None):
        self.progressbar = progressbar

        orig_filename = filename
        count_source = self.conn.execute(
            self.count_source.where(source.c.name == orig_filename)).scalar()
        if count_source > 0:
            print("%s is already imported" % filename)
            return

        # collect new names not in they dict yet
        self.event_data = []
        self.site_data = []
        self.player_data = []
        self.annotator_data = []
        self.source_data = []

        # collect new games and commit them in big chunks for speed
        self.game_data = []
        self.tag_game_data = []

        if filename.startswith("http"):
            filename = download_file(filename, progressbar=progressbar)
            if filename is None:
                return
        else:
            if not os.path.isfile(filename):
                print("Can't open %s" % filename)
                return

        if filename.lower().endswith(".zip") and zipfile.is_zipfile(filename):
            with zipfile.ZipFile(filename, "r") as zf:
                path = os.path.dirname(filename)
                files = [
                    os.path.join(path, f) for f in zf.namelist()
                    if f.lower().endswith(".pgn")
                ]
                zf.extractall(path)
        else:
            files = [filename]

        for pgnfile in files:
            base_offset = self.chessfile.size if self.append_pgn else 0

            basename = os.path.basename(pgnfile)
            if progressbar is not None:
                GLib.idle_add(progressbar.set_text,
                              "Reading %s ..." % basename)
            else:
                print("Reading %s ..." % pgnfile)

            size = os.path.getsize(pgnfile)
            handle = protoopen(pgnfile)

            # estimated game count
            all_games = max(size / 840, 1)

            get_id = self.get_id
            # use transaction to avoid autocommit slowness
            trans = self.conn.begin()
            try:
                i = 0
                for offs, tags in read_games(handle):
                    if not tags:
                        print("Empty game #%s" % (i + 1))
                        continue

                    if self.cancel:
                        trans.rollback()
                        return

                    fenstr = tags.get("FEN")

                    variant = tags.get("Variant")
                    if variant:
                        if "fischer" in variant.lower() or "960" in variant:
                            variant = "Fischerandom"
                        else:
                            variant = variant.lower().capitalize()

                    # Fixes for some non statndard Chess960 .pgn
                    if fenstr and variant == "Fischerandom":
                        parts = fenstr.split()
                        parts[0] = parts[0].replace(".", "/").replace("0", "")
                        if len(parts) == 1:
                            parts.append("w")
                            parts.append("-")
                            parts.append("-")
                        fenstr = " ".join(parts)

                    if variant:
                        if variant not in name2variant:
                            print("Unknown variant: %s" % variant)
                            continue
                        variant = name2variant[variant].variant
                        if variant == NORMALCHESS:
                            # lichess uses tag [Variant "Standard"]
                            variant = 0
                    else:
                        variant = 0

                    white = tags.get('White')
                    black = tags.get('Black')

                    event_id = get_id(tags.get('Event'), event, EVENT)

                    site_id = get_id(tags.get('Site'), site, SITE)

                    game_date = tags['Date'].strip()
                    try:
                        if game_date and '?' not in game_date:
                            ymd = game_date.split('.')
                            if len(ymd) == 3:
                                game_year, game_month, game_day = map(int, ymd)
                            else:
                                game_year, game_month, game_day = int(
                                    game_date[:4]), None, None
                        elif game_date and '?' not in game_date[:4]:
                            game_year, game_month, game_day = int(
                                game_date[:4]), None, None
                        else:
                            game_year, game_month, game_day = None, None, None
                    except:
                        game_year, game_month, game_day = None, None, None

                    game_round = tags.get('Round')

                    white_id = get_id(unicode(white), player, PLAYER)
                    black_id = get_id(unicode(black), player, PLAYER)

                    result = tags.get("Result")
                    if result in pgn2Const:
                        result = pgn2Const[result]
                    else:
                        print("Invalid Result tag in game #%s: %s" %
                              (i + 1, result))
                        continue

                    white_elo = tags.get('WhiteElo')
                    white_elo = int(
                        white_elo
                    ) if white_elo and white_elo.isdigit() else None

                    black_elo = tags.get('BlackElo')
                    black_elo = int(
                        black_elo
                    ) if black_elo and black_elo.isdigit() else None

                    time_control = tags.get("TimeControl")

                    eco = tags.get("ECO")
                    eco = eco[:3] if eco else None

                    fen = tags.get("FEN")

                    board_tag = tags.get("Board")

                    annotator_id = get_id(tags.get("Annotator"), annotator,
                                          ANNOTATOR)

                    source_id = get_id(unicode(orig_filename),
                                       source,
                                       SOURCE,
                                       info=info)

                    self.next_id[GAME] += 1

                    ply_count = tags.get("PlyCount")

                    self.game_data.append({
                        'offset': base_offset + int(offs),
                        'offset8': (int(offs) >> 3) << 3,
                        'event_id': event_id,
                        'site_id': site_id,
                        'date_year': game_year,
                        'date_month': game_month,
                        'date_day': game_day,
                        'round': game_round,
                        'white_id': white_id,
                        'black_id': black_id,
                        'result': result,
                        'white_elo': white_elo,
                        'black_elo': black_elo,
                        'ply_count': ply_count,
                        'eco': eco,
                        'fen': fen,
                        'variant': variant,
                        'board': board_tag,
                        'time_control': time_control,
                        'annotator_id': annotator_id,
                        'source_id': source_id,
                    })

                    i += 1

                    if len(self.game_data) >= self.CHUNK:
                        if self.event_data:
                            self.conn.execute(self.ins_event, self.event_data)
                            self.event_data = []

                        if self.site_data:
                            self.conn.execute(self.ins_site, self.site_data)
                            self.site_data = []

                        if self.player_data:
                            self.conn.execute(self.ins_player,
                                              self.player_data)
                            self.player_data = []

                        if self.annotator_data:
                            self.conn.execute(self.ins_annotator,
                                              self.annotator_data)
                            self.annotator_data = []

                        if self.source_data:
                            self.conn.execute(self.ins_source,
                                              self.source_data)
                            self.source_data = []

                        self.conn.execute(self.ins_game, self.game_data)
                        self.game_data = []

                        if progressbar is not None:
                            GLib.idle_add(progressbar.set_fraction,
                                          i / float(all_games))
                            GLib.idle_add(
                                progressbar.set_text,
                                "%s game headers from %s imported" %
                                (i, basename))
                        else:
                            print(pgnfile, i)

                if self.event_data:
                    self.conn.execute(self.ins_event, self.event_data)
                    self.event_data = []

                if self.site_data:
                    self.conn.execute(self.ins_site, self.site_data)
                    self.site_data = []

                if self.player_data:
                    self.conn.execute(self.ins_player, self.player_data)
                    self.player_data = []

                if self.annotator_data:
                    self.conn.execute(self.ins_annotator, self.annotator_data)
                    self.annotator_data = []

                if self.source_data:
                    self.conn.execute(self.ins_source, self.source_data)
                    self.source_data = []

                if self.game_data:
                    self.conn.execute(self.ins_game, self.game_data)
                    self.game_data = []

                if progressbar is not None:
                    GLib.idle_add(progressbar.set_fraction,
                                  i / float(all_games))
                    GLib.idle_add(
                        progressbar.set_text,
                        "%s game headers from %s imported" % (i, basename))
                else:
                    print(pgnfile, i)
                trans.commit()

                if self.append_pgn:
                    # reopen database to write
                    self.db_handle.close()
                    self.db_handle = protosave(self.chessfile.path,
                                               self.append_pgn)

                    print("Append from %s to %s" %
                          (pgnfile, self.chessfile.path))
                    handle.seek(0)
                    for line in handle:
                        self.db_handle.write(line)
                    self.db_handle.close()

                self.chessfile.handle = protoopen(self.chessfile.path)

            except SQLAlchemyError as e:
                trans.rollback()
                print("Importing %s failed! \n%s" % (pgnfile, e))
Example #46
0
    def do_import(self, filename, info=None, progressbar=None):
        self.progressbar = progressbar

        orig_filename = filename
        count_source = self.conn.execute(
            self.count_source.where(source.c.name == orig_filename)).scalar()
        if count_source > 0:
            print("%s is already imported" % filename)
            return

        # collect new names not in they dict yet
        self.event_data = []
        self.site_data = []
        self.player_data = []
        self.annotator_data = []
        self.source_data = []

        # collect new games and commit them in big chunks for speed
        self.game_data = []
        self.tag_game_data = []

        if filename.startswith("http"):
            filename = download_file(filename, progressbar=progressbar)
            if filename is None:
                return
        else:
            if not os.path.isfile(filename):
                print("Can't open %s" % filename)
                return

        if filename.lower().endswith(".zip") and zipfile.is_zipfile(filename):
            with zipfile.ZipFile(filename, "r") as zf:
                path = os.path.dirname(filename)
                files = [
                    os.path.join(path, f) for f in zf.namelist()
                    if f.lower().endswith(".pgn")
                ]
                zf.extractall(path)
        else:
            files = [filename]

        for pgnfile in files:
            base_offset = self.chessfile.size if self.append_pgn else 0

            basename = os.path.basename(pgnfile)
            if progressbar is not None:
                GLib.idle_add(progressbar.set_text,
                              "Reading %s ..." % basename)
            else:
                print("Reading %s ..." % pgnfile)

            size = os.path.getsize(pgnfile)
            handle = protoopen(pgnfile)

            # estimated game count
            all_games = max(size / 840, 1)

            handle_json = None
            if pgnextractor is not None:
                try:
                    headers_json = os.path.splitext(
                        pgnfile)[0] + ".headers.json"
                    if not os.path.isfile(headers_json):
                        output = subprocess.check_output(
                            [pgnextractor, "headers", pgnfile]).decode()
                        for line in output:
                            if line.startswith("Games"):
                                all_games = line.split()[1]
                    handle_json = protoopen(headers_json)
                except subprocess.CalledProcessError:
                    print("pgnextractor failed")

            get_id = self.get_id
            # use transaction to avoid autocommit slowness
            trans = self.conn.begin()
            try:
                i = 0
                for tags in read_games(handle, handle_json):
                    if not tags:
                        print("Empty game #%s" % (i + 1))
                        continue

                    if self.cancel:
                        trans.rollback()
                        return

                    fenstr = tags["FEN"] if "FEN" in tags else ""

                    variant = tags["Variant"] if "Variant" in tags else ""
                    if variant:
                        if "fischer" in variant.lower() or "960" in variant:
                            variant = "Fischerandom"
                        else:
                            variant = variant.lower().capitalize()

                    # Fixes for some non statndard Chess960 .pgn
                    if fenstr and variant == "Fischerandom":
                        parts = fenstr.split()
                        parts[0] = parts[0].replace(".", "/").replace("0", "")
                        if len(parts) == 1:
                            parts.append("w")
                            parts.append("-")
                            parts.append("-")
                        fenstr = " ".join(parts)

                    if variant:
                        if variant not in name2variant:
                            print("Unknown variant: %s" % variant)
                            continue
                        variant = name2variant[variant].variant
                        if variant == NORMALCHESS:
                            # lichess uses tag [Variant "Standard"]
                            variant = 0
                    else:
                        variant = 0

                    white = tags["White"] if "White" in tags else ""
                    black = tags["Black"] if "Black" in tags else ""

                    event_id = get_id(tags["Event"] if "Event" in tags else "",
                                      event, EVENT)

                    site_id = get_id(tags["Site"] if "Site" in tags else "",
                                     site, SITE)

                    game_date = tags["Date"] if "Date" in tags else ""
                    try:
                        if game_date and '?' not in game_date:
                            ymd = game_date.split('.')
                            if len(ymd) == 3:
                                game_year, game_month, game_day = map(int, ymd)
                            else:
                                game_year, game_month, game_day = int(
                                    game_date[:4]), None, None
                        elif game_date and '?' not in game_date[:4]:
                            game_year, game_month, game_day = int(
                                game_date[:4]), None, None
                        else:
                            game_year, game_month, game_day = None, None, None
                    except:
                        game_year, game_month, game_day = None, None, None

                    game_round = tags['Round'] if "Round" in tags else ""

                    white_id = get_id(white, player, PLAYER)
                    black_id = get_id(black, player, PLAYER)

                    result = tags["Result"] if "Result" in tags else ""
                    if result in pgn2Const:
                        result = pgn2Const[result]
                    else:
                        if basename != "eco.pgn":
                            print("Invalid Result tag in game #%s: %s" %
                                  (i + 1, result))
                        continue

                    white_elo = tags['WhiteElo'] if "WhiteElo" in tags else "0"
                    white_elo = int(
                        white_elo) if white_elo and white_elo.isdigit() else 0

                    black_elo = tags['BlackElo'] if "BlackElo" in tags else ""
                    black_elo = int(
                        black_elo) if black_elo and black_elo.isdigit() else 0

                    time_control = tags[
                        "TimeControl"] if "TimeControl" in tags else ""

                    eco = tags["ECO"][:3] if "ECO" in tags else ""

                    fen = tags["FEN"] if "FEN" in tags else ""

                    board_tag = int(tags["Board"]) if "Board" in tags else 0

                    annotator_id = get_id(
                        tags["Annotator"] if "Annotator" in tags else "",
                        annotator, ANNOTATOR)

                    source_id = get_id(orig_filename,
                                       source,
                                       SOURCE,
                                       info=info)

                    self.next_id[GAME] += 1

                    ply_count = tags["PlyCount"] if "PlyCount" in tags else 0

                    offset = base_offset + int(tags["offset"])

                    self.game_data.append({
                        'offset': offset,
                        'offset8': (offset >> 3) << 3,
                        'event_id': event_id,
                        'site_id': site_id,
                        'date_year': game_year,
                        'date_month': game_month,
                        'date_day': game_day,
                        'round': game_round,
                        'white_id': white_id,
                        'black_id': black_id,
                        'result': result,
                        'white_elo': white_elo,
                        'black_elo': black_elo,
                        'ply_count': ply_count,
                        'eco': eco,
                        'fen': fen,
                        'variant': variant,
                        'board': board_tag,
                        'time_control': time_control,
                        'annotator_id': annotator_id,
                        'source_id': source_id,
                    })

                    i += 1

                    if len(self.game_data) >= self.CHUNK:
                        if self.event_data:
                            self.conn.execute(self.ins_event, self.event_data)
                            self.event_data = []

                        if self.site_data:
                            self.conn.execute(self.ins_site, self.site_data)
                            self.site_data = []

                        if self.player_data:
                            self.conn.execute(self.ins_player,
                                              self.player_data)
                            self.player_data = []

                        if self.annotator_data:
                            self.conn.execute(self.ins_annotator,
                                              self.annotator_data)
                            self.annotator_data = []

                        if self.source_data:
                            self.conn.execute(self.ins_source,
                                              self.source_data)
                            self.source_data = []

                        self.conn.execute(self.ins_game, self.game_data)
                        self.game_data = []

                        if progressbar is not None:
                            GLib.idle_add(progressbar.set_fraction,
                                          i / float(all_games))
                            GLib.idle_add(
                                progressbar.set_text,
                                "%s game headers from %s imported" %
                                (i, basename))
                        else:
                            print(pgnfile, i)

                if self.event_data:
                    self.conn.execute(self.ins_event, self.event_data)
                    self.event_data = []

                if self.site_data:
                    self.conn.execute(self.ins_site, self.site_data)
                    self.site_data = []

                if self.player_data:
                    self.conn.execute(self.ins_player, self.player_data)
                    self.player_data = []

                if self.annotator_data:
                    self.conn.execute(self.ins_annotator, self.annotator_data)
                    self.annotator_data = []

                if self.source_data:
                    self.conn.execute(self.ins_source, self.source_data)
                    self.source_data = []

                if self.game_data:
                    self.conn.execute(self.ins_game, self.game_data)
                    self.game_data = []

                if progressbar is not None:
                    GLib.idle_add(progressbar.set_fraction,
                                  i / float(all_games))
                    GLib.idle_add(
                        progressbar.set_text,
                        "%s game headers from %s imported" % (i, basename))
                else:
                    print(pgnfile, i)
                trans.commit()

                if self.append_pgn:
                    # reopen database to write
                    self.db_handle.close()
                    self.db_handle = protosave(self.chessfile.path,
                                               self.append_pgn)

                    print("Append from %s to %s" %
                          (pgnfile, self.chessfile.path))
                    handle.seek(0)
                    self.db_handle.writelines(handle)
                    self.db_handle.close()
                    handle.close()

                    if self.chessfile.scoutfish is not None:
                        # create new .scout from pgnfile we are importing
                        from pychess.Savers.pgn import scoutfish_path
                        args = [
                            scoutfish_path, "make", pgnfile,
                            "%s" % base_offset
                        ]
                        output = subprocess.check_output(
                            args, stderr=subprocess.STDOUT).decode()

                        # append it to our existing one
                        if output.find("Processing...done") > 0:
                            old_scout = self.chessfile.scoutfish.db
                            new_scout = os.path.splitext(pgnfile)[0] + '.scout'

                            with open(old_scout,
                                      "ab") as file1, open(new_scout,
                                                           "rb") as file2:
                                file1.write(file2.read())

                self.chessfile.handle = protoopen(self.chessfile.path)

            except SQLAlchemyError as e:
                trans.rollback()
                print("Importing %s failed! \n%s" % (pgnfile, e))
Example #47
0
    def do_import(self, filename, info=None, progressbar=None):
        self.progressbar = progressbar

        orig_filename = filename
        count_source = self.conn.execute(self.count_source.where(source.c.name == orig_filename)).scalar()
        if count_source > 0:
            print("%s is already imported" % filename)
            return

        # collect new names not in they dict yet
        self.event_data = []
        self.site_data = []
        self.player_data = []
        self.annotator_data = []
        self.source_data = []

        # collect new games and commit them in big chunks for speed
        self.game_data = []
        self.tag_game_data = []

        if filename.startswith("http"):
            filename = download_file(filename, progressbar=progressbar)
            if filename is None:
                return
        else:
            if not os.path.isfile(filename):
                print("Can't open %s" % filename)
                return

        if filename.lower().endswith(".zip") and zipfile.is_zipfile(filename):
            with zipfile.ZipFile(filename, "r") as zf:
                path = os.path.dirname(filename)
                files = [os.path.join(path, f) for f in zf.namelist() if f.lower().endswith(".pgn")]
                zf.extractall(path)
        else:
            files = [filename]

        for pgnfile in files:
            base_offset = self.chessfile.size if self.append_pgn else 0

            basename = os.path.basename(pgnfile)
            if progressbar is not None:
                GLib.idle_add(progressbar.set_text, "Reading %s ..." % basename)
            else:
                print("Reading %s ..." % pgnfile)

            size = os.path.getsize(pgnfile)
            handle = protoopen(pgnfile)

            # estimated game count
            all_games = max(size / 840, 1)

            handle_json = None
            if pgnextractor is not None:
                try:
                    headers_json = os.path.splitext(pgnfile)[0] + ".headers.json"
                    if not os.path.isfile(headers_json):
                        output = subprocess.check_output([pgnextractor, "headers", pgnfile]).decode()
                        for line in output:
                            if line.startswith("Games"):
                                all_games = line.split()[1]
                    handle_json = protoopen(headers_json)
                except subprocess.CalledProcessError:
                    print("pgnextractor failed")

            get_id = self.get_id
            # use transaction to avoid autocommit slowness
            trans = self.conn.begin()
            try:
                i = 0
                for tags in read_games(handle, handle_json):
                    if not tags:
                        print("Empty game #%s" % (i + 1))
                        continue

                    if self.cancel:
                        trans.rollback()
                        return

                    fenstr = tags["FEN"] if "FEN" in tags else ""

                    variant = tags["Variant"] if "Variant" in tags else ""
                    if variant:
                        if "fischer" in variant.lower() or "960" in variant:
                            variant = "Fischerandom"
                        else:
                            variant = variant.lower().capitalize()

                    # Fixes for some non statndard Chess960 .pgn
                    if fenstr and variant == "Fischerandom":
                        parts = fenstr.split()
                        parts[0] = parts[0].replace(".", "/").replace("0", "")
                        if len(parts) == 1:
                            parts.append("w")
                            parts.append("-")
                            parts.append("-")
                        fenstr = " ".join(parts)

                    if variant:
                        if variant not in name2variant:
                            print("Unknown variant: %s" % variant)
                            continue
                        variant = name2variant[variant].variant
                        if variant == NORMALCHESS:
                            # lichess uses tag [Variant "Standard"]
                            variant = 0
                    else:
                        variant = 0

                    white = tags["White"] if "White" in tags else ""
                    black = tags["Black"] if "Black" in tags else ""

                    event_id = get_id(tags["Event"] if "Event" in tags else "", event, EVENT)

                    site_id = get_id(tags["Site"] if "Site" in tags else "", site, SITE)

                    game_date = tags["Date"] if "Date" in tags else ""
                    try:
                        if game_date and '?' not in game_date:
                            ymd = game_date.split('.')
                            if len(ymd) == 3:
                                game_year, game_month, game_day = map(int, ymd)
                            else:
                                game_year, game_month, game_day = int(game_date[:4]), None, None
                        elif game_date and '?' not in game_date[:4]:
                            game_year, game_month, game_day = int(game_date[:4]), None, None
                        else:
                            game_year, game_month, game_day = None, None, None
                    except:
                        game_year, game_month, game_day = None, None, None

                    game_round = tags['Round'] if "Round" in tags else ""

                    white_id = get_id(white, player, PLAYER)
                    black_id = get_id(black, player, PLAYER)

                    result = tags["Result"] if "Result" in tags else ""
                    if result in pgn2Const:
                        result = pgn2Const[result]
                    else:
                        if basename != "eco.pgn":
                            print("Invalid Result tag in game #%s: %s" % (i + 1, result))
                        continue

                    white_elo = tags['WhiteElo'] if "WhiteElo" in tags else "0"
                    white_elo = int(white_elo) if white_elo and white_elo.isdigit() else 0

                    black_elo = tags['BlackElo'] if "BlackElo" in tags else ""
                    black_elo = int(black_elo) if black_elo and black_elo.isdigit() else 0

                    time_control = tags["TimeControl"] if "TimeControl" in tags else ""

                    eco = tags["ECO"][:3] if "ECO" in tags else ""

                    fen = tags["FEN"] if "FEN" in tags else ""

                    board_tag = int(tags["Board"]) if "Board" in tags else 0

                    annotator_id = get_id(tags["Annotator"] if "Annotator" in tags else "", annotator, ANNOTATOR)

                    source_id = get_id(orig_filename, source, SOURCE, info=info)

                    self.next_id[GAME] += 1

                    ply_count = tags["PlyCount"] if "PlyCount" in tags else 0

                    offset = base_offset + int(tags["offset"])

                    self.game_data.append({
                        'offset': offset,
                        'offset8': (offset >> 3) << 3,
                        'event_id': event_id,
                        'site_id': site_id,
                        'date_year': game_year,
                        'date_month': game_month,
                        'date_day': game_day,
                        'round': game_round,
                        'white_id': white_id,
                        'black_id': black_id,
                        'result': result,
                        'white_elo': white_elo,
                        'black_elo': black_elo,
                        'ply_count': ply_count,
                        'eco': eco,
                        'fen': fen,
                        'variant': variant,
                        'board': board_tag,
                        'time_control': time_control,
                        'annotator_id': annotator_id,
                        'source_id': source_id,
                    })

                    i += 1

                    if len(self.game_data) >= self.CHUNK:
                        if self.event_data:
                            self.conn.execute(self.ins_event, self.event_data)
                            self.event_data = []

                        if self.site_data:
                            self.conn.execute(self.ins_site, self.site_data)
                            self.site_data = []

                        if self.player_data:
                            self.conn.execute(self.ins_player,
                                              self.player_data)
                            self.player_data = []

                        if self.annotator_data:
                            self.conn.execute(self.ins_annotator,
                                              self.annotator_data)
                            self.annotator_data = []

                        if self.source_data:
                            self.conn.execute(self.ins_source, self.source_data)
                            self.source_data = []

                        self.conn.execute(self.ins_game, self.game_data)
                        self.game_data = []

                        if progressbar is not None:
                            GLib.idle_add(progressbar.set_fraction, i / float(all_games))
                            GLib.idle_add(progressbar.set_text, "%s game headers from %s imported" % (i, basename))
                        else:
                            print(pgnfile, i)

                if self.event_data:
                    self.conn.execute(self.ins_event, self.event_data)
                    self.event_data = []

                if self.site_data:
                    self.conn.execute(self.ins_site, self.site_data)
                    self.site_data = []

                if self.player_data:
                    self.conn.execute(self.ins_player, self.player_data)
                    self.player_data = []

                if self.annotator_data:
                    self.conn.execute(self.ins_annotator, self.annotator_data)
                    self.annotator_data = []

                if self.source_data:
                    self.conn.execute(self.ins_source, self.source_data)
                    self.source_data = []

                if self.game_data:
                    self.conn.execute(self.ins_game, self.game_data)
                    self.game_data = []

                if progressbar is not None:
                    GLib.idle_add(progressbar.set_fraction, i / float(all_games))
                    GLib.idle_add(progressbar.set_text, "%s game headers from %s imported" % (i, basename))
                else:
                    print(pgnfile, i)
                trans.commit()

                if self.append_pgn:
                    # reopen database to write
                    self.db_handle.close()
                    self.db_handle = protosave(self.chessfile.path, self.append_pgn)

                    print("Append from %s to %s" % (pgnfile, self.chessfile.path))
                    handle.seek(0)
                    self.db_handle.writelines(handle)
                    self.db_handle.close()
                    handle.close()

                    if self.chessfile.scoutfish is not None:
                        # create new .scout from pgnfile we are importing
                        from pychess.Savers.pgn import scoutfish_path
                        args = [scoutfish_path, "make", pgnfile, "%s" % base_offset]
                        output = subprocess.check_output(args, stderr=subprocess.STDOUT).decode()

                        # append it to our existing one
                        if output.find("Processing...done") > 0:
                            old_scout = self.chessfile.scoutfish.db
                            new_scout = os.path.splitext(pgnfile)[0] + '.scout'

                            with open(old_scout, "ab") as file1, open(new_scout, "rb") as file2:
                                file1.write(file2.read())

                self.chessfile.handle = protoopen(self.chessfile.path)

            except SQLAlchemyError as e:
                trans.rollback()
                print("Importing %s failed! \n%s" % (pgnfile, e))