@typeonce/ritmo-math 0.12.0 → 0.14.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/CHANGELOG.md +60 -0
- package/README.md +3 -3
- package/dist/Aabb.d.ts +15 -15
- package/dist/Aabb.d.ts.map +1 -1
- package/dist/Aabb.js +13 -5
- package/dist/Aabb.js.map +1 -1
- package/dist/Collide2.d.ts +48 -14
- package/dist/Collide2.d.ts.map +1 -1
- package/dist/Collide2.js +140 -17
- package/dist/Collide2.js.map +1 -1
- package/dist/Random.d.ts +16 -6
- package/dist/Random.d.ts.map +1 -1
- package/dist/Random.js +13 -3
- package/dist/Random.js.map +1 -1
- package/dist/Scalar.d.ts +26 -7
- package/dist/Scalar.d.ts.map +1 -1
- package/dist/Scalar.js +6 -3
- package/dist/Scalar.js.map +1 -1
- package/dist/Segment2.d.ts +56 -0
- package/dist/Segment2.d.ts.map +1 -0
- package/dist/Segment2.js +32 -0
- package/dist/Segment2.js.map +1 -0
- package/dist/Size2.d.ts +15 -15
- package/dist/Size2.d.ts.map +1 -1
- package/dist/Size2.js +13 -5
- package/dist/Size2.js.map +1 -1
- package/dist/Vector2.d.ts +15 -15
- package/dist/Vector2.d.ts.map +1 -1
- package/dist/Vector2.js +13 -5
- package/dist/Vector2.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/internal/aabb.d.ts +9 -2
- package/dist/internal/aabb.d.ts.map +1 -1
- package/dist/internal/aabb.js +3 -1
- package/dist/internal/aabb.js.map +1 -1
- package/dist/internal/codec.d.ts +9 -0
- package/dist/internal/codec.d.ts.map +1 -0
- package/dist/internal/codec.js +16 -0
- package/dist/internal/codec.js.map +1 -0
- package/dist/internal/scalar.d.ts +3 -4
- package/dist/internal/scalar.d.ts.map +1 -1
- package/dist/internal/scalar.js +19 -12
- package/dist/internal/scalar.js.map +1 -1
- package/dist/internal/size2.d.ts +9 -2
- package/dist/internal/size2.d.ts.map +1 -1
- package/dist/internal/size2.js +3 -1
- package/dist/internal/size2.js.map +1 -1
- package/dist/internal/vector2.d.ts +9 -2
- package/dist/internal/vector2.d.ts.map +1 -1
- package/dist/internal/vector2.js +3 -1
- package/dist/internal/vector2.js.map +1 -1
- package/package.json +2 -2
- package/src/Aabb.ts +15 -16
- package/src/Collide2.ts +153 -22
- package/src/Random.ts +21 -7
- package/src/Scalar.ts +27 -7
- package/src/Segment2.ts +71 -0
- package/src/Size2.ts +15 -16
- package/src/Vector2.ts +15 -16
- package/src/index.ts +6 -4
- package/src/internal/aabb.ts +8 -2
- package/src/internal/codec.ts +21 -0
- package/src/internal/scalar.ts +24 -13
- package/src/internal/size2.ts +8 -2
- package/src/internal/vector2.ts +8 -2
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { StandardSchema } from "@typeonce/ritmo/Descriptor"
|
|
2
|
+
import type * as Result from "@typeonce/ritmo/Result"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The codec of one math type, from its decode: a Standard Schema whose saved
|
|
6
|
+
* form is the raw shape. The value is already plain data, so it needs no
|
|
7
|
+
* `encode`.
|
|
8
|
+
*/
|
|
9
|
+
export const codecOf = <Raw, Value>(
|
|
10
|
+
decode: (raw: unknown) => Result.Result<Value, unknown>,
|
|
11
|
+
expected: string
|
|
12
|
+
): StandardSchema<Raw, Value> => ({
|
|
13
|
+
"~standard": {
|
|
14
|
+
version: 1,
|
|
15
|
+
vendor: "ritmo-math",
|
|
16
|
+
validate: (raw) => {
|
|
17
|
+
const value = decode(raw)
|
|
18
|
+
return value.ok ? { value: value.value } : { issues: [{ message: `Expected ${expected}` }] }
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
})
|
package/src/internal/scalar.ts
CHANGED
|
@@ -1,18 +1,33 @@
|
|
|
1
|
-
import * as Brand from "@typeonce/ritmo/Brand"
|
|
2
1
|
import * as Result from "@typeonce/ritmo/Result"
|
|
3
2
|
import type * as Scalar from "../Scalar.ts"
|
|
3
|
+
import { codecOf } from "./codec.ts"
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
// A branded number's constructors, guard, and codec, from its check.
|
|
6
|
+
const refine = <Value extends number>(
|
|
7
|
+
validate: (raw: number) => Result.Result<Value, Scalar.Error>,
|
|
8
|
+
expected: string
|
|
9
|
+
): Scalar.Constructor<Value> => ({
|
|
10
|
+
result: validate,
|
|
11
|
+
option: (raw) => {
|
|
12
|
+
const result = validate(raw)
|
|
13
|
+
return result.ok ? result.value : null
|
|
14
|
+
},
|
|
15
|
+
is: (raw): raw is Value => typeof raw === "number" && validate(raw).ok,
|
|
16
|
+
codec: codecOf<number, Value>((raw) => typeof raw === "number" ? validate(raw) : Result.failure(raw), expected)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
export const Finite = refine<Scalar.Finite>((value) =>
|
|
6
20
|
Number.isFinite(value)
|
|
7
21
|
? Result.success(value as Scalar.Finite)
|
|
8
22
|
: Result.failure({
|
|
9
23
|
tag: "Scalar/NotFinite",
|
|
10
24
|
value
|
|
11
|
-
})
|
|
25
|
+
}),
|
|
26
|
+
"a finite number"
|
|
12
27
|
)
|
|
13
28
|
|
|
14
|
-
const
|
|
15
|
-
const finite =
|
|
29
|
+
export const NonNegative = refine<Scalar.NonNegative>((value) => {
|
|
30
|
+
const finite = Finite.result(value)
|
|
16
31
|
if (!finite.ok) {
|
|
17
32
|
return finite
|
|
18
33
|
}
|
|
@@ -23,10 +38,10 @@ const nonNegativeBrand = Brand.refine<Scalar.NonNegative, number, Scalar.Error>(
|
|
|
23
38
|
tag: "Scalar/Negative",
|
|
24
39
|
value
|
|
25
40
|
})
|
|
26
|
-
})
|
|
41
|
+
}, "a finite number, 0 or more")
|
|
27
42
|
|
|
28
|
-
const
|
|
29
|
-
const finite =
|
|
43
|
+
export const Positive = refine<Scalar.Positive>((value) => {
|
|
44
|
+
const finite = Finite.result(value)
|
|
30
45
|
if (!finite.ok) {
|
|
31
46
|
return finite
|
|
32
47
|
}
|
|
@@ -37,11 +52,7 @@ const positiveBrand = Brand.refine<Scalar.Positive, number, Scalar.Error>((value
|
|
|
37
52
|
tag: "Scalar/NonPositive",
|
|
38
53
|
value
|
|
39
54
|
})
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
export const Finite = finiteBrand
|
|
43
|
-
export const NonNegative = nonNegativeBrand
|
|
44
|
-
export const Positive = positiveBrand
|
|
55
|
+
}, "a finite number above 0")
|
|
45
56
|
|
|
46
57
|
export const clamp = (value: number, min: number, max: number): Scalar.Finite =>
|
|
47
58
|
Math.min(Math.max(value, min), max) as Scalar.Finite
|
package/src/internal/size2.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { codecOf } from "./codec.ts"
|
|
1
2
|
import * as Result from "@typeonce/ritmo/Result"
|
|
2
3
|
import * as Scalar from "../Scalar.ts"
|
|
3
4
|
import type * as Size2 from "../Size2.ts"
|
|
@@ -28,7 +29,7 @@ export const option = (raw: Size2.Raw): Size2.Size2 | null => {
|
|
|
28
29
|
return next.ok ? next.value : null
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
export const is = (raw:
|
|
32
|
+
export const is = (raw: unknown): raw is Size2.Size2 => decode(raw).ok
|
|
32
33
|
|
|
33
34
|
export const toRaw = (size: Size2.Size2): Size2.Raw => ({
|
|
34
35
|
width: size.width,
|
|
@@ -44,5 +45,10 @@ export const height = (size: Size2.Size2): Scalar.NonNegative => size.height
|
|
|
44
45
|
export const isRawShape = (raw: unknown): raw is Size2.Raw =>
|
|
45
46
|
typeof raw === "object" && raw !== null && typeof (raw as Record<string, unknown>)["width"] === "number" && typeof (raw as Record<string, unknown>)["height"] === "number"
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
/** Untrusted input without the raw shape. */
|
|
49
|
+
type Malformed = { readonly tag: "Size2/Malformed"; readonly input: unknown }
|
|
50
|
+
|
|
51
|
+
export const decode = (raw: unknown): Result.Result<Size2.Size2, Size2.Error | Malformed> =>
|
|
48
52
|
isRawShape(raw) ? result(raw) : Result.failure({ tag: "Size2/Malformed", input: raw })
|
|
53
|
+
|
|
54
|
+
export const codec = codecOf<Size2.Raw, Size2.Size2>(decode, "a size { width, height } of non-negative finite numbers")
|
package/src/internal/vector2.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { codecOf } from "./codec.ts"
|
|
1
2
|
import * as Result from "@typeonce/ritmo/Result"
|
|
2
3
|
import * as Scalar from "../Scalar.ts"
|
|
3
4
|
import type * as Vector2 from "../Vector2.ts"
|
|
@@ -28,7 +29,7 @@ export const option = (raw: Vector2.Raw): Vector2.Vector2 | null => {
|
|
|
28
29
|
return next.ok ? next.value : null
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
export const is = (raw:
|
|
32
|
+
export const is = (raw: unknown): raw is Vector2.Vector2 => decode(raw).ok
|
|
32
33
|
|
|
33
34
|
export const toRaw = (vector: Vector2.Vector2): Vector2.Raw => ({
|
|
34
35
|
x: vector.x,
|
|
@@ -111,5 +112,10 @@ export const normalizeXYOrZero = (x: number, y: number): {
|
|
|
111
112
|
export const isRawShape = (raw: unknown): raw is Vector2.Raw =>
|
|
112
113
|
typeof raw === "object" && raw !== null && typeof (raw as Record<string, unknown>)["x"] === "number" && typeof (raw as Record<string, unknown>)["y"] === "number"
|
|
113
114
|
|
|
114
|
-
|
|
115
|
+
/** Untrusted input without the raw shape. */
|
|
116
|
+
type Malformed = { readonly tag: "Vector2/Malformed"; readonly input: unknown }
|
|
117
|
+
|
|
118
|
+
export const decode = (raw: unknown): Result.Result<Vector2.Vector2, Vector2.Error | Malformed> =>
|
|
115
119
|
isRawShape(raw) ? result(raw) : Result.failure({ tag: "Vector2/Malformed", input: raw })
|
|
120
|
+
|
|
121
|
+
export const codec = codecOf<Vector2.Raw, Vector2.Vector2>(decode, "a vector { x, y } of finite numbers")
|