kopia lustrzana https://gitlab.com/tomaszg/geostat
199 wiersze
5.8 KiB
C++
199 wiersze
5.8 KiB
C++
#include "powertrail.h"
|
|
#include "debug.h"
|
|
#include "common.h"
|
|
|
|
#include <regex>
|
|
#include <fstream>
|
|
|
|
#include <curl/curl.h>
|
|
#include <time.h>
|
|
#include <nlohmann/json.hpp>
|
|
|
|
using json = nlohmann::json;
|
|
|
|
static const std::string url = "https://opencaching.pl/powerTrail.php?ptAction=showSerie&ptrail=";
|
|
static const std::string url2 = "https://opencaching.pl/powerTrail/ajaxGetPowerTrailCaches.php?ptAction=showSerie&ptrail=";
|
|
|
|
static const std::regex regex_name("<span id=\"powerTrailName\">(.*?)</span>");
|
|
static const std::regex regex_type("<span id=\"ptTypeName\">(.*?)</span>");
|
|
static const std::regex regex_date("<span id=\"powerTrailDateCreated\">(.*?)</span>");
|
|
static const std::regex regex_perc("<span id=\"powerTrailpercent\">(.*?)</span>");
|
|
static const std::regex regex_cache("<a href=\"(OP.*?)\">.*?<img src=\"/images/log/(.*?)\\.png\"");
|
|
|
|
void to_json(json& j, const Powertrail& item) {
|
|
j = json{ { "name", item.name }, { "date", item.date_str }, { "treshold", item.treshold_perc }, { "active", item.active_caches }, { "caches", item.caches }, { "type", item.type } };
|
|
}
|
|
|
|
void from_json(const json& j, Powertrail& item) {
|
|
j.at("name").get_to(item.name);
|
|
j.at("date").get_to(item.date_str);
|
|
j.at("treshold").get_to(item.treshold_perc);
|
|
j.at("active").get_to(item.active_caches);
|
|
j.at("caches").get_to(item.caches);
|
|
j.at("type").get_to(item.type);
|
|
strptime(item.date_str.c_str(), "%d-%m-%Y", &item.date);
|
|
item.treshold = (item.caches.size() * item.treshold_perc + 99) / 100; // Integer division rounding up
|
|
item.active_caches_not_found = item.active_caches;
|
|
}
|
|
|
|
std::string Powertrail::link() const {
|
|
return "https://opencaching.pl/powerTrail.php?ptAction=showSerie&ptrail=" + std::to_string(number);
|
|
}
|
|
|
|
std::string Powertrail::link_name() const {
|
|
return "<a href=\"" + link() + "\">" + safe_name() + "</a>";
|
|
}
|
|
|
|
std::string Powertrail::safe_name() const {
|
|
std::string tmp = name;
|
|
htmlencode(tmp);
|
|
return tmp;
|
|
}
|
|
std::string Powertrail::get_type() const {
|
|
return types[type];
|
|
}
|
|
|
|
PowertrailDB::PowertrailDB() {
|
|
curl = curl_easy_init();
|
|
if (!curl) {
|
|
curl_global_cleanup();
|
|
throw 0;
|
|
}
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&curl_output);
|
|
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5);
|
|
}
|
|
|
|
PowertrailDB::~PowertrailDB() {
|
|
curl_easy_cleanup(curl);
|
|
}
|
|
|
|
void PowertrailDB::get_trail(uint n) {
|
|
CURLcode curl_res;
|
|
std::smatch res;
|
|
|
|
Powertrail T;
|
|
T.number = n;
|
|
|
|
curl_output.clear();
|
|
curl_easy_setopt(curl, CURLOPT_URL, (url + std::to_string(n)).c_str());
|
|
curl_res = curl_easy_perform(curl);
|
|
if (curl_res != CURLE_OK) {
|
|
Debug(1) << "Connection failed: " << curl_easy_strerror(curl_res) << '\n';
|
|
curl_easy_cleanup(curl);
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (std::regex_search(curl_output, res, regex_name) && res.size() == 2) {
|
|
T.name = res[1].str();
|
|
if (T.name.empty()) return;
|
|
Debug(2) << "Read name: " << T.name;
|
|
} else
|
|
return;
|
|
if (std::regex_search(curl_output, res, regex_type) && res.size() == 2) {
|
|
if (res[1].str() == "Geo-szkic")
|
|
T.type = geoszkic;
|
|
else if (res[1].str() == "Krajoznawcza")
|
|
T.type = krajoznawcza;
|
|
else if (res[1].str() == "Przyrodnicza")
|
|
T.type = przyrodnicza;
|
|
else if (res[1].str() == "Tematyczna")
|
|
T.type = tematyczna;
|
|
else
|
|
T.type = unknown_type;
|
|
}
|
|
if (std::regex_search(curl_output, res, regex_date) && res.size() == 2) {
|
|
strptime(res[1].str().c_str(), "%d-%m-%Y", &T.date);
|
|
T.date_str = res[1].str();
|
|
Debug(2) << "Read time: " << T.date_str;
|
|
}
|
|
if (std::regex_search(curl_output, res, regex_perc) && res.size() == 2) {
|
|
T.treshold_perc = std::stoi(res[1].str());
|
|
Debug(2) << "Read percent: " << T.treshold_perc;
|
|
}
|
|
|
|
curl_output.clear();
|
|
curl_easy_setopt(curl, CURLOPT_URL, (url2 + std::to_string(n)).c_str());
|
|
curl_res = curl_easy_perform(curl);
|
|
if (curl_res != CURLE_OK) {
|
|
Debug(1) << "Connection failed: " << curl_easy_strerror(curl_res) << '\n';
|
|
curl_easy_cleanup(curl);
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
|
|
auto caches_begin = std::sregex_iterator(curl_output.begin(), curl_output.end(), regex_cache);
|
|
auto caches_end = std::sregex_iterator();
|
|
|
|
Debug(2) << "Found " << std::distance(caches_begin, caches_end) << " caches.\n";
|
|
|
|
for (std::sregex_iterator i = caches_begin; i != caches_end; i++) {
|
|
std::smatch match = *i;
|
|
T.caches.insert(match[1].str());
|
|
if (match[2].str() == "16x16-published")
|
|
T.active_caches++;
|
|
}
|
|
|
|
T.treshold = (T.caches.size() * T.treshold_perc + 99) / 100; // Integer division rounding up
|
|
|
|
data.insert({ n, T });
|
|
}
|
|
|
|
// Callback for cURL easy interface used to save received output to std::string object
|
|
size_t PowertrailDB::write_cb(char* ptr, __attribute__((unused)) size_t size, size_t nmemb, void* userdata) {
|
|
std::string* str = reinterpret_cast<std::string*>(userdata);
|
|
str->append(ptr, nmemb);
|
|
return nmemb;
|
|
}
|
|
|
|
void PowertrailDB::read_from_json(std::string file) {
|
|
std::ifstream datafile(file);
|
|
|
|
try {
|
|
json j;
|
|
datafile >> j;
|
|
data = j.get<std::unordered_map<uint, Powertrail>>();
|
|
}
|
|
catch (...) {
|
|
Debug(1) << "Cache file: " << file << " corrupted.";
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
|
|
for (auto& p : data)
|
|
p.second.number = p.first;
|
|
};
|
|
|
|
void PowertrailDB::save_to_json(std::string file) {
|
|
std::ofstream datafile(file);
|
|
json j(data);
|
|
datafile << j;
|
|
};
|
|
|
|
Caches_in_Powertrails::Caches_in_Powertrails(const PowertrailDB& db) {
|
|
for (auto& t : db.data) {
|
|
for (auto& c : t.second.caches) {
|
|
data.insert({ c, t.second.number });
|
|
}
|
|
}
|
|
}
|
|
|
|
void Caches_in_Powertrails::read_from_json(std::string file) {
|
|
std::ifstream datafile(file);
|
|
|
|
try {
|
|
json j;
|
|
datafile >> j;
|
|
data = j.get<std::unordered_map<std::string, int>>();
|
|
}
|
|
catch (...) {
|
|
Debug(1) << "Cache file: " << file << " corrupted.";
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
};
|
|
|
|
void Caches_in_Powertrails::save_to_json(std::string file) {
|
|
std::ofstream datafile(file);
|
|
json j(data);
|
|
datafile << j;
|
|
};
|