distark-render 1.1.10 → 1.1.12

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.
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Character Validator
3
+ *
4
+ * Validates a character rig JSON object and returns a list of issues.
5
+ * Errors = character will not work correctly.
6
+ * Warnings = character may look wrong or have limited expressiveness.
7
+ *
8
+ * This is the single source of truth for what constitutes a valid character.
9
+ * The Ruby mirror in app/models/artifact/character.rb implements the same rules.
10
+ */
11
+ export type IssueSeverity = 'error' | 'warning';
12
+ export type IssueCategory = 'parts' | 'eyes' | 'mouth' | 'pivots' | 'zIndex' | 'dimensions';
13
+ export interface ValidationIssue {
14
+ field: string;
15
+ message: string;
16
+ severity: IssueSeverity;
17
+ category: IssueCategory;
18
+ }
19
+ export interface CharacterValidationResult {
20
+ /** true only when there are zero errors (warnings are allowed) */
21
+ valid: boolean;
22
+ issues: ValidationIssue[];
23
+ }
24
+ /** The 12 body part image paths every character must have */
25
+ export declare const REQUIRED_BODY_PARTS: readonly ["head", "torso", "leftUpperArm", "leftForearm", "leftHand", "rightUpperArm", "rightForearm", "rightHand", "leftThigh", "leftLeg", "rightThigh", "rightLeg"];
26
+ /** The 13 pivot point connections that chain all limbs */
27
+ export declare const REQUIRED_PIVOT_POINTS: readonly ["root_torso", "torso_head", "head_mouth", "torso_leftUpperArm", "leftUpperArm_leftForearm", "leftForearm_leftHand", "torso_rightUpperArm", "rightUpperArm_rightForearm", "rightForearm_rightHand", "torso_leftThigh", "leftThigh_leftLeg", "torso_rightThigh", "rightThigh_rightLeg"];
28
+ /** Every part that must have a z-index value */
29
+ export declare const REQUIRED_Z_INDEX_PARTS: readonly ["head", "mouth", "torso", "leftEye", "leftIris", "leftEyeLid", "rightEye", "rightIris", "rightEyeLid", "leftUpperArm", "leftForearm", "leftHand", "rightUpperArm", "rightForearm", "rightHand", "leftThigh", "leftLeg", "rightThigh", "rightLeg"];
30
+ /** Eye image hash fields required in the eyes object */
31
+ export declare const REQUIRED_EYE_IMAGES: readonly ["leftEyeImage", "rightEyeImage", "leftIris", "rightIris", "leftEyeLidOpen", "rightEyeLidOpen", "leftEyeLidHalfClosed", "rightEyeLidHalfClosed", "leftEyeLidClosed", "rightEyeLidClosed"];
32
+ /** Eye coordinate fields that must be numbers */
33
+ export declare const REQUIRED_EYE_COORDS: readonly ["leftEyeXCoor", "leftEyeYCoor", "rightEyeXCoor", "rightEyeYCoor", "leftEyeLidXCoor", "leftEyeLidYCoor", "rightEyeLidXCoor", "rightEyeLidYCoor", "leftIrisXCoor", "leftIrisYCoor", "rightIrisXCoor", "rightIrisYCoor"];
34
+ /** Iris size fields that must be positive numbers */
35
+ export declare const REQUIRED_IRIS_SIZES: readonly ["leftIrisWidth", "leftIrisHeight", "rightIrisWidth", "rightIrisHeight"];
36
+ /** Parts that must have a dimensionValues entry with width > 0 and height > 0 */
37
+ export declare const REQUIRED_DIMENSION_PARTS: readonly ["head", "torso", "mouth", "leftUpperArm", "leftForearm", "leftHand", "rightUpperArm", "rightForearm", "rightHand", "leftThigh", "leftLeg", "rightThigh", "rightLeg"];
38
+ /** Mouth shapes that represent the character talking */
39
+ export declare const TALKING_MOUTH_SHAPES: readonly ["open", "half-open", "wide-open", "slightly-open", "f", "l", "ds", "ee", "eh"];
40
+ export declare function validateCharacter(data: unknown): CharacterValidationResult;
41
+ //# sourceMappingURL=characterValidator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"characterValidator.d.ts","sourceRoot":"","sources":["../../modules/characterValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,CAAC;AAChD,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,YAAY,CAAC;AAE5F,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,aAAa,CAAC;CAC3B;AAED,MAAM,WAAW,yBAAyB;IACtC,kEAAkE;IAClE,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;CAC7B;AAID,6DAA6D;AAC7D,eAAO,MAAM,mBAAmB,uKAMtB,CAAC;AAEX,0DAA0D;AAC1D,eAAO,MAAM,qBAAqB,iSAMxB,CAAC;AAEX,gDAAgD;AAChD,eAAO,MAAM,sBAAsB,6PAQzB,CAAC;AAEX,wDAAwD;AACxD,eAAO,MAAM,mBAAmB,oMAMtB,CAAC;AAEX,iDAAiD;AACjD,eAAO,MAAM,mBAAmB,iOAOtB,CAAC;AAEX,qDAAqD;AACrD,eAAO,MAAM,mBAAmB,mFAGtB,CAAC;AAEX,iFAAiF;AACjF,eAAO,MAAM,wBAAwB,gLAM3B,CAAC;AAEX,wDAAwD;AACxD,eAAO,MAAM,oBAAoB,0FAEvB,CAAC;AAyBX,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,yBAAyB,CAoL1E"}
@@ -0,0 +1,233 @@
1
+ /**
2
+ * Character Validator
3
+ *
4
+ * Validates a character rig JSON object and returns a list of issues.
5
+ * Errors = character will not work correctly.
6
+ * Warnings = character may look wrong or have limited expressiveness.
7
+ *
8
+ * This is the single source of truth for what constitutes a valid character.
9
+ * The Ruby mirror in app/models/artifact/character.rb implements the same rules.
10
+ */
11
+ // ─── Schema constants (exported so Ruby mirror + docs can reference them) ────
12
+ /** The 12 body part image paths every character must have */
13
+ export const REQUIRED_BODY_PARTS = [
14
+ 'head', 'torso',
15
+ 'leftUpperArm', 'leftForearm', 'leftHand',
16
+ 'rightUpperArm', 'rightForearm', 'rightHand',
17
+ 'leftThigh', 'leftLeg',
18
+ 'rightThigh', 'rightLeg',
19
+ ];
20
+ /** The 13 pivot point connections that chain all limbs */
21
+ export const REQUIRED_PIVOT_POINTS = [
22
+ 'root_torso', 'torso_head', 'head_mouth',
23
+ 'torso_leftUpperArm', 'leftUpperArm_leftForearm', 'leftForearm_leftHand',
24
+ 'torso_rightUpperArm', 'rightUpperArm_rightForearm', 'rightForearm_rightHand',
25
+ 'torso_leftThigh', 'leftThigh_leftLeg',
26
+ 'torso_rightThigh', 'rightThigh_rightLeg',
27
+ ];
28
+ /** Every part that must have a z-index value */
29
+ export const REQUIRED_Z_INDEX_PARTS = [
30
+ 'head', 'mouth', 'torso',
31
+ 'leftEye', 'leftIris', 'leftEyeLid',
32
+ 'rightEye', 'rightIris', 'rightEyeLid',
33
+ 'leftUpperArm', 'leftForearm', 'leftHand',
34
+ 'rightUpperArm', 'rightForearm', 'rightHand',
35
+ 'leftThigh', 'leftLeg',
36
+ 'rightThigh', 'rightLeg',
37
+ ];
38
+ /** Eye image hash fields required in the eyes object */
39
+ export const REQUIRED_EYE_IMAGES = [
40
+ 'leftEyeImage', 'rightEyeImage',
41
+ 'leftIris', 'rightIris',
42
+ 'leftEyeLidOpen', 'rightEyeLidOpen',
43
+ 'leftEyeLidHalfClosed', 'rightEyeLidHalfClosed',
44
+ 'leftEyeLidClosed', 'rightEyeLidClosed',
45
+ ];
46
+ /** Eye coordinate fields that must be numbers */
47
+ export const REQUIRED_EYE_COORDS = [
48
+ 'leftEyeXCoor', 'leftEyeYCoor',
49
+ 'rightEyeXCoor', 'rightEyeYCoor',
50
+ 'leftEyeLidXCoor', 'leftEyeLidYCoor',
51
+ 'rightEyeLidXCoor', 'rightEyeLidYCoor',
52
+ 'leftIrisXCoor', 'leftIrisYCoor',
53
+ 'rightIrisXCoor', 'rightIrisYCoor',
54
+ ];
55
+ /** Iris size fields that must be positive numbers */
56
+ export const REQUIRED_IRIS_SIZES = [
57
+ 'leftIrisWidth', 'leftIrisHeight',
58
+ 'rightIrisWidth', 'rightIrisHeight',
59
+ ];
60
+ /** Parts that must have a dimensionValues entry with width > 0 and height > 0 */
61
+ export const REQUIRED_DIMENSION_PARTS = [
62
+ 'head', 'torso', 'mouth',
63
+ 'leftUpperArm', 'leftForearm', 'leftHand',
64
+ 'rightUpperArm', 'rightForearm', 'rightHand',
65
+ 'leftThigh', 'leftLeg',
66
+ 'rightThigh', 'rightLeg',
67
+ ];
68
+ /** Mouth shapes that represent the character talking */
69
+ export const TALKING_MOUTH_SHAPES = [
70
+ 'open', 'half-open', 'wide-open', 'slightly-open', 'f', 'l', 'ds', 'ee', 'eh',
71
+ ];
72
+ // ─── Internal helpers ────────────────────────────────────────────────────────
73
+ function isValidHash(value) {
74
+ return typeof value === 'string' && value.length > 0 && !value.includes('[MEDIA_REMOVED]');
75
+ }
76
+ function isNum(value) {
77
+ return typeof value === 'number' && !isNaN(value);
78
+ }
79
+ function isPositiveNum(value) {
80
+ return isNum(value) && value > 0;
81
+ }
82
+ function asObj(value) {
83
+ if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
84
+ return value;
85
+ }
86
+ return null;
87
+ }
88
+ // ─── Main validator ──────────────────────────────────────────────────────────
89
+ export function validateCharacter(data) {
90
+ const issues = [];
91
+ function addError(field, message, category) {
92
+ issues.push({ field, message, severity: 'error', category });
93
+ }
94
+ function addWarning(field, message, category) {
95
+ issues.push({ field, message, severity: 'warning', category });
96
+ }
97
+ // Must be a plain object
98
+ const d = asObj(data);
99
+ if (!d) {
100
+ addError('root', 'Character data must be a plain object', 'parts');
101
+ return { valid: false, issues };
102
+ }
103
+ // ── imagePaths: 12 body parts ────────────────────────────────────────────
104
+ const imagePaths = asObj(d.imagePaths) ?? {};
105
+ for (const part of REQUIRED_BODY_PARTS) {
106
+ if (!isValidHash(imagePaths[part])) {
107
+ addError(`imagePaths.${part}`, `Body part "${part}" image is missing or removed`, 'parts');
108
+ }
109
+ }
110
+ // ── pivotPoints: 13 joints ───────────────────────────────────────────────
111
+ const pivotPoints = asObj(d.pivotPoints) ?? {};
112
+ for (const key of REQUIRED_PIVOT_POINTS) {
113
+ const pivot = asObj(pivotPoints[key]);
114
+ if (!pivot) {
115
+ addError(`pivotPoints.${key}`, `Pivot point "${key}" is missing`, 'pivots');
116
+ }
117
+ else if (!isNum(pivot.x) || !isNum(pivot.y)) {
118
+ addError(`pivotPoints.${key}`, `Pivot point "${key}" must have numeric x and y`, 'pivots');
119
+ }
120
+ }
121
+ // ── zIndexValues: 19 parts ───────────────────────────────────────────────
122
+ const zi = asObj(d.zIndexValues) ?? {};
123
+ for (const part of REQUIRED_Z_INDEX_PARTS) {
124
+ if (!isNum(zi[part])) {
125
+ addError(`zIndexValues.${part}`, `Z-index for "${part}" is missing`, 'zIndex');
126
+ }
127
+ }
128
+ // Z-index ordering rules (hard constraints)
129
+ const leftEyeLid = zi.leftEyeLid;
130
+ const leftIris = zi.leftIris;
131
+ const leftEye = zi.leftEye;
132
+ if (isNum(leftEyeLid) && isNum(leftIris) && isNum(leftEye)) {
133
+ if (!(leftEyeLid > leftIris && leftIris > leftEye)) {
134
+ addError('zIndexValues', `Left eye z-order must be leftEyeLid(${leftEyeLid}) > leftIris(${leftIris}) > leftEye(${leftEye})`, 'zIndex');
135
+ }
136
+ }
137
+ const rightEyeLid = zi.rightEyeLid;
138
+ const rightIris = zi.rightIris;
139
+ const rightEye = zi.rightEye;
140
+ if (isNum(rightEyeLid) && isNum(rightIris) && isNum(rightEye)) {
141
+ if (!(rightEyeLid > rightIris && rightIris > rightEye)) {
142
+ addError('zIndexValues', `Right eye z-order must be rightEyeLid(${rightEyeLid}) > rightIris(${rightIris}) > rightEye(${rightEye})`, 'zIndex');
143
+ }
144
+ }
145
+ const mouthZ = zi.mouth;
146
+ const headZ = zi.head;
147
+ if (isNum(mouthZ) && isNum(headZ)) {
148
+ if (!(mouthZ > headZ)) {
149
+ addError('zIndexValues', `mouth z-index(${mouthZ}) must be greater than head z-index(${headZ})`, 'zIndex');
150
+ }
151
+ }
152
+ // ── eyes: images, coords, iris sizes ────────────────────────────────────
153
+ const eyes = asObj(d.eyes) ?? {};
154
+ for (const img of REQUIRED_EYE_IMAGES) {
155
+ if (!isValidHash(eyes[img])) {
156
+ addError(`eyes.${img}`, `Eye image "${img}" is missing or removed`, 'eyes');
157
+ }
158
+ }
159
+ for (const coord of REQUIRED_EYE_COORDS) {
160
+ if (!isNum(eyes[coord])) {
161
+ addError(`eyes.${coord}`, `Eye coordinate "${coord}" must be a number`, 'eyes');
162
+ }
163
+ }
164
+ for (const sizeKey of REQUIRED_IRIS_SIZES) {
165
+ if (!isPositiveNum(eyes[sizeKey])) {
166
+ addError(`eyes.${sizeKey}`, `Iris size "${sizeKey}" must be a positive number`, 'eyes');
167
+ }
168
+ }
169
+ // ── eyeSockets: left and right, ≥ 3 points each ─────────────────────────
170
+ const sockets = asObj(d.eyeSockets) ?? {};
171
+ for (const side of ['left', 'right']) {
172
+ const socket = sockets[side];
173
+ if (!Array.isArray(socket)) {
174
+ addError(`eyeSockets.${side}`, `Eye socket "${side}" must be an array of points`, 'eyes');
175
+ }
176
+ else if (socket.length < 3) {
177
+ addError(`eyeSockets.${side}`, `Eye socket "${side}" must have at least 3 points (has ${socket.length})`, 'eyes');
178
+ }
179
+ else {
180
+ const bad = socket.filter(p => {
181
+ const pt = asObj(p);
182
+ return !pt || !isNum(pt.x) || !isNum(pt.y);
183
+ });
184
+ if (bad.length > 0) {
185
+ addError(`eyeSockets.${side}`, `Eye socket "${side}" has ${bad.length} invalid point(s) — each must have numeric x and y`, 'eyes');
186
+ }
187
+ }
188
+ }
189
+ // ── mouth ────────────────────────────────────────────────────────────────
190
+ const mouth = asObj(d.mouth) ?? {};
191
+ if (!isValidHash(mouth.closed)) {
192
+ addError('mouth.closed', 'Mouth "closed" image is required', 'mouth');
193
+ }
194
+ if (!isNum(mouth.xCoor)) {
195
+ addError('mouth.xCoor', 'Mouth xCoor must be a number', 'mouth');
196
+ }
197
+ if (!isNum(mouth.yCoor)) {
198
+ addError('mouth.yCoor', 'Mouth yCoor must be a number', 'mouth');
199
+ }
200
+ const hasMouthSize = isPositiveNum(mouth.size);
201
+ const hasMouthDims = isPositiveNum(mouth.width) && isPositiveNum(mouth.height);
202
+ if (!hasMouthSize && !hasMouthDims) {
203
+ addError('mouth', 'Mouth needs size > 0, or both width > 0 and height > 0', 'mouth');
204
+ }
205
+ // ── dimensionValues: 13 parts ────────────────────────────────────────────
206
+ const dims = asObj(d.dimensionValues) ?? {};
207
+ for (const part of REQUIRED_DIMENSION_PARTS) {
208
+ const dim = asObj(dims[part]);
209
+ if (!dim) {
210
+ addError(`dimensionValues.${part}`, `Dimension for "${part}" is missing`, 'dimensions');
211
+ }
212
+ else if (!isPositiveNum(dim.width) || !isPositiveNum(dim.height)) {
213
+ addError(`dimensionValues.${part}`, `Dimension for "${part}" must have width > 0 and height > 0`, 'dimensions');
214
+ }
215
+ }
216
+ // ── Warnings ─────────────────────────────────────────────────────────────
217
+ // Pivot sanity: head pivot should be above (lower y) than torso root
218
+ const rootTorso = asObj(pivotPoints.root_torso);
219
+ const torsoHead = asObj(pivotPoints.torso_head);
220
+ if (rootTorso && torsoHead && isNum(rootTorso.y) && isNum(torsoHead.y)) {
221
+ if (torsoHead.y >= rootTorso.y) {
222
+ addWarning('pivotPoints.torso_head', `torso_head.y (${torsoHead.y}) should be less than root_torso.y (${rootTorso.y}) — head pivot should be above the torso root`, 'pivots');
223
+ }
224
+ }
225
+ // Mouth expressiveness: at least one talking shape should be present
226
+ const talkingAvailable = TALKING_MOUTH_SHAPES.filter(shape => isValidHash(mouth[shape]));
227
+ if (talkingAvailable.length === 0) {
228
+ addWarning('mouth', 'No talking mouth shapes found — character cannot animate speech. Add at least "open" or "slightly-open"', 'mouth');
229
+ }
230
+ const errorCount = issues.filter(i => i.severity === 'error').length;
231
+ return { valid: errorCount === 0, issues };
232
+ }
233
+ //# sourceMappingURL=characterValidator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"characterValidator.js","sourceRoot":"","sources":["../../modules/characterValidator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * RED/GREEN TDD: Character Validator tests.
3
+ *
4
+ * Run against STUB first → mostly RED.
5
+ * Run against full implementation → all GREEN.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=test-character-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-character-validator.d.ts","sourceRoot":"","sources":["../../tests/test-character-validator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,445 @@
1
+ /**
2
+ * RED/GREEN TDD: Character Validator tests.
3
+ *
4
+ * Run against STUB first → mostly RED.
5
+ * Run against full implementation → all GREEN.
6
+ */
7
+ import { validateCharacter, REQUIRED_BODY_PARTS, REQUIRED_PIVOT_POINTS, REQUIRED_Z_INDEX_PARTS, REQUIRED_EYE_IMAGES, REQUIRED_EYE_COORDS, REQUIRED_IRIS_SIZES, REQUIRED_DIMENSION_PARTS, TALKING_MOUTH_SHAPES, } from '../modules/characterValidator.js';
8
+ import { EyeSystem } from '../modules/eyeSystem.js';
9
+ import { MouthSystem, extractMouthShapesFromRigData } from '../modules/mouthSystem.js';
10
+ import { assert, printSummary } from './helpers.js';
11
+ function clone(obj) {
12
+ return JSON.parse(JSON.stringify(obj));
13
+ }
14
+ /** Delete a dot-path field from a cloned object */
15
+ function del(obj, path) {
16
+ const result = clone(obj);
17
+ const parts = path.split('.');
18
+ let cur = result;
19
+ for (let i = 0; i < parts.length - 1; i++) {
20
+ cur = cur[parts[i]];
21
+ }
22
+ delete cur[parts[parts.length - 1]];
23
+ return result;
24
+ }
25
+ /** Set a dot-path field on a cloned object */
26
+ function set(obj, path, value) {
27
+ const result = clone(obj);
28
+ const parts = path.split('.');
29
+ let cur = result;
30
+ for (let i = 0; i < parts.length - 1; i++) {
31
+ cur = cur[parts[i]];
32
+ }
33
+ cur[parts[parts.length - 1]] = value;
34
+ return result;
35
+ }
36
+ function errors(r) {
37
+ return r.issues.filter(i => i.severity === 'error');
38
+ }
39
+ function warnings(r) {
40
+ return r.issues.filter(i => i.severity === 'warning');
41
+ }
42
+ function hasError(r, field) {
43
+ return r.issues.some(i => i.severity === 'error' && i.field === field);
44
+ }
45
+ function hasWarning(r, field) {
46
+ return r.issues.some(i => i.severity === 'warning' && i.field === field);
47
+ }
48
+ // ─── Valid character fixture ─────────────────────────────────────────────────
49
+ function h(n) {
50
+ return `abcdef${n.toString().padStart(26, '0')}`;
51
+ }
52
+ function buildValidCharacter() {
53
+ return {
54
+ id: 'TestChar',
55
+ key: 'TestChar',
56
+ kind: 'character',
57
+ name: 'Test Character',
58
+ imagePaths: {
59
+ head: h(1), torso: h(2),
60
+ leftUpperArm: h(3), leftForearm: h(4), leftHand: h(5),
61
+ rightUpperArm: h(6), rightForearm: h(7), rightHand: h(8),
62
+ leftThigh: h(9), leftLeg: h(10),
63
+ rightThigh: h(11), rightLeg: h(12),
64
+ },
65
+ eyes: {
66
+ leftEyeImage: h(13), rightEyeImage: h(14),
67
+ leftIris: h(15), rightIris: h(16),
68
+ leftEyeLidOpen: h(17), rightEyeLidOpen: h(18),
69
+ leftEyeLidHalfClosed: h(19), rightEyeLidHalfClosed: h(20),
70
+ leftEyeLidClosed: h(21), rightEyeLidClosed: h(22),
71
+ leftEyeXCoor: -17, leftEyeYCoor: -188,
72
+ rightEyeXCoor: 111, rightEyeYCoor: -209,
73
+ leftEyeLidXCoor: -13, leftEyeLidYCoor: -209,
74
+ rightEyeLidXCoor: 115, rightEyeLidYCoor: -213,
75
+ leftIrisXCoor: -4, leftIrisYCoor: -188,
76
+ rightIrisXCoor: 119, rightIrisYCoor: -200,
77
+ leftIrisWidth: 37, leftIrisHeight: 58,
78
+ rightIrisWidth: 37, rightIrisHeight: 58,
79
+ },
80
+ eyeSockets: {
81
+ left: [
82
+ { x: 34, y: 39 }, { x: 29, y: 43 }, { x: 27, y: 47 },
83
+ { x: 34, y: 60 }, { x: 48, y: 59 }, { x: 53, y: 45 },
84
+ ],
85
+ right: [
86
+ { x: 77, y: 34 }, { x: 71, y: 37 }, { x: 70, y: 47 },
87
+ { x: 75, y: 52 }, { x: 83, y: 53 }, { x: 90, y: 42 },
88
+ ],
89
+ },
90
+ pivotPoints: {
91
+ root_torso: { x: 19, y: -62 },
92
+ torso_head: { x: 40, y: -343 },
93
+ head_mouth: { x: 23, y: -68 },
94
+ torso_leftUpperArm: { x: -56, y: -309 },
95
+ leftUpperArm_leftForearm: { x: 4, y: 60 },
96
+ leftForearm_leftHand: { x: 6, y: 33 },
97
+ torso_rightUpperArm: { x: 76, y: -322 },
98
+ rightUpperArm_rightForearm: { x: -9, y: 49 },
99
+ rightForearm_rightHand: { x: -4, y: 27 },
100
+ torso_leftThigh: { x: -22, y: -67 },
101
+ leftThigh_leftLeg: { x: 0, y: 40 },
102
+ torso_rightThigh: { x: 85, y: -58 },
103
+ rightThigh_rightLeg: { x: 9, y: 36 },
104
+ },
105
+ zIndexValues: {
106
+ rightUpperArm: 1, rightForearm: 2,
107
+ rightEye: 3, rightIris: 4, rightEyeLid: 5,
108
+ rightLeg: 6, rightThigh: 7, torso: 8, head: 9,
109
+ leftUpperArm: 10, leftForearm: 11,
110
+ leftEye: 12, leftIris: 13, leftEyeLid: 14,
111
+ leftLeg: 15, leftThigh: 16, rightHand: 17, leftHand: 18, mouth: 19,
112
+ },
113
+ mouth: {
114
+ closed: h(30), open: h(31), 'half-open': h(32),
115
+ 'wide-open': h(33), 'slightly-open': h(34),
116
+ f: h(35), l: h(36),
117
+ xCoor: 23, yCoor: -68,
118
+ size: 1.5, width: 61.5, height: 44.8,
119
+ },
120
+ dimensionValues: {
121
+ head: { width: 337, height: 437 },
122
+ torso: { width: 278, height: 383 },
123
+ mouth: { width: 61.5, height: 44.8 },
124
+ leftUpperArm: { width: 88, height: 203 },
125
+ leftForearm: { width: 58, height: 135 },
126
+ leftHand: { width: 91, height: 81 },
127
+ rightUpperArm: { width: 83, height: 203 },
128
+ rightForearm: { width: 59, height: 137 },
129
+ rightHand: { width: 91, height: 81 },
130
+ leftThigh: { width: 111, height: 198 },
131
+ leftLeg: { width: 184, height: 137 },
132
+ rightThigh: { width: 80, height: 166 },
133
+ rightLeg: { width: 184, height: 137 },
134
+ },
135
+ };
136
+ }
137
+ // ─── Tests ───────────────────────────────────────────────────────────────────
138
+ function runTests() {
139
+ const valid = buildValidCharacter();
140
+ // ── Valid character ───────────────────────────────────────────────────────
141
+ console.log('\n--- Valid character ---');
142
+ {
143
+ const r = validateCharacter(valid);
144
+ assert(r.valid === true, 'valid character: valid = true');
145
+ assert(errors(r).length === 0, 'valid character: zero errors');
146
+ assert(warnings(r).length === 0, 'valid character: zero warnings');
147
+ }
148
+ // ── Bad input ─────────────────────────────────────────────────────────────
149
+ console.log('\n--- Bad input format ---');
150
+ {
151
+ const r = validateCharacter(null);
152
+ assert(r.valid === false, 'null: invalid');
153
+ assert(errors(r).length > 0, 'null: has errors');
154
+ }
155
+ {
156
+ const r = validateCharacter('string');
157
+ assert(r.valid === false, 'string: invalid');
158
+ }
159
+ // ── Body parts (imagePaths) ───────────────────────────────────────────────
160
+ console.log('\n--- Body parts (imagePaths) ---');
161
+ {
162
+ // All 12 body parts flagged when imagePaths removed
163
+ const r = validateCharacter(del(valid, 'imagePaths'));
164
+ for (const part of REQUIRED_BODY_PARTS) {
165
+ assert(hasError(r, `imagePaths.${part}`), `missing imagePaths → error for ${part}`);
166
+ }
167
+ }
168
+ {
169
+ // Single missing part
170
+ const r = validateCharacter(del(valid, 'imagePaths.head'));
171
+ assert(hasError(r, 'imagePaths.head'), 'missing imagePaths.head → error');
172
+ assert(!hasError(r, 'imagePaths.torso'), 'imagePaths.torso still present → no error');
173
+ }
174
+ {
175
+ // [MEDIA_REMOVED] treated as missing
176
+ const r = validateCharacter(set(valid, 'imagePaths.torso', '[MEDIA_REMOVED]'));
177
+ assert(hasError(r, 'imagePaths.torso'), '[MEDIA_REMOVED] torso → error');
178
+ }
179
+ {
180
+ // Empty string treated as missing
181
+ const r = validateCharacter(set(valid, 'imagePaths.leftHand', ''));
182
+ assert(hasError(r, 'imagePaths.leftHand'), 'empty string leftHand → error');
183
+ }
184
+ // ── Pivot points ──────────────────────────────────────────────────────────
185
+ console.log('\n--- Pivot points ---');
186
+ {
187
+ const r = validateCharacter(del(valid, 'pivotPoints'));
188
+ for (const key of REQUIRED_PIVOT_POINTS) {
189
+ assert(hasError(r, `pivotPoints.${key}`), `missing pivotPoints → error for ${key}`);
190
+ }
191
+ }
192
+ {
193
+ const r = validateCharacter(del(valid, 'pivotPoints.torso_head'));
194
+ assert(hasError(r, 'pivotPoints.torso_head'), 'missing torso_head → error');
195
+ }
196
+ {
197
+ // Non-numeric x
198
+ const r = validateCharacter(set(valid, 'pivotPoints.root_torso', { x: 'bad', y: -62 }));
199
+ assert(hasError(r, 'pivotPoints.root_torso'), 'non-numeric pivot x → error');
200
+ }
201
+ {
202
+ // Not an object
203
+ const r = validateCharacter(set(valid, 'pivotPoints.head_mouth', 42));
204
+ assert(hasError(r, 'pivotPoints.head_mouth'), 'pivot is a number, not object → error');
205
+ }
206
+ // ── Z-index values ────────────────────────────────────────────────────────
207
+ console.log('\n--- Z-index values ---');
208
+ {
209
+ const r = validateCharacter(del(valid, 'zIndexValues'));
210
+ for (const part of REQUIRED_Z_INDEX_PARTS) {
211
+ assert(hasError(r, `zIndexValues.${part}`), `missing zIndexValues → error for ${part}`);
212
+ }
213
+ }
214
+ {
215
+ const r = validateCharacter(del(valid, 'zIndexValues.mouth'));
216
+ assert(hasError(r, 'zIndexValues.mouth'), 'missing zIndexValues.mouth → error');
217
+ }
218
+ // ── Z-index ordering ──────────────────────────────────────────────────────
219
+ console.log('\n--- Z-index ordering ---');
220
+ {
221
+ // leftEyeLid must be > leftIris
222
+ let r = validateCharacter(set(valid, 'zIndexValues.leftEyeLid', 13)); // equal to leftIris
223
+ assert(hasError(r, 'zIndexValues'), 'leftEyeLid = leftIris → ordering error');
224
+ r = validateCharacter(set(valid, 'zIndexValues.leftEyeLid', 12)); // below leftIris
225
+ assert(hasError(r, 'zIndexValues'), 'leftEyeLid < leftIris → ordering error');
226
+ }
227
+ {
228
+ // leftIris must be > leftEye
229
+ const r = validateCharacter(set(valid, 'zIndexValues.leftIris', 11)); // = leftEye(12)? no, leftEye=12, set leftIris=11 → 11 < 12
230
+ assert(hasError(r, 'zIndexValues'), 'leftIris < leftEye → ordering error');
231
+ }
232
+ {
233
+ // rightEyeLid must be > rightIris > rightEye
234
+ const r = validateCharacter(set(valid, 'zIndexValues.rightIris', 3)); // = rightEye
235
+ assert(hasError(r, 'zIndexValues'), 'rightIris = rightEye → ordering error');
236
+ }
237
+ {
238
+ // mouth must be > head
239
+ const r = validateCharacter(set(valid, 'zIndexValues.mouth', 9)); // = head
240
+ assert(hasError(r, 'zIndexValues'), 'mouth = head → ordering error');
241
+ }
242
+ {
243
+ // Correct ordering does not raise error
244
+ const r = validateCharacter(valid);
245
+ assert(!hasError(r, 'zIndexValues'), 'correct z-order → no ordering error');
246
+ }
247
+ // ── Eyes ─────────────────────────────────────────────────────────────────
248
+ console.log('\n--- Eyes ---');
249
+ {
250
+ const r = validateCharacter(del(valid, 'eyes'));
251
+ for (const img of REQUIRED_EYE_IMAGES) {
252
+ assert(hasError(r, `eyes.${img}`), `missing eyes → error for eyes.${img}`);
253
+ }
254
+ for (const coord of REQUIRED_EYE_COORDS) {
255
+ assert(hasError(r, `eyes.${coord}`), `missing eyes → error for eyes.${coord}`);
256
+ }
257
+ for (const sz of REQUIRED_IRIS_SIZES) {
258
+ assert(hasError(r, `eyes.${sz}`), `missing eyes → error for eyes.${sz}`);
259
+ }
260
+ }
261
+ {
262
+ const r = validateCharacter(set(valid, 'eyes.leftEyeLidOpen', '[MEDIA_REMOVED]'));
263
+ assert(hasError(r, 'eyes.leftEyeLidOpen'), '[MEDIA_REMOVED] leftEyeLidOpen → error');
264
+ }
265
+ {
266
+ const r = validateCharacter(del(valid, 'eyes.rightEyeLidClosed'));
267
+ assert(hasError(r, 'eyes.rightEyeLidClosed'), 'missing rightEyeLidClosed → error');
268
+ }
269
+ {
270
+ const r = validateCharacter(set(valid, 'eyes.leftIrisXCoor', 'bad'));
271
+ assert(hasError(r, 'eyes.leftIrisXCoor'), 'string leftIrisXCoor → error');
272
+ }
273
+ {
274
+ const r = validateCharacter(del(valid, 'eyes.leftIrisWidth'));
275
+ assert(hasError(r, 'eyes.leftIrisWidth'), 'missing leftIrisWidth → error');
276
+ }
277
+ {
278
+ const r = validateCharacter(set(valid, 'eyes.rightIrisHeight', 0));
279
+ assert(hasError(r, 'eyes.rightIrisHeight'), 'zero rightIrisHeight → error');
280
+ }
281
+ // ── Eye sockets ───────────────────────────────────────────────────────────
282
+ console.log('\n--- Eye sockets ---');
283
+ {
284
+ const r = validateCharacter(del(valid, 'eyeSockets'));
285
+ assert(hasError(r, 'eyeSockets.left'), 'missing eyeSockets → left error');
286
+ assert(hasError(r, 'eyeSockets.right'), 'missing eyeSockets → right error');
287
+ }
288
+ {
289
+ const r = validateCharacter(set(valid, 'eyeSockets.left', [{ x: 1, y: 2 }, { x: 3, y: 4 }]));
290
+ assert(hasError(r, 'eyeSockets.left'), '2-point left socket → error');
291
+ }
292
+ {
293
+ const r = validateCharacter(set(valid, 'eyeSockets.right', [{ x: 1 }, { x: 2, y: 3 }, { x: 4, y: 5 }]));
294
+ assert(hasError(r, 'eyeSockets.right'), 'point missing y → error');
295
+ }
296
+ // ── Mouth ─────────────────────────────────────────────────────────────────
297
+ console.log('\n--- Mouth ---');
298
+ {
299
+ const r = validateCharacter(del(valid, 'mouth.closed'));
300
+ assert(hasError(r, 'mouth.closed'), 'missing mouth.closed → error');
301
+ }
302
+ {
303
+ const r = validateCharacter(set(valid, 'mouth.closed', '[MEDIA_REMOVED]'));
304
+ assert(hasError(r, 'mouth.closed'), '[MEDIA_REMOVED] mouth.closed → error');
305
+ }
306
+ {
307
+ const r = validateCharacter(del(valid, 'mouth.xCoor'));
308
+ assert(hasError(r, 'mouth.xCoor'), 'missing mouth.xCoor → error');
309
+ }
310
+ {
311
+ const r = validateCharacter(set(valid, 'mouth.yCoor', 'bad'));
312
+ assert(hasError(r, 'mouth.yCoor'), 'string mouth.yCoor → error');
313
+ }
314
+ {
315
+ // Remove size, width, height all — no sizing info
316
+ let c = del(valid, 'mouth.size');
317
+ c = del(c, 'mouth.width');
318
+ c = del(c, 'mouth.height');
319
+ const r = validateCharacter(c);
320
+ assert(hasError(r, 'mouth'), 'no mouth size/width/height → error');
321
+ }
322
+ {
323
+ // width+height without size is enough
324
+ const c = del(valid, 'mouth.size');
325
+ const r = validateCharacter(c);
326
+ assert(!hasError(r, 'mouth'), 'width+height without size → no size error');
327
+ }
328
+ {
329
+ // size alone without width/height is enough
330
+ let c = del(valid, 'mouth.width');
331
+ c = del(c, 'mouth.height');
332
+ const r = validateCharacter(c);
333
+ assert(!hasError(r, 'mouth'), 'size alone → no size error');
334
+ }
335
+ // ── Dimension values ──────────────────────────────────────────────────────
336
+ console.log('\n--- Dimension values ---');
337
+ {
338
+ const r = validateCharacter(del(valid, 'dimensionValues'));
339
+ for (const part of REQUIRED_DIMENSION_PARTS) {
340
+ assert(hasError(r, `dimensionValues.${part}`), `missing dimensionValues → error for ${part}`);
341
+ }
342
+ }
343
+ {
344
+ const r = validateCharacter(set(valid, 'dimensionValues.head', { width: 0, height: 437 }));
345
+ assert(hasError(r, 'dimensionValues.head'), 'zero width head → error');
346
+ }
347
+ {
348
+ const r = validateCharacter(del(valid, 'dimensionValues.mouth'));
349
+ assert(hasError(r, 'dimensionValues.mouth'), 'missing dimensionValues.mouth → error');
350
+ }
351
+ // ── Warnings ──────────────────────────────────────────────────────────────
352
+ console.log('\n--- Warnings ---');
353
+ {
354
+ // Head pivot above torso root → warning
355
+ const c = set(valid, 'pivotPoints.torso_head', { x: 40, y: 50 }); // y=50 > root_torso.y=-62
356
+ const r = validateCharacter(c);
357
+ assert(hasWarning(r, 'pivotPoints.torso_head'), 'head pivot above torso root → warning');
358
+ assert(r.valid === true, 'warning does not make character invalid');
359
+ }
360
+ {
361
+ // No talking mouths → warning
362
+ let c = clone(valid);
363
+ for (const shape of TALKING_MOUTH_SHAPES) {
364
+ c = del(c, `mouth.${shape}`);
365
+ }
366
+ const r = validateCharacter(c);
367
+ assert(hasWarning(r, 'mouth'), 'no talking mouth shapes → warning');
368
+ assert(r.valid === true, 'warning-only character is still valid');
369
+ }
370
+ {
371
+ // Warnings with valid pivot do not fire
372
+ const r = validateCharacter(valid);
373
+ assert(!hasWarning(r, 'pivotPoints.torso_head'), 'correct pivot → no pivot warning');
374
+ assert(!hasWarning(r, 'mouth'), 'has talking mouths → no mouth warning');
375
+ }
376
+ // ── valid flag semantics ───────────────────────────────────────────────────
377
+ console.log('\n--- valid flag semantics ---');
378
+ {
379
+ // Errors make valid = false
380
+ const r = validateCharacter(del(valid, 'imagePaths.head'));
381
+ assert(r.valid === false, 'errors make valid = false');
382
+ }
383
+ {
384
+ // Warnings alone keep valid = true
385
+ const c = set(valid, 'pivotPoints.torso_head', { x: 40, y: 50 });
386
+ const r = validateCharacter(c);
387
+ assert(r.valid === true, 'warnings alone keep valid = true');
388
+ }
389
+ // ── Functional: EyeSystem ────────────────────────────────────────────────
390
+ console.log('\n--- Functional: EyeSystem ---');
391
+ {
392
+ // Instantiates without throwing
393
+ const eyeSystem = new EyeSystem('test', {
394
+ leftIrisXCoor: -4, leftIrisYCoor: -188,
395
+ rightIrisXCoor: 119, rightIrisYCoor: -200,
396
+ });
397
+ assert(eyeSystem !== null, 'EyeSystem instantiates');
398
+ // State is open at t=0
399
+ eyeSystem.resetTiming(0);
400
+ eyeSystem.updateBlinking(0);
401
+ assert(eyeSystem.getEyelidState() === 'open', 'eyelid open at t=0');
402
+ // Blink triggers by t=6 (interval max is 5s)
403
+ eyeSystem.updateBlinking(6.0);
404
+ const stateAt6 = eyeSystem.getEyelidState();
405
+ assert(stateAt6 === 'half-closed' || stateAt6 === 'closed', `blink triggered by t=6 (state: ${stateAt6})`);
406
+ // Direction: center returns to base
407
+ eyeSystem.setEyeDirection('center');
408
+ const center = eyeSystem.getIrisPositions();
409
+ assert(center.left.x === -4, 'center direction: left iris at base x');
410
+ // Direction: left moves iris left
411
+ eyeSystem.setEyeDirection('left');
412
+ const leftPos = eyeSystem.getIrisPositions();
413
+ assert(leftPos.left.x < center.left.x, 'left direction: iris moves left');
414
+ // Direction: right moves iris right
415
+ eyeSystem.setEyeDirection('right');
416
+ const rightPos = eyeSystem.getIrisPositions();
417
+ assert(rightPos.left.x > center.left.x, 'right direction: iris moves right');
418
+ // Left and right iris start at different x positions (not on top of each other)
419
+ eyeSystem.setEyeDirection('center');
420
+ const pos = eyeSystem.getIrisPositions();
421
+ assert(pos.left.x !== pos.right.x, 'left and right iris have different base x');
422
+ }
423
+ // ── Functional: MouthSystem ───────────────────────────────────────────────
424
+ console.log('\n--- Functional: MouthSystem ---');
425
+ {
426
+ const rigData = valid;
427
+ // extractMouthShapesFromRigData returns multiple shapes for valid character
428
+ const shapes = extractMouthShapesFromRigData(rigData);
429
+ assert(shapes.length >= 2, `extractMouthShapesFromRigData returns ≥2 shapes (got ${shapes.length})`);
430
+ assert(shapes.includes('closed'), 'extracted shapes include closed');
431
+ // MouthSystem instantiates and starts closed
432
+ const mouth = new MouthSystem('test', new Set(shapes));
433
+ assert(mouth.getCurrentMouth() === 'closed', 'MouthSystem starts closed');
434
+ // updateFromViseme moves away from closed
435
+ mouth.updateFromViseme('F'); // maps to 'f' or similar open shape
436
+ // It may stay closed if the mapped shape isn't available; just check no throw
437
+ assert(mouth.getCurrentMouth() !== undefined, 'updateFromViseme does not throw');
438
+ // reset returns to closed
439
+ mouth.reset();
440
+ assert(mouth.getCurrentMouth() === 'closed', 'reset() returns to closed');
441
+ }
442
+ printSummary();
443
+ }
444
+ runTests();
445
+ //# sourceMappingURL=test-character-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-character-validator.js","sourceRoot":"","sources":["../../tests/test-character-validator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACH,iBAAiB,EAEjB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,GACvB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAEvF,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAMpD,SAAS,KAAK,CAAC,GAAQ;IACnB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAQ,CAAC;AAClD,CAAC;AAED,mDAAmD;AACnD,SAAS,GAAG,CAAC,GAAQ,EAAE,IAAY;IAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,GAAG,GAAQ,MAAM,CAAC;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAQ,CAAC;IAC/B,CAAC;IACD,OAAO,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IACpC,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,8CAA8C;AAC9C,SAAS,GAAG,CAAC,GAAQ,EAAE,IAAY,EAAE,KAAc;IAC/C,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,GAAG,GAAQ,MAAM,CAAC;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAQ,CAAC;IAC/B,CAAC;IACD,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;IACrC,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAS,MAAM,CAAC,CAA4B;IACxC,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,QAAQ,CAAC,CAA4B;IAC1C,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,QAAQ,CAAC,CAA4B,EAAE,KAAa;IACzD,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS,UAAU,CAAC,CAA4B,EAAE,KAAa;IAC3D,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;AAC7E,CAAC;AAED,gFAAgF;AAEhF,SAAS,CAAC,CAAC,CAAS;IAChB,OAAO,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,mBAAmB;IACxB,OAAO;QACH,EAAE,EAAE,UAAU;QACd,GAAG,EAAE,UAAU;QACf,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,gBAAgB;QACtB,UAAU,EAAE;YACR,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;YACvB,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;YACrD,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;YACxD,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC;YAC/B,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC;SACrC;QACD,IAAI,EAAE;YACF,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC;YACzC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC;YACjC,cAAc,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC;YAC7C,oBAAoB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,qBAAqB,EAAE,CAAC,CAAC,EAAE,CAAC;YACzD,gBAAgB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,iBAAiB,EAAE,CAAC,CAAC,EAAE,CAAC;YACjD,YAAY,EAAE,CAAC,EAAE,EAAE,YAAY,EAAE,CAAC,GAAG;YACrC,aAAa,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,GAAG;YACvC,eAAe,EAAE,CAAC,EAAE,EAAE,eAAe,EAAE,CAAC,GAAG;YAC3C,gBAAgB,EAAE,GAAG,EAAE,gBAAgB,EAAE,CAAC,GAAG;YAC7C,aAAa,EAAE,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,GAAG;YACtC,cAAc,EAAE,GAAG,EAAE,cAAc,EAAE,CAAC,GAAG;YACzC,aAAa,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE;YACrC,cAAc,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE;SAC1C;QACD,UAAU,EAAE;YACR,IAAI,EAAE;gBACF,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE;gBACpD,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE;aACvD;YACD,KAAK,EAAE;gBACH,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE;gBACpD,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE;aACvD;SACJ;QACD,WAAW,EAAE;YACT,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;YAC7B,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE;YAC9B,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;YAC7B,kBAAkB,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE;YACvC,wBAAwB,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE;YACzC,oBAAoB,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE;YACrC,mBAAmB,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE;YACvC,0BAA0B,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE;YAC5C,sBAAsB,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE;YACxC,eAAe,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;YACnC,iBAAiB,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE;YAClC,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;YACnC,mBAAmB,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE;SACvC;QACD,YAAY,EAAE;YACV,aAAa,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC;YACjC,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC;YACzC,QAAQ,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC;YAC7C,YAAY,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE;YACjC,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE;YACzC,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE;SACrE;QACD,KAAK,EAAE;YACH,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC;YAC9C,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC;YAC1C,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YAClB,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE;YACrB,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI;SACvC;QACD,eAAe,EAAE;YACb,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;YACjC,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;YAClC,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;YACpC,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE;YACxC,WAAW,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE;YACvC,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;YACnC,aAAa,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE;YACzC,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE;YACxC,SAAS,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;YACpC,SAAS,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;YACtC,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;YACpC,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE;YACtC,QAAQ,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;SACxC;KACJ,CAAC;AACN,CAAC;AAED,gFAAgF;AAEhF,SAAS,QAAQ;IACb,MAAM,KAAK,GAAG,mBAAmB,EAAE,CAAC;IAEpC,6EAA6E;IAC7E,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACzC,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,EAAE,+BAA+B,CAAC,CAAC;QAC1D,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,8BAA8B,CAAC,CAAC;QAC/D,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,gCAAgC,CAAC,CAAC;IACvE,CAAC;IAED,6EAA6E;IAC7E,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC1C,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,EAAE,eAAe,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,kBAAkB,CAAC,CAAC;IACrD,CAAC;IACD,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,EAAE,iBAAiB,CAAC,CAAC;IACjD,CAAC;IAED,6EAA6E;IAC7E,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IACjD,CAAC;QACG,oDAAoD;QACpD,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC;QACtD,KAAK,MAAM,IAAI,IAAI,mBAAmB,EAAE,CAAC;YACrC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,cAAc,IAAI,EAAE,CAAC,EAAE,kCAAkC,IAAI,EAAE,CAAC,CAAC;QACxF,CAAC;IACL,CAAC;IACD,CAAC;QACG,sBAAsB;QACtB,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAC3D,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,iBAAiB,CAAC,EAAE,iCAAiC,CAAC,CAAC;QAC1E,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,kBAAkB,CAAC,EAAE,2CAA2C,CAAC,CAAC;IAC1F,CAAC;IACD,CAAC;QACG,qCAAqC;QACrC,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAC/E,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,kBAAkB,CAAC,EAAE,+BAA+B,CAAC,CAAC;IAC7E,CAAC;IACD,CAAC;QACG,kCAAkC;QAClC,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,qBAAqB,EAAE,EAAE,CAAC,CAAC,CAAC;QACnE,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,qBAAqB,CAAC,EAAE,+BAA+B,CAAC,CAAC;IAChF,CAAC;IAED,6EAA6E;IAC7E,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACtC,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC;QACvD,KAAK,MAAM,GAAG,IAAI,qBAAqB,EAAE,CAAC;YACtC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,eAAe,GAAG,EAAE,CAAC,EAAE,mCAAmC,GAAG,EAAE,CAAC,CAAC;QACxF,CAAC;IACL,CAAC;IACD,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAC,CAAC;QAClE,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,wBAAwB,CAAC,EAAE,4BAA4B,CAAC,CAAC;IAChF,CAAC;IACD,CAAC;QACG,gBAAgB;QAChB,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,wBAAwB,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACxF,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,wBAAwB,CAAC,EAAE,6BAA6B,CAAC,CAAC;IACjF,CAAC;IACD,CAAC;QACG,gBAAgB;QAChB,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,wBAAwB,EAAE,EAAE,CAAC,CAAC,CAAC;QACtE,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,wBAAwB,CAAC,EAAE,uCAAuC,CAAC,CAAC;IAC3F,CAAC;IAED,6EAA6E;IAC7E,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IACxC,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC;QACxD,KAAK,MAAM,IAAI,IAAI,sBAAsB,EAAE,CAAC;YACxC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,gBAAgB,IAAI,EAAE,CAAC,EAAE,oCAAoC,IAAI,EAAE,CAAC,CAAC;QAC5F,CAAC;IACL,CAAC;IACD,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC;QAC9D,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,oBAAoB,CAAC,EAAE,oCAAoC,CAAC,CAAC;IACpF,CAAC;IAED,6EAA6E;IAC7E,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC1C,CAAC;QACG,gCAAgC;QAChC,IAAI,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,yBAAyB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,oBAAoB;QAC1F,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,wCAAwC,CAAC,CAAC;QAE9E,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,yBAAyB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,iBAAiB;QACnF,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,wCAAwC,CAAC,CAAC;IAClF,CAAC;IACD,CAAC;QACG,6BAA6B;QAC7B,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,uBAAuB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,2DAA2D;QACjI,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,qCAAqC,CAAC,CAAC;IAC/E,CAAC;IACD,CAAC;QACG,6CAA6C;QAC7C,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,wBAAwB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa;QACnF,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,uCAAuC,CAAC,CAAC;IACjF,CAAC;IACD,CAAC;QACG,uBAAuB;QACvB,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;QAC3E,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,+BAA+B,CAAC,CAAC;IACzE,CAAC;IACD,CAAC;QACG,wCAAwC;QACxC,MAAM,CAAC,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,qCAAqC,CAAC,CAAC;IAChF,CAAC;IAED,4EAA4E;IAC5E,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAC9B,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;QAChD,KAAK,MAAM,GAAG,IAAI,mBAAmB,EAAE,CAAC;YACpC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,GAAG,EAAE,CAAC,EAAE,iCAAiC,GAAG,EAAE,CAAC,CAAC;QAC/E,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,mBAAmB,EAAE,CAAC;YACtC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,KAAK,EAAE,CAAC,EAAE,iCAAiC,KAAK,EAAE,CAAC,CAAC;QACnF,CAAC;QACD,KAAK,MAAM,EAAE,IAAI,mBAAmB,EAAE,CAAC;YACnC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,iCAAiC,EAAE,EAAE,CAAC,CAAC;QAC7E,CAAC;IACL,CAAC;IACD,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,qBAAqB,CAAC,EAAE,wCAAwC,CAAC,CAAC;IACzF,CAAC;IACD,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAC,CAAC;QAClE,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,wBAAwB,CAAC,EAAE,mCAAmC,CAAC,CAAC;IACvF,CAAC;IACD,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,oBAAoB,EAAE,KAAK,CAAC,CAAC,CAAC;QACrE,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,oBAAoB,CAAC,EAAE,8BAA8B,CAAC,CAAC;IAC9E,CAAC;IACD,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC;QAC9D,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,oBAAoB,CAAC,EAAE,+BAA+B,CAAC,CAAC;IAC/E,CAAC;IACD,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC,CAAC,CAAC;QACnE,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,sBAAsB,CAAC,EAAE,8BAA8B,CAAC,CAAC;IAChF,CAAC;IAED,6EAA6E;IAC7E,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACrC,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC;QACtD,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,iBAAiB,CAAC,EAAE,iCAAiC,CAAC,CAAC;QAC1E,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,kBAAkB,CAAC,EAAE,kCAAkC,CAAC,CAAC;IAChF,CAAC;IACD,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7F,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,iBAAiB,CAAC,EAAE,6BAA6B,CAAC,CAAC;IAC1E,CAAC;IACD,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,kBAAkB,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACxG,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,kBAAkB,CAAC,EAAE,yBAAyB,CAAC,CAAC;IACvE,CAAC;IAED,6EAA6E;IAC7E,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC/B,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,8BAA8B,CAAC,CAAC;IACxE,CAAC;IACD,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,cAAc,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAC3E,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,sCAAsC,CAAC,CAAC;IAChF,CAAC;IACD,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC;QACvD,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,aAAa,CAAC,EAAE,6BAA6B,CAAC,CAAC;IACtE,CAAC;IACD,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC;QAC9D,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,aAAa,CAAC,EAAE,4BAA4B,CAAC,CAAC;IACrE,CAAC;IACD,CAAC;QACG,kDAAkD;QAClD,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;QACjC,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;QAC1B,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QAC3B,MAAM,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,oCAAoC,CAAC,CAAC;IACvE,CAAC;IACD,CAAC;QACG,sCAAsC;QACtC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;QACnC,MAAM,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,2CAA2C,CAAC,CAAC;IAC/E,CAAC;IACD,CAAC;QACG,4CAA4C;QAC5C,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;QAClC,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QAC3B,MAAM,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,4BAA4B,CAAC,CAAC;IAChE,CAAC;IAED,6EAA6E;IAC7E,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC1C,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAC3D,KAAK,MAAM,IAAI,IAAI,wBAAwB,EAAE,CAAC;YAC1C,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,mBAAmB,IAAI,EAAE,CAAC,EAAE,uCAAuC,IAAI,EAAE,CAAC,CAAC;QAClG,CAAC;IACL,CAAC;IACD,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,sBAAsB,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QAC3F,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,sBAAsB,CAAC,EAAE,yBAAyB,CAAC,CAAC;IAC3E,CAAC;IACD,CAAC;QACG,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC;QACjE,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,uBAAuB,CAAC,EAAE,uCAAuC,CAAC,CAAC;IAC1F,CAAC;IAED,6EAA6E;IAC7E,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAClC,CAAC;QACG,wCAAwC;QACxC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,EAAE,wBAAwB,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,0BAA0B;QAC5F,MAAM,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,wBAAwB,CAAC,EAAE,uCAAuC,CAAC,CAAC;QACzF,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,EAAE,yCAAyC,CAAC,CAAC;IACxE,CAAC;IACD,CAAC;QACG,8BAA8B;QAC9B,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,KAAK,MAAM,KAAK,IAAI,oBAAoB,EAAE,CAAC;YACvC,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC,CAAC;QACjC,CAAC;QACD,MAAM,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,mCAAmC,CAAC,CAAC;QACpE,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,EAAE,uCAAuC,CAAC,CAAC;IACtE,CAAC;IACD,CAAC;QACG,wCAAwC;QACxC,MAAM,CAAC,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,wBAAwB,CAAC,EAAE,kCAAkC,CAAC,CAAC;QACrF,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,uCAAuC,CAAC,CAAC;IAC7E,CAAC;IAED,8EAA8E;IAC9E,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAC9C,CAAC;QACG,4BAA4B;QAC5B,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAC3D,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,EAAE,2BAA2B,CAAC,CAAC;IAC3D,CAAC;IACD,CAAC;QACG,mCAAmC;QACnC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,EAAE,wBAAwB,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACjE,MAAM,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,EAAE,kCAAkC,CAAC,CAAC;IACjE,CAAC;IAED,4EAA4E;IAC5E,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC/C,CAAC;QACG,gCAAgC;QAChC,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE;YACpC,aAAa,EAAE,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,GAAG;YACtC,cAAc,EAAE,GAAG,EAAE,cAAc,EAAE,CAAC,GAAG;SAC5C,CAAC,CAAC;QACH,MAAM,CAAC,SAAS,KAAK,IAAI,EAAE,wBAAwB,CAAC,CAAC;QAErD,uBAAuB;QACvB,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACzB,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,SAAS,CAAC,cAAc,EAAE,KAAK,MAAM,EAAE,oBAAoB,CAAC,CAAC;QAEpE,6CAA6C;QAC7C,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,QAAQ,GAAG,SAAS,CAAC,cAAc,EAAE,CAAC;QAC5C,MAAM,CACF,QAAQ,KAAK,aAAa,IAAI,QAAQ,KAAK,QAAQ,EACnD,kCAAkC,QAAQ,GAAG,CAChD,CAAC;QAEF,oCAAoC;QACpC,SAAS,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,SAAS,CAAC,gBAAgB,EAAE,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,uCAAuC,CAAC,CAAC;QAEtE,kCAAkC;QAClC,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,OAAO,GAAG,SAAS,CAAC,gBAAgB,EAAE,CAAC;QAC7C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,iCAAiC,CAAC,CAAC;QAE1E,oCAAoC;QACpC,SAAS,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAG,SAAS,CAAC,gBAAgB,EAAE,CAAC;QAC9C,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,mCAAmC,CAAC,CAAC;QAE7E,gFAAgF;QAChF,SAAS,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,SAAS,CAAC,gBAAgB,EAAE,CAAC;QACzC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,2CAA2C,CAAC,CAAC;IACpF,CAAC;IAED,6EAA6E;IAC7E,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IACjD,CAAC;QACG,MAAM,OAAO,GAAG,KAA2B,CAAC;QAE5C,4EAA4E;QAC5E,MAAM,MAAM,GAAG,6BAA6B,CAAC,OAAO,CAAC,CAAC;QACtD,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,wDAAwD,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QACrG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,iCAAiC,CAAC,CAAC;QAErE,6CAA6C;QAC7C,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,MAAM,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QACvD,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,QAAQ,EAAE,2BAA2B,CAAC,CAAC;QAE1E,0CAA0C;QAC1C,KAAK,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,oCAAoC;QACjE,8EAA8E;QAC9E,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,SAAS,EAAE,iCAAiC,CAAC,CAAC;QAEjF,0BAA0B;QAC1B,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,QAAQ,EAAE,2BAA2B,CAAC,CAAC;IAC9E,CAAC;IAED,YAAY,EAAE,CAAC;AACnB,CAAC;AAED,QAAQ,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "distark-render",
3
- "version": "1.1.10",
3
+ "version": "1.1.12",
4
4
  "description": "Rendering-agnostic character rig system with TypeScript",
5
5
  "type": "module",
6
6
  "main": "./dist/modules/renderRig.js",
@@ -34,6 +34,10 @@
34
34
  "types": "./dist/modules/adapters/skiaRenderer.d.ts",
35
35
  "import": "./dist/modules/adapters/skiaRenderer.js"
36
36
  },
37
+ "./characterValidator": {
38
+ "types": "./dist/modules/characterValidator.d.ts",
39
+ "import": "./dist/modules/characterValidator.js"
40
+ },
37
41
  "./animationDiff": {
38
42
  "types": "./dist/modules/animationDiff.d.ts",
39
43
  "import": "./dist/modules/animationDiff.js"
@@ -57,6 +61,8 @@
57
61
  "distark-check": "./dist/cli/distark-check.js"
58
62
  },
59
63
  "scripts": {
64
+ "install-cli": "npm run build && if [ -d \"$HOME/bin\" ]; then rm -f $HOME/bin/distark-check && printf '#!/bin/sh\\nexec node %s/dist/cli/distark-check.js \"$@\"\\n' $(pwd) > $HOME/bin/distark-check && chmod +x $HOME/bin/distark-check && echo 'Installed to ~/bin/distark-check'; else echo '~/bin not found, skipping install'; fi",
65
+ "install-cli": "npm run build && printf '#!/bin/sh\\nexec node %s/dist/cli/distark-check.js \"$@\"\\n' $(pwd) > $HOME/bin/distark-check && chmod +x $HOME/bin/distark-check",
60
66
  "build": "tsc",
61
67
  "check": "node dist/cli/distark-check.js",
62
68
  "test-cli": "npm run build && node dist/tests/test-cli.js",