diff --git a/cache.cpp b/cache.cpp index cb09b0a..f910b4d 100644 --- a/cache.cpp +++ b/cache.cpp @@ -14,6 +14,10 @@ void Cache::show() const { std::cout << '\t' << pos.lat << " " << pos.lon << "\t\t D/T: " << diff << '/' << terr << '\n'; } +std::string Cache::link() const { + return "http://coord.eu/" + code; +} + float Cache::distance() const { return 2 * Earth_radius * asin(sqrt(pow(sin(degtorad((pos.lat - home.lat) / 2)), 2) + cos(degtorad(pos.lat)) * cos(degtorad(home.lat)) * pow(sin(degtorad((pos.lon - home.lon) / 2)), 2))); } diff --git a/cache.h b/cache.h index 8f1e481..08688c5 100644 --- a/cache.h +++ b/cache.h @@ -54,6 +54,7 @@ public: static Position home; void show() const; + std::string link() const; float distance() const; }; diff --git a/geo.css b/geo.css new file mode 100644 index 0000000..b210754 --- /dev/null +++ b/geo.css @@ -0,0 +1,517 @@ +@import url('https://fonts.googleapis.com/css?family=Lato|Special+Elite|Averia+Serif+Libre'); + +body { + padding: 0px; + margin: 0px; + background: white; + font-family: 'Lato', serif; + font-weight: normal; + font-size: 14px; +} + +h1 { + text-align: center; + font-family: 'Averia Serif Libre', serif; + font-size: 34px; + font-weight: bold; + color: #BBB; +} + +h2 { + text-align: center; + font-family: 'Special Elite', serif; + font-size: 26px; + font-weight: bold; + color: #48B; +} + +table, dl, .histogram_others, .heatmap { + margin-left: auto; + margin-right: auto; + padding-bottom: 20px; +} + +.heatmap { + display: block; +} + +.dt_head { + font-weight: bold; +} + +td { + width: 4em; + background: #CCC; + color: #000; + text-align: center; +} + +td.dt_zero { + color: #888; +} + + +.bar { + font-size: .8em; + line-height: 1; + text-transform: uppercase; + width: 500px; + height: 40px; + margin-left: 200px; + background: repeating-linear-gradient( + to right, + #ddd, + #ddd 1px, + #fff 1px, + #fff 5% + ); +} + +.bar:after { + content: ""; + display: block; + background-color: #48B; + width: 50px; + margin-bottom: 10px; + height: 90%; + position: relative; + top: 50%; + transform: translateY(-50%); +} + +.text { +/* font-weight: 600;*/ + display: flex; + align-items: center; + height: 40px; + width: 200px; + background-color: white; + position: absolute; + left: 0; + justify-content: flex-end; +} + +dl { + display: flex; + background-color: white; + flex-direction: column; + width: 100%; + max-width: 700px; + position: relative; + padding: 20px; + padding-top: 0; +} + +.histogram_others { + width: 700px; +} +/* +dt { + align-self: flex-start; + width: 100%; + display: block; + text-align: center; + margin-bottom: 20px; + margin-left: 130px; +} +*/ + +.bar-1:after { + width: 1%; +} + +.bar-2:after { + width: 2%; +} + +.bar-3:after { + width: 3%; +} + +.bar-4:after { + width: 4%; +} + +.bar-5:after { + width: 5%; +} + +.bar-6:after { + width: 6%; +} + +.bar-7:after { + width: 7%; +} + +.bar-8:after { + width: 8%; +} + +.bar-9:after { + width: 9%; +} + +.bar-10:after { + width: 10%; +} + +.bar-11:after { + width: 11%; +} + +.bar-12:after { + width: 12%; +} + +.bar-13:after { + width: 13%; +} + +.bar-14:after { + width: 14%; +} + +.bar-15:after { + width: 15%; +} + +.bar-16:after { + width: 16%; +} + +.bar-17:after { + width: 17%; +} + +.bar-18:after { + width: 18%; +} + +.bar-19:after { + width: 19%; +} + +.bar-20:after { + width: 20%; +} + +.bar-21:after { + width: 21%; +} + +.bar-22:after { + width: 22%; +} + +.bar-23:after { + width: 23%; +} + +.bar-24:after { + width: 24%; +} + +.bar-25:after { + width: 25%; +} + +.bar-26:after { + width: 26%; +} + +.bar-27:after { + width: 27%; +} + +.bar-28:after { + width: 28%; +} + +.bar-29:after { + width: 29%; +} + +.bar-30:after { + width: 30%; +} + +.bar-31:after { + width: 31%; +} + +.bar-32:after { + width: 32%; +} + +.bar-33:after { + width: 33%; +} + +.bar-34:after { + width: 34%; +} + +.bar-35:after { + width: 35%; +} + +.bar-36:after { + width: 36%; +} + +.bar-37:after { + width: 37%; +} + +.bar-38:after { + width: 38%; +} + +.bar-39:after { + width: 39%; +} + +.bar-40:after { + width: 40%; +} + +.bar-41:after { + width: 41%; +} + +.bar-42:after { + width: 42%; +} + +.bar-43:after { + width: 43%; +} + +.bar-44:after { + width: 44%; +} + +.bar-45:after { + width: 45%; +} + +.bar-46:after { + width: 46%; +} + +.bar-47:after { + width: 47%; +} + +.bar-48:after { + width: 48%; +} + +.bar-49:after { + width: 49%; +} + +.bar-50:after { + width: 50%; +} + +.bar-51:after { + width: 51%; +} + +.bar-52:after { + width: 52%; +} + +.bar-53:after { + width: 53%; +} + +.bar-54:after { + width: 54%; +} + +.bar-55:after { + width: 55%; +} + +.bar-56:after { + width: 56%; +} + +.bar-57:after { + width: 57%; +} + +.bar-58:after { + width: 58%; +} + +.bar-59:after { + width: 59%; +} + +.bar-60:after { + width: 60%; +} + +.bar-61:after { + width: 61%; +} + +.bar-62:after { + width: 62%; +} + +.bar-63:after { + width: 63%; +} + +.bar-64:after { + width: 64%; +} + +.bar-65:after { + width: 65%; +} + +.bar-66:after { + width: 66%; +} + +.bar-67:after { + width: 67%; +} + +.bar-68:after { + width: 68%; +} + +.bar-69:after { + width: 69%; +} + +.bar-70:after { + width: 70%; +} + +.bar-71:after { + width: 71%; +} + +.bar-72:after { + width: 72%; +} + +.bar-73:after { + width: 73%; +} + +.bar-74:after { + width: 74%; +} + +.bar-75:after { + width: 75%; +} + +.bar-76:after { + width: 76%; +} + +.bar-77:after { + width: 77%; +} + +.bar-78:after { + width: 78%; +} + +.bar-79:after { + width: 79%; +} + +.bar-80:after { + width: 80%; +} + +.bar-81:after { + width: 81%; +} + +.bar-82:after { + width: 82%; +} + +.bar-83:after { + width: 83%; +} + +.bar-84:after { + width: 84%; +} + +.bar-85:after { + width: 85%; +} + +.bar-86:after { + width: 86%; +} + +.bar-87:after { + width: 87%; +} + +.bar-88:after { + width: 88%; +} + +.bar-89:after { + width: 89%; +} + +.bar-90:after { + width: 90%; +} + +.bar-91:after { + width: 91%; +} + +.bar-92:after { + width: 92%; +} + +.bar-93:after { + width: 93%; +} + +.bar-94:after { + width: 94%; +} + +.bar-95:after { + width: 95%; +} + +.bar-96:after { + width: 96%; +} + +.bar-97:after { + width: 97%; +} + +.bar-98:after { + width: 98%; +} + +.bar-99:after { + width: 99%; +} + +.bar-100:after { + width: 100%; +} diff --git a/geostat.cpp b/geostat.cpp index 3bede2f..0b7dd01 100644 --- a/geostat.cpp +++ b/geostat.cpp @@ -11,7 +11,9 @@ #include #include -void show_histogram(Caches* cc, std::string Cache::*ptr) { +const int HIST_MAX = 20; + +void show_histogram(Caches* cc, std::string Cache::*ptr, std::string caption, bool html = 0) { std::map histogram; std::vector> pairs; for (auto el : *cc) @@ -20,8 +22,31 @@ void show_histogram(Caches* cc, std::string Cache::*ptr) { pairs.push_back(el); sort(pairs.begin(), pairs.end(), [=](std::pair& a, std::pair& b) { return a.second > b.second; }); - for (auto own : pairs) - std::cout << own.first << ": " << own.second << '\n'; + if (html) { + int max = pairs[0].second; + int i = 0; + std::cout << "

" << caption << "

\n"; + std::cout << "
\n"; + for (auto own : pairs) { + if (i < HIST_MAX) + std::cout << "
" << own.first << ": " << own.second << "
\n"; + else if (i == HIST_MAX) { + std::cout << "
\n"; + std::cout << "
Other: " << own.first; + } + if (i > HIST_MAX) + std::cout << ", " << own.first; + i++; + } + if (i < HIST_MAX) + std::cout << "\n"; + else + std::cout << "
\n"; + } else { + std::cout << caption << '\n'; + for (auto own : pairs) + std::cout << own.first << ": " << own.second << '\n'; + } } int main(int argc, char** argv) { @@ -31,6 +56,7 @@ int main(int argc, char** argv) { bool show_dt = 0; bool show_owners = 0; bool show_types = 0; + bool show_html = 0; std::string heat_file; int heat_stamp_size = 15; std::string heat_map = "Poland"; @@ -46,7 +72,7 @@ int main(int argc, char** argv) { #include "config_user.h" int o; - while ((o = getopt(argc, argv, "qng:d:pu:MDOH:s:m:eLTYh?")) != -1) + while ((o = getopt(argc, argv, "qng:d:pu:MDOH:s:m:eLTYWh?")) != -1) switch (o) { case 'd': try { @@ -87,6 +113,9 @@ int main(int argc, char** argv) { case 'Y': show_types = 1; break; + case 'W': + show_html = 1; + break; case 'H': heat_file = optarg; break; @@ -135,10 +164,19 @@ int main(int argc, char** argv) { std::cout << "\t-T\tprint D/T matrix\n"; std::cout << "\t-O\tprint owner count for found caches\n"; std::cout << "\t-Y\tprint types count for found caches\n"; + std::cout << "\t-W\toutput all data in HTML format\n"; std::cout << "\t-h\tdisplay this help screen\n"; std::exit(EXIT_FAILURE); } + if (show_html) { + show_dist = 0; + show_list = 0; + show_dt = 0; + show_owners = 0; + show_types = 0; + } + Caches cc; if (use_ocpl) { @@ -171,6 +209,18 @@ int main(int argc, char** argv) { Debug(2) << "Caches read: " << cc.size() << '\n'; + if (show_html) { + std::cout << "\n"; + std::cout << "\n"; + std::cout << " \n"; + std::cout << " \n"; + std::cout << " \n"; + std::cout << " Geocaching stats\n"; + std::cout << "\n"; + std::cout << "\n"; + std::cout << "

Geocaching stats for user " << ocpl_user << "
Powered by GeoStat

\n"; + } + if (!heat_file.empty()) { const Map* chosen_map; if (maps.count(heat_map) > 0) @@ -181,22 +231,39 @@ int main(int argc, char** argv) { } Heat hmap(&cc, chosen_map); hmap.generate(heat_file, heat_stamp_size, (heat_exp == 1 ? "exp" : "soft")); + if (show_html) + std::cout << "\"heat\n"; } - if (show_minmax) { + if (show_minmax || show_html) { auto N = std::max_element(cc.begin(), cc.end(), CacheCmpNS); auto S = std::min_element(cc.begin(), cc.end(), CacheCmpNS); auto E = std::max_element(cc.begin(), cc.end(), CacheCmpEW); auto W = std::min_element(cc.begin(), cc.end(), CacheCmpEW); - 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_minmax) { + 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(); + } else { + std::cout << "

Geographically extreme caches

\n"; + std::cout << "\n"; + std::cout << "\n"; + std::cout << " \n"; + std::cout << "\n"; + std::cout << " \n"; + std::cout << "\n"; + std::cout << " \n"; + std::cout << "\n"; + std::cout << " \n"; + std::cout << "\n"; + std::cout << "
North:link() << "\"" << N->name << " (" << N->code << ")" << N->pos.lat << "
South:link() << "\"" << S->name << " (" << S->code << ")" << S->pos.lat << "
East: link() << "\"" << E->name << " (" << E->code << ")" << E->pos.lon << "
West: link() << "\"" << W->name << " (" << W->code << ")" << W->pos.lon << "
\n"; + } } if (show_dist) { @@ -214,20 +281,14 @@ int main(int argc, char** argv) { el.show(); } - if (show_owners) { - std::cout << "Owners:\n"; - show_histogram(&cc, &Cache::owner); + if (show_owners || show_html) { + show_histogram(&cc, &Cache::owner, "Cache owners", show_html); } - if (show_types) { - std::cout << "Types:\n"; - show_histogram(&cc, &Cache::type); - - std::cout << "\nServices:\n"; - show_histogram(&cc, &Cache::origin); - - std::cout << "\nRegions:\n"; - show_histogram(&cc, &Cache::region); + if (show_types || show_html) { + show_histogram(&cc, &Cache::type, "Cache types", show_html); + if (!show_html) show_histogram(&cc, &Cache::origin, "Services", 0); + show_histogram(&cc, &Cache::region, "Regions", show_html); } if (show_dt) { @@ -248,4 +309,32 @@ int main(int argc, char** argv) { std::cout << '\n'; } } + if (show_html) { + short dt_table[11][11]; + + std::cout << "

Difficulty / terrain matrix

\n"; + std::cout << "\n"; + std::cout << ""; + for (int j = 2; j <= 10; j++) { // print table terr headers + std::cout << ""; + } + std::cout << "\n"; + + for (int i = 2; i <= 10; i++) { // i -> diff in rows + std::cout << " "; + for (int j = 2; j <= 10; j++) { // j -> terr in cols + dt_table[i][j] = std::count_if(cc.begin(), cc.end(), [i, j](Cache c) { return (c.diff == i / 2.0 && c.terr == j / 2.0); }); + if (dt_table[i][j] == 0) + std::cout << ""; + else + std::cout << ""; + } + std::cout << "\n"; + } + std::cout << "
" << j / 2.0 << "
" << i / 2.0 << "" << dt_table[i][j] << "" << dt_table[i][j] << "
\n"; + } + + if (show_html) { + std::cout << "\n\n"; + } }