Back to index

supertuxkart  0.5+dfsg1
highscore_manager.cpp
Go to the documentation of this file.
00001 //  $Id: highscores.hpp 921 2007-02-28 05:43:34Z hiker $
00002 //
00003 //  SuperTuxKart - a fun racing game with go-kart
00004 //  Copyright (C) 2006 Joerg Henrichs
00005 //
00006 //  This program is free software; you can redistribute it and/or
00007 //  modify it under the terms of the GNU General Public License
00008 //  as published by the Free Software Foundation; either version 2
00009 //  of the License, or (at your option) any later version.
00010 //
00011 //  This program is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //  GNU General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU General Public License
00017 //  along with this program; if not, write to the Free Software
00018 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 
00020 #include <stdexcept>
00021 #include "highscore_manager.hpp"
00022 #include "race_manager.hpp"
00023 #include "lisp/parser.hpp"
00024 #include "lisp/writer.hpp"
00025 #include "translation.hpp"
00026 #include "string_utils.hpp"
00027 #include "file_manager.hpp"
00028 #include "user_config.hpp"
00029 #if defined(WIN32) && !defined(__CYGWIN__)
00030 #  define snprintf _snprintf
00031 #endif
00032 HighscoreManager* highscore_manager=0;
00033 
00034 HighscoreManager::HighscoreManager()
00035 {
00036     m_can_write=true;
00037     SetFilename();
00038     Load();
00039 }   // HighscoreManager
00040 
00041 // -----------------------------------------------------------------------------
00042 HighscoreManager::~HighscoreManager()
00043 {
00044     Save();
00045     for(type_all_scores::iterator i  = m_allScores.begin(); 
00046                                   i != m_allScores.end();  i++)
00047         delete *i;
00048 }   // ~HighscoreManager
00049 
00050 // -----------------------------------------------------------------------------
00053 void HighscoreManager::SetFilename()
00054 {
00055     if ( getenv("SUPERTUXKART_HIGHSCOREDIR") != NULL )
00056     {
00057         m_filename = getenv("SUPERTUXKART_HIGHSCOREDIR")
00058                  + std::string("/highscore.data");
00059     }
00060     else 
00061     {
00062         m_filename=file_manager->getHighscoreFile("highscore.data");
00063     }
00064 
00065     return;
00066 }   // SetFilename
00067 
00068 // -----------------------------------------------------------------------------
00069 void HighscoreManager::Load()
00070 {
00071 
00072     const lisp::Lisp* root = 0;
00073        std::exception err;
00074 
00075     try
00076     {
00077         lisp::Parser parser;
00078         root = parser.parse(m_filename);
00079     }
00080     catch(std::exception& err)
00081     {
00082         (void)err;   // remove warning about unused variable
00083         Save();
00084         if(m_can_write)
00085         {
00086             fprintf(stderr, "New highscore file '%s' created.\n", 
00087                     m_filename.c_str());
00088         }
00089         delete root;
00090         return;
00091     }
00092     try
00093     {
00094         const lisp::Lisp* const node = root->getLisp("highscores");
00095         if(!node)
00096         {
00097             char msg[MAX_ERROR_MESSAGE_LENGTH];
00098             snprintf(msg, sizeof(msg), "No 'highscore' node found.");
00099             throw std::runtime_error(msg);
00100         }
00101         int n;
00102         if (!node->get("number-entries",n))
00103         {
00104             char msg[MAX_ERROR_MESSAGE_LENGTH];
00105             snprintf(msg, sizeof(msg), "No 'number-entries' node found.");
00106             throw std::runtime_error(msg);
00107         }
00108 
00109         for(int i=0; i<n; i++)
00110         {
00111             char record_name[255];
00112             snprintf(record_name, sizeof(record_name), "record-%d", i);
00113             const lisp::Lisp* const node_record=node->getLisp(record_name);
00114             if(!node_record) 
00115             {
00116                 char msg[MAX_ERROR_MESSAGE_LENGTH];
00117                 snprintf(msg, sizeof(msg),"Can't find record '%d' in '%s'",
00118                          i,m_filename.c_str());
00119                 throw std::runtime_error(msg);
00120             }
00121             Highscores *highscores = new Highscores();
00122             m_allScores.push_back(highscores);
00123             highscores->Read(node_record);
00124         }
00125     fprintf(stderr, "Highscores will be saved in '%s'.\n",m_filename.c_str());
00126     }
00127     catch(std::exception& err)
00128     {
00129         fprintf(stderr, "Error while parsing highscore file '%s':\n", 
00130                 m_filename.c_str());
00131         fprintf(stderr, err.what());
00132         fprintf(stderr, "\n");
00133         fprintf(stderr, "No old highscores will be available.\n");
00134     }
00135     delete root;
00136 }   // Load
00137 
00138 // -----------------------------------------------------------------------------
00139 void HighscoreManager::Save()
00140 {
00141     // Print error message only once
00142     if(!m_can_write) return;
00143     try
00144     {
00145         lisp::Writer writer(m_filename);
00146         writer.beginList("highscores");
00147           writer.writeComment("Number of highscores in this file");
00148           writer.write("number-entries\t",(unsigned int)m_allScores.size());
00149           int record_number=0;
00150           for(type_all_scores::iterator i  = m_allScores.begin(); 
00151               i != m_allScores.end();  i++)
00152           {
00153               char record_name[255];
00154               snprintf(record_name, sizeof(record_name),"record-%d\t",record_number);
00155               record_number++;
00156               writer.beginList(record_name);
00157               (*i)->Write(&writer);
00158               writer.endList(record_name);
00159           }   // for i
00160         writer.endList("highscores");
00161         m_can_write=true;
00162     }   // try
00163     catch(std::exception &e)
00164     {
00165         printf("Problems saving highscores in '%s'\n",
00166                m_filename.c_str());
00167         printf(e.what());
00168         printf("\n");
00169         m_can_write=false;
00170     }
00171 }   // Save
00172 
00173 // -----------------------------------------------------------------------------
00174 Highscores* HighscoreManager::getHighscores(const Highscores::HighscoreType highscore_type)
00175 {
00176     Highscores *highscores = 0;
00177 
00178     // See if we already have a record for this type
00179 
00180     for(type_all_scores::iterator i  = m_allScores.begin(); 
00181                                   i != m_allScores.end();  i++)
00182     {
00183         if((*i)->matches(highscore_type, race_manager->getNumKarts(), 
00184                          race_manager->getDifficulty(), race_manager->getTrackName(),
00185                          race_manager->getNumLaps()))
00186         {
00187             return (*i);
00188         }
00189     }   // for i in m_allScores
00190 
00191     highscores = new Highscores();
00192     m_allScores.push_back(highscores);
00193     return highscores;
00194 }   // getHighscores
00195 
00196 // -----------------------------------------------------------------------------
00197 // Checks if the specified times needs to be put into the highscore list.
00198 // If it's one of the fastest HIGHSCORE_LEN results, it is put into the
00199 // list and the new position (1 ... HIGHSCORE_LEN) is returned, otherwise 0.
00200 Highscores * HighscoreManager::addResult(const Highscores::HighscoreType highscore_type, 
00201                                          const std::string kart_name,
00202                                          const std::string name, 
00203                                          const float time)
00204 {
00205     Highscores *highscores = getHighscores(highscore_type);
00206 
00207     if(highscores->addData(highscore_type, kart_name, name, time) >0)
00208     {
00209         Save();
00210     }
00211     return highscores;
00212 }   // addResult
00213 // -----------------------------------------------------------------------------