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 { getThreadPoolTraceBufferCacheKey } from './database/SqlLite';
17
18export enum TraceMode {
19  NORMAL,
20  LONG_TRACE,
21  DISTRIBUTED,
22}
23
24export const applicationHtml: string = `
25        <style>
26        :host{
27
28        }
29        .dark{
30        --dark-background: #272C34;
31        --dark-background1: #424851;
32        --dark-background2: #262f3c;
33        --dark-background3: #292D33;
34        --dark-background4: #323841;
35        --dark-background5: #333840;
36        --dark-background6: rgba(82,145,255,0.2);
37        --dark-background7: #494d52;
38        --dark-background8: #5291FF;
39        --dark-color: rgba(255,255,255,0.6);
40        --dark-color1: rgba(255,255,255,0.86);
41        --dark-color2: rgba(255,255,255,0.9);
42        --dark-border: #474F59;
43        --dark-color3:#4694C2;
44        --dark-color4:#5AADA0;
45        --dark-border1: #454E5A;
46        --bark-expansion:#0076FF;
47        --bark-prompt:#9e9e9e;
48        --dark-icon:#adafb3;
49        --dark-img: url('img/dark_pic.png');
50            background: #272C34;
51            color: #FFFFFF;
52        }
53        .root{
54            display: grid;
55            grid-template-rows: min-content 1fr;
56            grid-template-columns: min-content 1fr;
57            grid-template-areas: 'm s'
58                                 'm b';
59            height: 100vh;
60            width: 100vw;
61        }
62        .filedrag::after {
63             content: 'Drop the trace file to open it';
64             position: fixed;
65             z-index: 2001;
66             top: 0;
67             left: 0;
68             right: 0;
69             bottom: 0;
70             border: 5px dashed var(--dark-color1,#404854);
71             text-align: center;
72             font-size: 3rem;
73             line-height: 100vh;
74             background: rgba(255, 255, 255, 0.5);
75        }
76        .menu{
77            grid-area: m;
78            /*transition: all 0.2s;*/
79            box-shadow: 4px 0px 20px rgba(0,0,0,0.05);
80            z-index: 2000;
81        }
82        .search-vessel{
83            z-index: 999;
84            position: relative;
85            cursor: default;
86        }
87        .progress{
88            bottom: 0;
89            position: absolute;
90            height: 1px;
91            left: 0;
92            right: 0;
93        }
94
95        :host(:not([search])) .search-vessel  {
96           display: none;
97        }
98        :host(:not([search])) .search-vessel .search  {
99            background-color: var(--dark-background5,#F6F6F6);
100        }
101        .search{
102            grid-area: s;
103            background-color: var(--dark-background,#FFFFFF);
104            height: 48px;
105            display: flex;
106            justify-content: center;
107            align-items: center;
108
109        }
110        .search .search-bg{
111            background-color: var(--dark-background5,#fff);
112            border-radius: 40px;
113            padding: 3px 20px;
114            display: flex;
115            justify-content: center;
116            align-items: center;
117            border: 1px solid var(--dark-border,#c5c5c5);
118        }
119        lit-search input{
120            outline: none;
121            border: 0px;
122            background-color: transparent;
123            font-size: inherit;
124            color: var(--dark-color,#666666);
125            width: 30vw;
126            height: auto;
127            vertical-align:middle;
128            line-height:inherit;
129            height:inherit;
130            padding: 6px 6px 6px 6px};
131            max-height: inherit;
132            box-sizing: border-box;
133
134        }
135        ::placeholder { /* CSS 3 標準 */
136          color: #b5b7ba;
137          font-size: 1em;
138        }
139        lit-search input::placeholder {
140          color: #b5b7ba;
141          font-size: 1em;
142        }
143        .content{
144            grid-area: b;
145            background-color: #ffffff;
146            height: 100%;
147            overflow: auto;
148            position:relative;
149        }
150        .sheet{
151
152        }
153        .sidebar-button{
154            position: absolute;
155            top: 0;
156            left: 0;
157            background-color: var(--dark-background1,#FFFFFF);
158            height: 100%;
159            border-radius: 0 5px 5px 0;
160            width: 48px;
161            display: flex;
162            align-content: center;
163            justify-content: center;
164            cursor: pointer;
165        }
166        :host{
167            font-size: inherit;
168            display: inline-block;
169            transition: .3s;
170         }
171         :host([spin]){
172            animation: rotate 1.75s linear infinite;
173         }
174         @keyframes rotate {
175            to{
176                transform: rotate(360deg);
177            }
178         }
179         .icon{
180            display: block;
181            width: 1em;
182            height: 1em;
183            margin: auto;
184            fill: currentColor;
185            overflow: hidden;
186            font-size: 20px;
187            color: #1E4EEA;
188         }
189        :host([chart_filter]) .chart-filter {
190            display: grid;
191            grid-template-rows: min-content min-content min-content max-content auto;
192            overflow-y: clip;
193            height: 99%;
194            visibility: visible;
195            position: absolute;
196            width: 40%;
197            right: 0;
198            z-index: 1001;
199            top: 0;
200        }
201        :host([custom-color]) .custom-color {
202            display: grid;
203            grid-template-rows: min-content min-content min-content max-content auto;
204            overflow-y: auto;
205            height: 100%;
206            visibility: visible;
207            position: absolute;
208            width: 50%;
209            right: 0;
210            z-index: 1002;
211            top: 0;
212        }
213        .filter-config {
214            opacity: 1;
215            visibility: hidden;
216        }
217        .filter-config:hover {
218            opacity: 0.7;
219        }
220        .page-button[prohibit] {
221          cursor: none;
222        }
223        .page-button {
224            background: #D8D8D8;
225            border-radius: 12px;
226            width: 24px;
227            height: 24px;
228            margin-right: 12px;
229            display: flex;
230            justify-content: center;
231            align-items: center;
232        }
233        #preview-button:hover {
234          cursor: pointer;
235          background: #0A59F7;
236          color: #FFFFFF;
237          opacity: 1;
238        }
239        #next-button:hover {
240          cursor: pointer;
241          background: #0A59F7;
242          color: #FFFFFF;
243          opacity: 1;
244        }
245        .pagination:hover {
246          cursor: pointer;
247          background: #0A59F7;
248          color: #FFFFFF;
249          opacity: 1;
250        }
251        .confirm-button:hover {
252          cursor: pointer;
253          background: #0A59F7;
254          color: #FFFFFF;
255          opacity: 1;
256        }
257        .pagination {
258            background: #D8D8D8;
259            color: #000000;
260            border-radius: 12px;
261            width: 24px;
262            height: 24px;
263            margin-right: 12px;
264            display: flex;
265            justify-content: center;
266            align-items: center;
267            font-family: Helvetica;
268            font-size: 12px;
269            text-align: center;
270            line-height: 20px;
271            font-weight: 400;
272            opacity: 0.6;
273        }
274        .pagination[selected] {
275            background: #0A59F7;
276            color: #FFFFFF;
277            opacity: 1;
278        }
279        .page-jump-font {
280            opacity: 0.6;
281            font-family: Helvetica;
282            font-size: 12px;
283            color: #000000;
284            text-align: center;
285            line-height: 20px;
286            font-weight: 400;
287        }
288        .page-input {
289            background: #D8D8D8;
290            border-radius: 10px;
291            width: 40px;
292            height: 24px;
293            justify-content: center;
294            align-items: center;
295            text-align: center;
296            margin-right: 8px;
297            border: none;
298        }
299        .confirm-button {
300            font-family: Helvetica;
301            font-size: 12px;
302            color: #0A59F7;
303            text-align: center;
304            font-weight: 400;
305            border: 1px solid #0A59F7;
306            border-radius: 10px;
307            width: 64px;
308            height: 24px;
309            line-height: 24px;
310        }
311        .long_trace_page {
312            justify-content: center;
313            width: -webkit-fill-available;
314            margin-right: 5.2em;
315            align-items: center;
316            display: none;
317        }
318        .content-center-option {
319          justify-content: center;
320          width: -webkit-fill-available;
321          margin-right: 5.2em;
322          align-items: center;
323          width: auto;
324        }
325        .page-number-list {
326            display: flex;
327        }
328
329        #sp-ai-analysis {
330            top:0px;
331            right:0px;
332            position:absolute;
333            z-index:9999;
334            min-width:430px;
335            max-width:75%;
336            width:430px;
337            height:740px;
338            box-shadow:3px 0px 14px #000;
339            border-radius:8px;
340            background-color:#fff;
341            padding:10px 10px 10px 5px;
342            user-select:none;
343            box-sizing:border-box;
344            visibility:hidden;
345        }
346        </style>
347        <div class="root" style="position: relative;">
348            <sp-bubble-ai style="visibility: visible; top:50%;right:2px;position: absolute;z-index: 1000" id="sp-bubbles"></sp-bubble-ai>
349            <sp-advertisement style="bottom:2px;right:2px;position: absolute;z-index: 10086" id= "sp-advertisement"></sp-advertisement>
350            <lit-main-menu id="main-menu" class="menu" data=''></lit-main-menu>
351            <sp-keyboard style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0px;left:0px;right:0;bottom:0px;position:absolute;z-index: 8888" id="sp-keyboard">
352            </sp-keyboard>
353            <div class="search-vessel">
354                <div class="search" style="position: relative;">
355                    <div class="sidebar-button" style="width: 0">
356                        <svg class="icon" id="icon" aria-hidden="true" viewBox="0 0 1024 1024">
357                             <use id="use" xlink:href="./base-ui/icon.svg#icon-menu"></use>
358                        </svg>
359                    </div>
360                    <div class = "content-left-option" style="text-align: left;
361                      position: absolute;left: 5px ; cursor: pointer;top: 15px">
362                      <div title="Import Key Path" id="import-key-path" style="display: none ;text-align: left;cursor: pointer;">
363                        <input id="import-config" style="display: none;pointer-events: none" type="file" accept=".json" >
364                        <label style="width: 20px;height: 20px;cursor: pointer;" for="import-config">
365                            <lit-icon id="import-btn" name="copy-csv" style="pointer-events: none" size="20">
366                            </lit-icon>
367                        </label>
368                      </div>
369                      <lit-icon  id="close-key-path" name="close" title="Close Key Path" color='#fff' size="20" style="display: none;text-align: left;cursor: pointer;">
370                      </lit-icon>
371                    </div>
372                    <lit-search id="lit-search"></lit-search>
373                    <lit-search id="lit-record-search"></lit-search>
374                    <div class="content-center-option" style="display: ">
375                      <div class="long_trace_page" style="display: none;">
376                        <div class="page-button" id="preview-button">
377                          <img title="preview" src="img/preview.png"/>
378                        </div>
379                        <div class="page-number-list"></div>
380                        <div class="page-button" id="next-button" style="margin-right: 8px;">
381                           <img title="next" src="img/next.png"/>
382                        </div>
383                        <div class="page-jump-font" style="margin-right: 8px;">To</div>
384                        <input class="page-input" />
385                        <div class="confirm-button">Confirm</div>
386                      </div>
387                    </div>
388                </div>
389                <div class = "content-right-option" style="display: flex;flex-flow: nowrap;text-align: right;position: absolute;right: 1.2em;cursor: pointer;top: 17px"">
390                  <img class="ai_analysis" title="Display Template" src="img/ai-analysis.png" style="margin-left: 0.8em;width:16px;height:16px">
391                  <lit-icon class="export-record" title="Download Mark Trace" name="download" size="16" style="margin-left: 0.8em;"></lit-icon>
392                  <img class="cut-trace-file" title="Cut Trace File" src="img/menu-cut.svg" style="margin-left: 0.8em;">
393                  <img class="filter-config" title="Display Template" src="img/config_filter.png" style="margin-left: 0.8em;">
394                </div>
395                <lit-progress-bar class="progress"></lit-progress-bar>
396            </div>
397            <div id="app-content" class="content">
398                <sp-welcome style="visibility:visible;top:0px;left:0px;position:absolute;z-index: 100" id="sp-welcome">
399                </sp-welcome>
400                <sp-ai-analysis id="sp-ai-analysis">
401                </sp-ai-analysis>
402                <sp-system-trace style="visibility:hidden;z-index: 101;" id="sp-system-trace">
403                </sp-system-trace>
404                <sp-record-trace style="overflow:auto;width:100%;height:100%;visibility:hidden;top:0px;left:0px;right:0;bottom:0px;position:absolute;z-index: 102" id="sp-record-trace">
405                </sp-record-trace>
406                <sp-record-trace record_template='' style="overflow:auto;width:100%;height:100%;visibility:hidden;top:0px;left:0px;right:0;bottom:0px;position:absolute;z-index: 102" id="sp-record-template">
407                </sp-record-trace>
408                <sp-scheduling-analysis style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0;left:0;right:0;bottom:0;position:absolute;" id="sp-scheduling-analysis"></sp-scheduling-analysis>
409                <sp-metrics style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0;left:0;right:0;bottom:0;position:absolute;z-index: 105" id="sp-metrics">
410                </sp-metrics>
411                <sp-query-sql style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0;left:0;right:0;bottom:0;position:absolute;z-index: 106" id="sp-query-sql">
412                </sp-query-sql>
413                <sp-info-and-stats style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0;left:0;right:0;bottom:0;position:absolute;z-index: 107" id="sp-info-and-stats">
414                </sp-info-and-stats>
415                <sp-convert-trace style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0;left:0;right:0;bottom:0;position:absolute;z-index: 107" id="sp-convert-trace">
416                </sp-convert-trace>
417                <sp-help style="width:100%;height:100%;overflow:hidden;visibility:hidden;top:0px;left:0px;right:0;bottom:0px;position:absolute;z-index: 103" id="sp-help">
418                </sp-help>
419                <sp-flags style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0px;left:0px;right:0;bottom:0px;position:absolute;z-index: 104" id="sp-flags">
420                </sp-flags>
421                <sp-third-party style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0px;left:0px;right:0;bottom:0px;position:absolute;z-index: 104" id="sp-third-party">
422                </sp-third-party>
423                <trace-row-config class="chart-filter" style="height:100%;top:0px;right:0;bottom:0px;position:absolute;z-index: 1001"></trace-row-config>
424                <custom-theme-color class="custom-color" style="height:100%;top:0px;right:0;bottom:0px;position:absolute;z-index: 1001"></custom-theme-color>
425            </div>
426        </div>
427        `;
428
429export function readTraceFileBuffer(): Promise<ArrayBuffer | undefined> {
430  return new Promise((resolve) => {
431    caches.match(getThreadPoolTraceBufferCacheKey('1')).then((res) => {
432      if (res) {
433        res.arrayBuffer().then((buffer) => {
434          resolve(buffer);
435        });
436      } else {
437        resolve(undefined);
438      }
439    });
440  });
441}
442
443export function clearTraceFileCache(): void {
444  caches.keys().then((keys) => {
445    keys.forEach((key) => {
446      if (key === getThreadPoolTraceBufferCacheKey('1')) {
447        caches.delete(key).then();
448      } else if (key.includes('/') && key.includes('-')) {
449        let splits = key.split('/');
450        let keyStr = splits[splits.length - 1];
451        let time = keyStr.split('-')[0];
452        let fileDate = new Date(parseInt(time));
453        if (fileDate.toLocaleDateString() !== new Date().toLocaleDateString()) {
454          //如果不是当天的缓存则删去缓存文件
455          caches.delete(key).then();
456        }
457      } else {
458        caches.delete(key).then();
459      }
460    });
461  });
462}
463
464export function postLog(filename: string, fileSize: string): void {
465  fetch(`https://${window.location.host.split(':')[0]}:${window.location.port}/logger`, {
466    method: 'POST',
467    headers: {
468      'Content-Type': 'application/json',
469    },
470    body: JSON.stringify({
471      fileName: filename,
472      fileSize: fileSize,
473    }),
474  })
475    .then((response) => response.json())
476    .then((data) => { })
477    .catch((error) => { });
478}
479
480export function indexedDataToBufferData(sourceData: unknown): ArrayBuffer {
481  let uintArrayLength = 0;
482  //@ts-ignore
483  let uintDataList = sourceData.map((item: unknown) => {
484    //@ts-ignore
485    let currentBufData = new Uint8Array(item.buf);
486    uintArrayLength += currentBufData.length;
487    return currentBufData;
488  });
489  let resultArrayBuffer = new ArrayBuffer(uintArrayLength);
490  let resultUintArray = new Uint8Array(resultArrayBuffer);
491  let offset = 0;
492  uintDataList.forEach((currentArray: Uint8Array) => {
493    resultUintArray.set(currentArray, offset);
494    offset += currentArray.length;
495  });
496  return resultArrayBuffer;
497}
498
499export function findFreeSizeAlgorithm(numbers: Array<number>, freeSize: number): Array<number> {
500  let closestSize = 0;
501  let currentSize = 0;
502  let finalIndex: Array<number> = [];
503  let currentSelectIndex: Array<number> = [];
504
505  function reBackFind(index: number): void {
506    if (index === numbers.length) {
507      const sumDifference = Math.abs(currentSize - freeSize);
508      if (currentSize <= freeSize && sumDifference < Math.abs(closestSize - freeSize)) {
509        closestSize = currentSize;
510        finalIndex = [...currentSelectIndex];
511      }
512      return;
513    }
514    currentSize += numbers[index];
515    currentSelectIndex.push(index);
516    reBackFind(index + 1);
517    currentSize -= numbers[index];
518    currentSelectIndex.pop();
519    reBackFind(index + 1);
520  }
521
522  reBackFind(0);
523  return finalIndex;
524}
525
526export function getCurrentDataTime(): string[] {
527  let current = new Date();
528  let year = '' + current.getFullYear();
529  let month = ('0' + (current.getMonth() + 1)).slice(-2);
530  let day = ('0' + current.getDate()).slice(-2);
531  let hours = ('0' + current.getHours()).slice(-2);
532  let minutes = ('0' + current.getMinutes()).slice(-2);
533  let seconds = ('0' + current.getSeconds()).slice(-2);
534  return [year, month, day, hours, minutes, seconds];
535}
536