From 7532d2cd7f0711306e101c2ecf22003a10d5e144 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Wed, 14 Aug 2013 13:41:14 +0100 Subject: [PATCH] Issue #41. Overlaps can no longer cause cycle-forming edges. Also fixed plugins with the same size not being detected. Not sure about how the edge formation changes affect the sorting validity, haven't checked yet. --- src/backend/graph.cpp | 24 ++++++++++++++++++++++-- src/backend/graph.h | 2 ++ src/backend/metadata.h | 8 ++++++++ src/gui/main.cpp | 15 ++++++++------- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/backend/graph.cpp b/src/backend/graph.cpp index 7b40e1c9..f5333805 100644 --- a/src/backend/graph.cpp +++ b/src/backend/graph.cpp @@ -26,6 +26,7 @@ #include #include +#include using namespace std; @@ -244,8 +245,8 @@ namespace boss { if (overlapIt != overlapMap.end()) { for (vector::const_iterator it=overlapIt->second.begin(), itend=overlapIt->second.end(); it != itend; ++it) { if (boss::GetVertexByName(graph, *it, parentVertex) && - !boost::edge(*vit, parentVertex, graph).second && - !boost::edge(parentVertex, *vit, graph).second) { //No edge going the other way, OK to add this edge. + !boost::edge(parentVertex, *vit, graph).second && + !EdgeCreatesCycle(graph, parentVertex, *vit)) { //No edge going the other way, OK to add this edge. BOOST_LOG_TRIVIAL(trace) << "Adding edge from \"" << graph[parentVertex]->Name() << "\" to \"" << graph[*vit]->Name() << "\"."; @@ -263,4 +264,23 @@ namespace boss { boost::remove_edge(*it, graph); } } + + bool EdgeCreatesCycle(PluginGraph& graph, vertex_t u, vertex_t v) { + //A cycle is created when adding the edge (u,v) if there already exists a path from v to u, so check for that using a breadth-first search. + + //Breadth-first search requires an index map, which std::list-based VertexList graphs don't have, so one needs to be built separately. + + map index_map; + boost::associative_property_map< map > v_index_map(index_map); + size_t i=0; + BGL_FORALL_VERTICES(v, graph, PluginGraph) + put(v_index_map, v, i++); + + map predecessor_map; + boost::associative_property_map< map > v_predecessor_map(predecessor_map); + + boost::breadth_first_search(graph, v, visitor(boost::make_bfs_visitor(boost::record_predecessors(v_predecessor_map, boost::on_tree_edge()))).vertex_index_map(v_index_map)); + + return predecessor_map.find(u) != predecessor_map.end(); + } } diff --git a/src/backend/graph.h b/src/backend/graph.h index 4c7e97e7..cfa1821f 100644 --- a/src/backend/graph.h +++ b/src/backend/graph.h @@ -71,6 +71,8 @@ namespace boss { void AddOverlapEdges(PluginGraph& graph, const boost::unordered_map< std::string, std::vector >& overlapMap); void ClearEdges(PluginGraph& graph); + + bool EdgeCreatesCycle(PluginGraph& graph, vertex_t u, vertex_t v); } #endif diff --git a/src/backend/metadata.h b/src/backend/metadata.h index dc4bd47d..86d1c353 100644 --- a/src/backend/metadata.h +++ b/src/backend/metadata.h @@ -203,6 +203,14 @@ namespace boss { size_t numOverrideRecords; }; + struct plugin_hash : std::unary_function { + inline size_t operator () (const Plugin& p) const { + size_t seed = 0; + boost::hash_combine(seed, p.Name()); + return seed; + } + }; + bool operator == (const File& lhs, const Plugin& rhs); bool operator == (const Plugin& lhs, const File& rhs); diff --git a/src/gui/main.cpp b/src/gui/main.cpp index c6825448..0d4c21ae 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -466,28 +466,29 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { //First calculate the mean plugin size. Store it temporarily in a map to reduce filesystem lookups and file size recalculation. size_t meanFileSize = 0; - boost::unordered_map tempMap; + boost::unordered_map tempMap; for (fs::directory_iterator it(_game.DataPath()); it != fs::directory_iterator(); ++it) { if (fs::is_regular_file(it->status()) && IsPlugin(it->path().string())) { + size_t fileSize = fs::file_size(it->path()); meanFileSize += fileSize; - tempMap.emplace(fileSize, boss::Plugin(it->path().filename().string())); + tempMap.emplace(boss::Plugin(it->path().filename().string()), fileSize); } } meanFileSize /= tempMap.size(); //Now load plugins. plugin_list_loader pll(plugins, _game); - for (boost::unordered_map::const_iterator it=tempMap.begin(), endit=tempMap.end(); it != endit; ++it) { + for (boost::unordered_map::const_iterator it=tempMap.begin(), endit=tempMap.end(); it != endit; ++it) { - BOOST_LOG_TRIVIAL(trace) << "Found plugin: " << it->second.Name(); + BOOST_LOG_TRIVIAL(trace) << "Found plugin: " << it->first.Name(); - plugins.push_back(it->second); + plugins.push_back(it->first); - if (it->first > meanFileSize) { + if (it->second > meanFileSize) { plugin_loader pl(plugins.back(), _game); - pll.skipPlugins.insert(it->second.Name()); + pll.skipPlugins.insert(it->first.Name()); group.create_thread(pl); }