underpost 2.6.3 → 2.7.2
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/.dockerignore +13 -13
- package/.env.development +7 -7
- package/.env.production +7 -7
- package/.env.test +7 -7
- package/.github/workflows/publish.yml +26 -0
- package/.nycrc +9 -9
- package/.prettierignore +12 -12
- package/.prettierrc +9 -9
- package/.vscode/extensions.json +72 -72
- package/.vscode/settings.json +100 -99
- package/AUTHORS.md +10 -0
- package/CHANGELOG.md +91 -0
- package/Dockerfile +89 -89
- package/LICENSE +21 -21
- package/README.md +96 -96
- package/bin/db.js +172 -119
- package/bin/deploy.js +582 -626
- package/bin/dns.js +1 -1
- package/bin/file.js +92 -92
- package/bin/index.js +53 -34
- package/bin/install.js +398 -357
- package/bin/shortcut.js +44 -44
- package/bin/ssl.js +65 -61
- package/bin/util.js +182 -182
- package/bin/vs.js +35 -35
- package/conf.js +251 -249
- package/docker-compose.yml +67 -67
- package/jsconfig.json +7 -7
- package/jsdoc.json +32 -32
- package/nodemon.json +6 -6
- package/package.json +137 -128
- package/prometheus.yml +36 -36
- package/setup.sh +24 -24
- package/src/api/core/core.controller.js +69 -69
- package/src/api/core/core.model.js +11 -11
- package/src/api/core/core.router.js +23 -23
- package/src/api/core/core.service.js +29 -29
- package/src/api/crypto/crypto.controller.js +51 -51
- package/src/api/crypto/crypto.model.js +23 -23
- package/src/api/crypto/crypto.router.js +20 -20
- package/src/api/crypto/crypto.service.js +64 -64
- package/src/api/default/default.controller.js +69 -69
- package/src/api/default/default.model.js +20 -20
- package/src/api/default/default.router.js +23 -23
- package/src/api/default/default.service.js +31 -31
- package/src/api/file/file.controller.js +53 -51
- package/src/api/file/file.model.js +19 -19
- package/src/api/file/file.router.js +21 -20
- package/src/api/file/file.service.js +76 -70
- package/src/api/instance/instance.controller.js +69 -69
- package/src/api/instance/instance.model.js +36 -36
- package/src/api/instance/instance.router.js +33 -33
- package/src/api/instance/instance.service.js +48 -48
- package/src/api/test/test.controller.js +59 -59
- package/src/api/test/test.model.js +14 -14
- package/src/api/test/test.router.js +21 -21
- package/src/api/test/test.service.js +35 -35
- package/src/api/user/user.build.js +16 -0
- package/src/api/user/user.controller.js +70 -70
- package/src/api/user/user.model.js +65 -65
- package/src/api/user/user.router.js +345 -345
- package/src/api/user/user.service.js +479 -479
- package/src/api.js +23 -23
- package/src/client/Default.index.js +40 -40
- package/src/client/components/core/Account.js +290 -290
- package/src/client/components/core/AgGrid.js +160 -160
- package/src/client/components/core/Auth.js +19 -19
- package/src/client/components/core/Badge.js +32 -32
- package/src/client/components/core/BlockChain.js +41 -41
- package/src/client/components/core/Blog.js +9 -9
- package/src/client/components/core/BtnIcon.js +101 -94
- package/src/client/components/core/CalendarCore.js +458 -319
- package/src/client/components/core/Chat.js +64 -64
- package/src/client/components/core/ColorPalette.js +5267 -5267
- package/src/client/components/core/CommonJs.js +735 -732
- package/src/client/components/core/Content.js +193 -49
- package/src/client/components/core/Css.js +1064 -1027
- package/src/client/components/core/CssCore.js +817 -796
- package/src/client/components/core/D3Chart.js +44 -44
- package/src/client/components/core/Docs.js +229 -229
- package/src/client/components/core/DropDown.js +164 -164
- package/src/client/components/core/EventsUI.js +46 -54
- package/src/client/components/core/FileExplorer.js +699 -624
- package/src/client/components/core/FullScreen.js +45 -45
- package/src/client/components/core/Input.js +346 -259
- package/src/client/components/core/JoyStick.js +77 -77
- package/src/client/components/core/Keyboard.js +73 -73
- package/src/client/components/core/LoadingAnimation.js +179 -157
- package/src/client/components/core/LogIn.js +187 -181
- package/src/client/components/core/LogOut.js +58 -52
- package/src/client/components/core/Logger.js +26 -26
- package/src/client/components/core/Modal.js +1612 -1596
- package/src/client/components/core/NotificationManager.js +84 -84
- package/src/client/components/core/Panel.js +613 -413
- package/src/client/components/core/PanelForm.js +468 -0
- package/src/client/components/core/Polyhedron.js +162 -162
- package/src/client/components/core/Recover.js +204 -204
- package/src/client/components/core/Responsive.js +53 -53
- package/src/client/components/core/RichText.js +51 -27
- package/src/client/components/core/Router.js +76 -77
- package/src/client/components/core/Scroll.js +34 -0
- package/src/client/components/core/SignUp.js +125 -125
- package/src/client/components/core/SocketIo.js +72 -72
- package/src/client/components/core/Stream.js +113 -113
- package/src/client/components/core/ToggleSwitch.js +87 -87
- package/src/client/components/core/ToolTip.js +26 -26
- package/src/client/components/core/Translate.js +437 -408
- package/src/client/components/core/Validator.js +100 -100
- package/src/client/components/core/VanillaJs.js +460 -457
- package/src/client/components/core/Wallet.js +106 -106
- package/src/client/components/core/Webhook.js +25 -25
- package/src/client/components/core/Worker.js +272 -272
- package/src/client/components/default/CommonDefault.js +29 -29
- package/src/client/components/default/CssDefault.js +13 -13
- package/src/client/components/default/ElementsDefault.js +38 -38
- package/src/client/components/default/LogInDefault.js +41 -41
- package/src/client/components/default/LogOutDefault.js +28 -28
- package/src/client/components/default/MenuDefault.js +389 -389
- package/src/client/components/default/RoutesDefault.js +48 -48
- package/src/client/components/default/SettingsDefault.js +16 -16
- package/src/client/components/default/SignUpDefault.js +9 -9
- package/src/client/components/default/SocketIoDefault.js +54 -54
- package/src/client/components/default/TranslateDefault.js +7 -7
- package/src/client/public/default/assets/mailer/api-user-check.png +0 -0
- package/src/client/public/default/assets/mailer/api-user-invalid-token.png +0 -0
- package/src/client/public/default/assets/mailer/api-user-recover.png +0 -0
- package/src/client/public/default/browserconfig.xml +11 -11
- package/src/client/public/default/manifest.webmanifest +68 -68
- package/src/client/public/default/plantuml/client-conf.svg +1 -0
- package/src/client/public/default/plantuml/client-schema.svg +1 -0
- package/src/client/public/default/plantuml/cron-conf.svg +1 -0
- package/src/client/public/default/plantuml/cron-schema.svg +1 -0
- package/src/client/public/default/plantuml/server-conf.svg +1 -0
- package/src/client/public/default/plantuml/server-schema.svg +1 -0
- package/src/client/public/default/plantuml/ssr-conf.svg +1 -0
- package/src/client/public/default/plantuml/ssr-schema.svg +1 -0
- package/src/client/public/default/sitemap +147 -147
- package/src/client/public/default/yandex-browser-manifest.json +8 -8
- package/src/client/public/doc/sitemap +147 -147
- package/src/client/public/test/sitemap +147 -147
- package/src/client/services/core/core.service.js +170 -152
- package/src/client/services/crypto/crypto.service.js +70 -70
- package/src/client/services/default/default.management.js +345 -345
- package/src/client/services/default/default.service.js +89 -89
- package/src/client/services/file/file.service.js +70 -70
- package/src/client/services/instance/instance.management.js +74 -74
- package/src/client/services/instance/instance.service.js +89 -89
- package/src/client/services/test/test.service.js +70 -70
- package/src/client/services/user/user.management.js +50 -50
- package/src/client/services/user/user.service.js +89 -89
- package/src/client/ssr/Render.js +16 -16
- package/src/client/ssr/body-components/CacheControl.js +114 -113
- package/src/client/ssr/body-components/DefaultSplashScreen.js +79 -79
- package/src/client/ssr/email-components/DefaultRecoverEmail.js +21 -21
- package/src/client/ssr/email-components/DefaultVerifyEmail.js +17 -17
- package/src/client/ssr/head-components/Css.js +241 -241
- package/src/client/ssr/head-components/DefaultScripts.js +3 -3
- package/src/client/ssr/head-components/Microdata.js +11 -11
- package/src/client/ssr/head-components/Production.js +1 -1
- package/src/client/ssr/head-components/PwaDefault.js +59 -59
- package/src/client/ssr/head-components/Seo.js +14 -14
- package/src/client/sw/default.sw.js +201 -201
- package/src/client/sw/template.sw.js +84 -84
- package/src/client.build.js +22 -22
- package/src/client.dev.js +21 -21
- package/src/cron.js +25 -25
- package/src/db/DataBaseProvider.js +34 -34
- package/src/db/mariadb/MariaDB.js +33 -33
- package/src/db/mongo/MongooseDB.js +46 -46
- package/src/dns.js +22 -22
- package/src/index.js +42 -0
- package/src/mailer/EmailRender.js +69 -69
- package/src/mailer/MailerProvider.js +96 -96
- package/src/proxy.js +22 -22
- package/src/runtime/lampp/Lampp.js +69 -44
- package/src/runtime/nginx/Nginx.js +3 -3
- package/src/runtime/xampp/Xampp.js +49 -49
- package/src/server/auth.js +235 -204
- package/src/server/backup.js +101 -84
- package/src/server/client-build-live.js +72 -72
- package/src/server/client-build.js +705 -699
- package/src/server/client-dev-server.js +60 -58
- package/src/server/client-formatted.js +48 -48
- package/src/server/client-icons.js +149 -150
- package/src/server/conf.js +860 -611
- package/src/server/dns.js +98 -87
- package/src/server/downloader.js +42 -42
- package/src/server/logger.js +180 -135
- package/src/server/network.js +122 -122
- package/src/server/peer.js +33 -33
- package/src/server/process.js +66 -66
- package/src/server/prompt-optimizer.js +28 -0
- package/src/server/proxy.js +118 -118
- package/src/server/runtime.js +444 -393
- package/src/server/ssl.js +109 -107
- package/src/server.js +25 -25
- package/src/ws/IoInterface.js +45 -45
- package/src/ws/IoServer.js +39 -39
- package/src/ws/core/channels/core.ws.chat.js +23 -23
- package/src/ws/core/channels/core.ws.mailer.js +35 -35
- package/src/ws/core/channels/core.ws.stream.js +31 -31
- package/src/ws/core/core.ws.connection.js +28 -28
- package/src/ws/core/core.ws.emit.js +14 -14
- package/src/ws/core/core.ws.server.js +24 -24
- package/src/ws/core/management/core.ws.chat.js +8 -8
- package/src/ws/core/management/core.ws.mailer.js +16 -16
- package/src/ws/core/management/core.ws.stream.js +8 -8
- package/src/ws/default/channels/default.ws.main.js +16 -16
- package/src/ws/default/default.ws.connection.js +22 -22
- package/src/ws/default/default.ws.emit.js +14 -14
- package/src/ws/default/default.ws.server.js +20 -20
- package/src/ws/default/management/default.ws.main.js +8 -8
- package/startup.js +11 -11
- package/supervisord-openssh-server.conf +4 -4
- package/test/api.test.js +60 -60
- package/bin/help.js +0 -110
|
@@ -1,732 +1,735 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Common JavaScript functions
|
|
3
|
-
* @module src/client/components/core/CommonJs.js
|
|
4
|
-
* @namespace CommonJS
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* The function `s4` generates a random hexadecimal string with a length of 4 characters.
|
|
9
|
-
* @memberof CommonJS
|
|
10
|
-
*/
|
|
11
|
-
const s4 = () => (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* The `range` function generates an array of numbers within a specified range, handling both ascending
|
|
15
|
-
* and descending ranges.
|
|
16
|
-
* @param start - The `start` parameter in the `range` function represents the starting value of the
|
|
17
|
-
* range you want to generate.
|
|
18
|
-
* @param end - The `end` parameter in the `range` function represents the ending value of the range
|
|
19
|
-
* that you want to generate.
|
|
20
|
-
* @returns The `range` function returns an array containing a range of numbers starting from the
|
|
21
|
-
* `start` value up to the `end` value (inclusive). If `end` is less than `start`, it will recursively
|
|
22
|
-
* call the `range` function with the arguments swapped and then reverse the resulting array.
|
|
23
|
-
* @memberof CommonJS
|
|
24
|
-
*/
|
|
25
|
-
const range = (start, end) => {
|
|
26
|
-
return end < start
|
|
27
|
-
? range(end, start).reverse()
|
|
28
|
-
: Array.apply(0, Array(end - start + 1)).map((element, index) => index + start);
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* The `getId` function generates a unique identifier based on an array of objects or keys.
|
|
33
|
-
* @param arr - The `arr` parameter in the `getId` function is an array of objects or an object. If it
|
|
34
|
-
* is an object, the function converts it into an array of objects where each object has a key
|
|
35
|
-
* specified by the `keyId` parameter.
|
|
36
|
-
* @param
|
|
37
|
-
* the generated ID. It is optional and by default is an empty string. You can provide a suffix to be
|
|
38
|
-
* appended to the generated ID if needed.
|
|
39
|
-
* @param
|
|
40
|
-
* array elements that contains the unique identifier (ID) for each element. By default, the function
|
|
41
|
-
* assumes that the ID is stored in a property named `'id'`, but you can customize this by providing
|
|
42
|
-
* @returns The `getId` function returns a unique identifier `_id` based on the input array `arr`,
|
|
43
|
-
* optional `suffix`, and `keyId`.
|
|
44
|
-
* @memberof CommonJS
|
|
45
|
-
*/
|
|
46
|
-
const getId = (arr, suffix = '', keyId = 'id') => {
|
|
47
|
-
if (!Array.isArray(arr) && typeof arr === 'object')
|
|
48
|
-
arr = Object.keys(arr).map((id) => {
|
|
49
|
-
const idElement = {};
|
|
50
|
-
idElement[keyId] = id;
|
|
51
|
-
return idElement;
|
|
52
|
-
});
|
|
53
|
-
let _id;
|
|
54
|
-
while (arr.find((element) => element[keyId] === _id) || !_id)
|
|
55
|
-
_id = suffix + (s4() + s4() + s4() + s4() + s4()).slice(1);
|
|
56
|
-
return _id;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* The function `random` generates a random integer within a specified range.
|
|
61
|
-
* @param min - The `min` parameter represents the minimum value of the range from which you want to
|
|
62
|
-
* generate a random number.
|
|
63
|
-
* @param max - The `max` parameter in the `random` function represents the maximum value that you want
|
|
64
|
-
* to generate a random number up to.
|
|
65
|
-
* @memberof CommonJS
|
|
66
|
-
*/
|
|
67
|
-
const random = (min, max) => Math.floor(Math.random() * (max - min + 1) + min); // The maximum is inclusive and the minimum is inclusive
|
|
68
|
-
|
|
69
|
-
const randomHexColor = () => '#' + ((Math.random() * 0xffffff) << 0).toString(16).padStart(6, '0');
|
|
70
|
-
|
|
71
|
-
const getRawCsvFromArray = (array) =>
|
|
72
|
-
array[0]
|
|
73
|
-
? Object.keys(array[0]).join(';') +
|
|
74
|
-
'\r\n' +
|
|
75
|
-
array
|
|
76
|
-
.map((x) => {
|
|
77
|
-
return (
|
|
78
|
-
Object.keys(x)
|
|
79
|
-
.map((attr) => x[attr])
|
|
80
|
-
.join(';') + '\r\n'
|
|
81
|
-
);
|
|
82
|
-
})
|
|
83
|
-
.join('')
|
|
84
|
-
: '';
|
|
85
|
-
|
|
86
|
-
const newInstance = (obj) => {
|
|
87
|
-
// structuredClone() 2022 ES6 feature
|
|
88
|
-
try {
|
|
89
|
-
return JSON.parse(JSON.stringify(obj));
|
|
90
|
-
} catch (error) {
|
|
91
|
-
return { error: error.message };
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const cap = (str) =>
|
|
96
|
-
str
|
|
97
|
-
.toLowerCase()
|
|
98
|
-
.split(' ')
|
|
99
|
-
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
100
|
-
.join(' ');
|
|
101
|
-
|
|
102
|
-
const capFirst = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
103
|
-
|
|
104
|
-
const uniqueArray = (arr) => arr.filter((item, pos) => arr.indexOf(item) == pos);
|
|
105
|
-
|
|
106
|
-
const orderArrayFromAttrInt = (arr, attr, type) =>
|
|
107
|
-
// type -> true asc
|
|
108
|
-
// type -> false desc
|
|
109
|
-
type === 'asc' ? arr.sort((a, b) => a[attr] - b[attr]) : arr.sort((a, b) => b[attr] - a[attr]);
|
|
110
|
-
|
|
111
|
-
const getRandomPoint = (suffix, pointsArray) => {
|
|
112
|
-
const point = pointsArray[random(0, pointsArray.length - 1)];
|
|
113
|
-
const returnPoint = {};
|
|
114
|
-
returnPoint['x' + suffix] = point[0];
|
|
115
|
-
returnPoint['y' + suffix] = point[1];
|
|
116
|
-
return returnPoint;
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
const getYouTubeID = (url) => {
|
|
120
|
-
const p =
|
|
121
|
-
/^(?:https?:\/\/)?(?:m\.|www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/;
|
|
122
|
-
if (url.match(p)) return url.match(p)[1];
|
|
123
|
-
return false;
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
const timer = (ms) => new Promise((res) => setTimeout(res, ms));
|
|
127
|
-
|
|
128
|
-
const reOrderIntArray = (array) => {
|
|
129
|
-
/* shuffle */
|
|
130
|
-
let currentIndex = array.length,
|
|
131
|
-
randomIndex;
|
|
132
|
-
|
|
133
|
-
// While there remain elements to shuffle.
|
|
134
|
-
while (currentIndex != 0) {
|
|
135
|
-
// Pick a remaining element.
|
|
136
|
-
randomIndex = Math.floor(Math.random() * currentIndex);
|
|
137
|
-
currentIndex--;
|
|
138
|
-
|
|
139
|
-
// And swap it with the current element.
|
|
140
|
-
[array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return array;
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
const orderAbc = (arr, attr) =>
|
|
147
|
-
arr.sort((a, b) => {
|
|
148
|
-
if (attr) {
|
|
149
|
-
if (a[attr] < b[attr]) {
|
|
150
|
-
return -1;
|
|
151
|
-
}
|
|
152
|
-
if (a[attr] > b[attr]) {
|
|
153
|
-
return 1;
|
|
154
|
-
}
|
|
155
|
-
} else {
|
|
156
|
-
if (a < b) {
|
|
157
|
-
return -1;
|
|
158
|
-
}
|
|
159
|
-
if (a > b) {
|
|
160
|
-
return 1;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
return 0;
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
const JSONmatrix = (matrix) => {
|
|
167
|
-
if (Array.isArray(matrix))
|
|
168
|
-
return `[\r\n${matrix
|
|
169
|
-
.map((x, i) => ` ` + JSON.stringify(x) + (i === matrix.length - 1 ? '' : ',') + '\r\n')
|
|
170
|
-
.join('')}]`;
|
|
171
|
-
else
|
|
172
|
-
return `[\r\n${Object.keys(matrix)
|
|
173
|
-
.map((x, i) => ` ` + JSON.stringify(Object.values(matrix[x])) + (i === matrix.length - 1 ? '' : ',') + '\r\n')
|
|
174
|
-
.join('')}]`;
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
const getDistance = (x1, y1, x2, y2) => {
|
|
178
|
-
const disX = Math.abs(x2 - x1);
|
|
179
|
-
const disY = Math.abs(y2 - y1);
|
|
180
|
-
return Math.sqrt(disX * disX + disY * disY);
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
const setPad = (num, padValue, targetLength, endPad, separator) => {
|
|
184
|
-
separator = separator ? separator : '.';
|
|
185
|
-
let str = String(num).split(separator);
|
|
186
|
-
let removeSeparator = false;
|
|
187
|
-
if (!str[1]) {
|
|
188
|
-
str[1] = '';
|
|
189
|
-
if (!endPad) removeSeparator = true;
|
|
190
|
-
}
|
|
191
|
-
while (endPad ? str[1].length < targetLength : str[0].length < targetLength)
|
|
192
|
-
endPad ? (str[1] = str[1] + padValue) : (str[0] = padValue + str[0]);
|
|
193
|
-
return removeSeparator ? str.join(separator).replace(separator, '') : str.join(separator);
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Decimal setting of a number.
|
|
198
|
-
*
|
|
199
|
-
* @param {String} type The type of setting.
|
|
200
|
-
* @param {Number} value The number.
|
|
201
|
-
* @param {Integer} exp The exponent (the log 10 of the base fit).
|
|
202
|
-
* @returns {Number} The adjusted value.
|
|
203
|
-
* @memberof CommonJS
|
|
204
|
-
*/
|
|
205
|
-
const decimalAdjust = (type, value, exp) => {
|
|
206
|
-
if (typeof exp === 'undefined' || +exp === 0) {
|
|
207
|
-
return Math[type](value);
|
|
208
|
-
}
|
|
209
|
-
value = +value;
|
|
210
|
-
exp = +exp;
|
|
211
|
-
|
|
212
|
-
if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
|
|
213
|
-
return NaN;
|
|
214
|
-
}
|
|
215
|
-
// Shift
|
|
216
|
-
value = value.toString().split('e');
|
|
217
|
-
value = Math[type](+(value[0] + 'e' + (value[1] ? +value[1] - exp : -exp)));
|
|
218
|
-
// Shift back
|
|
219
|
-
value = value.toString().split('e');
|
|
220
|
-
return +(value[0] + 'e' + (value[1] ? +value[1] + exp : exp));
|
|
221
|
-
|
|
222
|
-
// https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Math/round
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
const floatRound = (v, d) => parseFloat(parseFloat(v).toFixed(d));
|
|
226
|
-
|
|
227
|
-
// Decimal round
|
|
228
|
-
|
|
229
|
-
const round10 = (value, exp) => {
|
|
230
|
-
return decimalAdjust('round', value, exp);
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
// Decimal floor
|
|
234
|
-
|
|
235
|
-
const floor10 = (value, exp) => {
|
|
236
|
-
return decimalAdjust('floor', value, exp);
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
// Decimal ceil
|
|
240
|
-
|
|
241
|
-
const ceil10 = (value, exp) => {
|
|
242
|
-
return decimalAdjust('ceil', value, exp);
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
// // Round
|
|
246
|
-
// round10(55.55, -1); // 55.6
|
|
247
|
-
// round10(55.549, -1); // 55.5
|
|
248
|
-
// round10(55, 1); // 60
|
|
249
|
-
// round10(54.9, 1); // 50
|
|
250
|
-
// round10(-55.55, -1); // -55.5
|
|
251
|
-
// round10(-55.551, -1); // -55.6
|
|
252
|
-
// round10(-55, 1); // -50
|
|
253
|
-
// round10(-55.1, 1); // -60
|
|
254
|
-
// round10(1.005, -2); // 1.01 -- compare this with round(1.005*100)/100 above
|
|
255
|
-
// // Floor
|
|
256
|
-
// floor10(55.59, -1); // 55.5
|
|
257
|
-
// floor10(59, 1); // 50
|
|
258
|
-
// floor10(-55.51, -1); // -55.6
|
|
259
|
-
// floor10(-51, 1); // -60
|
|
260
|
-
// // Ceil
|
|
261
|
-
// ceil10(55.51, -1); // 55.6
|
|
262
|
-
// ceil10(51, 1); // 60
|
|
263
|
-
// ceil10(-55.59, -1); // -55.5
|
|
264
|
-
// ceil10(-59, 1); // -50
|
|
265
|
-
|
|
266
|
-
function objectEquals(x, y) {
|
|
267
|
-
// TODO:
|
|
268
|
-
// https://www.npmjs.com/package/deep-equal
|
|
269
|
-
// https://www.npmjs.com/package/fast-deep-equal
|
|
270
|
-
const ok = Object.keys,
|
|
271
|
-
tx = typeof x,
|
|
272
|
-
ty = typeof y;
|
|
273
|
-
return x && y && tx === 'object' && tx === ty
|
|
274
|
-
? ok(x).length === ok(y).length && ok(x).every((key) => objectEquals(x[key], y[key]))
|
|
275
|
-
: x === y;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
function insertTransitionCoordinates(coordinates, transitionFactor) {
|
|
279
|
-
// Create a new array to store the resulting coordinates
|
|
280
|
-
const coordinatesWithTransition = [];
|
|
281
|
-
|
|
282
|
-
// Iterate over the coordinates array
|
|
283
|
-
for (let i = 0; i < coordinates.length - 1; i++) {
|
|
284
|
-
const [x1, y1] = coordinates[i];
|
|
285
|
-
const [x2, y2] = coordinates[i + 1];
|
|
286
|
-
|
|
287
|
-
// Add the initial integer coordinate to the new array
|
|
288
|
-
coordinatesWithTransition.push([x1, y1]);
|
|
289
|
-
|
|
290
|
-
// Calculate the increments for each coordinate
|
|
291
|
-
const incrementX = (x2 - x1) / transitionFactor;
|
|
292
|
-
const incrementY = (y2 - y1) / transitionFactor;
|
|
293
|
-
|
|
294
|
-
// Add the intermediate coordinates
|
|
295
|
-
for (let j = 1; j <= transitionFactor - 1; j++) {
|
|
296
|
-
const xIntermediate = x1 + incrementX * j;
|
|
297
|
-
const yIntermediate = y1 + incrementY * j;
|
|
298
|
-
coordinatesWithTransition.push([xIntermediate, yIntermediate]);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// Add the last integer coordinate to the new array
|
|
303
|
-
coordinatesWithTransition.push(coordinates[coordinates.length - 1]);
|
|
304
|
-
|
|
305
|
-
// Now, coordinatesWithTransition contains the coordinates with transition
|
|
306
|
-
return coordinatesWithTransition;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const getIsoDate = (date) => date.toISOString().slice(0, -5).replace('T', ' ');
|
|
310
|
-
|
|
311
|
-
const clearTerminalStringColor = (str) => str.replace(/\x1b\[[0-9;]*m/g, '');
|
|
312
|
-
|
|
313
|
-
function getValueFromJoinString(obj, path, join = '.') {
|
|
314
|
-
// Split the path string into an array of attribute names
|
|
315
|
-
const attributes = path.split(join);
|
|
316
|
-
|
|
317
|
-
// Iterate through the attributes to access the desired value
|
|
318
|
-
let value = obj;
|
|
319
|
-
for (let i = 0; i < attributes.length; i++) {
|
|
320
|
-
value = value[attributes[i]];
|
|
321
|
-
|
|
322
|
-
// Check if the value is null or undefined at each step
|
|
323
|
-
if (value === null || value === undefined) {
|
|
324
|
-
// If the value is null or undefined, stop the iteration
|
|
325
|
-
break;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
return value;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
function getDirection(options = { x1: 1, y1: 1, x2: 1, y2: 1, radians: 1 }) {
|
|
333
|
-
const { x1, y1, x2, y2, radians } = options;
|
|
334
|
-
// Calculate the angle in radians
|
|
335
|
-
const angle = radians !== undefined ? radians : Math.atan2(y2 - y1, x2 - x1);
|
|
336
|
-
|
|
337
|
-
// Convert the angle to degrees
|
|
338
|
-
let degrees = angle * (180 / Math.PI);
|
|
339
|
-
|
|
340
|
-
// Adjust the angle to be positive
|
|
341
|
-
if (degrees < 0) {
|
|
342
|
-
degrees += 360;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// 45 / 2 = 22.5
|
|
346
|
-
// formula -> 22.5 + (45*n)
|
|
347
|
-
|
|
348
|
-
// Map the angle to one of the eight directions
|
|
349
|
-
let direction;
|
|
350
|
-
if (degrees >= 337.5 || degrees < 22.5) {
|
|
351
|
-
// direction = 'right';
|
|
352
|
-
// direction = 'East';
|
|
353
|
-
direction = 'e';
|
|
354
|
-
} else if (degrees >= 22.5 && degrees < 67.5) {
|
|
355
|
-
// direction = 'up-right';
|
|
356
|
-
// direction = 'South East';
|
|
357
|
-
direction = 'se';
|
|
358
|
-
} else if (degrees >= 67.5 && degrees < 112.5) {
|
|
359
|
-
// direction = 'up';
|
|
360
|
-
// direction = 'South';
|
|
361
|
-
direction = 's';
|
|
362
|
-
} else if (degrees >= 112.5 && degrees < 157.5) {
|
|
363
|
-
// direction = 'up-left';
|
|
364
|
-
// direction = 'South West';
|
|
365
|
-
direction = 'sw';
|
|
366
|
-
} else if (degrees >= 157.5 && degrees < 202.5) {
|
|
367
|
-
// direction = 'left';
|
|
368
|
-
// direction = 'West';
|
|
369
|
-
direction = 'w';
|
|
370
|
-
} else if (degrees >= 202.5 && degrees < 247.5) {
|
|
371
|
-
// direction = 'down-left';
|
|
372
|
-
// direction = 'North West';
|
|
373
|
-
direction = 'nw';
|
|
374
|
-
} else if (degrees >= 247.5 && degrees < 292.5) {
|
|
375
|
-
// direction = 'down';
|
|
376
|
-
// direction = 'North';
|
|
377
|
-
direction = 'n';
|
|
378
|
-
} else if (degrees >= 292.5 && degrees < 337.5) {
|
|
379
|
-
// direction = 'down-right';
|
|
380
|
-
// direction = 'North East';
|
|
381
|
-
direction = 'ne';
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
return direction;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// Function to amplify a matrix in horizontal and vertical directions
|
|
388
|
-
const amplifyMatrix = (matrix, factor) => {
|
|
389
|
-
// Get the original dimensions of the matrix
|
|
390
|
-
const rows = matrix.length;
|
|
391
|
-
const cols = matrix[0].length;
|
|
392
|
-
|
|
393
|
-
// Create a new amplified matrix filled with zeros
|
|
394
|
-
const amplifiedMatrix = Array.from({ length: rows * factor }, () => Array(cols * factor).fill(0));
|
|
395
|
-
|
|
396
|
-
// Iterate over the original matrix
|
|
397
|
-
for (let i = 0; i < rows; i++) {
|
|
398
|
-
for (let j = 0; j < cols; j++) {
|
|
399
|
-
// Get the current value in the original matrix
|
|
400
|
-
const originalValue = matrix[i][j];
|
|
401
|
-
|
|
402
|
-
// Amplify in horizontal and vertical directions
|
|
403
|
-
for (let x = 0; x < factor; x++) {
|
|
404
|
-
for (let y = 0; y < factor; y++) {
|
|
405
|
-
// Assign the amplified value to the new matrix
|
|
406
|
-
amplifiedMatrix[i * factor + x][j * factor + y] = originalValue;
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
return amplifiedMatrix;
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
// Function to reduce a matrix by a factor in horizontal and vertical directions
|
|
416
|
-
const reduceMatrix = (matrix, factor) => {
|
|
417
|
-
// Get the original dimensions of the matrix
|
|
418
|
-
const rows = matrix.length;
|
|
419
|
-
const cols = matrix[0].length;
|
|
420
|
-
|
|
421
|
-
// Calculate the dimensions of the reduced matrix
|
|
422
|
-
const reducedRows = Math.ceil(rows / factor);
|
|
423
|
-
const reducedCols = Math.ceil(cols / factor);
|
|
424
|
-
|
|
425
|
-
// Create a new reduced matrix filled with zeros
|
|
426
|
-
const reducedMatrix = Array.from({ length: reducedRows }, () => Array(reducedCols).fill(0));
|
|
427
|
-
|
|
428
|
-
// Iterate over the original matrix
|
|
429
|
-
for (let i = 0; i < reducedRows; i++) {
|
|
430
|
-
for (let j = 0; j < reducedCols; j++) {
|
|
431
|
-
// Calculate the sum of values in the corresponding block of the original matrix
|
|
432
|
-
let sum = 0;
|
|
433
|
-
|
|
434
|
-
for (let x = 0; x < factor; x++) {
|
|
435
|
-
for (let y = 0; y < factor; y++) {
|
|
436
|
-
// Safely access the original matrix considering the boundaries
|
|
437
|
-
const rowIndex = i * factor + x;
|
|
438
|
-
const colIndex = j * factor + y;
|
|
439
|
-
|
|
440
|
-
if (rowIndex < rows && colIndex < cols) {
|
|
441
|
-
sum += matrix[rowIndex][colIndex];
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// Calculate the average value for the reduced matrix
|
|
447
|
-
reducedMatrix[i][j] = sum / Math.min(factor * factor, rows * cols);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
return reducedMatrix;
|
|
452
|
-
};
|
|
453
|
-
|
|
454
|
-
const mergeMatrices = (input) => {
|
|
455
|
-
const rows = Object.keys(input).reduce((acc, key) => {
|
|
456
|
-
const rowData = Object.keys(input[key]).reduce((rowAcc, subKey) => {
|
|
457
|
-
const subArray = input[key][subKey];
|
|
458
|
-
const rowIndex = parseInt(key, 10) * subArray.length;
|
|
459
|
-
subArray.forEach((subRow, subRowIndex) => {
|
|
460
|
-
const fullRowIndex = rowIndex + subRowIndex;
|
|
461
|
-
if (!rowAcc[fullRowIndex]) {
|
|
462
|
-
rowAcc[fullRowIndex] = [];
|
|
463
|
-
}
|
|
464
|
-
rowAcc[fullRowIndex] = rowAcc[fullRowIndex].concat(subRow);
|
|
465
|
-
});
|
|
466
|
-
return rowAcc;
|
|
467
|
-
}, []);
|
|
468
|
-
acc = acc.concat(rowData);
|
|
469
|
-
return acc;
|
|
470
|
-
}, []);
|
|
471
|
-
|
|
472
|
-
// Remove empty rows
|
|
473
|
-
const nonEmptyRows = rows.filter((row) => row.some((cell) => cell !== undefined));
|
|
474
|
-
|
|
475
|
-
// Remove empty columns
|
|
476
|
-
const transpose = nonEmptyRows[0].map((col, i) => nonEmptyRows.map((row) => row[i]));
|
|
477
|
-
const nonEmptyColumns = transpose.filter((col) => col.some((cell) => cell !== undefined));
|
|
478
|
-
|
|
479
|
-
// Transpose back to rows
|
|
480
|
-
const result = nonEmptyColumns[0].map((row, i) => nonEmptyColumns.map((col) => col[i]));
|
|
481
|
-
|
|
482
|
-
return result;
|
|
483
|
-
};
|
|
484
|
-
|
|
485
|
-
const titleFormatted = (str) => cap(str.trim().replaceAll('/', '').replaceAll('-', ' '));
|
|
486
|
-
|
|
487
|
-
const getSubpaths = (path) =>
|
|
488
|
-
path
|
|
489
|
-
.split('/')
|
|
490
|
-
.filter(Boolean)
|
|
491
|
-
.map((_, i, segments) => `/${segments.slice(0, i + 1).join('/')}`);
|
|
492
|
-
|
|
493
|
-
function formatBytes(bytes, decimals = 2) {
|
|
494
|
-
if (!+bytes) return '0 Bytes';
|
|
495
|
-
|
|
496
|
-
const k = 1024;
|
|
497
|
-
const dm = decimals < 0 ? 0 : decimals;
|
|
498
|
-
const sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
|
|
499
|
-
|
|
500
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
501
|
-
|
|
502
|
-
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
function getDirname(path) {
|
|
506
|
-
// Split the path based on the path separator
|
|
507
|
-
const parts = path.split(/[/|\\]/);
|
|
508
|
-
|
|
509
|
-
// Remove the last element (filename)
|
|
510
|
-
parts.pop();
|
|
511
|
-
|
|
512
|
-
// If the path ends with a separator, remove the empty element
|
|
513
|
-
if (parts[parts.length - 1] === '') {
|
|
514
|
-
parts.pop();
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
// Join the remaining parts to get the directory path
|
|
518
|
-
return parts.join('/'); // Adjust separator if needed for Windows ('\')
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
const isDayValid = (day) => {
|
|
522
|
-
const date = new Date();
|
|
523
|
-
date.setDate(day);
|
|
524
|
-
return date.getDate() === day;
|
|
525
|
-
};
|
|
526
|
-
|
|
527
|
-
const isMonthValid = (month) => {
|
|
528
|
-
const date = new Date();
|
|
529
|
-
date.setMonth(month - 1);
|
|
530
|
-
return date.getMonth() === month - 1;
|
|
531
|
-
};
|
|
532
|
-
|
|
533
|
-
const isValidDate = (day, month, year) => {
|
|
534
|
-
if (!isDayValid(day) || !isMonthValid(month)) {
|
|
535
|
-
return false;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
const date = new Date(year, month - 1, day);
|
|
539
|
-
return !isNaN(date.getTime());
|
|
540
|
-
};
|
|
541
|
-
|
|
542
|
-
const isValidFormat = (value, format) => {
|
|
543
|
-
try {
|
|
544
|
-
switch (format) {
|
|
545
|
-
case 'ALPHANUMERIC':
|
|
546
|
-
return /^[a-z0-9]+$/i.test(value);
|
|
547
|
-
case 'DDMMYYYY': {
|
|
548
|
-
const day = parseInt(value.substring(0, 2));
|
|
549
|
-
const month = parseInt(value.substring(2, 4));
|
|
550
|
-
const year = parseInt(value.substring(4));
|
|
551
|
-
return isValidDate(day, month, year);
|
|
552
|
-
}
|
|
553
|
-
case 'YYYYDDMM': {
|
|
554
|
-
const day = parseInt(value.substring(4, 6));
|
|
555
|
-
const month = parseInt(value.substring(6, 8));
|
|
556
|
-
const year = parseInt(value.substring(0, 4));
|
|
557
|
-
return isValidDate(day, month, year);
|
|
558
|
-
}
|
|
559
|
-
case 'DD-MM-YYYY': {
|
|
560
|
-
value = value.split('-');
|
|
561
|
-
const day = parseInt(value[0]);
|
|
562
|
-
const month = parseInt(value[1]);
|
|
563
|
-
const year = parseInt(value[2]);
|
|
564
|
-
return isValidDate(day, month, year);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
default:
|
|
568
|
-
return false;
|
|
569
|
-
}
|
|
570
|
-
} catch (error) {
|
|
571
|
-
console.error(error);
|
|
572
|
-
return false;
|
|
573
|
-
}
|
|
574
|
-
};
|
|
575
|
-
|
|
576
|
-
/**
|
|
577
|
-
* Returns the time difference between UTC time and local time, in minutes.
|
|
578
|
-
* @memberof CommonJS
|
|
579
|
-
*/
|
|
580
|
-
const getTimezoneOffset = () => new Date().getTimezoneOffset();
|
|
581
|
-
|
|
582
|
-
// https://unicode-explorer.com/c/<unicode>
|
|
583
|
-
// example: https://unicode-explorer.com/c/0000
|
|
584
|
-
function cleanString(string) {
|
|
585
|
-
// Define the problematic escape sequences unicode characters to remove with descriptions
|
|
586
|
-
const problematicCharacters = [
|
|
587
|
-
// '\u0000', // Null character (Represents absence of a character) not work
|
|
588
|
-
'\u0008', // Backspace character
|
|
589
|
-
'\u0002', // Start of Text (STX) character
|
|
590
|
-
'\u0009', // Horizontal Tab character
|
|
591
|
-
'\u000B', // Vertical Tab character
|
|
592
|
-
'\u000C', // Form Feed character
|
|
593
|
-
'\u000D', // Carriage Return character
|
|
594
|
-
'\u001D', // Group Separator (GS) character
|
|
595
|
-
'\u001F', // Substitution character
|
|
596
|
-
// '\u0020', // Space character
|
|
597
|
-
'\u200B', // Zero Width Space character
|
|
598
|
-
'\u200C', // Zero Width Non-Joiner character
|
|
599
|
-
'\u200D', // Zero Width Joiner character
|
|
600
|
-
'\u200F', // Right-to-Left Mark character
|
|
601
|
-
'\u2028', // Left-to-Right Mark character
|
|
602
|
-
'\u2060', // Word Spacing character
|
|
603
|
-
'\u2061', // Word Joiner character
|
|
604
|
-
'\u2062', // Invisible Text Character character
|
|
605
|
-
'\u2063', // Inhibit Explicit Word Joining character
|
|
606
|
-
'\u2064', // Invisible Text Processing character
|
|
607
|
-
];
|
|
608
|
-
|
|
609
|
-
// Replace each problematic character with an empty string
|
|
610
|
-
return problematicCharacters.reduce((cleanString, character) => {
|
|
611
|
-
const charRegex = new RegExp(character, 'g'); // Regular expression for character
|
|
612
|
-
return cleanString.replace(charRegex, ''); // Replace with empty string
|
|
613
|
-
}, string);
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
function splitEveryXChar(originalString, everyXChar = 30, nextCharSplit) {
|
|
617
|
-
let modifiedString = '';
|
|
618
|
-
const arrayString = [];
|
|
619
|
-
let i = -1;
|
|
620
|
-
let charSplit = false;
|
|
621
|
-
for (let char of originalString) {
|
|
622
|
-
i++;
|
|
623
|
-
modifiedString += char;
|
|
624
|
-
if (i !== 0 && i % everyXChar === 0) charSplit = true;
|
|
625
|
-
if (modifiedString.length >= everyXChar && charSplit && (!nextCharSplit || nextCharSplit.includes(char))) {
|
|
626
|
-
arrayString.push(newInstance(modifiedString));
|
|
627
|
-
modifiedString = '';
|
|
628
|
-
charSplit = false;
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
if (modifiedString) arrayString.push(modifiedString);
|
|
632
|
-
return arrayString;
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
const getMostFrequentValue = (arr) =>
|
|
636
|
-
arr.sort((a, b) => arr.filter((v) => v === a).length - arr.filter((v) => v === b).length).pop();
|
|
637
|
-
|
|
638
|
-
const getFillMatrix = (maxX, maxY, value = 0) =>
|
|
639
|
-
new Array(maxY).fill().map(() => new Array(maxX).fill().map(() => value));
|
|
640
|
-
|
|
641
|
-
function validatePassword(password) {
|
|
642
|
-
let errors = [];
|
|
643
|
-
if (!/[a-z]/.test(password))
|
|
644
|
-
errors.push({ en: 'must contain at least one lowercase letter', es: 'debe contener al menos una letra minúscula' });
|
|
645
|
-
if (!/[A-Z]/.test(password))
|
|
646
|
-
errors.push({ en: 'must contain at least one uppercase letter', es: 'debe contener al menos una letra mayúscula' });
|
|
647
|
-
if (!/\d/.test(password))
|
|
648
|
-
errors.push({ en: 'must contain at least one number', es: 'debe contener al menos un número' });
|
|
649
|
-
if (!/[@#$-%^&*()_+{}\[\]:;<>,.!?\/\\|`~]/.test(password))
|
|
650
|
-
errors.push({
|
|
651
|
-
en: 'must contain at least one special character',
|
|
652
|
-
es: 'debe contener al menos un carácter especial',
|
|
653
|
-
});
|
|
654
|
-
if (password.length < 8)
|
|
655
|
-
errors.push({ en: 'must be at least 8 characters long', es: 'debe tener al menos 8 caracteres de largo' });
|
|
656
|
-
|
|
657
|
-
return errors;
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
function componentFromStr(numStr, percent) {
|
|
661
|
-
const num = Math.max(0, parseInt(numStr, 10));
|
|
662
|
-
return percent ? Math.floor((255 * Math.min(100, num)) / 100) : Math.min(255, num);
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
function rgbToHex(rgb) {
|
|
666
|
-
const rgbRegex = /^rgb\(\s*(-?\d+)(%?)\s*,\s*(-?\d+)(%?)\s*,\s*(-?\d+)(%?)\s*\)$/;
|
|
667
|
-
let result,
|
|
668
|
-
r,
|
|
669
|
-
g,
|
|
670
|
-
b,
|
|
671
|
-
hex = '';
|
|
672
|
-
if ((result = rgbRegex.exec(rgb))) {
|
|
673
|
-
r = componentFromStr(result[1], result[2]);
|
|
674
|
-
g = componentFromStr(result[3], result[4]);
|
|
675
|
-
b = componentFromStr(result[5], result[6]);
|
|
676
|
-
|
|
677
|
-
hex = '' + (0x1000000 + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
|
678
|
-
}
|
|
679
|
-
return hex;
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Common JavaScript functions
|
|
3
|
+
* @module src/client/components/core/CommonJs.js
|
|
4
|
+
* @namespace CommonJS
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The function `s4` generates a random hexadecimal string with a length of 4 characters.
|
|
9
|
+
* @memberof CommonJS
|
|
10
|
+
*/
|
|
11
|
+
const s4 = () => (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The `range` function generates an array of numbers within a specified range, handling both ascending
|
|
15
|
+
* and descending ranges.
|
|
16
|
+
* @param start - The `start` parameter in the `range` function represents the starting value of the
|
|
17
|
+
* range you want to generate.
|
|
18
|
+
* @param end - The `end` parameter in the `range` function represents the ending value of the range
|
|
19
|
+
* that you want to generate.
|
|
20
|
+
* @returns The `range` function returns an array containing a range of numbers starting from the
|
|
21
|
+
* `start` value up to the `end` value (inclusive). If `end` is less than `start`, it will recursively
|
|
22
|
+
* call the `range` function with the arguments swapped and then reverse the resulting array.
|
|
23
|
+
* @memberof CommonJS
|
|
24
|
+
*/
|
|
25
|
+
const range = (start, end) => {
|
|
26
|
+
return end < start
|
|
27
|
+
? range(end, start).reverse()
|
|
28
|
+
: Array.apply(0, Array(end - start + 1)).map((element, index) => index + start);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The `getId` function generates a unique identifier based on an array of objects or keys.
|
|
33
|
+
* @param arr - The `arr` parameter in the `getId` function is an array of objects or an object. If it
|
|
34
|
+
* is an object, the function converts it into an array of objects where each object has a key
|
|
35
|
+
* specified by the `keyId` parameter.
|
|
36
|
+
* @param suffix - The `suffix` parameter in the `getId` function is a string that can be added to
|
|
37
|
+
* the generated ID. It is optional and by default is an empty string. You can provide a suffix to be
|
|
38
|
+
* appended to the generated ID if needed.
|
|
39
|
+
* @param keyId - The `keyId` parameter in the `getId` function is used to specify the key in the
|
|
40
|
+
* array elements that contains the unique identifier (ID) for each element. By default, the function
|
|
41
|
+
* assumes that the ID is stored in a property named `'id'`, but you can customize this by providing
|
|
42
|
+
* @returns The `getId` function returns a unique identifier `_id` based on the input array `arr`,
|
|
43
|
+
* optional `suffix`, and `keyId`.
|
|
44
|
+
* @memberof CommonJS
|
|
45
|
+
*/
|
|
46
|
+
const getId = (arr, suffix = '', keyId = 'id') => {
|
|
47
|
+
if (!Array.isArray(arr) && typeof arr === 'object')
|
|
48
|
+
arr = Object.keys(arr).map((id) => {
|
|
49
|
+
const idElement = {};
|
|
50
|
+
idElement[keyId] = id;
|
|
51
|
+
return idElement;
|
|
52
|
+
});
|
|
53
|
+
let _id;
|
|
54
|
+
while (arr.find((element) => element[keyId] === _id) || !_id)
|
|
55
|
+
_id = suffix + (s4() + s4() + s4() + s4() + s4()).slice(1);
|
|
56
|
+
return _id;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The function `random` generates a random integer within a specified range.
|
|
61
|
+
* @param min - The `min` parameter represents the minimum value of the range from which you want to
|
|
62
|
+
* generate a random number.
|
|
63
|
+
* @param max - The `max` parameter in the `random` function represents the maximum value that you want
|
|
64
|
+
* to generate a random number up to.
|
|
65
|
+
* @memberof CommonJS
|
|
66
|
+
*/
|
|
67
|
+
const random = (min, max) => Math.floor(Math.random() * (max - min + 1) + min); // The maximum is inclusive and the minimum is inclusive
|
|
68
|
+
|
|
69
|
+
const randomHexColor = () => '#' + ((Math.random() * 0xffffff) << 0).toString(16).padStart(6, '0');
|
|
70
|
+
|
|
71
|
+
const getRawCsvFromArray = (array) =>
|
|
72
|
+
array[0]
|
|
73
|
+
? Object.keys(array[0]).join(';') +
|
|
74
|
+
'\r\n' +
|
|
75
|
+
array
|
|
76
|
+
.map((x) => {
|
|
77
|
+
return (
|
|
78
|
+
Object.keys(x)
|
|
79
|
+
.map((attr) => x[attr])
|
|
80
|
+
.join(';') + '\r\n'
|
|
81
|
+
);
|
|
82
|
+
})
|
|
83
|
+
.join('')
|
|
84
|
+
: '';
|
|
85
|
+
|
|
86
|
+
const newInstance = (obj) => {
|
|
87
|
+
// structuredClone() 2022 ES6 feature
|
|
88
|
+
try {
|
|
89
|
+
return JSON.parse(JSON.stringify(obj));
|
|
90
|
+
} catch (error) {
|
|
91
|
+
return { error: error.message };
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const cap = (str) =>
|
|
96
|
+
str
|
|
97
|
+
.toLowerCase()
|
|
98
|
+
.split(' ')
|
|
99
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
100
|
+
.join(' ');
|
|
101
|
+
|
|
102
|
+
const capFirst = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
103
|
+
|
|
104
|
+
const uniqueArray = (arr) => arr.filter((item, pos) => arr.indexOf(item) == pos);
|
|
105
|
+
|
|
106
|
+
const orderArrayFromAttrInt = (arr, attr, type) =>
|
|
107
|
+
// type -> true asc
|
|
108
|
+
// type -> false desc
|
|
109
|
+
type === 'asc' ? arr.sort((a, b) => a[attr] - b[attr]) : arr.sort((a, b) => b[attr] - a[attr]);
|
|
110
|
+
|
|
111
|
+
const getRandomPoint = (suffix, pointsArray) => {
|
|
112
|
+
const point = pointsArray[random(0, pointsArray.length - 1)];
|
|
113
|
+
const returnPoint = {};
|
|
114
|
+
returnPoint['x' + suffix] = point[0];
|
|
115
|
+
returnPoint['y' + suffix] = point[1];
|
|
116
|
+
return returnPoint;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const getYouTubeID = (url) => {
|
|
120
|
+
const p =
|
|
121
|
+
/^(?:https?:\/\/)?(?:m\.|www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/;
|
|
122
|
+
if (url.match(p)) return url.match(p)[1];
|
|
123
|
+
return false;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const timer = (ms) => new Promise((res) => setTimeout(res, ms));
|
|
127
|
+
|
|
128
|
+
const reOrderIntArray = (array) => {
|
|
129
|
+
/* shuffle */
|
|
130
|
+
let currentIndex = array.length,
|
|
131
|
+
randomIndex;
|
|
132
|
+
|
|
133
|
+
// While there remain elements to shuffle.
|
|
134
|
+
while (currentIndex != 0) {
|
|
135
|
+
// Pick a remaining element.
|
|
136
|
+
randomIndex = Math.floor(Math.random() * currentIndex);
|
|
137
|
+
currentIndex--;
|
|
138
|
+
|
|
139
|
+
// And swap it with the current element.
|
|
140
|
+
[array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return array;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const orderAbc = (arr, attr) =>
|
|
147
|
+
arr.sort((a, b) => {
|
|
148
|
+
if (attr) {
|
|
149
|
+
if (a[attr] < b[attr]) {
|
|
150
|
+
return -1;
|
|
151
|
+
}
|
|
152
|
+
if (a[attr] > b[attr]) {
|
|
153
|
+
return 1;
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
if (a < b) {
|
|
157
|
+
return -1;
|
|
158
|
+
}
|
|
159
|
+
if (a > b) {
|
|
160
|
+
return 1;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return 0;
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const JSONmatrix = (matrix) => {
|
|
167
|
+
if (Array.isArray(matrix))
|
|
168
|
+
return `[\r\n${matrix
|
|
169
|
+
.map((x, i) => ` ` + JSON.stringify(x) + (i === matrix.length - 1 ? '' : ',') + '\r\n')
|
|
170
|
+
.join('')}]`;
|
|
171
|
+
else
|
|
172
|
+
return `[\r\n${Object.keys(matrix)
|
|
173
|
+
.map((x, i) => ` ` + JSON.stringify(Object.values(matrix[x])) + (i === matrix.length - 1 ? '' : ',') + '\r\n')
|
|
174
|
+
.join('')}]`;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const getDistance = (x1, y1, x2, y2) => {
|
|
178
|
+
const disX = Math.abs(x2 - x1);
|
|
179
|
+
const disY = Math.abs(y2 - y1);
|
|
180
|
+
return Math.sqrt(disX * disX + disY * disY);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const setPad = (num, padValue, targetLength, endPad, separator) => {
|
|
184
|
+
separator = separator ? separator : '.';
|
|
185
|
+
let str = String(num).split(separator);
|
|
186
|
+
let removeSeparator = false;
|
|
187
|
+
if (!str[1]) {
|
|
188
|
+
str[1] = '';
|
|
189
|
+
if (!endPad) removeSeparator = true;
|
|
190
|
+
}
|
|
191
|
+
while (endPad ? str[1].length < targetLength : str[0].length < targetLength)
|
|
192
|
+
endPad ? (str[1] = str[1] + padValue) : (str[0] = padValue + str[0]);
|
|
193
|
+
return removeSeparator ? str.join(separator).replace(separator, '') : str.join(separator);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Decimal setting of a number.
|
|
198
|
+
*
|
|
199
|
+
* @param {String} type The type of setting.
|
|
200
|
+
* @param {Number} value The number.
|
|
201
|
+
* @param {Integer} exp The exponent (the log 10 of the base fit).
|
|
202
|
+
* @returns {Number} The adjusted value.
|
|
203
|
+
* @memberof CommonJS
|
|
204
|
+
*/
|
|
205
|
+
const decimalAdjust = (type, value, exp) => {
|
|
206
|
+
if (typeof exp === 'undefined' || +exp === 0) {
|
|
207
|
+
return Math[type](value);
|
|
208
|
+
}
|
|
209
|
+
value = +value;
|
|
210
|
+
exp = +exp;
|
|
211
|
+
|
|
212
|
+
if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
|
|
213
|
+
return NaN;
|
|
214
|
+
}
|
|
215
|
+
// Shift
|
|
216
|
+
value = value.toString().split('e');
|
|
217
|
+
value = Math[type](+(value[0] + 'e' + (value[1] ? +value[1] - exp : -exp)));
|
|
218
|
+
// Shift back
|
|
219
|
+
value = value.toString().split('e');
|
|
220
|
+
return +(value[0] + 'e' + (value[1] ? +value[1] + exp : exp));
|
|
221
|
+
|
|
222
|
+
// https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Math/round
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const floatRound = (v, d) => parseFloat(parseFloat(v).toFixed(d));
|
|
226
|
+
|
|
227
|
+
// Decimal round
|
|
228
|
+
|
|
229
|
+
const round10 = (value, exp) => {
|
|
230
|
+
return decimalAdjust('round', value, exp);
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// Decimal floor
|
|
234
|
+
|
|
235
|
+
const floor10 = (value, exp) => {
|
|
236
|
+
return decimalAdjust('floor', value, exp);
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// Decimal ceil
|
|
240
|
+
|
|
241
|
+
const ceil10 = (value, exp) => {
|
|
242
|
+
return decimalAdjust('ceil', value, exp);
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
// // Round
|
|
246
|
+
// round10(55.55, -1); // 55.6
|
|
247
|
+
// round10(55.549, -1); // 55.5
|
|
248
|
+
// round10(55, 1); // 60
|
|
249
|
+
// round10(54.9, 1); // 50
|
|
250
|
+
// round10(-55.55, -1); // -55.5
|
|
251
|
+
// round10(-55.551, -1); // -55.6
|
|
252
|
+
// round10(-55, 1); // -50
|
|
253
|
+
// round10(-55.1, 1); // -60
|
|
254
|
+
// round10(1.005, -2); // 1.01 -- compare this with round(1.005*100)/100 above
|
|
255
|
+
// // Floor
|
|
256
|
+
// floor10(55.59, -1); // 55.5
|
|
257
|
+
// floor10(59, 1); // 50
|
|
258
|
+
// floor10(-55.51, -1); // -55.6
|
|
259
|
+
// floor10(-51, 1); // -60
|
|
260
|
+
// // Ceil
|
|
261
|
+
// ceil10(55.51, -1); // 55.6
|
|
262
|
+
// ceil10(51, 1); // 60
|
|
263
|
+
// ceil10(-55.59, -1); // -55.5
|
|
264
|
+
// ceil10(-59, 1); // -50
|
|
265
|
+
|
|
266
|
+
function objectEquals(x, y) {
|
|
267
|
+
// TODO:
|
|
268
|
+
// https://www.npmjs.com/package/deep-equal
|
|
269
|
+
// https://www.npmjs.com/package/fast-deep-equal
|
|
270
|
+
const ok = Object.keys,
|
|
271
|
+
tx = typeof x,
|
|
272
|
+
ty = typeof y;
|
|
273
|
+
return x && y && tx === 'object' && tx === ty
|
|
274
|
+
? ok(x).length === ok(y).length && ok(x).every((key) => objectEquals(x[key], y[key]))
|
|
275
|
+
: x === y;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function insertTransitionCoordinates(coordinates, transitionFactor) {
|
|
279
|
+
// Create a new array to store the resulting coordinates
|
|
280
|
+
const coordinatesWithTransition = [];
|
|
281
|
+
|
|
282
|
+
// Iterate over the coordinates array
|
|
283
|
+
for (let i = 0; i < coordinates.length - 1; i++) {
|
|
284
|
+
const [x1, y1] = coordinates[i];
|
|
285
|
+
const [x2, y2] = coordinates[i + 1];
|
|
286
|
+
|
|
287
|
+
// Add the initial integer coordinate to the new array
|
|
288
|
+
coordinatesWithTransition.push([x1, y1]);
|
|
289
|
+
|
|
290
|
+
// Calculate the increments for each coordinate
|
|
291
|
+
const incrementX = (x2 - x1) / transitionFactor;
|
|
292
|
+
const incrementY = (y2 - y1) / transitionFactor;
|
|
293
|
+
|
|
294
|
+
// Add the intermediate coordinates
|
|
295
|
+
for (let j = 1; j <= transitionFactor - 1; j++) {
|
|
296
|
+
const xIntermediate = x1 + incrementX * j;
|
|
297
|
+
const yIntermediate = y1 + incrementY * j;
|
|
298
|
+
coordinatesWithTransition.push([xIntermediate, yIntermediate]);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Add the last integer coordinate to the new array
|
|
303
|
+
coordinatesWithTransition.push(coordinates[coordinates.length - 1]);
|
|
304
|
+
|
|
305
|
+
// Now, coordinatesWithTransition contains the coordinates with transition
|
|
306
|
+
return coordinatesWithTransition;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const getIsoDate = (date) => date.toISOString().slice(0, -5).replace('T', ' ');
|
|
310
|
+
|
|
311
|
+
const clearTerminalStringColor = (str) => str.replace(/\x1b\[[0-9;]*m/g, '');
|
|
312
|
+
|
|
313
|
+
function getValueFromJoinString(obj, path, join = '.') {
|
|
314
|
+
// Split the path string into an array of attribute names
|
|
315
|
+
const attributes = path.split(join);
|
|
316
|
+
|
|
317
|
+
// Iterate through the attributes to access the desired value
|
|
318
|
+
let value = obj;
|
|
319
|
+
for (let i = 0; i < attributes.length; i++) {
|
|
320
|
+
value = value[attributes[i]];
|
|
321
|
+
|
|
322
|
+
// Check if the value is null or undefined at each step
|
|
323
|
+
if (value === null || value === undefined) {
|
|
324
|
+
// If the value is null or undefined, stop the iteration
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return value;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function getDirection(options = { x1: 1, y1: 1, x2: 1, y2: 1, radians: 1 }) {
|
|
333
|
+
const { x1, y1, x2, y2, radians } = options;
|
|
334
|
+
// Calculate the angle in radians
|
|
335
|
+
const angle = radians !== undefined ? radians : Math.atan2(y2 - y1, x2 - x1);
|
|
336
|
+
|
|
337
|
+
// Convert the angle to degrees
|
|
338
|
+
let degrees = angle * (180 / Math.PI);
|
|
339
|
+
|
|
340
|
+
// Adjust the angle to be positive
|
|
341
|
+
if (degrees < 0) {
|
|
342
|
+
degrees += 360;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// 45 / 2 = 22.5
|
|
346
|
+
// formula -> 22.5 + (45*n)
|
|
347
|
+
|
|
348
|
+
// Map the angle to one of the eight directions
|
|
349
|
+
let direction;
|
|
350
|
+
if (degrees >= 337.5 || degrees < 22.5) {
|
|
351
|
+
// direction = 'right';
|
|
352
|
+
// direction = 'East';
|
|
353
|
+
direction = 'e';
|
|
354
|
+
} else if (degrees >= 22.5 && degrees < 67.5) {
|
|
355
|
+
// direction = 'up-right';
|
|
356
|
+
// direction = 'South East';
|
|
357
|
+
direction = 'se';
|
|
358
|
+
} else if (degrees >= 67.5 && degrees < 112.5) {
|
|
359
|
+
// direction = 'up';
|
|
360
|
+
// direction = 'South';
|
|
361
|
+
direction = 's';
|
|
362
|
+
} else if (degrees >= 112.5 && degrees < 157.5) {
|
|
363
|
+
// direction = 'up-left';
|
|
364
|
+
// direction = 'South West';
|
|
365
|
+
direction = 'sw';
|
|
366
|
+
} else if (degrees >= 157.5 && degrees < 202.5) {
|
|
367
|
+
// direction = 'left';
|
|
368
|
+
// direction = 'West';
|
|
369
|
+
direction = 'w';
|
|
370
|
+
} else if (degrees >= 202.5 && degrees < 247.5) {
|
|
371
|
+
// direction = 'down-left';
|
|
372
|
+
// direction = 'North West';
|
|
373
|
+
direction = 'nw';
|
|
374
|
+
} else if (degrees >= 247.5 && degrees < 292.5) {
|
|
375
|
+
// direction = 'down';
|
|
376
|
+
// direction = 'North';
|
|
377
|
+
direction = 'n';
|
|
378
|
+
} else if (degrees >= 292.5 && degrees < 337.5) {
|
|
379
|
+
// direction = 'down-right';
|
|
380
|
+
// direction = 'North East';
|
|
381
|
+
direction = 'ne';
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
return direction;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Function to amplify a matrix in horizontal and vertical directions
|
|
388
|
+
const amplifyMatrix = (matrix, factor) => {
|
|
389
|
+
// Get the original dimensions of the matrix
|
|
390
|
+
const rows = matrix.length;
|
|
391
|
+
const cols = matrix[0].length;
|
|
392
|
+
|
|
393
|
+
// Create a new amplified matrix filled with zeros
|
|
394
|
+
const amplifiedMatrix = Array.from({ length: rows * factor }, () => Array(cols * factor).fill(0));
|
|
395
|
+
|
|
396
|
+
// Iterate over the original matrix
|
|
397
|
+
for (let i = 0; i < rows; i++) {
|
|
398
|
+
for (let j = 0; j < cols; j++) {
|
|
399
|
+
// Get the current value in the original matrix
|
|
400
|
+
const originalValue = matrix[i][j];
|
|
401
|
+
|
|
402
|
+
// Amplify in horizontal and vertical directions
|
|
403
|
+
for (let x = 0; x < factor; x++) {
|
|
404
|
+
for (let y = 0; y < factor; y++) {
|
|
405
|
+
// Assign the amplified value to the new matrix
|
|
406
|
+
amplifiedMatrix[i * factor + x][j * factor + y] = originalValue;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
return amplifiedMatrix;
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
// Function to reduce a matrix by a factor in horizontal and vertical directions
|
|
416
|
+
const reduceMatrix = (matrix, factor) => {
|
|
417
|
+
// Get the original dimensions of the matrix
|
|
418
|
+
const rows = matrix.length;
|
|
419
|
+
const cols = matrix[0].length;
|
|
420
|
+
|
|
421
|
+
// Calculate the dimensions of the reduced matrix
|
|
422
|
+
const reducedRows = Math.ceil(rows / factor);
|
|
423
|
+
const reducedCols = Math.ceil(cols / factor);
|
|
424
|
+
|
|
425
|
+
// Create a new reduced matrix filled with zeros
|
|
426
|
+
const reducedMatrix = Array.from({ length: reducedRows }, () => Array(reducedCols).fill(0));
|
|
427
|
+
|
|
428
|
+
// Iterate over the original matrix
|
|
429
|
+
for (let i = 0; i < reducedRows; i++) {
|
|
430
|
+
for (let j = 0; j < reducedCols; j++) {
|
|
431
|
+
// Calculate the sum of values in the corresponding block of the original matrix
|
|
432
|
+
let sum = 0;
|
|
433
|
+
|
|
434
|
+
for (let x = 0; x < factor; x++) {
|
|
435
|
+
for (let y = 0; y < factor; y++) {
|
|
436
|
+
// Safely access the original matrix considering the boundaries
|
|
437
|
+
const rowIndex = i * factor + x;
|
|
438
|
+
const colIndex = j * factor + y;
|
|
439
|
+
|
|
440
|
+
if (rowIndex < rows && colIndex < cols) {
|
|
441
|
+
sum += matrix[rowIndex][colIndex];
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// Calculate the average value for the reduced matrix
|
|
447
|
+
reducedMatrix[i][j] = sum / Math.min(factor * factor, rows * cols);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
return reducedMatrix;
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
const mergeMatrices = (input) => {
|
|
455
|
+
const rows = Object.keys(input).reduce((acc, key) => {
|
|
456
|
+
const rowData = Object.keys(input[key]).reduce((rowAcc, subKey) => {
|
|
457
|
+
const subArray = input[key][subKey];
|
|
458
|
+
const rowIndex = parseInt(key, 10) * subArray.length;
|
|
459
|
+
subArray.forEach((subRow, subRowIndex) => {
|
|
460
|
+
const fullRowIndex = rowIndex + subRowIndex;
|
|
461
|
+
if (!rowAcc[fullRowIndex]) {
|
|
462
|
+
rowAcc[fullRowIndex] = [];
|
|
463
|
+
}
|
|
464
|
+
rowAcc[fullRowIndex] = rowAcc[fullRowIndex].concat(subRow);
|
|
465
|
+
});
|
|
466
|
+
return rowAcc;
|
|
467
|
+
}, []);
|
|
468
|
+
acc = acc.concat(rowData);
|
|
469
|
+
return acc;
|
|
470
|
+
}, []);
|
|
471
|
+
|
|
472
|
+
// Remove empty rows
|
|
473
|
+
const nonEmptyRows = rows.filter((row) => row.some((cell) => cell !== undefined));
|
|
474
|
+
|
|
475
|
+
// Remove empty columns
|
|
476
|
+
const transpose = nonEmptyRows[0].map((col, i) => nonEmptyRows.map((row) => row[i]));
|
|
477
|
+
const nonEmptyColumns = transpose.filter((col) => col.some((cell) => cell !== undefined));
|
|
478
|
+
|
|
479
|
+
// Transpose back to rows
|
|
480
|
+
const result = nonEmptyColumns[0].map((row, i) => nonEmptyColumns.map((col) => col[i]));
|
|
481
|
+
|
|
482
|
+
return result;
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
const titleFormatted = (str) => cap(str.trim().replaceAll('/', '').replaceAll('-', ' '));
|
|
486
|
+
|
|
487
|
+
const getSubpaths = (path) =>
|
|
488
|
+
path
|
|
489
|
+
.split('/')
|
|
490
|
+
.filter(Boolean)
|
|
491
|
+
.map((_, i, segments) => `/${segments.slice(0, i + 1).join('/')}`);
|
|
492
|
+
|
|
493
|
+
function formatBytes(bytes, decimals = 2) {
|
|
494
|
+
if (!+bytes) return '0 Bytes';
|
|
495
|
+
|
|
496
|
+
const k = 1024;
|
|
497
|
+
const dm = decimals < 0 ? 0 : decimals;
|
|
498
|
+
const sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
|
|
499
|
+
|
|
500
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
501
|
+
|
|
502
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
function getDirname(path) {
|
|
506
|
+
// Split the path based on the path separator
|
|
507
|
+
const parts = path.split(/[/|\\]/);
|
|
508
|
+
|
|
509
|
+
// Remove the last element (filename)
|
|
510
|
+
parts.pop();
|
|
511
|
+
|
|
512
|
+
// If the path ends with a separator, remove the empty element
|
|
513
|
+
if (parts[parts.length - 1] === '') {
|
|
514
|
+
parts.pop();
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Join the remaining parts to get the directory path
|
|
518
|
+
return parts.join('/'); // Adjust separator if needed for Windows ('\')
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const isDayValid = (day) => {
|
|
522
|
+
const date = new Date();
|
|
523
|
+
date.setDate(day);
|
|
524
|
+
return date.getDate() === day;
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
const isMonthValid = (month) => {
|
|
528
|
+
const date = new Date();
|
|
529
|
+
date.setMonth(month - 1);
|
|
530
|
+
return date.getMonth() === month - 1;
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
const isValidDate = (day, month, year) => {
|
|
534
|
+
if (!isDayValid(day) || !isMonthValid(month)) {
|
|
535
|
+
return false;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const date = new Date(year, month - 1, day);
|
|
539
|
+
return !isNaN(date.getTime());
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
const isValidFormat = (value, format) => {
|
|
543
|
+
try {
|
|
544
|
+
switch (format) {
|
|
545
|
+
case 'ALPHANUMERIC':
|
|
546
|
+
return /^[a-z0-9]+$/i.test(value);
|
|
547
|
+
case 'DDMMYYYY': {
|
|
548
|
+
const day = parseInt(value.substring(0, 2));
|
|
549
|
+
const month = parseInt(value.substring(2, 4));
|
|
550
|
+
const year = parseInt(value.substring(4));
|
|
551
|
+
return isValidDate(day, month, year);
|
|
552
|
+
}
|
|
553
|
+
case 'YYYYDDMM': {
|
|
554
|
+
const day = parseInt(value.substring(4, 6));
|
|
555
|
+
const month = parseInt(value.substring(6, 8));
|
|
556
|
+
const year = parseInt(value.substring(0, 4));
|
|
557
|
+
return isValidDate(day, month, year);
|
|
558
|
+
}
|
|
559
|
+
case 'DD-MM-YYYY': {
|
|
560
|
+
value = value.split('-');
|
|
561
|
+
const day = parseInt(value[0]);
|
|
562
|
+
const month = parseInt(value[1]);
|
|
563
|
+
const year = parseInt(value[2]);
|
|
564
|
+
return isValidDate(day, month, year);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
default:
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
570
|
+
} catch (error) {
|
|
571
|
+
console.error(error);
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Returns the time difference between UTC time and local time, in minutes.
|
|
578
|
+
* @memberof CommonJS
|
|
579
|
+
*/
|
|
580
|
+
const getTimezoneOffset = () => new Date().getTimezoneOffset();
|
|
581
|
+
|
|
582
|
+
// https://unicode-explorer.com/c/<unicode>
|
|
583
|
+
// example: https://unicode-explorer.com/c/0000
|
|
584
|
+
function cleanString(string) {
|
|
585
|
+
// Define the problematic escape sequences unicode characters to remove with descriptions
|
|
586
|
+
const problematicCharacters = [
|
|
587
|
+
// '\u0000', // Null character (Represents absence of a character) not work
|
|
588
|
+
'\u0008', // Backspace character
|
|
589
|
+
'\u0002', // Start of Text (STX) character
|
|
590
|
+
'\u0009', // Horizontal Tab character
|
|
591
|
+
'\u000B', // Vertical Tab character
|
|
592
|
+
'\u000C', // Form Feed character
|
|
593
|
+
'\u000D', // Carriage Return character
|
|
594
|
+
'\u001D', // Group Separator (GS) character
|
|
595
|
+
'\u001F', // Substitution character
|
|
596
|
+
// '\u0020', // Space character
|
|
597
|
+
'\u200B', // Zero Width Space character
|
|
598
|
+
'\u200C', // Zero Width Non-Joiner character
|
|
599
|
+
'\u200D', // Zero Width Joiner character
|
|
600
|
+
'\u200F', // Right-to-Left Mark character
|
|
601
|
+
'\u2028', // Left-to-Right Mark character
|
|
602
|
+
'\u2060', // Word Spacing character
|
|
603
|
+
'\u2061', // Word Joiner character
|
|
604
|
+
'\u2062', // Invisible Text Character character
|
|
605
|
+
'\u2063', // Inhibit Explicit Word Joining character
|
|
606
|
+
'\u2064', // Invisible Text Processing character
|
|
607
|
+
];
|
|
608
|
+
|
|
609
|
+
// Replace each problematic character with an empty string
|
|
610
|
+
return problematicCharacters.reduce((cleanString, character) => {
|
|
611
|
+
const charRegex = new RegExp(character, 'g'); // Regular expression for character
|
|
612
|
+
return cleanString.replace(charRegex, ''); // Replace with empty string
|
|
613
|
+
}, string);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
function splitEveryXChar(originalString, everyXChar = 30, nextCharSplit) {
|
|
617
|
+
let modifiedString = '';
|
|
618
|
+
const arrayString = [];
|
|
619
|
+
let i = -1;
|
|
620
|
+
let charSplit = false;
|
|
621
|
+
for (let char of originalString) {
|
|
622
|
+
i++;
|
|
623
|
+
modifiedString += char;
|
|
624
|
+
if (i !== 0 && i % everyXChar === 0) charSplit = true;
|
|
625
|
+
if (modifiedString.length >= everyXChar && charSplit && (!nextCharSplit || nextCharSplit.includes(char))) {
|
|
626
|
+
arrayString.push(newInstance(modifiedString));
|
|
627
|
+
modifiedString = '';
|
|
628
|
+
charSplit = false;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
if (modifiedString) arrayString.push(modifiedString);
|
|
632
|
+
return arrayString;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
const getMostFrequentValue = (arr) =>
|
|
636
|
+
arr.sort((a, b) => arr.filter((v) => v === a).length - arr.filter((v) => v === b).length).pop();
|
|
637
|
+
|
|
638
|
+
const getFillMatrix = (maxX, maxY, value = 0) =>
|
|
639
|
+
new Array(maxY).fill().map(() => new Array(maxX).fill().map(() => value));
|
|
640
|
+
|
|
641
|
+
function validatePassword(password) {
|
|
642
|
+
let errors = [];
|
|
643
|
+
if (!/[a-z]/.test(password))
|
|
644
|
+
errors.push({ en: 'must contain at least one lowercase letter', es: 'debe contener al menos una letra minúscula' });
|
|
645
|
+
if (!/[A-Z]/.test(password))
|
|
646
|
+
errors.push({ en: 'must contain at least one uppercase letter', es: 'debe contener al menos una letra mayúscula' });
|
|
647
|
+
if (!/\d/.test(password))
|
|
648
|
+
errors.push({ en: 'must contain at least one number', es: 'debe contener al menos un número' });
|
|
649
|
+
if (!/[@#$-%^&*()_+{}\[\]:;<>,.!?\/\\|`~]/.test(password))
|
|
650
|
+
errors.push({
|
|
651
|
+
en: 'must contain at least one special character',
|
|
652
|
+
es: 'debe contener al menos un carácter especial',
|
|
653
|
+
});
|
|
654
|
+
if (password.length < 8)
|
|
655
|
+
errors.push({ en: 'must be at least 8 characters long', es: 'debe tener al menos 8 caracteres de largo' });
|
|
656
|
+
|
|
657
|
+
return errors;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
function componentFromStr(numStr, percent) {
|
|
661
|
+
const num = Math.max(0, parseInt(numStr, 10));
|
|
662
|
+
return percent ? Math.floor((255 * Math.min(100, num)) / 100) : Math.min(255, num);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function rgbToHex(rgb) {
|
|
666
|
+
const rgbRegex = /^rgb\(\s*(-?\d+)(%?)\s*,\s*(-?\d+)(%?)\s*,\s*(-?\d+)(%?)\s*\)$/;
|
|
667
|
+
let result,
|
|
668
|
+
r,
|
|
669
|
+
g,
|
|
670
|
+
b,
|
|
671
|
+
hex = '';
|
|
672
|
+
if ((result = rgbRegex.exec(rgb))) {
|
|
673
|
+
r = componentFromStr(result[1], result[2]);
|
|
674
|
+
g = componentFromStr(result[3], result[4]);
|
|
675
|
+
b = componentFromStr(result[5], result[6]);
|
|
676
|
+
|
|
677
|
+
hex = '' + (0x1000000 + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
|
678
|
+
}
|
|
679
|
+
return hex;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
const getCapVariableName = (value = 'default') => cap(value.replaceAll('-', ' ')).replaceAll(' ', '');
|
|
683
|
+
|
|
684
|
+
export {
|
|
685
|
+
s4,
|
|
686
|
+
range,
|
|
687
|
+
random,
|
|
688
|
+
newInstance,
|
|
689
|
+
cap,
|
|
690
|
+
uniqueArray,
|
|
691
|
+
orderArrayFromAttrInt,
|
|
692
|
+
getYouTubeID,
|
|
693
|
+
timer,
|
|
694
|
+
getRawCsvFromArray,
|
|
695
|
+
reOrderIntArray,
|
|
696
|
+
capFirst,
|
|
697
|
+
orderAbc,
|
|
698
|
+
getDistance,
|
|
699
|
+
decimalAdjust,
|
|
700
|
+
round10,
|
|
701
|
+
floor10,
|
|
702
|
+
ceil10,
|
|
703
|
+
JSONmatrix,
|
|
704
|
+
getRandomPoint,
|
|
705
|
+
objectEquals,
|
|
706
|
+
floatRound,
|
|
707
|
+
getId,
|
|
708
|
+
insertTransitionCoordinates,
|
|
709
|
+
randomHexColor,
|
|
710
|
+
clearTerminalStringColor,
|
|
711
|
+
getIsoDate,
|
|
712
|
+
getValueFromJoinString,
|
|
713
|
+
getDirection,
|
|
714
|
+
amplifyMatrix,
|
|
715
|
+
reduceMatrix,
|
|
716
|
+
mergeMatrices,
|
|
717
|
+
titleFormatted,
|
|
718
|
+
setPad,
|
|
719
|
+
getSubpaths,
|
|
720
|
+
formatBytes,
|
|
721
|
+
getDirname,
|
|
722
|
+
isDayValid,
|
|
723
|
+
isMonthValid,
|
|
724
|
+
isValidDate,
|
|
725
|
+
isValidFormat,
|
|
726
|
+
getTimezoneOffset,
|
|
727
|
+
cleanString,
|
|
728
|
+
splitEveryXChar,
|
|
729
|
+
getMostFrequentValue,
|
|
730
|
+
getFillMatrix,
|
|
731
|
+
validatePassword,
|
|
732
|
+
componentFromStr,
|
|
733
|
+
rgbToHex,
|
|
734
|
+
getCapVariableName,
|
|
735
|
+
};
|