kopia lustrzana https://gitlab.com/tomaszg/geostat
Support for HTML output together with a sample CSS style
rodzic
46a7321434
commit
91fc2ff7e4
|
@ -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)));
|
||||
}
|
||||
|
|
1
cache.h
1
cache.h
|
@ -54,6 +54,7 @@ public:
|
|||
static Position home;
|
||||
|
||||
void show() const;
|
||||
std::string link() const;
|
||||
float distance() const;
|
||||
};
|
||||
|
||||
|
|
|
@ -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%;
|
||||
}
|
119
geostat.cpp
119
geostat.cpp
|
@ -11,7 +11,9 @@
|
|||
#include <unistd.h>
|
||||
#include <map>
|
||||
|
||||
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<std::string, int> histogram;
|
||||
std::vector<std::pair<std::string, int>> 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<std::string, int>& a, std::pair<std::string, int>& b) { return a.second > b.second; });
|
||||
|
||||
if (html) {
|
||||
int max = pairs[0].second;
|
||||
int i = 0;
|
||||
std::cout << "<h2>" << caption << "</h2>\n";
|
||||
std::cout << "<dl class=\"histogram\">\n";
|
||||
for (auto own : pairs) {
|
||||
if (i < HIST_MAX)
|
||||
std::cout << "<dd class=\"bar bar-" << 100 * own.second / max << "\"><span class=\"text\">" << own.first << ": " << own.second << "</span></dd>\n";
|
||||
else if (i == HIST_MAX) {
|
||||
std::cout << "</dl>\n";
|
||||
std::cout << "<div class=\"histogram_others\">Other: " << own.first;
|
||||
}
|
||||
if (i > HIST_MAX)
|
||||
std::cout << ", " << own.first;
|
||||
i++;
|
||||
}
|
||||
if (i < HIST_MAX)
|
||||
std::cout << "</dl>\n";
|
||||
else
|
||||
std::cout << "</div>\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 << "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n";
|
||||
std::cout << "<html>\n";
|
||||
std::cout << " <head>\n";
|
||||
std::cout << " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=\"utf-8\">\n";
|
||||
std::cout << " <link rel=\"stylesheet\" type=\"text/css\" href=\"geo.css\">\n";
|
||||
std::cout << " <title>Geocaching stats</title>\n";
|
||||
std::cout << "</head>\n";
|
||||
std::cout << "<body>\n";
|
||||
std::cout << "<h1>Geocaching stats for user " << ocpl_user << "<br>Powered by <a href=\"https://gitlab.com/tomaszg/geostat\">GeoStat</a></h1>\n";
|
||||
}
|
||||
|
||||
if (!heat_file.empty()) {
|
||||
const Map* chosen_map;
|
||||
if (maps.count(heat_map) > 0)
|
||||
|
@ -181,14 +231,17 @@ 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 << "<img class=\"heatmap\" src=\"" << heat_file << "\" alt=\"heat map\">\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);
|
||||
|
||||
if (show_minmax) {
|
||||
std::cout << "Most N:\n";
|
||||
N->show();
|
||||
std::cout << "Most S:\n";
|
||||
|
@ -197,6 +250,20 @@ int main(int argc, char** argv) {
|
|||
E->show();
|
||||
std::cout << "Most W:\n";
|
||||
W->show();
|
||||
} else {
|
||||
std::cout << "<h2>Geographically extreme caches</h2>\n";
|
||||
std::cout << "<table class=\"minmax\">\n";
|
||||
std::cout << "<tr>\n";
|
||||
std::cout << " <td>North:</td><td><a href=\"" << N->link() << "\"</a>" << N->name << " (" << N->code << ")</a></td><td>" << N->pos.lat << "</td>\n";
|
||||
std::cout << "</tr><tr>\n";
|
||||
std::cout << " <td>South:</td><td><a href=\"" << S->link() << "\"</a>" << S->name << " (" << S->code << ")</a></td><td>" << S->pos.lat << "</td>\n";
|
||||
std::cout << "</tr><tr>\n";
|
||||
std::cout << " <td>East:</td> <td><a href=\"" << E->link() << "\"</a>" << E->name << " (" << E->code << ")</a></td><td>" << E->pos.lon << "</td>\n";
|
||||
std::cout << "</tr><tr>\n";
|
||||
std::cout << " <td>West:</td> <td><a href=\"" << W->link() << "\"</a>" << W->name << " (" << W->code << ")</a></td><td>" << W->pos.lon << "</td>\n";
|
||||
std::cout << "</tr>\n";
|
||||
std::cout << "</table>\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 << "<h2>Difficulty / terrain matrix</h2>\n";
|
||||
std::cout << "<table class=\"dt\">\n";
|
||||
std::cout << "<tr class=\"dt_head\"><td></td>";
|
||||
for (int j = 2; j <= 10; j++) { // print table terr headers
|
||||
std::cout << "<td>" << j / 2.0 << "</td>";
|
||||
}
|
||||
std::cout << "</tr>\n";
|
||||
|
||||
for (int i = 2; i <= 10; i++) { // i -> diff in rows
|
||||
std::cout << "<tr><td class=\"dt_head\">" << i / 2.0 << "</td> ";
|
||||
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 << "<td class=\"dt_zero\">" << dt_table[i][j] << "</td>";
|
||||
else
|
||||
std::cout << "<td>" << dt_table[i][j] << "</td>";
|
||||
}
|
||||
std::cout << "</tr>\n";
|
||||
}
|
||||
std::cout << "</table>\n";
|
||||
}
|
||||
|
||||
if (show_html) {
|
||||
std::cout << "</body>\n</html>\n";
|
||||
}
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue