All files / src/app/utils utils.ts

89.02% Statements 73/82
73.46% Branches 36/49
87.5% Functions 14/16
88.31% Lines 68/77

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158          9299x 6206x     3093x 437x 437x 2737x   437x     2656x 2656x 6524x 6524x     2656x           3213x     3213x     3213x     3213x     3213x   3213x           6828x 4778x   2050x 2050x                             189x 66x     123x 87x       87x       87x 2x       87x     36x 44x     44x     28x     8x       36x       35x 35x 55x 41x     35x       145x 435x 435x 145x 15255x 15255x 2025x   13230x 13230x 13230x 13230x     145x 145x 405x 405x 405x     405x   145x     15255x   15255x 810x 145x       810x 810x 810x 810x 810x    
import { SimpleConfiguration } from "../models/configuration";
import { Device } from "../models/devices";
import { SignalGroup, SignalDisplay } from "../models/signals";
 
export function deepCopy<T>(obj: T): T {
    if (obj === null || typeof obj !== 'object') {
        return obj;
    }
 
    if (Array.isArray(obj)) {
        const arrCopy: T[] = [];
        for (const item of obj) {
            arrCopy.push(deepCopy(item));
        }
        return arrCopy as unknown as T;
    }
 
    const objCopy: { [key: string]: T[keyof T] } = {} as { [key: string]: T[keyof T] };
    for (const key in obj) {
        Eif (Object.prototype.hasOwnProperty.call(obj, key)) {
            objCopy[key] = deepCopy((obj as { [key: string]: T[keyof T] })[key]);
        }
    }
    return objCopy as T;
}
 
 
export function getWeekNumber(date: Date): number {
    // Clone the date to avoid modifying the original
    const current = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
 
    // Set the first day of the week to Monday
    const day = current.getUTCDay() === 0 ? 7 : current.getUTCDay(); // Sunday is 7
 
    // Set the current date to the nearest Thursday (current day + 4 - day number)
    current.setUTCDate(current.getUTCDate() + 4 - day);
 
    // Get the year of the adjusted date
    const yearStart = new Date(Date.UTC(current.getUTCFullYear(), 0, 1));
 
    // Calculate the week number
    const weekNumber = Math.ceil((((current.getTime() - yearStart.getTime()) / 86400000) + 1) / 7);
 
    return weekNumber;
}
 
 
 
export function getSeverity(status: string) {
    if (status === "up") {
        return "success";
    }
    Eif (status === "no data") {
        return "info";
    }
    return "danger";
}
 
function componentToHex(c: number) {
    const hex = Math.round(c).toString(16);
    return hex.length == 1 ? "0" + hex : hex;
}
 
export function rgbToHex(r: number, g: number, b: number) {
    return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}
 
export function areEqual<T>(firstObject: T, secondObject: T): boolean {
    if (firstObject === null || typeof firstObject !== 'object') {
        return firstObject === secondObject;
    }
 
    if (Array.isArray(firstObject) && Array.isArray(secondObject)) {
        Iif (firstObject === secondObject) {
            return true;
        }
 
        Iif (firstObject.length !== secondObject.length) {
            return false;
        }
 
        for (let i = 0; i < firstObject.length; ++i) {
            Iif (!areEqual(firstObject[i], secondObject[i])) {
                return false;
            }
        }
        return true;
    }
 
    for (const key in firstObject) {
        Iif (!Object.prototype.hasOwnProperty.call(firstObject, key) || !Object.prototype.hasOwnProperty.call(secondObject, key)) {
            return false;
        }
        if (!areEqual(
            (firstObject as { [key: string]: T[keyof T] })[key],
            (secondObject as { [key: string]: T[keyof T] })[key])) {
            return false;
        }
    }
    return true;
}
 
export function arrayContains<T>(array: T[], object: T) {
    return (array.find(element => areEqual(element, object)) !== undefined);
}
 
export function getDistinctElements<T>(array: T[]): T[] {
    const newArray: T[] = [];
    for (const element of array) {
        if (newArray.every(elem => !areEqual(elem, element))) {
            newArray.push(element);
        }
    }
    return newArray;
}
 
export function groupSignalIds(devices: Device[], signalIds: string[], configs: SimpleConfiguration[] = []) {
    const signalsGroupMap = new Map<string, SignalDisplay[]>();
    const devicesById = new Map(devices.map(device => [device.device_id, device]));
    const configNamesById = new Map(configs.map(config => [config.config_id, config.config_name]));
    for (const signalId of signalIds) {
        const splitSignalId = signalId.split(".");
        if (splitSignalId.length < 3) {
            continue;
        }
        const groupName = `${splitSignalId[0]}.${splitSignalId[1]}`;
        const groupSignalIds = signalsGroupMap.get(groupName) ?? [];
        groupSignalIds.push({signalId: signalId, ticker: splitSignalId[splitSignalId.length - 1]});
        signalsGroupMap.set(groupName, groupSignalIds);
    }
 
    const signalGroups: SignalGroup[] = [];
    for (const [device_config, signals] of signalsGroupMap) {
        const device = devicesById.get(device_config.split(".")[0]);
        const configName = configNamesById.get(device_config.split(".")[1]) ?? "Unknown config";
        Iif (device === undefined) {
            continue;
        }
        signalGroups.push({deviceName: `${device.name} (${configName})`, signals: signals});
    }
    signalGroups.push({
        deviceName: "System",
        signals: signalIds.filter(signalId => {
            const deviceId = signalId.split(".")[0];
            // if device/config id is not hexadecimal, it comes from the system
            return !deviceId.match(/[0-9A-Fa-f]{12}/g);
        }).map(signalId => {return {signalId: signalId, ticker: formatSystemSignal(signalId)};})});
    return signalGroups;
}
 
export function formatSystemSignal(signalId: string): string {
    const cleanId = signalId.replaceAll("_", " ");
    const splitSignalId = cleanId.split(".");
    const service_name = splitSignalId[0];
    const cleanTicker = (splitSignalId[splitSignalId.length - 1] ?? "unknown ticker").toLowerCase();
    return `${service_name}'s ${cleanTicker}`;
  }