Bridges-C++  3.1.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 
8 using namespace std;
9 
10 #include <JSONutil.h>
12 #include "./data_src/Game.h"
13 #include "./data_src/Shakespeare.h"
17 #include "./data_src/Song.h"
19 #include "./data_src/OSMData.h"
20 #include "./data_src/OSMVertex.h"
21 #include "./data_src/OSMEdge.h"
23 #include "ColorGrid.h"
24 #include "base64.h"
25 #include <GraphAdjList.h>
26 #include <ServerComm.h>
27 #include <Bridges.h>
28 #include "rapidjson/document.h"
29 #include "assert.h"
30 #include "rapidjson/error/en.h"
31 #include <fstream>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <stdio.h>
35 
36 
37 #include <Cache.h>
38 
39 
40 namespace bridges {
41  using namespace bridges::dataset;
42  using namespace bridges::datastructure;
43 
44 
45 
46 
59  class DataSource {
60 
61  private:
62 
63  int debug() const {
64  return 0;
65  }
66  bridges::Bridges* bridges_inst;
67  bridges::lruCache my_cache;
68 
69  string getOSMBaseURL() const {
70  //return "http://cci-bridges-osm-t.uncc.edu/";
71  return "http://cci-bridges-osm.uncc.edu/";
72  }
73 
74  public:
76  : bridges_inst(br), my_cache(120) {}
77 
79  : DataSource(&br) {}
80 
81 
94  vector<Game> getGameData() {
95  using namespace rapidjson;
96  Document d;
97 
98  // request the game dataset and parse it
99  d.Parse(
100  ServerComm::makeRequest("http://bridgesdata.herokuapp.com/api/games",
101  {"Accept: application/json"}).c_str());
102 
103  const Value& D = d["data"];
104  vector<Game> wrapper;
105  for (SizeType i = 0; i < D.Size(); i++) {
106  const Value& V = D[i];
107  const Value& G = V["genre"];
108 
109  vector<string> genre;
110  for (SizeType j = 0; j < G.Size(); j++) {
111  genre.push_back(G[j].GetString());
112  }
113  wrapper.push_back(
114  Game( V["game"].GetString(),
115  V["platform"].GetString(),
116  V["rating"].GetDouble(),
117  genre ) );
118  }
119  return wrapper;
120  }
132  vector<ActorMovieIMDB> getActorMovieIMDBData(int number = 0) {
133  using namespace rapidjson;
134  Document d;
135  vector<ActorMovieIMDB> wrapper;
136  string url = "http://bridgesdata.herokuapp.com/api/imdb?limit=" +
137  to_string(number);
138 
139  // retrieve the data and parse
140  d.Parse(ServerComm::makeRequest( url, {"Accept: application/json"}).c_str());
141 
142  const Value& D = d["data"];
143  for (SizeType i = 0; i < D.Size(); i++) {
144  const Value& V = D[i];
145  wrapper.push_back(
147  V["actor"].GetString(),
148  V["movie"].GetString()
149  )
150  );
151  }
152  return wrapper;
153  }
154 
155 
166  vector<ActorMovieIMDB> getActorMovieIMDBData2() {
167  using namespace rapidjson;
168  Document d;
169  vector<ActorMovieIMDB> wrapper;
170  string url = "http://bridgesdata.herokuapp.com/api/imdb2";
171 
172  // retrieve the data and parse
173  d.Parse(ServerComm::makeRequest( url, {"Accept: application/json"}).c_str());
174 
175  const Value& D = d["data"];
176  for (SizeType i = 0; i < D.Size(); i++) {
177  const Value& V = D[i];
178  string actor = V["actor"].GetString();
179  string movie = V["movie"].GetString();
180  double rating = V["rating"].GetDouble();
181  const Value& G = V["genres"];
182  vector<string> genres;
183  for (SizeType j = 0; j < G.Size(); j++) {
184  genres.push_back(G[j].GetString());
185  }
186  wrapper.push_back(ActorMovieIMDB( actor, movie, (float)rating, genres));
187  }
188  return wrapper;
189  }
190 
202  vector<EarthquakeUSGS> getEarthquakeUSGSData(int number = 0) {
203  using namespace rapidjson;
204  Document d;
205  vector<EarthquakeUSGS> wrapper;
206  if (number <= 0) {
207  d.Parse(ServerComm::makeRequest( "http://earthquakes-uncc.herokuapp.com/eq",
208  {"Accept: application/json"}).c_str());
209  for (SizeType i = 0; i < d.Size(); i++) {
210  const Value& V = d[i]["properties"];
211  const Value& G = d[i]["geometry"]["coordinates"];
212  wrapper.push_back(
214  V["mag"].GetDouble(),
215  G[0].GetDouble(),
216  G[1].GetDouble(),
217  V["place"].GetString(),
218  V["title"].GetString(),
219  V["url"].GetString(),
220  V["time"].GetString() )
221  );
222  }
223  }
224  else {
225  d.Parse(ServerComm::makeRequest( "http://earthquakes-uncc.herokuapp.com/eq/latest/" +
226  to_string(number), {"Accept: application/json"}).c_str());
227 
228  const Value& D = d["Earthquakes"];
229  for (SizeType i = 0; i < D.Size(); i++) {
230  const Value& V = D[i]["properties"];
231  const Value& G = D[i]["geometry"]["coordinates"];
232  // wrapper.push_back({V["mag"].GetDouble(),G[0].GetDouble(),G[1].GetDouble(),V["place"].GetString(),V["title"].GetString(),V["url"].GetString(),V["time"].GetString()});
233  wrapper.push_back(
235  V["mag"].GetDouble(),
236  G[0].GetDouble(),
237  G[1].GetDouble(),
238  V["place"].GetString(),
239  V["title"].GetString(),
240  V["url"].GetString(),
241  V["time"].GetString() )
242  );
243  }
244  }
245  return wrapper;
246  }
262  vector<Shakespeare> getShakespeareData(string type = "",
263  bool textonly = false) {
264  using namespace rapidjson;
265  Document d;
266  vector<Shakespeare> wrapper;
267 
268  string url = "http://bridgesdata.herokuapp.com/api/shakespeare/";
269 
270  if (type == "plays" || type == "poems")
271  url += "/" + type;
272  if (textonly) {
273  url += "?format=simple";
274  }
275  // retrieve the data and parse
276  d.Parse(ServerComm::makeRequest( url, {"Accept: application/json"}).c_str());
277 
278  const Value& D = d["data"];
279  for (SizeType i = 0; i < D.Size(); i++) {
280  const Value& V = D[i];
281  wrapper.push_back(
282  Shakespeare(
283  V["title"].GetString(),
284  V["type"].GetString(),
285  V["text"].GetString()
286  )
287  );
288 
289  }
290  return wrapper;
291  }
308  Song getSong(string songTitle, string artistName) {
309  using namespace rapidjson;
310 
311  Document d;
312  vector<Song> wrapper;
313  string url = "http://bridgesdata.herokuapp.com/api/songs/find/";
314  // retrieve the data and parse
315  if (songTitle.size() > 0)
316  url += songTitle;
317  else {
318  throw "Incorrect use of getSong. songTitle should be given.";
319  }
320 
321  if (artistName.size())
322  url += "?artistName=" + artistName;
323  else {
324  throw "Incorrect use of getSong. artistName should be given.";
325  }
326  // check for spaces in url and replace them by '%20'
327  string::size_type n = 0;
328  while ( (n = url.find(" ", n)) != string::npos) {
329  url.replace(n, 1, "%20");
330  n++;
331  }
332 
333  d.Parse(ServerComm::makeRequest( url, {"Accept: application/json"}).c_str());
334 
335  string artist = (d.HasMember("artist")) ?
336  d["artist"].GetString() : string();
337  string song = (d.HasMember("song")) ?
338  d["song"].GetString() : string();
339  string album = (d.HasMember("album")) ?
340  d["album"].GetString() : string();
341  string lyrics = (d.HasMember("lyrics")) ?
342  d["lyrics"].GetString() : string();
343  string release_date = (d.HasMember("release_date")) ?
344  d["release_date"].GetString() : string();
345 
346  return Song (artist, song, album, lyrics, release_date);
347  }
363  vector<Song> getSongData() {
364  using namespace rapidjson;
365 
366  Document d;
367  vector<Song> all_songs;
368 
369  string url = "http://bridgesdata.herokuapp.com/api/songs/";
370  // retrieve the data and parse
371 
372  d.Parse(ServerComm::makeRequest( url, {"Accept: application/json"}).c_str());
373 
374  const Value& D = d["data"];
375 
376  // get the songs and put them into a vector
377  for (SizeType i = 0; i < D.Size(); i++) {
378  const Value& v = D[i];
379 
380  //cout << v["artist"].GetString() << endl;
381  string artist = (v.HasMember("artist")) ? v["artist"].GetString() : string();
382  string song = (v.HasMember("song")) ? v["song"].GetString() : string();
383  string album = (v.HasMember("album")) ? v["album"].GetString() : string();
384  string lyrics = (v.HasMember("lyrics")) ? v["lyrics"].GetString() : string();
385  string release_date = (v.HasMember("release_date")) ?
386  v["release_date"].GetString() : string();
387  all_songs.push_back( Song ( artist, song, album, lyrics, release_date) );
388 
389  }
390  return all_songs;
391  }
403  vector<GutenbergBook> getGutenbergBookData(int num = 0) {
404  using namespace rapidjson;
405 
406  Document d;
407  vector<GutenbergBook> wrapper;
408  string url = "http://bridgesdata.herokuapp.com/api/books";
409  if (num > 0) {
410  url += "?limit=" + to_string(num);
411  }
412 
413  d.Parse(ServerComm::makeRequest( url, {"Accept: application/json"}).c_str());
414  const Value& D = d["data"];
415  for (SizeType i = 0; i < D.Size(); i++) {
416  const Value& V = D[i];
417 
418  const Value& A = V["author"];
419  const Value& L = V["languages"];
420 
421  vector<string> lang;
422  for (SizeType j = 0; j < L.Size(); j++) {
423  lang.push_back(L[j].GetString());
424  }
425 
426  const Value& G = V["genres"];
427  vector<string> genre;
428  for (SizeType j = 0; j < G.Size(); j++) {
429  genre.push_back(G[j].GetString());
430  }
431 
432  const Value& S = V["subjects"];
433  vector<string> subject;
434  for (SizeType j = 0; j < S.Size(); j++) {
435  subject.push_back(S[j].GetString());
436  }
437 
438  const Value& M = V["metrics"];
439  wrapper.push_back(
441  A["name"].GetString(),
442  A["birth"].GetInt(),
443  A["death"].GetInt(),
444  V["title"].GetString(),
445  lang,
446  genre,
447  subject,
448  M["characters"].GetInt(),
449  M["words"].GetInt(),
450  M["sentences"].GetInt(),
451  M["difficultWords"].GetInt(),
452  V["url"].GetString(),
453  V["downloads"].GetInt()
454  )
455  );
456  }
457  return wrapper;
458  }
464  vector<CancerIncidence> getCancerIncidenceData(int num = 0) {
465  using namespace rapidjson;
466 
467  Document d;
468  vector<CancerIncidence> wrapper;
469  string url = "http://bridgesdata.herokuapp.com/api/cancer/withlocations";
470  if (num > 0) {
471  url += "?limit=" + to_string(num);
472  }
473 
474  d.Parse(ServerComm::makeRequest( url, {"Accept: application/json"}).c_str());
475 
476  // get the JSON dataset
477  const Value& D = d["data"];
478 
479  CancerIncidence c;
480  for (SizeType i = 0; i < D.Size(); i++) {
481  const Value& v = D[i];
482  const Value& age = v["Age"];
483 
484  c.setAgeAdjustedRate( age["Age Adjusted Rate"].GetDouble());
485  c.setAgeAdjustedCI_Lower(age["Age Adjusted CI Lower"].GetDouble());
486  c.setAgeAdjustedCI_Upper(age["Age Adjusted CI Upper"].GetDouble());
487 
488  c.setYear(v["Year"].GetInt());
489 
490  const Value& data = v["Data"];
491  c.setCrudeRate(data["Crude Rate"].GetDouble());
492  c.setCrudeRate_CI_Lower(data["Crude CI Lower"].GetDouble());
493  c.setCrudeRate_CI_Upper(data["Crude CI Upper"].GetDouble());
494  c.setRace(data["Race"].GetString());
495  c.setPopulation(data["Population"].GetInt());
496  c.setEventType(data["Event Type"].GetString());
497 
498  c.setAffectedArea(v["Area"].GetString());
499 
500  const Value& loc = v["loc"];
501  c.setLocationX(loc[0].GetDouble());
502  c.setLocationY(loc[1].GetDouble());
503 
504  wrapper.push_back(c);
505  }
506  return wrapper;
507  }
515  OSMData getOSMDataFromJSON (const string& osm_json) {
516  using namespace rapidjson;
517 
518  Document osm_data;
519 
520  osm_data.Parse(osm_json.c_str());
521 
522  // create an osm data object
523  OSMData osm;
524 
525  if (osm_data.HasMember("nodes")) {
526  vector<OSMVertex> vertices;
527  Value& nodes = osm_data["nodes"];
528 
529  vector<long> vertex_ids;
530  // get the vertices
531  for (SizeType i = 0; i < nodes.Size(); i++) {
532  const Value& node = nodes[i];
533  OSMVertex::OSMVertexID id = node[0].GetInt64();
534 
535  vertex_ids.push_back(id);
536  double lat = node[1].GetDouble(), longit = node[2].GetDouble();
537  vertices.push_back(OSMVertex(id, lat, longit));
538  }
539  osm.setVertices(vertices);
540  }
541  // add vertices to object
542  // get the edges
543 
544  if (osm_data.HasMember("edges")) {
545  vector<OSMEdge> edges;
546  Value& links = osm_data["edges"];
547 
548  for (SizeType i = 0; i < links.Size(); i++) {
549  const Value& link = links[i];
550  OSMVertex::OSMVertexID id1 = link[0].GetInt64();
551  OSMVertex::OSMVertexID id2 = link[1].GetInt64();
552  double dist = link[2].GetDouble();
553 
554  edges.push_back(OSMEdge(id1, id2, dist));
555  }
556  osm.setEdges(edges);
557  }
558  // add edges to object
559 
560  if (osm_data.HasMember("meta")) {
561  // get lat long range
562  Value& meta = osm_data["meta"];
563  double lat_min = meta["lat_min"].GetDouble();
564  double lat_max = meta["lat_max"].GetDouble();
565  double longit_min = meta["lon_min"].GetDouble();
566  double longit_max = meta["lon_max"].GetDouble();
567  osm.setLatLongRange(lat_min, lat_max, longit_min, longit_max);
568  // get dataset name
569  osm.setName(meta["name"].GetString());
570  }
571  return osm;
572  }
573 
574 
585  OSMData getOSMData (double lat_min, double long_min,
586  double lat_max, double long_max, string level = "default") {
587 
588  //URL for hash request
589  string hash_url = getOSMBaseURL() + "hash?minLon=" + std::to_string(long_min) +
590  "&minLat=" + std::to_string(lat_min) +
591  "&maxLon=" + std::to_string(long_max) +
592  "&maxLat=" + std::to_string(lat_max) +
593  "&level=" + ServerComm::encodeURLPart(level);
594 
595  //URL to request map
596  string url =
597  getOSMBaseURL() + "coords?minLon=" + std::to_string(long_min) +
598  "&minLat=" + std::to_string(lat_min) +
599  "&maxLon=" + std::to_string(long_max) +
600  "&maxLat=" + std::to_string(lat_max) +
601  "&level=" + ServerComm::encodeURLPart(level);
602 
603  //trys to get hash value for bounding box map
604  if (debug())
605  std::cerr << "Hitting hash URL: " << hash_url << "\n";
606  string hash_value = ServerComm::makeRequest(hash_url, {"Accept: application/json"});
607 
608 
609  std::string osm_json;
610  //std::cerr<<"url: "<<url<<"\n";
611 
612  //Checks to see if map requested is stored in local cache
613  if (my_cache.inCache(hash_value) == true) { //local map is up-to-date
614  try {
615  if (my_cache.inCache(hash_value)) {
616  osm_json = my_cache.getDoc(hash_value);
617  }
618  }
619  catch (CacheException& ce) {
620  //something went bad trying to access the cache
621  std::cout << "Exception while reading from cache. Ignoring cache and continue." << std::endl;
622  }
623 
624  }
625  else if (hash_value.compare("false") == 0 || my_cache.inCache(hash_value) == false) {
626  //Server response is false or somehow map got saved as false
627 
628  if (debug())
629  std::cerr << "Hitting json URL: " << url << "\n";
630 
631  osm_json = ServerComm::makeRequest(url, {"Accept: application/json"}); //Requests the map data then requests the maps hash
632  if (debug())
633  std::cerr << "Hitting hash URL: " << hash_url << "\n";
634 
635  hash_value = ServerComm::makeRequest(hash_url, {"Accept: application/json"});
636 
637  if (hash_value.compare("false") == 0) {
638  std::cerr << "Error while gathering hash data for generated map..." << std::endl;
639  std::cerr << osm_json << std::endl;
640  abort();
641  }
642 
643  //Saves map to cache directory
644  try {
645  my_cache.putDoc(hash_value, osm_json);
646 
647  }
648  catch (CacheException& ce) {
649 
650  //something went bad trying to access the cache
651  std::cerr << "Exception while storing in cache. Weird but not critical." << std::endl;
652  if (debug())
653  std::cerr << "Tried to store hash=" << hash_value << " key=" << osm_json << std::endl;
654  }
655 
656  }
657  return getOSMDataFromJSON(osm_json);
658  }
659 
669  OSMData getOSMData (string location, string level = "default") {
670  //URL for hash request
671  string hash_url = getOSMBaseURL() + "hash?location=" + ServerComm::encodeURLPart(location) +
672  "&level=" + ServerComm::encodeURLPart(level);
673 
674  //URL to request map
675  string url =
676  getOSMBaseURL() + "loc?location=" + ServerComm::encodeURLPart(location) +
677  "&level=" + ServerComm::encodeURLPart(level);
678 
679  //trys to get hash value for bounding box map
680  if (debug())
681  std::cerr << "Hitting hash URL: " << hash_url << "\n";
682  string hash_value = ServerComm::makeRequest(hash_url, {"Accept: application/json"});
683 
684 
685  std::string osm_json;
686 
687  std::cerr << "url: " << url << "\n";
688 
689  if (my_cache.inCache(hash_value) == true) { //local map is up-to-date
690  try {
691  if (my_cache.inCache(hash_value)) {
692  osm_json = my_cache.getDoc(hash_value);
693  }
694  }
695  catch (CacheException& ce) { //something went bad trying to access the cache
696  std::cout << "Exception while reading from cache. Ignoring cache and continue." << std::endl;
697  }
698 
699  }
700  else if (hash_value.compare("false") == 0 || my_cache.inCache(hash_value) == false) { //Server response is false or somehow map got saved as false
701  if (debug())
702  std::cerr << "Hitting json URL: " << url << "\n";
703  osm_json = ServerComm::makeRequest(url, {"Accept: application/json"}); //Requests the map data then requests the maps hash
704  if (debug())
705  std::cerr << "Hitting hash URL: " << hash_url << "\n";
706  hash_value = ServerComm::makeRequest(hash_url, {"Accept: application/json"});
707  if (hash_value.compare("false") == 0) {
708  std::cerr << "Error while gathering hash data for generated map..." << std::endl;
709  std::cerr << osm_json << std::endl;
710  abort();
711  }
712 
713  //Saves map to cache directory
714  try {
715  my_cache.putDoc(hash_value, osm_json);
716  }
717  catch (CacheException& ce) {
718  //something went bad trying to access the cache
719  std::cerr << "Exception while storing in cache. Weird but not critical." << std::endl;
720  if (debug())
721  std::cerr << "Tried to store hash=" << hash_value << " key=" << osm_json << std::endl;
722  }
723 
724  }
725  return getOSMDataFromJSON(osm_json);
726  }
727 
728 
739  OSMData getOSMDataOld (string location) {
740  std::transform(location.begin(), location.end(), location.begin(),
741  ::tolower);
742  std::string osm_json;
743  bool from_cache = false;
744  try {
745  if (my_cache.inCache(location)) {
746  osm_json = my_cache.getDoc(location);
747  from_cache = true;
748  }
749  }
750  catch (CacheException& ce) {
751  //something went bad trying to access the cache
752  std::cout << "Exception while reading from cache. Ignoring cache and continue." << std::endl;
753  }
754 
755  string url = string("http://osm-api.herokuapp.com/name/") + location;
756 
757  if (!from_cache) {
758  // get the OSM data json
759  osm_json = ServerComm::makeRequest(url, {"Accept: application/json"});
760 
761  try {
762  my_cache.putDoc(location, osm_json);
763  }
764  catch (CacheException& ce) {
765  //something went bad trying to access the cache
766  std::cerr << "Exception while storing in cache. Weird but not critical." << std::endl;
767  }
768  }
769 
770  return getOSMDataFromJSON(osm_json);
771 
772  }
773 
774 
788  int assignment,
789  int subassignment = 0) {
791 
792  std::string s = this->getAssignment(user, assignment, subassignment);
793 
794  rapidjson::Document doc;
795  doc.Parse(s.c_str());
796  if (doc.HasParseError())
797  throw "Malformed JSON";
798 
799  //Access doc["assignmentJSON"]
800  const auto& assjson = doc.FindMember("assignmentJSON");
801 
802  if (assjson == doc.MemberEnd())
803  throw "Malformed GraphAdjacencyList JSON: no assignmentJSON";
804 
805  //Access doc["assignmentJSON"]["data"]
806  const auto& dataArray = assjson->value.FindMember("data");
807 
808  if (dataArray == assjson->value.MemberEnd()
809  || dataArray->value.IsArray() == false)
810  throw "Malformed GraphAdjacencyList JSON: No data";
811 
812  const auto& data = dataArray->value.GetArray()[0];
813 
814  //Access doc["assignmentJSON"]["data"][0]["visual"]
815  const auto& dataVisual = data.FindMember("visual");
816 
817  if (dataVisual == data.MemberEnd() ||
818  dataVisual->value.IsString() == false)
819  throw "Malformed GraphAdjacencyList JSON";
820 
821  std::string assignment_type = dataVisual->value.GetString();
822 
823  if (assignment_type != "GraphAdjacencyList")
824  throw "Malformed GraphAdjacencyList JSON: Not a GraphAdjacencyList";
825 
826  //reconstructing vertices out of nodes, and using the optional "name" as the data associated
827  {
828  const auto& nodes = data.FindMember("nodes");
829  if (nodes == data.MemberEnd() ||
830  nodes->value.IsArray() == false)
831  throw "Malformed GraphAdjacencyList JSON: malformed nodes";
832 
833 
834  const auto& nodeArray = nodes->value.GetArray();
835  int nbVertex = nodeArray.Size();
836  for (int i = 0; i < nbVertex; ++i) {
837  std::string name;
838 
839  const auto& vertexJSONstr = nodeArray[i];
840 
841  const auto& nameJSON = vertexJSONstr.FindMember("name");
842  if (nameJSON != vertexJSONstr.MemberEnd()
843  && nameJSON->value.IsString()) {
844  name = nameJSON->value.GetString();
845  }
846  gr.addVertex(i, name);
847  }
848  }
849 
850  //reconstructing links, and using "label" as data associated with the link
851  {
852  const auto& links = data.FindMember("links");
853  if (links == data.MemberEnd() ||
854  links->value.IsArray() == false)
855  throw "Malformed GraphAdjacencyList JSON: malformed links";
856 
857  const auto& linkArray = links->value.GetArray();
858  int nbLink = linkArray.Size();
859  for (int i = 0; i < nbLink; ++i) {
860  std::string name;
861  int src;
862  int dest;
863  int wgt;
864 
865  const auto& linkJSONstr = linkArray[i];
866 
867  //checking label. Maybe does not exist? (is that field optional?)
868  const auto& nameJSON = linkJSONstr.FindMember("label");
869  if (nameJSON != linkJSONstr.MemberEnd()
870  && nameJSON->value.IsString()) {
871  name = nameJSON->value.GetString();
872  }
873 
874  //checking source
875  const auto& srcJSON = linkJSONstr.FindMember("source");
876  if (srcJSON == linkJSONstr.MemberEnd()
877  || srcJSON->value.IsInt() == false) {
878  throw "Malformed GraphAdjacencyList JSON: malformed link";
879  }
880  src = srcJSON->value.GetInt();
881 
882 
883  //checking destination
884  const auto& dstJSON = linkJSONstr.FindMember("target");
885  if (dstJSON == linkJSONstr.MemberEnd()
886  || dstJSON->value.IsInt() == false) {
887  throw "Malformed GraphAdjacencyList JSON: malformed link";
888  }
889  dest = dstJSON->value.GetInt();
890 
891  //checking weight. //why is weight a mandatory parameter?
892  const auto& wgtJSON = linkJSONstr.FindMember("weight");
893  if (wgtJSON == linkJSONstr.MemberEnd()
894  || wgtJSON->value.IsInt() == false) {
895  throw "Malformed GraphAdjacencyList JSON: malformed link";
896  }
897  wgt = wgtJSON->value.GetInt();
898 
899 
900  //adding edge.
901  gr.addEdge(src, dest, name);
902  }
903  }
904 
905  return gr;
906  }
907 
916  int assignment,
917  int subassignment = 0) {
918 
919  std::string s = this->getAssignment(user, assignment, subassignment);
920 
921  rapidjson::Document doc;
922  doc.Parse(s.c_str());
923  if (doc.HasParseError())
924  throw "Malformed JSON";
925 
926  try {
927  std::string assignment_type = doc["assignment_type"].GetString();
928 
929  if (assignment_type != "ColorGrid")
930  throw "Malformed ColorGrid JSON: Not a ColorGrid";
931  }
932  catch (rapidjson_exception re) {
933  throw "Malformed JSON: Not a Bridges assignment?";
934  }
935 
936 
937  try {
938  auto& data = doc["data"][0];
939 
940  std::string encoding = data["encoding"].GetString();
941  if (encoding != "RAW" && encoding != "RLE")
942  throw "Malformed ColorGrid JSON: encoding not supported";
943 
944 
945  //Access doc["data"][0]["dimensions"]
946  const auto& dimensions = data["dimensions"];
947  int dimx = dimensions[0].GetInt();
948  int dimy = dimensions[1].GetInt();
949 
950  if (debug())
951  std::cerr << "Dimensions: " << dimx << "x" << dimy << std::endl;
952 
953  //Access doc["data"][0]["nodes"][0]
954  std::string base64_encoded_assignment = data["nodes"][0].GetString();
955 
956 
957  std::vector<bridges::BYTE> decoded = bridges::base64::decode(base64_encoded_assignment);
958 
959  bridges::ColorGrid cg (dimx, dimy);
960 
961 
962  if (encoding == "RAW") {
963  if (debug())
964  std::cerr << "decoding RAW" << std::endl;
965  if (debug())
966  std::cerr << "length: " << decoded.size() << std::endl;
967  if (decoded.size() < dimx * dimy * 4)
968  throw "Malformed ColorGrid JSON: nodes is smaller than expected";
969 
970  //first pixel
971  //std::cerr<<(int)decoded[0]<<" "<<(int)decoded[1]<<" "<<(int)decoded[2]<<" "<<(int)decoded[3]<<std::endl;
972 
973  //bridges::ColorGrid* ptr = new bridges::ColorGrid (dimx, dimy);
974 
975  size_t base = 0;
976 
977  for (int x = 0; x < dimx; ++x) {
978  for (int y = 0; y < dimy; ++y) {
979  bridges::Color c ((int)decoded[base],
980  (int)decoded[base + 1],
981  (int)decoded[base + 2],
982  (int)decoded[base + 3]
983  );
984 
985  cg.set(x, y, c);
986  base += 4;
987  }
988  }
989  }
990  else if (encoding == "RLE") {
991  if (debug())
992  std::cerr << "Decoding RLE" << std::endl;
993 
994  int currentInDecoded = 0;
995  int currentInCG = 0;
996  while (currentInDecoded != decoded.size()) {
997  if (currentInDecoded + 5 > decoded.size())
998  throw "Malformed ColorGrid JSON: nodes is not a multiple of 5";
999 
1000 
1001 
1002  int repeat = (BYTE) decoded[currentInDecoded++];
1003  int r = (BYTE) decoded[currentInDecoded++];
1004  int g = (BYTE) decoded[currentInDecoded++];
1005  int b = (BYTE) decoded[currentInDecoded++];
1006  int a = (BYTE) decoded[currentInDecoded++];
1007 
1008  if (debug())
1009  std::cerr << "indecoded: " << currentInDecoded
1010  << " repeat: " << (int)repeat
1011  << " color(" << (int)r << "," << (int)g << "," << (int)b << "," << (int)a << ")"
1012  << std::endl;
1013 
1014  bridges::Color c (r, g, b, a);
1015 
1016  while (repeat >= 0) {
1017  int posX = currentInCG / dimy;
1018  int posY = currentInCG % dimy;
1019  if (posX >= dimx || posY >= dimy) {
1020  if (debug())
1021  std::cerr << posX << " " << dimx << " " << posY << " " << dimy << std::endl;
1022  throw "Malformed ColorGrid JSON: Too much data in nodes";
1023  }
1024  cg.set(posX, posY, c);
1025 
1026  currentInCG++;
1027  repeat --;
1028  }
1029  }
1030  if (debug())
1031  std::cerr << "written " << currentInCG << " pixels" << std::endl;
1032  if (currentInCG != dimx * dimy)
1033  throw "Malformed ColorGrid JSON: Not enough data in nodes";
1034  }
1035 
1036  return cg;
1037  }
1038  catch (rapidjson_exception re) {
1039  throw "Malformed ColorGrid JSON";
1040  }
1041 
1042  }
1043  private:
1044  /***
1045  * This function obtains the JSON representation of a particular subassignment.
1046  *
1047  * @return a string that is the JSON representation of the subassignment as stored by the Bridges server.
1048  * @param user the name of the user who uploaded the assignment
1049  * @param assignment the ID of the assignment to get
1050  * @param subassignment the ID of the subassignment to get
1051  ***/
1052  std::string getAssignment(std::string user,
1053  int assignment,
1054  int subassignment = 0) {
1055  std::vector<std::string> headers;
1056 
1057  std::stringstream ss;
1058 
1060  if (bridges_inst)
1061  ss << bridges_inst->getServerURL();
1062  else
1063  ss << bridges::Bridges::getDefaultServerURL();
1064  ss << "/assignmentJSON/"
1065  << assignment << ".";
1066  ss << std::setfill('0') << std::setw(2) << subassignment;
1067  ss << "/" << user;
1068 
1069  std::string url = ss.str();
1070 
1071  // std::cout<<"URL: "<<url<<std::endl;
1072 
1073  std::string s = bridges::ServerComm::makeRequest(url, headers);
1074 
1075  return s;
1076  }
1077 
1078 
1079  void removeFirstOccurence (std::string & str, const std::string & toRemove) {
1080  size_t pos = str.find(toRemove);
1081  if (pos != std::string::npos) {
1082  str.erase(pos, toRemove.length());
1083  }
1084  }
1085 
1095  void getWikidataActorMovieDirect (int yearbegin, int yearend, std::vector<MovieActorWikidata>& vout) {
1096  std::string codename = "wikidata-actormovie-" + std::to_string(yearbegin) + "-" + std::to_string(yearend);
1097  std::string json;
1098  bool from_cache = false;
1099  try {
1100  if (my_cache.inCache(codename)) {
1101  json = my_cache.getDoc(codename);
1102  from_cache = true;
1103  }
1104  }
1105  catch (CacheException& ce) {
1106  //something went bad trying to access the cache
1107  std::cout << "Exception while reading from cache. Ignoring cache and continue." << std::endl;
1108  }
1109 
1110 
1111  if (!from_cache) {
1112  std::vector<std::string> http_headers;
1113  http_headers.push_back("User-Agent: bridges-cxx"); //wikidata kicks you out if you don't have a useragent
1114  http_headers.push_back("Accept: application/json"); //tell wikidata we are OK with JSON
1115 
1116  string url = "https://query.wikidata.org/sparql?";
1117 
1118  //Q1860 is "English"
1119  //P364 is "original language of film or TV show"
1120  //P161 is "cast member"
1121  //P577 is "publication date"
1122  //A11424 is "film"
1123  //P31 is "instance of"
1124  // "instance of film" is necessary to filter out tv shows
1125  std::string sparqlquery = "SELECT ?movie ?movieLabel ?actor ?actorLabel WHERE \
1126 {\
1127  ?movie wdt:P31 wd:Q11424.\
1128  ?movie wdt:P161 ?actor.\
1129  ?movie wdt:P364 wd:Q1860.\
1130  ?movie wdt:P577 ?date.\
1131  FILTER(YEAR(?date) >= " + std::to_string(yearbegin) + " && YEAR(?date) <= " + std::to_string(yearend) + ").\
1132  SERVICE wikibase:label { bd:serviceParam wikibase:language \"en\". } \
1133 }";
1134  url += "query=" + ServerComm::encodeURLPart(sparqlquery);
1135  url += "&";
1136  url += "format=json";
1137 
1138  // get the OSM data json
1139  json = ServerComm::makeRequest(url, http_headers);
1140 
1141  try {
1142  my_cache.putDoc(codename, json);
1143  }
1144  catch (CacheException& ce) {
1145  //something went bad trying to access the cache
1146  std::cerr << "Exception while storing in cache. Weird but not critical." << std::endl;
1147  }
1148  }
1149 
1150  {
1151  using namespace rapidjson;
1152  rapidjson::Document doc;
1153  doc.Parse(json.c_str());
1154  if (doc.HasParseError())
1155  throw "Malformed JSON";
1156 
1157  try {
1158  const auto& resultsArray = doc["results"]["bindings"].GetArray();
1159 
1160  for (auto& mak_json : resultsArray) {
1161  MovieActorWikidata mak;
1162 
1163  // all wikidata uri start with "http://www.wikidata.org/entity/"
1164  // so strip it out because it does not help discriminate and
1165  // consume memory and runtime to compare string
1166  std::string actoruri = mak_json["actor"]["value"].GetString();
1167  std::string movieuri = mak_json["movie"]["value"].GetString();
1168  removeFirstOccurence (actoruri, "http://www.wikidata.org/entity/");
1169 
1170  removeFirstOccurence (movieuri, "http://www.wikidata.org/entity/");
1171 
1172 
1173  mak.setActorURI(actoruri);
1174  mak.setMovieURI(movieuri);
1175  mak.setActorName(mak_json["actorLabel"]["value"].GetString());
1176  mak.setMovieName(mak_json["movieLabel"]["value"].GetString());
1177  vout.push_back(mak);
1178  }
1179 
1180  }
1181  catch (rapidjson_exception re) {
1182  throw "Malformed JSON: Not from wikidata?";
1183  }
1184  }
1185  }
1186  public:
1187 
1195  std::vector<MovieActorWikidata> getWikidataActorMovie (int yearbegin, int yearend) {
1196  //Internally this function get the data year by year. This
1197  //is pretty bad because it hits wikidata the first time
1198  //for multiple years. But it enables to work around
1199  //wikidata's time limit. This also works well because the
1200  //Cache will store each year independently and so without
1201  //redundancy. Though I (Erik) am not completely sure that a
1202  //movie can be appear in different years, for instance it
1203  //can be released in the US in 2005 but in canada in
1204  //2006...
1205 
1206  std::vector<MovieActorWikidata> ret;
1207  for (int y = yearbegin; y <= yearend; ++y) {
1208  cout << "getting year " << y << endl;
1209  getWikidataActorMovieDirect (y, y, ret);
1210  }
1211  return ret;
1212  }
1213 
1214 
1227  double latitMin, double longitMin,
1228  double latitMax, double longitMax, double res = 0.0166) {
1229 
1230  // set up the elevation data url to get the data, given
1231  // a lat/long bounding box
1232  string server_str =
1233  "http://cci-bridges-elevation-t.dyn.uncc.edu/";
1234 
1235  string elev_str = "elevation?";
1236 
1237  string bbox_str =
1238  "&minLon=" + std::to_string(longitMin) +
1239  "&minLat=" + std::to_string(latitMin) +
1240  "&maxLon=" + std::to_string(longitMax) +
1241  "&maxLat=" + std::to_string(latitMax);
1242 
1243  string resn_str = "&resX=" + std::to_string(res)
1244  + "&resY=" + std::to_string(res);
1245 
1246  string elev_data_url =
1247  server_str + elev_str + bbox_str + resn_str;
1248 
1249  if (debug())
1250  cerr << "Hitting data URL: " << elev_data_url << "\n";
1251  string hash_str = "hash?";
1252  string hash_url = server_str + hash_str + bbox_str;
1253 
1254 
1255 
1256  if (debug())
1257  cerr << "Hitting hash URL: " << hash_url << "\n";
1258 
1259  // get hash value for elevation data
1260  string hash_value = ServerComm::makeRequest(hash_url,
1261  {"Accept: application/json"});
1262 
1263  string elev_json;
1264 
1265  //Checks to see if elevation data is already in local cache
1266  if (my_cache.inCache(hash_value)) { // already exists
1267  try {
1268  elev_json = my_cache.getDoc(hash_value);
1269  }
1270  catch (CacheException& ce) {
1271  //something went bad trying to access the cache
1272  cout << "Exception while reading from cache. Ignoring cache." << std::endl;
1273  }
1274  }
1275  else { //Server response is false or not cached
1276 
1277  if (debug())
1278  cerr << "Hitting json URL: " << elev_data_url << "\n";
1279 
1280  // get the eleveation data
1281  elev_json = ServerComm::makeRequest(elev_data_url,
1282  {"Accept: application/json"});
1283 
1284  if (debug())
1285  cerr << "Hitting elev data URL: " << elev_data_url << "\n";
1286 
1287  string hash_value = ServerComm::makeRequest(hash_url,
1288  {"Accept: application/json"});
1289 
1290  if (hash_value == "false") {
1291  cerr << "Error in getting hash value for generated map..." << endl;
1292  cerr << elev_json << endl;
1293  abort();
1294  }
1295 
1296  // store map in cache
1297  try {
1298  my_cache.putDoc(hash_value, elev_json);
1299  }
1300  catch (CacheException& ce) {
1301  //something went bad trying to access the cache
1302  cerr << "Exception while storing in cache. Weird but not critical."
1303  << endl;
1304  }
1305  }
1306  return getElevationDataFromJSON(elev_json);
1307  }
1308 
1309  // get Elevation data from the JSON
1311 
1312  // use a string stream to parse the data, which is not really a JSON,
1313  // but raw text
1314  stringstream ss(elev_json);
1315 
1316  int rows, cols, elev_val;
1317  double ll_x, ll_y, cell_size;
1318  string tmp;
1319 
1320  // get the dimensions, origin
1321  ss >> tmp >> cols >> tmp >> rows >>
1322  tmp >> ll_x >> tmp >> ll_y >>
1323  tmp >> cell_size;
1324 
1325 
1326  // create the elevation object
1327  ElevationData *elev_data = new ElevationData(rows, cols);
1328  elev_data->setxll(ll_x);
1329  elev_data->setyll(ll_y);
1330  elev_data->setCellSize(cell_size);
1331 
1332  // tmp
1333  int data[85 * 185];
1334  int l = 0;
1335  // load the elevation data
1336  for (int i = 0; i < rows; i++) {
1337  for (int j = 0; j < cols; j++) {
1338  ss >> elev_val;
1339  elev_data->setVal(i, j, elev_val);
1340  }
1341  }
1342  return elev_data;
1343  }
1344 
1345  }; // class DataSource
1346 } // namespace bridges
1347 #endif
void setEventType(const string &et)
Set event type.
Definition: CancerIncidence.h:233
void setYear(int y)
Definition: CancerIncidence.h:183
void setMovieURI(std::string mu)
Definition: MovieActorWikidata.h:18
void setAffectedArea(const string &area)
Set cancer incidenc area.
Definition: CancerIncidence.h:269
A Gutenberg Book object metadata only, used along with the books data source.
Definition: GutenbergBook.h:25
void setCrudeRate(double cr)
Definition: CancerIncidence.h:126
Definition: Cache.h:14
vector< Shakespeare > getShakespeareData(string type="", bool textonly=false)
Get data of Shakespeare works (plays, poems)
Definition: DataSource.h:262
Definition: ActorMovieIMDB.h:10
A Shakespeare book object, used along with the Shakespeare books data source.
Definition: Shakespeare.h:28
virtual void putDoc(const std::string &hash_value, const std::string &content) override
Definition: Cache.h:168
std::vector< MovieActorWikidata > getWikidataActorMovie(int yearbegin, int yearend)
This function returns the Movie and Actors playing in them between two years.
Definition: DataSource.h:1195
Definition: MovieActorWikidata.h:8
void setCrudeRate_CI_Lower(double cr_l)
Definition: CancerIncidence.h:145
Definition: Cache.h:142
void setCrudeRate_CI_Upper(double cr_u)
Set crude rate CI (upper)
Definition: CancerIncidence.h:165
vector< Game > getGameData()
Definition: DataSource.h:94
STL namespace.
This class provides methods to represent adjacency list based graphs.
Definition: Element.h:19
void setActorName(std::string an)
Definition: MovieActorWikidata.h:30
A Song object, used along with the Songs data source.
Definition: Song.h:24
long OSMVertexID
Definition: OSMVertex.h:30
vector< Song > getSongData()
Definition: DataSource.h:363
Class that hold Open Street Map edges.
Definition: OSMEdge.h:21
void setLocationX(double locX)
Set location (X coord)
Definition: CancerIncidence.h:303
This is a class in BRIDGES for representing an image.
Definition: ColorGrid.h:22
bridges::ColorGrid getColorGridFromAssignment(const std::string &user, int assignment, int subassignment=0)
Definition: DataSource.h:915
Definition: JSONutil.h:6
void setName(const string &n)
change the name of the dataset
Definition: OSMData.h:222
void setAgeAdjustedCI_Lower(double ci_l)
Definition: CancerIncidence.h:90
virtual std::string getDoc(const std::string &hash_value) override
Definition: Cache.h:152
OSMData getOSMDataOld(string location)
old interface for the OSM data set.
Definition: DataSource.h:739
vector< ActorMovieIMDB > getActorMovieIMDBData(int number=0)
Definition: DataSource.h:132
This class represents Color, and supports rgba, hexadecimal and named color values.
Definition: Color.h:51
This class contains methods to connect and transmit a user&#39;s data structure representation to the Bri...
Definition: Bridges.h:39
void addVertex(const K &k, const E1 &e=E1())
Definition: GraphAdjList.h:96
void setActorURI(std::string au)
Definition: MovieActorWikidata.h:22
void setLocationY(double locY)
Set location (Y coord)
Definition: CancerIncidence.h:321
vector< EarthquakeUSGS > getEarthquakeUSGSData(int number=0)
Definition: DataSource.h:202
these methods convert byte arrays in to base64 codes and are used in BRIDGES to represent the color a...
Definition: alltypes.h:4
This class provides an API to various data sources used in BRIDGES.
Definition: DataSource.h:59
void setPopulation(int pop)
Set population size.
Definition: CancerIncidence.h:251
void setyll(int y_ll)
Definition: ElevationData.h:163
void setMovieName(std::string mn)
Definition: MovieActorWikidata.h:26
void setVertices(const vector< OSMVertex > &verts)
replace the vertices stored by this new set.
Definition: OSMData.h:267
vector< GutenbergBook > getGutenbergBookData(int num=0)
Definition: DataSource.h:403
A class to hold actor movie data – using IMDB dataset.
Definition: ActorMovieIMDB.h:19
void setLatLongRange(double *lat_range, double *longit_range)
set the latitude and longitude range of the dataset
Definition: OSMData.h:108
void setAgeAdjustedCI_Upper(double ci_u)
Definition: CancerIncidence.h:109
vector< CancerIncidence > getCancerIncidenceData(int num=0)
Definition: DataSource.h:464
unsigned char BYTE
Definition: base64.h:44
Class that hold elevation data.
Definition: ElevationData.h:21
bridges::GraphAdjList< int, std::string > getGraphFromAssignment(const std::string &user, int assignment, int subassignment=0)
Definition: DataSource.h:787
Song getSong(string songTitle, string artistName)
Definition: DataSource.h:308
ElevationData * getElevationData(double latitMin, double longitMin, double latitMax, double longitMax, double res=0.0166)
Definition: DataSource.h:1226
Class that hold Open Street Map vertices.
Definition: OSMData.h:34
void setRace(const string &r)
Set race.
Definition: CancerIncidence.h:216
DataSource(bridges::Bridges *br=nullptr)
Definition: DataSource.h:75
void set(int row, int col, E val)
Definition: Grid.h:144
OSMData getOSMData(double lat_min, double long_min, double lat_max, double long_max, string level="default")
Definition: DataSource.h:585
ElevationData * getElevationDataFromJSON(string elev_json)
Definition: DataSource.h:1310
void setxll(int x_ll)
Definition: ElevationData.h:145
OSMData getOSMData(string location, string level="default")
Definition: DataSource.h:669
DataSource(bridges::Bridges &br)
Definition: DataSource.h:78
void setCellSize(int cell_size)
Definition: ElevationData.h:181
void setAgeAdjustedRate(double aar)
Definition: CancerIncidence.h:69
virtual bool inCache(const std::string &hash_value) override
Definition: Cache.h:161
void setEdges(const vector< OSMEdge > &e)
set edges
Definition: OSMData.h:305
A Game object, used along with the Games data source.
Definition: Game.h:24
A class representing the attributes for cancer incidence.
Definition: CancerIncidence.h:26
OSMData getOSMDataFromJSON(const string &osm_json)
Definition: DataSource.h:515
Class that hold earthquake data, for use with USGIS retrieved quake data.
Definition: EarthquakeUSGS.h:21
void setVal(int r, int c, int val)
Definition: ElevationData.h:108
vector< ActorMovieIMDB > getActorMovieIMDBData2()
Definition: DataSource.h:166
Definition: Array.h:9
void addEdge(const K &src, const K &dest, const E2 &data=E2())
add an edge with data.
Definition: GraphAdjList.h:119
Class that hold Open Street Map vertices.
Definition: OSMVertex.h:28
vector< BYTE > decode(string const &encoded_string)
Definition: base64.h:103