HighScoreManager.cxx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #include "HighScoreManager.hxx"
  2. #include <SDL.h>
  3. #include <boost/archive/binary_iarchive.hpp>
  4. #include <boost/archive/binary_oarchive.hpp>
  5. #include <algorithm>
  6. #include <filesystem>
  7. #include <fstream>
  8. namespace fs = std::filesystem;
  9. HighScoreManager::HighScoreManager()
  10. {
  11. data_dir_ = SDL_GetPrefPath("draconic-bytes", "snake");
  12. fs::create_directories(data_dir_);
  13. load();
  14. }
  15. void HighScoreManager::load()
  16. {
  17. auto const filename = fs::path{data_dir_}/"highscore.dat";
  18. std::ifstream input{filename, std::ios::binary};
  19. if (!input) {
  20. SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Missing high score file: %s", filename.c_str());
  21. return;
  22. }
  23. boost::archive::binary_iarchive archive{input};
  24. archive >> high_score_;
  25. std::ranges::stable_sort(high_score_.scores_, std::greater<>{}, &Score::points_);
  26. if (high_score_.scores_.empty()) {
  27. SDL_Log("No existing high scores.");
  28. }
  29. else {
  30. SDL_Log("Loaded high scores:");
  31. for (auto const& score: high_score_.scores_) {
  32. SDL_Log(" - %s: %u", score.player_name_.c_str(), score.points_);
  33. }
  34. }
  35. }
  36. void HighScoreManager::save() const
  37. {
  38. auto const filename = fs::path{data_dir_}/"highscore.dat";
  39. std::ofstream output{filename, std::ios::binary};
  40. if (!output) {
  41. SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed saving high scores to file %s", filename.c_str());
  42. return;
  43. }
  44. boost::archive::binary_oarchive archive{output};
  45. archive << high_score_;
  46. if (high_score_.scores_.empty()) {
  47. SDL_Log("No high scores saved.");
  48. }
  49. else {
  50. SDL_Log("Saved high scores:");
  51. for (auto const& score: high_score_.scores_) {
  52. SDL_Log(" - %s: %u", score.player_name_.c_str(), score.points_);
  53. }
  54. }
  55. }
  56. void HighScoreManager::set_new_score(unsigned int score)
  57. {
  58. if (high_score_.scores_.size()<MAX_SCORES || high_score_.scores_.back().points_<score) {
  59. new_score_ = score;
  60. }
  61. }
  62. bool HighScoreManager::has_new_score() const
  63. {
  64. return new_score_.has_value();
  65. }
  66. unsigned HighScoreManager::get_new_score() const
  67. {
  68. return new_score_.value_or(0u);
  69. }
  70. void HighScoreManager::provide_name_for_new_score(std::string const& name)
  71. {
  72. if (new_score_.has_value()) {
  73. high_score_.scores_.push_back({name, new_score_.value()});
  74. new_score_.reset();
  75. std::ranges::stable_sort(high_score_.scores_, std::greater<>{}, &Score::points_);
  76. if (high_score_.scores_.size()>MAX_SCORES) {
  77. high_score_.scores_.resize(MAX_SCORES);
  78. }
  79. save();
  80. }
  81. }
  82. HighScoreManager& HighScoreManager::instance()
  83. {
  84. static HighScoreManager manager;
  85. return manager;
  86. }
  87. std::vector<Score> const& HighScoreManager::get_scores() const
  88. {
  89. return high_score_.scores_;
  90. }