source: trunk/src/configuration.cpp @ 211

Last change on this file since 211 was 191, checked in by guyru, 6 years ago

Portable Edition 1.9 Preparations.

Removed SQLite support. Fixed configuration file path. Add new MSVC
configuration for the portable edition.

  • Property svn:executable set to *
File size: 6.7 KB
Line 
1/***************************************************************************
2 *   Copyright (C) 2006-2008 by Guy Rutenberg   *
3 *   guyrutenberg@gmail.com   *
4 *                                                                         *
5 *   This program is free software; you can redistribute it and/or modify  *
6 *   it under the terms of the GNU General Public License as published by  *
7 *   the Free Software Foundation; either version 2 of the License, or     *
8 *   (at your option) any later version.                                   *
9 *                                                                         *
10 *   This program is distributed in the hope that it will be useful,       *
11 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13 *   GNU General Public License for more details.                          *
14 *                                                                         *
15 *   You should have received a copy of the GNU General Public License     *
16 *   along with this program; if not, write to the                         *
17 *   Free Software Foundation, Inc.,                                       *
18 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19 ***************************************************************************/
20
21#include <cstdlib> // used in the back-compatibility code
22#include <sstream>
23#include "configuration.h"
24#include "../config.h"
25
26using namespace std;
27using namespace configuration;
28
29Configuration::Configuration(string file)
30{
31        load(file);
32}
33
34void Configuration::load(string file)
35{
36        m_file = file;
37
38        ifstream conf_file (file.c_str());
39        if (!conf_file.is_open()) {
40                // file couldn't be opened, this is due to missing file or
41                // permission error.
42                loadDefaultSettings();
43                save();
44                return;
45        }
46       
47        // the file was opened successfully. we need to check if it is an
48        // Open Yahtzee configuration file.
49        string header;
50        getline(conf_file,header);
51        if (header.substr(0,11) != "openyahtzee") {
52                /* The file might be an old configuration file or
53                 * currupted, anyway re-create it
54                 */
55                loadDefaultSettings();
56                save();
57                return;
58        }
59       
60        while(!conf_file.eof()) {
61                getline(conf_file,header);
62                if (header == "[settings]") {
63                        parseSettings(&conf_file);
64                } else if (header == "[highscores]") {
65                        parseHighscores(&conf_file);
66                }
67        }
68
69        conf_file.close();
70}
71
72void Configuration::parseSettings(ifstream *file)
73{
74        loadDefaultSettings();
75        string temp_line;
76        size_t pos; // used to loacate the '=' sign
77
78        while(!file->eof()) {
79                char temp_chr = file->get();
80                file->unget();
81                if (temp_chr == '[') { //new section started
82                        // we already called unget
83                        return;
84                }
85                getline(*file,temp_line);
86                pos = temp_line.find('=');
87                if (pos == string::npos) {
88                        // this isn't a configuration line, but it isn't a new section
89                        // as we checked this before, just skip
90                        continue;
91                }
92                m_settings[temp_line.substr(0,pos)] = temp_line.substr(pos+1);
93        }
94}
95
96void Configuration::parseHighscores(ifstream *file)
97{
98        char temp_chr;
99        int score;
100        string date,hour,name;
101        HighscoreItem temp_item;
102
103        temp_chr = file->get();
104        file->unget();
105
106        while(file->good()) {
107                temp_chr = file->get();
108                file->unget();
109                if (temp_chr == '[') {
110                        // we already called unget
111                        return;
112                }
113                (*file)>>score;
114                (*file)>>date;
115                (*file)>>hour;
116                (*file).get(); // discard space before name
117                getline(*file,name);
118                temp_item.score = score;
119                temp_item.name = name;
120                temp_item.date = date+" "+hour;
121                m_highscores.push_back(temp_item);
122
123                // The following two lines read one character forword and
124                // return it. This is done in order to raise the eofbit if
125                // we reached the eof (it is raised only after reading
126                // operation failed).
127                temp_chr = file->get();
128                file->unget();
129        }
130}
131
132void Configuration::save()
133{
134        ofstream conf_file (m_file.c_str());
135        if (!conf_file.is_open()) {
136                // file couldn't be opened, probably due to permission error
137                return;
138        }
139        conf_file<<"openyahtzee="<<VERSION<<endl;
140
141        conf_file<<"[settings]\n";
142        saveSettings(&conf_file);
143        conf_file<<"[highscores]\n";
144        saveHighscores(&conf_file);
145
146        conf_file.close();
147}
148
149void Configuration::saveSettings(ofstream *file)
150{
151        map<string,string>::iterator it;
152        for (it = m_settings.begin(); it!=m_settings.end(); it++) {
153                (*file)<<(*it).first<<"="<<(*it).second<<"\n";
154        }
155}
156
157void Configuration::saveHighscores(ofstream *file)
158{
159        HighscoresList::iterator it;
160        for (it = m_highscores.begin(); it!=m_highscores.end(); it++) {
161                (*file)<<(*it).score<<" ";
162                (*file)<<(*it).date<<" ";
163                (*file)<<(*it).name<<"\n";
164        }
165}
166
167string Configuration::get(string key)
168{
169        map<string,string>::iterator obj;
170
171        obj = m_settings.find(key);
172        if (obj == m_settings.end()) {
173                // key is missing return empty string
174                return "";
175        }
176        return obj->second;
177}
178
179Configuration* Configuration::set(string key, string value)
180{
181        m_settings[key] = value;
182        return this;
183}
184
185void Configuration::loadDefaultSettings()
186{
187        m_settings["dice-animation"] = "True";
188        m_settings["calculate-subtotal"] = "True";
189        m_settings["horizontal-layout"] = "True";
190        m_settings["score-hints"] = "True";
191        m_settings["highscore-list-size"] = DEFAULT_HIGHSCORE_SIZE;
192}
193
194bool Configuration::isHighscore(int score) {
195        const unsigned int highscore_list_size = atoi(m_settings["highscore-list-size"].c_str());
196        if (m_highscores.size()<highscore_list_size) {
197                // we have extra room in the highscore list
198                return true;
199        }
200
201        HighscoresList::iterator it= m_highscores.end();
202        if ((--it)->score<score) {
203                return true;
204        }
205
206        return false;
207}
208
209int Configuration::submitHighscore(int score, string name, string date) {
210        const unsigned int highscore_list_size = atoi(m_settings["highscore-list-size"].c_str());
211        unsigned int place = 1;
212        HighscoreItem temp_item;
213
214        //create sentinel in end of list, we'll remove when we finish
215        temp_item.score = -1; // this is lower than any valid score
216        m_highscores.push_back(temp_item);
217
218        temp_item.score = score;
219        temp_item.date = date;
220        temp_item.name = name;
221
222        HighscoresList::iterator it = m_highscores.begin();
223        while (it!=m_highscores.end()) {
224                if (it->score < temp_item.score) {
225                        m_highscores.insert(it, temp_item);
226                        break;
227                }
228                place++;
229                it++;
230        }
231        m_highscores.pop_back(); // remove the sentinel;
232
233        if (m_highscores.size()>highscore_list_size) {
234                m_highscores.pop_back();
235        }
236
237        if (place>highscore_list_size) {
238                return 0;
239        }
240        save();
241        return place;
242}
243
244const HighscoresList* Configuration::getHighscores() const
245{
246        const HighscoresList * ptr = &m_highscores;
247        return ptr;
248}
249
250void Configuration::clearHighscores()
251{
252        m_highscores.clear();
253        save();
254}
255
256void Configuration::setHighscoresSize(size_t size)
257{
258
259        std::ostringstream o;
260        o << size;
261        m_settings["highscore-list-size"] = o.str();
262
263        while (m_highscores.size()>size) {
264                m_highscores.pop_back();
265        }
266
267        save();
268}
Note: See TracBrowser for help on using the repository browser.