devicer.js 1.0.9 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/libs/confidence.js +69 -38
- package/src/libs/confidence.ts +103 -45
- package/src/main.js +3 -1
- package/src/main.ts +2 -2
- package/tests/comparisons.test.ts +92 -0
- package/tests/confidence.test.ts +1 -3
package/package.json
CHANGED
package/src/libs/confidence.js
CHANGED
|
@@ -1,73 +1,104 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.calculateConfidence = void 0;
|
|
3
|
+
exports.calculateConfidence = exports.compareDatasets = exports.compareArrays = void 0;
|
|
4
4
|
const tlsh_1 = require("./tlsh");
|
|
5
|
-
function compareArrays(arr1, arr2) {
|
|
5
|
+
function compareArrays(arr1, arr2, max_depth = 5) {
|
|
6
6
|
let fields = 0;
|
|
7
7
|
let matches = 0;
|
|
8
|
-
|
|
8
|
+
// Ensure max_depth is not exceeded
|
|
9
|
+
if (max_depth <= 0) {
|
|
10
|
+
throw new Error("Max depth exceeded");
|
|
11
|
+
}
|
|
12
|
+
// Sort arrays to ensure consistent comparison
|
|
13
|
+
const sortedArr1 = arr1.map((item) => JSON.stringify(item)).sort().map((item) => {
|
|
14
|
+
try {
|
|
15
|
+
return JSON.parse(item);
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
const sortedArr2 = arr2.map((item) => JSON.stringify(item)).sort().map((item) => {
|
|
22
|
+
try {
|
|
23
|
+
return JSON.parse(item);
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
const maxLength = Math.min(arr1.length, arr2.length);
|
|
9
30
|
for (let i = 0; i < maxLength; i++) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
matches++;
|
|
25
|
-
}
|
|
31
|
+
fields++;
|
|
32
|
+
if (Array.isArray(sortedArr1[i]) && Array.isArray(sortedArr2[i])) {
|
|
33
|
+
const subData = compareArrays(sortedArr1[i], sortedArr2[i], max_depth - 1);
|
|
34
|
+
fields += subData[0] - 1; // Subtract 1 for the index itself
|
|
35
|
+
matches += subData[1];
|
|
36
|
+
}
|
|
37
|
+
else if ((typeof sortedArr1[i] == "object" && sortedArr1[i]) &&
|
|
38
|
+
(typeof sortedArr2[i] == "object" && sortedArr2[i])) {
|
|
39
|
+
const subData = compareDatasets(sortedArr1[i], sortedArr2[i], max_depth - 1);
|
|
40
|
+
fields += subData[0] - 1; // Subtract 1 for the index itself
|
|
41
|
+
matches += subData[1];
|
|
42
|
+
}
|
|
43
|
+
if (arr1[i] === arr2[i]) {
|
|
44
|
+
matches++;
|
|
26
45
|
}
|
|
27
46
|
}
|
|
28
47
|
return [fields, matches];
|
|
29
48
|
}
|
|
30
|
-
|
|
49
|
+
exports.compareArrays = compareArrays;
|
|
50
|
+
function compareDatasets(data1, data2, max_depth = 5) {
|
|
31
51
|
let fields = 0;
|
|
32
52
|
let matches = 0;
|
|
53
|
+
// Ensure max_depth is not exceeded
|
|
54
|
+
if (max_depth <= 0) {
|
|
55
|
+
throw new Error("Max depth exceeded");
|
|
56
|
+
}
|
|
33
57
|
for (const key in data1) {
|
|
34
58
|
if (data1[key] !== undefined && data2[key] !== undefined) {
|
|
35
59
|
fields++;
|
|
36
60
|
if ((typeof data1[key] == "object" && data1[key]) &&
|
|
37
61
|
(typeof data2[key] == "object" && data2[key])) {
|
|
38
|
-
const subData = compareDatasets(data1[key], data2[key]);
|
|
62
|
+
const subData = compareDatasets(data1[key], data2[key], max_depth - 1);
|
|
39
63
|
fields += subData[0] - 1; // Subtract 1 for the key itself
|
|
40
64
|
matches += subData[1];
|
|
41
65
|
}
|
|
42
66
|
else if (Array.isArray(data1[key]) && Array.isArray(data2[key])) {
|
|
43
|
-
const subData = compareArrays(data1[key], data2[key]);
|
|
67
|
+
const subData = compareArrays(data1[key], data2[key], max_depth - 1);
|
|
44
68
|
fields += subData[0] - 1; // Subtract 1 for the key itself
|
|
45
69
|
matches += subData[1];
|
|
46
70
|
}
|
|
47
|
-
if (data1[key] == data2[key]) {
|
|
71
|
+
else if (data1[key] == data2[key]) {
|
|
48
72
|
matches++;
|
|
49
73
|
}
|
|
50
74
|
}
|
|
51
75
|
}
|
|
52
76
|
return [fields, matches];
|
|
53
77
|
}
|
|
78
|
+
exports.compareDatasets = compareDatasets;
|
|
54
79
|
function calculateConfidence(data1, data2) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
80
|
+
try {
|
|
81
|
+
// Compare how many fields are the same in both datasets
|
|
82
|
+
const [fields, matches] = compareDatasets(data1, data2);
|
|
83
|
+
if (fields === 0 || matches === 0) {
|
|
84
|
+
return 0;
|
|
85
|
+
}
|
|
86
|
+
// Calculate the hash for each user data
|
|
87
|
+
const hash1 = (0, tlsh_1.getHash)(JSON.stringify(data1));
|
|
88
|
+
const hash2 = (0, tlsh_1.getHash)(JSON.stringify(data2));
|
|
89
|
+
// Compare the hashes to get their difference
|
|
90
|
+
const differenceScore = (0, tlsh_1.compareHashes)(hash1, hash2);
|
|
91
|
+
const inverseMatchScore = 1 - (matches / fields);
|
|
92
|
+
const x = 1.3 * differenceScore * inverseMatchScore;
|
|
93
|
+
if (inverseMatchScore === 0 || differenceScore === 0) {
|
|
94
|
+
return 100;
|
|
95
|
+
}
|
|
96
|
+
const confidenceScore = 100 / (1 + Math.E ** (-4.5 + (0.3 * x)));
|
|
97
|
+
return confidenceScore;
|
|
59
98
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
// Compare the hashes to get their difference
|
|
64
|
-
const differenceScore = (0, tlsh_1.compareHashes)(hash1, hash2);
|
|
65
|
-
const inverseMatchScore = 1 - (matches / fields);
|
|
66
|
-
const x = 1.3 * differenceScore * inverseMatchScore;
|
|
67
|
-
if (inverseMatchScore === 0 || differenceScore === 0) {
|
|
68
|
-
return 100;
|
|
99
|
+
catch (error) {
|
|
100
|
+
console.error("Error calculating confidence:", error);
|
|
101
|
+
return 0; // Return 0 if an error occurs during comparison
|
|
69
102
|
}
|
|
70
|
-
const confidenceScore = 100 / (1 + Math.E ** (-4.5 + (0.3 * x)));
|
|
71
|
-
return confidenceScore;
|
|
72
103
|
}
|
|
73
104
|
exports.calculateConfidence = calculateConfidence;
|
package/src/libs/confidence.ts
CHANGED
|
@@ -1,39 +1,85 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { compareHashes, getHash } from "./tlsh";
|
|
2
2
|
import { FPDataSet } from "../types/data";
|
|
3
3
|
|
|
4
|
-
function compareArrays(
|
|
4
|
+
export function compareArrays(
|
|
5
|
+
arr1: any[],
|
|
6
|
+
arr2: any[],
|
|
7
|
+
max_depth: number = 5,
|
|
8
|
+
): [number, number] {
|
|
5
9
|
let fields = 0;
|
|
6
10
|
let matches = 0;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
) {
|
|
21
|
-
const subData = compareDatasets(arr1[i] as FPDataSet, arr2[i] as FPDataSet);
|
|
22
|
-
fields += subData[0] - 1; // Subtract 1 for the index itself
|
|
23
|
-
matches += subData[1];
|
|
11
|
+
|
|
12
|
+
// Ensure max_depth is not exceeded
|
|
13
|
+
if (max_depth <= 0) {
|
|
14
|
+
throw new Error("Max depth exceeded");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Sort arrays to ensure consistent comparison
|
|
18
|
+
const sortedArr1 = arr1.map((item) => JSON.stringify(item)).sort().map(
|
|
19
|
+
(item) => {
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(item);
|
|
22
|
+
} catch (e) {
|
|
23
|
+
return undefined;
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
},
|
|
26
|
+
);
|
|
27
|
+
const sortedArr2 = arr2.map((item) => JSON.stringify(item)).sort().map(
|
|
28
|
+
(item) => {
|
|
29
|
+
try {
|
|
30
|
+
return JSON.parse(item);
|
|
31
|
+
} catch (e) {
|
|
32
|
+
return undefined;
|
|
28
33
|
}
|
|
34
|
+
},
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const maxLength = Math.min(arr1.length, arr2.length);
|
|
38
|
+
for (let i = 0; i < maxLength; i++) {
|
|
39
|
+
fields++;
|
|
40
|
+
if (Array.isArray(sortedArr1[i]) && Array.isArray(sortedArr2[i])) {
|
|
41
|
+
const subData = compareArrays(
|
|
42
|
+
sortedArr1[i],
|
|
43
|
+
sortedArr2[i],
|
|
44
|
+
max_depth - 1,
|
|
45
|
+
);
|
|
46
|
+
fields += subData[0] - 1; // Subtract 1 for the index itself
|
|
47
|
+
matches += subData[1];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
else if (
|
|
51
|
+
(typeof sortedArr1[i] == "object" && sortedArr1[i]) &&
|
|
52
|
+
(typeof sortedArr2[i] == "object" && sortedArr2[i])
|
|
53
|
+
) {
|
|
54
|
+
const subData = compareDatasets(
|
|
55
|
+
sortedArr1[i] as FPDataSet,
|
|
56
|
+
sortedArr2[i] as FPDataSet,
|
|
57
|
+
max_depth - 1,
|
|
58
|
+
);
|
|
59
|
+
fields += subData[0] - 1; // Subtract 1 for the index itself
|
|
60
|
+
matches += subData[1];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (arr1[i] === arr2[i]) {
|
|
64
|
+
matches++;
|
|
29
65
|
}
|
|
30
66
|
}
|
|
31
67
|
return [fields, matches];
|
|
32
68
|
}
|
|
33
69
|
|
|
34
|
-
function compareDatasets(
|
|
70
|
+
export function compareDatasets(
|
|
71
|
+
data1: FPDataSet,
|
|
72
|
+
data2: FPDataSet,
|
|
73
|
+
max_depth: number = 5,
|
|
74
|
+
): [number, number] {
|
|
35
75
|
let fields = 0;
|
|
36
76
|
let matches = 0;
|
|
77
|
+
|
|
78
|
+
// Ensure max_depth is not exceeded
|
|
79
|
+
if (max_depth <= 0) {
|
|
80
|
+
throw new Error("Max depth exceeded");
|
|
81
|
+
}
|
|
82
|
+
|
|
37
83
|
for (const key in data1) {
|
|
38
84
|
if (data1[key] !== undefined && data2[key] !== undefined) {
|
|
39
85
|
fields++;
|
|
@@ -41,18 +87,22 @@ function compareDatasets(data1: FPDataSet, data2: FPDataSet): [number, number] {
|
|
|
41
87
|
(typeof data1[key] == "object" && data1[key]) &&
|
|
42
88
|
(typeof data2[key] == "object" && data2[key])
|
|
43
89
|
) {
|
|
44
|
-
const subData = compareDatasets(
|
|
90
|
+
const subData = compareDatasets(
|
|
91
|
+
data1[key] as FPDataSet,
|
|
92
|
+
data2[key] as FPDataSet,
|
|
93
|
+
max_depth - 1,
|
|
94
|
+
);
|
|
45
95
|
fields += subData[0] - 1; // Subtract 1 for the key itself
|
|
46
96
|
matches += subData[1];
|
|
47
97
|
}
|
|
48
|
-
|
|
98
|
+
|
|
49
99
|
else if (Array.isArray(data1[key]) && Array.isArray(data2[key])) {
|
|
50
|
-
const subData = compareArrays(data1[key], data2[key]);
|
|
100
|
+
const subData = compareArrays(data1[key], data2[key], max_depth - 1);
|
|
51
101
|
fields += subData[0] - 1; // Subtract 1 for the key itself
|
|
52
102
|
matches += subData[1];
|
|
53
103
|
}
|
|
54
104
|
|
|
55
|
-
if (data1[key] == data2[key]) {
|
|
105
|
+
else if (data1[key] == data2[key]) {
|
|
56
106
|
matches++;
|
|
57
107
|
}
|
|
58
108
|
}
|
|
@@ -60,26 +110,34 @@ function compareDatasets(data1: FPDataSet, data2: FPDataSet): [number, number] {
|
|
|
60
110
|
return [fields, matches];
|
|
61
111
|
}
|
|
62
112
|
|
|
63
|
-
export function calculateConfidence(
|
|
64
|
-
|
|
65
|
-
|
|
113
|
+
export function calculateConfidence(
|
|
114
|
+
data1: FPDataSet,
|
|
115
|
+
data2: FPDataSet,
|
|
116
|
+
): number {
|
|
117
|
+
try {
|
|
118
|
+
// Compare how many fields are the same in both datasets
|
|
119
|
+
const [fields, matches] = compareDatasets(data1, data2);
|
|
66
120
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
121
|
+
if (fields === 0 || matches === 0) {
|
|
122
|
+
return 0;
|
|
123
|
+
}
|
|
70
124
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
125
|
+
// Calculate the hash for each user data
|
|
126
|
+
const hash1 = getHash(JSON.stringify(data1));
|
|
127
|
+
const hash2 = getHash(JSON.stringify(data2));
|
|
74
128
|
|
|
75
|
-
|
|
76
|
-
|
|
129
|
+
// Compare the hashes to get their difference
|
|
130
|
+
const differenceScore = compareHashes(hash1, hash2);
|
|
77
131
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
132
|
+
const inverseMatchScore = 1 - (matches / fields);
|
|
133
|
+
const x = 1.3 * differenceScore * inverseMatchScore;
|
|
134
|
+
if (inverseMatchScore === 0 || differenceScore === 0) {
|
|
135
|
+
return 100;
|
|
136
|
+
}
|
|
137
|
+
const confidenceScore = 100 / (1 + Math.E ** (-4.5 + (0.3 * x)));
|
|
138
|
+
return confidenceScore;
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.error("Error calculating confidence:", error);
|
|
141
|
+
return 0; // Return 0 if an error occurs during comparison
|
|
82
142
|
}
|
|
83
|
-
|
|
84
|
-
return confidenceScore;
|
|
85
|
-
}
|
|
143
|
+
}
|
package/src/main.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.calculateConfidence = void 0;
|
|
3
|
+
exports.calculateConfidence = exports.compareDatasets = exports.compareArrays = void 0;
|
|
4
4
|
const confidence_1 = require("./libs/confidence");
|
|
5
|
+
Object.defineProperty(exports, "compareArrays", { enumerable: true, get: function () { return confidence_1.compareArrays; } });
|
|
6
|
+
Object.defineProperty(exports, "compareDatasets", { enumerable: true, get: function () { return confidence_1.compareDatasets; } });
|
|
5
7
|
Object.defineProperty(exports, "calculateConfidence", { enumerable: true, get: function () { return confidence_1.calculateConfidence; } });
|
package/src/main.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { FPUserDataSet, FPDataSet } from "./types/data";
|
|
2
|
-
import { calculateConfidence } from "./libs/confidence";
|
|
2
|
+
import { compareArrays, compareDatasets, calculateConfidence } from "./libs/confidence";
|
|
3
3
|
|
|
4
|
-
export { type FPUserDataSet, type FPDataSet, calculateConfidence };
|
|
4
|
+
export { type FPUserDataSet, type FPDataSet, compareArrays, compareDatasets, calculateConfidence };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { compareArrays, compareDatasets } from "../src/libs/confidence";
|
|
3
|
+
|
|
4
|
+
const sampleData1 = {"userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0","platform":"Win32","timezone":"America/Chicago","language":"en-US","languages":["en-US","en","es","la"],"cookieEnabled":true,"doNotTrack":"1","hardwareConcurrency":8,"deviceMemory":8,"product":"Gecko","productSub":"20030107","vendor":"Google Inc.","vendorSub":"unknown","appName":"Netscape","appVersion":"5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0","appCodeName":"Mozilla","appMinorVersion":"unknown","buildID":"unknown","plugins":[{"name":"PDF Viewer","description":"Portable Document Format"},{"name":"Chrome PDF Viewer","description":"Portable Document Format"},{"name":"Chromium PDF Viewer","description":"Portable Document Format"},{"name":"Microsoft Edge PDF Viewer","description":"Portable Document Format"},{"name":"WebKit built-in PDF","description":"Portable Document Format"}],"mimeTypes":[{"type":"application/pdf","suffixes":"pdf","description":"Portable Document Format"},{"type":"text/pdf","suffixes":"pdf","description":"Portable Document Format"}],"screen":{"width":1920,"height":1080,"colorDepth":24,"pixelDepth":24,"orientation":{"type":"landscape-primary","angle":0}},"highEntropyValues":{"architecture":"x86","bitness":"64","brands":[{"brand":"Not)A;Brand","version":"8"},{"brand":"Chromium","version":"138"},{"brand":"Microsoft Edge","version":"138"}],"mobile":false,"model":"","platform":"Windows","platformVersion":"19.0.0","uaFullVersion":"138.0.3351.34"}};
|
|
5
|
+
|
|
6
|
+
const sampleData2 = {"userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36","platform":"Win32","timezone":"America/Chicago","language":"en-US","languages":["en-US","en"],"cookieEnabled":true,"hardwareConcurrency":16,"deviceMemory":8,"product":"Gecko","productSub":"20030107","vendor":"Google Inc.","vendorSub":"unknown","appName":"Netscape","appVersion":"5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36","appCodeName":"Mozilla","appMinorVersion":"unknown","buildID":"unknown","plugins":[{"name":"PDF Viewer","description":"Portable Document Format"},{"name":"Chrome PDF Viewer","description":"Portable Document Format"},{"name":"Chromium PDF Viewer","description":"Portable Document Format"},{"name":"Microsoft Edge PDF Viewer","description":"Portable Document Format"},{"name":"WebKit built-in PDF","description":"Portable Document Format"}],"mimeTypes":[{"type":"application/pdf","suffixes":"pdf","description":"Portable Document Format"},{"type":"text/pdf","suffixes":"pdf","description":"Portable Document Format"}],"screen":{"width":1920,"height":1080,"colorDepth":24,"pixelDepth":24,"orientation":{"type":"landscape-primary","angle":0}},"highEntropyValues":{"architecture":"x86","bitness":"64","brands":[{"brand":"Google Chrome","version":"137"},{"brand":"Chromium","version":"137"},{"brand":"Not/A)Brand","version":"24"}],"mobile":false,"model":"","platform":"Windows","platformVersion":"19.0.0","uaFullVersion":"137.0.7151.119"}};
|
|
7
|
+
|
|
8
|
+
describe("Array Comparison", () => {
|
|
9
|
+
it("should compare two identical arrays", () => {
|
|
10
|
+
const arr1 = [1, 2, 3];
|
|
11
|
+
const arr2 = [1, 2, 3];
|
|
12
|
+
const result = compareArrays(arr1, arr2);
|
|
13
|
+
console.log("Result:", result);
|
|
14
|
+
expect(result).toEqual([3, 3]); // 3 fields, 3 matches
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("should compare two different arrays", () => {
|
|
18
|
+
const arr1 = [1, 2, 3];
|
|
19
|
+
const arr2 = [3, 1, 4];
|
|
20
|
+
const result = compareArrays(arr1, arr2);
|
|
21
|
+
console.log("Result:", result);
|
|
22
|
+
expect(result).toEqual([3, 0]); // 3 fields, 0 matches
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("should handle nested arrays", () => {
|
|
26
|
+
const arr1 = [1, [2, 3], 4];
|
|
27
|
+
const arr2 = [1, [2, 3], 5];
|
|
28
|
+
const result = compareArrays(arr1, arr2);
|
|
29
|
+
console.log("Result:", result);
|
|
30
|
+
expect(result).toEqual([4, 3]); // 4 fields, 3 matches
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("should handle empty arrays", () => {
|
|
34
|
+
const arr1: any[] = [];
|
|
35
|
+
const arr2: any[] = [];
|
|
36
|
+
const result = compareArrays(arr1, arr2);
|
|
37
|
+
console.log("Result:", result);
|
|
38
|
+
expect(result).toEqual([0, 0]); // 0 fields, 0 matches
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("should handle arrays with different lengths", () => {
|
|
42
|
+
const arr1 = [1, 2, 3];
|
|
43
|
+
const arr2 = [1, 2];
|
|
44
|
+
const result = compareArrays(arr1, arr2);
|
|
45
|
+
console.log("Result:", result);
|
|
46
|
+
expect(result).toEqual([2, 2]); // 2 fields, 2 matches
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("should handle arrays with undefined values", () => {
|
|
50
|
+
const arr1 = [1, undefined, 3];
|
|
51
|
+
const arr2 = [1, 2, 3];
|
|
52
|
+
const result = compareArrays(arr1, arr2);
|
|
53
|
+
console.log("Result:", result);
|
|
54
|
+
expect(result).toEqual([3, 2]); // 3 fields, 2 matches
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("should handle nested empty arrays", () => {
|
|
58
|
+
const arr1 = [1, [], [[], []], 3];
|
|
59
|
+
const arr2 = [1, [2], [[], []], 3];
|
|
60
|
+
const result = compareArrays(arr1, arr2);
|
|
61
|
+
console.log("Result:", result);
|
|
62
|
+
expect(result).toEqual([3, 2]); // 3 fields, 2 matches
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("should handle arrays of objects", () => {
|
|
66
|
+
const arr1 = [{ a: 1 }, { b: 2 }];
|
|
67
|
+
const arr2 = [{ a: 1 }, { b: 3 }];
|
|
68
|
+
const result = compareArrays(arr1, arr2);
|
|
69
|
+
console.log("Result:", result);
|
|
70
|
+
expect(result).toEqual([2, 1]); // 2 fields, 1 matches
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("should throw an error for max depth exceeded", () => {
|
|
74
|
+
const arr1 = [1, [2, [3, [4, [5, [6]]]]]];
|
|
75
|
+
const arr2 = [1, [2, [3, [4, [5, [6]]]]]];
|
|
76
|
+
expect(() => compareArrays(arr1, arr2, 0)).toThrow("Max depth exceeded");
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe("Dataset Comparison", () => {
|
|
81
|
+
it("should compare two identical datasets", () => {
|
|
82
|
+
const result = compareDatasets(sampleData1, sampleData1);
|
|
83
|
+
console.log("Result:", result);
|
|
84
|
+
expect(result).toEqual([56, 56]); // 20 fields, 20 matches
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("should compare two different datasets", () => {
|
|
88
|
+
const result = compareDatasets(sampleData1, sampleData2);
|
|
89
|
+
console.log("Result:", result);
|
|
90
|
+
expect(result).toEqual([53, 44]); // 20 fields, 10 matches
|
|
91
|
+
});
|
|
92
|
+
});
|
package/tests/confidence.test.ts
CHANGED
|
@@ -89,9 +89,7 @@ describe('Confidence Calculation', () => {
|
|
|
89
89
|
ram: 4096
|
|
90
90
|
},
|
|
91
91
|
timezone: 'Europe/London',
|
|
92
|
-
ip: '178.238.11.6'
|
|
93
|
-
languages: ['en-GB', 'en'],
|
|
94
|
-
userAgent: 'Mozilla/5.0 (compatible; Konqueror/2.2.2-3; Linux)'
|
|
92
|
+
ip: '178.238.11.6'
|
|
95
93
|
};
|
|
96
94
|
const confidence = calculateConfidence(sampleData1, partialData);
|
|
97
95
|
console.log('Confidence for partially similar data:', confidence);
|