node-red-contrib-prib-functions 0.23.2 → 0.26.0

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.
Files changed (58) hide show
  1. package/.github/copilot-instructions.md +36 -0
  2. package/README.md +153 -140
  3. package/columnar/columnar.html +258 -0
  4. package/columnar/columnar.js +1055 -0
  5. package/columnar/icons/columnar.svg +38 -0
  6. package/fileSystem/filesystem.html +299 -0
  7. package/fileSystem/filesystem.js +170 -0
  8. package/gitlab/gitlab.html +191 -0
  9. package/gitlab/gitlab.js +248 -0
  10. package/gitlab/icons/gitlab.svg +17 -0
  11. package/lib/AlphaBeta.js +32 -0
  12. package/lib/GraphDB.js +40 -9
  13. package/lib/MinMax.js +17 -0
  14. package/lib/Tree.js +64 -0
  15. package/lib/objectExtensions.js +28 -5
  16. package/lib/timeDimension.js +36 -0
  17. package/lib/typedInput.js +18 -2
  18. package/logisticRegression/icons/logisticregression.svg +22 -0
  19. package/logisticRegression/logisticRegression.html +136 -0
  20. package/logisticRegression/logisticRegression.js +83 -0
  21. package/package.json +21 -9
  22. package/test/02-graphdb.js +46 -0
  23. package/test/columnar.js +509 -0
  24. package/test/data/.config.nodes.json +114 -70
  25. package/test/data/.config.nodes.json.backup +104 -71
  26. package/test/data/.config.runtime.json +2 -1
  27. package/test/data/.config.runtime.json.backup +2 -1
  28. package/test/data/.config.users.json +3 -2
  29. package/test/data/.config.users.json.backup +3 -2
  30. package/test/data/.flow.json.backup +1545 -369
  31. package/test/data/flow.json +1457 -270
  32. package/test/data/package-lock.json +11 -11
  33. package/test/data/shares/.config.nodes.json +611 -0
  34. package/test/data/shares/.config.nodes.json.backup +589 -0
  35. package/test/data/shares/.config.runtime.json +5 -0
  36. package/test/data/shares/.config.runtime.json.backup +4 -0
  37. package/test/data/shares/.config.users.json +33 -0
  38. package/test/data/shares/.config.users.json.backup +33 -0
  39. package/test/data/shares/.flow.json.backup +230 -0
  40. package/test/data/shares/.flow_cred.json.backup +3 -0
  41. package/test/data/shares/flow.json +267 -0
  42. package/test/data/shares/flow_cred.json +3 -0
  43. package/test/data/shares/package.json +6 -0
  44. package/test/data/shares/settings.js +544 -0
  45. package/test/dataAnalysisExtensions.js +93 -93
  46. package/test/logisticRegression.js +379 -0
  47. package/test/transform.js +11 -11
  48. package/test/transformConfluence.js +4 -2
  49. package/test/transformNumPy.js +3 -1
  50. package/test/transformXLSX.js +4 -2
  51. package/test/transformXML.js +4 -2
  52. package/test-runner.js +400 -0
  53. package/test.parq +0 -0
  54. package/test_select.js +37 -0
  55. package/testing/test.js +8 -7
  56. package/transform/transform.html +23 -2
  57. package/transform/transform.js +239 -283
  58. package/transform/xlsx2.js +74 -0
@@ -0,0 +1,191 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('gitlab', {
3
+ category: 'function',
4
+ color: '#FC6D26',
5
+ defaults: {
6
+ name: {value:"", required:false},
7
+ action: {value:"getRepo", required:true},
8
+ gitlabUrl: {value:"https://gitlab.com", required:true},
9
+ accessToken: {value:"", required:true},
10
+ projectId: {value:"", required:true},
11
+ filePath: {value:"", required:false}
12
+ },
13
+ inputs: 1,
14
+ inputLabels: "in",
15
+ outputs:1,
16
+ outputLabels: ["Result"],
17
+ paletteLabel: "GitLab",
18
+ icon: "gitlab.svg",
19
+ label: function() {
20
+ return this.name || (this.action + " GitLab");
21
+ },
22
+ labelStyle: function() {
23
+ return "node_label_italic";
24
+ },
25
+ oneditprepare: function() {
26
+ const node = this;
27
+ $("#node-input-action").change(function() {
28
+ const action = $(this).val();
29
+ if (action === 'getFile') {
30
+ $("#file-path-row").show();
31
+ } else {
32
+ $("#file-path-row").hide();
33
+ }
34
+ });
35
+ $("#node-input-action").change(); // trigger on load
36
+ }
37
+ });
38
+ </script>
39
+
40
+ <script type="text/x-red" data-template-name="gitlab">
41
+ <div class="form-row">
42
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
43
+ <input type="text" id="node-input-name" placeholder="Name">
44
+ </div>
45
+ <div class="form-row">
46
+ <label for="node-input-action"><i class="fa fa-cogs"></i> Action</label>
47
+ <select type="text" id="node-input-action">
48
+ <option value="getRepo">Get Repository Info</option>
49
+ <option value="listIssues">List Issues</option>
50
+ <option value="createIssue">Create Issue</option>
51
+ <option value="getMergeRequests">Get Merge Requests</option>
52
+ <option value="createMergeRequest">Create Merge Request</option>
53
+ <option value="getFile">Get File</option>
54
+ <option value="runPipeline">Run Pipeline</option>
55
+ <option value="createCommit">Create Commit</option>
56
+ <option value="getCommits">Get Commits</option>
57
+ <option value="getCommit">Get Commit</option>
58
+ </select>
59
+ </div>
60
+ <div class="form-row">
61
+ <label for="node-input-gitlabUrl">GitLab URL</label>
62
+ <input type="text" id="node-input-gitlabUrl" placeholder="https://gitlab.com">
63
+ </div>
64
+ <div class="form-row">
65
+ <label for="node-input-accessToken">Access Token</label>
66
+ <input type="password" id="node-input-accessToken" placeholder="GitLab personal access token">
67
+ </div>
68
+ <div class="form-row">
69
+ <label for="node-input-projectId">Project ID</label>
70
+ <input type="text" id="node-input-projectId" placeholder="project-id or namespace/project-name">
71
+ </div>
72
+ <div class="form-row" id="file-path-row" style="display:none;">
73
+ <label for="node-input-filePath">File Path</label>
74
+ <input type="text" id="node-input-filePath" placeholder="path/to/file.txt">
75
+ </div>
76
+ </script>
77
+
78
+ <script type="text/x-red" data-help-name="gitlab">
79
+ <p>GitLab API access node for performing various operations on GitLab repositories.</p>
80
+
81
+ <h3>Configuration</h3>
82
+ <ul>
83
+ <li><b>GitLab URL:</b> The GitLab instance URL (default: https://gitlab.com)</li>
84
+ <li><b>Access Token:</b> GitLab personal access token with appropriate permissions</li>
85
+ <li><b>Project ID:</b> The project identifier (numeric ID or namespace/project-name)</li>
86
+ <li><b>File Path:</b> Path to file in repository (only shown for Get File action)</li>
87
+ </ul>
88
+
89
+ <h3>Actions</h3>
90
+ <ul>
91
+ <li><b>Get Repository Info:</b> Retrieves basic information about the repository</li>
92
+ <li><b>List Issues:</b> Lists issues in the repository. Optional filters in msg.payload: state, labels, assignee_id</li>
93
+ <li><b>Create Issue:</b> Creates a new issue. Required in msg.payload: title. Optional: description, labels, assignee_ids</li>
94
+ <li><b>Get Merge Requests:</b> Lists merge requests. Optional filters in msg.payload: state, source_branch, target_branch</li>
95
+ <li><b>Create Merge Request:</b> Creates a new merge request. Required in msg.payload: title, source_branch, target_branch. Optional: description, assignee_id, labels</li>
96
+ <li><b>Get File:</b> Retrieves file content from repository. File path can be in msg.payload.file_path or configured in node. Optional: ref (branch/tag/commit)</li>
97
+ <li><b>Run Pipeline:</b> Triggers a CI/CD pipeline. Optional in msg.payload: ref (default: main), variables (array of {key, value})</li>
98
+ <li><b>Create Commit:</b> Creates a new commit with file changes. Required in msg.payload: branch, commit_message, actions (array of file operations)</li>
99
+ <li><b>Get Commits:</b> Lists commits in repository. Optional filters in msg.payload: ref_name, since, until, path, author, per_page</li>
100
+ <li><b>Get Commit:</b> Retrieves details of a specific commit. Required in msg.payload: commit_sha</li>
101
+ </ul>
102
+
103
+ <h3>Authentication</h3>
104
+ <p>You need a GitLab personal access token with appropriate scopes:
105
+ <ul>
106
+ <li>api - for full API access</li>
107
+ <li>read_repository - for read operations</li>
108
+ <li>write_repository - for write operations</li>
109
+ </ul>
110
+ Create tokens at: GitLab Profile → Access Tokens</p>
111
+
112
+ <h3>Project ID</h3>
113
+ <p>The project ID can be found in the repository URL or project settings. It can be:
114
+ <ul>
115
+ <li>Numeric ID (e.g., 12345)</li>
116
+ <li>URL-encoded path (e.g., namespace%2Fproject-name)</li>
117
+ </ul></p>
118
+
119
+ <h3>Examples</h3>
120
+
121
+ <h4>Get Repository Info</h4>
122
+ <pre>Input: (any)
123
+ Output: Repository object with id, name, description, etc.</pre>
124
+
125
+ <h4>Create Issue</h4>
126
+ <pre>Input:
127
+ {
128
+ "title": "Bug report",
129
+ "description": "Found a critical bug",
130
+ "labels": ["bug", "critical"],
131
+ "assignee_ids": [123]
132
+ }
133
+ Output: Created issue object</pre>
134
+
135
+ <h4>Get File</h4>
136
+ <pre>Input:
137
+ {
138
+ "file_path": "README.md",
139
+ "ref": "main"
140
+ }
141
+ Output: File object with content, encoding, size, etc.</pre>
142
+
143
+ <h4>Run Pipeline</h4>
144
+ <pre>Input:
145
+ {
146
+ "ref": "develop",
147
+ "variables": [
148
+ {"key": "ENV", "value": "staging"}
149
+ ]
150
+ }
151
+ Output: Pipeline object with id, status, etc.</pre>
152
+
153
+ <h4>Create Commit</h4>
154
+ <pre>Input:
155
+ {
156
+ "branch": "main",
157
+ "commit_message": "Update README.md",
158
+ "actions": [
159
+ {
160
+ "action": "update",
161
+ "file_path": "README.md",
162
+ "content": "Updated content here..."
163
+ }
164
+ ],
165
+ "author_email": "user@example.com",
166
+ "author_name": "User Name"
167
+ }
168
+ Output: Commit object with id, short_id, title, etc.</pre>
169
+
170
+ <h4>Get Commits</h4>
171
+ <pre>Input:
172
+ {
173
+ "ref_name": "main",
174
+ "per_page": 10,
175
+ "author": "user@example.com"
176
+ }
177
+ Output: Array of commit objects</pre>
178
+
179
+ <h4>Get Commit</h4>
180
+ <pre>Input:
181
+ {
182
+ "commit_sha": "abc123..."
183
+ }
184
+ Output: Detailed commit object with stats, files, etc.</pre>
185
+
186
+ <h3>Output</h3>
187
+ <p>Results are returned in msg.result. The structure depends on the action performed.</p>
188
+
189
+ <h3>Error Handling</h3>
190
+ <p>Errors from the GitLab API are caught and reported. Check msg.error for details.</p>
191
+ </script>
@@ -0,0 +1,248 @@
1
+ const logger = new (require("node-red-contrib-logger"))("GitLab Access");
2
+ logger.sendInfo("Copyright 2025 Jaroslav Peter Prib");
3
+
4
+ const axios = require('axios');
5
+
6
+ const actions = {
7
+ getRepo: async (RED, node, msg) => {
8
+ const url = `${node.gitlabUrl}/api/v4/projects/${encodeURIComponent(node.projectId)}`;
9
+ const response = await axios.get(url, {
10
+ headers: {
11
+ 'Private-Token': node.accessToken,
12
+ 'User-Agent': 'Node-RED-GitLab-Node'
13
+ }
14
+ });
15
+ return response.data;
16
+ },
17
+
18
+ listIssues: async (RED, node, msg) => {
19
+ const url = `${node.gitlabUrl}/api/v4/projects/${encodeURIComponent(node.projectId)}/issues`;
20
+ const params = {};
21
+ if (msg.payload && msg.payload.state) params.state = msg.payload.state;
22
+ if (msg.payload && msg.payload.labels) params.labels = msg.payload.labels;
23
+ if (msg.payload && msg.payload.assignee_id) params.assignee_id = msg.payload.assignee_id;
24
+
25
+ const response = await axios.get(url, {
26
+ headers: {
27
+ 'Private-Token': node.accessToken,
28
+ 'User-Agent': 'Node-RED-GitLab-Node'
29
+ },
30
+ params
31
+ });
32
+ return response.data;
33
+ },
34
+
35
+ createIssue: async (RED, node, msg) => {
36
+ if (!msg.payload || !msg.payload.title) {
37
+ throw new Error("msg.payload must contain title for issue creation");
38
+ }
39
+
40
+ const url = `${node.gitlabUrl}/api/v4/projects/${encodeURIComponent(node.projectId)}/issues`;
41
+ const data = {
42
+ title: msg.payload.title,
43
+ description: msg.payload.description || '',
44
+ labels: msg.payload.labels || [],
45
+ assignee_ids: msg.payload.assignee_ids || []
46
+ };
47
+
48
+ const response = await axios.post(url, data, {
49
+ headers: {
50
+ 'Private-Token': node.accessToken,
51
+ 'User-Agent': 'Node-RED-GitLab-Node'
52
+ }
53
+ });
54
+ return response.data;
55
+ },
56
+
57
+ getMergeRequests: async (RED, node, msg) => {
58
+ const url = `${node.gitlabUrl}/api/v4/projects/${encodeURIComponent(node.projectId)}/merge_requests`;
59
+ const params = {};
60
+ if (msg.payload && msg.payload.state) params.state = msg.payload.state;
61
+ if (msg.payload && msg.payload.source_branch) params.source_branch = msg.payload.source_branch;
62
+ if (msg.payload && msg.payload.target_branch) params.target_branch = msg.payload.target_branch;
63
+
64
+ const response = await axios.get(url, {
65
+ headers: {
66
+ 'Private-Token': node.accessToken,
67
+ 'User-Agent': 'Node-RED-GitLab-Node'
68
+ },
69
+ params
70
+ });
71
+ return response.data;
72
+ },
73
+
74
+ createMergeRequest: async (RED, node, msg) => {
75
+ if (!msg.payload || !msg.payload.title || !msg.payload.source_branch || !msg.payload.target_branch) {
76
+ throw new Error("msg.payload must contain title, source_branch, and target_branch for MR creation");
77
+ }
78
+
79
+ const url = `${node.gitlabUrl}/api/v4/projects/${encodeURIComponent(node.projectId)}/merge_requests`;
80
+ const data = {
81
+ title: msg.payload.title,
82
+ description: msg.payload.description || '',
83
+ source_branch: msg.payload.source_branch,
84
+ target_branch: msg.payload.target_branch,
85
+ assignee_id: msg.payload.assignee_id,
86
+ labels: msg.payload.labels || []
87
+ };
88
+
89
+ const response = await axios.post(url, data, {
90
+ headers: {
91
+ 'Private-Token': node.accessToken,
92
+ 'User-Agent': 'Node-RED-GitLab-Node'
93
+ }
94
+ });
95
+ return response.data;
96
+ },
97
+
98
+ getFile: async (RED, node, msg) => {
99
+ const filePath = msg.payload && msg.payload.file_path ? msg.payload.file_path : node.filePath;
100
+ if (!filePath) {
101
+ throw new Error("file_path must be provided in msg.payload or configured in node");
102
+ }
103
+
104
+ const url = `${node.gitlabUrl}/api/v4/projects/${encodeURIComponent(node.projectId)}/repository/files/${encodeURIComponent(filePath)}`;
105
+ const params = {};
106
+ if (msg.payload && msg.payload.ref) params.ref = msg.payload.ref;
107
+ else params.ref = 'main';
108
+
109
+ const response = await axios.get(url, {
110
+ headers: {
111
+ 'Private-Token': node.accessToken,
112
+ 'User-Agent': 'Node-RED-GitLab-Node'
113
+ },
114
+ params
115
+ });
116
+ return {
117
+ file_path: response.data.file_path,
118
+ file_name: response.data.file_name,
119
+ size: response.data.size,
120
+ encoding: response.data.encoding,
121
+ content: Buffer.from(response.data.content, response.data.encoding).toString('utf8'),
122
+ ref: response.data.ref,
123
+ blob_id: response.data.blob_id,
124
+ commit_id: response.data.commit_id,
125
+ last_commit_id: response.data.last_commit_id
126
+ };
127
+ },
128
+
129
+ runPipeline: async (RED, node, msg) => {
130
+ const url = `${node.gitlabUrl}/api/v4/projects/${encodeURIComponent(node.projectId)}/pipeline`;
131
+ const data = {
132
+ ref: msg.payload && msg.payload.ref ? msg.payload.ref : 'main',
133
+ variables: msg.payload && msg.payload.variables ? msg.payload.variables : []
134
+ };
135
+
136
+ const response = await axios.post(url, data, {
137
+ headers: {
138
+ 'Private-Token': node.accessToken,
139
+ 'User-Agent': 'Node-RED-GitLab-Node'
140
+ }
141
+ });
142
+ return response.data;
143
+ },
144
+
145
+ createCommit: async (RED, node, msg) => {
146
+ if (!msg.payload || !msg.payload.branch || !msg.payload.commit_message || !msg.payload.actions) {
147
+ throw new Error("msg.payload must contain branch, commit_message, and actions for commit creation");
148
+ }
149
+
150
+ const url = `${node.gitlabUrl}/api/v4/projects/${encodeURIComponent(node.projectId)}/repository/commits`;
151
+ const data = {
152
+ branch: msg.payload.branch,
153
+ commit_message: msg.payload.commit_message,
154
+ actions: msg.payload.actions,
155
+ author_email: msg.payload.author_email,
156
+ author_name: msg.payload.author_name
157
+ };
158
+
159
+ const response = await axios.post(url, data, {
160
+ headers: {
161
+ 'Private-Token': node.accessToken,
162
+ 'User-Agent': 'Node-RED-GitLab-Node'
163
+ }
164
+ });
165
+ return response.data;
166
+ },
167
+
168
+ getCommits: async (RED, node, msg) => {
169
+ const url = `${node.gitlabUrl}/api/v4/projects/${encodeURIComponent(node.projectId)}/repository/commits`;
170
+ const params = {};
171
+ if (msg.payload && msg.payload.ref_name) params.ref_name = msg.payload.ref_name;
172
+ if (msg.payload && msg.payload.since) params.since = msg.payload.since;
173
+ if (msg.payload && msg.payload.until) params.until = msg.payload.until;
174
+ if (msg.payload && msg.payload.path) params.path = msg.payload.path;
175
+ if (msg.payload && msg.payload.author) params.author = msg.payload.author;
176
+ params.per_page = msg.payload && msg.payload.per_page ? msg.payload.per_page : 20;
177
+
178
+ const response = await axios.get(url, {
179
+ headers: {
180
+ 'Private-Token': node.accessToken,
181
+ 'User-Agent': 'Node-RED-GitLab-Node'
182
+ },
183
+ params
184
+ });
185
+ return response.data;
186
+ },
187
+
188
+ getCommit: async (RED, node, msg) => {
189
+ const commitSha = msg.payload && msg.payload.commit_sha ? msg.payload.commit_sha : '';
190
+ if (!commitSha) {
191
+ throw new Error("commit_sha must be provided in msg.payload");
192
+ }
193
+
194
+ const url = `${node.gitlabUrl}/api/v4/projects/${encodeURIComponent(node.projectId)}/repository/commits/${commitSha}`;
195
+
196
+ const response = await axios.get(url, {
197
+ headers: {
198
+ 'Private-Token': node.accessToken,
199
+ 'User-Agent': 'Node-RED-GitLab-Node'
200
+ }
201
+ });
202
+ return response.data;
203
+ }
204
+
205
+ module.exports = function (RED) {
206
+ function GitLabNode(config) {
207
+ RED.nodes.createNode(this, config);
208
+ const node = Object.assign(this, config, {
209
+ gitlabUrl: config.gitlabUrl || 'https://gitlab.com',
210
+ accessToken: config.accessToken || '',
211
+ projectId: config.projectId || '',
212
+ filePath: config.filePath || ''
213
+ });
214
+
215
+ node.callFunction = actions[config.action];
216
+ if (!node.callFunction) {
217
+ node.error("Unknown action: " + config.action);
218
+ node.status({ fill: "red", shape: "ring", text: "Unknown action: " + config.action });
219
+ return;
220
+ }
221
+
222
+ if (!node.accessToken) {
223
+ node.error("GitLab access token is required");
224
+ node.status({ fill: "red", shape: "ring", text: "Access token required" });
225
+ return;
226
+ }
227
+
228
+ if (!node.projectId) {
229
+ node.error("GitLab project ID is required");
230
+ node.status({ fill: "red", shape: "ring", text: "Project ID required" });
231
+ return;
232
+ }
233
+
234
+ node.status({ fill: "green", shape: "dot", text: "Ready" });
235
+
236
+ node.on('input', async function (msg) {
237
+ try {
238
+ msg.result = await node.callFunction(RED, node, msg);
239
+ node.send(msg);
240
+ node.status({ fill: "green", shape: "dot", text: "Success" });
241
+ } catch (error) {
242
+ node.error(error.message, msg);
243
+ node.status({ fill: "red", shape: "ring", text: error.message.substring(0, 20) });
244
+ }
245
+ });
246
+ }
247
+ RED.nodes.registerType("gitlab", GitLabNode);
248
+ };
@@ -0,0 +1,17 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
2
+ <defs>
3
+ <linearGradient id="gitlabGradient" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#FC6D26;stop-opacity:1" />
5
+ <stop offset="100%" style="stop-color:#E24329;stop-opacity:1" />
6
+ </linearGradient>
7
+ </defs>
8
+
9
+ <!-- GitLab fox-like logo simplified -->
10
+ <path d="M16 2C8.3 2 2 8.3 2 16s6.3 14 14 14 14-6.3 14-14S23.7 2 16 2zm6.5 20.5c-.3.3-.7.3-1 0L16 17l-5.5 5.5c-.3.3-.7.3-1 0s-.3-.7 0-1L15 16l-5.5-5.5c-.3-.3-.3-.7 0-1s.7-.3 1 0L16 15l5.5-5.5c.3-.3.7-.3 1 0s.3.7 0 1L17 16l5.5 5.5c.3.3.3.7 0 1z" fill="url(#gitlabGradient)"/>
11
+
12
+ <!-- Simplified fox face -->
13
+ <circle cx="16" cy="12" r="2" fill="#FFFFFF"/>
14
+ <circle cx="13" cy="10" r="1" fill="#FFFFFF"/>
15
+ <circle cx="19" cy="10" r="1" fill="#FFFFFF"/>
16
+ <path d="M14 14c1-1 2-1 3 0" stroke="#FFFFFF" stroke-width="1" fill="none" stroke-linecap="round"/>
17
+ </svg>
@@ -0,0 +1,32 @@
1
+ function alphabeta(node, depth,
2
+ isTerminalNode=node=>node.children.lenght==0 ,
3
+ forEachChild=call=>this.children.forEach(c=>call(c)),
4
+ getHeuristicValue=node=>node.value,
5
+ alpha=-Infinity, beta=Infinity,
6
+ maximizingPlayer=true
7
+ ){
8
+ if( depth == 0 || isTerminalNode(node)) return getHeuristicValue (node)
9
+ const notMaximizingPlayer=!maximizingPlayer
10
+ const minMaxFunction=maximizingPlayer?Math.max:Math.min
11
+ let value=Infinity*(maximizingPlayer?-1:1)
12
+ let loopFunction=maximizingPlayer?
13
+ child=>{
14
+ value = minMaxFunction(value,
15
+ minimax(child,depth-1,isTerminalNode,forEachChild,getHeuristicValue ,alpha, beta, notMaximizingPlayer))
16
+ if(value >= beta ) throw Error("break")
17
+ else alpha = minMaxFunction(alpha, value)
18
+ }:child=>{
19
+ value = minMaxFunction(value,
20
+ minimax(child,depth-1,isTerminalNode,forEachChild,getHeuristicValue ,alpha, beta, notMaximizingPlayer))
21
+ if(value <= alpha) throw Error("break")
22
+ beta = minMaxFunction(beta, value)
23
+ }
24
+ try{
25
+ forEachChild(loopFunction)
26
+ } catch(ex){
27
+ if(ex.message!=="break") throw ex
28
+ }
29
+ return value
30
+ }
31
+
32
+ module.exports=alphabeta
package/lib/GraphDB.js CHANGED
@@ -1,14 +1,45 @@
1
1
  require("../lib/objectExtensions")
2
+ function Edge(from,to,properties){
3
+ if(!from) throw Error("from vertix is not defined")
4
+ if(!to) throw Error("to vertix is not defined")
5
+ if(!from instanceof Vertex) throw Error("from not type Vertex")
6
+ if(!to instanceof Vertex) throw Error("to not type Vertex")
7
+ Object.assign(this,{_from:from,_to:to},properties)
8
+ from.addTo(this)
9
+ to.addFrom(this)
10
+ }
11
+ function Vertex(properties){
12
+ Object.assign(this,{_to:[],_from:[]},properties)
13
+ }
14
+ Vertex.prototype.addTo=function(r){
15
+ this._to.push(r)
16
+ }
17
+ Vertex.prototype.addFrom=function(r){
18
+ this._from.push(r)
19
+ }
2
20
  function GraphDB(properties){
3
- Object.assign(this,{type:null,vertices:[],edges:[]},properties)
4
-
21
+ Object.assign(this,{vertices:[],edges:[]},properties)
22
+ }
23
+ GraphDB.prototype.addEdge=function(from,to,properties) {
24
+ const edge=new Edge(from,to,properties)
25
+ this.edges.push(edge)
26
+ return edge
27
+ }
28
+ GraphDB.prototype.addVertex=function(vertexDetails) {
29
+ const vertex=new Vertex(vertexDetails)
30
+ this.vertices.push(vertex)
31
+ return vertex
32
+ }
33
+ GraphDB.prototype.getEdgesCount=function() {
34
+ return this.edges.length
35
+ }
36
+ GraphDB.prototype.getVerticesCount=function() {
37
+ return this.vertices.length
5
38
  }
6
- GraphDB.prototype.addVertex=function(vertex) {
7
- this.vertices.addList(vertex)
39
+ GraphDB.prototype.getVertices=function(filterFunction) {
40
+ return this.vertices.filter(filterFunction)
8
41
  }
9
- GraphDB.prototype.addEdge=function(from,to) {
10
- this.edges.addList({from:from,to:to})
42
+ GraphDB.prototype.getEdges=function(filterFunction) {
43
+ return this.Edges.filter(filterFunction)
11
44
  }
12
-
13
- this.addErrorFunctions()
14
- module.exports=GraphDB
45
+ module.exports=GraphDB
package/lib/MinMax.js ADDED
@@ -0,0 +1,17 @@
1
+ function minimax(node, depth,
2
+ isTerminalNode=node=>node.children.lenght==0 ,
3
+ forEachChild=call=>this.children.forEach(c=>call(c)),
4
+ getHeuristicValue =node=>node.value,
5
+ maximizingPlayer=true
6
+ ){
7
+ if( depth == 0 || isTerminalNode(node)) return getHeuristicValue (node)
8
+ const notMaximizingPlayer=!maximizingPlayer
9
+ const minMaxFunction=maximizingPlayer?Math.max:Math.min
10
+ let value=Infinity*(maximizingPlayer?-1:1)
11
+ forEachChild(child=> value = minMaxFunction(value,
12
+ minimax(child,depth-1,isTerminalNode,forEachChild,getHeuristicValue ,notMaximizingPlayer))
13
+ )
14
+ return value
15
+ }
16
+
17
+ module.exports=minimax
package/lib/Tree.js ADDED
@@ -0,0 +1,64 @@
1
+ function Level(parent,...children){
2
+ this.children=children
3
+ this.setBTree(10)
4
+ }
5
+ function Leaf(parent,value){
6
+ this.values=[]
7
+ }
8
+ Leaf.prototype.find=function(value,foundCall,notFoundCall=foundCall,notFoundAllCall=v=>notFoundCall(0,v)){
9
+ let i=this.keys.length
10
+ const key=this.getKey(value)
11
+ while (i >= 0){
12
+ const currentKey=this.getKey(this.values[i])
13
+ if(key>currentKey) return notFoundCall(i,key)
14
+ if(key==currentKey) return foundCall(i,key)
15
+ i--
16
+ }
17
+ notFoundAllCall(key)
18
+ }
19
+ Leaf.prototype.getKey=function(node){return node}
20
+ Leaf.prototype.insert=function(value){
21
+ const _this=this
22
+ this.find(value,i=>_this.values.splice(i, 0, value))
23
+ }
24
+ function Tree (root=new Level(null)){
25
+ this.root=root
26
+ }
27
+ Tree.prototype.setDegree=function(v){this.degree=v}
28
+
29
+
30
+
31
+ Tree.prototype.insert(key,value) {
32
+ const root = this.root;
33
+ if(root.keys.length === (2 * this.degree - 1)) { // Root is full
34
+ const newRoot = new BTreeNode(false);
35
+ newRoot.children.push(root);
36
+ this.splitChild(newRoot, 0, root);
37
+ this.root = newRoot;
38
+ this.insertNonFull(newRoot, key);
39
+ } else {
40
+ this.insertNonFull(root, key);
41
+ }
42
+ }
43
+
44
+ Tree.prototype.insertNonFull(node, key) {
45
+ let i = node.keys.length - 1;
46
+ if (node.isLeaf) {
47
+
48
+ } else {
49
+ while (i >= 0 && key < node.keys[i]) {
50
+ i--;
51
+ }
52
+ i++;
53
+ if (node.children[i].keys.length === (2 * this.degree - 1)) {
54
+ this.splitChild(node, i, node.children[i]);
55
+ if (key > node.keys[i]) {
56
+ i++;
57
+ }
58
+ }
59
+ this.insertNonFull(node.children[i], key);
60
+ }
61
+ }
62
+
63
+
64
+ module.exports=Tree
@@ -440,8 +440,26 @@ const nullif=(a,b)=>{return a==b?null:a}
440
440
  defineMethod(type,"deepClone",function(){ return new type(this)})
441
441
  })
442
442
 
443
+ const getWord=(value,wordPosition)=>value.split(/\s+/g,wordPosition+1)[wordPosition-1]
444
+
445
+ const deepClone=(deepObject) =>{
446
+ if(deepObject==null) return null;
447
+ if(deepObject instanceof Array)
448
+ var newObj=[];
449
+ else if(deepObject instanceof String)
450
+ return new String(deepObject);
451
+ else if(deepObject instanceof Number)
452
+ return new Number(deepObject);
453
+ else if(deepObject instanceof Date)
454
+ return new Date(deepObject);
455
+ else if(typeof deepObject == "object")
456
+ var newObj={};
457
+ else return deepObject;
458
+ for (const i in deepObject)
459
+ newObj[i]=deepClone(deepObject[i]);
460
+ return newObj;
461
+ }
443
462
 
444
- //defineMethod(TypedArray,"deepClone",function(){ return new type(this)})
445
463
  defineMethod(Array,"deepClone",function(){
446
464
  const clone=[]
447
465
  for (let i in this)
@@ -449,11 +467,13 @@ defineMethod(Array,"deepClone",function(){
449
467
  return clone
450
468
  })
451
469
  defineMethod(Object,"deepClone",function(){
452
- const clone={}
453
- for (let i in this)
454
- clone[i]=this[i].deepClone()
455
- return clone
470
+ // const clone={}
471
+ // for (let i in this)
472
+ // clone[i]=this[i].deepClone()
473
+ // return clone
474
+ return deepClone(this)
456
475
  })
476
+ const rangeLimit=(value,min=value,max=value)=>value<min?min:value>max?max:value
457
477
  defineMethod(Number, "rangeLimit",function(min,max) {return (min!=null && this<min) ? min : ((max!=null && this>max) ? max : this)})
458
478
  defineMethod(BigInt, "rangeLimit",function(min,max) {return (min!=null && this<min) ? min : ((max!=null && this>max) ? max : this)})
459
479
  defineMethod(Date, "rangeLimit",function(min,max) {return (min!=null && this<min) ? min : ((max!=null && this>max) ? max : this)})
@@ -465,7 +485,10 @@ module.exports={
465
485
  coalesce:coalesce,
466
486
  colours:colours,
467
487
  colourSmallList:colourSmallList,
488
+ deepClone,deepClone,
489
+ getWord,getWord,
468
490
  nullif:nullif,
491
+ rangeLimit,rangeLimit,
469
492
  toDateType,
470
493
  toDateTypeZulu,
471
494
  }