[gnome-games/sudoku-tube] Properly notify each other when puzzle finished
- From: Zhang Sen <zhangsen src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-games/sudoku-tube] Properly notify each other when puzzle finished
- Date: Fri, 7 Aug 2009 14:06:24 +0000 (UTC)
commit ba033fc668b1ae180455c2a2a3f349359644c1e8
Author: Zhang Sen <zh jesse gmail com>
Date: Fri Aug 7 19:50:02 2009 +0800
Properly notify each other when puzzle finished
Still many glitches
gnome-sudoku/src/lib/main.py | 110 +++++++++++++++++++++++++++---------
gnome-sudoku/src/lib/networking.py | 27 ++++++---
gnome-sudoku/src/lib/view.py | 1 +
3 files changed, 102 insertions(+), 36 deletions(-)
---
diff --git a/gnome-sudoku/src/lib/main.py b/gnome-sudoku/src/lib/main.py
index a10d91b..8d330f8 100644
--- a/gnome-sudoku/src/lib/main.py
+++ b/gnome-sudoku/src/lib/main.py
@@ -56,7 +56,8 @@ class UI (gconf_wrapper.GConfWrapper):
}
_tube_service = 'org.gnome.Sudoku'
_view_obj_path = "/SideView"
- _virgin_puzzle_obj_path = "/virgin_puzzle"
+ _initiator_obj_path = "/Initiator"
+ _receiver_obj_path = "/Receiver"
def __init__ (self):
gconf_wrapper.GConfWrapper.__init__(self,
@@ -68,6 +69,7 @@ class UI (gconf_wrapper.GConfWrapper):
self._main_grid_vew = None
self._history_manager = None
self._tube = None
+ self._is_initiator = None
self._is_waiting_for_response = None # this should be extraced out
self.setup_gui()
@@ -95,7 +97,6 @@ class UI (gconf_wrapper.GConfWrapper):
if game:
self._open_game(*game)
- self._post_open_setup()
else:
logger.error("can't open game")
self.quit_cb()
@@ -139,7 +140,7 @@ class UI (gconf_wrapper.GConfWrapper):
else:
logger.fatal("shouldn't be here")
- self._main_grid_vew.connect_to_notes_model(self._notes_model)
+ self._post_open_setup()
def _open_saved_game(self, jar):
virgin, in_prog = jar["game"].split('\n')
@@ -176,6 +177,7 @@ class UI (gconf_wrapper.GConfWrapper):
"""Properly do the setup after entering game
Like show highlight, update hints, start timer, etc."""
+ self._main_grid_vew.connect_to_notes_model(self._notes_model)
self._main_model.connect('puzzle-finished', self.you_win_callback)
self._calc_difficulty()
self.setup_toggles()
@@ -394,8 +396,52 @@ class UI (gconf_wrapper.GConfWrapper):
self.sudoku_tracker.finish_game(self._jar_game())
self.dancer = dancer.GridDancer(self._main_grid_vew, self._main_model)
self.dancer.start_dancing()
+
+ if not self._tube: # local game
+ label = self._build_report_label()
+ else:
+ if self._negotiate_result():
+ label = "You WIN"
+ else:
+ return
+
dialog_extras.show_message(_("You win!"), label = _("You win!"),
- sublabel=self._build_report_label())
+ sublabel=label)
+
+ def _negotiate_result(self):
+ def reply_handler(self, *args):
+ print 'acknowledge reply', args
+ def error_handler(self, error):
+ print 'acknowledge error:', error
+
+ if self._is_initiator:
+ i_win = True
+ logger.info('signal receiver that they fail')
+ self._peer.acknowledge_win(
+ reply_handler=reply_handler,
+ error_handler=error_handler)
+ else:
+ assert self._peer is not None
+ if not self._peer.has_won():
+ i_win = True
+ logger.info('signal initiator that they fail')
+ self._peer.acknowledge_win(
+ reply_handler=reply_handler,
+ error_handler=error_handler)
+ # else do nothing; wait for initatior to tell us that we fail
+ return i_win
+
+ def fail_network_game(self):
+ dialog = gtk.Dialog("You fail",
+ self.w,
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
+ (gtk.STOCK_OK, gtk.RESPONSE_OK))
+ label = gtk.Label("you fail")
+ label.show()
+ dialog.vbox.pack_start(label)
+ dialog.connect("response", self._stop_network_game)
+ dialog.run()
+ dialog.destroy()
def new_cb (self, *args):
if self._close_current_game():
@@ -407,6 +453,8 @@ class UI (gconf_wrapper.GConfWrapper):
self._open_game(choice[0], choice[1])
def _new_with_contact_cb(self, action):
+ assert self._is_initiator is None
+ self._is_initiator = True
choice = contact_selector.contact_selector_run(self.w)
if choice:
conn, handle, contact = choice
@@ -442,6 +490,7 @@ class UI (gconf_wrapper.GConfWrapper):
def _offer_fail_cb(self, offer, reason):
self._is_waiting_for_response = False
+ self._is_initiator = None
# clear label and button
vbox = self._wait_dialog.vbox
vbox.remove(vbox.get_children()[0])
@@ -459,15 +508,23 @@ class UI (gconf_wrapper.GConfWrapper):
def _tube_received_cb(self, bus, tube):
"""Called when we receive a tube"""
+
+ def error_cb(exception):
+ print 'get puzzle error:', exception
+
+ assert self._is_initiator is None
+ self._is_initiator = False
self._bus = bus
self._tube = tube
self._tube[tp_tube.CHANNEL_INTERFACE].connect_to_signal(
'Closed', self._tube_closed_cb)
- virgin_puzzle = bus.get_object(object_path=self._virgin_puzzle_obj_path)
- virgin_puzzle.get_puzzle(
+
+ myself = networking.Peer(bus, self._receiver_obj_path, self)
+ self._peer = bus.get_object(object_path=self._initiator_obj_path)
+ self._peer.get_puzzle(
dbus_interface="org.gnome.Sudoku.view",
reply_handler=self._got_remote_puzzle_cb,
- error_handler=self._error_cb)
+ error_handler=error_cb)
def _got_remote_puzzle_cb(self, puzzle):
logger.info("got puzzle: %s; type: %s" % (puzzle, type(puzzle)))
@@ -475,11 +532,8 @@ class UI (gconf_wrapper.GConfWrapper):
assert len(puzzle) == 81
self._close_current_game()
self._open_game(game_selector.NewOrSavedGameSelector.NEW_GAME, puzzle)
- self._init_side_view_display(puzzle)
- self._tube_open_cb(self._bus, is_initiator=False)
-
- def _error_cb(self, exception):
- print 'error', exception
+ self._init_side_view_display()
+ self._negotiate_sideview(self._bus)
def _tube_offered_cb(self, offer, bus, tube):
"""Called when the peer accepts our tube"""
@@ -492,24 +546,27 @@ class UI (gconf_wrapper.GConfWrapper):
# string. FIXME
self._auto_open_game(check_saved=False)
- puzzle = self._puzzle.replace(" ", "") # delete all spaces
- print 'exporting', puzzle
- virgin_puzzle = networking.VirginGameString(bus,
- self._virgin_puzzle_obj_path, puzzle)
- self._init_side_view_display(puzzle)
- self._tube_open_cb(bus, is_initiator=True)
+ myself = networking.Peer(bus, self._initiator_obj_path, self)
+ self._peer = bus.get_object(object_path=self._receiver_obj_path)
+
+ self._init_side_view_display()
+ self._negotiate_sideview(bus)
- def _init_side_view_display(self, puzzle):
+ def get_puzzle(self):
+ return self._puzzle.replace(" ", "") # delete all spaces
+
+ def _init_side_view_display(self):
+ puzzle = self.get_puzzle()
for x in range(9):
for y in range(9):
val = int(puzzle[9 * y + x])
if val:
self._side_grid_vew.set_value(x, y, val)
- def _tube_open_cb(self, bus, is_initiator):
+ def _negotiate_sideview(self, bus):
receiver_view = self._view_obj_path + "/receiver"
initiator_view = self._view_obj_path + "/initiator"
- if is_initiator:
+ if self._is_initiator:
our_obj_path, peer_obj_path = initiator_view, receiver_view
else:
our_obj_path, peer_obj_path = receiver_view, initiator_view
@@ -520,12 +577,12 @@ class UI (gconf_wrapper.GConfWrapper):
logger.info("exported side-view on dbus")
# Then fetch our peer's side-grid-view
- remote_view_proxy = bus.get_object(object_path=peer_obj_path)
+ _remote_view_proxy = bus.get_object(object_path=peer_obj_path)
logger.info("got a remote view which we can manipulate")
# we issue command on remote_view_handler, which will communicate with
# remote_view
- view_handler = networking.RemoteViewHandler(remote_view_proxy)
- view_handler.connect_to_model(self._main_model)
+ view_handler = networking.RemoteViewHandler(_remote_view_proxy)
+ self._main_model.add_observer(view_handler)
self._side_grid_vew.show()
@@ -562,12 +619,13 @@ class UI (gconf_wrapper.GConfWrapper):
self.gconf['height'] = event.height
def _tube_closed_cb(self):
- logger.info("tube has been closed")
+ self._is_initiator = None
self._side_grid_vew.reset()
self._side_grid_vew.hide()
self._tube = None
+ logger.info("tube has been closed")
- def _stop_network_game(self):
+ def _stop_network_game(self, *args):
logger.info("close tube-channel")
self._tube[tp_tube.CHANNEL_INTERFACE].Close()
self._side_grid_vew.reset()
diff --git a/gnome-sudoku/src/lib/networking.py b/gnome-sudoku/src/lib/networking.py
index 7e19f78..0074d89 100644
--- a/gnome-sudoku/src/lib/networking.py
+++ b/gnome-sudoku/src/lib/networking.py
@@ -8,20 +8,30 @@ logger = logging.getLogger("main.network")
view_interface = "org.gnome.Sudoku.view"
-class VirginGameString(dbus.service.Object):
- """Receiver use this to get the game
- """
+class Peer(dbus.service.Object):
- def __init__(self, bus, obj_path, puzzle):
- """puzzle should be a string
+ def __init__(self, bus, obj_path, game):
+ """game is the UI in main.py, for which we should get a better name
"""
dbus.service.Object.__init__(self, bus, obj_path)
- self._puzzle = puzzle
+ self._game = game
@dbus.service.method(dbus_interface=view_interface,
in_signature="", out_signature="s")
def get_puzzle(self):
- return self._puzzle
+ return self._game.get_puzzle()
+
+ @dbus.service.method(dbus_interface=view_interface,
+ in_signature="", out_signature="b")
+ def has_won(self):
+ return self._game.won
+
+ @dbus.service.method(dbus_interface=view_interface,
+ in_signature="", out_signature="")
+ def acknowledge_win(self):
+ """Used by the peer to tell us that we fail"""
+ logger.info('our peer says we fail')
+ self._game.fail_network_game()
class SideViewProxy(dbus.service.Object):
"""A dbus object, which exports a sudoku game's side-view on dbus
@@ -77,9 +87,6 @@ class RemoteViewHandler:
def puzzle_finished_cb(self):
self._remote_proxy.puzzle_finished_cb()
- def connect_to_model(self, model):
- model.add_observer(self)
-
def _handle_reply(self):
pass
diff --git a/gnome-sudoku/src/lib/view.py b/gnome-sudoku/src/lib/view.py
index 8003b4f..de6e669 100644
--- a/gnome-sudoku/src/lib/view.py
+++ b/gnome-sudoku/src/lib/view.py
@@ -428,3 +428,4 @@ class SudokuSideView(SudokuNumberGrid):
for x in range(self.group_size):
for y in range(self.group_size):
self.set_value(x, y, 0)
+ self.set_color(x, y, None)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]