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 { LitTable } from '../../../../../base-ui/table/lit-table'; 18import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection'; 19import { XpowerThreadInfoStruct } from '../../../../database/ui-worker/ProcedureWorkerXpowerThreadInfo'; 20import { SortDetail, resizeObserver } from '../SheetUtils'; 21 22@element('tabpane-xpower-thread-energy') 23export class TabPaneXpowerThreadEnergy extends BaseElement { 24 private XpowerThreadEnergyTbl: LitTable | null | undefined; 25 private XpowerThreadEnergyRange: HTMLLabelElement | null | undefined; 26 private XpowerThreadEnergySource: Array<SelectionData> = []; 27 private sumCount: number = 0; 28 private tabTitle: HTMLDivElement | undefined | null; 29 30 set data(XpowerThreadEnergyValue: SelectionParam) { 31 this.init(); 32 this.XpowerThreadEnergyTbl!.shadowRoot!.querySelector<HTMLDivElement>('.table')!.style!.height = `${ 33 this.parentElement!.clientHeight - 45 34 }px`; 35 this.XpowerThreadEnergyRange!.textContent = `Selected range: ${parseFloat( 36 ((XpowerThreadEnergyValue.rightNs - XpowerThreadEnergyValue.leftNs) / 1000000.0).toFixed(5) 37 )} ms`; 38 this.getThreadEnergyData(XpowerThreadEnergyValue).then(); 39 } 40 41 async getThreadEnergyData(XpowerThreadEnergyValue: SelectionParam): Promise<void> { 42 this.sumCount = 0; 43 let dataSource: SelectionData[] = []; 44 let collect = XpowerThreadEnergyValue.xpowerThreadEnergyMapData; 45 this.XpowerThreadEnergyTbl!.loading = true; 46 for (let key of collect.keys()) { 47 let threadEnergys = collect.get(key); 48 let res = (await threadEnergys?.({ 49 startNS: XpowerThreadEnergyValue.leftNs, 50 endNS: XpowerThreadEnergyValue.rightNs, 51 queryAll: true, 52 })) as XpowerThreadInfoStruct[]; 53 let sd = this.createSelectThreadEnergyData(res || []); 54 dataSource = dataSource.concat(sd); 55 } 56 this.XpowerThreadEnergyTbl!.loading = false; 57 this.XpowerThreadEnergySource = dataSource; 58 this.XpowerThreadEnergyTbl!.recycleDataSource = dataSource; 59 } 60 61 private init(): void { 62 const thTable = this.tabTitle!.querySelector('.th'); 63 const list = thTable!.querySelectorAll('div'); 64 if (this.tabTitle!.hasAttribute('sort')) { 65 this.tabTitle!.removeAttribute('sort'); 66 list.forEach((item) => { 67 item.querySelectorAll('svg').forEach((svg) => { 68 svg.style.display = 'none'; 69 }); 70 }); 71 } 72 } 73 74 initElements(): void { 75 this.XpowerThreadEnergyTbl = this.shadowRoot?.querySelector<LitTable>('#tb-threadEnergy'); 76 this.tabTitle = this.XpowerThreadEnergyTbl!.shadowRoot?.querySelector('.thead') as HTMLDivElement; 77 this.XpowerThreadEnergyRange = this.shadowRoot?.querySelector('#time-range'); 78 this.XpowerThreadEnergyTbl!.addEventListener('column-click', (evt): void => { 79 // @ts-ignore 80 this.sortByColumn(evt.detail); 81 }); 82 } 83 84 connectedCallback(): void { 85 super.connectedCallback(); 86 resizeObserver(this.parentElement!, this.XpowerThreadEnergyTbl!); 87 } 88 89 initHtml(): string { 90 return ` 91 <style> 92 .xpower-thread-energy-label{ 93 margin-bottom: 5px; 94 } 95 :host{ 96 padding: 10px 10px; 97 display: flex; 98 flex-direction: column; 99 } 100 </style> 101 <label id="time-range" class="xpower-thread-energy-label" style="width: 100%;height: 20px;text-align: end;font-size: 10pt;">Selected range:0.0 ms</label> 102 <lit-table id="tb-threadEnergy" style="height: auto"> 103 <lit-table-column order title="ThreadName" data-index="name" key="name" align="flex-start" width="25%"> 104 </lit-table-column> 105 <lit-table-column data-index="count" title="Count" order key="count" align="flex-start" width="1fr"> 106 </lit-table-column> 107 <lit-table-column title="Avg Energy(mAh)" data-index="avgNumber" order key="avgNumber" align="flex-start" width="1fr"> 108 </lit-table-column> 109 <lit-table-column title="Max Energy(mAh)" align="flex-start" order data-index="maxNumber" key="maxNumber" width="1fr"> 110 </lit-table-column> 111 <lit-table-column title="Min Energy(mAh)" key="minNumber" data-index="minNumber" order align="flex-start" width="1fr"> 112 </lit-table-column> 113 </lit-table> 114 `; 115 } 116 117 private createSelectThreadEnergyData(list: Array<XpowerThreadInfoStruct>): SelectionData[] { 118 let SelectThreadEnergyArray: SelectionData[] = []; 119 if (list.length > 0) { 120 let threadEnergyMap = new Map(); 121 list.forEach((item) => { 122 if (item.value > 0) { 123 if (threadEnergyMap.has(item.threadName)) { 124 const data = threadEnergyMap.get(item.threadName)!; 125 data.push(item); 126 } else { 127 const data: XpowerThreadInfoStruct[] = []; 128 data.push(item); 129 threadEnergyMap.set(item.threadName, data); 130 } 131 } 132 }); 133 for (let itemArray of threadEnergyMap.values()) { 134 let SelectThreadEnergyData = new SelectionData(); 135 let max = 0; 136 let min = 0; 137 let sum = 0; 138 SelectThreadEnergyData.name = itemArray[0].threadName; 139 SelectThreadEnergyData.count = itemArray.length; 140 if (itemArray.length > 1) { 141 max = itemArray.map((item: { value: unknown }) => item.value).reduce((a: number, b: number) => Math.max(a, b)); 142 min = itemArray.map((item: { value: unknown }) => item.value).reduce((a: number, b: number) => Math.min(a, b)); 143 // @ts-ignore 144 sum = itemArray.reduce((acc: unknown, obj: { value: unknown }) => acc + obj.value, 0); 145 SelectThreadEnergyData.avgNumber = parseFloat((sum / itemArray.length).toFixed(2)); 146 SelectThreadEnergyData.maxNumber = max; 147 SelectThreadEnergyData.minNumber = min; 148 } else if (itemArray.length === 1) { 149 let value = itemArray[0].value; 150 SelectThreadEnergyData.avgNumber = value; 151 SelectThreadEnergyData.maxNumber = value; 152 SelectThreadEnergyData.minNumber = value; 153 } 154 this.sumCount += itemArray.length; 155 SelectThreadEnergyArray.push(SelectThreadEnergyData); 156 } 157 } 158 return SelectThreadEnergyArray; 159 } 160 161 private sortByColumn(detail: SortDetail): void { 162 function compare(property: string, sort: number, type: string) { 163 return function (xpowerThreadEnergyLeftData: SelectionData, xpowerThreadEnergyRightData: SelectionData): number { 164 if (xpowerThreadEnergyLeftData.process === ' ' || xpowerThreadEnergyRightData.process === ' ') { 165 return 0; 166 } 167 if (type === 'number') { 168 return sort === 2 // @ts-ignore 169 ? parseFloat(xpowerThreadEnergyRightData[property]) - parseFloat(xpowerThreadEnergyLeftData[property]) // @ts-ignore 170 : parseFloat(xpowerThreadEnergyLeftData[property]) - parseFloat(xpowerThreadEnergyRightData[property]); 171 } else { 172 // @ts-ignore 173 if (xpowerThreadEnergyRightData[property] > xpowerThreadEnergyLeftData[property]) { 174 return sort === 2 ? 1 : -1; 175 } else { 176 // @ts-ignore 177 if (xpowerThreadEnergyRightData[property] === xpowerThreadEnergyLeftData[property]) { 178 return 0; 179 } else { 180 return sort === 2 ? -1 : 1; 181 } 182 } 183 } 184 }; 185 } 186 if (detail.key === 'name') { 187 this.XpowerThreadEnergySource.sort(compare(detail.key, detail.sort, 'string')); 188 } else { 189 this.XpowerThreadEnergySource.sort(compare(detail.key, detail.sort, 'number')); 190 } 191 this.XpowerThreadEnergyTbl!.recycleDataSource = this.XpowerThreadEnergySource; 192 } 193} 194