Skip to content

Commit

Permalink
Fixes for filters based on playcount, playtime, file availability
Browse files Browse the repository at this point in the history
- correctly update filter list after playing a game if list is sorted
  on playcount or playtime, including by repositioning current selection
  if necessary
- switch statistics to be kept per game and emulator instead of per game
  and romlist
- added lazier loading of play stats, only load them if/when necessary
  • Loading branch information
mickelson committed Feb 13, 2023
1 parent 54ce6b9 commit 6feddfa
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 65 deletions.
12 changes: 10 additions & 2 deletions src/fe_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,11 @@ void FeRomInfo::load_stats( const std::string &path )
m_info[PlayedCount] = "0";
m_info[PlayedTime] = "0";

std::string filename = path + m_info[Romname] + FE_STAT_FILE_EXTENSION;
if ( path.empty() )
return;

std::string filename = path + m_info[Emulator] + "/"
+ m_info[Romname] + FE_STAT_FILE_EXTENSION;
nowide::ifstream myfile( filename.c_str() );

if ( !myfile.is_open() )
Expand All @@ -144,13 +148,17 @@ void FeRomInfo::load_stats( const std::string &path )

void FeRomInfo::update_stats( const std::string &path, int count_incr, int played_incr )
{
load_stats( path );

int new_count = as_int( m_info[PlayedCount] ) + count_incr;
int new_time = as_int( m_info[PlayedTime] ) + played_incr;

m_info[PlayedCount] = as_str( new_count );
m_info[PlayedTime] = as_str( new_time );

std::string filename = path + m_info[Romname] + FE_STAT_FILE_EXTENSION;
confirm_directory( path, m_info[Emulator] );
std::string filename = path + m_info[Emulator] + "/"
+ m_info[Romname] + FE_STAT_FILE_EXTENSION;
nowide::ofstream myfile( filename.c_str() );

if ( !myfile.is_open() )
Expand Down
74 changes: 50 additions & 24 deletions src/fe_romlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
const char *FE_ROMLIST_FILE_EXTENSION = ".txt";
const char *FE_FAVOURITE_FILE_EXTENSION = ".tag";

const char *FE_ROMLIST_SUBDIR = "romlists/";
const char *FE_STATS_SUBDIR = "stats/";

SQRex *FeRomListSorter::m_rex = NULL;

void FeRomListSorter::init_title_rex( const std::string &re_mask )
Expand Down Expand Up @@ -141,6 +144,7 @@ FeRomList::FeRomList( const std::string &config_path )
m_fav_changed( false ),
m_tags_changed( false ),
m_availability_checked( false ),
m_played_stats_checked( false ),
m_group_clones( false )
{
}
Expand All @@ -151,13 +155,13 @@ FeRomList::~FeRomList()

void FeRomList::init_as_empty_list()
{
m_user_path.clear();
m_romlist_name.clear();
m_list.clear();
m_filtered_list.clear();
m_filtered_list.push_back( FeFilterEntry() ); // there always has to be at least one filter
m_tags.clear();
m_availability_checked = false;
m_played_stats_checked = false;
m_group_clones = false;
m_fav_changed=false;
m_tags_changed=false;
Expand All @@ -174,16 +178,16 @@ void FeRomList::mark_favs_and_tags_changed()

bool FeRomList::load_romlist( const std::string &path,
const std::string &romlist_name,
const std::string &user_path,
const std::string &stat_path,
FeDisplayInfo &display,
bool group_clones )
bool group_clones,
bool load_stats )
{
m_user_path = user_path;
m_romlist_name = romlist_name;

m_list.clear();
m_availability_checked = false;
m_played_stats_checked = !load_stats;

m_group_clones = group_clones;

int global_filtered_out_count = 0;
Expand All @@ -207,7 +211,7 @@ bool FeRomList::load_romlist( const std::string &path,
m_extra_favs.clear();
m_fav_changed=false;

std::string load_name( m_user_path + m_romlist_name + FE_FAVOURITE_FILE_EXTENSION );
std::string load_name( m_config_path + FE_ROMLIST_SUBDIR + m_romlist_name + FE_FAVOURITE_FILE_EXTENSION );
nowide::ifstream myfile( load_name.c_str() );

if ( myfile.is_open() )
Expand Down Expand Up @@ -239,7 +243,7 @@ bool FeRomList::load_romlist( const std::string &path,
m_tags.clear();
m_extra_tags.clear();
m_tags_changed=false;
load_name = m_user_path + m_romlist_name + "/";
load_name = m_config_path + FE_ROMLIST_SUBDIR + m_romlist_name + "/";

if ( directory_exists( load_name ) )
{
Expand Down Expand Up @@ -287,9 +291,14 @@ bool FeRomList::load_romlist( const std::string &path,
{
first_filter->init();

if ( first_filter->test_for_target( FeRomInfo::FileIsAvailable ) )
if ( first_filter->test_for_target( FeRomInfo::FileIsAvailable )
|| ( first_filter->get_sort_by() == FeRomInfo::FileIsAvailable ))
get_file_availability();

if ( first_filter->test_for_target( FeRomInfo::PlayedCount )
|| first_filter->test_for_target( FeRomInfo::PlayedTime ) )
get_played_stats();

FeRomInfoListType::iterator last_it=m_list.begin();
for ( FeRomInfoListType::iterator it=m_list.begin(); it!=m_list.end(); )
{
Expand Down Expand Up @@ -342,15 +351,6 @@ bool FeRomList::load_romlist( const std::string &path,
m_list.erase( last_it, m_list.end() );
}

//
// make sure stats are loaded now
//
if ( !stat_path.empty() )
{
for ( FeRomInfoListType::iterator it=m_list.begin(); it!=m_list.end(); ++it )
(*it).load_stats( stat_path );
}

FeLog() << " - Loaded master romlist '" << m_romlist_name
<< "' in " << load_timer.getElapsedTime().asMilliseconds()
<< " ms (" << m_list.size() << " entries kept, " << global_filtered_out_count
Expand Down Expand Up @@ -384,9 +384,14 @@ void FeRomList::build_single_filter_list( FeFilter *f,
if ( f->get_size() > 0 ) // if this is non zero then we've loaded before and know how many to expect
result.filter_list.reserve( f->get_size() );

if ( f->test_for_target( FeRomInfo::FileIsAvailable ) )
if (( f->test_for_target( FeRomInfo::FileIsAvailable ) )
|| ( f->get_sort_by() == FeRomInfo::FileIsAvailable ))
get_file_availability();

if ( f->test_for_target( FeRomInfo::PlayedCount )
|| f->test_for_target( FeRomInfo::PlayedTime ) )
get_played_stats();

f->init();

for ( FeRomInfoListType::iterator itr=m_list.begin(); itr!=m_list.end(); ++itr )
Expand Down Expand Up @@ -465,6 +470,10 @@ void FeRomList::build_single_filter_list( FeFilter *f,

if ( sort_by != FeRomInfo::LAST_INDEX )
{
if (( sort_by == FeRomInfo::PlayedCount )
|| ( sort_by == FeRomInfo::PlayedTime ))
get_played_stats();

std::stable_sort( result.filter_list.begin(),
result.filter_list.end(),
FeRomListSorter2( sort_by, rev ) );
Expand Down Expand Up @@ -565,7 +574,7 @@ void FeRomList::save_state()

void FeRomList::save_favs()
{
if (( !m_fav_changed ) || ( m_user_path.empty() ) || ( m_romlist_name.empty() ))
if (( !m_fav_changed ) || ( m_romlist_name.empty() ))
return;

//
Expand All @@ -580,7 +589,7 @@ void FeRomList::save_favs()
//
// Now save the contents of favs list
//
std::string fname = m_user_path + m_romlist_name + FE_FAVOURITE_FILE_EXTENSION;
std::string fname = m_config_path + FE_ROMLIST_SUBDIR + m_romlist_name + FE_FAVOURITE_FILE_EXTENSION;

if ( m_extra_favs.empty() )
{
Expand All @@ -601,7 +610,7 @@ void FeRomList::save_favs()

void FeRomList::save_tags()
{
if (( !m_tags_changed ) || ( m_user_path.empty() ) || ( m_romlist_name.empty() ))
if (( !m_tags_changed ) || ( m_romlist_name.empty() ))
return;

// First construct a mapping of tags to rom entries
Expand Down Expand Up @@ -637,8 +646,9 @@ void FeRomList::save_tags()
} while ( pos < my_tags.size() );
}

confirm_directory( m_user_path, m_romlist_name );
std::string my_path = m_user_path + m_romlist_name + "/";
std::string user_path = m_config_path + FE_ROMLIST_SUBDIR;
confirm_directory( user_path, m_romlist_name );
std::string my_path = user_path + m_romlist_name + "/";

//
// Now save the tags
Expand Down Expand Up @@ -764,7 +774,7 @@ bool FeRomList::fix_filters( FeDisplayInfo &display, FeRomInfo::Index target )
FeFilter *f = display.get_filter( i );
ASSERT( f );

if ( f->test_for_target( target ) )
if ( f->test_for_target( target ) || ( f->get_sort_by() == target ) )
{
m_filtered_list[i].clear();
build_single_filter_list( f, m_filtered_list[i] );
Expand Down Expand Up @@ -810,6 +820,22 @@ void FeRomList::get_file_availability()
}
}

void FeRomList::get_played_stats()
{
if ( m_played_stats_checked )
return;

for ( FeRomInfoListType::iterator itr=m_list.begin(); itr != m_list.end(); ++itr )
(*itr).load_stats( m_config_path + FE_STATS_SUBDIR );

m_played_stats_checked = true;
}

void FeRomList::load_stats( int filter_idx, int idx )
{
lookup( filter_idx, idx ).load_stats( m_config_path + FE_STATS_SUBDIR );
}

// NOTE: this function is implemented in fe_settings.cpp
bool internal_resolve_config_file(
const std::string &config_path,
Expand Down
26 changes: 16 additions & 10 deletions src/fe_romlist.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

typedef std::list<FeRomInfo> FeRomInfoListType;
extern const char *FE_ROMLIST_FILE_EXTENSION;
extern const char *FE_ROMLIST_SUBDIR;
extern const char *FE_STATS_SUBDIR;

//
// Comparison used when sorting/merging FeRomLists
Expand Down Expand Up @@ -90,12 +92,12 @@ class FeRomList : public FeBaseConfigurable
std::multimap< std::string, const char * > m_extra_tags; // store for tags that are filtered out by global filter
FeFilter *m_global_filter_ptr; // this will only get set if we are globally filtering out games during the initial load

std::string m_user_path;
std::string m_romlist_name;
const std::string &m_config_path;
bool m_fav_changed;
bool m_tags_changed;
bool m_availability_checked;
bool m_played_stats_checked;
bool m_group_clones;
int m_global_filtered_out_count; // for keeping stats during load

Expand All @@ -106,12 +108,7 @@ class FeRomList : public FeBaseConfigurable
//
void build_single_filter_list( FeFilter *f, FeFilterEntry &result );

// Fixes m_filtered_list as needed using the filters in the given "display", with the
// assumption that the specified "target" attribute for all games might have been changed
//
// returns true if list changes might have been made
//
bool fix_filters( FeDisplayInfo &display, FeRomInfo::Index target );
void get_played_stats();

void save_favs();
void save_tags();
Expand All @@ -124,10 +121,9 @@ class FeRomList : public FeBaseConfigurable

bool load_romlist( const std::string &romlist_path,
const std::string &romlist_name,
const std::string &user_path,
const std::string &stat_path,
FeDisplayInfo &display,
bool group_clones );
bool group_clones,
bool load_stats );

void create_filters( FeDisplayInfo &display ); // called by load_romlist()

Expand All @@ -154,6 +150,16 @@ class FeRomList : public FeBaseConfigurable

void get_file_availability();

void load_stats( int filter_idx, int idx );

// Fixes m_filtered_list as needed using the filters in the given "display", with the
// assumption that the specified "target" attribute for all games might have been changed
//
// returns true if list changes might have been made
//
bool fix_filters( FeDisplayInfo &display, FeRomInfo::Index target );


FeEmulatorInfo *get_emulator( const std::string & );
FeEmulatorInfo *create_emulator( const std::string &, const std::string & );
void delete_emulator( const std::string & );
Expand Down
Loading

0 comments on commit 6feddfa

Please sign in to comment.