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.
This commit is contained in:
WrinklyNinja
2013-08-14 13:41:14 +01:00
parent 3b4c54b3b9
commit 7532d2cd7f
4 changed files with 40 additions and 9 deletions
+22 -2
View File
@@ -26,6 +26,7 @@
#include <boost/algorithm/string.hpp>
#include <boost/log/trivial.hpp>
#include <boost/graph/breadth_first_search.hpp>
using namespace std;
@@ -244,8 +245,8 @@ namespace boss {
if (overlapIt != overlapMap.end()) {
for (vector<string>::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<vertex_t, size_t> index_map;
boost::associative_property_map< map<vertex_t, size_t> > v_index_map(index_map);
size_t i=0;
BGL_FORALL_VERTICES(v, graph, PluginGraph)
put(v_index_map, v, i++);
map<vertex_t, vertex_t> predecessor_map;
boost::associative_property_map< map<vertex_t, vertex_t> > 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();
}
}
+2
View File
@@ -71,6 +71,8 @@ namespace boss {
void AddOverlapEdges(PluginGraph& graph, const boost::unordered_map< std::string, std::vector<std::string> >& overlapMap);
void ClearEdges(PluginGraph& graph);
bool EdgeCreatesCycle(PluginGraph& graph, vertex_t u, vertex_t v);
}
#endif
+8
View File
@@ -203,6 +203,14 @@ namespace boss {
size_t numOverrideRecords;
};
struct plugin_hash : std::unary_function<Plugin, size_t> {
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);
+8 -7
View File
@@ -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<size_t, boss::Plugin> tempMap;
boost::unordered_map<boss::Plugin, size_t, plugin_hash> 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<size_t, boss::Plugin>::const_iterator it=tempMap.begin(), endit=tempMap.end(); it != endit; ++it) {
for (boost::unordered_map<boss::Plugin, size_t, plugin_hash>::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);
}