1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "statistics_event.h"
16
17#include <iomanip>
18#include <iostream>
19#include <map>
20#include <sstream>
21
22namespace OHOS {
23namespace WuKong {
24namespace {
25const uint32_t DECIMAL_LENGTH = 2;
26const float PERCENTAGE = 100.0;
27}  // namespace
28
29void StatisticsEvent::StatisticsDetail(std::vector<std::map<std::string, std::string>> srcDatas,
30                                       std::map<std::string, std::shared_ptr<Table>> &destTables)
31{
32    SrcDatasPretreatment(srcDatas);
33    // loop bundle store event statistics msg
34    for (auto bundle : eventStatisticsMsg_) {
35        DEBUG_LOG_STR("start bundlename{%s}", bundle.first.c_str());
36        std::shared_ptr<EventStatisticsMsg> curEventStatisticsMsgPtr = bundle.second;
37        uint32_t curElementTypeLength = curEventStatisticsMsgPtr->eventTypes_.size();
38        std::vector<std::string> line;
39        std::shared_ptr<EventStatisticsRecord> curEventStatisticsRecordPtr = nullptr;
40        std::shared_ptr<EventStatisticsRecord> curBundleAllStatisticsPtr =
41            std::make_shared<EventStatisticsRecord>();
42        curBundleAllStatisticsPtr->eventType_ = "total";
43        for (uint32_t i = 0; i < curElementTypeLength; i++) {
44            curEventStatisticsRecordPtr = curEventStatisticsMsgPtr->eventTypeRecord_[i];
45            UpdateLine(curEventStatisticsRecordPtr, curEventStatisticsMsgPtr->eventTypeTotal_, line);
46            record_.push_back(line);
47            curBundleAllStatisticsPtr->execTimes_ += curEventStatisticsRecordPtr->execTimes_;
48        }
49
50        UpdateLine(curBundleAllStatisticsPtr, curEventStatisticsMsgPtr->eventTypeTotal_, line);
51        record_.push_back(line);
52        std::shared_ptr<Table> table = std::make_shared<Table>(headers_, record_);
53        table->SetName(bundle.first);
54        table->SetDetail("event");
55        destTables[bundle.first] = table;
56        record_.clear();
57    }
58
59    GlobalElementTypesStatistics();
60    std::shared_ptr<Table> globalTable = std::make_shared<Table>(headers_, record_);
61    globalTable->SetName("all");
62    globalTable->SetDetail("event");
63    destTables["all"] = globalTable;
64    record_.clear();
65}
66
67void StatisticsEvent::SrcDatasPretreatment(std::vector<std::map<std::string, std::string>> srcDatas)
68{
69    for (auto srcData : srcDatas) {
70        DEBUG_LOG_STR("bundlename{%s} | eventType{%s}", srcData["bundleName"].c_str(), srcData["event"].c_str());
71        std::vector<std::string>::iterator globalElementTypesIter =
72            find(globalElementTypes_.begin(), globalElementTypes_.end(), srcData["event"]);
73        if (globalElementTypesIter == globalElementTypes_.end()) {
74            DEBUG_LOG_STR("push event{%s} to globalElementTypes_", srcData["event"].c_str());
75            globalElementTypes_.push_back(srcData["event"]);
76        }
77
78        // check whether bundle is entered resolve create or reuse already exist  StatisticsMsgPtr
79        std::shared_ptr<EventStatisticsMsg> curStatisticsMsgPtr = std::make_shared<EventStatisticsMsg>();
80        std::map<std::string, std::shared_ptr<EventStatisticsMsg>>::iterator eventStatisticsMsgIter =
81            eventStatisticsMsg_.find(srcData["bundleName"]);
82        if (eventStatisticsMsgIter != eventStatisticsMsg_.end()) {
83            DEBUG_LOG_STR("use inited curStatisticsMsgPtr by bundleName{%s}", srcData["bundleName"].c_str());
84            curStatisticsMsgPtr = eventStatisticsMsg_[srcData["bundleName"]];
85        }
86        // check whether eventType is entered resolve create or reuse already exist EventStatisticsRecordPtr
87        std::shared_ptr<EventStatisticsRecord> curEventStatisticsRecordPtr =
88            std::make_shared<EventStatisticsRecord>();
89        uint32_t index = curStatisticsMsgPtr->ElementTypesIndex(srcData["event"]);
90        uint32_t curElementTypeTotal = curStatisticsMsgPtr->eventTypeTotal_;
91        if (index != curStatisticsMsgPtr->eventTypes_.size()) {
92            curEventStatisticsRecordPtr = curStatisticsMsgPtr->eventTypeRecord_[index];
93            DEBUG_LOG_STR("use inited curEventStatisticsRecordPtr in index{%d} | event{%s}", index,
94                          srcData["event"].c_str());
95        }
96        // update record msg
97        curEventStatisticsRecordPtr->eventType_ = srcData["event"];
98        curEventStatisticsRecordPtr->execTimes_++;
99
100        if (curStatisticsMsgPtr->eventTypeRecord_.size() > index) {
101            curStatisticsMsgPtr->eventTypeRecord_[index] = curEventStatisticsRecordPtr;
102            curStatisticsMsgPtr->eventTypes_[index] = srcData["event"];
103        } else {
104            curStatisticsMsgPtr->eventTypeRecord_.push_back(curEventStatisticsRecordPtr);
105            curStatisticsMsgPtr->eventTypes_.push_back(srcData["event"]);
106        }
107
108        curElementTypeTotal++;
109        DEBUG_LOG_STR("curElementTypeTotal{%d}", curElementTypeTotal);
110        curStatisticsMsgPtr->eventTypeTotal_ = curElementTypeTotal;
111        eventStatisticsMsg_[srcData["bundleName"]] = curStatisticsMsgPtr;
112        execCount_++;
113    }
114}
115void StatisticsEvent::UpdateLine(std::shared_ptr<EventStatisticsRecord> EventStatisticsRecordPtr,
116                                 uint32_t eventTypeTotal, std::vector<std::string> &line)
117{
118    std::stringstream bufferStream;
119    std::string curElementType = EventStatisticsRecordPtr->eventType_;
120    std::string curExecTimes = std::to_string(EventStatisticsRecordPtr->execTimes_);
121    std::string curProportionStr = "";
122    if (eventTypeTotal > 0) {
123        float proportion = (EventStatisticsRecordPtr->execTimes_ * PERCENTAGE) / eventTypeTotal;
124        bufferStream.str("");
125        bufferStream << std::setiosflags(std::ios::fixed) << std::setprecision(DECIMAL_LENGTH) << proportion;
126        curProportionStr = bufferStream.str() + "%";
127    }
128
129    DEBUG_LOG_STR("line content curElementType{%s} | curExecTimes{%s}", curElementType.c_str(), curExecTimes.c_str());
130    line = {curElementType, curExecTimes, curProportionStr};
131}
132
133void StatisticsEvent::GlobalElementTypesStatistics()
134{
135    std::vector<std::string> line;
136    std::shared_ptr<EventStatisticsRecord> globalAllStatisticsPtr = std::make_shared<EventStatisticsRecord>();
137    globalAllStatisticsPtr->eventType_ = "total";
138    for (auto eventType : globalElementTypes_) {
139        std::shared_ptr<EventStatisticsRecord> eventStatisticsRecordPtr = std::make_shared<EventStatisticsRecord>();
140        eventStatisticsRecordPtr->eventType_ = eventType;
141        for (auto bundle : eventStatisticsMsg_) {
142            std::shared_ptr<EventStatisticsMsg> curEventStatisticsMsgPtr = bundle.second;
143            uint32_t index = curEventStatisticsMsgPtr->ElementTypesIndex(eventType);
144            if (curEventStatisticsMsgPtr->eventTypeRecord_.size() > index) {
145                std::shared_ptr<EventStatisticsRecord> curEventStatisticsRecordPtr =
146                    curEventStatisticsMsgPtr->eventTypeRecord_[index];
147                eventStatisticsRecordPtr->execTimes_ += curEventStatisticsRecordPtr->execTimes_;
148            }
149        }
150        globalAllStatisticsPtr->execTimes_ += eventStatisticsRecordPtr->execTimes_;
151        UpdateLine(eventStatisticsRecordPtr, execCount_, line);
152        record_.push_back(line);
153    }
154    UpdateLine(globalAllStatisticsPtr, execCount_, line);
155    record_.push_back(line);
156}
157}  // namespace WuKong
158}  // namespace OHOS
159