|
From: Markus R. <god...@us...> - 2009-11-12 12:50:05
|
Module: performous
Branch: master
Commit: 20b425ffd6a6eaa119c125b675ea3164233b9acf
Author: Markus Raab <un...@ma...>
Date: Thu Nov 12 10:52:21 2009 +0100
Query Interface for Database
it is now possible to query the global hiscore
and hiscores per songs and player.
in test program you can now enter song too and query is used
more const correctness (queries are const)
assign_id_internal regression fixed
---
game/database.cc | 59 +++++++++++++++++++++++++++++++++++++++++++++++-----
game/database.hh | 9 ++++++-
game/hiscore.cc | 30 ++++++++++++++++++++++++--
game/hiscore.hh | 9 +++++++-
game/players.cc | 10 ++++++++-
game/players.hh | 9 ++++++-
game/songitems.cc | 14 ++++++++++-
game/songitems.hh | 5 ++++
8 files changed, 128 insertions(+), 17 deletions(-)
diff --git a/game/database.cc b/game/database.cc
index d9906dc..d0f2bba 100644
--- a/game/database.cc
+++ b/game/database.cc
@@ -76,17 +76,54 @@ void Database::addHiscore (boost::shared_ptr<Song> s) {
m_hiscores.addHiscore(score, playerid, songid);
}
-bool Database::reachedHiscore (boost::shared_ptr<Song> s) {
+bool Database::reachedHiscore (boost::shared_ptr<Song> s) const {
int score = m_players.scores.front();
int songid = m_songs.lookup(s);
+
return m_hiscores.reachedHiscore(score, songid);
}
-int test(std::string const& name, int score) {
+void Database::queryOverallHiscore (std::ostream & os, std::string const& track) const {
+ std::vector<HiscoreItem> hi = m_hiscores.queryHiscore (10, -1, -1, track);
+ for (size_t i=0; i<hi.size(); ++i)
+ {
+ os << i+1 << ".\t"
+ << m_players.lookup(hi[i].playerid) << "\t"
+ << m_songs.lookup(hi[i].songid) << "\t"
+ // << hi[i].track << "\t"
+ << hi[i].score << "\n";
+ }
+}
+
+void Database::queryPerSongHiscore (std::ostream & os, boost::shared_ptr<Song> s, std::string const& track) const {
+ int songid = m_songs.lookup(s);
+ std::vector<HiscoreItem> hi = m_hiscores.queryHiscore(10, -1, songid, track);
+ for (size_t i=0; i<hi.size(); ++i)
+ {
+ os << i+1 << ".\t"
+ << m_players.lookup(hi[i].playerid) << "\t"
+ // << hi[i].track << "\t"
+ << hi[i].score << "\n";
+ }
+}
+
+void Database::queryPerPlayerHiscore (std::ostream & os, std::string const& track) const {
+ int playerid = m_players.lookup(m_players.current().name);
+ std::vector<HiscoreItem> hi = m_hiscores.queryHiscore(10, playerid, -1, track);
+ for (size_t i=0; i<hi.size(); ++i)
+ {
+ os << i+1 << ".\t"
+ << m_songs.lookup(hi[i].songid) << "\t"
+ // << hi[i].track << "\t"
+ << hi[i].score << "\n";
+ }
+}
+
+int test(std::string const& name, std::string const& song, int score) {
Database d("database.xml");
// d.addPlayer("Markus", "m.jpg");
- boost::shared_ptr<Song> s(new Song("/usr/share/songs/ABBA/ABBA - Dancing Queen/", "ABBA - Dancing Queen.txt"));
+ boost::shared_ptr<Song> s(new Song("/usr/share/songs/ABBA/ABBA - " + song + "/", "ABBA - " + song + ".txt"));
d.addSong(s);
PlayerItem pi;
@@ -100,6 +137,15 @@ int test(std::string const& name, int score) {
d.addHiscore(s);
}
+ std::cout << " --- Overall Hiscore ---" << std::endl;
+ d.queryOverallHiscore(std::cout);
+
+ std::cout << " --- Player Hiscore ---" << std::endl;
+ d.queryPerPlayerHiscore(std::cout);
+
+ std::cout << " --- Song Hiscore ---" << std::endl;
+ d.queryPerSongHiscore(std::cout, s);
+
return 0;
}
@@ -107,10 +153,11 @@ int test(std::string const& name, int score) {
int main(int argc, char**argv) {
- if (argc < 3) return 3;
+ if (argc < 4) return 3;
std::string name = argv[1];
- int score = boost::lexical_cast<int>(argv[2]);
+ std::string song = argv[2];
+ int score = boost::lexical_cast<int>(argv[3]);
- return test(name, score);
+ return test(name, song, score);
}
diff --git a/game/database.hh b/game/database.hh
index 1adec0a..c884944 100644
--- a/game/database.hh
+++ b/game/database.hh
@@ -1,6 +1,7 @@
#pragma once
#include <string>
+#include <ostream>
#include "players.hh"
#include "hiscore.hh"
@@ -64,9 +65,13 @@ class Database
Queries if the current player with current score has reached a new hiscore
for the song s.
*/
- bool reachedHiscore (boost::shared_ptr<Song> s);
+ bool reachedHiscore (boost::shared_ptr<Song> s) const;
- friend int test(std::string const&, int);
+ void queryOverallHiscore (std::ostream & os, std::string const& track = "") const;
+ void queryPerSongHiscore (std::ostream & os, boost::shared_ptr<Song> s, std::string const& track = "") const;
+ void queryPerPlayerHiscore (std::ostream & os, std::string const& track = "") const;
+
+ friend int test(std::string const&, std::string const&, int);
private:
fs::path m_filename;
diff --git a/game/hiscore.cc b/game/hiscore.cc
index a74ec5e..4c0bcae 100644
--- a/game/hiscore.cc
+++ b/game/hiscore.cc
@@ -10,7 +10,7 @@
Hiscore::Hiscore()
{}
-bool Hiscore::reachedHiscore(int score, int songid, std::string const& track) {
+bool Hiscore::reachedHiscore(int score, int songid, std::string const& track) const {
if (score < 0) throw HiscoreException("Score negativ overflow");
if (score > 10000) throw HiscoreException("Score positive overflow");
@@ -46,6 +46,31 @@ void Hiscore::addHiscore(int score, int playerid, int songid, std::string const&
m_hiscore.insert(hi);
}
+Hiscore::HiscoreVector Hiscore::queryHiscore(int max, int playerid, int songid, std::string const& track) const {
+ HiscoreVector hv;
+ for (hiscore_t::const_iterator it = m_hiscore.begin(); it != m_hiscore.end(); ++it) {
+ if (playerid != -1)
+ {
+ if (playerid != it->playerid) continue;
+ }
+ if (songid != -1)
+ {
+ if (songid != it->songid) continue;
+ }
+ if (!track.empty())
+ {
+ if (track != it->track) continue;
+ }
+ if (max != -1)
+ {
+ if (max == 0) break;
+ --max;
+ }
+ hv.push_back(*it);
+ }
+ return hv;
+}
+
void Hiscore::load(xmlpp::NodeSet const& n) {
for (xmlpp::NodeSet::const_iterator it = n.begin(); it != n.end(); ++it)
{
@@ -72,8 +97,7 @@ void Hiscore::load(xmlpp::NodeSet const& n) {
}
void Hiscore::save(xmlpp::Element *hiscores) {
- for (hiscore_t::const_iterator it = m_hiscore.begin(); it != m_hiscore.end(); ++it)
- {
+ for (hiscore_t::const_iterator it = m_hiscore.begin(); it != m_hiscore.end(); ++it) {
xmlpp::Element* hiscore = hiscores->add_child("hiscore");
hiscore->set_attribute("playerid", boost::lexical_cast<std::string>(it->playerid));
hiscore->set_attribute("songid", boost::lexical_cast<std::string>(it->songid));
diff --git a/game/hiscore.hh b/game/hiscore.hh
index 951fe16..704fe61 100644
--- a/game/hiscore.hh
+++ b/game/hiscore.hh
@@ -51,7 +51,7 @@ class Hiscore
@return true if the score make it into the top.
@return false if addNewHiscore does not make sense
for that score.*/
- bool reachedHiscore(int score, int songid, std::string const& track = "vocals");
+ bool reachedHiscore(int score, int songid, std::string const& track = "vocals") const;
/**Add a specific highscore into the list.
@@ -65,6 +65,13 @@ class Hiscore
HiscoreException will be raised.
*/
void addHiscore(int score, int playerid, int songid, std::string const& track = "vocals");
+
+ typedef std::vector<HiscoreItem> HiscoreVector;
+ /**This queries the database for a sorted vector of highscores.
+ The defaults mean to query everything.
+ @param max limits the number of elements returned.
+ */
+ HiscoreVector queryHiscore(int max = -1, int playerid = -1, int songid = -1, std::string const& track = "") const;
private:
typedef std::multiset<HiscoreItem>hiscore_t;
diff --git a/game/players.cc b/game/players.cc
index 1a0a764..9919ac4 100644
--- a/game/players.cc
+++ b/game/players.cc
@@ -62,7 +62,7 @@ void Players::update() {
if (m_dirty) filter_internal();
}
-int Players::lookup(std::string const& name) {
+int Players::lookup(std::string const& name) const {
for (players_t::const_iterator it = m_players.begin(); it != m_players.end(); ++it) {
if (it->name == name) return it->id;
}
@@ -70,6 +70,14 @@ int Players::lookup(std::string const& name) {
return -1;
}
+std::string Players::lookup(int id) const {
+ PlayerItem pi;
+ pi.id = id;
+ players_t::iterator it = m_players.find(pi);
+ if (it == m_players.end()) return "Unkown Player";
+ else return it->name;
+}
+
void Players::addPlayer (std::string const& name, std::string const& picture, int id) {
PlayerItem pi;
pi.id = id;
diff --git a/game/players.hh b/game/players.hh
index e739b0f..2e67199 100644
--- a/game/players.hh
+++ b/game/players.hh
@@ -54,7 +54,7 @@ class Players: boost::noncopyable {
bool m_dirty;
- friend int test(std::string const&, int);
+ friend int test(std::string const&, std::string const&, int);
public:
cur_players_t cur;
@@ -70,7 +70,12 @@ class Players: boost::noncopyable {
void update();
/// lookup a playerid using the players name
- int lookup(std::string const& name);
+ int lookup(std::string const& name) const;
+
+ /** lookup a players name using the playerid.
+ @return the players name or "Unkown Player"
+ */
+ std::string lookup(int id) const;
/// add a player with a displayed name and an optional picture; if no id is given one will be assigned
void addPlayer (std::string const& name, std::string const& picture = "", int id = -1);
diff --git a/game/songitems.cc b/game/songitems.cc
index d4d44a1..8e78ae0 100644
--- a/game/songitems.cc
+++ b/game/songitems.cc
@@ -83,8 +83,18 @@ int SongItems::lookup(boost::shared_ptr<Song> song) const {
return -1;
}
+std::string SongItems::lookup (int id) const {
+ SongItem si;
+ si.id = id;
+ songs_t::iterator it = m_songs.find(si);
+ if (it == m_songs.end()) return "Unkown Song";
+ else if (!it->song) return it->artist + " - " + it->title;
+ else return it->song->artist + " - " + it->song->title;
+}
+
int SongItems::assign_id_internal() const {
- songs_t::const_iterator it = m_songs.begin();
- if (it != m_songs.end()) return it->id+1;
+ // use the last one with highest id
+ songs_t::const_reverse_iterator it = m_songs.rbegin();
+ if (it != m_songs.rend()) return it->id+1;
else return 1; // empty set
}
diff --git a/game/songitems.hh b/game/songitems.hh
index a71f100..4575c45 100644
--- a/game/songitems.hh
+++ b/game/songitems.hh
@@ -83,6 +83,11 @@ struct SongItems
@return -1 if no song found.*/
int lookup(boost::shared_ptr<Song> song) const;
+ /**Lookup the artist + title for a specific song.
+ @return "Unknown Song" if nothing is found.
+ */
+ std::string lookup (int id) const;
+
private:
int assign_id_internal() const;
|