-
Notifications
You must be signed in to change notification settings - Fork 0
/
Archipelago.cpp
155 lines (141 loc) · 4.59 KB
/
Archipelago.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "Archipelago.h"
#include <string>
#include <boost/graph/graphviz.hpp>
//#include <boost/utility.hpp>
#include "Factory.h"
#include "Vehicle.h"
#include "GraphTypes.h"
Archipelago::Archipelago(const std::string& islandFile, const std::string& linkFile)
{
// read from file if present
std::string currentFileRead = islandFile;
try
{
// consume island data file
std::ifstream is(islandFile);
if (is.good())
{
// digest file
std::istream_iterator<std::string> start(is), end;
std::vector<std::string> islandDataStrings = std::vector<std::string>(start, end);
// extact data to property set
std::vector<IslandProperties> islandNodes(islandDataStrings.size());
std::transform (islandDataStrings.begin(), islandDataStrings.end(), islandNodes.begin(), ExtractIslandData);
// insert data into graph
for ( auto island : islandNodes )
{
vertex_t u = boost::add_vertex(m_islandGraph);
m_islandGraph[u].name = island.name;
m_islandGraph[u].terrain = island.terrain;
}
}
currentFileRead = linkFile;
is = std::ifstream(linkFile);
if (is.good())
{
// digest file
std::istream_iterator<std::string> start(is), end;
std::vector<std::string> linkDataStrings = std::vector<std::string>(start, end);
// extact data to property set
std::vector<LinkData> linkData(linkDataStrings.size());
std::transform (linkDataStrings.begin(), linkDataStrings.end(), linkData.begin(), ExtractLinkData);
// insert data into graph
for ( auto link : linkData )
{
unsigned int searchResultA;
unsigned int searchResultB;
if (FindIslandByName(link.nodeNameA, searchResultA) && FindIslandByName(link.nodeNameB, searchResultB))
{
link.resolvedNodeA = searchResultA;
link.resolvedNodeB = searchResultB;
}
else
{
throw std::runtime_error("Error: could not find one of " + link.nodeNameA + " or " + link.nodeNameB + "in island nodes\n");
}
// Create an edge conecting those two vertices
edge_t e; bool b;
Graph::vertex_descriptor u = *vertices(m_islandGraph).first + link.resolvedNodeA;
Graph::vertex_descriptor v = *vertices(m_islandGraph).first + link.resolvedNodeB;
boost::tie(e,b) = boost::add_edge(u,v,m_islandGraph);
// Set the properties of a vertex and the edge
m_islandGraph[e].linkType = link.properties.linkType;
}
}
}
catch (std::runtime_error& error)
{
throw std::runtime_error(error.what() + std::string("Error in file: ") + currentFileRead + "\n");
}
}
bool Archipelago::FindIslandByName(const std::string& name, IslandHandle& island)
{
// search class dict for mapping
auto searchResult = m_vertexDict.find(name);
if (searchResult != m_vertexDict.end())
{
island = searchResult->second;
return true;
}
// if key not in dict then find through search
// get the property map for vertex indices
boost::graph_traits<Graph>::vertex_iterator it, end;
for (boost::tie( it, end ) = vertices(m_islandGraph); it != end; ++it)
{
if (m_islandGraph[*it].name == name)
{
island = *it;
m_vertexDict[name] = island;
return true;
}
}
return false;
}
bool Archipelago::FindIslandNameByHandle(IslandHandle island, std::string& name) const
{
// scan key value pair for match
for ( auto kv : m_vertexDict )
{
if (kv.second == island)
{
name = kv.first;
return true;
}
}
return false;
}
void Archipelago::Visit(VehicleBase& vehicle) const
{
try
{
// get the property map for vertex indices
typedef boost::property_map<Graph, boost::vertex_index_t>::type IndexMap;
IndexMap index = get(boost::vertex_index, m_islandGraph);
// for each adjacent node find route data
std::vector<RaceLegProperties> availableLinks;
auto adjacentEdges = m_islandGraph.out_edge_list(vehicle.GetIsland());
for (auto link : adjacentEdges)
{
// find edge connecting location and adjacent node
edge_t edge; bool edgeFound;
Graph::vertex_descriptor currentIsland = *vertices(m_islandGraph).first + vehicle.GetIsland();
Graph::vertex_descriptor adjacentIsland = *vertices(m_islandGraph).first + link.m_target;
boost::tie(edge, edgeFound) = boost::edge(currentIsland, adjacentIsland, m_islandGraph);
// copy data route data to be passed to vehicle
if ( edgeFound )
{
RaceLegProperties leg;
leg.linkType = m_islandGraph[edge].linkType;
leg.targetNode = link.m_target;
leg.terrain = m_islandGraph[leg.targetNode].terrain;
availableLinks.push_back(leg);
}
}
// pass all available routes to vehicle
vehicle.ChooseNextIsland(availableLinks);
}
catch (std::exception& error)
{
std::cerr << vehicle.ToString() << " has a problem: " << error.what() << "\n";
}
}