source: trunk/src/configuration.cpp @ 182

Last change on this file since 182 was 177, checked in by guyru, 5 years ago

resolve some compiler warnings

  • Property svn:executable set to *
File size: 8.5 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                // this is probably an old sqllite file import it.
53                conf_file.close();
54                importOldFile();
55                return;
56        }
57       
58        while(!conf_file.eof()) {
59                getline(conf_file,header);
60                if (header == "[settings]") {
61                        parseSettings(&conf_file);
62                } else if (header == "[highscores]") {
63                        parseHighscores(&conf_file);
64                }
65        }
66
67        conf_file.close();
68}
69
70void Configuration::parseSettings(ifstream *file)
71{
72        loadDefaultSettings();
73        string temp_line;
74        size_t pos; // used to loacate the '=' sign
75
76        while(!file->eof()) {
77                char temp_chr = file->get();
78                file->unget();
79                if (temp_chr == '[') { //new section started
80                        // we already called unget
81                        return;
82                }
83                getline(*file,temp_line);
84                pos = temp_line.find('=');
85                if (pos == string::npos) {
86                        // this isn't a configuration line, but it isn't a new section
87                        // as we checked this before, just skip
88                        continue;
89                }
90                m_settings[temp_line.substr(0,pos)] = temp_line.substr(pos+1);
91        }
92}
93
94void Configuration::parseHighscores(ifstream *file)
95{
96        char temp_chr;
97        int score;
98        string date,hour,name;
99        HighscoreItem temp_item;
100
101        temp_chr = file->get();
102        file->unget();
103
104        while(file->good()) {
105                temp_chr = file->get();
106                file->unget();
107                if (temp_chr == '[') {
108                        // we already called unget
109                        return;
110                }
111                (*file)>>score;
112                (*file)>>date;
113                (*file)>>hour;
114                (*file).get(); // discard space before name
115                getline(*file,name);
116                temp_item.score = score;
117                temp_item.name = name;
118                temp_item.date = date+" "+hour;
119                m_highscores.push_back(temp_item);
120
121                // The following two lines read one character forword and
122                // return it. This is done in order to raise the eofbit if
123                // we reached the eof (it is raised only after reading
124                // operation failed).
125                temp_chr = file->get();
126                file->unget();
127        }
128}
129
130void Configuration::save()
131{
132        ofstream conf_file (m_file.c_str());
133        if (!conf_file.is_open()) {
134                // file couldn't be opened, probably due to permission error
135                return;
136        }
137        conf_file<<"openyahtzee="<<VERSION<<endl;
138
139        conf_file<<"[settings]\n";
140        saveSettings(&conf_file);
141        conf_file<<"[highscores]\n";
142        saveHighscores(&conf_file);
143
144        conf_file.close();
145}
146
147void Configuration::saveSettings(ofstream *file)
148{
149        map<string,string>::iterator it;
150        for (it = m_settings.begin(); it!=m_settings.end(); it++) {
151                (*file)<<(*it).first<<"="<<(*it).second<<"\n";
152        }
153}
154
155void Configuration::saveHighscores(ofstream *file)
156{
157        HighscoresList::iterator it;
158        for (it = m_highscores.begin(); it!=m_highscores.end(); it++) {
159                (*file)<<(*it).score<<" ";
160                (*file)<<(*it).date<<" ";
161                (*file)<<(*it).name<<"\n";
162        }
163}
164
165string Configuration::get(string key)
166{
167        map<string,string>::iterator obj;
168
169        obj = m_settings.find(key);
170        if (obj == m_settings.end()) {
171                // key is missing return empty string
172                return "";
173        }
174        return obj->second;
175}
176
177Configuration* Configuration::set(string key, string value)
178{
179        m_settings[key] = value;
180        return this;
181}
182
183void Configuration::loadDefaultSettings()
184{
185        m_settings["dice-animation"] = "True";
186        m_settings["calculate-subtotal"] = "True";
187        m_settings["horizontal-layout"] = "True";
188        m_settings["score-hints"] = "True";
189        m_settings["highscore-list-size"] = DEFAULT_HIGHSCORE_SIZE;
190}
191
192
193void Configuration::importOldFile()
194{
195        loadDefaultSettings();
196        if (old_db.Open(m_file)!=SQLITE_OK) {
197                return;
198        }
199        importSettings();
200        // importHighscores is called after importSettings() so the
201        // highscore size settings will be known
202        importHighscores();
203}
204
205string Configuration::getKeyFromDb(string key)
206{
207        string tmp_query;
208        std::list<string> tmp_value;
209       
210        tmp_query = "SELECT value FROM settings WHERE key = \"" + key + "\"";
211
212        tmp_value = old_db.Query(tmp_query);
213        if (tmp_value.empty()) { //if there was no result return an empty string
214                tmp_query = ""; //use tmp_query for holding a tmp_string
215                return tmp_query;
216        }
217        return  *(tmp_value.begin());
218}
219
220void Configuration::importSettings()
221{
222        string temp_value;
223
224        temp_value = getKeyFromDb("animate");
225        if (temp_value=="No") {
226                set("dice-animation","False");
227        }
228
229        temp_value = getKeyFromDb("calculatesubtotal");
230        if (temp_value=="No") {
231                set("calculate-subtotal","False");
232        }
233
234        temp_value = getKeyFromDb("horizontalayout");
235        if (temp_value=="No") {
236                set("horizontal-layout","False");
237        }
238
239        temp_value = getKeyFromDb("score_hints");
240        if (temp_value=="No") {
241                set("score-hints","False");
242        }
243
244        temp_value = getKeyFromDb("highscoresize");
245        if (temp_value=="") {
246                set("highscore-list-size",DEFAULT_HIGHSCORE_SIZE);
247        }
248}
249
250void Configuration::importHighscores()
251{
252        string tmp_query = "SELECT name,date,score FROM highscore LIMIT "
253                + m_settings["highscore-list-size"];
254       
255        list<string> res = old_db.Query(tmp_query);
256        HighscoreItem temp_item;
257
258        list<string>::iterator it = res.begin();
259        size_t pos;
260        while(it!=res.end()) {
261                temp_item.name = (*it++);
262
263                // the database saved the the hour before the date,
264                // we need to reverse this
265                pos = it->find(' ');
266                temp_item.date = it->substr(pos+1); // date
267                temp_item.date += " " + it->substr(0,pos-3); // time, without seconds
268                it++;
269
270                temp_item.score = atoi((*it++).c_str());
271
272                m_highscores.push_back(temp_item);
273        }
274}
275
276bool Configuration::isHighscore(int score) {
277        const unsigned int highscore_list_size = atoi(m_settings["highscore-list-size"].c_str());
278        if (m_highscores.size()<highscore_list_size) {
279                // we have extra room in the highscore list
280                return true;
281        }
282
283        HighscoresList::iterator it= m_highscores.end();
284        if ((--it)->score<score) {
285                return true;
286        }
287
288        return false;
289}
290
291int Configuration::submitHighscore(int score, string name, string date) {
292        const unsigned int highscore_list_size = atoi(m_settings["highscore-list-size"].c_str());
293        unsigned int place = 1;
294        HighscoreItem temp_item;
295
296        //create sentinel in end of list, we'll remove when we finish
297        temp_item.score = -1; // this is lower than any valid score
298        m_highscores.push_back(temp_item);
299
300        temp_item.score = score;
301        temp_item.date = date;
302        temp_item.name = name;
303
304        HighscoresList::iterator it = m_highscores.begin();
305        while (it!=m_highscores.end()) {
306                if (it->score < temp_item.score) {
307                        m_highscores.insert(it, temp_item);
308                        break;
309                }
310                place++;
311                it++;
312        }
313        m_highscores.pop_back(); // remove the sentinel;
314
315        if (m_highscores.size()>highscore_list_size) {
316                m_highscores.pop_back();
317        }
318
319        if (place>highscore_list_size) {
320                return 0;
321        }
322        save();
323        return place;
324}
325
326const HighscoresList* Configuration::getHighscores() const
327{
328        const HighscoresList * ptr = &m_highscores;
329        return ptr;
330}
331
332void Configuration::clearHighscores()
333{
334        m_highscores.clear();
335        save();
336}
337
338void Configuration::setHighscoresSize(size_t size)
339{
340
341        std::ostringstream o;
342        o << size;
343        m_settings["highscore-list-size"] = o.str();
344
345        while (m_highscores.size()>size) {
346                m_highscores.pop_back();
347        }
348
349        save();
350}
Note: See TracBrowser for help on using the repository browser.