aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/lwtrace/mon/analytics/json_output.h
blob: 1d867c3d0505d0676b76befdceb9007f5e904be0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#pragma once

#include <util/string/printf.h>
#include <util/stream/str.h>
#include <util/string/vector.h>
#include <util/generic/set.h>
#include <util/generic/hash_set.h>
#include "data.h"
#include "util.h"

namespace NAnalytics {

inline TString ToJsonFlot(const TTable& in, const TString& xno, const TVector<TString>& ynos, const TString& opts = TString())
{
    TStringStream ss;
    ss << "[ ";
    bool first = true;

    TString xn;
    THashSet<TString> xopts;
    ParseNameAndOpts(xno, xn, xopts);
    bool xstack = xopts.contains("stack"); 

    for (const TString& yno : ynos) {
        TString yn;
        THashSet<TString> yopts;
        ParseNameAndOpts(yno, yn, yopts);
        bool ystackOpt = yopts.contains("stack"); 

        ss << (first? "": ",\n  ") <<  "{ " << opts << (opts? ", ": "") << "\"label\": \"" << yn << "\", \"data\": [ ";
        bool first2 = true;
        using TPt = std::tuple<double, double, TString>;
        std::vector<TPt> pts;
        for (const TRow& row : in) {
            double x, y;
            if (row.Get(xn, x) && row.Get(yn, y)) {
                pts.emplace_back(x, y, row.Name);
            }
        }

        if (xstack) {
            std::sort(pts.begin(), pts.end(), [] (const TPt& a, const TPt& b) {
                // At first sort by Name, then by x, then by y
                return std::make_tuple(std::get<2>(a), std::get<0>(a), std::get<1>(a)) <
                       std::make_tuple(std::get<2>(b), std::get<0>(b), std::get<1>(b));
            });
        } else {
            std::sort(pts.begin(), pts.end());
        }

        double x = 0.0, xsum = 0.0;
        double y = 0.0, ysum = 0.0;
        for (auto& pt : pts) {
            if (xstack) {
                x = xsum;
                xsum += std::get<0>(pt);
            } else {
                x = std::get<0>(pt);
            }

            if (ystackOpt) {
                y = ysum;
                ysum += std::get<1>(pt);
            } else {
                y = std::get<1>(pt);
            }

            ss << (first2? "": ", ") << "["
               << Sprintf("%.6lf", Finitize(x)) << ", "     // x coordinate
               << Sprintf("%.6lf", Finitize(y)) << ", "     // y coordinate
               << "\"" << std::get<2>(pt) << "\", "       // label
               << Sprintf("%.6lf", std::get<0>(pt)) << ", " // x label (real value)
               << Sprintf("%.6lf", std::get<1>(pt))         // y label (real value)
               << "]";
            first2 = false;
        }
        // Add final point
        if (!first2 && (xstack || ystackOpt)) {
            if (xstack)
                x = xsum;
            if (ystackOpt)
                y = ysum;
            ss << (first2? "": ", ") << "["
               << Sprintf("%.6lf", Finitize(x)) << ", " // x coordinate
               << Sprintf("%.6lf", Finitize(y)) << ", " // y coordinate
               << "\"\", "
               << Sprintf("%.6lf", x) << ", "           // x label (real value)
               << Sprintf("%.6lf", y)                   // y label (real value)
               << "]";
        }
        ss << " ] }";
        first = false;
    }
    ss << "\n]";
    return ss.Str();
}

}