Bridges-C++  3.4.1
Bridges(C++API)
DataSource.h
Go to the documentation of this file.
1 #ifndef DATA_SOURCE_H
2 #define DATA_SOURCE_H
3 
4 #include <vector>
5 #include <string>
6 #include <unordered_map>
7 #include <set>
8 
9 using namespace std;
10 
11 #include <JSONutil.h>
13 #include "./data_src/Game.h"
14 #include "./data_src/Shakespeare.h"
18 #include "./data_src/Song.h"
20 #include "./data_src/OSMData.h"
21 #include "./data_src/OSMVertex.h"
22 #include "./data_src/OSMEdge.h"
24 #include "./data_src/Amenity.h"
25 #include "./data_src/Reddit.h"
26 #include "./data_src/City.h"
27 #include "ColorGrid.h"
28 #include "base64.h"
29 #include <GraphAdjList.h>
30 #include <ServerComm.h>
31 #include <Bridges.h>
32 #include "rapidjson/document.h"
33 #include "assert.h"
34 #include "rapidjson/error/en.h"
35 #include <fstream>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <stdio.h>
39 
40 
41 #include <Cache.h>
42 
43 
44 namespace bridges {
45  using namespace bridges::dataset;
46  using namespace bridges::datastructure;
47 
48 
49 
50 
63  class DataSource {
64 
65  private:
66 
67  bool debug_flag = false;
68 
69  int debug() const {
70  return debug_flag;
71  }
72 
73  void set_debug_flag() {
74  debug_flag = true;
75  }
76 
77  bridges::Bridges* bridges_inst;
78  bridges::lruCache my_cache;
79 
80 
81  string getOSMBaseURL() const {
82  if (sourceType == "local")
83  return "http://localhost:3000/";
84 
85  return "http://bridges-data-server-osm.bridgesuncc.org/";
86  }
87  string getElevationBaseURL() const {
88  if (sourceType == "local")
89  return "http://localhost:3000/";
90 
91  return "http://bridges-data-server-elevation.bridgesuncc.org/";
92  }
93  string getGutenbergBaseURL() const {
94  if (sourceType == "local")
95  return "http://localhost:3000/";
96 
97  if (sourceType == "testing")
98  return "http://bridges-data-server-gutenberg-t.bridgesuncc.org/";
99 
100  return "http://bridges-data-server-gutenberg.bridgesuncc.org/";
101  }
102  string getRedditURL() {
103  if (sourceType == "testing")
104  return "http://bridges-data-server-reddit-t.bridgesuncc.org";
105  else if (sourceType == "local")
106  return "http://localhost:9999";
107  else
108  return "http://bridges-data-server-reddit.bridgesuncc.org";
109  }
110 
111  string sourceType = "live";
112 
113  string getUSCitiesURL() {
114  return "http://bridgesdata.herokuapp.com/api/us_cities";
115  }
116 
117  public:
119  : bridges_inst(br), my_cache(120) {}
120 
122  : DataSource(&br) {}
123 
131  void setSourceType(string type) {
132  if ( !((type == "live") || (type == "testing") || (type == "local")))
133  throw "Incorrect data server type. Must be live, testing or local";
134  if ((type == "testing") || (type == "local"))
135  debug_flag = true;
136 
137  sourceType = type;
138  }
139 
162  vector<City> getUSCities (unordered_map<string, string> params) {
163  // check the parameters for illegal keys
164  // get the legal keys into a set
165  set<string> keys;
166  keys.insert("city"); keys.insert("state"); keys.insert("country");
167  keys.insert("min_elev"); keys.insert("max_elev");
168  keys.insert("min_pop"); keys.insert("max_pop");
169  keys.insert("min_long"); keys.insert("max_long");
170  keys.insert("min_lat"); keys.insert("max_lat");
171  keys.insert("limit"); keys.insert("time_zone");
172 
173  unordered_map<string, string>::iterator it;
174  for (it = params.begin(); it != params.end(); it++) {
175  if (keys.find(it->first) == keys.end())
176  throw std::invalid_argument ("\n\nKey value : " + it->first +
177  " incorrect\n\n Legal key values: \n 'city', 'state', 'country', 'min_lat', 'max_lat', 'min_long', 'max_long', 'min_pop', 'max_pop', 'time_zone', 'limit' ");
178  }
179 
180 
181  string url = getUSCitiesURL() + "?";
182  if (params.find("city") != params.end())
183  url += "city=" + params["city"] + "&";
184  if (params.find("state") != params.end())
185  url += "state=" + params["state"] + "&";
186  if (params.find("country") != params.end())
187  url += "country=" + params["country"] + "&";
188  if (params.find("min_lat") != params.end())
189  url += "minLat=" + params["min_lat"] + "&";
190  if (params.find("max_lat") != params.end())
191  url += "maxLat=" + params["max_lat"] + "&";
192  if (params.find("min_long") != params.end())
193  url += "minLong=" + params["min_long"] + "&";
194  if (params.find("max_long") != params.end())
195  url += "maxLong=" + params["max_long"] + "&";
196  if (params.find("min_elev") != params.end())
197  url += "minElevation=" + params["min_elev"] + "&";
198  if (params.find("max_elev") != params.end())
199  url += "maxElevation=" + params["max_elev"] + "&";
200  if (params.find("min_pop") != params.end())
201  url += "minPopulation=" + params["min_pop"] + "&";
202  if (params.find("maxPopulation") != params.end())
203  url += "max_pop=" + params["max_pop"] + "&";
204  if (params.find("limit") != params.end())
205  url += "limit=" + params["limit"] + "&";
206 
207  // remove the last &
208  url = url.substr(0, url.length()-1);
209 
210  // make the request
211  using namespace rapidjson;
212  Document doc;
213  doc.Parse(
214  ServerComm::makeRequest(url, {"Accept: application/json"}).c_str()
215  );
216 
217  // parse the json
218  const Value& city_json = doc["data"];
219  vector<City> us_cities;
220  for (SizeType i = 0; i < city_json.Size(); i++) {
221  const Value& val = city_json[i];
222  us_cities.push_back (
223  City(
224  val["city"].GetString(),
225  val["state"].GetString(),
226  val["country"].GetString(),
227  val["timezone"].GetString(),
228  val["elevation"].GetInt(),
229  val["population"].GetInt(),
230  val["lat"].GetDouble(),
231  val["lon"].GetDouble()
232  ));
233  }
234 
235  return us_cities;
236  }
237 
250  vector<Game> getGameData() {
251  using namespace rapidjson;
252  Document d;
253 
254  // request the game dataset and parse it
255  d.Parse(
256  ServerComm::makeRequest("http://bridgesdata.herokuapp.com/api/games",
257  {"Accept: application/json"}).c_str());
258 
259  const Value& D = d["data"];
260  vector<Game> wrapper;
261  for (SizeType i = 0; i < D.Size(); i++) {
262  const Value& V = D[i];
263  const Value& G = V["genre"];
264 
265  vector<string> genre;
266  for (SizeType j = 0; j < G.Size(); j++) {
267  genre.push_back(G[j].GetString());
268  }
269  wrapper.push_back(
270  Game( V["game"].GetString(),
271  V["platform"].GetString(),
272  V["rating"].GetDouble(),
273  genre ) );
274  }
275  return wrapper;
276  }
288  vector<ActorMovieIMDB> getActorMovieIMDBData(int number = 0) {
289  using namespace rapidjson;
290  Document d;
291  vector<ActorMovieIMDB> wrapper;
292  string url = "http://bridgesdata.herokuapp.com/api/imdb?limit=" +
293  to_string(number);
294 
295  // retrieve the data and parse
296  d.Parse(ServerComm::makeRequest( url, {"Accept: application/json"}).c_str());
297 
298  const Value& D = d["data"];
299  for (SizeType i = 0; i < D.Size(); i++) {
300  const Value& V = D[i];
301  wrapper.push_back(
303  V["actor"].GetString(),
304  V["movie"].GetString()
305  )
306  );
307  }
308  return wrapper;
309  }
310 
311 
322  vector<ActorMovieIMDB> getActorMovieIMDBData2() {
323  using namespace rapidjson;
324  Document d;
325  vector<ActorMovieIMDB> wrapper;
326  string url = "http://bridgesdata.herokuapp.com/api/imdb2";
327 
328  // retrieve the data and parse
329  d.Parse(ServerComm::makeRequest( url, {"Accept: application/json"}).c_str());
330 
331  const Value& D = d["data"];
332  for (SizeType i = 0; i < D.Size(); i++) {
333  const Value& V = D[i];
334  string actor = V["actor"].GetString();
335  string movie = V["movie"].GetString();
336  double rating = V["rating"].GetDouble();
337  const Value& G = V["genres"];
338  vector<string> genres;
339  for (SizeType j = 0; j < G.Size(); j++) {
340  genres.push_back(G[j].GetString());
341  }
342  wrapper.push_back(ActorMovieIMDB( actor, movie, (float)rating, genres));
343  }
344  return wrapper;
345  }
346 
358  vector<EarthquakeUSGS> getEarthquakeUSGSData(int number = 0) {
359  using namespace rapidjson;
360  Document d;
361  vector<EarthquakeUSGS> wrapper;
362  if (number <= 0) {
363  d.Parse(ServerComm::makeRequest( "http://earthquakes-uncc.herokuapp.com/eq",
364  {"Accept: application/json"}).c_str());
365  for (SizeType i = 0; i < d.Size(); i++) {
366  const Value& V = d[i]["properties"];
367  const Value& G = d[i]["geometry"]["coordinates"];
368  wrapper.push_back(
370  V["mag"].GetDouble(),
371  G[0].GetDouble(),
372  G[1].GetDouble(),
373  V["place"].GetString(),
374  V["title"].GetString(),
375  V["url"].GetString(),
376  V["time"].GetString() )
377  );
378  }
379  }
380  else {
381  d.Parse(ServerComm::makeRequest( "http://earthquakes-uncc.herokuapp.com/eq/latest/" +
382  to_string(number), {"Accept: application/json"}).c_str());
383 
384  const Value& D = d["Earthquakes"];
385  for (SizeType i = 0; i < D.Size(); i++) {
386  const Value& V = D[i]["properties"];
387  const Value& G = D[i]["geometry"]["coordinates"];
388  // wrapper.push_back({V["mag"].GetDouble(),G[0].GetDouble(),G[1].GetDouble(),V["place"].GetString(),V["title"].GetString(),V["url"].GetString(),V["time"].GetString()});
389  wrapper.push_back(
391  V["mag"].GetDouble(),
392  G[0].GetDouble(),
393  G[1].GetDouble(),
394  V["place"].GetString(),
395  V["title"].GetString(),
396  V["url"].GetString(),
397  V["time"].GetString() )
398  );
399  }
400  }
401  return wrapper;
402  }
418  vector<Shakespeare> getShakespeareData(string type = "",
419  bool textonly = false) {
420  using namespace rapidjson;
421  Document d;
422  vector<Shakespeare> wrapper;
423 
424  string url = "http://bridgesdata.herokuapp.com/api/shakespeare/";
425 
426  if (type == "plays" || type == "poems")
427  url += "/" + type;
428  if (textonly) {
429  url += "?format=simple";
430  }
431  // retrieve the data and parse
432  d.Parse(ServerComm::makeRequest( url, {"Accept: application/json"}).c_str());
433 
434  const Value& D = d["data"];
435  for (SizeType i = 0; i < D.Size(); i++) {
436  const Value& V = D[i];
437  wrapper.push_back(
438  Shakespeare(
439  V["title"].GetString(),
440  V["type"].GetString(),
441  V["text"].GetString()
442  )
443  );
444 
445  }
446  return wrapper;
447  }
467  Song getSong(string songTitle, string artistName = "") {
468  using namespace rapidjson;
469 
470  Document d;
471  vector<Song> wrapper;
472  string url = "http://bridgesdata.herokuapp.com/api/songs/find/";
473  // retrieve the data and parse
474  if (songTitle.size() > 0)
475  url += songTitle;
476  else {
477  throw "Incorrect use of getSong. songTitle should be given.";
478  }
479 
480  if (artistName.size() > 0)
481  url += "?artistName=" + artistName;
482 
483  // check for spaces in url and replace them by '%20'
484  //TODO should use curl to do that
485  string::size_type n = 0;
486  while ( (n = url.find(" ", n)) != string::npos) {
487  url.replace(n, 1, "%20");
488  n++;
489  }
490  if (debug())
491  std::cerr<<"url: "<<url<<"\n";
492  d.Parse(ServerComm::makeRequest( url, {"Accept: application/json"}).c_str());
493 
494  string artist = (d.HasMember("artist")) ?
495  d["artist"].GetString() : string();
496  string song = (d.HasMember("song")) ?
497  d["song"].GetString() : string();
498  string album = (d.HasMember("album")) ?
499  d["album"].GetString() : string();
500  string lyrics = (d.HasMember("lyrics")) ?
501  d["lyrics"].GetString() : string();
502  string release_date = (d.HasMember("release_date")) ?
503  d["release_date"].GetString() : string();
504 
505  return Song (artist, song, album, lyrics, release_date);
506  }
522  vector<Song> getSongData() {
523  using namespace rapidjson;
524 
525  Document d;
526  vector<Song> all_songs;
527 
528  string url = "http://bridgesdata.herokuapp.com/api/songs/";
529  // retrieve the data and parse
530 
531  d.Parse(ServerComm::makeRequest( url, {"Accept: application/json"}).c_str());
532 
533  const Value& D = d["data"];
534 
535  // get the songs and put them into a vector
536  for (SizeType i = 0; i < D.Size(); i++) {
537  const Value& v = D[i];
538 
539  //cout << v["artist"].GetString() << endl;
540  string artist = (v.HasMember("artist")) ? v["artist"].GetString() : string();
541  string song = (v.HasMember("song")) ? v["song"].GetString() : string();
542  string album = (v.HasMember("album")) ? v["album"].GetString() : string();
543  string lyrics = (v.HasMember("lyrics")) ? v["lyrics"].GetString() : string();
544  string release_date = (v.HasMember("release_date")) ?
545  v["release_date"].GetString() : string();
546  all_songs.push_back( Song ( artist, song, album, lyrics, release_date) );
547 
548  }
549  return all_songs;
550  }
562  private:
563 
564  GutenbergBook getAGutenbergBookMetaData(const rapidjson::Value& V) {
565  using namespace rapidjson;
566 
567  const string s_id = V["id"].GetString();
568 
569  const int id = std::stoi(s_id);
570 
571  string title = V["title"].GetString();
572 
573  const Value& A = V["authors"];
574  vector<string> authors;
575  for (SizeType j = 0; j < A.Size(); j++)
576  authors.push_back(A[j].GetString());
577 
578  const Value& L = V["lang"];
579  string lang = L.GetString();
580 
581  const Value& da = V["date_added"];
582  string data_added = da.GetString();
583 
584  const Value& G = V["genres"];
585  vector<string> genres;
586  for (SizeType j = 0; j < G.Size(); j++)
587  genres.push_back(G[j].GetString());
588 
589  GutenbergBook gbook = GutenbergBook(title, id, authors, lang, genres, data_added);
590 
591  return gbook;
592  }
593 
594  public:
608  using namespace rapidjson;
609 
610  // get the query string to get meta data of book
611  string url = getGutenbergBaseURL() + "/meta?id=" + std::to_string(id);
612 
613  // make the query
614  Document d;
615  d.Parse(ServerComm::makeRequest( url, {"Accept: application/json"}).c_str());
616  // only 1 book
617  return getAGutenbergBookMetaData(d["book_list"][0]);
618  }
629  vector<GutenbergBook> getGutenbergBookMetaData(string term, string category) {
630  using namespace rapidjson;
631 
632  // get the query string to get meta data of book
633  string url = getGutenbergBaseURL() + "/search?search=" +
634  ServerComm::encodeURLPart(term)+ "&type="
635  + ServerComm::encodeURLPart(category);
636  // make the query
637 cout << url << endl;
638  Document d;
639  d.Parse(ServerComm::makeRequest(url, {"Accept: application/json"}).c_str());
640 
641  vector<GutenbergBook> book_list;
642  int size= d["book_list"].Size();
643 
644  book_list.clear();
645  for (int k = 0; k < size; k++)
646  book_list.push_back(getAGutenbergBookMetaData(d["book_list"][k]));
647 
648  return book_list;
649  }
650 
658  string getGutenbergBookText(int id = 0) {
659  using namespace rapidjson;
660 
661  //URL for data request
662  string data_url = getGutenbergBaseURL() + "/book?id=" + std::to_string(id);
663 
664  // generate the hash code - use the id
665  string hash_value = "gutenberg" + std::to_string(id);
666 
667  // get the dataset from cache, else from the server
668  string book_data = getDataSetJSON(data_url, hash_value, "gutenberg");
669  // parse, and get the book text
670  Document d;
671  d.Parse(book_data.c_str());
672 
673  string s = std::to_string(id);
674  return d[s.c_str()].GetString();
675  }
676 
683  vector<CancerIncidence> getCancerIncidenceData(int num = 0) {
684  using namespace rapidjson;
685 
686  Document d;
687  vector<CancerIncidence> wrapper;
688  string url = "http://bridgesdata.herokuapp.com/api/cancer/withlocations";
689  if (num > 0) {
690  url += "?limit=" + to_string(num);
691  }
692 
693  d.Parse(ServerComm::makeRequest( url, {"Accept: application/json"}).c_str());
694 
695  // get the JSON dataset
696  const Value& D = d["data"];
697 
698  CancerIncidence c;
699  for (SizeType i = 0; i < D.Size(); i++) {
700  const Value& v = D[i];
701  const Value& age = v["Age"];
702 
703  c.setAgeAdjustedRate( age["Age Adjusted Rate"].GetDouble());
704  c.setAgeAdjustedCI_Lower(age["Age Adjusted CI Lower"].GetDouble());
705  c.setAgeAdjustedCI_Upper(age["Age Adjusted CI Upper"].GetDouble());
706 
707  c.setYear(v["Year"].GetInt());
708 
709  const Value& data = v["Data"];
710  c.setCrudeRate(data["Crude Rate"].GetDouble());
711  c.setCrudeRate_CI_Lower(data["Crude CI Lower"].GetDouble());
712  c.setCrudeRate_CI_Upper(data["Crude CI Upper"].GetDouble());
713  c.setRace(data["Race"].GetString());
714  c.setPopulation(data["Population"].GetInt());
715  c.setEventType(data["Event Type"].GetString());
716  c.setCount(data["Count"].GetInt());
717 
718  c.setAffectedArea(v["Area"].GetString());
719 
720  const Value& loc = v["loc"];
721  c.setLocationX(loc[0].GetDouble());
722  c.setLocationY(loc[1].GetDouble());
723 
724  wrapper.push_back(c);
725  }
726  return wrapper;
727  }
735  private:
736  OSMData getOSMDataFromJSON (const string& osm_json) {
737  using namespace rapidjson;
738 
739  Document osm_data;
740 
741  osm_data.Parse(osm_json.c_str());
742 
743  // create an osm data object
744  OSMData osm;
745 
746  if (osm_data.HasMember("nodes")) {
747  vector<OSMVertex> vertices;
748  Value& nodes = osm_data["nodes"];
749 
750  vector<long> vertex_ids;
751  // get the vertices
752  for (SizeType i = 0; i < nodes.Size(); i++) {
753  const Value& node = nodes[i];
754  OSMVertex::OSMVertexID id = node[0].GetInt64();
755 
756  vertex_ids.push_back(id);
757  double lat = node[1].GetDouble(), longit = node[2].GetDouble();
758  vertices.push_back(OSMVertex(id, lat, longit));
759  }
760  osm.setVertices(vertices);
761  }
762  // add vertices to object
763  // get the edges
764 
765  if (osm_data.HasMember("edges")) {
766  vector<OSMEdge> edges;
767  Value& links = osm_data["edges"];
768 
769  for (SizeType i = 0; i < links.Size(); i++) {
770  const Value& link = links[i];
771  OSMVertex::OSMVertexID id1 = link[0].GetInt64();
772  OSMVertex::OSMVertexID id2 = link[1].GetInt64();
773  double dist = link[2].GetDouble();
774 
775  edges.push_back(OSMEdge(id1, id2, dist));
776  }
777  osm.setEdges(edges);
778  }
779  // add edges to object
780 
781  if (osm_data.HasMember("meta")) {
782  // get lat long range
783  Value& meta = osm_data["meta"];
784  double lat_min = meta["lat_min"].GetDouble();
785  double lat_max = meta["lat_max"].GetDouble();
786  double longit_min = meta["lon_min"].GetDouble();
787  double longit_max = meta["lon_max"].GetDouble();
788  osm.setLatLongRange(lat_min, lat_max, longit_min, longit_max);
789  // get dataset name
790  osm.setName(meta["name"].GetString());
791  }
792  return osm;
793  }
794 
795  public:
796 
819  OSMData getOSMData (double lat_min, double long_min,
820  double lat_max, double long_max, string level = "default") {
821 
822  //URL for hash request
823  string hash_url = getOSMBaseURL() +
824  "hash?minLon=" + std::to_string(long_min) +
825  "&minLat=" + std::to_string(lat_min) +
826  "&maxLon=" + std::to_string(long_max) +
827  "&maxLat=" + std::to_string(lat_max) +
828  "&level=" + ServerComm::encodeURLPart(level);
829 
830 
831  //URL to request map
832  string osm_url =
833  getOSMBaseURL() + "coords?minLon=" + std::to_string(long_min) +
834  "&minLat=" + std::to_string(lat_min) +
835  "&maxLon=" + std::to_string(long_max) +
836  "&maxLat=" + std::to_string(lat_max) +
837  "&level=" + ServerComm::encodeURLPart(level);
838 
839 
840  // get the data set from the server or, if available, from
841  // a local cache
842  string osm_json = getDataSetJSON(osm_url, hash_url, "osm");
843 
844  //tries to get hash value for bounding box map
845  return getOSMDataFromJSON(osm_json);
846  }
847 
862  vector<Amenity> getAmenityData(double minLat, double minLon, double
863  maxLat, double maxLon, std::string amenity) {
864 
865  std::string amenity_url = getOSMBaseURL() + "amenity?minLon=" +
866  ServerComm::encodeURLPart(std::to_string(minLon)) +
867  "&minLat=" + ServerComm::encodeURLPart(std::to_string(minLat)) +
868  "&maxLon=" + ServerComm::encodeURLPart(std::to_string(maxLon)) +
869  "&maxLat=" + ServerComm::encodeURLPart(std::to_string(maxLat)) +
870  "&amenity=" + ServerComm::encodeURLPart(amenity);
871 
872  std::string hash_url = getOSMBaseURL() + "hash?minLon=" +
873  ServerComm::encodeURLPart(std::to_string(minLon)) +
874  "&minLat=" + ServerComm::encodeURLPart(std::to_string(minLat)) +
875  "&maxLon=" + ServerComm::encodeURLPart(std::to_string(maxLon)) +
876  "&maxLat=" + ServerComm::encodeURLPart(std::to_string(maxLat)) +
877  "&amenity=" + ServerComm::encodeURLPart(amenity);
878 
879  // make the query to the server to get a JSON of the amenities
880  // implements caching to keep local copies
881  string amenity_json = getDataSetJSON(amenity_url, hash_url, "amenity");
882 
883  // parse the data and return amenity objects
884  return parseAmenityData (amenity_json);
885  }
886 
898  vector<Amenity> getAmenityData(const std::string& location,
899  const std::string& amenity) {
900  std::string amenity_url = getOSMBaseURL() + "amenity?location=" +
901  ServerComm::encodeURLPart(location) +
902  "&amenity=" + ServerComm::encodeURLPart(amenity);
903 
904  std::string hash_url = getOSMBaseURL() + "hash?location=" +
905  ServerComm::encodeURLPart(location) +
906  "&amenity=" + ServerComm::encodeURLPart(amenity);
907 
908 
909  // make the query to the server to get a JSON of the amenities
910  // implements caching to keep local copies
911  string amenity_json = getDataSetJSON(amenity_url, hash_url, "amenity");
912 
913  // parse the data and return amenity objects
914  return parseAmenityData (amenity_json);
915  }
916 
929  vector<Amenity> parseAmenityData(string amenity_json) {
930  using namespace rapidjson;
931 
932  vector<Amenity> amenities;
933  Document amenity_content;
934 
935  amenity_content.Parse(amenity_json.c_str());
936  if (amenity_content.HasMember("nodes")) {
937  const Value& nodes = amenity_content["nodes"];
938  if (amenity_content.HasMember("meta")) {
939  const Value& meta = amenity_content["meta"];
940 
941  // first get the meta data
942  // amenities.setCount(meta["count"].GetInt64());
943  // amenities.setMinLat(meta["minlat"].GetDouble());
944  // amenities.setMinLon(meta["minlon"].GetDouble());
945  // amenities.setMaxLat(meta["maxlat"].GetDouble());
946  // amenities.setMaxLon(meta["maxlon"].GetDouble());
947 
948  Amenity amen;
949  for (SizeType i = 0; i < nodes.Size(); i++) {
950  // get amenity data
951  const Value& node = nodes[i];
952  amen.setId(node[0].GetInt64());
953  amen.setLat(node[1].GetDouble());
954  amen.setLon(node[2].GetDouble());
955  amen.setName(node[3].GetString());
956 
957  // add to the list
958  amenities.push_back(amen);
959  }
960  }
961  else {
962  cout << "meta data not found!\n";
963  throw;
964  }
965  }
966  else {
967  cout << "nodes data not found!\n";
968  throw;
969  }
970  return amenities;
971  }
972 
992  OSMData getOSMData (string location, string level = "default") {
993  //URL for hash request
994  string hash_url = getOSMBaseURL() + " hash?location=" +
995  ServerComm::encodeURLPart(location) +
996  "&level=" + ServerComm::encodeURLPart(level);
997 
998  //URL to request map
999  string osm_url = getOSMBaseURL() +
1000  "loc?location=" + ServerComm::encodeURLPart(location) +
1001  "&level=" + ServerComm::encodeURLPart(level);
1002 
1003  // get the data set from the server or, if available, from
1004  // a local cache
1005  string osm_json = getDataSetJSON(osm_url, hash_url, "osm");
1006 
1007  return getOSMDataFromJSON(osm_json);
1008  }
1009 
1026  const std::string& user,
1027  int assignment,
1028  int subassignment = 0) {
1029 
1031 
1032  std::string s = this->getAssignment(user, assignment, subassignment);
1033 
1034  rapidjson::Document doc;
1035  doc.Parse(s.c_str());
1036  if (doc.HasParseError())
1037  throw "Malformed JSON";
1038 
1039  //Access doc["assignmentJSON"]
1040  const auto& assjson = doc.FindMember("assignmentJSON");
1041 
1042  if (assjson == doc.MemberEnd())
1043  throw "Malformed GraphAdjacencyList JSON: no assignmentJSON";
1044 
1045  //Access doc["assignmentJSON"]["data"]
1046  const auto& dataArray = assjson->value.FindMember("data");
1047 
1048  if (dataArray == assjson->value.MemberEnd()
1049  || dataArray->value.IsArray() == false)
1050  throw "Malformed GraphAdjacencyList JSON: No data";
1051 
1052  const auto& data = dataArray->value.GetArray()[0];
1053 
1054  //Access doc["assignmentJSON"]["data"][0]["visual"]
1055  const auto& dataVisual = data.FindMember("visual");
1056 
1057  if (dataVisual == data.MemberEnd() ||
1058  dataVisual->value.IsString() == false)
1059  throw "Malformed GraphAdjacencyList JSON";
1060 
1061  std::string assignment_type = dataVisual->value.GetString();
1062 
1063  if (assignment_type != "GraphAdjacencyList")
1064  throw "Malformed GraphAdjacencyList JSON: Not a GraphAdjacencyList";
1065 
1066  //reconstructing vertices out of nodes, and using the optional "name" as the data associated
1067  {
1068  const auto& nodes = data.FindMember("nodes");
1069  if (nodes == data.MemberEnd() ||
1070  nodes->value.IsArray() == false)
1071  throw "Malformed GraphAdjacencyList JSON: malformed nodes";
1072 
1073 
1074  const auto& nodeArray = nodes->value.GetArray();
1075  int nbVertex = nodeArray.Size();
1076  for (int i = 0; i < nbVertex; ++i) {
1077  std::string name;
1078 
1079  const auto& vertexJSONstr = nodeArray[i];
1080 
1081  const auto& nameJSON = vertexJSONstr.FindMember("name");
1082  if (nameJSON != vertexJSONstr.MemberEnd()
1083  && nameJSON->value.IsString()) {
1084  name = nameJSON->value.GetString();
1085  }
1086  gr.addVertex(i, name);
1087  }
1088  }
1089 
1090  //reconstructing links, and using "label" as data associated with the link
1091  {
1092  const auto& links = data.FindMember("links");
1093  if (links == data.MemberEnd() ||
1094  links->value.IsArray() == false)
1095  throw "Malformed GraphAdjacencyList JSON: malformed links";
1096 
1097  const auto& linkArray = links->value.GetArray();
1098  int nbLink = linkArray.Size();
1099  for (int i = 0; i < nbLink; ++i) {
1100  std::string name;
1101  int src;
1102  int dest;
1103  int wgt;
1104 
1105  const auto& linkJSONstr = linkArray[i];
1106 
1107  //checking label. Maybe does not exist? (is that field optional?)
1108  const auto& nameJSON = linkJSONstr.FindMember("label");
1109  if (nameJSON != linkJSONstr.MemberEnd()
1110  && nameJSON->value.IsString()) {
1111  name = nameJSON->value.GetString();
1112  }
1113 
1114  //checking source
1115  const auto& srcJSON = linkJSONstr.FindMember("source");
1116  if (srcJSON == linkJSONstr.MemberEnd()
1117  || srcJSON->value.IsInt() == false) {
1118  throw "Malformed GraphAdjacencyList JSON: malformed link";
1119  }
1120  src = srcJSON->value.GetInt();
1121 
1122 
1123  //checking destination
1124  const auto& dstJSON = linkJSONstr.FindMember("target");
1125  if (dstJSON == linkJSONstr.MemberEnd()
1126  || dstJSON->value.IsInt() == false) {
1127  throw "Malformed GraphAdjacencyList JSON: malformed link";
1128  }
1129  dest = dstJSON->value.GetInt();
1130 
1131  //checking weight. //why is weight a mandatory parameter?
1132  const auto& wgtJSON = linkJSONstr.FindMember("weight");
1133  if (wgtJSON == linkJSONstr.MemberEnd()
1134  || wgtJSON->value.IsInt() == false) {
1135  throw "Malformed GraphAdjacencyList JSON: malformed link";
1136  }
1137  wgt = wgtJSON->value.GetInt();
1138 
1139 
1140  //adding edge.
1141  gr.addEdge(src, dest, name);
1142  }
1143  }
1144 
1145  return gr;
1146  }
1147 
1156  int assignment,
1157  int subassignment = 0) {
1158 
1159  std::string s = this->getAssignment(user, assignment, subassignment);
1160 
1161  rapidjson::Document doc;
1162  doc.Parse(s.c_str());
1163  if (doc.HasParseError())
1164  throw "Malformed JSON";
1165 
1166  try {
1167  std::string assignment_type = doc["assignment_type"].GetString();
1168 
1169  if (assignment_type != "ColorGrid")
1170  throw "Malformed ColorGrid JSON: Not a ColorGrid";
1171  }
1172  catch (rapidjson_exception re) {
1173  throw "Malformed JSON: Not a Bridges assignment?";
1174  }
1175 
1176 
1177  try {
1178  auto& data = doc["data"][0];
1179 
1180  std::string encoding = data["encoding"].GetString();
1181  if (encoding != "RAW" && encoding != "RLE")
1182  throw "Malformed ColorGrid JSON: encoding not supported";
1183 
1184 
1185  //Access doc["data"][0]["dimensions"]
1186  const auto& dimensions = data["dimensions"];
1187  int dimx = dimensions[0].GetInt();
1188  int dimy = dimensions[1].GetInt();
1189 
1190  if (debug())
1191  std::cerr << "Dimensions: " << dimx << "x" << dimy << std::endl;
1192 
1193  //Access doc["data"][0]["nodes"][0]
1194  std::string base64_encoded_assignment = data["nodes"][0].GetString();
1195 
1196 
1197  std::vector<bridges::BYTE> decoded = bridges::base64::decode(base64_encoded_assignment);
1198 
1199  bridges::ColorGrid cg (dimx, dimy);
1200 
1201 
1202  if (encoding == "RAW") {
1203  if (debug())
1204  std::cerr << "decoding RAW" << std::endl;
1205  if (debug())
1206  std::cerr << "length: " << decoded.size() << std::endl;
1207  if (decoded.size() < dimx * dimy * 4)
1208  throw "Malformed ColorGrid JSON: nodes is smaller than expected";
1209 
1210  //first pixel
1211  //std::cerr<<(int)decoded[0]<<" "<<(int)decoded[1]<<" "<<(int)decoded[2]<<" "<<(int)decoded[3]<<std::endl;
1212 
1213  //bridges::ColorGrid* ptr = new bridges::ColorGrid (dimx, dimy);
1214 
1215  size_t base = 0;
1216 
1217  for (int x = 0; x < dimx; ++x) {
1218  for (int y = 0; y < dimy; ++y) {
1219  bridges::Color c ((int)decoded[base],
1220  (int)decoded[base + 1],
1221  (int)decoded[base + 2],
1222  (int)decoded[base + 3]
1223  );
1224 
1225  cg.set(x, y, c);
1226  base += 4;
1227  }
1228  }
1229  }
1230  else if (encoding == "RLE") {
1231  if (debug())
1232  std::cerr << "Decoding RLE" << std::endl;
1233 
1234  int currentInDecoded = 0;
1235  int currentInCG = 0;
1236  while (currentInDecoded != decoded.size()) {
1237  if (currentInDecoded + 5 > decoded.size())
1238  throw "Malformed ColorGrid JSON: nodes is not a multiple of 5";
1239 
1240 
1241 
1242  int repeat = (BYTE) decoded[currentInDecoded++];
1243  int r = (BYTE) decoded[currentInDecoded++];
1244  int g = (BYTE) decoded[currentInDecoded++];
1245  int b = (BYTE) decoded[currentInDecoded++];
1246  int a = (BYTE) decoded[currentInDecoded++];
1247 
1248  if (debug())
1249  std::cerr << "indecoded: " << currentInDecoded
1250  << " repeat: " << (int)repeat
1251  << " color(" << (int)r << "," << (int)g << "," << (int)b << "," << (int)a << ")"
1252  << std::endl;
1253 
1254  bridges::Color c (r, g, b, a);
1255 
1256  while (repeat >= 0) {
1257  int posX = currentInCG / dimy;
1258  int posY = currentInCG % dimy;
1259  if (posX >= dimx || posY >= dimy) {
1260  if (debug())
1261  std::cerr << posX << " " << dimx << " " << posY << " " << dimy << std::endl;
1262  throw "Malformed ColorGrid JSON: Too much data in nodes";
1263  }
1264  cg.set(posX, posY, c);
1265 
1266  currentInCG++;
1267  repeat --;
1268  }
1269  }
1270  if (debug())
1271  std::cerr << "written " << currentInCG << " pixels" << std::endl;
1272  if (currentInCG != dimx * dimy)
1273  throw "Malformed ColorGrid JSON: Not enough data in nodes";
1274  }
1275 
1276  return cg;
1277  }
1278  catch (rapidjson_exception re) {
1279  throw "Malformed ColorGrid JSON";
1280  }
1281 
1282  }
1283  private:
1284  /***
1285  * This function obtains the JSON representation of a particular subassignment.
1286  *
1287  * @return a string that is the JSON representation of the subassignment as stored by the Bridges server.
1288  * @param user the name of the user who uploaded the assignment
1289  * @param assignment the ID of the assignment to get
1290  * @param subassignment the ID of the subassignment to get
1291  ***/
1292  std::string getAssignment(std::string user,
1293  int assignment,
1294  int subassignment = 0) {
1295  std::vector<std::string> headers;
1296 
1297  std::stringstream ss;
1298 
1300  if (bridges_inst)
1301  ss << bridges_inst->getServerURL();
1302  else
1303  ss << bridges::Bridges::getDefaultServerURL();
1304  ss << "/assignmentJSON/"
1305  << assignment << ".";
1306  ss << std::setfill('0') << std::setw(2) << subassignment;
1307  ss << "/" << user;
1308 
1309  std::string url = ss.str();
1310 
1311 
1312  std::string s = bridges::ServerComm::makeRequest(url, headers);
1313 
1314  return s;
1315  }
1316 
1317 
1318  void removeFirstOccurence (std::string & str, const std::string & toRemove) {
1319  size_t pos = str.find(toRemove);
1320  if (pos != std::string::npos) {
1321  str.erase(pos, toRemove.length());
1322  }
1323  }
1324 
1334  void getWikidataActorMovieDirect (int yearbegin, int yearend, std::vector<MovieActorWikidata>& vout) {
1335  std::string codename = "wikidata-actormovie-" + std::to_string(yearbegin) + "-" + std::to_string(yearend);
1336  std::string json;
1337  bool from_cache = false;
1338  try {
1339  if (my_cache.inCache(codename)) {
1340  json = my_cache.getDoc(codename);
1341  from_cache = true;
1342  }
1343  }
1344  catch (CacheException& ce) {
1345  //something went bad trying to access the cache
1346  std::cout << "Exception while reading from cache. Ignoring cache and continue." << std::endl;
1347  }
1348 
1349 
1350  if (!from_cache) {
1351  std::vector<std::string> http_headers;
1352  http_headers.push_back("User-Agent: bridges-cxx"); //wikidata kicks you out if you don't have a useragent
1353  http_headers.push_back("Accept: application/json"); //tell wikidata we are OK with JSON
1354 
1355  string url = "https://query.wikidata.org/sparql?";
1356 
1357  //Q1860 is "English"
1358  //P364 is "original language of film or TV show"
1359  //P161 is "cast member"
1360  //P577 is "publication date"
1361  //A11424 is "film"
1362  //P31 is "instance of"
1363  // "instance of film" is necessary to filter out tv shows
1364  std::string sparqlquery =
1365  "SELECT ?movie ?movieLabel ?actor ?actorLabel WHERE \
1366 {\
1367  ?movie wdt:P31 wd:Q11424.\
1368  ?movie wdt:P161 ?actor.\
1369  ?movie wdt:P364 wd:Q1860.\
1370  ?movie wdt:P577 ?date.\
1371  FILTER(YEAR(?date) >= " + std::to_string(yearbegin) + " && YEAR(?date) <= " + std::to_string(yearend) + ").\
1372  SERVICE wikibase:label { bd:serviceParam wikibase:language \"en\". } \
1373 }";
1374  url += "query=" + ServerComm::encodeURLPart(sparqlquery);
1375  url += "&";
1376  url += "format=json";
1377 
1378 
1379  if (debug()) {
1380  std::cout<<"URL: "<<url<<"\n";
1381  }
1382  // get the Wikidata json
1383  json = ServerComm::makeRequest(url, http_headers);
1384 
1385  try {
1386  my_cache.putDoc(codename, json);
1387  }
1388  catch (CacheException& ce) {
1389  //something went bad trying to access the cache
1390  std::cerr << "Exception while storing in cache. Weird but not critical." << std::endl;
1391  }
1392  }
1393 
1394  {
1395  using namespace rapidjson;
1396  rapidjson::Document doc;
1397  doc.Parse(json.c_str());
1398  if (doc.HasParseError())
1399  throw "Malformed JSON";
1400 
1401  try {
1402  const auto& resultsArray = doc["results"]["bindings"].GetArray();
1403 
1404  for (auto& mak_json : resultsArray) {
1405  MovieActorWikidata mak;
1406 
1407  // all wikidata uri start with "http://www.wikidata.org/entity/"
1408  // so strip it out because it does not help discriminate and
1409  // consume memory and runtime to compare string
1410  std::string actoruri = mak_json["actor"]["value"].GetString();
1411  std::string movieuri = mak_json["movie"]["value"].GetString();
1412  removeFirstOccurence (actoruri, "http://www.wikidata.org/entity/");
1413 
1414  removeFirstOccurence (movieuri, "http://www.wikidata.org/entity/");
1415 
1416 
1417  mak.setActorURI(actoruri);
1418  mak.setMovieURI(movieuri);
1419  mak.setActorName(mak_json["actorLabel"]["value"].GetString());
1420  mak.setMovieName(mak_json["movieLabel"]["value"].GetString());
1421  vout.push_back(mak);
1422  }
1423 
1424  }
1425  catch (rapidjson_exception re) {
1426  throw "Malformed JSON: Not from wikidata?";
1427  }
1428  }
1429  }
1430  public:
1431 
1439  std::vector<MovieActorWikidata> getWikidataActorMovie (int yearbegin, int yearend) {
1440  //Internally this function get the data year by year. This
1441  //is pretty bad because it hits wikidata the first time
1442  //for multiple years. But it enables to work around
1443  //wikidata's time limit. This also works well because the
1444  //Cache will store each year independently and so without
1445  //redundancy. Though I (Erik) am not completely sure that a
1446  //movie can be appear in different years, for instance it
1447  //can be released in the US in 2005 but in canada in
1448  //2006...
1449 
1450  std::vector<MovieActorWikidata> ret;
1451  for (int y = yearbegin; y <= yearend; ++y) {
1452  cout << "getting year " << y << endl;
1453  getWikidataActorMovieDirect (y, y, ret);
1454  }
1455  return ret;
1456  }
1457 
1458 
1472  double minLat, double minLon,
1473  double maxLat, double maxLon, double res = 0.0166) {
1474 
1475  // set up the elevation data url to get the data, given
1476  // a lat/long bounding box
1477 
1478  std::string elev_url = getElevationBaseURL() +
1479  "elevation?minLon=" + ServerComm::encodeURLPart(std::to_string(minLon)) +
1480  "&minLat=" + ServerComm::encodeURLPart(std::to_string(minLat)) +
1481  "&maxLon=" + ServerComm::encodeURLPart(std::to_string(maxLon)) +
1482  "&maxLat=" + ServerComm::encodeURLPart(std::to_string(maxLat)) +
1483  "&resX=" + ServerComm::encodeURLPart(std::to_string(res)) +
1484  "&resY=" + ServerComm::encodeURLPart(std::to_string(res));
1485 
1486  if (debug())
1487  cout << "Elevation URL:" << elev_url << "\n";
1488 
1489  std::string hash_url = getElevationBaseURL() +
1490  "hash?minLon=" + ServerComm::encodeURLPart(std::to_string(minLon)) +
1491  "&minLat=" + ServerComm::encodeURLPart(std::to_string(minLat)) +
1492  "&maxLon=" + ServerComm::encodeURLPart(std::to_string(maxLon)) +
1493  "&maxLat=" + ServerComm::encodeURLPart(std::to_string(maxLat)) +
1494  "&resX=" + ServerComm::encodeURLPart(std::to_string(res)) +
1495  "&resY=" + ServerComm::encodeURLPart(std::to_string(res));
1496 
1497  if (debug())
1498  cout << "Hash URL:" << hash_url << "\n";
1499 
1500 
1501  // get the dataset's JSON from the local cache, if available,
1502  // else from the server
1503 
1504  string elev_json = getDataSetJSON(elev_url, hash_url, "elevation");
1505 
1506  return parseElevationData(elev_json);
1507  }
1508 
1516  ElevationData parseElevationData (string elev_json) {
1517 
1518  // use a string stream to parse the data, which is not really a JSON,
1519  // but raw text
1520  stringstream ss(elev_json);
1521 
1522  int rows, cols, elev_val;
1523  double ll_x, ll_y, cell_size;
1524  string tmp;
1525 
1526  // get the dimensions, origin
1527  ss >> tmp >> cols >> tmp >> rows >>
1528  tmp >> ll_x >> tmp >> ll_y >>
1529  tmp >> cell_size;
1530 
1531 
1532  // create the elevation object
1533  ElevationData elev_data (rows, cols);
1534  elev_data.setxll(ll_x);
1535  elev_data.setyll(ll_y);
1536  elev_data.setCellSize(cell_size);
1537 
1538  // load the elevation data
1539  for (int i = 0; i < rows; i++) {
1540  for (int j = 0; j < cols; j++) {
1541  ss >> elev_val;
1542  elev_data.setVal(i, j, elev_val);
1543  }
1544  }
1545  return elev_data;
1546  }
1547 
1554  std::vector<std::string> getAvailableSubreddits() {
1555  string base_url = getRedditURL();
1556  string url = base_url + "/listJSON";
1557  if (debug()) {
1558  std::cout<<"hitting url: "<<url<<"\n";
1559  }
1560  using namespace rapidjson;
1561  Document doc;
1562  {
1563  std::string s = ServerComm::makeRequest(url, {"Accept: application/json"});
1564  if (debug()) {
1565  std::cout<<"Returned JSON:"<<s<<"\n";
1566  }
1567  try {
1568  doc.Parse(s.c_str());
1569  } catch(rapidjson_exception& re) {
1570  std::cerr<<"malformed subreddit list"<<"\n";
1571  std::cerr<<"Original exception: "<<(std::string)re<<"\n";
1572  }
1573  }
1574 
1575  std::vector<std::string> subreddits;
1576  try {
1577  for (auto& m : doc.GetArray()) {
1578 
1579  std::string subred = m.GetString();
1580  subreddits.push_back(subred);
1581 
1582  }
1583  } catch(rapidjson_exception& re) {
1584  std::cerr<<"malformed subreddit list"<<"\n";
1585  std::cerr<<"Original exception: "<<(std::string)re<<"\n";
1586  }
1587 
1588  return subreddits;
1589 
1590  }
1591 
1601  vector<Reddit> getRedditData(string subreddit, int time_request=-9999) {
1602  string base_url = getRedditURL();
1603  if (debug()) {
1604  cout << "reddit base url:" << base_url << "\n";
1605  }
1606  string url = base_url + "/cache?subreddit=" + subreddit +
1607  "&time_request=" + std::to_string(time_request);
1608 
1609  if (debug()) {
1610  cout<< "reddit url:" << url << "\n";
1611  }
1612 
1613 
1614  using namespace rapidjson;
1615  Document doc;
1616  {
1617  std::string s = ServerComm::makeRequest(url, {"Accept: application/json"});
1618  if (debug()) {
1619  std::cout<<"Returned JSON:"<<s<<"\n";
1620  }
1621  doc.Parse(s.c_str());
1622  }
1623 
1624  vector<Reddit> reddit_posts;
1625  for (auto& m : doc.GetObject()) {
1626  try {
1627  if (debug()) {
1628  std::cout<<m.name.GetString()<<"\n";
1629  }
1630  auto& postJSON = m.value;
1631 
1632  std::string id = postJSON["id"].GetString();
1633  std::string title = postJSON["title"].GetString();
1634  std::string author = postJSON["author"].GetString();
1635  int score = postJSON["score"].GetInt();
1636  float vote_ratio = postJSON["vote_ratio"].GetDouble();
1637  int comment_count = postJSON["comment_count"].GetInt();
1638  std::string subreddit = postJSON["subreddit"].GetString();
1639  int posttime = postJSON["post_time"].GetDouble();
1640  std::string url = postJSON["url"].GetString();
1641  std::string text = postJSON["text"].GetString();
1642 
1643 
1644  Reddit r;
1645  r.setID(id);
1646  r.setTitle(title);
1647  r.setAuthor(author);
1648  r.setScore(score);
1649  r.setVoteRatio(vote_ratio);
1650  r.setCommentCount(comment_count);
1651  r.setSubreddit(subreddit);
1652  r.setPostTime(posttime);
1653  r.setURL(url);
1654  r.setText(text);
1655  reddit_posts.push_back(r);
1656  }
1657  catch(rapidjson_exception& re) {
1658  std::cerr<<"malformed Reddit post"<<"\n";
1659  std::cerr<<"Original exception: "<<(std::string)re<<"\n";
1660  }
1661  }
1662 
1663 
1664  return reddit_posts;
1665  }
1666 
1667  private:
1677  string getHashCode (string hash_url, string data_type) {
1678  string hash_value;
1679  if (data_type == "osm" || data_type == "amenity" ||
1680  data_type == "elevation") {
1681  hash_value = ServerComm::makeRequest(hash_url, {"Accept: application/json"});
1682  }
1683  else if (data_type == "gutenberg")
1684  hash_value = hash_url;
1685 
1686  return hash_value;
1687  }
1688 
1710  std::string getDataSetJSON(std::string data_url, std::string hash_url,
1711  std::string data_type) {
1712 
1713  std::string data_json = "";
1714 
1715  // First check to see if the requested data is stored in local cache
1716  // get hash value for elevation data
1717  if (debug())
1718  cerr << "Checking the cache: Hash url: " << hash_url << "\n";
1719 
1720  // generate the hash code
1721  string hash_value = getHashCode(hash_url, data_type);
1722 
1723  bool dataloaded=false;
1724 
1725  if ((hash_value != "false") && (my_cache.inCache(hash_value) == true)) { //local cache contains the dataset
1726  try {
1727  data_json = my_cache.getDoc(hash_value);
1728  dataloaded = true;
1729  }
1730  catch (CacheException& ce) {
1731  //something went bad trying to access the data in the local cache
1732  std::cout << "Exception while reading from cache. "
1733  << "Ignoring cache and continuing..\n.";
1734  }
1735  }
1736  if (!dataloaded) {
1737  //Data could not get accessed from cache for some reason.
1738  //So teh data need to be access from the remote server.
1739  //Then we will store it in a local cache for future usage.
1740  if (debug())
1741  std::cerr << "Hitting data URL: " << data_url << "\n";
1742 
1743  //Requests the data
1744  data_json = ServerComm::makeRequest(data_url,
1745  {"Accept: application/json"});
1746 
1747  //Store the data in cache for future reuse
1748  try {
1749  // We need the data's hash code to know where to store it in local cache.
1750  // We may already have it from the previous query.
1751  if (hash_value == "false") {
1752  if (debug())
1753  std::cerr << "Hitting hash URL: " << hash_value << "\n";
1754 
1755  hash_value = getHashCode(hash_url, data_type);
1756  }
1757 
1758  // This test should only ever be true if something wrong happens server-side
1759  if (hash_value == "false") {
1760  std::cerr << "Error while gathering hash value for "<<data_type<<" dataset..\n"
1761  << "Weird but not critical.\n";
1762  }
1763  else {
1764  my_cache.putDoc(hash_value, data_json);
1765  }
1766  }
1767  catch (CacheException& ce) {
1768  //something went bad trying to access the cache
1769  std::cerr << "Exception while storing in cache. " <<
1770  "Weird but not critical.\n";
1771  if (debug())
1772  std::cerr << "Tried to store hash=" << hash_value <<
1773  " key = " << data_json << std::endl;
1774  }
1775  }
1776 
1777  if (debug())
1778  cout << data_json;
1779 
1780  return data_json;
1781  }
1782 
1783  }; // class DataSource
1784 } // namespace bridges
1785 #endif
GutenbergBook getGutenbergBookMetaData(int id=0)
Get meta data of a single Gutenberg book This function retrieves, and formats the data into a list of...
Definition: DataSource.h:607
Class that hold Open Street Map Amenity data.
Definition: Amenity.h:22
ElevationData parseElevationData(string elev_json)
Parses the elevation data string and retuns an Elevation object.
Definition: DataSource.h:1516
void setMovieURI(std::string mu)
Definition: MovieActorWikidata.h:40
A Gutenberg Book object (meta data and book's full text)
Definition: GutenbergBook.h:32
vector< City > getUSCities(unordered_map< string, string > params)
Retrieves US city data based on a set of filtering parameters.
Definition: DataSource.h:162
vector< Shakespeare > getShakespeareData(string type="", bool textonly=false)
Get data of Shakespeare works (plays, poems)
Definition: DataSource.h:418
Definition: ActorMovieIMDB.h:10
A Shakespeare Data source object containing sonnets, poems and plays.
Definition: Shakespeare.h:32
virtual void putDoc(const std::string &hash_value, const std::string &content) override
Definition: Cache.h:172
std::vector< MovieActorWikidata > getWikidataActorMovie(int yearbegin, int yearend)
This function returns the Movie and Actors playing in them between two years.
Definition: DataSource.h:1439
This is a helper class for accessing actor-movie data from Wikidata.
Definition: MovieActorWikidata.h:23
void setId(long id)
Definition: Amenity.h:73
void setLon(double longitude)
Definition: Amenity.h:105
Definition: Cache.h:144
ElevationData getElevationData(double minLat, double minLon, double maxLat, double maxLon, double res=0.0166)
Definition: DataSource.h:1471
vector< Game > getGameData()
Get meta data of the IGN games collection.
Definition: DataSource.h:250
This class provides methods to represent adjacency list based graphs.
Definition: Element.h:19
void setActorName(std::string an)
Definition: MovieActorWikidata.h:64
A Song object, used along with the Songs data source.
Definition: Song.h:28
long OSMVertexID
Definition: OSMVertex.h:36
vector< Song > getSongData()
Get data of the songs (including lyrics) using the Genius API https://docs.genius....
Definition: DataSource.h:522
Class that hold Open Street Map edges.
Definition: OSMEdge.h:28
void setName(string n)
Definition: Amenity.h:121
This is a class in BRIDGES for representing an image.
Definition: ColorGrid.h:22
std::vector< std::string > getAvailableSubreddits()
retrieves the subreddits made available by BRIDGES
Definition: DataSource.h:1554
bridges::ColorGrid getColorGridFromAssignment(const std::string &user, int assignment, int subassignment=0)
Definition: DataSource.h:1155
Definition: JSONutil.h:6
void setName(const string &n)
change the name of the dataset
Definition: OSMData.h:230
vector< Reddit > getRedditData(string subreddit, int time_request=-9999)
Definition: DataSource.h:1601
virtual std::string getDoc(const std::string &hash_value) override
Definition: Cache.h:156
An object to represent a Reddit post, used along with the Reddit data source.
Definition: Reddit.h:28
vector< ActorMovieIMDB > getActorMovieIMDBData(int number=0)
Get ActorMovie IMDB Data Data is retrieved, formatted into a list of ActorMovieIMDB objects.
Definition: DataSource.h:288
This class represents Color, and supports rgba, hexadecimal and named color values.
Definition: Color.h:51
Class that holds data of a city.
Definition: City.h:30
Song getSong(string songTitle, string artistName="")
Get data of a particular songs (including lyrics) using the Genius API (https://docs....
Definition: DataSource.h:467
This class contains methods to connect and transmit a user's data structure representation to the Bri...
Definition: Bridges.h:42
void addVertex(const K &k, const E1 &e=E1())
Adds a vertex to the graph.
Definition: GraphAdjList.h:177
void setActorURI(std::string au)
Definition: MovieActorWikidata.h:48
vector< EarthquakeUSGS > getEarthquakeUSGSData(int number=0)
Get USGS earthquake data USGS Tweet data (https://earthquake.usgs.gov/earthquakes/map/) retrieved,...
Definition: DataSource.h:358
these methods convert byte arrays in to base64 codes and are used in BRIDGES to represent the color a...
Definition: alltypes.h:4
vector< GutenbergBook > getGutenbergBookMetaData(string term, string category)
Search the gutenberg data for retrieving meta data of books matching a string and a category.
Definition: DataSource.h:629
This class provides an API to various data sources used in BRIDGES.
Definition: DataSource.h:63
void setLat(double latitude)
Definition: Amenity.h:89
void setyll(int y_ll)
Definition: ElevationData.h:199
void setMovieName(std::string mn)
Definition: MovieActorWikidata.h:56
void setVertices(const vector< OSMVertex > &verts)
replace the vertices stored by this new set.
Definition: OSMData.h:275
A class to hold actor movie data – using IMDB dataset.
Definition: ActorMovieIMDB.h:31
void setLatLongRange(double *lat_range, double *longit_range)
set the latitude and longitude range of the dataset
Definition: OSMData.h:114
vector< CancerIncidence > getCancerIncidenceData(int num=0)
Retrieves the CDC dataset of Cancer Incidence. Data is retrieved into a vector of records See CancerI...
Definition: DataSource.h:683
unsigned char BYTE
Definition: base64.h:44
vector< Amenity > getAmenityData(double minLat, double minLon, double maxLat, double maxLon, std::string amenity)
Definition: DataSource.h:862
Class that hold elevation data.
Definition: ElevationData.h:27
bridges::GraphAdjList< int, std::string > getGraphFromAssignment(const std::string &user, int assignment, int subassignment=0)
Definition: DataSource.h:1025
void setSourceType(string type)
set data server type
Definition: DataSource.h:131
Class that hold Open Street Map Data.
Definition: OSMData.h:40
vector< Amenity > getAmenityData(const std::string &location, const std::string &amenity)
Definition: DataSource.h:898
DataSource(bridges::Bridges *br=nullptr)
Definition: DataSource.h:118
void set(int row, int col, E val)
Set the grid value for the (row, col) element.
Definition: Grid.h:192
OSMData getOSMData(double lat_min, double long_min, double lat_max, double long_max, string level="default")
Get OpenStreetMap data given a bounding rectangle of lat/long values.
Definition: DataSource.h:819
vector< Amenity > parseAmenityData(string amenity_json)
Parses the amenity string and returns an AmenityData object.
Definition: DataSource.h:929
void setxll(int x_ll)
Definition: ElevationData.h:182
OSMData getOSMData(string location, string level="default")
Definition: DataSource.h:992
DataSource(bridges::Bridges &br)
Definition: DataSource.h:121
virtual bool inCache(const std::string &hash_value) override
Definition: Cache.h:165
void setEdges(const vector< OSMEdge > &e)
set edges
Definition: OSMData.h:313
A Game object, used along with the Games data source.
Definition: Game.h:33
A class representing the attributes for cancer incidence.
Definition: CancerIncidence.h:32
Class that hold earthquake data, for use with USGIS retrieved quake data.
Definition: EarthquakeUSGS.h:29
void setVal(int r, int c, int val)
Definition: ElevationData.h:144
vector< ActorMovieIMDB > getActorMovieIMDBData2()
Get ActorMovie IMDB Data Data is retrieved, formatted into a list of ActorMovieIMDB objects.
Definition: DataSource.h:322
Definition: Array.h:9
void addEdge(const K &src, const K &dest, const E2 &data=E2())
Definition: GraphAdjList.h:200
Class that hold Open Street Map vertices.
Definition: OSMVertex.h:34
void setCellSize(float cell_size)
Definition: ElevationData.h:217
string getGutenbergBookText(int id=0)
Get the full text of the book with the provided id.
Definition: DataSource.h:658
vector< BYTE > decode(string const &encoded_string)
Definition: base64.h:103