#include "object_categories.h" #include #include namespace dingosdk::objects { namespace { std::string lower(std::string_view value) { std::string result(value); for (auto& c : result) if (c >= 'A' && c <= 'Z') c = static_cast(c + ('a' - 'A')); return result; } } std::map> object_groups(const content_cache::Catalogs& catalogs) { std::map> result; for (const bool browser : {true, false}) for (const auto& category : catalogs.object_categories) if (category.quick_drop == browser) for (const auto& group : category.groups) result.try_emplace(group.id, Placement{&category, &group}); return result; } Placement object_placement(std::string_view key, const content_cache::Catalogs& catalogs, const std::map>& groups) { const auto id = lower(key); if (!catalogs.items.is_object() || !catalogs.items.contains(id)) return {}; const auto& item = catalogs.items.at(id); if (!item.is_object() || !item.contains("group") || !item.at("group").is_string()) return {}; const auto found = groups.find(item.at("group").string()); return found == groups.end() ? Placement{} : found->second; } std::string browser_tile(std::string_view key, const content_cache::Catalogs& catalogs, const std::map>& groups) { const auto placement = object_placement(key, catalogs, groups); return placement.group ? placement.group->id : std::string(key); } std::vector browser_layout(const std::vector& objects, const content_cache::Catalogs& catalogs) { const auto groups = object_groups(catalogs); struct Entry { int rank; BrowserCategory category; }; std::map categories; for (const auto& object : objects) { const auto placement = object_placement(object.key, catalogs, groups); std::string category_id, category_title, tile_id, tile_title; std::uint32_t category_priority{}, tile_priority{}; int rank = 2; if (placement.group) { rank = placement.category->quick_drop ? 0 : 1; category_id = placement.category->id; category_title = placement.category->title; category_priority = placement.category->priority; tile_id = placement.group->id; tile_title = placement.group->title; tile_priority = placement.group->priority; } else { category_id = category_title = object.family; tile_id = object.key; tile_title = object.title; } auto& entry = categories.try_emplace(category_id, Entry{rank, {category_id, category_title, category_priority, {}}}).first->second; auto& tiles = entry.category.tiles; auto tile = std::find_if(tiles.begin(), tiles.end(), [&](const BrowserTile& t) { return t.id == tile_id; }); if (tile == tiles.end()) tile = tiles.insert(tiles.end(), {tile_id, tile_title, tile_priority, {}}); tile->items.push_back(object.key); } std::vector ordered; for (auto& [id, entry] : categories) ordered.push_back(std::move(entry)); std::stable_sort(ordered.begin(), ordered.end(), [](const Entry& a, const Entry& b) { return std::tie(a.rank, a.category.priority, a.category.title) < std::tie(b.rank, b.category.priority, b.category.title); }); std::vector result; for (auto& entry : ordered) { auto& tiles = entry.category.tiles; std::stable_sort(tiles.begin(), tiles.end(), [](const BrowserTile& a, const BrowserTile& b) { return std::tie(a.priority, a.title) < std::tie(b.priority, b.title); }); result.push_back(std::move(entry.category)); } return result; } }