gnome-games r8268 - branches/gnome-2-24/gnome-sudoku/src/lib
- From: rancell svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-games r8268 - branches/gnome-2-24/gnome-sudoku/src/lib
- Date: Thu, 6 Nov 2008 12:44:08 +0000 (UTC)
Author: rancell
Date: Thu Nov 6 12:44:08 2008
New Revision: 8268
URL: http://svn.gnome.org/viewvc/gnome-games?rev=8268&view=rev
Log:
Make Sudo generator resiliant to file IO failures (Bug #486385, #421487)
Modified:
branches/gnome-2-24/gnome-sudoku/src/lib/sudoku_maker.py
Modified: branches/gnome-2-24/gnome-sudoku/src/lib/sudoku_maker.py
==============================================================================
--- branches/gnome-2-24/gnome-sudoku/src/lib/sudoku_maker.py (original)
+++ branches/gnome-2-24/gnome-sudoku/src/lib/sudoku_maker.py Thu Nov 6 12:44:08 2008
@@ -311,35 +311,35 @@
self.batch_size = batch_size
self.load()
self.all_puzzles = {}
- self.reread_played_list()
+ self.played = self.get_pregenerated('finished')
- # Convenience methods for accessing puzzles we've created
-
- def reread_played_list (self):
- played_fn = os.path.join(self.pickle_to,'finished')
- self.played = []
- if os.path.exists(played_fn):
- for line in file(played_fn,'r'):
- self.played.append(line.strip('\n'))
-
def load (self):
try:
os.makedirs(self.pickle_to)
except os.error, e:
if e.errno != errno.EEXIST:
- raise
+ return
for cat in sudoku.DifficultyRating.categories:
- if not os.path.exists(os.path.join(self.pickle_to,
- cat.replace(' ','_'))):
+ source = os.path.join(os.path.join(PUZZLE_DIR),cat.replace(' ','_'))
+ target = os.path.join(self.pickle_to, cat.replace(' ','_'))
+ if not os.path.exists(target):
try:
- shutil.copy(os.path.join(os.path.join(PUZZLE_DIR),cat.replace(' ','_')),
- os.path.join(self.pickle_to,cat.replace(' ','_')))
+ shutil.copy(source, target)
except:
print 'Problem copying base puzzles'
- print 'Attempted to copy from ',os.path.join(os.path.join(PUZZLE_DIR),cat.replace(' ','_'))
- print 'to',os.path.join(self.pickle_to,cat.replace(' ','_'))
- raise
-
+ print 'Attempted to copy from %s to %s' % (source, target)
+
+ def get_pregenerated (self, difficulty):
+ fname = os.path.join(self.pickle_to, difficulty.replace(' ','_'))
+ try:
+ lines = file(fname).readlines()
+ except IOError, e:
+ if e.errno != errno.ENOENT:
+ print 'Error reading pregenerated puzzles for difficulty \'%s\': %s' % (difficulty, e.strerror)
+ return []
+ else:
+ return [line.strip() for line in lines]
+
def get_new_puzzle (self, difficulty, new=True):
"""Return puzzle with difficulty near difficulty.
@@ -352,21 +352,20 @@
if val_cat > 1: val_cat = 'very hard'
else: val_cat = 'easy'
puzzles = []
- ifi = file(os.path.join(self.pickle_to,
- val_cat.replace(' ','_'))
- )
+
+ lines = self.get_pregenerated(val_cat)
closest = 10000000000000,None
- for l in ifi.readlines():
- if not l.strip():
- print 'Warning: file %s contains an empty line'%ifi
+ for l in lines:
+ if len(l) == 0:
+ print 'Warning: file %s contains an empty line'%fname
continue
if not l.find('\t')>=0:
- print 'Warning: line "%s" of file %s has no tab character.'%(l,ifi)
+ print 'Warning: line "%s" of file %s has no tab character.'%(l,fname)
continue
puzzle,diff = l.split('\t')
if new and (puzzle in self.played): continue
if not sudoku.is_valid_puzzle(puzzle):
- print 'WARNING: invalid puzzle %s in file %s'%(puzzle,ifi)
+ print 'WARNING: invalid puzzle %s in file %s'%(puzzle,fname)
continue
diff = float(diff)
closeness_to_target = abs(diff - difficulty)
@@ -380,16 +379,12 @@
if not difficulty_category:
return sum([self.n_puzzles(c,new=new) for c in sudoku.DifficultyRating.categories])
else:
- path = os.path.join(self.pickle_to,
- difficulty_category.replace(' ','_')
- )
- if os.path.exists(path):
- ifi = file(path,'r')
- count = 0
- for line in ifi:
- if (not new) or line.split('\t')[0] not in self.played:
- count+=1
- return count
+ lines = self.get_pregenerated(difficulty_category)
+ count = 0
+ for line in lines:
+ if (not new) or line.split('\t')[0] not in self.played:
+ count+=1
+ return count
def list_puzzles (self, difficulty_category=None, new=True):
"""Return a list of all puzzles we have generated.
@@ -399,15 +394,11 @@
for c in sudoku.DifficultyRating.categories:
puzzle_list.extend(self.list_puzzles(c,new=new))
else:
- path = os.path.join(self.pickle_to,
- difficulty_category.replace(' ','_')
- )
- if os.path.exists(path):
- ifi = file(path,'r')
- for l in ifi.readlines():
- puzzle = l.split('\t')[0]
- if (not new) or puzzle not in self.played:
- puzzle_list.append(puzzle)
+ lines = self.get_pregenerated(difficulty_category)
+ for l in lines:
+ puzzle = l.split('\t')[0]
+ if (not new) or puzzle not in self.played:
+ puzzle_list.append(puzzle)
return puzzle_list
def get_puzzles_random (self, n, levels, new=True, exclude=[]):
@@ -422,10 +413,7 @@
# Open files to read puzzles...
puzzles_by_level = {}; files = {}
for l in levels:
- files[l] = os.path.join(self.pickle_to,
- l.replace(' ','_'))
- fi = file(files[l],'r')
- puzzles_by_level[l] = fi.readlines(); fi.close()
+ puzzles_by_level[l] = self.get_pregenerated(l)
random.shuffle(puzzles_by_level[l])
i = 0; il = 0
n_per_level = {}
@@ -470,11 +458,12 @@
if not n: return []
assert(levels)
puzzles = []
+
# Open files to read puzzles...
- files = dict([(l,
- file(os.path.join(self.pickle_to,
- l.replace(' ','_')),
- 'r')) for l in levels])
+ files = {}
+ for l in levels:
+ files[l] = self.get_pregenerated(l)
+
i = 0; il = 0
n_per_level = {}
finished = []
@@ -485,10 +474,12 @@
if lev in finished:
il += 1
continue
- line = files[lev].readline()
- if not line:
+
+ if len(files[lev]) == 0:
finished.append(lev)
else:
+ line = files[lev][0]
+ files[lev] = files[lev][1:]
try:
p,d = line.split('\t')
except ValueError:
@@ -504,7 +495,7 @@
if i < n:
print 'WARNING: Not able to provide %s puzzles in levels %s'%(n,levels)
print 'WARNING: Generate more puzzles if you really need this many puzzles!'
- for fi in files.values(): fi.close()
+
return puzzles
# End convenience methods for accessing puzzles we've created
@@ -540,19 +531,16 @@
diff.value_category().replace(' ','_'))
# Read through the existing file and make sure we're
# not a duplicate puzzle
- infi = file(outpath,'r')
- l = infi.readline()
- while l:
- if l==puzstring:
- continue
- l = infi.readline()
- infi.close()
- outfi = file(outpath,'a')
- outfi.write(puzstring+'\t'+str(diff.value)+'\n')
- outfi.close()
+ existing = self.get_pregenerated(diff.value_category())
+ if not puzstring in existing:
+ try:
+ outfi = file(outpath,'a')
+ outfi.write(puzstring+'\t'+str(diff.value)+'\n')
+ outfi.close()
+ except IOError, e:
+ print 'Error appending pregenerated puzzle: %s' % e.message
+
print 'done writing...'
- # Close all our open files...
- #for f in open_files.values(): f.close()
def pause (self, *args):
if hasattr(self,'new_generator'): self.new_generator.pause()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]