@inglorious/utils 3.8.0 → 4.0.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.
- package/README.md +67 -3
- package/package.json +88 -12
- package/src/algorithms/decision-tree.js +3 -3
- package/src/algorithms/path-finding.js +6 -6
- package/src/data-structures/board.js +97 -15
- package/src/data-structures/index.js +1 -2
- package/src/data-structures/objects.js +352 -34
- package/src/data-structures/tree.js +1 -1
- package/src/functions/functions.js +168 -0
- package/src/functions/index.js +1 -4
- package/src/math/circle.js +5 -7
- package/src/math/index.js +0 -4
- package/src/math/line.js +3 -3
- package/src/math/point.js +10 -9
- package/src/math/quaternions.js +20 -4
- package/src/math/rectangle.js +4 -4
- package/src/math/segment.js +11 -5
- package/src/math/vectors.js +471 -65
- package/src/physics/acceleration.js +2 -3
- package/src/physics/friction.js +2 -2
- package/src/physics/gravity.js +2 -2
- package/src/physics/jump.js +0 -4
- package/src/physics/velocity.js +2 -3
- package/src/v.js +1 -1
- package/types/algorithms/decision-tree.d.ts +27 -0
- package/types/algorithms/index.d.ts +2 -0
- package/types/algorithms/path-finding.d.ts +69 -0
- package/types/data-structures/array.d.ts +56 -0
- package/types/data-structures/board.d.ts +121 -0
- package/types/data-structures/boolean.d.ts +4 -0
- package/types/data-structures/heap.d.ts +69 -0
- package/types/data-structures/index.d.ts +8 -0
- package/types/data-structures/objects.d.ts +237 -0
- package/types/data-structures/set.d.ts +4 -0
- package/types/data-structures/tree.d.ts +21 -0
- package/types/functions/functions.d.ts +57 -0
- package/types/functions/index.d.ts +1 -0
- package/types/index.d.ts +6 -4
- package/types/math/circle.d.ts +22 -0
- package/types/math/hitmask.d.ts +20 -0
- package/types/math/index.d.ts +14 -0
- package/types/math/line.d.ts +11 -0
- package/types/math/linear-interpolation.d.ts +2 -0
- package/types/math/numbers.d.ts +26 -0
- package/types/math/point.d.ts +25 -0
- package/types/math/quaternions.d.ts +10 -0
- package/types/math/rectangle.d.ts +36 -0
- package/types/math/rng.d.ts +14 -0
- package/types/math/segment.d.ts +23 -0
- package/types/math/statistics.d.ts +11 -0
- package/types/math/triangle.d.ts +5 -0
- package/types/math/trigonometry.d.ts +26 -0
- package/types/math/vectors.d.ts +190 -0
- package/types/physics/acceleration.d.ts +24 -0
- package/types/physics/friction.d.ts +11 -0
- package/types/physics/gravity.d.ts +20 -0
- package/types/physics/index.d.ts +5 -0
- package/types/physics/jump.d.ts +10 -0
- package/types/physics/velocity.d.ts +20 -0
- package/types/v.d.ts +7 -3
- package/src/data-structures/object.js +0 -320
- package/src/functions/function.js +0 -9
- package/src/math/quaternion.js +0 -22
- package/src/math/vector.js +0 -426
- package/types/algorithms.d.ts +0 -26
- package/types/data-structures.d.ts +0 -53
- package/types/math.d.ts +0 -90
package/README.md
CHANGED
|
@@ -25,12 +25,43 @@ npm install @inglorious/utils
|
|
|
25
25
|
|
|
26
26
|
Here are a few examples of how you can use the utilities in this package.
|
|
27
27
|
|
|
28
|
+
### `compose`
|
|
29
|
+
|
|
30
|
+
Compose functions together from right to left.
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
import { compose } from "@inglorious/utils/functions"
|
|
34
|
+
|
|
35
|
+
const add = (a) => (b) => a + b
|
|
36
|
+
const multiply = (a) => (b) => a * b
|
|
37
|
+
|
|
38
|
+
const calculate = compose(
|
|
39
|
+
add(10), // 30 + 10 = 40
|
|
40
|
+
multiply(2), // 15 * 2 = 30
|
|
41
|
+
add(5), // 10 + 5 = 15
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
const result = calculate(10) // 40
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### `debounce`
|
|
48
|
+
|
|
49
|
+
Delay a function until calls stop for a given amount of time.
|
|
50
|
+
|
|
51
|
+
```javascript
|
|
52
|
+
import { debounce } from "@inglorious/utils/functions"
|
|
53
|
+
|
|
54
|
+
const debouncedSave = debounce(() => {
|
|
55
|
+
save()
|
|
56
|
+
}, 300)
|
|
57
|
+
```
|
|
58
|
+
|
|
28
59
|
### `pipe`
|
|
29
60
|
|
|
30
61
|
Compose functions together in a readable, left-to-right sequence.
|
|
31
62
|
|
|
32
63
|
```javascript
|
|
33
|
-
import { pipe } from "@inglorious/utils/functions
|
|
64
|
+
import { pipe } from "@inglorious/utils/functions"
|
|
34
65
|
|
|
35
66
|
const add = (a) => (b) => a + b
|
|
36
67
|
const multiply = (a) => (b) => a * b
|
|
@@ -44,12 +75,24 @@ const calculate = pipe(
|
|
|
44
75
|
const result = calculate(10) // 40
|
|
45
76
|
```
|
|
46
77
|
|
|
78
|
+
### `throttle`
|
|
79
|
+
|
|
80
|
+
Run a function immediately, then suppress repeated calls until the wait time has elapsed.
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
import { throttle } from "@inglorious/utils/functions"
|
|
84
|
+
|
|
85
|
+
const throttledSave = throttle(() => {
|
|
86
|
+
save()
|
|
87
|
+
}, 300)
|
|
88
|
+
```
|
|
89
|
+
|
|
47
90
|
### Vector Math
|
|
48
91
|
|
|
49
92
|
Perform vector operations on plain objects.
|
|
50
93
|
|
|
51
94
|
```javascript
|
|
52
|
-
import { add } from "@inglorious/utils/
|
|
95
|
+
import { add } from "@inglorious/utils/vectors"
|
|
53
96
|
|
|
54
97
|
const position = [10, 20]
|
|
55
98
|
const velocity = [2, -1]
|
|
@@ -64,11 +107,32 @@ const newPosition = add(position, velocity)
|
|
|
64
107
|
|
|
65
108
|
This package is designed to be used with subpath imports, which helps with tree-shaking.
|
|
66
109
|
|
|
110
|
+
Most modules are grouped by category:
|
|
111
|
+
|
|
67
112
|
- **`@inglorious/utils/algorithms`**: Utilities for AI algorithms, like decision trees and A\*.
|
|
68
|
-
- **`@inglorious/utils/
|
|
113
|
+
- **`@inglorious/utils/data-structures`**: Utilities for arrays, boards, heaps, objects, sets, strings, and trees.
|
|
114
|
+
- **`@inglorious/utils/functions`**: Utilities for function composition and timing.
|
|
69
115
|
- **`@inglorious/utils/math`**: Utilities for math operations.
|
|
70
116
|
- **`@inglorious/utils/physics`**: Utilities for calculations on friction, acceleration, and gravity.
|
|
71
117
|
|
|
118
|
+
The four largest modules are also available as top-level subpaths, so you don't need to
|
|
119
|
+
know whether a helper lives under `data-structures` or `math`:
|
|
120
|
+
|
|
121
|
+
- **`@inglorious/utils/functions`**: `compose`, `debounce`, `isFunction`, `pipe`, `throttle`.
|
|
122
|
+
- **`@inglorious/utils/objects`**: Single-object helpers (`clone`, `get`, `set`, `produce`, ...) alongside multi-object helpers (`merge`, `extend`, `defaults`, ...).
|
|
123
|
+
- **`@inglorious/utils/quaternions`**: `quaternion` and `combine`.
|
|
124
|
+
- **`@inglorious/utils/vectors`**: Single-vector helpers (`magnitude`, `normalize`, `rotate`, ...) alongside multi-vector helpers (`cross`, `dot`, `sum`, ...).
|
|
125
|
+
|
|
126
|
+
`divide`, `mod`, `multiply` and `power` accept either a scalar or one or more vectors:
|
|
127
|
+
a scalar is applied to every component, while vectors are combined component-wise.
|
|
128
|
+
|
|
129
|
+
```javascript
|
|
130
|
+
import { multiply } from "@inglorious/utils/vectors"
|
|
131
|
+
|
|
132
|
+
multiply([1, 2, 3], 2) // => [2, 4, 6]
|
|
133
|
+
multiply([1, 2, 3], [4, 5, 6]) // => [4, 10, 18]
|
|
134
|
+
```
|
|
135
|
+
|
|
72
136
|
---
|
|
73
137
|
|
|
74
138
|
## License
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inglorious/utils",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "A set of general-purpose utility functions designed with functional programming principles in mind.",
|
|
5
|
-
"author": "
|
|
5
|
+
"author": "Matteo Antony Mistretta <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -26,13 +26,89 @@
|
|
|
26
26
|
"types": "./types/index.d.ts",
|
|
27
27
|
"import": "./src/index.js"
|
|
28
28
|
},
|
|
29
|
-
"./
|
|
30
|
-
"types": "./types/
|
|
31
|
-
"import": "./src/
|
|
29
|
+
"./algorithms": {
|
|
30
|
+
"types": "./types/algorithms/index.d.ts",
|
|
31
|
+
"import": "./src/algorithms/index.js"
|
|
32
32
|
},
|
|
33
|
-
"
|
|
34
|
-
"types": "./types/*.d.ts",
|
|
35
|
-
"import": "./src
|
|
33
|
+
"./algorithms/*.js": {
|
|
34
|
+
"types": "./types/algorithms/*.d.ts",
|
|
35
|
+
"import": "./src/algorithms/*.js"
|
|
36
|
+
},
|
|
37
|
+
"./algorithms/*": {
|
|
38
|
+
"types": "./types/algorithms/*.d.ts",
|
|
39
|
+
"import": "./src/algorithms/*.js"
|
|
40
|
+
},
|
|
41
|
+
"./data-structures": {
|
|
42
|
+
"types": "./types/data-structures/index.d.ts",
|
|
43
|
+
"import": "./src/data-structures/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./data-structures/*.js": {
|
|
46
|
+
"types": "./types/data-structures/*.d.ts",
|
|
47
|
+
"import": "./src/data-structures/*.js"
|
|
48
|
+
},
|
|
49
|
+
"./data-structures/*": {
|
|
50
|
+
"types": "./types/data-structures/*.d.ts",
|
|
51
|
+
"import": "./src/data-structures/*.js"
|
|
52
|
+
},
|
|
53
|
+
"./functions": {
|
|
54
|
+
"types": "./types/functions/index.d.ts",
|
|
55
|
+
"import": "./src/functions/index.js"
|
|
56
|
+
},
|
|
57
|
+
"./math": {
|
|
58
|
+
"types": "./types/math/index.d.ts",
|
|
59
|
+
"import": "./src/math/index.js"
|
|
60
|
+
},
|
|
61
|
+
"./math/*.js": {
|
|
62
|
+
"types": "./types/math/*.d.ts",
|
|
63
|
+
"import": "./src/math/*.js"
|
|
64
|
+
},
|
|
65
|
+
"./math/*": {
|
|
66
|
+
"types": "./types/math/*.d.ts",
|
|
67
|
+
"import": "./src/math/*.js"
|
|
68
|
+
},
|
|
69
|
+
"./physics": {
|
|
70
|
+
"types": "./types/physics/index.d.ts",
|
|
71
|
+
"import": "./src/physics/index.js"
|
|
72
|
+
},
|
|
73
|
+
"./physics/*.js": {
|
|
74
|
+
"types": "./types/physics/*.d.ts",
|
|
75
|
+
"import": "./src/physics/*.js"
|
|
76
|
+
},
|
|
77
|
+
"./physics/*": {
|
|
78
|
+
"types": "./types/physics/*.d.ts",
|
|
79
|
+
"import": "./src/physics/*.js"
|
|
80
|
+
},
|
|
81
|
+
"./objects.js": {
|
|
82
|
+
"types": "./types/data-structures/objects.d.ts",
|
|
83
|
+
"import": "./src/data-structures/objects.js"
|
|
84
|
+
},
|
|
85
|
+
"./objects": {
|
|
86
|
+
"types": "./types/data-structures/objects.d.ts",
|
|
87
|
+
"import": "./src/data-structures/objects.js"
|
|
88
|
+
},
|
|
89
|
+
"./quaternions.js": {
|
|
90
|
+
"types": "./types/math/quaternions.d.ts",
|
|
91
|
+
"import": "./src/math/quaternions.js"
|
|
92
|
+
},
|
|
93
|
+
"./quaternions": {
|
|
94
|
+
"types": "./types/math/quaternions.d.ts",
|
|
95
|
+
"import": "./src/math/quaternions.js"
|
|
96
|
+
},
|
|
97
|
+
"./vectors.js": {
|
|
98
|
+
"types": "./types/math/vectors.d.ts",
|
|
99
|
+
"import": "./src/math/vectors.js"
|
|
100
|
+
},
|
|
101
|
+
"./vectors": {
|
|
102
|
+
"types": "./types/math/vectors.d.ts",
|
|
103
|
+
"import": "./src/math/vectors.js"
|
|
104
|
+
},
|
|
105
|
+
"./v.js": {
|
|
106
|
+
"types": "./types/v.d.ts",
|
|
107
|
+
"import": "./src/v.js"
|
|
108
|
+
},
|
|
109
|
+
"./v": {
|
|
110
|
+
"types": "./types/v.d.ts",
|
|
111
|
+
"import": "./src/v.js"
|
|
36
112
|
}
|
|
37
113
|
},
|
|
38
114
|
"files": [
|
|
@@ -45,10 +121,10 @@
|
|
|
45
121
|
},
|
|
46
122
|
"sideEffects": false,
|
|
47
123
|
"devDependencies": {
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
124
|
+
"@inglorious/eslint-config": "1.1.2",
|
|
125
|
+
"prettier": "^3.9.6",
|
|
126
|
+
"vite": "^8.2.2",
|
|
127
|
+
"vitest": "^5.0.0"
|
|
52
128
|
},
|
|
53
129
|
"engines": {
|
|
54
130
|
"node": ">= 22"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @typedef {import("../../types/algorithms").Conditions} Conditions
|
|
3
|
-
* @typedef {import("../../types/algorithms").Outcome} Outcome
|
|
4
|
-
* @typedef {import("../../types/algorithms").DecisionTree} DecisionTree
|
|
2
|
+
* @typedef {import("../../types/algorithms/decision-tree").Conditions} Conditions
|
|
3
|
+
* @typedef {import("../../types/algorithms/decision-tree").Outcome} Outcome
|
|
4
|
+
* @typedef {import("../../types/algorithms/decision-tree").DecisionTree} DecisionTree
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @typedef {import("../../types/
|
|
3
|
-
* @typedef {import("../../types/
|
|
2
|
+
* @typedef {import("../../types/algorithms/path-finding").Node} Node
|
|
3
|
+
* @typedef {import("../../types/algorithms/path-finding").Graph} Graph
|
|
4
|
+
* @typedef {import("../../types/math/vectors").Vector2} Vector2
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
7
|
import { contains, push, remove, root } from "../data-structures/heap.js"
|
|
7
|
-
import { abs, magnitude } from "../math/
|
|
8
|
-
import { subtract } from "../math/vectors.js"
|
|
8
|
+
import { abs, magnitude, subtract } from "../math/vectors.js"
|
|
9
9
|
|
|
10
10
|
const NO_COST = 0
|
|
11
11
|
|
|
@@ -32,7 +32,7 @@ export const eucledianDistance = (a, b) =>
|
|
|
32
32
|
*
|
|
33
33
|
* @param {Node} a - The first node.
|
|
34
34
|
* @param {Node} b - The second node.
|
|
35
|
-
* @returns {
|
|
35
|
+
* @returns {Vector2} The component-wise Manhattan distance between the two nodes.
|
|
36
36
|
*/
|
|
37
37
|
export const manhattanDistance = (a, b) => abs(subtract(a.position, b.position))
|
|
38
38
|
|
|
@@ -61,7 +61,7 @@ const compareTotalCost = (a, b) => b.totalCost - a.totalCost
|
|
|
61
61
|
* @param {string} start - The ID of the start node.
|
|
62
62
|
* @param {string} end - The ID of the end node.
|
|
63
63
|
* @param {(a: Node, b: Node) => number} [heuristic=eucledianDistance] - The heuristic function to estimate the cost.
|
|
64
|
-
* @returns {string[]} -
|
|
64
|
+
* @returns {string[]|undefined} - The node IDs representing the shortest path, or `undefined` if no path exists.
|
|
65
65
|
*/
|
|
66
66
|
export function findPath(graph, start, end, heuristic = eucledianDistance) {
|
|
67
67
|
const { nodes, arcs } = adaptGraph(graph)
|
|
@@ -11,24 +11,55 @@ const DEFAULT_FILLER = () => null
|
|
|
11
11
|
*/
|
|
12
12
|
const DEFAULT_CELL_TO_STRING = (cell) => `${cell}`
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Default predicate that matches every neighboring cell.
|
|
16
|
+
* @returns {boolean} Always true.
|
|
17
|
+
*/
|
|
18
|
+
const DEFAULT_NEIGHBOR_PREDICATE = () => true
|
|
19
|
+
|
|
14
20
|
const FIRST_ROW = 0
|
|
15
21
|
const FIRST_COLUMN = 0
|
|
16
22
|
const LAST_ROW_OFFSET = 1
|
|
17
23
|
const LAST_COLUMN_OFFSET = 1
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
24
|
+
const DOWN = 1
|
|
25
|
+
const LEFT = -1
|
|
26
|
+
const RIGHT = 1
|
|
27
|
+
const UP = -1
|
|
28
|
+
const CENTER = 0
|
|
29
|
+
|
|
30
|
+
const BOTH = "both"
|
|
31
|
+
const HORIZONTAL = "horizontal"
|
|
32
|
+
const NO_WRAP = undefined
|
|
33
|
+
const VERTICAL = "vertical"
|
|
34
|
+
|
|
35
|
+
const NEIGHBOR_OFFSETS = [
|
|
36
|
+
[UP, LEFT],
|
|
37
|
+
[UP, CENTER],
|
|
38
|
+
[UP, RIGHT],
|
|
39
|
+
[CENTER, LEFT],
|
|
40
|
+
[CENTER, RIGHT],
|
|
41
|
+
[DOWN, LEFT],
|
|
42
|
+
[DOWN, CENTER],
|
|
43
|
+
[DOWN, RIGHT],
|
|
44
|
+
]
|
|
22
45
|
|
|
23
46
|
/**
|
|
24
|
-
*
|
|
25
|
-
* @param {
|
|
26
|
-
* @param {number}
|
|
27
|
-
* @param {number}
|
|
28
|
-
* @
|
|
47
|
+
* Counts the neighboring cells that satisfy a predicate.
|
|
48
|
+
* @param {Array} cells - The board cells.
|
|
49
|
+
* @param {[number, number]} coords - The coordinates [row, column].
|
|
50
|
+
* @param {[number, number]} size - Array containing the number of rows and columns.
|
|
51
|
+
* @param {Object} [options] - Neighbor options.
|
|
52
|
+
* @param {Function} [options.predicate=DEFAULT_NEIGHBOR_PREDICATE] - The predicate applied to each neighboring cell.
|
|
53
|
+
* @param {"horizontal" | "vertical" | "both"} [options.wrap=undefined] - The axes that wrap around board edges.
|
|
54
|
+
* @returns {number} The number of matching neighboring cells.
|
|
29
55
|
*/
|
|
30
|
-
function
|
|
31
|
-
|
|
56
|
+
export function countNeighbors(cells, coords, size, options = {}) {
|
|
57
|
+
const { predicate = DEFAULT_NEIGHBOR_PREDICATE, wrap = NO_WRAP } = options
|
|
58
|
+
const [, columns] = size
|
|
59
|
+
|
|
60
|
+
return neighbors(coords, size, { wrap }).filter(([row, column]) =>
|
|
61
|
+
predicate(cells[getIndex(row, column, columns)]),
|
|
62
|
+
).length
|
|
32
63
|
}
|
|
33
64
|
|
|
34
65
|
/**
|
|
@@ -56,7 +87,7 @@ export function down([i, j], [rows]) {
|
|
|
56
87
|
if (i === rows - LAST_ROW_OFFSET) {
|
|
57
88
|
throw new Error()
|
|
58
89
|
}
|
|
59
|
-
return [i +
|
|
90
|
+
return [i + DOWN, j]
|
|
60
91
|
}
|
|
61
92
|
|
|
62
93
|
/**
|
|
@@ -79,6 +110,17 @@ export function downRight(coords, size) {
|
|
|
79
110
|
return down(right(coords, size), size)
|
|
80
111
|
}
|
|
81
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Calculates the index in a one-dimensional array for given row and column.
|
|
115
|
+
* @param {number} row - The row index.
|
|
116
|
+
* @param {number} column - The column index.
|
|
117
|
+
* @param {number} columns - The total number of columns.
|
|
118
|
+
* @returns {number} The calculated index.
|
|
119
|
+
*/
|
|
120
|
+
export function getIndex(row, column, columns) {
|
|
121
|
+
return row * columns + column
|
|
122
|
+
}
|
|
123
|
+
|
|
82
124
|
/**
|
|
83
125
|
* Moves the given coordinates one step left.
|
|
84
126
|
* @param {[number, number]} coords - The current coordinates [row, column].
|
|
@@ -89,7 +131,36 @@ export function left([i, j]) {
|
|
|
89
131
|
if (j === FIRST_COLUMN) {
|
|
90
132
|
throw new Error()
|
|
91
133
|
}
|
|
92
|
-
return [i, j +
|
|
134
|
+
return [i, j + LEFT]
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Returns the coordinates neighboring the given coordinates that fall within the board.
|
|
139
|
+
* @param {[number, number]} coords - The coordinates [row, column].
|
|
140
|
+
* @param {[number, number]} size - Array containing the number of rows and columns.
|
|
141
|
+
* @param {Object} [options] - Neighbor options.
|
|
142
|
+
* @param {"horizontal" | "vertical" | "both"} [options.wrap=undefined] - The axes that wrap around board edges. "horizontal" wraps the column axis, "vertical" wraps the row axis, and "both" wraps each axis independently.
|
|
143
|
+
* @returns {[number, number][]} The neighboring coordinates within the board.
|
|
144
|
+
*/
|
|
145
|
+
export function neighbors([i, j], [rows, columns], options = {}) {
|
|
146
|
+
const { wrap = NO_WRAP } = options
|
|
147
|
+
const shouldWrapRows = wrap === BOTH || wrap === VERTICAL
|
|
148
|
+
const shouldWrapColumns = wrap === BOTH || wrap === HORIZONTAL
|
|
149
|
+
|
|
150
|
+
return NEIGHBOR_OFFSETS.map(([rowOffset, columnOffset]) => {
|
|
151
|
+
const row = shouldWrapRows ? wrapIndex(i + rowOffset, rows) : i + rowOffset
|
|
152
|
+
const column = shouldWrapColumns
|
|
153
|
+
? wrapIndex(j + columnOffset, columns)
|
|
154
|
+
: j + columnOffset
|
|
155
|
+
|
|
156
|
+
return [row, column]
|
|
157
|
+
}).filter(
|
|
158
|
+
([row, column]) =>
|
|
159
|
+
row >= FIRST_ROW &&
|
|
160
|
+
row < rows &&
|
|
161
|
+
column >= FIRST_COLUMN &&
|
|
162
|
+
column < columns,
|
|
163
|
+
)
|
|
93
164
|
}
|
|
94
165
|
|
|
95
166
|
/**
|
|
@@ -103,7 +174,7 @@ export function right([i, j], [, columns]) {
|
|
|
103
174
|
if (j === columns - LAST_COLUMN_OFFSET) {
|
|
104
175
|
throw new Error()
|
|
105
176
|
}
|
|
106
|
-
return [i, j +
|
|
177
|
+
return [i, j + RIGHT]
|
|
107
178
|
}
|
|
108
179
|
|
|
109
180
|
/**
|
|
@@ -135,7 +206,7 @@ export function up([i, j]) {
|
|
|
135
206
|
if (i === FIRST_ROW) {
|
|
136
207
|
throw new Error()
|
|
137
208
|
}
|
|
138
|
-
return [i +
|
|
209
|
+
return [i + UP, j]
|
|
139
210
|
}
|
|
140
211
|
|
|
141
212
|
/**
|
|
@@ -157,3 +228,14 @@ export function upLeft(coords, size) {
|
|
|
157
228
|
export function upRight(coords, size) {
|
|
158
229
|
return up(right(coords, size), size)
|
|
159
230
|
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Normalizes an index into a wrapping range.
|
|
234
|
+
* @param {number} index - The index to normalize.
|
|
235
|
+
* @param {number} length - The range length.
|
|
236
|
+
* @returns {number} The normalized index.
|
|
237
|
+
*/
|
|
238
|
+
function wrapIndex(index, length) {
|
|
239
|
+
const remainder = index % length
|
|
240
|
+
return remainder < FIRST_ROW ? remainder + length : remainder
|
|
241
|
+
}
|
|
@@ -2,10 +2,9 @@ import * as array from "./array.js"
|
|
|
2
2
|
import * as board from "./board.js"
|
|
3
3
|
import * as boolean from "./boolean.js"
|
|
4
4
|
import * as heap from "./heap.js"
|
|
5
|
-
import * as object from "./object.js"
|
|
6
5
|
import * as objects from "./objects.js"
|
|
7
6
|
import * as set from "./set.js"
|
|
8
7
|
import * as string from "./string.js"
|
|
9
8
|
import * as tree from "./tree.js"
|
|
10
9
|
|
|
11
|
-
export { array, board, boolean, heap,
|
|
10
|
+
export { array, board, boolean, heap, objects, set, string, tree }
|