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