1// Copyright (c) 2021 Huawei Device Co., Ltd.
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6//     http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14import { TraficEnum } from './utils/QueryEnum';
15import { FrameAnimationStruct } from '../ui-worker/ProcedureWorkerFrameAnimation';
16import { FrameSpacingStruct } from '../ui-worker/ProcedureWorkerFrameSpacing';
17import { Args } from './CommonArgs';
18
19export const chartFrameAnimationDataProtoSql = (args: Args): string => {
20  return `
21      SELECT
22          a.id AS animationId,
23          0 AS status,
24          ( 
25              CASE WHEN a.input_time NOT NULL 
26                  THEN ( a.input_time - ${args.recordStartNS} ) 
27                  ELSE ( a.start_point - ${args.recordStartNS} ) 
28              END 
29          ) AS startTs,
30          ( a.start_point - ${args.recordStartNS} ) AS endTs,
31          a.name AS name
32      FROM
33          animation AS a 
34      UNION
35      SELECT
36          a.id AS animationId,
37          1 AS status,
38          ( 
39              CASE WHEN a.input_time NOT NULL 
40                  THEN ( a.input_time - ${args.recordStartNS} ) 
41                  ELSE ( a.start_point - ${args.recordStartNS} ) 
42              END 
43          ) AS startTs,
44          ( a.end_point - ${args.recordStartNS} ) AS endTs,
45          a.name AS name
46      FROM
47          animation AS a;`;
48};
49
50export const chartFrameDynamicDataMemSql = (args: Args): string => {
51  return `
52        SELECT
53           dy.id,
54           dy.x,
55           dy.y,
56           dy.width,
57           dy.height,
58           dy.alpha,
59           (dy.end_time - ${args.recordStartNS}) AS ts,
60           dy.name as appName
61        FROM 
62            dynamic_frame AS dy
63        WHERE ts >= ${Math.floor(args.startNS)}
64          and ts <= ${Math.floor(args.endNS)}`;
65};
66
67export const chartFrameSpacingDataMemSql = (args: Args): string => {
68  return `
69      SELECT
70          d.id,
71          d.x,
72          d.y,
73          d.width AS currentFrameWidth,
74          d.height AS currentFrameHeight,
75          (d.end_time - ${args.recordStartNS}) AS currentTs,
76          d.name AS nameId
77      FROM
78          dynamic_frame AS d
79      WHERE currentTs >= ${Math.floor(args.startNS)}
80          and currentTs <= ${Math.floor(args.endNS)};`;
81};
82
83export function frameAnimationReceiver(data: unknown, proc: Function): void {
84  // @ts-ignore
85  let res = proc(chartFrameAnimationDataProtoSql(data.params));
86  // @ts-ignore
87  let transfer = data.params.trafic !== TraficEnum.SharedArrayBuffer;
88  let frameAnimation = new FrameAnimation(data, res, transfer);
89  let unitIndex: number = 1;
90  let isIntersect = (a: FrameAnimationStruct, b: FrameAnimationStruct): boolean =>
91    Math.max(a.startTs! + a.dur!, b.startTs! + b.dur!) - Math.min(a.startTs!, b.startTs!) < a.dur! + b.dur!;
92  let depths: unknown[] = [];
93  for (let index: number = 0; index < res.length; index++) {
94    let itemData = res[index];
95    // @ts-ignore
96    data.params.trafic === TraficEnum.ProtoBuffer && (itemData = itemData.frameAnimationData);
97    itemData.dur = itemData.endTs - itemData.startTs;
98    if (!itemData.dur || itemData.dur < 0) {
99      continue;
100    }
101    if (depths.length === 0) {
102      itemData.depth = 0;
103      depths[0] = itemData;
104    } else {
105      let depthIndex: number = 0;
106      let isContinue: boolean = true;
107      while (isContinue) {
108        // @ts-ignore
109        if (isIntersect(depths[depthIndex], itemData)) {
110          if (depths[depthIndex + unitIndex] === undefined || !depths[depthIndex + unitIndex]) {
111            itemData.depth = depthIndex + unitIndex;
112            depths[depthIndex + unitIndex] = itemData;
113            isContinue = false;
114          }
115        } else {
116          itemData.depth = depthIndex;
117          depths[depthIndex] = itemData;
118          isContinue = false;
119        }
120        depthIndex++;
121      }
122    }
123    frameAnimation.animationId[index] = itemData.animationId;
124    frameAnimation.status[index] = itemData.status;
125    frameAnimation.startTs[index] = itemData.startTs;
126    frameAnimation.endTs[index] = itemData.endTs;
127    frameAnimation.dur[index] = itemData.dur;
128    frameAnimation.depth[index] = itemData.depth;
129  }
130  postFrameAnimationMessage(data, transfer, frameAnimation, res.length);
131}
132function postFrameAnimationMessage(
133  data: unknown,
134  transfer: boolean,
135  frameAnimation: FrameAnimation,
136  len: number
137): void {
138  (self as unknown as Worker).postMessage(
139    {
140      // @ts-ignore
141      id: data.id,
142      // @ts-ignore
143      action: data.action,
144      results: transfer
145        ? {
146            animationId: frameAnimation.animationId.buffer,
147            status: frameAnimation.status.buffer,
148            startTs: frameAnimation.startTs.buffer,
149            endTs: frameAnimation.endTs.buffer,
150            dur: frameAnimation.dur.buffer,
151            depth: frameAnimation.depth.buffer,
152          }
153        : {},
154      len: len,
155      transfer: transfer,
156    },
157    transfer
158      ? [
159          frameAnimation.animationId.buffer,
160          frameAnimation.status.buffer,
161          frameAnimation.startTs.buffer,
162          frameAnimation.endTs.buffer,
163          frameAnimation.dur.buffer,
164          frameAnimation.depth.buffer,
165        ]
166      : []
167  );
168}
169class FrameAnimation {
170  animationId: Uint16Array;
171  status: Uint16Array;
172  startTs: Float64Array;
173  endTs: Float64Array;
174  dur: Float64Array;
175  depth: Uint16Array;
176
177  constructor(data: unknown, res: unknown[], transfer: boolean) {
178    // @ts-ignore
179    this.animationId = new Uint16Array(transfer ? res.length : data.params.sharedArrayBuffers.animationId);
180    // @ts-ignore
181    this.status = new Uint16Array(transfer ? res.length : data.params.sharedArrayBuffers.status);
182    // @ts-ignore
183    this.startTs = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startTs);
184    // @ts-ignore
185    this.endTs = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.endTs);
186    // @ts-ignore
187    this.dur = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.dur);
188    // @ts-ignore
189    this.depth = new Uint16Array(transfer ? res.length : data.params.sharedArrayBuffers.depth);
190  }
191}
192
193let frameSpacingList: Array<unknown> = [];
194let frameDynamic: Array<unknown> = [];
195export function resetDynamicEffect(): void {
196  frameSpacingList = [];
197  frameDynamic = [];
198}
199export function frameDynamicReceiver(data: unknown, proc: Function): void {
200  if (frameDynamic.length === 0) {
201    // @ts-ignore
202    frameDynamic = proc(chartFrameDynamicDataMemSql(data.params));
203  }
204  // @ts-ignore
205  let transfer = data.params.trafic !== TraficEnum.SharedArrayBuffer;
206  // @ts-ignore
207  let id = new Uint16Array(transfer ? frameDynamic.length : data.params.sharedArrayBuffers.id);
208  // @ts-ignore
209  let x = new Float32Array(transfer ? frameDynamic.length : data.params.sharedArrayBuffers.x);
210  // @ts-ignore
211  let y = new Float32Array(transfer ? frameDynamic.length : data.params.sharedArrayBuffers.y);
212  // @ts-ignore
213  let width = new Float32Array(transfer ? frameDynamic.length : data.params.sharedArrayBuffers.width);
214  // @ts-ignore
215  let height = new Float32Array(transfer ? frameDynamic.length : data.params.sharedArrayBuffers.height);
216  // @ts-ignore
217  let alpha = new Float32Array(transfer ? frameDynamic.length : data.params.sharedArrayBuffers.alpha);
218  // @ts-ignore
219  let ts = new Float64Array(transfer ? frameDynamic.length : data.params.sharedArrayBuffers.ts);
220  for (let index: number = 0; index < frameDynamic.length; index++) {
221    let itemData = frameDynamic[index];
222    // @ts-ignore
223    data.params.trafic === TraficEnum.ProtoBuffer && (itemData = itemData.frameDynamicData);
224    // @ts-ignore
225    id[index] = itemData.id;
226    // @ts-ignore
227    x[index] = Number(itemData.x);
228    // @ts-ignore
229    y[index] = Number(itemData.y);
230    // @ts-ignore
231    width[index] = Number(itemData.width);
232    // @ts-ignore
233    height[index] = Number(itemData.height);
234    // @ts-ignore
235    alpha[index] = Number(itemData.alpha);
236    // @ts-ignore
237    ts[index] = itemData.ts;
238  }
239  (self as unknown as Worker).postMessage(
240    {
241      // @ts-ignore
242      id: data.id,
243      // @ts-ignore
244      action: data.action,
245      results: transfer
246        ? {
247            id: id.buffer,
248            x: x.buffer,
249            y: y.buffer,
250            width: width.buffer,
251            height: height.buffer,
252            alpha: alpha.buffer,
253            ts: ts.buffer,
254          }
255        : {},
256      len: frameDynamic.length,
257      transfer: transfer,
258    },
259    transfer ? [id.buffer, x.buffer, y.buffer, width.buffer, height.buffer, alpha.buffer, ts.buffer] : []
260  );
261}
262export function frameSpacingReceiver(data: unknown, proc: Function): void {
263  if (frameSpacingList.length === 0) {
264    // @ts-ignore
265    frameSpacingList = proc(chartFrameSpacingDataMemSql(data.params));
266  }
267  // @ts-ignore
268  let transfer = data.params.trafic !== TraficEnum.SharedArrayBuffer;
269  let frameSpacing = new FrameSpacing(data, frameSpacingList, transfer);
270  let nameDataMap: Map<string, Array<FrameSpacingStruct>> = new Map();
271  for (let index: number = 0; index < frameSpacingList.length; index++) {
272    let itemData = frameSpacingList[index];
273    // @ts-ignore
274    data.params.trafic === TraficEnum.ProtoBuffer && (itemData = itemData.frameSpacingData);
275    // @ts-ignore
276    if (nameDataMap.has(itemData.nameId)) {
277      // @ts-ignore
278      setSpacingStructs(nameDataMap, itemData, data);
279    } else {
280      // @ts-ignore
281      setNameDataMap(nameDataMap, itemData);
282    }
283    // @ts-ignore
284    frameSpacing.id[index] = itemData.id;
285    // @ts-ignore
286    frameSpacing.x[index] = Number(itemData.x);
287    // @ts-ignore
288    frameSpacing.y[index] = Number(itemData.y);
289    // @ts-ignore
290    frameSpacing.currentFrameWidth[index] = Number(itemData.currentFrameWidth);
291    // @ts-ignore
292    frameSpacing.currentFrameHeight[index] = Number(itemData.currentFrameHeight);
293    // @ts-ignore
294    frameSpacing.currentTs[index] = itemData.currentTs;
295    // @ts-ignore
296    frameSpacing.frameSpacingResult[index] = Number(itemData.frameSpacingResult);
297    // @ts-ignore
298    frameSpacing.preTs[index] = itemData.preTs;
299    // @ts-ignore
300    frameSpacing.preFrameWidth[index] = Number(itemData.preFrameWidth);
301    // @ts-ignore
302    frameSpacing.preFrameHeight[index] = Number(itemData.preFrameHeight);
303    // @ts-ignore
304    frameSpacing.preX[index] = Number(itemData.preX);
305    // @ts-ignore
306    frameSpacing.preY[index] = Number(itemData.preY);
307  }
308  postFrameSpacingMessage(data, transfer, frameSpacing, frameSpacingList.length);
309}
310function postFrameSpacingMessage(data: unknown, transfer: boolean, frameSpacing: FrameSpacing, len: number): void {
311  (self as unknown as Worker).postMessage(
312    {
313      // @ts-ignore
314      id: data.id,
315      // @ts-ignore
316      action: data.action,
317      results: transfer
318        ? {
319            id: frameSpacing.id.buffer,
320            x: frameSpacing.x.buffer,
321            y: frameSpacing.y.buffer,
322            currentFrameWidth: frameSpacing.currentFrameWidth.buffer,
323            currentFrameHeight: frameSpacing.currentFrameHeight.buffer,
324            currentTs: frameSpacing.currentTs.buffer,
325            frameSpacingResult: frameSpacing.frameSpacingResult.buffer,
326            preTs: frameSpacing.preTs.buffer,
327            preFrameWidth: frameSpacing.preFrameWidth.buffer,
328            preFrameHeight: frameSpacing.preFrameHeight.buffer,
329            preX: frameSpacing.preX.buffer,
330            preY: frameSpacing.preY.buffer,
331          }
332        : {},
333      len: len,
334      transfer: transfer,
335    },
336    transfer
337      ? [
338          frameSpacing.id.buffer,
339          frameSpacing.x.buffer,
340          frameSpacing.y.buffer,
341          frameSpacing.currentFrameWidth.buffer,
342          frameSpacing.currentFrameHeight.buffer,
343          frameSpacing.currentTs.buffer,
344          frameSpacing.frameSpacingResult.buffer,
345          frameSpacing.preTs.buffer,
346          frameSpacing.preFrameWidth.buffer,
347          frameSpacing.preFrameHeight.buffer,
348          frameSpacing.preX.buffer,
349          frameSpacing.preY.buffer,
350        ]
351      : []
352  );
353}
354function setSpacingStructs(
355  nameDataMap: Map<string, Array<FrameSpacingStruct>>,
356  itemData: FrameSpacingStruct,
357  data: unknown
358): void {
359  let unitIndex: number = 1;
360  let secondToNanosecond: number = 1000_000_000;
361  let spacingStructs = nameDataMap.get(itemData.nameId!);
362  if (spacingStructs) {
363    let lastIndexData = spacingStructs[spacingStructs.length - 1];
364    let intervalTime = (itemData.currentTs - lastIndexData.currentTs) / secondToNanosecond;
365    let widthDifference = Number(itemData.currentFrameWidth!) - Number(lastIndexData.currentFrameWidth!);
366    let heightDifference = Number(itemData.currentFrameHeight!) - Number(lastIndexData.currentFrameHeight!);
367    let xDifference = Number(itemData.x!) - Number(lastIndexData.x!);
368    let yDifference = Number(itemData.y!) - Number(lastIndexData.y!);
369    // @ts-ignore
370    let frameWidth = Math.abs(widthDifference / data.params.physicalWidth / intervalTime);
371    // @ts-ignore
372    let frameHeight = Math.abs(heightDifference / data.params.physicalHeight / intervalTime);
373    // @ts-ignore
374    let frameX = Math.abs(xDifference / data.params.physicalWidth / intervalTime);
375    // @ts-ignore
376    let frameY = Math.abs(yDifference / data.params.physicalHeight / intervalTime);
377    let result = Math.max(frameWidth, frameHeight, frameX, frameY);
378    itemData.frameSpacingResult = Number(result.toFixed(unitIndex));
379    itemData.preTs = lastIndexData.currentTs;
380    itemData.preFrameWidth = Number(lastIndexData.currentFrameWidth);
381    itemData.preFrameHeight = Number(lastIndexData.currentFrameHeight);
382    itemData.preX = Number(lastIndexData.x);
383    itemData.preY = Number(lastIndexData.y);
384    spacingStructs.push(itemData);
385  }
386}
387function setNameDataMap(nameDataMap: Map<string, Array<FrameSpacingStruct>>, itemData: FrameSpacingStruct): void {
388  itemData.frameSpacingResult = 0;
389  itemData.preTs = 0;
390  itemData.preFrameWidth = 0;
391  itemData.preFrameHeight = 0;
392  itemData.preX = 0;
393  itemData.preY = 0;
394  nameDataMap.set(itemData.nameId!, [itemData]);
395}
396class FrameSpacing {
397  id: Uint16Array;
398  x: Float32Array;
399  y: Float32Array;
400  currentFrameWidth: Float32Array;
401  currentFrameHeight: Float32Array;
402  currentTs: Float64Array;
403  frameSpacingResult: Float32Array;
404  preTs: Float64Array;
405  preFrameWidth: Float32Array;
406  preFrameHeight: Float32Array;
407  preX: Float32Array;
408  preY: Float32Array;
409
410  constructor(data: unknown, len: unknown[], transfer: boolean) {
411    // @ts-ignore
412    this.id = new Uint16Array(transfer ? len : data.params.sharedArrayBuffers.animationId);
413    // @ts-ignore
414    this.x = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId);
415    // @ts-ignore
416    this.y = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId);
417    // @ts-ignore
418    this.currentFrameWidth = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId);
419    // @ts-ignore
420    this.currentFrameHeight = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId);
421    // @ts-ignore
422    this.currentTs = new Float64Array(transfer ? len : data.params.sharedArrayBuffers.animationId);
423    // @ts-ignore
424    this.frameSpacingResult = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId);
425    // @ts-ignore
426    this.preTs = new Float64Array(transfer ? len : data.params.sharedArrayBuffers.animationId);
427    // @ts-ignore
428    this.preFrameWidth = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId);
429    // @ts-ignore
430    this.preFrameHeight = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId);
431    // @ts-ignore
432    this.preX = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId);
433    // @ts-ignore
434    this.preY = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId);
435  }
436}
437