GNOME Bugzilla – Bug 484691
Sudoku should autosave games and should not store puzzles in memory
Last modified: 2008-04-06 21:35:34 UTC
As bug 418834 and 393243 point out, pickles are a problem for sudoku. Generated puzzles have been not working properly (bug 462754). Automatic saving and resuming of puzzles has been disabled (469085) to try to reduce the number of bugs related to this weakness. I propose a major overhaul of the sudoku code doing the following: 1. Store generated puzzles in a plain text format. 2. Store saved games as one-pickle-per-file, so that we lose at most one game at a time due to corruption. Also, write these files during runtime, so that a crash doesn't result in as much last data. (Note -- we could also store these things in a database, but one-pickle-per-file requires minimal changes to code and delivers much more stability). The work I've done toward this would also overhaul the new-game/open-game interface for greater simplicity -- see 484690
Created attachment 96907 [details] [review] Patch implementing plan described in this bug and in bug 484690 Not sure how to do a changelog for a patch -- here's the changelog for this patch. * gnome-sudoku/src/lib/sudoku_maker.py Keep generated puzzles in plain text files, with one file per difficulty level, rather than in one giant pickle. Remove "names" (what did the names mean anyway?). Organize module into two sections -- "methods for accessing puzzles we've created" and "methods for creating new puzzles". The methods for accessing have changed substantially (and changed names), resulting in changes throughout gnome-sudoku. The methods for generating puzzles have changed only slightly, with writes to files replacing holding things in memory, but the method names etc. staying the same. Remove SudokuTracker from this module to the module saver, reflecting it's new role (saving games rather than holding all games ever played in memory). * gnome-sudoku/src/lib/gnome_sudoku.py inactivate_new_game_etc - decorator now returns whatever the wrapped function returns. disable "Save", "Open", "ByHand", "HighScore" menu items. Remove "Clear" and "Clear Notes" from toolbar. Add gconf key auto_save_interval (default to 60) -- interval between autosaves in seconds. UI.__init__ - reorganize into various setup_* functions for greater clarity. New methods are: setup_gui, setup_main_window, setup_actions, setup_undo, setup_color, setup_autosave, setup_main_boxes, setup_by_hand_area, setup_toggles UI.start_worker_thread - make use of new sudoku_maker convenience method n_puzzles to count puzzles. UI.you_win_callback - disable high scores and display simple dialog. UI.new_cb - use new "select game" interface (for opening game or new game). UI.quit_cb - save unfinished puzzle on quit UI.save_game - use new saver.sudoku_tracker saving UI.autosave - method to autosave, called on a gobject.timeout GamesTracker - remove stub class that has no use. * gnome-sudoku/src/lib/sudoku_thumber.py Create module to draw pretty thumbnails of sudoku. * gnome-sudoku/src/lib/colors.py color_hex_to_float - Add a convenience method to allow us to turn html colors into gtk color tuples. This makes it more convenient to follow tango guidelines from their website. * gnome-sudoku/src/lib/gtk_goodies/dialog_extras.py UserCancelledError exception type for convient catching of user cancellations of dialogs. * gnome-sudoku/src/lib/game_selector.py _compareGameNames - Deleted - no need for this function any more. color_from_difficulty - Added function to conveniently generate color-coding for difficulties for out gameselector thumbnails. NewOrSavedGameSelector - Create new Selector to allow user to select either a new or used game in one, simple package. This will replace the NewGameSelector and the OldGameSelector NewGameSelector - delete OldGameSelector - delete HighScores - delete GamePrinter - Simplified. No longer includes a list of all puzzles; nor does it include difficulty sliders. Instead, we have a simpler, checkbox-style interface. * gnome-sudoku/src/lib/sudoku.py is_valid_puzzle - convenience method to check the validity of a puzzle (i.e. crash-proofness). Loaders can use this to avoid showing users tracebacks when files have been corrupted. sudoku_grid_from_string - convenience method to go from puzzle string to grid quickly (this had been included in a SudokuDisplay class but should be here as it is more generally useful. DifficultyRating - Add dictionaries to make it easy to go from a category description ('easy') to an i18n label (_('Easy') to a range (0.0-0.35). DifficultyRating.value_category - Add convenience method to return the name of the "level" (easy, hard, etc) get_difficulty_category_name and get_difficulty_category - convenience methods for going from float difficulty values to category name. * gnome-sudoku/src/lib/timer.py format_time - Add "friendly" option which makes short, user-friendly time strings. format_time_compact - Alternate method of showing user a time in 00:00:00 format format_friendly_date - Format date/times with nice words like "2 minutes ago", "Yesterday", etc. if the date is recent. * gnome-sudoku/src/lib/saver.py SudokuTracker - move SudokuTracker class here, since it's main purpose is now to deal with saved games. Games are saved into a ~/.sudoku/ directory. Finished games are moved into a finished folder (in case we ever want to reimplement high scores). * gnome-sudoku/src/lib/sudoku_generator_gui.py Update to use new sudoku_maker. Counting puzzles got substantially simpler. * gnome-sudoku/data/easy, medium, hard, very_hard - New starter puzzles in new format. * gnome-sudoku/glade/print_games.glade - New slider-less, simplified print dialog. * gnome-sudoku/glade/select_game.glade - New open-and-new dialog
Removing "Gnome Target" tag for this bugreport, because it doesn't block a GNOME release. See the description for "Gnome Target": "This field describes the version of GNOME that a bug should be fixed in. This is not a 'it would be nice' field, it is a 'Gnome releases may need to be delayed for this issue' field. It is intended for use by senior-ish bug triagers and the release team. We allow others to nominate 'showstopper' bugs by setting this field, but bugsquadders and release team members review such bugs and unmark ones where the change is not warranted."
Take a look at bug #409172, where I believe that the crash in Sudoku was caused by a race condition. When re-inplementing saving and loading for Sudoku, you should very carefully make sure that the saving and loading is thread safe if multiple threads can execute the loading/saving functions.
Andreas, Thanks for the heads up. In the new system, we append puzzles to a file rather than keeping them in memory. I'm not sure what happens if two processes try to write to a file at the same time -- I could set up a lock system to prevent this. At any rate, it should be better than the race condition described in bug 409172.
Yes, if several threads can access saving/loading, then mutexes should be used to protect the critical sections of the code.
I committed the patch for you now Tom
One bug I've noticed with Sudoku now is that if you have a saved game which is easy and start a new game, the easy puzzle will be the same one you have saved. This obviously applies to any of the levels. This means that you can only really have one puzzle on each level on the go at any time. I'd open a new bug, but I thought it would be better here.
Hmm -- that's definitely a bug :) I believe it's supposed to check a list of games played before grabbing a new game -- maybe I forgot to add saved games to that list.
Bruce -- indeed saved games weren't included on the list of games to exclude when grabbing a new game. I'm committing the fix now to svn.
Thanks for that. Surely this bug could be closed now, or is there something which has not been done yet?
Saying as this bug hasn't been closed, it would be nice if the wee mini-puzzles could scale to fill the space in the window.