diff --git a/cache.h b/cache.h
index a4ef19d..fece0b9 100644
--- a/cache.h
+++ b/cache.h
@@ -54,6 +54,7 @@ public:
class Cache {
public:
std::string code;
+ int internal_id;
Position pos;
std::string name;
Status status;
@@ -86,6 +87,7 @@ public:
int age_when_found = -1;
int age_now = -1;
int trail = 0;
+ bool ftf = 0;
void set_date(const std::tm& t);
void set_date_hidden(const std::tm& t);
diff --git a/geostat.cpp b/geostat.cpp
index d517d77..98b6889 100644
--- a/geostat.cpp
+++ b/geostat.cpp
@@ -201,7 +201,8 @@ int main(int argc, char** argv) {
if (use_oc) {
if (!ocpl_user_uuid.empty() || !ocpl_user.empty()) {
Okapi OCpl(ocpl_url, ocpl_key);
- if (!ocpl_user.empty()) ocpl_user_uuid = OCpl.get_uuid(ocpl_user);
+ int uid;
+ if (!ocpl_user.empty()) ocpl_user_uuid = OCpl.get_uuid(ocpl_user, &uid);
Caches tmp = OCpl.get_user_caches(ocpl_user_uuid, 0);
t.read_from_json("powertrails.json");
@@ -217,6 +218,8 @@ int main(int argc, char** argv) {
}
}
+ OCpl.get_ftf(uid, tmp);
+
std::copy(tmp.begin(), tmp.end(), std::back_inserter(cc));
ocpl_user_profile = OCpl.get_profile_url(ocpl_user_uuid);
}
@@ -346,6 +349,7 @@ int main(int argc, char** argv) {
pCaches caches_by_fav;
pCaches caches_by_fav_perc;
pCaches caches_by_finds;
+ pCaches caches_ftf;
// pCaches caches_by_rating;
pCaches fcc;
@@ -369,7 +373,8 @@ int main(int argc, char** argv) {
caches_by_fav_perc.push_back(&*i);
caches_by_finds.push_back(&*i);
// caches_by_rating.push_back(&*i);
-
+ if (i->ftf)
+ caches_ftf.push_back(&*i);
i++;
}
std::sort(caches_by_fav.begin(), caches_by_fav.end(), [&](const Cache* a, const Cache* b) { return a->fav > b->fav; });
@@ -910,6 +915,34 @@ int main(int argc, char** argv) {
std::cout << "Number of started power trails: " << tt.size() << "
\n";
std::cout << "\n";
+ std::cout << "
FTF
\n";
+ std::cout << "\n";
+ std::cout << " | ";
+ std::cout << "Cache | ";
+ std::cout << "Type | ";
+ std::cout << "Region | ";
+ std::cout << "Date hidden | ";
+ std::cout << "Finds | ";
+ std::cout << "
\n";
+
+ n = 1;
+
+ for (auto i : caches_ftf) {
+ std::cout << "" << n << " | ";
+ std::cout << "" << i->link_name() << " | ";
+ std::cout << "" << i->type << " | ";
+ std::cout << "" << i->region << " | ";
+ std::cout << "" << i->date_hidden << " | ";
+ std::cout << "" << i->founds << " | ";
+ std::cout << "
\n";
+ n++;
+// if (n > LIST_MAX) break;
+ }
+ std::cout << "
\n";
+ std::cout << "\n";
+// std::cout << "Number of FTFs: " << std::count_if(cc.begin(), cc.end(), [&](const auto& a) { return a.ftf; }) << "
\n";
+ std::cout << "Number of FTFs: " << caches_ftf.size() << "
\n";
+ std::cout << "
\n";
} // end of main if
if (get_not_found) {
diff --git a/okapi.cpp b/okapi.cpp
index 2f3e6a2..fa6f7cb 100644
--- a/okapi.cpp
+++ b/okapi.cpp
@@ -93,7 +93,7 @@ void Okapi::get_user_caches_json(const std::string& uuid, int count, int offset)
void Okapi::get_caches_json(const std::string& codes) const {
std::string service = url + OKAPI_caches;
- std::string query = "consumer_key=" + key + "&cache_codes=" + codes + "&fields=code|name|location|type|status|difficulty|terrain|owner|region|country2|size2|date_created|recommendations|rating|founds|status";
+ std::string query = "consumer_key=" + key + "&cache_codes=" + codes + "&fields=code|name|location|type|status|difficulty|terrain|owner|region|country2|size2|date_created|recommendations|rating|founds|status|internal_id";
curl_post(service, query);
}
@@ -153,6 +153,7 @@ Caches Okapi::get_caches(const std::set& codes) const {
for (auto& el : j.items()) {
if (el.value().is_null()) continue;
c.code = el.value()["code"];
+ c.internal_id = el.value()["internal_id"];
c.name = el.value()["name"];
c.type = el.value()["type"];
c.size = el.value()["size2"];
@@ -310,13 +311,14 @@ void Okapi::update_caches_ratings(Caches& cc) const {
}
}
-std::string Okapi::get_uuid(const std::string& username) const {
+std::string Okapi::get_uuid(const std::string& username, int* id) const {
std::string service = url + OKAPI_username;
char* user_esc = curl_easy_escape(curl, username.c_str(), username.size());
- std::string query = "consumer_key=" + key + "&username=" + user_esc + "&fields=uuid";
+ std::string query = "consumer_key=" + key + "&username=" + user_esc + "&fields=uuid|internal_id";
curl_free(user_esc);
curl_post(service, query);
json j = json::parse(curl_output);
+ if (id) *id = j["internal_id"];
return j["uuid"];
}
@@ -334,3 +336,29 @@ std::string Okapi::get_changelog_json(int revision) const {
curl_post(service, query);
return curl_output;
}
+
+void Okapi::get_ftf(int id, Caches& cc) const {
+ std::string url = "https://opencaching.pl/UserProfile/getUserFtfsAjax/" + std::to_string(id);
+ CURLcode res;
+
+ curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
+ curl_output.clear();
+
+ res = curl_easy_perform(curl);
+ if (res != CURLE_OK) {
+ Debug(1) << "Connection failed: " << curl_easy_strerror(res) << '\n';
+ curl_easy_cleanup(curl);
+ std::exit(EXIT_FAILURE);
+ }
+
+ Debug(5) << "FTF query result: " << curl_output;
+ json j = json::parse(curl_output);
+ for (auto& el : j.items()) {
+ if (el.value().is_null()) continue;
+ int id = std::stoi(el.value()["cache_id"].get());
+ auto res = std::find_if(cc.begin(), cc.end(), [&](const auto& a) { return a.internal_id == id; });
+ if (res != std::end(cc))
+ res->ftf = 1;
+ }
+}
diff --git a/okapi.h b/okapi.h
index 42e7555..c0db747 100644
--- a/okapi.h
+++ b/okapi.h
@@ -40,6 +40,7 @@ public:
void update_caches(Caches& cc) const;
void update_caches_ratings(Caches& cc) const;
- std::string get_uuid(const std::string& username) const;
+ std::string get_uuid(const std::string& username, int* id = nullptr) const;
std::string get_profile_url(const std::string& uuid) const;
+ void get_ftf(int id, Caches& cc) const;
};