1 /*
2 ===========================================================================
3 blockattack - Block Attack - Rise of the Blocks
4 Copyright (C) 2005-2012 Poul Sander
5
6 This program 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.
10
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.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see http://www.gnu.org/licenses/
18
19 Source information and contacts persons can be found at
20 https://blockattack.net
21 ===========================================================================
22 */
23
24 #include "highscore.h"
25 #include "os.hpp"
26 #include "cereal/cereal.hpp"
27 #include "cereal/types/vector.hpp"
28 #include "cereal/archives/json.hpp"
29 #include "sago/SagoMisc.hpp"
30 #include <algorithm>
31 #include "common.h"
32
33 namespace cereal {
34
35 template<class Archive>
save(Archive & archive,record const & m)36 void save(Archive& archive, record const& m) {
37 archive( cereal::make_nvp("Name", m.name), cereal::make_nvp("Score", m.score) );
38 }
39
40 template<class Archive>
load(Archive & archive,record & m)41 void load(Archive& archive, record& m) {
42 archive( cereal::make_nvp("Name", m.name), cereal::make_nvp("Score", m.score) );
43 }
44
45 }
46
47 /*
48 This sorts in reverse order. So the highest will be first
49 */
record_sorter(const record & i,const record & j)50 bool record_sorter (const record& i,const record& j) {
51 return (i.score > j.score);
52 }
53
Highscore(const std::string & type,double speed)54 Highscore::Highscore(const std::string& type, double speed) : filename(type+".json.dat"), type(type), speed(speed) {
55 if (speed < 0.4) {
56 std::string old_locale = setlocale (LC_NUMERIC, nullptr);
57 setlocale (LC_NUMERIC, "C");
58 //Use special filenames for higher speeds (higher speed = lower number)
59 filename = SPrintStringF("%s_%.4f.json.dat", type.c_str(), speed);
60 setlocale(LC_NUMERIC, old_locale.c_str());
61 }
62 std::string readFileContent = sago::GetFileContent(filename.c_str());
63 if (readFileContent.length() > 0) {
64 try {
65 std::stringstream ss(readFileContent);
66 {
67 cereal::JSONInputArchive archive(ss);
68 archive(cereal::make_nvp("highscore", table));
69 }
70 }
71 catch (cereal::Exception& e) {
72 std::cerr << "Failed to read highscore " << filename << " due to formatting errors. Resetting the file. Reason: " <<
73 e.what() << "\n";
74 table.clear();
75 }
76 }
77 if (table.size() < top) {
78 for (int i = 0; i<top; i++) {
79 record r;
80 r.name = "Poul Sander";
81 r.score = 2000 - i*100;
82 table.push_back(r);
83 }
84 }
85 std::stable_sort(table.begin(), table.end(), record_sorter);
86 table.resize(top);
87 writeFile();
88 }
89
90
writeFile()91 void Highscore::writeFile() {
92 std::stringstream ss;
93 {
94 cereal::JSONOutputArchive archive(ss);
95 archive(cereal::make_nvp("highscore", table));
96 }
97 sago::WriteFileContent(filename.c_str(), ss.str());
98 }
99
isHighScore(int newScore)100 bool Highscore::isHighScore(int newScore) {
101 if (newScore>table.back().score) {
102 return true;
103 }
104 return false;
105 }
106
addScore(const std::string & newName,int newScore)107 void Highscore::addScore(const std::string& newName, int newScore) {
108 record r;
109 r.name = newName;
110 r.score = newScore;
111 table.push_back(r);
112 std::stable_sort(table.begin(), table.end(), record_sorter);
113 table.resize(top);
114 Highscore::writeFile();
115 }
116
getScoreNumber(int room)117 record Highscore::getScoreNumber(int room) {
118 record ret;
119 if (room < static_cast<int>(table.size()) ) {
120 ret = table.at(room);
121 }
122 return ret;
123 }
124
125