Program Listing for File indicator_manipulation.cpp
↰ Return to documentation for file (lib/indicator_manipulation.cpp
)
#include "AnalysisGraph.hpp"
#include "data.hpp"
#include <sqlite3.h>
#include <range/v3/all.hpp>
using namespace std;
using namespace delphi::utils;
using fmt::print;
using namespace fmt::literals;
/*
============================================================================
Public: Indicator Manipulation
============================================================================
*/
int AnalysisGraph::set_indicator(string concept,
string indicator,
string source) {
if (in(this->indicators_in_CAG, indicator)) {
print("{0} already exists in Causal Analysis Graph, Indicator {0} was "
"not added to Concept {1}.",
indicator,
concept);
return -1;
}
int ind_id = (*this)[concept].add_indicator(indicator, source);
this->indicators_in_CAG.insert(indicator);
return ind_id;
}
void AnalysisGraph::delete_indicator(string concept, string indicator) {
(*this)[concept].delete_indicator(indicator);
this->indicators_in_CAG.erase(indicator);
}
void AnalysisGraph::delete_all_indicators(string concept) {
(*this)[concept].clear_indicators();
}
void AnalysisGraph::map_concepts_to_indicators(int n_indicators,
string country) {
sqlite3* db = this->open_delphi_db(SQLITE_OPEN_READONLY);
if (db == nullptr) {
cout << "\n\nERROR: opening delphi.db" << endl;
exit(1);
}
int rc;
sqlite3_stmt* stmt = nullptr;
string query_base = "select Indicator from concept_to_indicator_mapping ";
string query;
// Check if there are any data values for an indicator for this country.
auto has_data = [&](string indicator) {
query =
"select `Value` from indicator where `Variable` like '{0}' and `Country` like '{1}'"_format(
indicator, country);
rc = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, NULL);
rc = sqlite3_step(stmt) == SQLITE_ROW;
sqlite3_finalize(stmt);
stmt = nullptr;
return rc;
};
auto get_indicator_source = [&](string indicator) {
query =
"select `Source` from indicator where `Variable` like '{0}' and `Country` like '{1}' limit 1"_format(
indicator, country);
rc = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, NULL);
rc = sqlite3_step(stmt);
string source =
string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
sqlite3_finalize(stmt);
stmt = nullptr;
return source;
};
for (Node& node : this->nodes()) {
node.clear_indicators(); // Clear pre-existing attached indicators
query = "{0} where `Concept` like '{1}' order by `Score` desc"_format(
query_base, node.name);
rc = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, NULL);
vector<string> matches = {};
while (sqlite3_step(stmt) == SQLITE_ROW) {
matches.push_back(
string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0))));
}
sqlite3_finalize(stmt);
stmt = nullptr;
string ind_name, ind_source;
for (int i = 0; i < n_indicators; i++) {
bool at_least_one_indicator_found = false;
for (string indicator : matches) {
if (!in(this->indicators_in_CAG, indicator) and has_data(indicator)) {
node.add_indicator(indicator, get_indicator_source(indicator));
this->indicators_in_CAG.insert(indicator);
at_least_one_indicator_found = true;
break;
}
}
if (!at_least_one_indicator_found) {
print("No suitable indicators found for concept '{0}' for country "
"'{1}', please select "
"one manually.\n",
node.name,
country);
}
}
}
rc = sqlite3_finalize(stmt);
rc = sqlite3_close(db);
stmt = nullptr;
db = nullptr;
}