kopia lustrzana https://gitlab.com/tomaszg/geostat
276 wiersze
7.7 KiB
C++
276 wiersze
7.7 KiB
C++
#include "user.h"
|
|
#include "debug.h"
|
|
#include "heat.h"
|
|
#include "common.h"
|
|
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <algorithm>
|
|
#include <unistd.h>
|
|
|
|
void show_usage() {
|
|
std::cout << "Usage: geostat [options]\n";
|
|
std::cout << "Generate stats from Opencaching data or GPX files.\n\n";
|
|
std::cout << " * Data sources:\n";
|
|
std::cout << "\t-o[user]\tuse Opencaching; if specified user will be a user name used for all OC instances\n";
|
|
std::cout << "\t-p user\t\tuser for opencaching.pl\n";
|
|
std::cout << "\t-d user\t\tuser for opencaching.de\n";
|
|
std::cout << "\t-u user\t\tuser for opencaching.us\n";
|
|
std::cout << "\t-n user\t\tuser for opencaching.nl\n";
|
|
std::cout << "\t-r user\t\tuser for opencaching.ro\n";
|
|
std::cout << "\t-k user\t\tuser for opencaching.uk\n";
|
|
std::cout << "\t-g file\t\tuse specified gpx file\n";
|
|
std::cout << "\t-q\t\tuse local SQLite file with dump of OC database\n";
|
|
std::cout << " * Output:\n";
|
|
std::cout << "\t-N\t\tcompute stats only for unfound caches (works only with SQLite)\n";
|
|
std::cout << "\t-M\t\tprint geographically extreme caches\n";
|
|
// std::cout << "\t-D\t\tprint furthest and closest caches\n";
|
|
std::cout << "\t-C\t\tprint calendar related stats\n";
|
|
std::cout << "\t-H file\t\trender a heat map to a file\n";
|
|
std::cout << "\t-s n\t\tstamp size for a heat map (default = 15)\n";
|
|
std::cout << "\t-e\t\tuse exponential to flatten the heat map\n";
|
|
std::cout << "\t-t\t\tdraw trail instead of heat map\n";
|
|
std::cout << "\t-a\t\tdraw animated map instead of heat map\n";
|
|
std::cout << "\t-m map\t\tchosen map: Poland, Poland_relief, Poland_big, Europe, World or a name of voivodeship (default = Poland)\n";
|
|
std::cout << "\t-L\t\tprint all caches\n";
|
|
std::cout << "\t-T\t\tprint D/T matrix\n";
|
|
std::cout << "\t-O\t\tprint owner count for found caches\n";
|
|
std::cout << "\t-Y\t\tprint types count for found caches\n";
|
|
std::cout << "\t-h\t\tdisplay this help screen\n";
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
User user;
|
|
bool show_minmax = 0;
|
|
// bool show_dist = 0;
|
|
bool show_list = 0;
|
|
bool show_dt = 0;
|
|
bool show_owners = 0;
|
|
bool show_types = 0;
|
|
bool show_calendar = 0;
|
|
std::string heat_file;
|
|
int heat_stamp_size = 15;
|
|
std::string heat_map = "Poland";
|
|
bool heat_exp = 0;
|
|
bool trail = 0;
|
|
bool anim = 0;
|
|
|
|
std::string gpx_file;
|
|
|
|
#include "config_user.h"
|
|
|
|
if (argc == 1) show_usage();
|
|
|
|
int o;
|
|
while ((o = getopt(argc, argv, "qNOg:o::p:d:u:n:r:k:MDCH:s:m:etaLTYh?")) != -1)
|
|
switch (o) {
|
|
// case 'd':
|
|
// Debug::set_debug_level(get_num('d',optarg));
|
|
// break;
|
|
// case 'g':
|
|
// gpx_file = optarg;
|
|
break;
|
|
case 'o':
|
|
user.use_oc = 1;
|
|
if (optarg) {
|
|
user.ocpl_user = optarg;
|
|
user.ocde_user = optarg;
|
|
user.ocus_user = optarg;
|
|
user.ocnl_user = optarg;
|
|
user.ocro_user = optarg;
|
|
user.ocuk_user = optarg;
|
|
}
|
|
break;
|
|
case 'p':
|
|
user.ocpl_user = optarg;
|
|
break;
|
|
case 'd':
|
|
user.ocde_user = optarg;
|
|
break;
|
|
case 'u':
|
|
user.ocus_user = optarg;
|
|
break;
|
|
case 'n':
|
|
user.ocnl_user = optarg;
|
|
break;
|
|
case 'r':
|
|
user.ocro_user = optarg;
|
|
break;
|
|
case 'k':
|
|
user.ocuk_user = optarg;
|
|
break;
|
|
case 'q':
|
|
user.use_ocdb = 1;
|
|
break;
|
|
case 'N':
|
|
user.get_not_found = 1;
|
|
break;
|
|
case 'O':
|
|
user.get_owned = 1;
|
|
break;
|
|
case 'M':
|
|
show_minmax = 1;
|
|
break;
|
|
// case 'D':
|
|
// show_dist = 1;
|
|
// break;
|
|
case 'C':
|
|
show_calendar = 1;
|
|
break;
|
|
// case 'O':
|
|
// show_owners = 1;
|
|
// break;
|
|
case 'Y':
|
|
show_types = 1;
|
|
break;
|
|
case 'H':
|
|
heat_file = optarg;
|
|
break;
|
|
case 's':
|
|
heat_stamp_size = get_num('s', optarg);
|
|
break;
|
|
case 'm':
|
|
heat_map = optarg;
|
|
break;
|
|
case 'e':
|
|
heat_exp = 1;
|
|
break;
|
|
case 't':
|
|
trail = 1;
|
|
break;
|
|
case 'a':
|
|
anim = 1;
|
|
break;
|
|
case 'L':
|
|
show_list = 1;
|
|
break;
|
|
case 'T':
|
|
show_dt = 1;
|
|
break;
|
|
case 'h':
|
|
case '?':
|
|
default:
|
|
show_usage();
|
|
}
|
|
|
|
if (user.get_not_found || user.get_owned) {
|
|
user.use_oc = 0;
|
|
user.use_ocdb = 1;
|
|
// trail = 0;
|
|
if (user.ocpl_user_uuid.empty() && user.ocpl_user.empty() && user.ocde_user_uuid.empty() && user.ocde_user.empty()) {
|
|
std::cout << "Options \"-N\" or \"-O\" work only with OCpl or OCde.\n";
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
if (user.get_not_found && user.get_owned) {
|
|
std::cout << "Options \"-N\" and \"-O\" are mutually exclusive.\n";
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
if (trail && anim) {
|
|
std::cout << "Options \"-a\" and \"-t\" are mutually exclusive.\n";
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
|
|
user.get_caches();
|
|
|
|
if (user.caches_count == 0) {
|
|
std::cout << "No caches found, aborting.\n";
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
|
|
user.prepare_lists_of_caches();
|
|
|
|
if (!heat_file.empty()) {
|
|
const Map* chosen_map;
|
|
if (maps.count(heat_map) > 0)
|
|
chosen_map = &maps.at(heat_map);
|
|
else {
|
|
std::cout << "Map " << heat_map << " not found.\n";
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
Heat hmap(chosen_map);
|
|
if (trail)
|
|
hmap.generate_path(heat_file, user.sorted_caches);
|
|
else if (anim)
|
|
hmap.generate_anim(heat_file, user.sorted_caches, heat_stamp_size);
|
|
else
|
|
hmap.generate(heat_file, user.fcc, heat_stamp_size, (heat_exp == 1 ? "exp" : "soft"));
|
|
}
|
|
|
|
if (!user.get_not_found) {
|
|
if (show_list) {
|
|
for (auto el : user.sorted_caches)
|
|
el.second->show();
|
|
}
|
|
|
|
if (show_minmax) {
|
|
auto N = *std::max_element(user.fcc.begin(), user.fcc.end(), [&](const Cache* a, const Cache* b) { return a->pos.lat < b->pos.lat; });
|
|
auto S = *std::min_element(user.fcc.begin(), user.fcc.end(), [&](const Cache* a, const Cache* b) { return a->pos.lat < b->pos.lat; });
|
|
auto E = *std::max_element(user.fcc.begin(), user.fcc.end(), [&](const Cache* a, const Cache* b) { return a->pos.lon < b->pos.lon; });
|
|
auto W = *std::min_element(user.fcc.begin(), user.fcc.end(), [&](const Cache* a, const Cache* b) { return a->pos.lon < b->pos.lon; });
|
|
|
|
std::cout << "Most N:\n";
|
|
N->show();
|
|
std::cout << "Most S:\n";
|
|
S->show();
|
|
std::cout << "Most E:\n";
|
|
E->show();
|
|
std::cout << "Most W:\n";
|
|
W->show();
|
|
}
|
|
|
|
// if (show_dist) {
|
|
// auto far = *std::max_element(user.fcc.begin(), user.fcc.end(), [&](const Cache* a, const Cache* b) { return a->distance() < b->distance(); });
|
|
// auto near = *std::min_element(user.fcc.begin(), user.fcc.end(), [&](const Cache* a, const Cache* b) { return a->distance() < b->distance(); });
|
|
//
|
|
// std::cout << "Nearest cache: " << near->distance() << " km\n";
|
|
// near->show();
|
|
// std::cout << "Furthest cache: " << far->distance() << " km\n";
|
|
// far->show();
|
|
// }
|
|
|
|
if (show_owners) {
|
|
show_histogram(user.cc, &Cache::owner, "Cache owners");
|
|
}
|
|
|
|
if (show_types) {
|
|
show_histogram(user.cc, &Cache::type, "Cache types");
|
|
show_histogram(user.cc, &Cache::size, "Cache sizes");
|
|
show_histogram(user.cc, &Cache::origin, "Services");
|
|
show_histogram(user.cc, &Cache::region, "Regions");
|
|
}
|
|
|
|
if (show_calendar) {
|
|
show_histogram(user.cc, &Cache::day_of_week, "Days of the week", 0, 0);
|
|
show_histogram(user.cc, &Cache::mon, "Months", 0, 0);
|
|
show_histogram(user.cc, &Cache::year, "Years", 0, 0);
|
|
}
|
|
|
|
if (show_dt) {
|
|
short dt_table[11][11];
|
|
|
|
std::cout << std::setw(5) << "D\\T";
|
|
for (int j = 2; j <= 10; j++) { // print table terr headers
|
|
std::cout << std::setw(5) << j / 2.0;
|
|
}
|
|
std::cout << '\n';
|
|
|
|
for (int i = 2; i <= 10; i++) { // i -> diff in rows
|
|
std::cout << std::setw(5) << i / 2.0;
|
|
for (int j = 2; j <= 10; j++) { // j -> terr in cols
|
|
dt_table[i][j] = std::count_if(user.cc.begin(), user.cc.end(), [i, j](const Cache& c) { return (c.diff == i / 2.0 && c.terr == j / 2.0); });
|
|
std::cout << std::setw(5) << dt_table[i][j];
|
|
}
|
|
std::cout << '\n';
|
|
}
|
|
}
|
|
} else {
|
|
if (show_list) {
|
|
for (const auto& el : user.cc)
|
|
el.show();
|
|
}
|
|
}
|
|
}
|