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]]
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)
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]]
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)
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
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)
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))
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
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
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)
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')
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)
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
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)
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
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)
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)
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
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
def compareRuleset(self): """compare the ruleset of this table against ours""" table = self.selectedTable() self.differ = RulesetDiffer(table.ruleset, Ruleset.availableRulesets()) self.differ.show()
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
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
def remote_needRuleset(ruleset): """server only knows hash, needs full definition""" result = Ruleset.cached(ruleset) assert result and result.hash == ruleset return result.toList()
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
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
def refresh(self): """retranslate and reload rulesets""" self.retranslateUi() self.rulesetView.rulesets = Ruleset.availableRulesets()