diff --git a/include/gamedetails.h b/include/gamedetails.h index 462268d..5e86cb9 100644 --- a/include/gamedetails.h +++ b/include/gamedetails.h @@ -21,10 +21,12 @@ class gameDetails std::string gamename; std::string title; std::string icon;; + void filterWithPriorities(const Config& config); void makeFilepaths(const Config& config); Json::Value getDetailsAsJson(); virtual ~gameDetails(); protected: + void filterListWithPriorities(std::vector& list, const Config& config); private: }; diff --git a/include/gamefile.h b/include/gamefile.h index eb3b27f..f7d5c76 100644 --- a/include/gamefile.h +++ b/include/gamefile.h @@ -19,6 +19,7 @@ class gameFile std::string size; unsigned int platform; unsigned int language; + int score; int silent; void setFilepath(const std::string& path); std::string getFilepath(); diff --git a/src/api.cpp b/src/api.cpp index d4f7c9c..737d55b 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -518,9 +518,9 @@ gameDetails API::getGameDetails(const std::string& game_name, const unsigned int if (!langpacknames.empty()) // found at least one language pack { - for (unsigned int i = 0; i < langpacknames.size(); ++i) + for (unsigned int j = 0; j < langpacknames.size(); ++j) { - Json::Value langpack = root["game"][langpacknames[i]]; + Json::Value langpack = root["game"][langpacknames[j]]; game.languagepacks.push_back( gameFile( false, /* language packs don't have "updated" flag */ langpack["id"].isInt() ? std::to_string(langpack["id"].asInt()) : langpack["id"].asString(), diff --git a/src/downloader.cpp b/src/downloader.cpp index a9e4d35..5f9f681 100644 --- a/src/downloader.cpp +++ b/src/downloader.cpp @@ -252,6 +252,8 @@ int Downloader::getGameDetails() game = gogAPI->getGameDetails(gameItems[i].name, conf.iInstallerType, conf.iInstallerLanguage, config.bDuplicateHandler); if (!gogAPI->getError()) { + game.filterWithPriorities(config); + if (game.extras.empty() && config.bExtras) // Try to get extras from account page if API didn't return any extras { game.extras = this->getExtras(gameItems[i].name, gameItems[i].id); @@ -262,6 +264,7 @@ int Downloader::getGameDetails() { gameDetails dlc; dlc = gogAPI->getGameDetails(gameItems[i].dlcnames[j], conf.iInstallerType, conf.iInstallerLanguage, config.bDuplicateHandler); + dlc.filterWithPriorities(config); if (dlc.extras.empty() && config.bExtras) // Try to get extras from account page if API didn't return any extras { dlc.extras = this->getExtras(gameItems[i].dlcnames[j], gameItems[i].id); @@ -2817,7 +2820,10 @@ std::vector Downloader::getGameDetailsFromJsonNode(Json::Value root } } if (!game.extras.empty() || !game.installers.empty() || !game.patches.empty() || !game.languagepacks.empty() || !game.dlcs.empty()) - details.push_back(game); + { + game.filterWithPriorities(config); + details.push_back(game); + } } return details; } @@ -2840,6 +2846,8 @@ void Downloader::updateCache() config.sGameRegex = ".*"; config.iInstallerLanguage = all_languages; config.iInstallerType = all_platforms; + config.vLanguagePriority.clear(); + config.vPlatformPriority.clear(); this->getGameList(); this->getGameDetails(); diff --git a/src/gamedetails.cpp b/src/gamedetails.cpp index 9829475..ae02b18 100644 --- a/src/gamedetails.cpp +++ b/src/gamedetails.cpp @@ -11,6 +11,61 @@ gameDetails::~gameDetails() //dtor } +void gameDetails::filterWithPriorities(const Config& config) +{ + if (config.vPlatformPriority.empty() && config.vLanguagePriority.empty()) + return; + + filterListWithPriorities(installers, config); + filterListWithPriorities(patches, config); + filterListWithPriorities(languagepacks, config); +} + +void gameDetails::filterListWithPriorities(std::vector& list, const Config& config) +{ + /* + Compute the score of each item - we use a scoring mechanism and we keep all ties + Like if someone asked French then English and Linux then Windows, but there are + only Windows French, Windows English and Linux English versions, we'll get the + Windows French and Linux English ones. + Score is inverted: lower is better. + */ + int bestscore = -1; + + for (std::vector::iterator fileDetails = list.begin(); fileDetails != list.end(); fileDetails++) + { + fileDetails->score = 0; + if (!config.vPlatformPriority.empty()) + { + for (size_t i = 0; i != config.vPlatformPriority.size(); i++) + if (fileDetails->platform & config.vPlatformPriority[i]) + { + fileDetails->score += i; + break; + } + } + if (!config.vLanguagePriority.empty()) + { + for (size_t i = 0; i != config.vLanguagePriority.size(); i++) + if (fileDetails->language & config.vLanguagePriority[i]) + { + fileDetails->score += i; + break; + } + } + if ((fileDetails->score < bestscore) or (bestscore < 0)) + bestscore = fileDetails->score; + } + + for (std::vector::iterator fileDetails = list.begin(); fileDetails != list.end(); ) + { + if (fileDetails->score > bestscore) + fileDetails = list.erase(fileDetails); + else + fileDetails++; + } +} + void gameDetails::makeFilepaths(const Config& config) { std::string filepath;