From: <umg...@us...> - 2007-08-31 13:45:22
|
Revision: 500 http://pybridge.svn.sourceforge.net/pybridge/?rev=500&view=rev Author: umgangee Date: 2007-08-31 06:45:20 -0700 (Fri, 31 Aug 2007) Log Message: ----------- Refactor rubber scoring, to facilitate rubber scoresheet display. Modified Paths: -------------- trunk/pybridge/pybridge/games/bridge/game.py trunk/pybridge/pybridge/games/bridge/result.py trunk/pybridge/pybridge/games/bridge/ui/window_bridgetable.py Added Paths: ----------- trunk/pybridge/pybridge/games/bridge/ui/window_scoresheet.py Modified: trunk/pybridge/pybridge/games/bridge/game.py =================================================================== --- trunk/pybridge/pybridge/games/bridge/game.py 2007-08-03 18:42:14 UTC (rev 499) +++ trunk/pybridge/pybridge/games/bridge/game.py 2007-08-31 13:45:20 UTC (rev 500) @@ -97,14 +97,14 @@ if len(self.rubbers) == 0 or self.rubbers[-1].winner: self.board['vuln'] = Vulnerable.None # First round, new rubber. else: - games = self.rubbers[-1].games - if len(games[(Direction.North, Direction.South)]) > 0: - if len(games[(Direction.East, Direction.West)]) > 0: + pairs = [pair for game, pair in self.rubbers[-1].games] + if pairs.count((Direction.North, Direction.South)) > 0: + if pairs.count((Direction.East, Direction.West)) > 0: self.board['vuln'] = Vulnerable.All else: self.board['vuln'] = Vulnerable.NorthSouth else: - if len(games[(Direction.East, Direction.West)]) > 0: + if pairs.count((Direction.East, Direction.West)) > 0: self.board['vuln'] = Vulnerable.EastWest else: self.board['vuln'] = Vulnerable.None Modified: trunk/pybridge/pybridge/games/bridge/result.py =================================================================== --- trunk/pybridge/pybridge/games/bridge/result.py 2007-08-03 18:42:14 UTC (rev 499) +++ trunk/pybridge/pybridge/games/bridge/result.py 2007-08-31 13:45:20 UTC (rev 500) @@ -233,40 +233,41 @@ def _getGames(self): - """Returns, for each pair, a list of completed 'games' won by the pair - in this rubber. + """Returns a list of completed (ie. won) 'games' in this rubber, in the + order of their completion. - A game is represented as the list of consecutive results in this rubber, - with below-the-line scores that count towards the game. + A game is represented as a list of consecutive results from this rubber, + coupled with the identifier of the scoring pair. """ - gamesNS, gamesEW = [], [] + games = [] - game = [] - belowNS, belowEW = 0, 0 # Cumulative totals for results. + thisgame = [] + belowNS, belowEW = 0, 0 # Cumulative totals for results in this game. + for result in self: - game.append(result) - + thisgame.append(result) if result.contract.declarer in (Direction.North, Direction.South): belowNS += result.score[1] if belowNS >= 100: - gamesNS.append(game) + games.append((thisgame, (Direction.North, Direction.South))) else: belowEW += result.score[1] if belowEW >= 100: - gamesEW.append(game) + games.append((thisgame, (Direction.East, Direction.West))) - # If either accumulated total exceeds 100, proceed to next game. - if belowNS >= 100 or belowEW >= 100: - game = [] - belowNS, belowEW = 0, 0 + # If either total for this game exceeds 100, proceed to next game. + if belowNS >= 100 or belowEW >= 100: + thisgame = [] + belowNS, belowEW = 0, 0 # Reset accumulators. - return {(Direction.North, Direction.South): gamesNS, - (Direction.East, Direction.West): gamesEW} + return games def _getWinner(self): """The rubber is won by the pair which have completed two games.""" - for pair, games in self.games.items(): - if len(games) >= 2: + pairs = [pair for game, pair in self.games] + + for pair in ((Direction.North, Direction.South), (Direction.East, Direction.West)): + if pairs.count(pair) >= 2: return pair Modified: trunk/pybridge/pybridge/games/bridge/ui/window_bridgetable.py =================================================================== --- trunk/pybridge/pybridge/games/bridge/ui/window_bridgetable.py 2007-08-03 18:42:14 UTC (rev 499) +++ trunk/pybridge/pybridge/games/bridge/ui/window_bridgetable.py 2007-08-31 13:45:20 UTC (rev 500) @@ -29,6 +29,7 @@ from pybridge.ui.window_gametable import WindowGameTable from window_bidbox import WindowBidbox +from window_scoresheet import ScoreSheet class BiddingView(gtk.TreeView): @@ -83,41 +84,6 @@ -class ScoreView(gtk.TreeView): - """A display of contracts bid, their results and their scores.""" - - - def __init__(self): - gtk.TreeView.__init__(self) - self.set_rules_hint(True) - - self.store = gtk.ListStore(str, str, str, str) - self.set_model(self.store) - self.clear = self.store.clear - renderer = gtk.CellRendererText() - - for index, title in enumerate([_('Contract'), _('Made'), _('N/S'), _('E/W')]): - column = gtk.TreeViewColumn(title, renderer, markup=index) - self.append_column(column) - - - def add_score(self, game): - declarerWon, defenceWon = game.play.wonTrickCount() - score = game.result.score - - textContract = render_contract(game.contract) - textMade = str(declarerWon) - if game.contract.declarer in (Direction.North, Direction.South) and score > 0 \ - or game.contract.declarer in (Direction.East, Direction.West) and score < 0: - textNS, textEW = str(abs(score)), '' - else: - textNS, textEW = '', str(abs(score)) - - self.store.prepend([textContract, textMade, textNS, textEW]) - - - - class BridgeDashboard(gtk.VBox): """An at-a-glance display of the state of a bridge game.""" @@ -242,7 +208,7 @@ exp = gtk.Expander(_('Bidding')) exp.set_expanded(True) exp.add(frame) - self.sidebar.pack_start(exp) + self.sidebar.pack_start(exp, expand=True) self.trickarea = TrickArea(positions=Direction) self.trickarea.set_size_request(-1, 180) @@ -253,10 +219,10 @@ exp.add(frame) self.sidebar.pack_start(exp, expand=False) - self.scoreview = ScoreView() + self.scoresheet = ScoreSheet() sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - sw.add(self.scoreview) + sw.add(self.scoresheet) frame = gtk.Frame() frame.add(sw) exp = gtk.Expander(_('Score Sheet')) @@ -265,11 +231,6 @@ self.sidebar.pack_start(exp, expand=False) - def errback(self, failure): - print "Error: %s" % failure.getErrorMessage() - print failure.getBriefTraceback() - - def setTable(self, table): """Changes display to match the table specified. @@ -337,12 +298,11 @@ # Determine and display score in dialog box and score sheet. if self.table.game.contract: - self.scoreview.add_score(self.table.game) + self.scoresheet.add_result(self.table.game.result) tricksMade = self.table.game.result.tricksMade tricksRequired = self.table.game.contract.bid.level.index + 7 offset = tricksMade - tricksRequired - score = self.table.game.result.score fields = {'contract': render_contract(self.table.game.contract), 'offset': abs(offset)} @@ -359,6 +319,10 @@ else: resultText = _('Contract %(contract)s made exactly.') % fields + score = self.table.game.result.score + if isinstance(score, tuple): # Rubber scoring. + score = sum(score) # TODO: display above, below separately. + pair = (score >= 0 and _('declarer')) or _('defence') scoreText = _('Score %(points)s points for %(pair)s.') % {'points': abs(score), 'pair': pair} Added: trunk/pybridge/pybridge/games/bridge/ui/window_scoresheet.py =================================================================== --- trunk/pybridge/pybridge/games/bridge/ui/window_scoresheet.py (rev 0) +++ trunk/pybridge/pybridge/games/bridge/ui/window_scoresheet.py 2007-08-31 13:45:20 UTC (rev 500) @@ -0,0 +1,140 @@ +# PyBridge -- online contract bridge made easy. +# Copyright (C) 2004-2007 PyBridge Project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +import gtk + +from pybridge.games.bridge.result import DuplicateResult, RubberResult +from pybridge.games.bridge.symbols import Direction + +from pybridge.ui.eventhandler import SimpleEventHandler +import pybridge.ui.vocabulary as voc + + +class ScoreSheet(gtk.TreeView): + """A score sheet widget, which presents GameResult information.""" + + # TODO: display total scores for N/S and E/W. + + + def __init__(self): + gtk.TreeView.__init__(self) + self.set_rules_hint(True) + + self.store = gtk.ListStore(int, str, str, str, str) + self.set_model(self.store) + + renderer = gtk.CellRendererText() + for index, title in enumerate([_('Board'), _('Contract'), _('Made'), _('N/S'), _('E/W')]): + column = gtk.TreeViewColumn(title, renderer, markup=index) + self.append_column(column) + + + def add_result(self, result): + if isinstance(result, RubberResult): + # Rubber results are split into 'above' and 'below' scores. + score = sum(result.score) + else: + score = result.score + + if result.contract is None: # Bidding passed out. + row = (result.board['num'], _('Passed out'), '-', '-', '', '') + + else: + if result.contract.declarer in (Direction.North, Direction.South) and score > 0 \ + or result.contract.declarer in (Direction.East, Direction.West) and score < 0: + scoreNS, scoreEW = str(abs(score)), '' + else: + scoreNS, scoreEW = '', str(abs(score)) + + row = (result.board['num'], voc.render_contract(result.contract), + #voc.DIRECTION_NAMES[result.contract.declarer], + str(result.tricksMade), scoreNS, scoreEW) + + self.store.append(row) + + + + +class RubberScoreSheet(gtk.TreeView): + """A score sheet widget, which presents a Rubber object.""" + + + def __init__(self): + gtk.TreeView.__init__(self) + self.set_rules_hint(True) + self.set_row_separator_func(self._row_separator) + + # Set bool field in a row to display as separator. + self.store = gtk.ListStore(str, str, bool) + self.set_model(self.store) + + renderer = gtk.CellRendererText() + for index, title in enumerate([_('N/S'), _('E/W')]): + column = gtk.TreeViewColumn(title, renderer, markup=index) + self.append_column(column) + + + def set_rubber(self, rubber): + self.store.clear() + self.store.append(('', '', True)) # The initial dividing line. + + for game, pair in rubber.games: + #aboveiters, belowiters = [], [] + for result in rubber: + above, below = result.score + if result.contract.declarer in (Direction.North, Direction.South) and below > 0 \ + or result.contract.declarer in (Direction.East, Direction.West) and score < 0: + self.store.prepend((str(above), '', False)) + self.store.append((str(below), '', False)) + else: + self.store.prepend(('', str(above), False)) + self.store.append(('', str(below), False)) + + + def _row_separator(self, model, iter, data): + print model, iter, data + return True + + + + +class WindowScoreSheet(object): + """""" + + + def __init__(self, parent=None): + self.window = gtk.Window() + if parent: + self.window.set_transient_for(parent.window) + self.window.set_title(_('Score Sheet')) + self.window.connect('delete_event', self.on_delete_event) + #self.window.set_resizable(False) + + self.eventHandler = SimpleEventHandler(self) + self.table = None + + + def tearDown(self): + pass + + + + def on_delete_event(self, widget, *args): + # TODO: call wm.close(self) + return True # Stops window deletion taking place. + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |