jspsych-tangram 0.0.2 → 0.0.4

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/index.js CHANGED
@@ -2926,8 +2926,7 @@ class InteractionTracker {
2926
2926
  }
2927
2927
  const sectorTangramMap = this.controller.state.cfg.sectors.map((s) => ({
2928
2928
  sectorId: s.id,
2929
- tangramId: s.id
2930
- // In our system, sector ID == tangram ID
2929
+ tangramId: s.tangramId
2931
2930
  }));
2932
2931
  const blueprintOrder = {
2933
2932
  primitives: this.controller.state.primitives.map((bp) => bp.id),
@@ -3432,11 +3431,11 @@ function constructFromSpec(sideLens, angles, firstEdgeUnits) {
3432
3431
  return pts;
3433
3432
  }
3434
3433
  const FIRST_EDGES_UNITS = {
3435
- small_triangle: [P(0, 0), P(0.5, 0.5)],
3436
- parallelogram: [P(0, 0), P(0.5, 0)],
3437
- large_triangle: [P(0, 0), P(0.5, -0.5)],
3438
- med_triangle: [P(0, 0), P(0.5, 0)],
3439
- square: [P(0, 0), P(0.5, 0)]
3434
+ "smalltriangle": [P(0, 0), P(0.5, 0.5)],
3435
+ "parallelogram": [P(0, 0), P(0.5, 0)],
3436
+ "largetriangle": [P(0, 0), P(0.5, -0.5)],
3437
+ "medtriangle": [P(0, 0), P(0.5, 0)],
3438
+ "square": [P(0, 0), P(0.5, 0)]
3440
3439
  };
3441
3440
  const PRIMITIVE_BLUEPRINTS_CACHE = (() => {
3442
3441
  const specs = [
@@ -3448,8 +3447,8 @@ const PRIMITIVE_BLUEPRINTS_CACHE = (() => {
3448
3447
  color: "#f43f5e"
3449
3448
  },
3450
3449
  {
3451
- id: "prim:small",
3452
- kind: "small_triangle",
3450
+ id: "prim:smalltriangle",
3451
+ kind: "smalltriangle",
3453
3452
  sideLens: [HALFDIAGONAL, HALFDIAGONAL, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT],
3454
3453
  angles: [180, 45, 180, 90, 180, 45],
3455
3454
  color: "#f59e0b"
@@ -3462,15 +3461,15 @@ const PRIMITIVE_BLUEPRINTS_CACHE = (() => {
3462
3461
  color: "#10b981"
3463
3462
  },
3464
3463
  {
3465
- id: "prim:med",
3466
- kind: "med_triangle",
3464
+ id: "prim:medtriangle",
3465
+ kind: "medtriangle",
3467
3466
  sideLens: [HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFDIAGONAL, HALFDIAGONAL, HALFDIAGONAL, HALFDIAGONAL],
3468
3467
  angles: [180, 180, 180, 45, 180, 90, 180, 45],
3469
3468
  color: "#3b82f6"
3470
3469
  },
3471
3470
  {
3472
- id: "prim:large",
3473
- kind: "large_triangle",
3471
+ id: "prim:largetriangle",
3472
+ kind: "largetriangle",
3474
3473
  sideLens: [
3475
3474
  HALFDIAGONAL,
3476
3475
  HALFDIAGONAL,
@@ -3540,48 +3539,103 @@ function convertAnchorCompositeToPixels(anchorComposite, primsByKind, gridStepPx
3540
3539
  }
3541
3540
 
3542
3541
  function startConstructionTrial(display_element, params, _jsPsych) {
3543
- const sectors = params.tangrams.map((tangramSpec) => ({
3544
- id: tangramSpec.id,
3545
- silhouette: {
3546
- id: tangramSpec.id,
3547
- mask: tangramSpec.silhouette.mask.map(
3548
- (polygonArray) => polygonArray.map(([x, y]) => ({ x: x ?? 0, y: -(y ?? 0) }))
3549
- // Convert to SVG coords (flip Y)
3550
- ),
3551
- requiredCount: tangramSpec.silhouette.requiredCount
3552
- }
3553
- }));
3542
+ const CANON = /* @__PURE__ */ new Set([
3543
+ "square",
3544
+ "smalltriangle",
3545
+ "parallelogram",
3546
+ "medtriangle",
3547
+ "largetriangle"
3548
+ ]);
3549
+ console.log("[ConstructionApp] Starting tangram conversion...");
3550
+ console.log("[ConstructionApp] Received tangrams:", params.tangrams);
3551
+ console.log("[ConstructionApp] Number of tangrams:", params.tangrams.length);
3552
+ const sectors = params.tangrams.map((tangramSpec, index) => {
3553
+ console.log(`
3554
+ [ConstructionApp] Processing tangram ${index}:`, tangramSpec);
3555
+ console.log(`[ConstructionApp] tangramID: ${tangramSpec.tangramID}`);
3556
+ console.log(`[ConstructionApp] setLabel: ${tangramSpec.setLabel}`);
3557
+ console.log(`[ConstructionApp] solutionTans count: ${tangramSpec.solutionTans?.length}`);
3558
+ console.log(`[ConstructionApp] solutionTans:`, tangramSpec.solutionTans);
3559
+ const filteredTans = tangramSpec.solutionTans.filter((tan) => {
3560
+ const tanName = tan.name ?? tan.kind;
3561
+ const isCanonical = CANON.has(tanName);
3562
+ console.log(`[ConstructionApp] Tan "${tanName}": canonical=${isCanonical}, vertices count=${tan.vertices?.length}`);
3563
+ return isCanonical;
3564
+ });
3565
+ console.log(`[ConstructionApp] Filtered to ${filteredTans.length} canonical pieces`);
3566
+ const mask = filteredTans.map((tan, tanIndex) => {
3567
+ const tanName = tan.name ?? tan.kind;
3568
+ const polygon = tan.vertices.map(([x, y]) => ({ x: x ?? 0, y: -(y ?? 0) }));
3569
+ console.log(`[ConstructionApp] Polygon ${tanIndex} (${tanName}): ${tan.vertices.length} vertices -> ${polygon.length} points`);
3570
+ console.log(`[ConstructionApp] First vertex: [${tan.vertices[0]?.[0]}, ${tan.vertices[0]?.[1]}] -> {x: ${polygon[0]?.x}, y: ${polygon[0]?.y}}`);
3571
+ return polygon;
3572
+ });
3573
+ const sectorId = `sector${index}`;
3574
+ console.log(`[ConstructionApp] Assigned sector ID: ${sectorId}`);
3575
+ console.log(`[ConstructionApp] Final mask has ${mask.length} polygons`);
3576
+ const sector = {
3577
+ id: sectorId,
3578
+ tangramId: tangramSpec.tangramID,
3579
+ silhouette: {
3580
+ id: sectorId,
3581
+ mask
3582
+ }
3583
+ };
3584
+ console.log(`[ConstructionApp] Created sector:`, sector);
3585
+ return sector;
3586
+ });
3587
+ console.log("\n[ConstructionApp] Final sectors array:", sectors);
3588
+ console.log(`[ConstructionApp] Total sectors created: ${sectors.length}`);
3589
+ console.log("\n[ConstructionApp] Processing quickstash macros...");
3590
+ console.log("[ConstructionApp] quickstash_macros:", params.quickstash_macros);
3591
+ console.log("[ConstructionApp] quickstash_macros count:", params.quickstash_macros?.length ?? 0);
3554
3592
  let quickstash = [];
3555
3593
  if (params.quickstash_macros && params.quickstash_macros.length > 0) {
3556
3594
  const firstMacro = params.quickstash_macros[0];
3595
+ console.log("[ConstructionApp] First macro:", firstMacro);
3557
3596
  if (firstMacro && "parts" in firstMacro && firstMacro.parts && firstMacro.parts[0] && "anchorOffset" in firstMacro.parts[0]) {
3597
+ console.log("[ConstructionApp] Detected anchor-based composites, converting to pixels...");
3558
3598
  const primsByKind = /* @__PURE__ */ new Map();
3559
3599
  PRIMITIVE_BLUEPRINTS.forEach((p) => primsByKind.set(p.kind, p));
3560
3600
  quickstash = params.quickstash_macros.map(
3561
3601
  (anchorComposite) => convertAnchorCompositeToPixels(anchorComposite, primsByKind, CONFIG.layout.grid.stepPx)
3562
3602
  // Use current CONFIG grid step
3563
3603
  );
3604
+ console.log("[ConstructionApp] Converted to pixel-based blueprints:", quickstash);
3564
3605
  } else {
3606
+ console.log("[ConstructionApp] Already pixel-based blueprints");
3565
3607
  quickstash = params.quickstash_macros;
3566
3608
  }
3609
+ } else {
3610
+ console.log("[ConstructionApp] No quickstash macros provided");
3567
3611
  }
3612
+ const gameBoardProps = {
3613
+ sectors,
3614
+ quickstash,
3615
+ primitives: PRIMITIVE_BLUEPRINTS,
3616
+ layout: params.layout || "semicircle",
3617
+ target: params.target || "silhouette",
3618
+ input: params.input || "drag",
3619
+ timeLimitMs: params.time_limit_ms || 0,
3620
+ maxQuickstashSlots: CONFIG.layout.defaults.maxQuickstashSlots,
3621
+ mode: "construction",
3622
+ // Explicit construction mode
3623
+ ...params.onInteraction && { onInteraction: params.onInteraction },
3624
+ ...params.onTrialEnd && { onTrialEnd: params.onTrialEnd }
3625
+ };
3626
+ console.log("\n[ConstructionApp] Final GameBoard props:");
3627
+ console.log("[ConstructionApp] sectors count:", gameBoardProps.sectors.length);
3628
+ console.log("[ConstructionApp] quickstash count:", gameBoardProps.quickstash.length);
3629
+ console.log("[ConstructionApp] primitives count:", gameBoardProps.primitives.length);
3630
+ console.log("[ConstructionApp] layout:", gameBoardProps.layout);
3631
+ console.log("[ConstructionApp] target:", gameBoardProps.target);
3632
+ console.log("[ConstructionApp] input:", gameBoardProps.input);
3633
+ console.log("[ConstructionApp] timeLimitMs:", gameBoardProps.timeLimitMs);
3634
+ console.log("[ConstructionApp] mode:", gameBoardProps.mode);
3635
+ console.log("[ConstructionApp] Full props:", gameBoardProps);
3568
3636
  const root = createRoot(display_element);
3569
- root.render(
3570
- React.createElement(GameBoard, {
3571
- sectors,
3572
- quickstash,
3573
- primitives: PRIMITIVE_BLUEPRINTS,
3574
- layout: params.layout || "semicircle",
3575
- target: params.target || "silhouette",
3576
- input: params.input || "drag",
3577
- timeLimitMs: params.time_limit_ms || 0,
3578
- maxQuickstashSlots: CONFIG.layout.defaults.maxQuickstashSlots,
3579
- mode: "construction",
3580
- // Explicit construction mode
3581
- ...params.onInteraction && { onInteraction: params.onInteraction },
3582
- ...params.onTrialEnd && { onTrialEnd: params.onTrialEnd }
3583
- })
3584
- );
3637
+ root.render(React.createElement(GameBoard, gameBoardProps));
3638
+ console.log("[ConstructionApp] GameBoard rendered successfully");
3585
3639
  return { root, display_element, jsPsych: _jsPsych };
3586
3640
  }
3587
3641
 
@@ -3728,6 +3782,8 @@ function startPrepTrial(display_element, params, jsPsych) {
3728
3782
  } = params;
3729
3783
  const prepSectors = Array.from({ length: numQuickstashSlots }, (_, i) => ({
3730
3784
  id: `prep-sector-${i}`,
3785
+ tangramId: `prep-sector-${i}`,
3786
+ // dummy value since prep mode doesn't have tangrams
3731
3787
  silhouette: {
3732
3788
  id: `prep-silhouette-${i}`,
3733
3789
  mask: []