Skip to content

Commit

Permalink
allow sorting pack downloads by various columns
Browse files Browse the repository at this point in the history
the way this is integrated with lua allows you to specify a very custom sort if you really want, but the ones provided should be good enough
  • Loading branch information
poco0317 committed Apr 23, 2024
1 parent 71cae5f commit 644ba2e
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 12 deletions.
3 changes: 3 additions & 0 deletions Themes/Rebirth/BGAnimations/playerInfoFrame/downloads.lua
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,7 @@ local function downloadsList()
ClickCommand = function(self, params)
if self:IsInvisible() then return end
if params.update ~= "OnMouseDown" then return end
pl:SortByName()
self:GetParent():playcommand("UpdateItemList")
end,
RolloverUpdateCommand = function(self, params)
Expand Down Expand Up @@ -997,6 +998,7 @@ local function downloadsList()
ClickCommand = function(self, params)
if self:IsInvisible() then return end
if params.update ~= "OnMouseDown" then return end
pl:SortByOverall()
self:GetParent():playcommand("UpdateItemList")
end,
RolloverUpdateCommand = function(self, params)
Expand Down Expand Up @@ -1027,6 +1029,7 @@ local function downloadsList()
ClickCommand = function(self, params)
if self:IsInvisible() then return end
if params.update ~= "OnMouseDown" then return end
pl:SortBySize()
self:GetParent():playcommand("UpdateItemList")
end,
RolloverUpdateCommand = function(self, params)
Expand Down
60 changes: 60 additions & 0 deletions Themes/Til Death/BGAnimations/packlistDisplay.lua
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,18 @@ local o = Def.ActorFrame {
self:halign(0)
self:settext(translated_info["Name"])
end,
MouseOverCommand = function(self)
self:diffusealpha(hoverAlpha)
end,
MouseOutCommand = function(self)
self:diffusealpha(1)
end,
MouseDownCommand = function(self, params)
if params.event == "DeviceButton_left mouse button" then
packlist:SortByName()
self:GetParent():queuecommand("Update")
end
end
},
UIElements.TextToolTip(1, 1, "Common Normal") .. {
Name = "AverageDiffHeader",
Expand All @@ -129,6 +141,18 @@ local o = Def.ActorFrame {
self:halign(1)
self:settext(translated_info["AverageDiff"])
end,
MouseOverCommand = function(self)
self:diffusealpha(hoverAlpha)
end,
MouseOutCommand = function(self)
self:diffusealpha(1)
end,
MouseDownCommand = function(self, params)
if params.event == "DeviceButton_left mouse button" then
packlist:SortByOverall()
self:GetParent():queuecommand("Update")
end
end
},
UIElements.TextToolTip(1, 1, "Common Normal") .. {
Name = "SizeHeader",
Expand All @@ -138,6 +162,18 @@ local o = Def.ActorFrame {
self:halign(1)
self:settext(translated_info["Size"])
end,
MouseOverCommand = function(self)
self:diffusealpha(hoverAlpha)
end,
MouseOutCommand = function(self)
self:diffusealpha(1)
end,
MouseDownCommand = function(self, params)
if params.event == "DeviceButton_left mouse button" then
packlist:SortBySize()
self:GetParent():queuecommand("Update")
end
end
},
UIElements.TextToolTip(1, 1, "Common Normal") .. {
Name = "PlaysHeader",
Expand All @@ -147,6 +183,18 @@ local o = Def.ActorFrame {
self:halign(1)
self:settext(translated_info["PackPlays"])
end,
MouseOverCommand = function(self)
self:diffusealpha(hoverAlpha)
end,
MouseOutCommand = function(self)
self:diffusealpha(1)
end,
MouseDownCommand = function(self, params)
if params.event == "DeviceButton_left mouse button" then
packlist:SortByPlays()
self:GetParent():queuecommand("Update")
end
end
},
UIElements.TextToolTip(1, 1, "Common Normal") .. {
Name = "SongCountHeader",
Expand All @@ -156,6 +204,18 @@ local o = Def.ActorFrame {
self:halign(1)
self:settext(translated_info["SongCount"])
end,
MouseOverCommand = function(self)
self:diffusealpha(hoverAlpha)
end,
MouseOutCommand = function(self)
self:diffusealpha(1)
end,
MouseDownCommand = function(self, params)
if params.event == "DeviceButton_left mouse button" then
packlist:SortBySongs()
self:GetParent():queuecommand("Update")
end
end
},
LoadFont("Common Large") .. {
Name = "AwaitingOrNoResults",
Expand Down
40 changes: 39 additions & 1 deletion Themes/_fallback/Scripts/09 PackList.lua
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ end

-- execute a seach. usually this invokes a request unless it is a duplicate
function PackList:FilterAndSearch(name, tags, perPage)
self.currentPagination = DLMAN:GetPackPagination(name, tags, perPage)
self.lastName = name
self.lastTags = tags
self.lastPerPage = perPage
self.currentPagination = DLMAN:GetPackPagination(name, tags, perPage, self.sortColumn, self.sortIsAscending)

if not self:IsAwaitingRequest() then
self.currentPagination:GetResults(whenRequestFinished(self))
Expand All @@ -73,10 +76,45 @@ function PackList:FilterAndSearch(name, tags, perPage)
return self
end

function PackList:SortByColumn(column)
if column == self.sortColumn then
self.sortIsAscending = not self.sortIsAscending
else
self.sortColumn = column
self.sortIsAscending = true
end
self:FilterAndSearch(self.lastName, self.lastTags, self.lastPerPage)
end

function PackList:SortByName()
self:SortByColumn("name")
end

function PackList:SortByPlays()
self:SortByColumn("play_count")
end

function PackList:SortBySize()
self:SortByColumn("bytes")
end

function PackList:SortBySongs()
self:SortByColumn("song_count")
end

function PackList:SortByOverall()
self:SortByColumn("overall")
end

function PackList:new()
local packlist = {}
packlist.packs = {} -- represents the packs on the current visible page
packlist.currentPagination = nil -- represents the internal pack search pagination
packlist.sortColumn = "name"
packlist.sortIsAscending = true
packlist.lastName = ""
packlist.lastTags = {}
packlist.lasPerPage = 1
setmetatable(
packlist,
{
Expand Down
54 changes: 48 additions & 6 deletions src/Etterna/Singletons/DownloadManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5475,6 +5475,25 @@ ApiSearchCriteriaToJSONBody(const ApiSearchCriteria& criteria)

Value arrDoc(kArrayType);

std::string sortByField = "name";
if (!criteria.sortBy.empty()) {
if (criteria.sortBy != sortByField) {
// this allows even further custom sorting
// if you know what you are doing...
sortByField =
fmt::format("{}:{},name:asc",
criteria.sortBy,
criteria.sortIsAscending ? "asc" : "desc");
}
else {
// this is always "name:XXXX"
sortByField =
fmt::format("{}:{}",
criteria.sortBy,
criteria.sortIsAscending ? "asc" : "desc");
}
}

if (!criteria.packName.empty() || !criteria.packTags.empty()) {
Document packSearchDoc;
packSearchDoc.SetObject();
Expand All @@ -5483,6 +5502,8 @@ ApiSearchCriteriaToJSONBody(const ApiSearchCriteria& criteria)
packSearchDoc.AddMember("q", stringToVal(criteria.packName, allocator), allocator);
packSearchDoc.AddMember("query_by", "name", allocator);
packSearchDoc.AddMember("num_typos", "0", allocator);
packSearchDoc.AddMember(
"sort_by", stringToVal(sortByField, allocator), allocator);
if (!criteria.packTags.empty()) {
// this should produce tags:=[`4k`,`5k`] ....
auto tagstr = "tags:=[`" + join("`,`", criteria.packTags) + "`]";
Expand All @@ -5498,6 +5519,8 @@ ApiSearchCriteriaToJSONBody(const ApiSearchCriteria& criteria)
songNameSearchDoc.AddMember(
"q", stringToVal(criteria.songName, allocator), allocator);
songNameSearchDoc.AddMember("query_by", "name", allocator);
songNameSearchDoc.AddMember(
"sort_by", stringToVal(sortByField, allocator), allocator);
arrDoc.PushBack(songNameSearchDoc, allocator);
}
if (!criteria.chartAuthor.empty()) {
Expand All @@ -5508,6 +5531,8 @@ ApiSearchCriteriaToJSONBody(const ApiSearchCriteria& criteria)
authorNameSearchDoc.AddMember(
"q", stringToVal(criteria.chartAuthor, allocator), allocator);
authorNameSearchDoc.AddMember("query_by", "author", allocator);
authorNameSearchDoc.AddMember(
"sort_by", stringToVal(sortByField, allocator), allocator);
arrDoc.PushBack(authorNameSearchDoc, allocator);
}
if (!criteria.songArtist.empty()) {
Expand All @@ -5518,6 +5543,8 @@ ApiSearchCriteriaToJSONBody(const ApiSearchCriteria& criteria)
artistNameSearchDoc.AddMember(
"q", stringToVal(criteria.chartAuthor, allocator), allocator);
artistNameSearchDoc.AddMember("query_by", "artist", allocator);
artistNameSearchDoc.AddMember(
"sort_by", stringToVal(sortByField, allocator), allocator);
arrDoc.PushBack(artistNameSearchDoc, allocator);
}

Expand All @@ -5528,6 +5555,8 @@ ApiSearchCriteriaToJSONBody(const ApiSearchCriteria& criteria)
unfilteredSearchDoc.AddMember("collection", "packs", allocator);
unfilteredSearchDoc.AddMember("q", "", allocator);
unfilteredSearchDoc.AddMember("query_by", "name", allocator);
unfilteredSearchDoc.AddMember(
"sort_by", stringToVal(sortByField, allocator), allocator);
arrDoc.PushBack(unfilteredSearchDoc, allocator);
}

Expand Down Expand Up @@ -5699,12 +5728,15 @@ DownloadManager::GetPackTagsRequest() {
DownloadablePackPagination&
DownloadManager::GetPackPagination(const std::string& searchString,
std::set<std::string> tagFilters,
int perPage)
int perPage,
const std::string& sortBy,
bool sortIsAsc)
{
auto key = DownloadablePackPaginationKey(searchString, tagFilters, perPage);
auto key = DownloadablePackPaginationKey(
searchString, tagFilters, perPage, sortBy, sortIsAsc);
if (!downloadablePackPaginations.contains(key)) {
downloadablePackPaginations[key] =
DownloadablePackPagination(searchString, tagFilters, perPage);
downloadablePackPaginations[key] = DownloadablePackPagination(
searchString, tagFilters, perPage, sortBy, sortIsAsc);
}
return downloadablePackPaginations[key];
}
Expand Down Expand Up @@ -5778,6 +5810,8 @@ DownloadablePackPagination::setPage(int page, LuaReference& whenDone) {
searchCriteria.packTags =
std::vector<std::string>(key.tagFilters.begin(), key.tagFilters.end());
searchCriteria.packName = key.searchString;
searchCriteria.sortBy = key.sortByField;
searchCriteria.sortIsAscending = key.sortIsAsc;

pendingRequest = true;

Expand Down Expand Up @@ -6031,8 +6065,16 @@ class LunaDownloadManager : public Luna<DownloadManager>

auto perPage = IArg(3);

auto& pagination = p->GetPackPagination(searchString, tags, perPage);
pagination.PushSelf(L);
if (lua_isnoneornil(L, 4)) {
auto& pagination =
p->GetPackPagination(searchString, tags, perPage, "name", true);
pagination.PushSelf(L);
}
else {
auto& pagination = p->GetPackPagination(
searchString, tags, perPage, SArg(4), BArg(5));
pagination.PushSelf(L);
}

return 1;
}
Expand Down
33 changes: 28 additions & 5 deletions src/Etterna/Singletons/DownloadManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,38 +111,50 @@ class DownloadablePackPaginationKey
public:
DownloadablePackPaginationKey(const std::string& searchString,
std::set<std::string>& tagFilters,
int perPage)
int perPage,
const std::string& sortField,
bool ascendingSort)
: searchString(searchString)
, tagFilters(tagFilters)
, perPage(perPage)
, sortByField(sortField)
, sortIsAsc(ascendingSort)
{
}
DownloadablePackPaginationKey()
: searchString("")
, tagFilters({})
, perPage(0)
, sortByField("")
, sortIsAsc(true)
{
}

bool operator==(const DownloadablePackPaginationKey& other) const
{
return (perPage == other.perPage) &&
(searchString == other.searchString) &&
(tagFilters == other.tagFilters);
(tagFilters == other.tagFilters) &&
(sortByField == other.sortByField) &&
(sortIsAsc == other.sortIsAsc);
}

std::string searchString{};
std::set<std::string> tagFilters{};
int perPage = 0;
std::string sortByField{};
bool sortIsAsc = true;
};

class DownloadablePackPagination
{
public:
DownloadablePackPagination(const std::string& searchString,
std::set<std::string>& tagFilters,
int perPage)
: key(searchString, tagFilters, perPage)
int perPage,
const std::string& sortByField,
bool sortIsAsc)
: key(searchString, tagFilters, perPage, sortByField, sortIsAsc)
{
}
DownloadablePackPagination(const DownloadablePackPaginationKey& key)
Expand Down Expand Up @@ -283,6 +295,8 @@ struct std::hash<DownloadablePackPaginationKey>
s ^= h(tag) + 0x9e3779b9 + (s << 6) + (s >> 2);
}
r = r * 31 + s;
r = r * 31 + std::hash<std::string>()(k.sortByField);
r = r * 31 + std::hash<bool>()(k.sortIsAsc);
return r;
}
};
Expand All @@ -296,6 +310,9 @@ struct ApiSearchCriteria
std::string songArtist{};
std::vector<std::string> packTags{};

std::string sortBy{};
bool sortIsAscending = true;

// request params (actual names)
int page = 0;
int per_page = 0;
Expand Down Expand Up @@ -323,6 +340,10 @@ struct ApiSearchCriteria
}
o += "]";
}
if (!sortBy.empty()) {
o += fmt::format(
", sortBy: {}:{}", sortBy, sortIsAscending ? "asc" : "desc");
}
return o + ")";
}
};
Expand Down Expand Up @@ -556,7 +577,9 @@ class DownloadManager
DownloadablePackPagination& GetPackPagination(
const std::string& searchString,
std::set<std::string> tagFilters,
int perPage);
int perPage,
const std::string& sortBy,
bool sortIsAsc);

private:
/// Default empty reference for calls allowing Lua functions to be passed
Expand Down

0 comments on commit 644ba2e

Please sign in to comment.