* -------------------------------------------------------------------------
* This file is part of the MindStudio project.
* Copyright (c) 2025 Huawei Technologies Co.,Ltd.
*
* MindStudio is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*/
import type { Theme } from '@emotion/react';
import type { Session } from '../../entity/session';
import type { CardMetaData } from '../../entity/data';
import type { InsightUnit } from '../../entity/insight';
export const colorPalette: Array<keyof Theme['colorPalette']> = [
'deepBlue',
'coralRed',
'tealGreen',
'aquaBlue',
'raspberryPink',
'vividBlue',
'vividRed',
'royalPurple',
'skyBlue',
'sunsetOrange',
'amethystPurple',
'limeGreen',
];
export function getTimeOffset(session: Session, metaData: { cardId?: string; processId?: string }, units: InsightUnit[] = [], timestampOffset?: Record<string, number>): number {
const timeOffsetKey = getTimeOffsetKey(session, metaData, units);
timestampOffset = timestampOffset ?? session?.unitsConfig.offsetConfig.timestampOffset;
return metaData.cardId !== undefined
? timestampOffset?.[timeOffsetKey] ?? 0
: 0;
}
export function getTimeOffsetKey(session: Session, metaData: { cardId?: string; processId?: string }, units: InsightUnit[] = []): string {
if (units.length === 0) {
units = session.units;
}
const unit = units.find(value => containCardId(value, metaData.cardId ?? ''));
const realCardId = unit ? (unit.metadata as CardMetaData).cardId : 'Host';
let realProcessId = metaData.processId;
if (realProcessId !== undefined && !isNaN(Number(realProcessId))) {
const upper32BitProcessId = Math.floor(Number(realProcessId) / Math.pow(2, 32));
if (upper32BitProcessId !== 0) {
realProcessId = upper32BitProcessId.toString();
}
}
return (realProcessId != null) ? `${realCardId}__${realProcessId}` : realCardId;
}
export interface TimeOffsetUnitTree {
metadata?: Record<string, unknown>;
children?: TimeOffsetUnitTree[];
alignStartTimestamp?: number;
}
export function visitUnitTree(unit: TimeOffsetUnitTree | undefined, visitor: (unit: TimeOffsetUnitTree) => void, loopIndex = 0): void {
const MaxLoop = 100;
if (unit === undefined || loopIndex > MaxLoop) {
return;
}
visitor(unit);
unit.children?.forEach(child => {
visitUnitTree(child, visitor, loopIndex + 1);
});
}
export function setTimeOffsetForUnitTree(
session: Session,
unit: TimeOffsetUnitTree | undefined,
offset: number | undefined,
timestampOffsetConfig: Record<string, number>,
): void {
if (offset === undefined) {
return;
}
visitUnitTree(unit, (item) => {
if (item.metadata === undefined) {
return;
}
item.alignStartTimestamp = offset;
const key = getTimeOffsetKey(session, item.metadata as { cardId?: string; processId?: string });
timestampOffsetConfig[key] = offset;
});
}
function containCardId(unit: InsightUnit, cardId: string): boolean {
if ((unit.metadata as CardMetaData)?.cardId === cardId) {
return true;
}
return unit.children?.some(childUnit => containCardId(childUnit, cardId)) ?? false;
}
function parseDecimal(str: string): {
sign: bigint;
int: string;
frac: string;
} {
let sign = BigInt(1);
if (str.startsWith('-')) {
sign = BigInt(-1);
str = str.slice(1);
} else if (str.startsWith('+')) {
str = str.slice(1);
}
const [intPart, fracPart = ''] = str.split('.');
return { sign, int: intPart || '0', frac: fracPart };
}
export function bigSubtract(a: number | string, b: number | string): string {
if (typeof BigInt === 'undefined') {
return '-';
}
const aStr = String(a);
const bStr = String(b);
const aParser = parseDecimal(aStr);
const bParser = parseDecimal(bStr);
const maxFracLen = Math.max(aParser.frac.length, bParser.frac.length);
const aFracPadded = aParser.frac.padEnd(maxFracLen, '0');
const bFracPadded = bParser.frac.padEnd(maxFracLen, '0');
const aBig = aParser.sign * BigInt(aParser.int + aFracPadded);
const bBig = bParser.sign * BigInt(bParser.int + bFracPadded);
let resultBig = aBig - bBig;
let signStr = '';
if (resultBig < 0) {
signStr = '-';
resultBig = -resultBig;
}
let resultStr = resultBig.toString().padStart(maxFracLen + 1, '0');
if (maxFracLen > 0) {
const intPart = resultStr.slice(0, -maxFracLen);
const fracPart = resultStr.slice(-maxFracLen);
resultStr = intPart + '.' + fracPart;
}
resultStr = resultStr.replace(/^0+(?=\d)/, '');
if (resultStr.includes('.')) {
resultStr = resultStr.replace(/(\.\d*?[1-9])0+$/, '$1');
resultStr = resultStr.replace(/\.$/, '');
}
return signStr + resultStr;
}