jspsych-tangram 0.0.1 → 0.0.3

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