Fixed multiple issues with random selection of systems and games.

This commit is contained in:
Leon Styhre 2020-07-28 15:19:54 +02:00
parent ce9d5c2599
commit ea59d9f9c4
8 changed files with 115 additions and 35 deletions

View file

@ -62,6 +62,9 @@ Many bugs have been fixed, and numerous features that were only partially implem
* Toggling the screensaver didn't work as expected
* The setting to enable or disable audio for the video screensaver only worked on Raspberry Pi
* The screensaver random function did not consider the previously selected game and could potentially show the same image or video over and over again
* The random system selection did not consider the currently selected system
* The random game selection did not consider the currently selected game
* The random game selection traversed folders, i.e. a game could be selected inside a subdirectory and vice versa
* Deleting a game did not delete the game media files or its entry in the gamelist.xml file
* SystemView didn't properly loop the systems if only two systems were available
* Hidden files still showed up if they had a gamelist.xml entry

View file

@ -729,10 +729,12 @@ void CollectionSystemManager::updateCollectionFolderMetadata(SystemData* sys)
FileData* randomGame = sys->getRandomGame();
if (randomGame) {
video = randomGame->getVideoPath();
thumbnail = randomGame->getThumbnailPath();
image = randomGame->getImagePath();
}
}
rootFolder->metadata.set("desc", desc);
rootFolder->metadata.set("rating", rating);

View file

@ -114,7 +114,7 @@ const bool FileData::getHidden()
return false;
}
const std::vector<FileData*> FileData::getChildrenRercursive() const
const std::vector<FileData*> FileData::getChildrenRecursive() const
{
std::vector<FileData*> childrenRecursive;
@ -123,7 +123,7 @@ const std::vector<FileData*> FileData::getChildrenRercursive() const
childrenRecursive.push_back((*it).second);
// Recurse through any subdirectories.
if ((*it).second->getType() == FOLDER) {
std::vector<FileData*> childrenSubdirectory = (*it).second->getChildrenRercursive();
std::vector<FileData*> childrenSubdirectory = (*it).second->getChildrenRecursive();
childrenRecursive.insert(childrenRecursive.end(),
childrenSubdirectory.begin(), childrenSubdirectory.end());
}

View file

@ -48,7 +48,7 @@ public:
const std::string& getSortName();
const bool getFavorite();
const bool getHidden();
const std::vector<FileData*> getChildrenRercursive() const;
const std::vector<FileData*> getChildrenRecursive() const;
inline FileType getType() const { return mType; }
inline const std::string& getPath() const { return mPath; }
inline FileData* getParent() const { return mParent; }

View file

@ -329,7 +329,7 @@ bool SystemData::loadConfig()
// games for the system are hidden. That will flag the system as empty.
if (!Settings::getInstance()->getBool("ShowHiddenGames")) {
std::vector<FileData*> recursiveGames =
newSys->getRootFolder()->getChildrenRercursive();
newSys->getRootFolder()->getChildrenRecursive();
onlyHidden = true;
for (auto it = recursiveGames.cbegin(); it != recursiveGames.cend(); it++) {
if ((*it)->getType() != FOLDER) {
@ -490,44 +490,110 @@ unsigned int SystemData::getGameCount() const
return (unsigned int)mRootFolder->getFilesRecursive(GAME).size();
}
SystemData* SystemData::getRandomSystem()
SystemData* SystemData::getRandomSystem(const SystemData* currentSystem)
{
// This is a bit brute force.
// It might be more efficient to just do a while (!gameSystem) do random again...
unsigned int total = 0;
for (auto it = sSystemVector.cbegin(); it != sSystemVector.cend(); it++) {
if ((*it)->isGameSystem())
total++;
}
if (total < 2)
return nullptr;
SystemData* randomSystem;
do {
// Get a random number in range.
int target = (int)Math::round((std::rand() / (float)RAND_MAX) * (total - 1));
for (auto it = sSystemVector.cbegin(); it != sSystemVector.cend(); it++)
{
if ((*it)->isGameSystem()) {
if (target > 0)
target--;
else
return (*it);
}
}
// If we end up here, there is no valid system.
return nullptr;
for (auto it = sSystemVector.cbegin(); it != sSystemVector.cend(); it++) {
if ((*it)->isGameSystem()) {
if (target > 0) {
target--;
}
else {
randomSystem = (*it);
break;
}
}
}
}
while (randomSystem == currentSystem);
return randomSystem;
}
FileData* SystemData::getRandomGame()
FileData* SystemData::getRandomCollectionFolder(const FileData* currentFolder)
{
std::vector<FileData*> list = mRootFolder->getFilesRecursive(GAME, true);
unsigned int total = (int)list.size();
if (!currentFolder)
return nullptr;
std::vector<FileData*> collectionFolders = currentFolder->getParent()->getChildren();
unsigned int total = collectionFolders.size();
int target = 0;
// Get a random number in range.
if (total == 0)
if (total < 2)
return nullptr;
target = (int)Math::round((std::rand() / (float)RAND_MAX) * (total - 1));
return list.at(target);
do {
// Get a random number in range.
target = (int)Math::round((std::rand() / (float)RAND_MAX) * (total - 1));
}
while (collectionFolders.at(target) == currentFolder);
return collectionFolders.at(target);
}
FileData* SystemData::getRandomGame(const FileData* currentGame)
{
std::vector<FileData*> gameList = mRootFolder->getFilesRecursive(GAME, true);
if (currentGame) {
// If the game is inside a folder, update gameList to only contain the games
// inside this folder.
if (currentGame->getParent()->getFullPath() !=
currentGame->getSystem()->getRootFolder()->getFullPath()) {
std::vector<FileData*> folderList;
for (auto it = gameList.cbegin(); it != gameList.cend(); it++) {
if ((*it)->getParent()->getFullPath() == currentGame->getParent()->getFullPath())
folderList.push_back((*it));
}
gameList.erase(gameList.cbegin(), gameList.cend());
gameList.reserve(folderList.size());
gameList.insert(gameList.cend(), folderList.cbegin(), folderList.cend());
}
// If the game is not inside a folder, update gameList to exclude all folders.
else {
std::vector<FileData*> childrenList = mRootFolder->getChildren();
std::vector<FileData*> noFolderList;
for (auto it = childrenList.cbegin(); it != childrenList.cend(); it++) {
if ((*it)->getType() == GAME)
noFolderList.push_back((*it));
}
gameList.erase(gameList.cbegin(), gameList.cend());
gameList.reserve(noFolderList.size());
gameList.insert(gameList.cend(), noFolderList.cbegin(), noFolderList.cend());
}
}
unsigned int total = (int)gameList.size();
int target = 0;
if (total < 2)
return nullptr;
do {
// Get a random number in range.
target = (int)Math::round((std::rand() / (float)RAND_MAX) * (total - 1));
}
while (currentGame && gameList.at(target) == currentGame);
return gameList.at(target);
}
unsigned int SystemData::getDisplayedGameCount() const

View file

@ -86,8 +86,9 @@ public:
SystemData* getNext() const;
SystemData* getPrev() const;
static SystemData* getRandomSystem();
FileData* getRandomGame();
static SystemData* getRandomSystem(const SystemData* currentSystem);
static FileData* getRandomCollectionFolder(const FileData* currentFolder);
FileData* getRandomGame(const FileData* currentGame = nullptr);
// Load or re-load theme.
void loadTheme();

View file

@ -195,7 +195,7 @@ bool SystemView::input(InputConfig* config, Input input)
// Get random system.
// Go to system.
NavigationSounds::getInstance()->playThemeNavigationSound(SYSTEMBROWSESOUND);
setCursor(SystemData::getRandomSystem());
setCursor(SystemData::getRandomSystem(getSelected()));
return true;
}
}

View file

@ -141,9 +141,17 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
if (mRoot->getSystem()->isGameSystem()) {
// Go to random system game.
NavigationSounds::getInstance()->playThemeNavigationSound(SCROLLSOUND);
FileData* randomGame = getCursor()->getSystem()->getRandomGame();
FileData* randomGame = getCursor()->getSystem()->getRandomGame(getCursor());
if (randomGame)
setCursor(randomGame);
// If it's not a game, maybe it's a folder for an unthemed collection.
else if (getCursor()->getSystem()->isCollection()) {
FileData* randomFolder =
mRoot->getSystem()->getRandomCollectionFolder(getCursor());
if (randomFolder)
setCursor(randomFolder);
}
return true;
}
}