Imported Upstream version 2008.1+svn1553
[opeanno-debian-packaging.git] / game / savegamemanager.py
blobfdc2bb48e0e1b6f4529f1ef7da35e86780e6ef69
1 # ###################################################
2 # Copyright (C) 2008 The OpenAnno Team
3 # team@openanno.org
4 # This file is part of OpenAnno.
6 # OpenAnno is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the
18 # Free Software Foundation, Inc.,
19 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 # ###################################################
23 import os
24 import os.path
25 import re
26 import glob
27 import time
29 import game.main
30 from dbreader import DbReader
32 class InvalidSavegamenameException(Exception):
33 pass
35 class SavegameManager(object):
36 """Controls savegamefiles.
38 This class is rather a namespace than a "real" object, since it has no members.
40 The return values is usually a tuple: (list_of_savegame_files, list_of_savegame_names),
41 where savegame_names are meant for displaying to the user.
42 """
43 savegame_dir = "content/save"
44 autosave_dir = savegame_dir+"/autosave"
45 quicksave_dir = savegame_dir+"/quicksave"
46 demo_dir = "content/demo"
48 savegame_extension = "sqlite"
50 autosave_basename = "autosave-"
51 quicksave_basename = "quicksave-"
53 autosave_filenamepattern = autosave_basename+'%(timestamp)d.'+savegame_extension
54 quicksave_filenamepattern = quicksave_basename+'%(timestamp).2f.'+savegame_extension
56 display_timeformat = "%y/%m/%d %H:%M"
58 _shared_state = {}
60 def __init__(self):
61 # share members across all instances
62 self.__dict__ = self._shared_state
64 def __get_displaynames(self, files):
65 """Returns list of names files, that should be displayed to the user.
66 @param files: iterable object containing strings"""
67 displaynames = []
68 for f in files:
69 if f.startswith(self.autosave_dir):
70 savegameinfo = self.get_savegame_info(f)
71 timestr = "" if savegameinfo['timestamp'] == -1 else time.strftime("%y/%m/%d %H:%M", time.localtime(savegameinfo['timestamp']))
72 name = "Autosave %s" % timestr
73 elif f.startswith(self.quicksave_dir):
74 savegameinfo = self.get_savegame_info(f)
75 timestr = "" if savegameinfo['timestamp'] == -1 else time.strftime("%y/%m/%d %H:%M", time.localtime(savegameinfo['timestamp']))
76 name = "Quicksave %s" % timestr
77 else:
78 name = os.path.splitext(os.path.basename(f))[0]
79 displaynames.append(name)
80 return displaynames
82 def __get_saves_from_dirs(self, dirs, include_displaynames = True):
83 """Internal function, that returns the saves of a dir"""
84 files = [f for p in dirs for f in glob.glob(p+'/*.'+self.savegame_extension) if os.path.isfile(f)]
85 if include_displaynames:
86 return (files, self.__get_displaynames(files))
87 else:
88 return (files,)
90 def check_savegame_name(self, name):
91 """OBSOLETE: currently no checking is done, just IOErrors from low level functions are caught and interpreted as invalid filenames
93 Checks if a user-entered name is possible for a savegame.
94 Currently, we only allow alphanumeric, '.' and '-'.
95 @return: Bool
96 """
97 return True
98 """
99 if re.match('^[\w\.\-]+$', name) is None:
100 return False
101 else:
102 return True
105 def create_filename(self, savegamename):
106 """Returns the full path for a regular save of the name savegamename"""
108 if not self.check_savegame_name(savegamename):
109 raise InvalidSavegamenameException
111 return "%s/%s.%s" % (self.savegame_dir, savegamename, self.savegame_extension)
113 def create_autosave_filename(self):
114 """Returns the filename for an autosave"""
115 return "%s/%s.%s" % (self.autosave_dir, self.autosave_filenamepattern % {'timestamp':time.time()}, self.savegame_extension)
117 def create_quicksave_filename(self):
118 """Returns the filename for a quicksave"""
119 return "%s/%s.%s" % (self.quicksave_dir, self.quicksave_filenamepattern % {'timestamp':time.time()}, self.savegame_extension)
121 def delete_dispensable_savegames(self, autosaves = False, quicksaves = False):
122 """Delete savegames that are no longer needed
123 @param autosaves, quicksaves: Bool, set to true if this kind of saves should be cleaned
125 def tmp_del(pattern, limit):
126 files = glob.glob(pattern)
127 if len(files) > limit:
128 files.sort()
129 for i in xrange(0, len(files) - limit):
130 os.unlink(files[i])
132 if autosaves:
133 tmp_del("%s/*.%s" % (self.autosave_dir, self.savegame_extension),
134 game.main.settings.savegame.savedautosaves)
135 if quicksaves:
136 tmp_del("%s/*.%s" % (self.quicksave_dir, self.savegame_extension),
137 game.main.settings.savegame.savedquicksaves)
139 def get_savegame_info(self, savegamefile):
140 """Returns metainfo of a savegame as dict.
141 See last line of this function for reference of infos.
143 db = DbReader(savegamefile)
144 result = db("SELECT `value` FROM `metadata` WHERE `name` = \"timestamp\"")
145 if len(result) == 0: # no metadata in savegame
146 return {'timestamp' : -1}
147 else:
148 return {'timestamp' : float(result[0][0]) }
150 def write_metadata(self, db):
151 """Writes metadata to db.
152 @param db: DbReader"""
153 db("INSERT INTO metadata(name, value) VALUES(\"timestamp\", ?)", time.time())
155 def get_regular_saves(self, include_displaynames = True):
156 """Returns the savegames, that were saved via the ingame save dialog"""
157 return self.__get_saves_from_dirs([self.savegame_dir], include_displaynames = include_displaynames)
159 def get_saves(self, include_displaynames = True):
160 """Returns all savegames"""
161 return self.__get_saves_from_dirs([self.savegame_dir, self.autosave_dir, self.quicksave_dir, self.demo_dir], include_displaynames = include_displaynames)
163 def get_quicksaves(self, include_displaynames = True):
164 return self.__get_saves_from_dirs([self.quicksave_dir], include_displaynames = include_displaynames)