Beispiel #1
0
def initRulesets():
    """exits if user only wanted to see available rulesets"""
    import predefined  # pylint: disable=unused-variable

    if Options.showRulesets or Options.rulesetName:
        from rule import Ruleset

        rulesets = dict((x.name, x) for x in Ruleset.selectableRulesets())
        if Options.showRulesets:
            for name in rulesets:
                kprint(name)
            Internal.db.close()
            sys.exit(0)
        elif Options.rulesetName in rulesets:
            # we have an exact match
            Options.ruleset = rulesets[Options.rulesetName]
        else:
            matches = list(x for x in rulesets if Options.rulesetName in x)
            if len(matches) != 1:
                if len(matches) == 0:
                    msg = "Ruleset %s is unknown" % Options.rulesetName
                else:
                    msg = "Ruleset %s is ambiguous: %s" % (Options.rulesetName, ", ".join(matches))
                Internal.db.close()
                raise SystemExit(msg)
            Options.ruleset = rulesets[matches[0]]
Beispiel #2
0
 def serverChanged(self, dummyText=None):
     """the user selected a different server"""
     records = Query(
         'select player.name from player, passwords '
         'where passwords.url=? and passwords.player = player.id',
         list([self.url])).records
     players = list(x[0] for x in records)
     preferPlayer = Options.player
     if preferPlayer:
         if preferPlayer in players:
             players.remove(preferPlayer)
         players.insert(0, preferPlayer)
     self.cbUser.clear()
     self.cbUser.addItems(players)
     if not self.cbUser.count():
         user = KUser() if os.name == 'nt' else KUser(os.geteuid())
         self.cbUser.addItem(user.fullName() or user.loginName())
     if not preferPlayer:
         userNames = [x[1] for x in self.servers if x[0] == self.url]
         if userNames:
             userIdx = self.cbUser.findText(userNames[0])
             if userIdx >= 0:
                 self.cbUser.setCurrentIndex(userIdx)
     showPW = self.url != Query.localServerName
     self.grid.labelForField(self.edPassword).setVisible(showPW)
     self.edPassword.setVisible(showPW)
     self.grid.labelForField(self.cbRuleset).setVisible(
         not showPW and not Options.ruleset)
     self.cbRuleset.setVisible(not showPW and not Options.ruleset)
     if not showPW:
         self.cbRuleset.clear()
         if Options.ruleset:
             self.cbRuleset.items = [Options.ruleset]
         else:
             self.cbRuleset.items = Ruleset.selectableRulesets(self.url)
Beispiel #3
0
def initRulesets():
    """exits if user only wanted to see available rulesets"""
    import predefined
    predefined.load()
    if Options.showRulesets or Options.rulesetName:
        from rule import Ruleset
        rulesets = dict((x.name, x) for x in Ruleset.selectableRulesets())
        if Options.showRulesets:
            for name in rulesets:
                print(name)
            Internal.db.close()
            sys.exit(0)
        elif Options.rulesetName in rulesets:
            # we have an exact match
            Options.ruleset = rulesets[Options.rulesetName]
        else:
            matches = list(x for x in rulesets if Options.rulesetName in x)
            if len(matches) != 1:
                if len(matches) == 0:
                    msg = 'Ruleset %s is unknown' % Options.rulesetName
                else:
                    msg = 'Ruleset %s is ambiguous: %s' % (Options.rulesetName,
                                                           ', '.join(matches))
                Internal.db.close()
                raise SystemExit(msg)
            Options.ruleset = rulesets[matches[0]]
Beispiel #4
0
 def serverChanged(self, dummyText=None):
     """the user selected a different server"""
     records = Query('select player.name from player, passwords '
             'where passwords.url=? and passwords.player = player.id', list([self.url])).records
     players = list(x[0] for x in records)
     preferPlayer = Options.player
     if preferPlayer:
         if preferPlayer in players:
             players.remove(preferPlayer)
         players.insert(0, preferPlayer)
     self.cbUser.clear()
     self.cbUser.addItems(players)
     if not self.cbUser.count():
         user = KUser() if os.name == 'nt' else KUser(os.geteuid())
         self.cbUser.addItem(user.fullName() or user.loginName())
     if not preferPlayer:
         userNames = [x[1] for x in self.servers if x[0] == self.url]
         if userNames:
             userIdx = self.cbUser.findText(userNames[0])
             if userIdx >= 0:
                 self.cbUser.setCurrentIndex(userIdx)
     showPW = self.url != Query.localServerName
     self.grid.labelForField(self.edPassword).setVisible(showPW)
     self.edPassword.setVisible(showPW)
     self.grid.labelForField(self.cbRuleset).setVisible(not showPW and not Options.ruleset)
     self.cbRuleset.setVisible(not showPW and not Options.ruleset)
     if not showPW:
         self.cbRuleset.clear()
         if Options.ruleset:
             self.cbRuleset.items = [Options.ruleset]
         else:
             self.cbRuleset.items = Ruleset.selectableRulesets(self.url)
Beispiel #5
0
 def loadSuspendedTables(self, user):
     """loads all yet unloaded suspended tables where this
     user is participating. We do not unload them if the
     user logs out, there are filters anyway returning only
     the suspended games for a certain user.
     Never load old autoplay games."""
     query = Query("select distinct g.id, g.starttime, " \
         "g.seed, " \
         "ruleset, s.scoretime " \
         "from game g, player p0, score s," \
         "player p1, player p2, player p3 " \
         "where autoplay=0 " \
         " and p0.id=g.p0 and p1.id=g.p1 " \
         " and p2.id=g.p2 and p3.id=g.p3 " \
         " and (p0.name=? or p1.name=? or p2.name=? or p3.name=?) " \
         " and s.game=g.id" \
         " and g.endtime is null" \
         " and exists(select 1 from score where game=g.id)" \
         " and s.scoretime = (select max(scoretime) from score where game=g.id) limit 10",
         list([user.name, user.name, user.name, user.name]))
     for gameid, starttime, seed, ruleset, suspendTime in query.records:
         playOpen = False # do not continue playing resumed games with open tiles,
                                     # playOpen is for testing purposes only anyway
         if gameid not in self.suspendedTables and starttime:
             # why do we get a record with empty fields when the query should return nothing?
             if gameid not in (x.game.gameid if x.game else None for x in self.tables.values()):
                 table = Table(self, None, Ruleset.cached(ruleset, used=True), playOpen,
                     autoPlay=False, wantedGame=str(seed))
                 table.tableid = 1000 + gameid
                 table.status = m18ncE('table status', 'Suspended') + suspendTime
                 table.preparedGame = RemoteGame.loadFromDB(gameid, None, cacheRuleset=True)
                 self.suspendedTables[gameid] = table
Beispiel #6
0
    def newTable(self,
                 user,
                 ruleset,
                 playOpen,
                 autoPlay,
                 wantedGame,
                 tableId=None):
        """user creates new table and joins it"""
        def gotRuleset(ruleset):
            """now we have the full ruleset definition from the client"""
            Ruleset.cached(
                ruleset).save()  # make it known to the cache and save in db

        if tableId in self.tables:
            return fail(
                srvError(
                    pb.Error,
                    'You want a new table with id=%d but that id is already used for table %s'
                    % (tableId, self.tables[tableId])))
        if Ruleset.hashIsKnown(ruleset):
            return self.__newTable(None, user, ruleset, playOpen, autoPlay,
                                   wantedGame, tableId)
        else:
            return self.callRemote(
                user, 'needRuleset',
                ruleset).addCallback(gotRuleset).addCallback(
                    self.__newTable, user, ruleset, playOpen, autoPlay,
                    wantedGame, tableId)
Beispiel #7
0
 def remote_serverRulesets(hashes):
     """the server will normally send us hashes of rulesets. If
     a hash is not known by us, tell the server so it will send the
     full ruleset definition instead of the hash. It would be even better if
     the server always only sends the hash and the client then says "I do
     not know this ruleset, please send definition", but that would mean
     more changes to the client code"""
     return list(x for x in hashes if not Ruleset.hashIsKnown(x))
Beispiel #8
0
 def remote_serverRulesets(hashes):
     """the server will normally send us hashes of rulesets. If
     a hash is not known by us, tell the server so it will send the
     full ruleset definition instead of the hash. It would be even better if
     the server always only sends the hash and the client then says "I do
     not know this ruleset, please send definition", but that would mean
     more changes to the client code"""
     return list(x for x in hashes if not Ruleset.hashIsKnown(x))
Beispiel #9
0
 def __defineRuleset(self):
     """find out what ruleset to use"""
     if Options.ruleset:
         return Options.ruleset
     elif Internal.autoPlay or bool(Options.host):
         return Ruleset.selectableRulesets()[0]
     else:
         return self.cbRuleset.current
Beispiel #10
0
 def __defineRuleset(self):
     """find out what ruleset to use"""
     if Options.ruleset:
         return Options.ruleset
     elif Internal.autoPlay or bool(Options.host):
         return Ruleset.selectableRulesets()[0]
     else:
         return self.cbRuleset.current
Beispiel #11
0
 def __init__(self, tableid, ruleset, suspendedAt, running, playOpen,
              autoPlay, wantedGame):
     self.tableid = tableid
     if isinstance(ruleset, Ruleset):
         self.ruleset = ruleset
     else:
         self.ruleset = Ruleset.cached(ruleset)
     self.suspendedAt = suspendedAt
     self.running = running
     self.playOpen = playOpen
     self.autoPlay = autoPlay
     self.wantedGame = wantedGame
Beispiel #12
0
 def __init__(self, tableid, ruleset, suspendedAt,
              running, playOpen, autoPlay, wantedGame):
     self.tableid = tableid
     if isinstance(ruleset, Ruleset):
         self.ruleset = ruleset
     else:
         self.ruleset = Ruleset.cached(ruleset)
     self.suspendedAt = suspendedAt
     self.running = running
     self.playOpen = playOpen
     self.autoPlay = autoPlay
     self.wantedGame = wantedGame
Beispiel #13
0
 def remote_newTables(self, tables):
     """update table list"""
     assert len(tables)
     def gotRulesets(result):
         """the server sent us the wanted ruleset definitions"""
         for ruleset in result:
             Ruleset.cached(ruleset).save(copy=True) # make it known to the cache and save in db
         return tables
     rulesetHashes = set(x[1] for x in tables)
     needRulesets = list(x for x in rulesetHashes if not Ruleset.hashIsKnown(x))
     if needRulesets:
         self.callServer('needRulesets', needRulesets).addCallback(gotRulesets).addCallback(self.__receiveTables)
     else:
         self.__receiveTables(tables)
Beispiel #14
0
 def __init__(self, server, owner, rulesetStr, playOpen, autoPlay, wantedGame):
     self.server = server
     self.owner = owner
     if isinstance(rulesetStr, Ruleset):
         self.ruleset = rulesetStr
     else:
         self.ruleset = Ruleset.fromList(rulesetStr)
     self.playOpen = playOpen
     self.autoPlay = autoPlay
     self.wantedGame = wantedGame
     self.tableid = None
     self.users = [owner] if owner else []
     self.preparedGame = None
     self.game = None
     self.status = m18ncE('table status','New')
Beispiel #15
0
 def __init__(self, server=None):
     QDialog.__init__(self, None)
     self.setWindowTitle(m18n('Select a ruleset') + ' - Kajongg')
     self.buttonBox = KDialogButtonBox(self)
     self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
     self.buttonBox.accepted.connect(self.accept)
     self.buttonBox.rejected.connect(self.reject)
     self.cbRuleset = ListComboBox(Ruleset.selectableRulesets(server))
     self.grid = QGridLayout() # our child SelectPlayers needs this
     self.grid.setColumnStretch(0, 1)
     self.grid.setColumnStretch(1, 6)
     vbox = QVBoxLayout(self)
     vbox.addLayout(self.grid)
     vbox.addWidget(self.cbRuleset)
     vbox.addWidget(self.buttonBox)
Beispiel #16
0
 def __init__(self, client, tableid, ruleset, gameid, suspendedAt, running,
              playOpen, autoPlay, wantedGame, playerNames, playersOnline,
              endValues):
     Table.__init__(self, tableid, ruleset, suspendedAt, running, playOpen,
                    autoPlay, wantedGame)
     self.client = client
     self.gameid = gameid
     self.playerNames = playerNames
     self.playersOnline = playersOnline
     self.endValues = endValues
     self.myRuleset = None  # if set, points to an identical local ruleset
     for myRuleset in Ruleset.availableRulesets():
         if myRuleset == self.ruleset:
             self.myRuleset = myRuleset
             break
     self.chatWindow = None
Beispiel #17
0
 def __init__(self, server=None):
     QDialog.__init__(self, None)
     decorateWindow(self, i18n('Select a ruleset'))
     self.buttonBox = KDialogButtonBox(self)
     self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                       | QDialogButtonBox.Ok)
     self.buttonBox.accepted.connect(self.accept)
     self.buttonBox.rejected.connect(self.reject)
     self.cbRuleset = ListComboBox(Ruleset.selectableRulesets(server))
     self.grid = QGridLayout()  # our child SelectPlayers needs this
     self.grid.setColumnStretch(0, 1)
     self.grid.setColumnStretch(1, 6)
     vbox = QVBoxLayout(self)
     vbox.addLayout(self.grid)
     vbox.addWidget(self.cbRuleset)
     vbox.addWidget(self.buttonBox)
Beispiel #18
0
    def loadFromDB(cls, gameid, client=None):
        """load game by game id and return a new Game instance"""
        Internal.logPrefix = 'S' if Internal.isServer else 'C'
        qGame = Query("select p0,p1,p2,p3,ruleset,seed from game where id = %d" % gameid)
        if not qGame.records:
            return None
        rulesetId = qGame.records[0][4] or 1
        ruleset = Ruleset.cached(rulesetId)
        Players.load() # we want to make sure we have the current definitions
        game = cls(Game.__getNames(qGame.records[0]), ruleset, gameid=gameid,
                client=client, wantedGame=qGame.records[0][5])
        qLastHand = Query("select hand,rotated from score where game=%d and hand="
            "(select max(hand) from score where game=%d)" % (gameid, gameid))
        if qLastHand.records:
            (game.handctr, game.rotated) = qLastHand.records[0]

        qScores = Query("select player, wind, balance, won, prevailing from score "
            "where game=%d and hand=%d" % (gameid, game.handctr))
        # default value. If the server saved a score entry but our client did not,
        # we get no record here. Should we try to fix this or exclude such a game from
        # the list of resumable games?
        prevailing = 'E'
        for record in qScores.records:
            playerid = record[0]
            wind = str(record[1])
            player = game.players.byId(playerid)
            if not player:
                logError(
                'game %d inconsistent: player %d missing in game table' % \
                    (gameid, playerid))
            else:
                player.getsPayment(record[2])
                player.wind = wind
            if record[3]:
                game.winner = player
            prevailing = record[4]
        game.roundsFinished = WINDS.index(prevailing)
        game.handctr += 1
        game.notRotated += 1
        game.maybeRotateWinds()
        game.sortPlayers()
        game.wall.decorate()
        return game
Beispiel #19
0
    def remote_newTables(self, tables):
        """update table list"""
        assert len(tables)

        def gotRulesets(result):
            """the server sent us the wanted ruleset definitions"""
            for ruleset in result:
                Ruleset.cached(ruleset).save()  # make it known to the cache and save in db
            return tables
        rulesetHashes = set(x[1] for x in tables)
        needRulesets = list(
            x for x in rulesetHashes if not Ruleset.hashIsKnown(x))
        if needRulesets:
            self.callServer(
                'needRulesets',
                needRulesets).addCallback(
                    gotRulesets).addCallback(
                        self.__receiveTables)
        else:
            self.__receiveTables(tables)
Beispiel #20
0
def initRulesets():
    """exits if user only wanted to see available rulesets"""
    import predefined # pylint: disable=W0612
    if Options.showRulesets or Options.rulesetName:
        from rule import Ruleset
        from util import kprint
        from query import DBHandle
        rulesets = Ruleset.selectableRulesets()
        if Options.showRulesets:
            for ruleset in rulesets:
                kprint(ruleset.name)
            DBHandle.default = None
            sys.exit(0)
        else:
            for ruleset in rulesets:
                if ruleset.name == Options.rulesetName:
                    Options.ruleset = ruleset
                    break
            else:
                DBHandle.default = None
                raise SystemExit('Ruleset %s is unknown' % Options.rulesetName)
Beispiel #21
0
 def __init__(self, client, tableid, ruleset, gameid, suspendedAt, running,
              playOpen, autoPlay, wantedGame, playerNames,
              playersOnline, endValues):
     Table.__init__(
         self,
         tableid,
         ruleset,
         suspendedAt,
         running,
         playOpen,
         autoPlay,
         wantedGame)
     self.client = client
     self.gameid = gameid
     self.playerNames = playerNames
     self.playersOnline = playersOnline
     self.endValues = endValues
     self.myRuleset = None  # if set, points to an identical local ruleset
     for myRuleset in Ruleset.availableRulesets():
         if myRuleset == self.ruleset:
             self.myRuleset = myRuleset
             break
     self.chatWindow = None
Beispiel #22
0
    def loadFromDB(cls, gameid, client=None):
        """load game by game id and return a new Game instance"""
        Internal.logPrefix = 'S' if Internal.isServer else 'C'
        records = Query(
            "select p0,p1,p2,p3,ruleset,seed from game where id = ?",
            (gameid, )).records
        if not records:
            return None
        qGameRecord = records[0]
        rulesetId = qGameRecord[4] or 1
        ruleset = Ruleset.cached(rulesetId)
        Players.load()  # we want to make sure we have the current definitions
        records = Query(
            "select hand,rotated from score where game=? and hand="
            "(select max(hand) from score where game=?)",
            (gameid, gameid)).records
        if records:
            qLastHandRecord = records[0]
        else:
            qLastHandRecord = tuple([0, 0])
        qScoreRecords = Query(
            "select player, wind, balance, won, prevailing from score "
            "where game=? and hand=?", (gameid, qLastHandRecord[0])).records
        if not qScoreRecords:
            # this should normally not happen
            qScoreRecords = list([
                tuple([qGameRecord[wind], wind.char, 0, False, East.char])
                for wind in Wind.all4
            ])
        if len(qScoreRecords) != 4:
            logError('game %d inconsistent: There should be exactly '
                     '4 score records for the last hand' % gameid)

        # after loading SQL, prepare values.

        # default value. If the server saved a score entry but our client
        # did not, we get no record here. Should we try to fix this or
        # exclude such a game from the list of resumable games?
        if len(set(x[4] for x in qScoreRecords)) != 1:
            logError('game %d inconsistent: All score records for the same '
                     'hand must have the same prevailing wind' % gameid)

        players = list(
            tuple([Wind(x[1]), Game.__getName(x[0])]) for x in qScoreRecords)

        # create the game instance.
        game = cls(players,
                   ruleset,
                   gameid=gameid,
                   client=client,
                   wantedGame=qGameRecord[5])
        game.handctr, game.rotated = qLastHandRecord

        for record in qScoreRecords:
            playerid = record[0]
            player = game.players.byId(playerid)
            if not player:
                logError(
                    'game %d inconsistent: player %d missing in game table' %
                    (gameid, playerid))
            else:
                player.getsPayment(record[2])
            if record[3]:
                game.winner = player
        game.roundsFinished = Wind(qScoreRecords[0][4]).__index__()
        game.handctr += 1
        game.notRotated += 1
        game.maybeRotateWinds()
        game.sortPlayers()
        with AnimationSpeed(Speeds.windMarker):
            animateAndDo(game.wall.decorate4)
        return game
Beispiel #23
0
 def compareRuleset(self):
     """compare the ruleset of this table against ours"""
     table = self.selectedTable()
     self.differ = RulesetDiffer(table.ruleset, Ruleset.availableRulesets())
     self.differ.show()
Beispiel #24
0
 def gotRuleset(ruleset):
     """now we have the full ruleset definition from the client"""
     Ruleset.cached(
         ruleset).save()  # make it known to the cache and save in db
Beispiel #25
0
 def compareRuleset(self):
     """compare the ruleset of this table against ours"""
     table = self.selectedTable()
     self.differ = RulesetDiffer(table.ruleset, Ruleset.availableRulesets())
     self.differ.show()
Beispiel #26
0
    def loadFromDB(cls, gameid, client=None):
        """load game by game id and return a new Game instance"""
        Internal.logPrefix = 'S' if Internal.isServer else 'C'
        records = Query(
            "select p0,p1,p2,p3,ruleset,seed from game where id = ?",
            (gameid,)).records
        if not records:
            return None
        qGameRecord = records[0]
        rulesetId = qGameRecord[4] or 1
        ruleset = Ruleset.cached(rulesetId)
        Players.load()  # we want to make sure we have the current definitions
        records = Query(
            "select hand,rotated from score where game=? and hand="
            "(select max(hand) from score where game=?)",
            (gameid, gameid)).records
        if records:
            qLastHandRecord = records[0]
        else:
            qLastHandRecord = tuple([0, 0])
        qScoreRecords = Query(
            "select player, wind, balance, won, prevailing from score "
            "where game=? and hand=?",
            (gameid, qLastHandRecord[0])).records
        if not qScoreRecords:
            # this should normally not happen
            qScoreRecords = list([
                tuple([qGameRecord[wind], wind.char, 0, False, East.char])
                for wind in Wind.all4])
        if len(qScoreRecords) != 4:
            logError(u'game %d inconsistent: There should be exactly '
                     '4 score records for the last hand' % gameid)

        # after loading SQL, prepare values.

        # default value. If the server saved a score entry but our client
        # did not, we get no record here. Should we try to fix this or
        # exclude such a game from the list of resumable games?
        if len(set(x[4] for x in qScoreRecords)) != 1:
            logError(u'game %d inconsistent: All score records for the same '
                     'hand must have the same prevailing wind' % gameid)

        players = list(tuple([Wind(x[1]), Game.__getName(x[0])])
                       for x in qScoreRecords)

        # create the game instance.
        game = cls(players, ruleset, gameid=gameid, client=client,
                   wantedGame=qGameRecord[5])
        game.handctr, game.rotated = qLastHandRecord

        for record in qScoreRecords:
            playerid = record[0]
            player = game.players.byId(playerid)
            if not player:
                logError(
                    u'game %d inconsistent: player %d missing in game table' %
                    (gameid, playerid))
            else:
                player.getsPayment(record[2])
            if record[3]:
                game.winner = player
        game.roundsFinished = Wind(qScoreRecords[0][4]).__index__()
        game.handctr += 1
        game.notRotated += 1
        game.maybeRotateWinds()
        game.sortPlayers()
        game.wall.decorate()
        return game
Beispiel #27
0
 def remote_needRuleset(ruleset):
     """server only knows hash, needs full definition"""
     result = Ruleset.cached(ruleset)
     assert result and result.hash == ruleset
     return result.toList()
Beispiel #28
0
 def gotRulesets(result):
     """the server sent us the wanted ruleset definitions"""
     for ruleset in result:
         Ruleset.cached(ruleset).save(copy=True) # make it known to the cache and save in db
     return tables
Beispiel #29
0
 def gotRulesets(result):
     """the server sent us the wanted ruleset definitions"""
     for ruleset in result:
         Ruleset.cached(ruleset).save()  # make it known to the cache and save in db
     return tables
Beispiel #30
0
 def remote_needRuleset(ruleset):
     """server only knows hash, needs full definition"""
     result = Ruleset.cached(ruleset)
     assert result and result.hash == ruleset
     return result.toList()
Beispiel #31
0
 def refresh(self):
     """retranslate and reload rulesets"""
     self.retranslateUi()
     self.rulesetView.rulesets = Ruleset.availableRulesets()
Beispiel #32
0
 def refresh(self):
     """retranslate and reload rulesets"""
     self.retranslateUi()
     self.rulesetView.rulesets = Ruleset.availableRulesets()