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
16import { BaseElement, element } from '../../../base-ui/BaseElement';
17import { LitChartPie } from '../../../base-ui/chart/pie/LitChartPie';
18import { procedurePool } from '../../database/Procedure';
19import { SpSchedulingAnalysis } from './SpSchedulingAnalysis';
20import { TabCpuDetailsThreads } from './TabCpuDetailsThreads';
21import './TabCpuDetailsThreads';
22import { info } from '../../../log/Log';
23import { LitTable } from '../../../base-ui/table/lit-table';
24import { getDataNo } from './utils/Utils';
25import '../../../base-ui/progress-bar/LitProgressBar';
26import { LitProgressBar } from '../../../base-ui/progress-bar/LitProgressBar';
27import './TableNoData';
28import { TableNoData } from './TableNoData';
29import { TabCpuDetailsFrequencyHtml } from './TabCpuDetailsFrequency.html';
30
31@element('tab-cpu-details-frequency')
32export class TabCpuDetailsFrequency extends BaseElement {
33  private tableNoData: TableNoData | null | undefined;
34  private cpuDetailsFrequencyProgress: LitProgressBar | null | undefined;
35  traceChange: boolean = false;
36  private cpuDetailsFrequencyPie: LitChartPie | null | undefined;
37  private cpuDetailsFrequencyUsageTbl: LitTable | null | undefined;
38  private tabCpuDetailsThreads: TabCpuDetailsThreads | null | undefined;
39  private cpu: number = 0;
40  private cpuDetailsFrequencyData: Array<unknown> = [];
41  private cpuDetailsFrequencySortColumn: string = '';
42  private sortType: number = 0;
43
44  initElements(): void {
45    this.tableNoData = this.shadowRoot!.querySelector<TableNoData>('#table-no-data');
46    this.cpuDetailsFrequencyProgress = this.shadowRoot!.querySelector<LitProgressBar>('#loading');
47    this.cpuDetailsFrequencyPie = this.shadowRoot!.querySelector<LitChartPie>('#chart-pie');
48    this.cpuDetailsFrequencyUsageTbl = this.shadowRoot!.querySelector<LitTable>('#fre-tb-cpu-usage');
49    this.tabCpuDetailsThreads = this.shadowRoot!.querySelector<TabCpuDetailsThreads>('#tab-cpu-details-threads');
50
51    this.cpuDetailsFrequencyUsageTbl!.addEventListener('row-click', (evt: unknown): void => {
52      //@ts-ignore
53      let data = evt.detail.data;
54      data.isSelected = true;
55      // @ts-ignore
56      if ((evt.detail as unknown).callBack) {
57        // @ts-ignore
58        (evt.detail as unknown).callBack(true);
59      }
60    });
61
62    this.cpuDetailsFrequencyUsageTbl!.addEventListener('column-click', (evt: unknown): void => {
63      //@ts-ignore
64      this.cpuDetailsFrequencySortColumn = evt.detail.key; //@ts-ignore
65      this.sortType = evt.detail.sort;
66      // @ts-ignore
67      this.sortByColumn(evt.detail);
68    });
69    this.cpuDetailsFrequencyUsageTbl!.addEventListener('row-hover', (evt: unknown): void => {
70      //@ts-ignore
71      if (evt.detail.data) {
72        //@ts-ignore
73        let data = evt.detail.data;
74        data.isHover = true; //@ts-ignore
75        if ((evt.detail as unknown).callBack) {
76          //@ts-ignore
77          (evt.detail as unknown).callBack(true);
78        }
79      }
80      this.cpuDetailsFrequencyPie?.showHover();
81    });
82  }
83
84  init(cpu: number): void {
85    this.cpu = cpu;
86    this.queryPieChartDataByType('CPU Frequency', cpu);
87  }
88
89  queryPieChartDataByType(type: string, cpu: number): void {
90    if (this.traceChange) {
91      return;
92    }
93    this.cpuDetailsFrequencyProgress!.loading = true;
94    this.queryLoginWorker(`scheduling-${type}`, 'query Cpu Frequency Analysis Time:', (res) => {
95      this.traceChange = true;
96      this.cpuDetailsFrequencyProgress!.loading = false; //@ts-ignore
97      this.cpuDetailsFrequencyData = res.get(cpu) || [];
98      this.cpuDetailsFrequencyData = getDataNo(this.cpuDetailsFrequencyData);
99      this.tableNoData!.noData = this.cpuDetailsFrequencyData.length === 0;
100      this.noData(this.cpuDetailsFrequencyData.length === 0);
101      this.setFrequencyPieConfig(cpu);
102      if (this.cpuDetailsFrequencySortColumn !== '') {
103        this.sortByColumn({
104          key: this.cpuDetailsFrequencySortColumn,
105          sort: this.sortType,
106        });
107      } else {
108        this.cpuDetailsFrequencyUsageTbl!.recycleDataSource = this.cpuDetailsFrequencyData;
109      }
110      this.cpuDetailsFrequencyUsageTbl?.reMeauseHeight();
111    });
112  }
113
114  private setFrequencyPieConfig(cpu: number): void {
115    this.cpuDetailsFrequencyPie!.config = {
116      appendPadding: 0,
117      data: this.cpuDetailsFrequencyData,
118      angleField: 'sum',
119      colorField: 'value',
120      radius: 1,
121      label: {
122        type: 'outer',
123      },
124      tip: (freObj): string => {
125        return `<div>
126                                <div>frequency:${
127                                  // @ts-ignore
128                                  freObj.obj.value
129                                }</div> 
130                                <div>min:${
131                                  // @ts-ignore
132                                  freObj.obj.min
133                                }</div>
134                                <div>max:${
135                                  // @ts-ignore
136                                  freObj.obj.max
137                                }</div>
138                                <div>average:${
139                                  // @ts-ignore
140                                  freObj.obj.avg
141                                }</div>
142                                <div>duration:${
143                                  // @ts-ignore
144                                  freObj.obj.sumTimeStr
145                                }</div>
146                                <div>ratio:${
147                                  // @ts-ignore
148                                  freObj.obj.ratio
149                                }%</div>
150                            </div>
151                                `;
152      },
153      hoverHandler: (cpuDetailsFreqData): void => {
154        if (cpuDetailsFreqData) {
155          this.cpuDetailsFrequencyUsageTbl!.setCurrentHover(cpuDetailsFreqData);
156        } else {
157          this.cpuDetailsFrequencyUsageTbl!.mouseOut();
158        }
159      },
160      angleClick: (it): void => {
161        this.tabCpuDetailsThreads!.setShow = true;
162        this.shadowRoot!.querySelector<HTMLDivElement>('.d-box')!.style.display = 'none';
163        this.tabCpuDetailsThreads!.init(cpu, it);
164      },
165      interactions: [
166        {
167          type: 'element-active',
168        },
169      ],
170    };
171  }
172
173  noData(value: boolean): void {
174    this.shadowRoot!.querySelector<HTMLDivElement>('.fre-chart-box')!.style.display = value ? 'none' : 'block';
175    this.shadowRoot!.querySelector<HTMLDivElement>('.table-box')!.style.width = value ? '100%' : '60%';
176  }
177
178  clearData(): void {
179    this.traceChange = false;
180    this.cpuDetailsFrequencyPie!.dataSource = [];
181    this.cpuDetailsFrequencyUsageTbl!.recycleDataSource = [];
182    this.shadowRoot!.querySelector<HTMLDivElement>('.d-box')!.style.display = 'flex';
183    this.tabCpuDetailsThreads!.setShow = false;
184    this.noData(false);
185  }
186
187  set setShow(v: boolean) {
188    if (v) {
189      this.shadowRoot!.querySelector<HTMLDivElement>('.d-box')!.style.display = 'flex';
190    } else {
191      this.shadowRoot!.querySelector<HTMLDivElement>('.d-box')!.style.display = 'none';
192    }
193  }
194
195  queryLoginWorker(cpuFrequencyType: string, log: string, handler: (res: unknown) => void): void {
196    let cpuDetailsFrequencyTime = new Date().getTime();
197    procedurePool.submitWithName(
198      'logic0',
199      cpuFrequencyType,
200      {
201        endTs: SpSchedulingAnalysis.endTs,
202        total: SpSchedulingAnalysis.totalDur,
203      },
204      undefined,
205      handler
206    );
207    let durTime = new Date().getTime() - cpuDetailsFrequencyTime;
208    info(log, durTime);
209  }
210
211  sortByColumn(detail: unknown): void {
212    // @ts-ignore
213    function compare(cpuDetailsFrequencyProperty, sort, type) {
214      return function (a: unknown, b: unknown) {
215        if (type === 'number') {
216          return sort === 2
217            ? // @ts-ignore
218              parseFloat(b[cpuDetailsFrequencyProperty]) - parseFloat(a[cpuDetailsFrequencyProperty])
219            : //@ts-ignore
220              parseFloat(a[cpuDetailsFrequencyProperty]) - parseFloat(b[cpuDetailsFrequencyProperty]);
221        } else {
222          if (sort === 2) {
223            //@ts-ignore
224            return b[cpuDetailsFrequencyProperty].toString().localeCompare(a[cpuDetailsFrequencyProperty].toString());
225          } else {
226            //@ts-ignore
227            return a[cpuDetailsFrequencyProperty].toString().localeCompare(b[cpuDetailsFrequencyProperty].toString());
228          }
229        }
230      };
231    }
232
233    //@ts-ignore
234    if (detail.key === 'min') {
235      //@ts-ignore
236      detail.key = 'minValue'; //@ts-ignore
237      this.cpuDetailsFrequencyData.sort(compare(detail.key, detail.sort, 'number')); //@ts-ignore
238    } else if (detail.key === 'max') {
239      //@ts-ignore
240      detail.key = 'maxValue'; //@ts-ignore
241      this.cpuDetailsFrequencyData.sort(compare(detail.key, detail.sort, 'number')); //@ts-ignore
242    } else if (detail.key === 'avg') {
243      //@ts-ignore
244      detail.key = 'avgValue'; //@ts-ignore
245      this.cpuDetailsFrequencyData.sort(compare(detail.key, detail.sort, 'number')); //@ts-ignore
246    } else if (detail.key === 'sumTimeStr') {
247      //@ts-ignore
248      detail.key = 'sum'; //@ts-ignore
249      this.cpuDetailsFrequencyData.sort(compare(detail.key, detail.sort, 'number')); //@ts-ignore
250    } else if (detail.key === 'value' || detail.key === 'ratio' || detail.key === 'index') {
251      //@ts-ignore
252      this.cpuDetailsFrequencyData.sort(compare(detail.key, detail.sort, 'number'));
253    } else {
254      //@ts-ignore
255      this.cpuDetailsFrequencyData.sort(compare(detail.key, detail.sort, 'string'));
256    }
257    this.cpuDetailsFrequencyUsageTbl!.recycleDataSource = this.cpuDetailsFrequencyData;
258  }
259
260  initHtml(): string {
261    return TabCpuDetailsFrequencyHtml;
262  }
263}
264