jspsych-tangram 0.0.4 → 0.0.5
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/dist/construct/index.browser.js +8 -47
- package/dist/construct/index.browser.js.map +1 -1
- package/dist/construct/index.browser.min.js +11 -15
- package/dist/construct/index.browser.min.js.map +1 -1
- package/dist/construct/index.cjs +8 -47
- package/dist/construct/index.cjs.map +1 -1
- package/dist/construct/index.js +8 -47
- package/dist/construct/index.js.map +1 -1
- package/dist/index.cjs +9 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +9 -48
- package/dist/index.js.map +1 -1
- package/dist/prep/index.browser.js +4 -3
- package/dist/prep/index.browser.js.map +1 -1
- package/dist/prep/index.browser.min.js +1 -1
- package/dist/prep/index.browser.min.js.map +1 -1
- package/dist/prep/index.cjs +4 -3
- package/dist/prep/index.cjs.map +1 -1
- package/dist/prep/index.js +4 -3
- package/dist/prep/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/components/board/GameBoard.tsx +4 -1
- package/src/core/engine/state/BaseGameController.ts +0 -1
- package/src/plugins/tangram-construct/ConstructionApp.tsx +7 -51
- package/src/plugins/tangram-construct/index.ts +1 -1
- package/src/plugins/tangram-prep/index.ts +1 -1
- package/tangram-construct.min.js +11 -15
- package/tangram-prep.min.js +1 -1
package/package.json
CHANGED
|
@@ -357,8 +357,11 @@ export default function GameBoard(props: GameBoardProps) {
|
|
|
357
357
|
setGameCompleted(true);
|
|
358
358
|
|
|
359
359
|
// Finalize trial data tracking (which calls onTrialEnd)
|
|
360
|
+
// Defer to avoid unmounting React while still in commit phase
|
|
360
361
|
if (tracker) {
|
|
361
|
-
|
|
362
|
+
setTimeout(() => {
|
|
363
|
+
tracker.finalizeTrial('auto_complete');
|
|
364
|
+
}, 0);
|
|
362
365
|
}
|
|
363
366
|
}
|
|
364
367
|
};
|
|
@@ -196,7 +196,6 @@ export class BaseGameController {
|
|
|
196
196
|
const allDone = Object.values(this.state.sectors).every((s: SectorState) => !!s.completedAt);
|
|
197
197
|
if (allDone && !this.state.endedAt) {
|
|
198
198
|
this.state.endedAt = NOW();
|
|
199
|
-
console.log("[BaseGameController] all sectors complete");
|
|
200
199
|
}
|
|
201
200
|
}
|
|
202
201
|
|
|
@@ -58,42 +58,24 @@ export function startConstructionTrial(
|
|
|
58
58
|
]);
|
|
59
59
|
|
|
60
60
|
// Convert JSON plugin parameters to internal Sector[] format
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
console.log('[ConstructionApp] Number of tangrams:', params.tangrams.length);
|
|
64
|
-
|
|
65
|
-
const sectors: Sector[] = params.tangrams.map((tangramSpec, index) => {
|
|
66
|
-
console.log(`\n[ConstructionApp] Processing tangram ${index}:`, tangramSpec);
|
|
67
|
-
console.log(`[ConstructionApp] tangramID: ${tangramSpec.tangramID}`);
|
|
68
|
-
console.log(`[ConstructionApp] setLabel: ${tangramSpec.setLabel}`);
|
|
69
|
-
console.log(`[ConstructionApp] solutionTans count: ${tangramSpec.solutionTans?.length}`);
|
|
70
|
-
console.log(`[ConstructionApp] solutionTans:`, tangramSpec.solutionTans);
|
|
71
|
-
|
|
61
|
+
const sectors: Sector[] = params.tangrams.map((tangramSpec, index) => {
|
|
62
|
+
|
|
72
63
|
// Filter to canonical pieces only and convert vertices to polygon format
|
|
73
64
|
const filteredTans = tangramSpec.solutionTans.filter((tan: any) => {
|
|
74
65
|
// Support both "name" and "kind" fields (different JSON formats)
|
|
75
66
|
const tanName = tan.name ?? tan.kind;
|
|
76
67
|
const isCanonical = CANON.has(tanName);
|
|
77
|
-
console.log(`[ConstructionApp] Tan "${tanName}": canonical=${isCanonical}, vertices count=${tan.vertices?.length}`);
|
|
78
68
|
return isCanonical;
|
|
79
69
|
});
|
|
80
70
|
|
|
81
|
-
console.log(`[ConstructionApp] Filtered to ${filteredTans.length} canonical pieces`);
|
|
82
|
-
|
|
83
71
|
const mask = filteredTans.map((tan: any, tanIndex: number) => {
|
|
84
|
-
const tanName = tan.name ?? tan.kind;
|
|
85
72
|
const polygon = tan.vertices.map(([x, y]: number[]) => ({ x: x ?? 0, y: -(y ?? 0) }));
|
|
86
|
-
console.log(`[ConstructionApp] Polygon ${tanIndex} (${tanName}): ${tan.vertices.length} vertices -> ${polygon.length} points`);
|
|
87
|
-
console.log(`[ConstructionApp] First vertex: [${tan.vertices[0]?.[0]}, ${tan.vertices[0]?.[1]}] -> {x: ${polygon[0]?.x}, y: ${polygon[0]?.y}}`);
|
|
88
73
|
return polygon;
|
|
89
74
|
});
|
|
90
75
|
|
|
91
76
|
// Assign sector ID from alphabetical sequence
|
|
92
77
|
const sectorId = `sector${index}`;
|
|
93
78
|
|
|
94
|
-
console.log(`[ConstructionApp] Assigned sector ID: ${sectorId}`);
|
|
95
|
-
console.log(`[ConstructionApp] Final mask has ${mask.length} polygons`);
|
|
96
|
-
|
|
97
79
|
const sector = {
|
|
98
80
|
id: sectorId,
|
|
99
81
|
tangramId: tangramSpec.tangramID,
|
|
@@ -103,27 +85,17 @@ export function startConstructionTrial(
|
|
|
103
85
|
},
|
|
104
86
|
};
|
|
105
87
|
|
|
106
|
-
console.log(`[ConstructionApp] Created sector:`, sector);
|
|
107
88
|
return sector;
|
|
108
89
|
});
|
|
109
90
|
|
|
110
|
-
console.log('\n[ConstructionApp] Final sectors array:', sectors);
|
|
111
|
-
console.log(`[ConstructionApp] Total sectors created: ${sectors.length}`);
|
|
112
|
-
|
|
113
91
|
// Convert quickstash_macros to Blueprint[] format
|
|
114
92
|
// Handle both anchor-based composites and pre-converted blueprints
|
|
115
|
-
console.log('\n[ConstructionApp] Processing quickstash macros...');
|
|
116
|
-
console.log('[ConstructionApp] quickstash_macros:', params.quickstash_macros);
|
|
117
|
-
console.log('[ConstructionApp] quickstash_macros count:', params.quickstash_macros?.length ?? 0);
|
|
118
|
-
|
|
119
93
|
let quickstash: Blueprint[] = [];
|
|
120
94
|
|
|
121
95
|
if (params.quickstash_macros && params.quickstash_macros.length > 0) {
|
|
122
96
|
// Check if the first item has anchorOffset (anchor-based) or offset (pixel-based)
|
|
123
97
|
const firstMacro = params.quickstash_macros[0];
|
|
124
|
-
console.log('[ConstructionApp] First macro:', firstMacro);
|
|
125
98
|
if (firstMacro && 'parts' in firstMacro && firstMacro.parts && firstMacro.parts[0] && 'anchorOffset' in firstMacro.parts[0]) {
|
|
126
|
-
console.log('[ConstructionApp] Detected anchor-based composites, converting to pixels...');
|
|
127
99
|
|
|
128
100
|
// Create primitive map for conversion
|
|
129
101
|
const primsByKind = new Map<TanKind, PrimitiveBlueprint>();
|
|
@@ -133,14 +105,11 @@ export function startConstructionTrial(
|
|
|
133
105
|
quickstash = (params.quickstash_macros as AnchorComposite[]).map(anchorComposite =>
|
|
134
106
|
convertAnchorCompositeToPixels(anchorComposite, primsByKind, CONFIG.layout.grid.stepPx) // Use current CONFIG grid step
|
|
135
107
|
);
|
|
136
|
-
console.log('[ConstructionApp] Converted to pixel-based blueprints:', quickstash);
|
|
137
108
|
} else {
|
|
138
|
-
console.log('[ConstructionApp] Already pixel-based blueprints');
|
|
139
109
|
// Already pixel-based blueprints
|
|
140
110
|
quickstash = params.quickstash_macros as Blueprint[];
|
|
141
111
|
}
|
|
142
112
|
} else {
|
|
143
|
-
console.log('[ConstructionApp] No quickstash macros provided');
|
|
144
113
|
}
|
|
145
114
|
|
|
146
115
|
// Create React root and render GameBoard
|
|
@@ -148,31 +117,18 @@ export function startConstructionTrial(
|
|
|
148
117
|
sectors,
|
|
149
118
|
quickstash,
|
|
150
119
|
primitives: PRIMITIVE_BLUEPRINTS,
|
|
151
|
-
layout:
|
|
152
|
-
target:
|
|
153
|
-
input:
|
|
154
|
-
timeLimitMs: params.time_limit_ms
|
|
120
|
+
layout: params.layout as LayoutMode,
|
|
121
|
+
target: params.target as PlacementTarget,
|
|
122
|
+
input: params.input as InputMode,
|
|
123
|
+
timeLimitMs: params.time_limit_ms,
|
|
155
124
|
maxQuickstashSlots: CONFIG.layout.defaults.maxQuickstashSlots,
|
|
156
|
-
mode: 'construction' as const,
|
|
125
|
+
mode: 'construction' as const,
|
|
157
126
|
...(params.onInteraction && { onInteraction: params.onInteraction }),
|
|
158
127
|
...(params.onTrialEnd && { onTrialEnd: params.onTrialEnd })
|
|
159
128
|
};
|
|
160
129
|
|
|
161
|
-
console.log('\n[ConstructionApp] Final GameBoard props:');
|
|
162
|
-
console.log('[ConstructionApp] sectors count:', gameBoardProps.sectors.length);
|
|
163
|
-
console.log('[ConstructionApp] quickstash count:', gameBoardProps.quickstash.length);
|
|
164
|
-
console.log('[ConstructionApp] primitives count:', gameBoardProps.primitives.length);
|
|
165
|
-
console.log('[ConstructionApp] layout:', gameBoardProps.layout);
|
|
166
|
-
console.log('[ConstructionApp] target:', gameBoardProps.target);
|
|
167
|
-
console.log('[ConstructionApp] input:', gameBoardProps.input);
|
|
168
|
-
console.log('[ConstructionApp] timeLimitMs:', gameBoardProps.timeLimitMs);
|
|
169
|
-
console.log('[ConstructionApp] mode:', gameBoardProps.mode);
|
|
170
|
-
console.log('[ConstructionApp] Full props:', gameBoardProps);
|
|
171
|
-
|
|
172
130
|
const root = createRoot(display_element);
|
|
173
131
|
root.render(React.createElement(GameBoard, gameBoardProps));
|
|
174
132
|
|
|
175
|
-
console.log('[ConstructionApp] GameBoard rendered successfully');
|
|
176
|
-
|
|
177
133
|
return { root, display_element, jsPsych: _jsPsych };
|
|
178
134
|
}
|
|
@@ -140,7 +140,7 @@ class TangramConstructPlugin implements JsPsychPlugin<Info> {
|
|
|
140
140
|
target: trial.target,
|
|
141
141
|
input: trial.input,
|
|
142
142
|
layout: trial.layout,
|
|
143
|
-
time_limit_ms: trial.time_limit_ms
|
|
143
|
+
time_limit_ms: trial.time_limit_ms,
|
|
144
144
|
onInteraction: trial.onInteraction,
|
|
145
145
|
onTrialEnd: wrappedOnTrialEnd
|
|
146
146
|
};
|
|
@@ -101,7 +101,7 @@ class TangramPrepPlugin implements JsPsychPlugin<Info> {
|
|
|
101
101
|
};
|
|
102
102
|
|
|
103
103
|
const params: StartPrepTrialParams = {
|
|
104
|
-
numQuickstashSlots: trial.num_quickstash_slots
|
|
104
|
+
numQuickstashSlots: trial.num_quickstash_slots,
|
|
105
105
|
maxPiecesPerMacro: trial.max_pieces_per_macro,
|
|
106
106
|
minPiecesPerMacro: trial.min_pieces_per_macro,
|
|
107
107
|
inputMode: trial.input as "click" | "drag",
|