Source

Fat x Fast / FatxFast / fileio.py

Full commit
# This file is part of FatxFast.
#
#    FatxFast is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    FatxFast is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with FatxFast.  If not, see <http://www.gnu.org/licenses/>.

# Versioning based on: 
# http://en.wikipedia.org/wiki/Versioning#Designating_development_stage
__author__ = "dryatu (c) 2013"
__version__ = "1.2.5"
import time
import pickle
from FatxFast.resource import resource_manager

class VersionError(Exception): pass

def check_version(struct):
    if struct.version != __version__:
        LOGGER.log_message(
            "File version mismatch.")
        raise VersionError(
            "Current: "+str(struct.version)+" Real: "+__version__)

class ScoreData(dict):    
    
    def __init__(self, date=None, mode="classicmode", points=0, **kwargs):
        super(ScoreData, self).__init__()
        if date is None:
            date = time.strftime("%d-%m-%y-%H:%M", time.localtime())
        self["total_time"] = kwargs.get("total_time", 0)
        self["date"] = date
        self["mode"] = mode
        self["points"] = points

class ResourceManager(object):

    def __init__(self, manager, filename):
        self.manager = manager
        self.filename = filename

class HighScoreManager(ResourceManager):
    
    def __init__(self, manager, filename="highscores"):
        super(HighScoreManager, self).__init__(manager, filename)
        self.resources = {
        "classic":[ScoreData(date="Empty"),
            ScoreData(date="Empty"),ScoreData(date="Empty")], 
        "timed": [ScoreData(date="Empty"),
            ScoreData(date="Empty"),ScoreData(date="Empty")]
        }
    
    def add_score(self, score, total_time, mode):    
        struct = self.manager.load(self.filename)
        if struct:
            self.resources = struct
        new_score = False
        scores = []
        mode = mode.lower()
        if mode == "classicmode":
            scores = self.resources["classic"]
        if mode == "timedmode":
            scores = self.resources["timed"]

        if not len(scores):
            return False

        pointer = len(scores)-1
        for oldscore in xrange(pointer, -1, -1):
            if score > scores[oldscore]["points"]:
                new_score = True
                pointer = oldscore
        if new_score:
            tempscore = ScoreData(date=time.strftime("%d-%m-%y-%H:%M", 
                time.localtime()), points=score, mode=mode, 
                total_time=total_time)    
            scores.insert(pointer, tempscore)    
            if len(scores) > 3:
                del scores[3:]
            self.manager.save(self.filename, self.resources)
        ##Return true if first place achieved
        if not pointer:
            return new_score
    
    @property
    def scores(self):
        struct = self.manager.load(self.filename)
        if struct:
            self.resources = struct
        return self.resources

class SaveManager(ResourceManager):

    def __init__(self, manager, filename="fatsave"):
        super(SaveManager, self).__init__(manager, filename)
        self.resources = [None, None, None]
        self.maxsaves = 3

    def edit_save(self, index, save):
        self._load_saves()
        save.game["date"] = time.strftime("%d-%m-%y-%H:%M", 
            time.localtime())
        save.version = __version__
        self.resources[index] = save
        self.manager.save(self.filename, self.resources)    
    
    def get_save(self, index=0):
        self._load_saves()
        return self.resources[index]
   
    def _load_saves(self):
        struct = self.manager.load(self.filename)
        if struct:
            try:
                for save in struct:
                    if save:
                        check_version(save)
            except VersionError:
                self.manager.save(self.filename, self.resources)
            else:
                self.resources = struct

    @property
    def saves(self):
        self._load_saves()
        return self.resources

class Log(object):

    def __init__(self, filename="general-log.txt"):
        self.filename = filename
        self._file = None
        self.open_log()

    def open_log(self):
        def open_file(mode):
            self._file = open(
                resource_manager.get_resource_path(self.filename), mode)
        try:
            open_file("a")
        except IOError:
            open_file("w")

    def log_message(self, message="", dump_to_console=False):
        if self._file:
            log_prefix = "[{0}] ".format(time.strftime("%d-%m-%y-%H:%M", 
                time.localtime()))
            text = log_prefix + message + "\n"
            if dump_to_console or __debug__:
                print text
            self._file.write(text)

class TimerLog(Log):
    
    def __init__(self):
        super(TimerLog, self).__init__("perflog.txt")
        self.instances = {}
    
    def start(self, name, msg):
        self.instances[name] = [msg, time.time(), 0]
    
    def stop(self, name):
        self.instances[name][2] = time.time()
        print(name, self.instances[name][2]-self.instances[name][1])
    
    def log_message(self, message=""):
        texts = [ "{0}: {1}".format(
            self.instances[name][0], 
                self.instances[name][2]-self.instances[name][1]) 
            for name in self.instances]
        text = "\n".join(texts)
        super(TimerLog, self).log_message(text)

LOGGER = Log()