176 std::set<std::string>& tagFilters,
179 const std::string& sortByField,
203 return key == other.key;
209 int totalEntries = 0;
210 std::vector<DownloadablePack*> results{};
213 bool pendingRequest =
false;
216 bool noResults =
false;
218 bool initialized =
false;
220 void initialize(
LuaReference& whenDone = EMPTY_REFERENCE) {
221 setPage(0, whenDone);
225 std::vector<DownloadablePack*> get() {
226 auto it = results.begin();
227 if (results.size() > currentPageStartIndex()) {
229 it += currentPageStartIndex();
232 std::vector<DownloadablePack*> o{};
234 while (it != results.end()) {
242 std::vector<DownloadablePack*> getCache() {
return results; }
246 void setPage(
int page,
LuaReference& whenDone = EMPTY_REFERENCE);
252 setPage(getNextPageNbr(), whenDone);
258 setPage(getPrevPageNbr(), whenDone);
262 int getTotalPages() {
263 return static_cast<int>(ceilf(
static_cast<float>(totalEntries) /
264 static_cast<float>(key.perPage)));
268 void PushSelf(lua_State* L);
274 std::set<int> finishedPageRequests{};
277 int currentPageStartIndex() {
278 return key.perPage * currentPage;
281 int getNextPageNbr() {
282 if (key.perPage >= totalEntries) {
285 if (currentPage == getTotalPages() - 1) {
288 return currentPage + 1;
291 int getPrevPageNbr() {
292 if (key.perPage >= totalEntries) {
295 if (currentPage == 0) {
296 return getTotalPages() - 1;
298 return currentPage - 1;
302 bool mustRequestPage(
int page) {
303 const auto ind = key.perPage * page;
304 if (results.size() <= ind) {
309 return results.at(ind) ==
nullptr;
480 void Update(
float fDeltaSeconds);
481 void UpdatePacks(
float fDeltaSeconds);
482 void UpdateHTTP(
float fDeltaSeconds);
483 void UpdateGameplayState(
bool gameplay);
487 void PushSelf(lua_State* L);
492 bool ShouldUploadScores();
493 bool InGameplay() {
return gameplay; }
498 const std::string& username,
499 const std::string& password,
500 std::function<
void(
bool)> done = [](
bool loggedIn) {})
502 LoginRequest(username, password, done);
505 const std::string& sessionToken,
506 std::function<
void(
bool)> done = [](
bool loggedIn) {});
508 void LogoutIfLoggedIn()
514 void GetRankedChartkeys(
515 std::function<
void(
void)> callback = []() {},
516 const DateTime start = DateTime::GetFromString(
"1990-01-01 12:00:00"),
517 const DateTime end = DateTime::GetFromString(
"2100-01-01 12:00:00"))
519 GetRankedChartkeysRequest(callback, start, end);
521 void AddFavorite(
const std::string& chartKey)
523 AddFavoriteRequest(chartKey);
525 void BulkAddFavorites(
526 std::vector<std::string> chartKeys,
527 std::function<
void()> = []() {});
528 void RemoveFavorite(
const std::string& chartKey)
530 RemoveFavoriteRequest(chartKey);
532 void RefreshFavorites(
533 const DateTime start = DateTime::GetFromString(
"1990-01-01 12:00:00"),
534 const DateTime end = DateTime::GetFromString(
"2100-01-01 12:00:00"));
536 AddGoalRequest(goal);
539 std::vector<ScoreGoal*> goals,
540 std::function<
void()> callback = []() {});
542 UpdateGoalRequest(goal);
544 void RemoveGoal(
ScoreGoal* goal,
bool oldGoal =
false) {
545 RemoveGoalRequest(goal, oldGoal);
548 const DateTime start = DateTime::GetFromString(
"1990-01-01 12:00:00"),
549 const DateTime end = DateTime::GetFromString(
"2100-01-01 12:00:00"));
550 void AddPlaylist(
const std::string& name) {
551 AddPlaylistRequest(name);
553 void UpdatePlaylist(
const std::string& name)
555 UpdatePlaylistRequest(name);
557 void RemovePlaylist(
const std::string& name)
559 RemovePlaylistRequest(name);
563 const DateTime start = DateTime::GetFromString(
"1990-01-01 12:00:00"),
564 const DateTime end = DateTime::GetFromString(
"2100-01-01 12:00:00"));
565 void DownloadMissingPlaylists(
566 const DateTime start = DateTime::GetFromString(
"1990-01-01 12:00:00"),
567 const DateTime end = DateTime::GetFromString(
"2100-01-01 12:00:00"));
568 void DownloadPlaylist(
const std::string& name);
572 std::function<
void()> callback,
573 bool load_from_disk);
574 void UploadScoreWithReplayData(
HighScore* hs);
575 void UploadScoreWithReplayDataFromDisk(
577 std::function<
void()> callback = []() {});
578 void UploadBulkScores(
579 std::vector<HighScore*> hsList,
580 std::function<
void()> callback = []() {});
582 void RefreshPackTags();
584 std::function<
void(rapidjson::Document&)> packSearchParser)
586 MultiSearchRequest(searchCriteria, packSearchParser);
590 bool ForceUploadPBsForChart(
const std::string& ck,
bool startNow =
false);
591 bool ForceUploadPBsForPack(
const std::string& pack,
bool startNow =
false);
592 bool ForceUploadAllPBs();
593 bool InitialScoreSync();
595 void GetChartLeaderboard(
const std::string& chartkey,
598 GetChartLeaderboardRequest(chartkey, ref);
600 void GetReplayData(
const std::string& scorekey,
602 const std::string& username,
603 const std::string& chartkey,
606 GetReplayDataRequest(scorekey, userid, username, chartkey, callback);
612 float GetSkillsetRating(Skillset ss);
613 int GetSkillsetRank(Skillset ss);
616 const std::string& searchString,
617 std::set<std::string> tagFilters,
620 const std::string& sortBy,
622 std::shared_ptr<Download> DownloadAndInstallPack(
const std::string& url,
623 std::string filename =
"");
625 bool mirror =
false);
627 void DownloadCoreBundle(
const std::string& bundlename,
bool mirror =
false);
628 std::vector<DownloadablePack*> GetCoreBundle(
const std::string& bundlename);
630 void DownloadImage(
const std::string& url,
633 bool OpenSitePage(
const std::string& path);
634 bool OpenProjectPage(
const std::string& path);
636 bool ShowPackPage(
int packid) {
637 return OpenSitePage(fmt::format(
"/packs/{}", packid));
639 bool ShowUserPage(
const std::string& username){
640 return OpenSitePage(fmt::format(
"/users/{}", username));
642 bool ShowScorePage(
const std::string& username,
int scoreid)
645 fmt::format(
"/users/{}/scores/{}", username, scoreid));
647 bool ShowBugReportSite();
648 bool ShowEditorSite();
649 bool ShowProjectReleases() {
650 return OpenProjectPage(
"/releases");
652 bool ShowProjectSite() {
653 return OpenProjectPage(
"");
659 std::string authToken{
"" };
661 std::string sessionUser{
"" };
663 std::map<Skillset, int> sessionRanks{};
665 std::map<Skillset, double> sessionRatings{};
669 std::deque<HighScore*> ScoreUploadSequentialQueue;
670 unsigned int sequentialScoreUploadTotalWorkload{ 0 };
674 std::deque<ScoreGoal*> GoalUploadSequentialQueue;
675 unsigned int sequentialGoalUploadTotalWorkload{ 0 };
679 std::deque<std::string> FavoriteUploadSequentialQueue;
680 unsigned int sequentialFavoriteUploadTotalWorkload{ 0 };
685 std::map<std::string, std::shared_ptr<Download>> downloads;
687 std::deque<std::pair<DownloadablePack*, bool>> DownloadQueue;
688 std::map<std::string, std::shared_ptr<Download>> finishedDownloads;
689 std::map<std::string, std::shared_ptr<Download>> pendingInstallDownloads;
690 std::map<int, DownloadablePack> downloadablePacks;
691 std::unordered_map<std::string, std::vector<std::string>> packTags;
694 downloadablePackPaginations{};
696 std::unordered_map<std::string, std::set<int>> tagPacks;
700 std::map<std::string, std::vector<OnlineScore>> chartLeaderboards{};
701 std::map<Skillset, std::vector<OnlineTopScore>> topScores{};
702 std::set<std::string> unrankedCharts{};
703 bool currentrateonly =
false;
704 bool topscoresonly =
true;
705 bool validonly =
true;
710 std::string lastVersion{
"" };
711 std::string countryCode{
"" };
719 bool HandleAuthErrorResponse(
const std::string& endpoint,
HTTPRequest& req);
721 bool HandleRatelimitResponse(
const std::string& endpoint,
HTTPRequest& req);
722 bool QueueRequestIfRatelimited(
const std::string& endpiont,
724 void QueueRatelimitedRequest(
const std::string& endpoint,
HTTPRequest& req);
728 bool Handle401And429Response(
729 const std::string& endpoint,
731 std::function<
void()> if401 = []() {},
732 std::function<void()> if429 = []() {});
736 void LoginRequest(
const std::string& username,
737 const std::string& password,
738 std::function<
void(
bool)> done);
739 void GetRankedChartkeysRequest(std::function<
void(
void)> callback,
742 void AddFavoriteRequest(
const std::string& chartKey);
743 void RemoveFavoriteRequest(
const std::string& chartKey);
744 void GetFavoritesRequest(
745 std::function<
void(std::set<std::string>)> onSuccess,
750 void RemoveGoalRequest(
ScoreGoal* goal,
bool oldGoal);
751 void GetGoalsRequest(std::function<
void(std::vector<ScoreGoal>)> onSuccess,
754 void AddPlaylistRequest(
const std::string& name);
755 void UpdatePlaylistRequest(
const std::string& name);
756 void RemovePlaylistRequest(
const std::string& name);
757 void GetPlaylistsRequest(
758 std::function<
void(std::unordered_map<std::string, Playlist>)> onSuccess,
761 void GetPlaylistRequest(std::function<
void(
Playlist)> onSuccess,
int id);
762 void GetChartLeaderboardRequest(
const std::string& chartkey,
764 void GetReplayDataRequest(
const std::string& scorekey,
766 const std::string& username,
767 const std::string& chartkey,
770 void RefreshUserData();
771 void RequestTop25(Skillset ss);
772 void RefreshLastVersion();
774 void GetPackTagsRequest();
775 void CachePacksForTag(
const std::string& tag);
778 std::function<
void(rapidjson::Document&)> whenDoneParser);
782 std::string requestName,
783 std::vector<std::pair<std::string, std::string>> params,
785 bool requireLogin =
true,
786 RequestMethod httpMethod = RequestMethod::GET,
787 bool compressed =
false,
789 bool withBearer =
true);
792 std::string requestName,
794 std::vector<std::pair<std::string, std::string>> params,
796 bool requireLogin =
true,
797 RequestMethod httpMethod = RequestMethod::GET,
798 bool compressed =
false,
800 bool withBearer =
true);
805 std::vector<std::pair<std::string, std::string>> params,
808 RequestMethod httpMethod,
814 std::vector<HTTPRequest*> HTTPRequests;
816 CURLM* pack_multi_handle =
nullptr;
817 CURLM* http_req_handle =
nullptr;
820 bool loggingIn{
false };
822 bool gameplay{
false };
823 bool initialized{
false };
825 float timeSinceLastDownload = 0.F;
827 std::unordered_map<std::string, std::chrono::steady_clock::time_point>
828 endpointRatelimitTimestamps{};
829 std::unordered_map<std::string, std::vector<HTTPRequest*>>
830 ratelimitedRequestQueue{};
831 std::unordered_set<std::string> newlyRankedChartkeys{};
833 std::unordered_map<std::string, DownloadableImage*> downloadableImages{};