1 # ###################################################
2 # Copyright (C) 2008 The OpenAnno Team
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 # ###################################################
30 from dbreader
import DbReader
32 class InvalidSavegamenameException(Exception):
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.
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"
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"""
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
78 name
= os
.path
.splitext(os
.path
.basename(f
))[0]
79 displaynames
.append(name
)
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
))
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 '-'.
99 if re.match('^[\w\.\-]+$', name) is None:
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
:
129 for i
in xrange(0, len(files
) - limit
):
133 tmp_del("%s/*.%s" % (self
.autosave_dir
, self
.savegame_extension
),
134 game
.main
.settings
.savegame
.savedautosaves
)
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}
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
)