From 221b08e07246e84587b4144eca5564ce9ad3a20a Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Fri, 1 Nov 2024 19:02:28 +0100 Subject: implement leaderboard functionality --- frontend/DB.cpp | 8 ++++---- frontend/DB.h | 4 ++-- frontend/GameController.cpp | 16 +++++++++++++--- frontend/GameData.cpp | 27 +++++++++++++++++++++++---- frontend/GameData.h | 9 +++++---- frontend/generate_dungeon.cpp | 4 ++-- frontend/load_dungeon.cpp | 4 ++-- frontend/strings.h | 4 ++++ 8 files changed, 55 insertions(+), 21 deletions(-) (limited to 'frontend') diff --git a/frontend/DB.cpp b/frontend/DB.cpp index f40a9fd..28a1c3d 100644 --- a/frontend/DB.cpp +++ b/frontend/DB.cpp @@ -77,24 +77,24 @@ DBQueryRow DBStatement::row() { DBQueryRow::DBQueryRow(DBStatement & parent) : parent(parent) { } template <> -const char * DBQueryRow::col(int index, const char * const & default_value) { +const char * DBQueryRow::col(int index, const char * const & default_value) const { int type = sqlite3_column_type(this->parent.stmt.get(), index); if (type == SQLITE_NULL) return default_value; return reinterpret_cast(sqlite3_column_text(this->parent.stmt.get(), index)); } template <> -const char * DBQueryRow::col(int index) { +const char * DBQueryRow::col(int index) const { return this->col(index, ""); } template <> -int DBQueryRow::col(int index, const int & default_value) { +int DBQueryRow::col(int index, const int & default_value) const { int type = sqlite3_column_type(this->parent.stmt.get(), index); if (type == SQLITE_NULL) return default_value; return sqlite3_column_int(this->parent.stmt.get(), index); } template <> -int DBQueryRow::col(int index) { +int DBQueryRow::col(int index) const { return this->col(index, 0); } diff --git a/frontend/DB.h b/frontend/DB.h index 0164e34..2746e09 100644 --- a/frontend/DB.h +++ b/frontend/DB.h @@ -13,9 +13,9 @@ public: public: template - T col(int index, const T & default_value); + T col(int index, const T & default_value) const; template - T col(int index); + T col(int index) const; private: DBStatement & parent; diff --git a/frontend/GameController.cpp b/frontend/GameController.cpp index d7b5f96..e015348 100644 --- a/frontend/GameController.cpp +++ b/frontend/GameController.cpp @@ -70,14 +70,17 @@ unique_ptr GameController::make_dungeon() noexcept { void GameController::gameloop() { this->dungeon = make_dungeon(); Player & player = this->dungeon->get_player(); + GameData & gamedata = GameData::get_instance(); lprtf("Wat is de naam van je karakter?\n"); player.name = rl().c_str(); player.set_location(dungeon->get_start_location()); - player.equip(static_cast(GameData::get_instance().create_object("Dolk"))); + player.equip(static_cast(gamedata.create_object("Dolk"))); cmdset_default(); + bool is_dead = false, last_is_dead = false; + this->playing = true; while (this->playing) { string line = rl(); @@ -88,8 +91,15 @@ void GameController::gameloop() { lprtf("FOUT: %s.\n", e.what()); } - if (player.is_dead()) - cmdset_death(); + last_is_dead = is_dead; + is_dead = player.is_dead(); + bool just_died = last_is_dead == false && is_dead == true; + if (!just_died) continue; + + cmdset_death(); + gamedata.leaderbord_add(player.name.c_str(), player.gold); + str_print(strings::DEATH); + gamedata.leaderbord_print(); } } diff --git a/frontend/GameData.cpp b/frontend/GameData.cpp index e62cff1..ee05d4b 100644 --- a/frontend/GameData.cpp +++ b/frontend/GameData.cpp @@ -6,6 +6,7 @@ #include "backend/LocationFactory.h" #include "backend/Object.h" #include "backend/ObjectFactory.h" +#include "backend/print.h" #include "GameData.h" @@ -20,7 +21,7 @@ GameData::GameData() { this->db = make_unique("kerkersendraken.db"); } -Enemy * GameData::create_enemy(const string & name) { +Enemy * GameData::create_enemy(const string & name) const { static DBStatement query = this->db->prepare(R"( select naam, @@ -62,7 +63,7 @@ static const unordered_map type_map = { { "goudstukken", ObjectType::GOLD }, }; -Object * GameData::create_object(const string & name) { +Object * GameData::create_object(const string & name) const { static DBStatement query = this->db->prepare(R"( select type, @@ -95,7 +96,7 @@ Object * GameData::create_object(const string & name) { } } -Location * GameData::create_location(const string & name) { +Location * GameData::create_location(const string & name) const{ static DBStatement query = this->db->prepare(R"( select naam, @@ -116,7 +117,7 @@ Location * GameData::create_location(const string & name) { } } -void GameData::leaderbord_add(const string & name, unsigned int gold) { +void GameData::leaderbord_add(const string & name, unsigned int gold) const { static DBStatement stmt = this->db->prepare(R"( insert into Leaderboard (naam, goudstukken) values (?, ?) @@ -128,6 +129,24 @@ void GameData::leaderbord_add(const string & name, unsigned int gold) { stmt.execute(); } +void GameData::leaderbord_print() const { + static DBStatement query = this->db->prepare(R"( + select naam, goudstukken + from Leaderboard + order by goudstukken desc + limit 10 + )"); + query.reset(); + printf("\033[1;4m"); + lprtf("%3s %-20s %4s", "#", "Naam", "Goud"); + printf("\033[0m"); + lprtf("\n"); + unsigned int i = 1; + for (DBQueryRow & row : query.rows()) { + lprtf("%3d %-20s %4d\n", i++, row.col(0), row.col(1)); + } +} + vector GameData::random_locations(unsigned count) { static DBStatement query = this->db->prepare(R"( select naam diff --git a/frontend/GameData.h b/frontend/GameData.h index 81e16c1..0d7577d 100644 --- a/frontend/GameData.h +++ b/frontend/GameData.h @@ -13,12 +13,13 @@ public: static GameData & get_instance(); public: - Enemy * create_enemy(const std::string & name); - Object * create_object(const std::string & name); - Location * create_location(const std::string & name); + Enemy * create_enemy(const std::string & name) const; + Object * create_object(const std::string & name) const; + Location * create_location(const std::string & name) const; public: - void leaderbord_add(const std::string & name, unsigned int gold); + void leaderbord_add(const std::string & name, unsigned int gold) const; + void leaderbord_print() const; std::vector random_locations(unsigned count = 1); private: diff --git a/frontend/generate_dungeon.cpp b/frontend/generate_dungeon.cpp index 6e34673..7ce1754 100644 --- a/frontend/generate_dungeon.cpp +++ b/frontend/generate_dungeon.cpp @@ -20,10 +20,10 @@ unique_ptr generate_dungeon() { string filename = rl(); location_count = stoul(filename); } catch (...) { - throw Exception("Geen geldig aantal ingevoerd"); + throw Exception("geen geldig aantal ingevoerd"); } if (location_count < 1) - throw Exception("Meer dan 1 locatie nodig"); + throw Exception("meer dan 1 locatie nodig"); vector locations = gd.random_locations(location_count); for (const string & name : locations) { diff --git a/frontend/load_dungeon.cpp b/frontend/load_dungeon.cpp index 0388387..75edf16 100644 --- a/frontend/load_dungeon.cpp +++ b/frontend/load_dungeon.cpp @@ -28,12 +28,12 @@ unique_ptr load_dungeon(const string & filename) { try { canonical = filesystem::canonical(canonical); } catch (...) { - throw Exception("Kon bestand niet vinden"); + throw Exception("kon bestand niet vinden (%s)", filename.c_str()); } xml_parse_result result = doc.load_file(canonical.c_str(), parse_default, encoding_latin1); if (!result) - throw Exception("Kon XML-bestand niet lezen"); + throw Exception("kon XML-bestand niet lezen"); xml_node locations = doc.child("locaties"); if (!locations) diff --git a/frontend/strings.h b/frontend/strings.h index 61236a6..93af5ef 100644 --- a/frontend/strings.h +++ b/frontend/strings.h @@ -13,6 +13,10 @@ static constexpr const char * UNKNOWN_CMD = R"(De ingevoerde actie is onbekend of op dit moment niet mogelijk. De actie `Help` laat een opsomming van bestaande acties te zien.)"; +static constexpr const char * DEATH = R"(Je bent dood gegaan! Je highscore is +opgeslagen in de ranglijst. Typ `Opnieuw` om opnieuw te spelen, of `Quit` om af +te sluiten.)"; + } void str_print(const char *); -- cgit v1.2.3