{
  "information": {
    "Title": "ejss_model_StackingMagnet8 Stacking ring magnets",
    "Author": [
      "weelookang@gmail.com",
      "Francisco Esquembre",
      "Felix J. Garcia Clemente",
      "Coco",
      "Siti"
    ],
    "AuthorLogo": [
      "./1authorlookangphoto5050.png",
      "./01authorPacoEsquembre2011.png",
      "./01authorFelix_J_Garcia_Clemente.png",
      "./StackingMagnet/coco.png",
      "./StackingMagnet/siti.png"
    ],
    "Password": "",
    "Keywords": "",
    "Abstract": "Corrected qualitative 1D stacking-ring magnet physics: like facing poles repel, unlike facing poles attract, iron is always attracted, wood is non-magnetic, pairwise forces obey equal-and-opposite reactions, and contact is resolved separately from Runge-Kutta force evaluation.",
    "Copyright": "",
    "Level": "",
    "Language": "",
    "Logo": [
      "./StackingMagnet/tempsnip.png"
    ],
    "RunAlways": "true",
    "ModelTab": "",
    "ModelTabTitle": "",
    "ModelName": "",
    "FixedNavigationBar": "false",
    "CSSFile": "",
    "DetectedFiles": [
      "./01authorFelix_J_Garcia_Clemente.png",
      "./01authorPacoEsquembre2011.png",
      "./1authorlookangphoto5050.png",
      "./StackingMagnet/coco.png",
      "./StackingMagnet/siti.png",
      "./StackingMagnet/tempsnip.png"
    ],
    "AuxiliaryFiles": [
      "./StackingMagnet/"
    ],
    "HTMLHead": "",
    "SaveInXMLFormat": "false",
    "IncludeSource": "true",
    "IncludeLibrary": "true",
    "UglifyJS": "false",
    "PreviewFullModel": "false",
    "UseInterpreter": "true",
    "UseDeltaForODE": "false"
  },
  "description": {
    "pages": [
      {
        "Name": "Intro Page",
        "Active": "true",
        "Internal": "false",
        "Type": "DESCRIPTION_EDITOR",
        "Locale": "_default_",
        "Title": "Intro Page",
        "External": "false",
        "Code": "<html>\n<head></head>\n<body>\n<p> </p><p style=\"margin-top: 0\">      Variables for references:    </p><p> </p><p style=\"margin-top: 0\">          </p><p> </p><p style=\"margin-top: 0\">      - xMove,yMove,zMove,wMove&amp;iMove are indications for when the object is       being dragged around. These variables are alr assigned false initially,       true on drag and false on release.    </p><p> </p><p style=\"margin-top: 0\">      - onRod is alr defined but not used. It is for indicating if a object is       on the Rod's top.    </p><p> </p><p style=\"margin-top: 0\">          </p><p> </p><p style=\"margin-top: 0\">      We tried to make a barrier where the user should not cross, specifically       for Magnet X we tried to form a barrier at the plastic rod.    </p><p> </p><p style=\"margin-top: 0\">      -----------------------------------------------------------------------------------------------------------------------------------------------------    </p><p> </p><p style=\"margin-top: 0\">          </p><p> </p><p>      &nbsp;Aims:    </p><p> </p><ul><li>        No dragging of magnet inside the rod.      </li><li> <del>Magnets dont feel any repelsion or attraction when blocked by         Wooden Ring. </del> </li><li> <del>attractive power should consider distance </del> </li><li> <del>repulsion should include MASS --&gt; use NumItemAbove() </del> </li><li> <del>find the item behind a selected item --&gt; use itemBelow()</del> </li><li> </li></ul><p> </p><p> </p><p>      &nbsp;Problems:    </p><p> </p><ul><li>        Error when item is dragged above \"Release area\".      </li><li> <del>Custom Prelim2 --&gt; Error for falling of Wooden Ring FOLLOWED         by Iron ring</del> </li><li> <del>distance should not be shared across all items.</del> </li><li> <del>X Repelsion --&gt; acceleration X</del> </li></ul><p> </p><p>      &nbsp;    </p><p> </p>\n</body>\n</html>"
      },
      {
        "Name": "Physics model v2",
        "Active": "true",
        "Internal": "false",
        "Type": "DESCRIPTION_EDITOR",
        "Locale": "_default_",
        "Title": "Physics model v2",
        "External": "false",
        "Code": "<html>\n<head></head>\n<body>\n<h2>Physics model v2</h2><p>This version uses 120 Hz physics stepping, pairwise magnetic forces, local critical damping for repelling magnet gaps, momentum-conserving collision impulses, and unilateral rigid contact constraints. The contact normal force can push but cannot pull, so a payload remains supported without jitter but separates when the required normal force would become negative.</p><p>The magnetic force coefficients remain qualitative until calibrated against measured force-versus-gap data for the actual ring magnets.</p>\n</body>\n</html>"
      }
    ]
  },
  "model": {
    "variables": {
      "pages": [
        {
          "Name": "Var Table",
          "Active": "true",
          "Internal": "false",
          "Type": "VARIABLE_EDITOR",
          "PageComment": "",
          "Variables": [
            {
              "Name": "t",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "dt",
              "Value": "1.0/120.0",
              "Type": "double",
              "Dimension": "",
              "Comment": "physics timestep; 120 Hz with SPD=2 and FPS=60 for stable contacts",
              "Domain": "public"
            },
            {
              "Name": "pi",
              "Value": "Math.PI",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "xBlockSize",
              "Value": "4",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "yBlockSize",
              "Value": "1",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "flipX",
              "Value": "false",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "X1 is default",
              "Domain": "public"
            },
            {
              "Name": "flipY",
              "Value": "false",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "Y1 is default",
              "Domain": "public"
            },
            {
              "Name": "flipZ",
              "Value": "false",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "Z1 is default",
              "Domain": "public"
            },
            {
              "Name": "flipXnumber",
              "Value": "1",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "flipYnumber",
              "Value": "1",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "flipZnumber",
              "Value": "1",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "redC",
              "Value": "\"rgba(235,0,0,1)\"",
              "Type": "String",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "blueC",
              "Value": "\"rgba(0,128,255,1)\"",
              "Type": "String",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            }
          ]
        },
        {
          "Name": "Var Table 2",
          "Active": "true",
          "Internal": "false",
          "Type": "VARIABLE_EDITOR",
          "PageComment": "",
          "Variables": [
            {
              "Name": "mMagnetX",
              "Value": "1",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "mMagnetY",
              "Value": "1",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "mMagnetZ",
              "Value": "1",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "xMagnetX",
              "Value": "-8.5",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "yMagnetX",
              "Value": "10.5",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "vyMagnetX",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "ayMagnetX",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "g",
              "Value": "-9.81",
              "Type": "double",
              "Dimension": "",
              "Comment": "gravity acceleration (downward)",
              "Domain": "public"
            },
            {
              "Name": "xMagnetY",
              "Value": "-8.5",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "yMagnetY",
              "Value": "8.5",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "vyMagnetY",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "ayMagnetY",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "xMagnetZ",
              "Value": "-8.5",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "yMagnetZ",
              "Value": "6.5",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "vyMagnetZ",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "ayMagnetZ",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "xWooden",
              "Value": "-8.5",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "yWooden",
              "Value": "4.5",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "vyWooden",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "ayWooden",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "xIron",
              "Value": "-8.5",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "yIron",
              "Value": "2.5",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "vyIron",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "ayIron",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "xLine",
              "Value": "2",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "font",
              "Value": "\"normal normal 2vw\"",
              "Type": "String",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "releasex",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "releasey",
              "Value": "12",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "releasedx",
              "Value": "xBlockSize+1.5",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "releasedy",
              "Value": "yBlockSize+0.5",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "basex",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "basey",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            }
          ]
        },
        {
          "Name": "Var Table 3",
          "Active": "true",
          "Internal": "false",
          "Type": "VARIABLE_EDITOR",
          "PageComment": "",
          "Variables": [
            {
              "Name": "xMove",
              "Value": "false",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "yMove",
              "Value": "false",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "zMove",
              "Value": "false",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "wMove",
              "Value": "false",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "iMove",
              "Value": "false",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "onRod",
              "Value": "false",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "rodList",
              "Value": "[]",
              "Type": "Object",
              "Dimension": "",
              "Comment": "Items in the rod",
              "Domain": "public"
            },
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "distance",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            }
          ]
        },
        {
          "Name": "layout",
          "Active": "true",
          "Internal": "false",
          "Type": "VARIABLE_EDITOR",
          "PageComment": "",
          "Variables": [
            {
              "Name": "iOS",
              "Value": "/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "http://stackoverflow.com/questions/9038625/detect-if-device-is-ios",
              "Domain": "public"
            },
            {
              "Name": "Android",
              "Value": "/Android|android/i.test(navigator.userAgent)",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "iPad",
              "Value": "/iPad/.test(navigator.userAgent) && !window.MSStream",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "http://stackoverflow.com/questions/9038625/detect-if-device-is-ios",
              "Domain": "public"
            },
            {
              "Name": "iPhone",
              "Value": "/iPhone|iPod/.test(navigator.userAgent) && !window.MSStream",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "http://stackoverflow.com/questions/9038625/detect-if-device-is-ios",
              "Domain": "public"
            },
            {
              "Name": "Width",
              "Value": "(_isEPub)?\"400\":\"100%\"",
              "Type": "String",
              "Dimension": "",
              "Comment": "display width",
              "Domain": "public"
            },
            {
              "Name": "Height",
              "Value": "(_isEPub)?\"500\":\"100%\"",
              "Type": "String",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "Width1",
              "Value": "\"100%\"",
              "Type": "String",
              "Dimension": "",
              "Comment": "display width",
              "Domain": "public"
            },
            {
              "Name": "Width2",
              "Value": "\"50%\"",
              "Type": "String",
              "Dimension": "",
              "Comment": "display width",
              "Domain": "public"
            },
            {
              "Name": "world",
              "Value": "true",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "graph",
              "Value": "true",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "disabledworld",
              "Value": "false",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "disabled",
              "Value": "false",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            }
          ]
        },
        {
          "Name": "cells",
          "Active": "true",
          "Internal": "false",
          "Type": "VARIABLE_EDITOR",
          "PageComment": "",
          "Variables": [
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "xmin",
              "Value": "-10",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "xmax",
              "Value": "10",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "ymin",
              "Value": "-10",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "ymax",
              "Value": "10",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            }
          ]
        },
        {
          "Name": "magnets",
          "Active": "true",
          "Internal": "false",
          "Type": "VARIABLE_EDITOR",
          "PageComment": "",
          "Variables": [
            {
              "Name": "distanceXY",
              "Value": "Math.abs(yMagnetX-yMagnetY)",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "distanceXZ",
              "Value": "Math.abs(yMagnetX-yMagnetZ)",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "distanceXW",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "distanceXI",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "distanceYZ",
              "Value": "Math.abs(yMagnetY-yMagnetZ)",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "distanceYW",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "distanceYI",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "distanceZW",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "distanceZI",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "attractivepowerXY",
              "Value": "300/(1+distanceXY)",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "attractivepowerXZ",
              "Value": "300/(1+distanceXZ)",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "attractivepowerXW",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "attractivepowerXI",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "attractivepowerYZ",
              "Value": "300/(1+distanceYZ)",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "attractivepowerYW",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "attractivepowerYI",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "attractivepowerZW",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "attractivepowerZI",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "tol",
              "Value": "3.5",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "stageMaster",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "debugging",
              "Domain": "public"
            },
            {
              "Name": "stageMaster2",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "debugging",
              "Domain": "public"
            },
            {
              "Name": "stageX",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "debugging",
              "Domain": "public"
            },
            {
              "Name": "stageY",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "debugging",
              "Domain": "public"
            },
            {
              "Name": "stageZ",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "debugging",
              "Domain": "public"
            },
            {
              "Name": "stageW",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "stageI",
              "Value": "0",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "k",
              "Value": "0.08",
              "Type": "double",
              "Dimension": "",
              "Comment": "legacy damping parameter; superseded by rodDrag and critical magnetic damping",
              "Domain": "public"
            },
            {
              "Name": "mass",
              "Value": "1.1",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "",
              "Value": "",
              "Type": "double",
              "Dimension": "",
              "Comment": "",
              "Domain": "public"
            },
            {
              "Name": "mWooden",
              "Value": "1.0",
              "Type": "double",
              "Dimension": "",
              "Comment": "wooden ring mass (relative model units; tune to measured mass)",
              "Domain": "public"
            },
            {
              "Name": "mIron",
              "Value": "1.0",
              "Type": "double",
              "Dimension": "",
              "Comment": "iron ring mass (relative model units; tune to measured mass)",
              "Domain": "public"
            },
            {
              "Name": "magnetStrength",
              "Value": "100.0",
              "Type": "double",
              "Dimension": "",
              "Comment": "Overall magnet-magnet force scale. Increased to 100 for stronger close-range repulsion in this learning model.",
              "Domain": "public"
            },
            {
              "Name": "ironStrength",
              "Value": "24.0",
              "Type": "double",
              "Dimension": "",
              "Comment": "qualitative magnet-iron attraction coefficient",
              "Domain": "public"
            },
            {
              "Name": "magneticDampingRatio",
              "Value": "1.0",
              "Type": "double",
              "Dimension": "",
              "Comment": "zeta=1 gives local critical damping for each repelling magnetic gap",
              "Domain": "public"
            },
            {
              "Name": "magneticDampingCap",
              "Value": "4.0",
              "Type": "double",
              "Dimension": "",
              "Comment": "caps phenomenological magnetic damping to this multiple of conservative force",
              "Domain": "public"
            },
            {
              "Name": "rodDrag",
              "Value": "0.0",
              "Type": "double",
              "Dimension": "",
              "Comment": "Set to zero so isolated falling objects are in textbook free fall; magnetic damping is handled pairwise.",
              "Domain": "public"
            },
            {
              "Name": "contactRestitution",
              "Value": "0.06",
              "Type": "double",
              "Dimension": "",
              "Comment": "normal coefficient of restitution for ring impacts; near-inelastic but preserves impulse physics",
              "Domain": "public"
            },
            {
              "Name": "contactSlop",
              "Value": "0.004",
              "Type": "double",
              "Dimension": "",
              "Comment": "small contact persistence tolerance to suppress numerical chatter/jitter",
              "Domain": "public"
            },
            {
              "Name": "contactVelocityThreshold",
              "Value": "0.08",
              "Type": "double",
              "Dimension": "",
              "Comment": "below this relative speed, supported touching bodies settle into persistent contact",
              "Domain": "public"
            },
            {
              "Name": "contactIterations",
              "Value": "14",
              "Type": "double",
              "Dimension": "",
              "Comment": "projected Gauss-Seidel iterations for normal contact constraints",
              "Domain": "public"
            }
          ]
        },
        {
          "Name": "Learning guidance",
          "Active": "true",
          "Internal": "false",
          "Type": "VARIABLE_EDITOR",
          "PageComment": "Dynamic productive-noticing text shown while the model runs.",
          "Variables": [
            {
              "Name": "showLearningHints",
              "Value": "true",
              "Type": "boolean",
              "Dimension": "",
              "Comment": "Show/hide the dynamic productive-noticing panel.",
              "Domain": "public"
            },
            {
              "Name": "learningHintHtml",
              "Value": "\"<b>What to notice:</b> Drag an object to the release area. Watch whether gravity, magnetic push/pull, or contact changes its motion.\"",
              "Type": "String",
              "Dimension": "",
              "Comment": "Dynamic learner-facing explanation of the current physical state.",
              "Domain": "public"
            },
            {
              "Name": "learningHintMode",
              "Value": "\"ready\"",
              "Type": "String",
              "Dimension": "",
              "Comment": "Current guidance state; useful for debugging or xAPI later.",
              "Domain": "public"
            },
            {
              "Name": "impactHintText",
              "Value": "\"\"",
              "Type": "String",
              "Dimension": "",
              "Comment": "Transient collision explanation.",
              "Domain": "public"
            },
            {
              "Name": "impactHintUntil",
              "Value": "-1",
              "Type": "double",
              "Dimension": "",
              "Comment": "Simulation time until which the transient impact hint remains visible.",
              "Domain": "public"
            },
            {
              "Name": "hintHoldSeconds",
              "Value": "0.9",
              "Type": "double",
              "Dimension": "",
              "Comment": "How long a short collision message remains visible.",
              "Domain": "public"
            },
            {
              "Name": "hoveredLearningItem",
              "Value": "\"\"",
              "Type": "String",
              "Dimension": "",
              "Comment": "Object currently under the pointer: X, Y, Z, W or I.",
              "Domain": "public"
            },
            {
              "Name": "hoverHintHtml",
              "Value": "\"\"",
              "Type": "String",
              "Dimension": "",
              "Comment": "Object-specific productive-noticing explanation shown while the pointer is over an object.",
              "Domain": "public"
            }
          ]
        }
      ]
    },
    "initialization": {
      "pages": []
    },
    "evolution": {
      "information": {
        "FPS": "25",
        "SPD": "2",
        "RealTimeVariable": "",
        "Autoplay": "true"
      },
      "pages": [
        {
          "Name": "Evol Page",
          "Active": "true",
          "Internal": "false",
          "Type": "ODE_EDITOR",
          "Comment": "120 Hz RK4 smooth-force integration plus impulse/constraint contact solver; local critical damping for repelling magnet pairs.",
          "IndependentVariable": "t",
          "Increment": "dt",
          "Equations": [
            {
              "state": "yMagnetX",
              "rate": "vyMagnetX"
            },
            {
              "state": "vyMagnetX",
              "rate": "ayMagnetX"
            },
            {
              "state": "yMagnetY",
              "rate": "vyMagnetY"
            },
            {
              "state": "vyMagnetY",
              "rate": "ayMagnetY"
            },
            {
              "state": "yMagnetZ",
              "rate": "vyMagnetZ"
            },
            {
              "state": "vyMagnetZ",
              "rate": "ayMagnetZ"
            },
            {
              "state": "yWooden",
              "rate": "vyWooden"
            },
            {
              "state": "vyWooden",
              "rate": "ayWooden"
            },
            {
              "state": "yIron",
              "rate": "vyIron"
            },
            {
              "state": "vyIron",
              "rate": "ayIron"
            },
            {
              "state": "",
              "rate": ""
            }
          ],
          "Method": "RungeKutta",
          "AbsoluteTolerance": "0.00001",
          "PreliminaryCode": {
            "Code": "prelim ();\n//prelimModular ();\n",
            "Comment": "Code to be executed before rate equations are evaluated"
          },
          "EventMaximumStep": "",
          "Events": {
            "pages": [
              {
                "Type": "EVENT_EDITOR",
                "Name": "hitbottomX",
                "Active": "false",
                "Internal": "false",
                "EventType": "CROSSING_EVENT",
                "Method": "BISECTION",
                "Iterations": "100",
                "Tolerance": "1.0e-5",
                "StopAtEvent": "true",
                "ZeroCondition": "if (xMagnetX==0){ \nreturn yMagnetX- yBlockSize/2- 0;\n}",
                "Action": "//_pause();\n\nvyMagnetX=0; // make stop moving\n//vyMagnetY=0; // make stop moving\n",
                "Comment": "Disabled: contact handled by enforceRodContacts(); legacy event could suppress magnetic repulsion."
              },
              {
                "Type": "EVENT_EDITOR",
                "Name": "hitbottomY",
                "Active": "false",
                "Internal": "false",
                "EventType": "CROSSING_EVENT",
                "Method": "BISECTION",
                "Iterations": "100",
                "Tolerance": "1.0e-5",
                "StopAtEvent": "true",
                "ZeroCondition": "if (xMagnetY==0){ \nreturn yMagnetY- yBlockSize/2- 0;\n}\n",
                "Action": "//_pause();\n\n//vyMagnetX=0; // make stop moving\nvyMagnetY=0; // make stop moving\n",
                "Comment": "Disabled: contact handled by enforceRodContacts(); legacy event could suppress magnetic repulsion."
              },
              {
                "Type": "EVENT_EDITOR",
                "Name": "topXhitYbottom",
                "Active": "false",
                "Internal": "false",
                "EventType": "CROSSING_EVENT",
                "Method": "BISECTION",
                "Iterations": "100",
                "Tolerance": "1.0e-5",
                "StopAtEvent": "true",
                "ZeroCondition": "if (xMagnetX==0&&xMagnetY==0){ //check in rod align\nreturn yMagnetY-  yMagnetX+ yBlockSize;\n}",
                "Action": "//_pause();\n//alert(\"topXhitYbottom\");\n\nvyMagnetX=0; // make stop moving\nvyMagnetY=0; // make stop moving",
                "Comment": "Disabled: contact handled by enforceRodContacts(); legacy event could suppress magnetic repulsion."
              },
              {
                "Type": "EVENT_EDITOR",
                "Name": "topYhitXbottom",
                "Active": "false",
                "Internal": "false",
                "EventType": "CROSSING_EVENT",
                "Method": "BISECTION",
                "Iterations": "100",
                "Tolerance": "1.0e-5",
                "StopAtEvent": "true",
                "ZeroCondition": "if (xMagnetX==0&&xMagnetY==0){ //check in rod align\nreturn yMagnetX-  yMagnetY+ yBlockSize;\n}",
                "Action": "//_pause();\n//alert(\"topYhitXbottom\");\nvyMagnetX=0; // make stop moving\nvyMagnetY=0; // make stop moving\n",
                "Comment": "Disabled: contact handled by enforceRodContacts(); legacy event could suppress magnetic repulsion."
              }
            ]
          },
          "ZenoEffect": {
            "Code": "",
            "Comment": "",
            "StopAfterEffect": "true"
          },
          "AccelerationIndependentOfVelocity": "false",
          "ForceSynchronization": "false",
          "UseBestInterpolation": "false",
          "EstimateFirstStep": "false",
          "MemoryLength": "",
          "InternalStep": "",
          "MaximumStep": "0.008333333333333333",
          "MaximumNumberOfSteps": "10000",
          "RelativeTolerance": "",
          "DelayList": "",
          "DelayMaximum": "",
          "DelayAddDiscont": "",
          "DelayInitialCondition": {
            "Code": "",
            "Comment": ""
          },
          "DirectIncidenceMatrix": "",
          "Discontinuities": {
            "pages": []
          },
          "ErrorHandling": {
            "pages": []
          }
        }
      ]
    },
    "fixed_relations": {
      "pages": [
        {
          "Name": "flip",
          "Active": "true",
          "Internal": "false",
          "Type": "CODE_EDITOR",
          "Comment": "",
          "Code": "if (flipX==true){ // set flipX to 1 or -1 depending on attract or repel\n  \n   flipXnumber =-1;\n    }\n    else {\n      flipXnumber =1;\n      }\n      \n      if (flipY==true){ // set flipX to 1 or -1 depending on attract or repel\n  \n   flipYnumber =-1;\n    }\n    else {\n      flipYnumber =1;\n      }\n      if (flipZ==true){ // set flipX to 1 or -1 depending on attract or repel\n  \n   flipZnumber =-1;\n    }\n    else {\n      flipZnumber =1;\n      }\n"
        },
        {
          "Name": "distancec",
          "Active": "true",
          "Internal": "false",
          "Type": "CODE_EDITOR",
          "Comment": "diagnostic distances/force magnitudes; dynamics are computed in prelim()",
          "Code": "distanceXY = Math.abs(yMagnetX-yMagnetY);\ndistanceXZ = Math.abs(yMagnetX-yMagnetZ);\ndistanceXW = Math.abs(yMagnetX-yWooden);\ndistanceXI = Math.abs(yMagnetX-yIron);\n\ndistanceYZ = Math.abs(yMagnetY-yMagnetZ);\ndistanceYW = Math.abs(yMagnetY-yWooden);\ndistanceYI = Math.abs(yMagnetY-yIron);\n\ndistanceZW = Math.abs(yMagnetZ-yWooden);\ndistanceZI = Math.abs(yMagnetZ-yIron);\n\n// Stored for the existing debug/UI variables. Wooden ring has no magnetic force.\nattractivepowerXY = magnetForce(distanceXY);\nattractivepowerXZ = magnetForce(distanceXZ);\nattractivepowerXW = 0;\nattractivepowerXI = ironAttractionForce(distanceXI);\n\nattractivepowerYZ = magnetForce(distanceYZ);\nattractivepowerYW = 0;\nattractivepowerYI = ironAttractionForce(distanceYI);\n\nattractivepowerZW = 0;\nattractivepowerZI = ironAttractionForce(distanceZI);\n"
        },
        {
          "Name": "prelimModular",
          "Active": "true",
          "Internal": "false",
          "Type": "CODE_EDITOR",
          "Comment": "",
          "Code": "//prelimModular ();"
        },
        {
          "Name": "prelim",
          "Active": "true",
          "Internal": "false",
          "Type": "CODE_EDITOR",
          "Comment": "Post-step collision impulses, position projection, and persistent-contact stabilization.",
          "Code": "// Resolve impact and rigid unilateral contact after each integration substep.\nenforceRodContacts();\n"
        },
        {
          "Name": "learningGuidance",
          "Active": "true",
          "Internal": "false",
          "Type": "CODE_EDITOR",
          "Comment": "Update productive-noticing text after the physics/contact state is resolved.",
          "Code": "updateLearningGuidance();\nupdateHoveredObjectGuidance();\n"
        }
      ]
    },
    "custom": {
      "pages": [
        {
          "Name": "fullscreen",
          "Active": "true",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "",
          "Code": "//https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode\n// does not work for iOS \n/*jslint browser:true */\nfunction toggleFullScreen() {\n  if (!document.fullscreenElement &&    // alternative standard method\n      !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement ) {  // current working methods\n    if (document.documentElement.requestFullscreen) {\n      document.documentElement.requestFullscreen();\n    } else if (document.documentElement.msRequestFullscreen) {\n      document.documentElement.msRequestFullscreen();\n    } else if (document.documentElement.mozRequestFullScreen) {\n      document.documentElement.mozRequestFullScreen();\n    } else if (document.documentElement.webkitRequestFullscreen) {\n      document.documentElement.webkitRequestFullscreen();\n    }\n  } else {\n    if (document.exitFullscreen) {\n      document.exitFullscreen();\n    } else if (document.msExitFullscreen) {\n      document.msExitFullscreen();\n    } else if (document.mozCancelFullScreen) {\n      document.mozCancelFullScreen();\n    } else if (document.webkitExitFullscreen) {\n      document.webkitExitFullscreen();\n    }\n  }\n}"
        },
        {
          "Name": "changeOrientation",
          "Active": "true",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "",
          "Code": "// code to be copied to EJSS source code under Custom and used in drawingPanel3D and plottingPanel2D\n// address the problem is height difference is iOS app , epub, and Firefox\n// user need to change only k and kepub\n// copy %changeOrientation()% into the Height Field of drawingPanel3D and plottingPanel2D\nfunction changeOrientation() {\n \nvar k =0.75 ; // k control height 1 is for full screen, 0.9 shorten etc\nvar kapple =k // control apple app height\nvar kepub =k ;\n// check platform for Apps\ntry { // allow code to run in Student Learning Space \n  var iOSapp =  (typeof parent.device != 'undefined' && parent.device.platform == \"iOS\");\n  var Androidapp = (typeof parent.device != 'undefined' && parent.device.platform == \"Android\");\n} catch(e) {\n  var iOSapp = false;\n  var Androidapp = false;\n}\n// check platform for web browsers\nvar iOS =/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;\nvar iPad =/iPad/.test(navigator.userAgent) && !window.MSStream;\nvar iPhone = /iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;\nvar Android= /Android|android/i.test(navigator.userAgent);\n\n//navigator\nvar Firefox = navigator.userAgent.indexOf(\"Firefox\") != -1;\n \nswitch (window.orientation) { // using window.orientation as deciding factor\n  case 0:\n  case 180:\n    this.screenOrientation = 'portrait';\n    if (iOSapp){ // does not seems to work\n      \n      return window.screen.height*kapple;  //0.1 for app and 0.1 for nonfullscreenapp  \n    \n    }\n    else if (_isEPub){ // does not seems to work\n      //   return Math.max(window.screen.width,window.screen.height)*0.9;\n      return window.innerHeight*kepub;  //0.1 for app and 0.1 for nonfullscreenapp  \n      // return window.screen.height;\n      //  return window.innerHeight;\n      // return document.documentElement.clientHeight;\n    }\n   \n    else {\n     \n      return 100*k+\"vh\";\n    }\n    break;\n  case 90:\n  case -90:\n    this.screenOrientation = 'landscape';\n \n    if (iOSapp){ // App\n      return window.screen.width*kapple;  \n      // return window.screen.height;\n      //  return window.innerHeight;\n      //  return document.documentElement.clientHeight;\n    }\n    else if (_isEPub){ // does not seems to work\n      //   return Math.max(window.screen.width,window.screen.height)*0.9;\n      return window.innerHeight*kepub;  //0.1 for app and 0.1 for nonfullscreenapp  \n      // return window.screen.height;\n      //  return window.innerHeight;\n      // return document.documentElement.clientHeight;\n    }\n   \n    else {\n      return 100*k+\"vh\";\n      }\n    break;\n  default:\n    this.screenOrientation = 'unknown';\n    //       return (iPad)?\"\"+(window.screen.width+window.screen.height)*0.4:((iPhone)?\"\"+window.screen.width:_view._format(window.innerHeight*0.9,\"0\"));\n     if (Firefox){\n      return window.innerHeight*k;// number as of 20180831 Firefox does not support vh yet so need a separate line to handle\n      }\n   //   else if (iOS&&(window.orientation==0)||(window.orientation==180)){\n   //   return  window.screen.height*k;// number as of 20180831 Firefox does not support vh yet so need a separate line to handle\n   //   }\n    //  else if (iOS&&(window.orientation==90)||(window.orientation==-90)){\n   //   return  window.screen.width*k;// number as of 20180831 Firefox does not support vh yet so need a separate line to handle\n   //   }\n      else {\n      //alert();\n      // return 100*k+\"%\"; // work on fullscreen works in EJSS6.0beta\n        //  works in EjsS_5.3_180131\n      return  window.innerHeight*k; // work on panel \n       \n}\n\n}\n \n}"
        },
        {
          "Name": "speech",
          "Active": "true",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "",
          "Code": "// copy this custom function\n// in iOS need to add speech to the play button as On iOS the API works but must be triggered by a user action callback, like a response to a tap event, to provide a better experience to users and avoid unexpected sounds out of your phone\nfunction speech (option) {\n\n\ntry { // allow code to run in Student Learning Space \nvar isCordova = (!!this.parent.cordova || !!window.cordova);\nif(isCordova) { // check it is running in Android or iOS\n       // parent.TTS.speak({text:option,locale:'zh-CN'});\n\tparent.TTS.speak({text:option,locale:'us-EN'});\n\t// parent.TTS.speak({text:option,locale:'en-US'});\n\t// parent.TTS.speak({text:option,locale:'id-ID'});\n} \n} \ncatch(e) {\n  var isCordova = false;\n  }\n  \n   var msg = new SpeechSynthesisUtterance(option);\n\n  //https://stackoverflow.com/questions/43983845/speechsynthesis-api-for-chinese-firefox\n  // Set the text.\n\t//msg.text = option; \n\t//https://forums.developer.apple.com/message/323564#323564\n\t// comment out the next 2 lines for english\n//msg.voice = speechSynthesis.getVoices().filter(function(voice) { return voice.name == 'Ting-Ting'; })[0];\n//msg.lang = 'zh-CH'; // need for android?\n//msg.lang = 'id-ID'; // need for android?\nmsg.lang = 'us-EN'; // need for android?\n\n//https://flaviocopes.com/speech-synthesis-api/\n//debug\n//console.log(`Voices #: ${speechSynthesis.getVoices().length}`)\n//speechSynthesis.getVoices().forEach(voice => {\n// console.log(voice.name, voice.lang)\n//})\n//debug\n\n// Queue this utterance.\nwindow.speechSynthesis.speak(msg);\n\n\n\n \n\n}"
        },
        {
          "Name": "onDrag",
          "Active": "true",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "Snap to rod release zone and clear stale vertical velocity while dragging.",
          "Code": "function onDragX () {\n  var tol = 2;\n  if (Math.abs(xMagnetX-releasex)<tol && Math.abs(yMagnetX-releasey)<tol){\n    xMagnetX=releasex;\n    yMagnetX=releasey;\n    vyMagnetX=0;\n    addToRod('X');\n  }\n}\n\nfunction onDragY () {\n  var tol = 2;\n  if (Math.abs(xMagnetY-releasex)<tol && Math.abs(yMagnetY-releasey)<tol){\n    xMagnetY=releasex;\n    yMagnetY=releasey;\n    vyMagnetY=0;\n    addToRod('Y');\n  }\n}\n\nfunction onDragZ () {\n  var tol = 2;\n  if (Math.abs(xMagnetZ-releasex)<tol && Math.abs(yMagnetZ-releasey)<tol){\n    xMagnetZ=releasex;\n    yMagnetZ=releasey;\n    vyMagnetZ=0;\n    addToRod('Z');\n  }\n}\n\nfunction onDragW () {\n  var tol = 2;\n  if (Math.abs(xWooden-releasex)<tol && Math.abs(yWooden-releasey)<tol){\n    xWooden=releasex;\n    yWooden=releasey;\n    vyWooden=0;\n    addToRod('W');\n  }\n}\n\nfunction onDragI () {\n  var tol = 2;\n  if (Math.abs(xIron-releasex)<tol && Math.abs(yIron-releasey)<tol){\n    xIron=releasex;\n    yIron=releasey;\n    vyIron=0;\n    addToRod('I');\n  }\n}\n"
        },
        {
          "Name": "barrier",
          "Active": "false",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "",
          "Code": "function barrier(xCoor,yCoor) {\n  if (2<xCoor<=3 && 2<yCoor<8){\n    xCoor=3;\n    }\n  if (-3<=xCoor<=-1){\n    xCoor=-3;\n    }\n   return xCoor\n}"
        },
        {
          "Name": "prelim",
          "Active": "false",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "",
          "Code": "function prelim () {\n if (flipX==true){ // set flipX to 1 or -1 depending on attract or repel\n  \n   flipXnumber =-1;\n    }\n    else {\n      flipXnumber =1;\n      }\n//var attractivepower = 300/(1+distance); // try to make an function of distance\n//var tol =3.5;\n\n\n// model gravity\nif (xMagnetX==0&&xMagnetY!=0&&yMagnetX>yBlockSize/2){ // align at the rod and ntg to influence it\n  vyMagnetX =vyMagnetX;\n   ayMagnetX= g-k*vyMagnetX; // g for downward as g =-10\n  stageX=\"1, X in rod,Y not in rod, X has not hit ground\";\n  }\n  \n  \n  // align at rod and bottom has magnet \n  else if(xMagnetX==0 && xMagnetY==0 && Math.abs(distanceXY)>1 && (yMagnetX>yBlockSize/2||yMagnetY>yBlockSize/2)) {\n  //alert();\n stageX=\"2, both X and Y in rod,X has not hit ground\";\n  attractivepowerXY = -flipXnumber*30/(1+distanceXY); // try to make an function of distance\n // attractivepowerXY = 50;\n vyMagnetX =vyMagnetX;\n   ayMagnetX= g+attractivepowerXY-k*vyMagnetX; // g for downward as g =-10\n  vyMagnetY =vyMagnetY;\n   ayMagnetY= g-attractivepowerXY-k*vyMagnetY; // g for downward as g =-10\n  \n  }\n\n\n  // repel upward like poles\n  \n// for magnet Y\nelse if (xMagnetY==0&&xMagnetX!=0&&yMagnetY>yBlockSize/2){ // align at the rod and ntg to influence it\n  vyMagnetY =vyMagnetY;\n   ayMagnetY= g-k*vyMagnetY; // g for downward as g =-10\n  stageX=\"3, Y in rod,X not in rod, Y has not hit ground\";\n  }\n  \n  // model stop\nelse if (xMagnetY==0&&xMagnetX==0&&Math.abs(distanceXY)==1&&(yMagnetX>=yBlockSize/2||yMagnetY>=yBlockSize/2) && rodList.length==2 ){\n  vyMagnetX=vyMagnetY;\n  vyMagnetY=vyMagnetX;\n  ayMagnetX= g-k*vyMagnetX; // dont move\n  ayMagnetY= g-k*vyMagnetY;\n  stageX=\"4, both X and Y in rod,X and Y meet together but either X nor Y has hit the ground\";\n  }\n\nelse if(xMagnetY==0&&xMagnetX==0&&Math.abs(distanceXY)==1&&(yMagnetX==yBlockSize/2||yMagnetY==yBlockSize/2)&& rodList.length==2){\n  if (yMagnetY<yMagnetX) {yMagnetY=yBlockSize/2;yMagnetX=yMagnetY+yBlockSize; }\n  else if (yMagnetX<yMagnetY) {yMagnetX=yBlockSize/2;yMagnetX=yMagnetY+yBlockSize; }\n  vyMagnetX=0;\n  vyMagnetY=0;\n  ayMagnetX=0;\n  ayMagnetY=0;\n  stageX=\"5, both X and Y in rod,X and Y meet together but either X or Y has hit the ground\";\n  }\n\n\n\n/*  \nelse{ // all stop at the bottom contact\n  vyMagnetX=0;\n  vyMagnetY=0;\n  vyMagnetZ=0;\n  vyWooden=0;\n  vyIron=0;\n  \n // ayMagnetX=0;\n // ayMagnetY=0;\n  stageX=200;\n  }\n*/\n\n// For magnet Z (Falling):\n/*\nelse if (xMagnetZ==0&&xMagnetY!=0&&yMagnetZ>yBlockSize/2){ // align at the rod and ntg to influence it\n  vyMagnetZ =vyMagnetZ;\n   ayMagnetZ= g-k*vyMagnetZ; // g for downward as g =-10\n  stageZ=\"7, Z in rod,x and Y not in rod, X has not hit ground\";\n  }*/\nif (xMagnetZ==releasex && yMagnetZ>yBlockSize/2 && rodList[rodList.length-1]=='Z'){\n  // Nothing in rod (Base case)\n  if (rodList.length == 1){ \n    stageZ = \"Z - Nothing in rod, Z falls freely\";\n    if (yMagnetZ>yBlockSize/2){\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g-k*vyMagnetZ;}\n    }\n  // >1 item in rod \n  if (rodList.length >= 2){ \n    // Check the last item on rodList, and its magnetism\n    //stageZ = \"Last item is \"+rodList[rodList.length-2]\n    if (rodList[rodList.length-2]=='X'){\n      if ( (flipX==false && flipZ==false)||(flipX==true && flipZ==true) ){\n        attractZ('X');}\n      else if ( (flipX==true&&flipZ==false)||(flipX==false&&flipZ==true) ){\n        repelZ('X');}\n      }\n    else if (rodList[rodList.length-2]=='Y'){\n      if ( (flipY==false && flipZ==false)||(flipY==true && flipZ==true) ){\n        attractZ('Y');}\n      else if ( (flipY==true&&flipZ==false)||(flipY==false&&flipZ==true) ){\n        repelZ('Y');}\n      }\n    else if (rodList[rodList.length-2]=='W'){\n      fallToW('Z');\n      }\n    else if (rodList[rodList.length-2]=='I'){\n      attractZ('I');}\n    }\n  }\n\n\n// For Wooden Ring(Falling):\nif (xWooden==releasex && yWooden>yBlockSize/2 && rodList[rodList.length-1]=='W'){//contains(rodList,'Z')){\n  // Nothing in rod (Base case)\n  if (rodList.length==1){\n    stageW = \"W - Nothing in rod, W falls freely\";\n    if (yWooden>yBlockSize/2){\n      //vyWooden = vyWooden;\n      ayWooden = g-k*vyWooden;}\n    }\n  else if (rodList.length>=2){\n    stageW = \"W - [length-1] item in rod\";\n    /*\n    // Falls to length position\n    if (yWooden> yBlockSize*(rodList.length-0.5)){  // falling\n      ayWooden = g-k*vyWooden;\n      }\n    else{  //reach position\n      vyWooden = 0;\n      yWooden = yBlockSize*(rodList.length-0.5)\n      }*/\n    // Falls to last item position\n    if (rodList[rodList.length-2]=='X'){\n      WfallTo('X');}\n    else if (rodList[rodList.length-2]=='Y'){\n     WfallTo('Y');}\n    else if (rodList[rodList.length-2]=='Z'){\n     WfallTo('Z');}\n    else if (rodList[rodList.length-2]=='I'){\n     WfallTo('I');}\n    }\n  }\n  \n// For Iron Ring (Falling): (TBC)\nif (xIron==releasex && yIron>yBlockSize/2 && rodList[rodList.length-1]=='I'){ //BUG in this sentence (var rodList?)\n  // Nothing in rod (Base case)\n  if (rodList.length==1){\n    stageI = \"I - Nothing in rod, I falls freely\";\n    if (yIron>yBlockSize/2){\n      ayIron = g-k*vyIron;}\n    }\n  else if (rodList.length>=2){\n    stageI = \"Iron - >1 item in rod\";\n    if (rodList[rodList.length-2]=='X'){\n      attractI('X');}\n    else if (rodList[rodList.length-2]=='Y'){\n      attractI('Y');}\n    else if (rodList[rodList.length-2]=='Z'){\n      attractI('Z');}\n    else if (rodList[rodList.length-2]=='W'){\n      fallToW('I');}\n    else{\n      vyIron=0;}\n    }\n  }\n\n\n}\n"
        },
        {
          "Name": "prelimModular",
          "Active": "false",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "",
          "Code": "function prelimModular () {\n\nvar option = _view.comboBox.getProperty(\"SelectedOptions\");\n\n\nif ( option==\"X-N\"&&xMagnetX==releasex){\n  \n    if (yMagnetX > yBlockSize/2){ // didnt collide floor yet\n      stageX = option+\" - Nothing in rod, X falls freely\";\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g-k*vyMagnetX;\n      }\n    else  if (yMagnetX <= yBlockSize/2){ // hit the floor\n      stageX = option+\" - hit floor\";\n      yMagnetX=yBlockSize/2;\n      vyMagnetX = 0;\n      ayMagnetX = 0;\n      }\n  }\n  \n else if ( option==\"X-S\"&&xMagnetX==releasex){\n  \n    if (yMagnetX > yBlockSize/2){\n      stageX = option+\" - Nothing in rod, X falls freely\";\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g-k*vyMagnetX;\n      }\n    else  if (yMagnetX <= yBlockSize/2){\n      stageX = option+\" - hit floor\";\n      yMagnetX=yBlockSize/2;\n      vyMagnetX = 0;\n      ayMagnetX = 0;\n      }\n  }\n  \n  \n  \n//duplicate for Y\nif ( option==\"Y-N\"&&xMagnetY==releasex){\n  \n    if (yMagnetY > yBlockSize/2){\n      stageY = option+\"- Nothing in rod, Y falls freely\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g-k*vyMagnetY;\n      }\n    else  if (yMagnetY <= yBlockSize/2){\n      stageY = option+\" - hit floor\";\n      yMagnetY=yBlockSize/2;\n      vyMagnetY = 0;\n      ayMagnetY = 0;\n      }\n  }\n  \n else if ( option==\"Y-S\"&&xMagnetY==releasex){\n  \n    if (yMagnetY > yBlockSize/2){\n      stageY = option+\" - Nothing in rod, Y falls freely\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g-k*vyMagnetY;\n      }\n    else  if (yMagnetY <= yBlockSize/2){\n      stageY = option+\"- hit floor\";\n      yMagnetY=yBlockSize/2;\n      vyMagnetY = 0;\n      ayMagnetY = 0;\n      }\n  }\n  \n  \n  \n  \n//start of 2 objects======================================================================\n// X on top: \n    // Attraction btwn XS+YN || XN+YS:\n    if ( option==\"XY-NN\" ||option==\"XY-SS\"){\n      // alert(\"SS\");\n       //case 5  X rest on Y at floor at time is infinity\n        if (yMagnetX <= yMagnetY+yBlockSize&&yMagnetX<=1.5*yBlockSize){\n      //alert(\"case 5\");\n        stageMaster = option+\" case 5  X rest on Y at floor time is infinity\";\n        yMagnetX=yMagnetY+yBlockSize; // not working well in prelim, must also put in fixed?\n      \n        vyMagnetX =0 //0.1; // move together with Y's\n        ayMagnetX =0 //0.1;\n        }\n        //case 6 X rest on Y stuck together moving at gravity only have not hit ground\n        if (yMagnetX == yMagnetY+yBlockSize&&yMagnetX>1.5*yBlockSize){\n    //  alert();\n        stageMaster2 = option+\" case 6  case 6 X rest on Y stuck together moving at gravity only\";\n        yMagnetX=yMagnetY+yBlockSize; // not working well in prelim, must also put in fixed?\n      yMagnetY=yMagnetX-yBlockSize;\n        vyMagnetX =vyMagnetY //0.1; // move together with Y's\n        vyMagnetY =vyMagnetX;\n        ayMagnetX =g //0.1;\n        ayMagnetY =g //0.1;\n        }\n        \n         if (yMagnetY > yBlockSize){ //calculate Y first as the position is needed to force X to be above it\n       // case 1 Y is above free fall plus magnetic force\n       stageY = option+\" case 1 Y is above free fall plus magnetic force 4- Nothing in rod, Y falls freely\";\n         vyMagnetY = vyMagnetY;\n         ayMagnetY = g-k*vyMagnetY+attractivepowerXY; //the + or - attractivepowerXY decides the up or down direction  \n         }\n      //case 2 Y hit ground\n      else  if (yMagnetY <= yBlockSize/2){\n        stageY = option+\" case 2 Y hit ground 51- hit floor\";\n   //  alert(\"hello case 2\");\n        yMagnetY=yBlockSize/2; // not working well in prelim code, must also put in fixed?\n        vyMagnetY = 0;\n        ayMagnetY = 0;\n        }\n        //case 3 X above Y free fall plus magnetic force\n      if (yMagnetX > yMagnetY+yBlockSize){\n        stageX = option+\" case 3 X above Y free fall plus magnetic force 1- Nothing in rod, X falls freely\";\n        vyMagnetX = vyMagnetX;\n        ayMagnetX = g-k*vyMagnetX-attractivepowerXY;\n        }\n        //case 4 X rest on Y\n      else  if (yMagnetX <= yMagnetY+yBlockSize){\n    //  alert();\n        stageX = option+\" case 4 X rest on Y 21- hit Y\";\n        yMagnetX=yMagnetY+yBlockSize; // not working well in prelim, must also put in fixed?\n        vyMagnetX = vyMagnetY; // move together with Y's \n        ayMagnetX = ayMagnetY;//+0.1;\n        }\n\n    }\n\n  // Repulsion magnetic force btwn XS+YS and XN+YN:-----------------------------------------------------------\n  else if ( option==\"XY-NS\"||option==\"XY-SN\"){\n    if (yMagnetY > yBlockSize){//calculate Y first as the position is needed to force X to be above it\n      stageY = option + \": Y falls freely\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g-k*vyMagnetY - attractivepowerXY; //Error for attractivepower\n      }\n    else if (yMagnetY <= yBlockSize/2){\n      stageY = option + \": Y hits floor\";\n      yMagnetY = yBlockSize/2; // Need include in both Prelim & Fixed?\n      vyMagnetY = 0;\n      ayMagnetY = 0;\n      }\n    if (yMagnetX > yMagnetY+yBlockSize){ //Reminder that X is top\n      stageX = option + \": X falls freely\";\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g-k*vyMagnetX + attractivepowerXY; // X is slightly dragged up (Error for attractive power)\n      }\n    else if (yMagnetX < yMagnetY+yBlockSize ){\n      stageX = option+\": X hits Y\";\n      yMagnetX = yMagnetY + yBlockSize; //Need include in both Prelim & Fixed? \n      vyMagnetX = vyMagnetY+0.1; // +0.1 to seperate X and Y\n      ayMagnetX = ayMagnetY;\n      }\n    else if (yMagnetX < yMagnetY+yBlockSize && yMagnetX<=1.5*yBlockSize){ //1.5 may edit\n      stageX = option + \": X floating and resting above Y\";\n      alert(\"XY Repelsion Settled Down.\");\n      yMagnetX = yMagnetY+yBlockSize; // Need include in both Prelim & Fixed?\n      vyMagnetX = 0; // move tgt\n      ayMagnetX = 0;\n      }\n  \n    }\n\n//start of 3 objects =====================================================================\n// X on top, followed by Y then Z: \n  // Attraction btwn XS with YN && YS with ZN:\n  if ( option==\"XYZ-NNN\"){\n    // Z - falling while attracted to Y above:\n    if (yMagnetZ > yBlockSize){ // calculate Z first as it is the btm item\n      stageZ = option + \": Z falls with magnetic force by Y (above)\";\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g - k*vyMagnetZ + attractivepowerYZ;\n      }\n    // Z - hits ground:\n    else if (yMagnetZ <= yBlockSize/2){\n      stageZ = option + \":Z hits ground\";\n      yMagnetZ = yBlockSize/2;\n      vyMagnetZ = 0;\n      ayMagnetZ = 0;\n      }\n    // Y - falling while attracted to X above, and Z below:\n    if (yMagnetY > yMagnetZ + yBlockSize || yMagnetY < yMagnetX - yBlockSize){\n      stageY = option+\": Y in btwn X and Z, falls with magnetism\";\n      vyMagetY = vyMagnetY;\n      ayMagnetY = g - k*vyMagnetY - attractivepowerYZ + attractivepowerXY; // Error: Y may drop when X is dragged up manually\n      }\n    // Y - hits ground, above Z:\n    else if (yMagnetY <= yMagnetZ + yBlockSize){\n      stageY = option+\": Y resting on Z while carrying X\";\n      yMagnetY = yMagnetZ + yBlockSize;\n      vyMagnetY = vyMagnetZ; // move tgt with Z\n      ayMagnetY = ayMagnetZ;\n      }\n    // X - falling while attracted to Y below:\n    if (yMagnetX > yMagnetY + yBlockSize){\n      stageX = option + \": X falls with magnetic force by Y (down)\";\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g - k*vyMagnetX - attractivepowerXY;  \n      }\n    // X - Hit floor, above Y and Z:\n    else if (yMagnetX <= yMagnetY + yBlockSize){\n      stageX = option + \": X resting on Y\";\n      yMagnetX = yMagnetY + yBlockSize;\n      vyMagnetX = vyMagnetY; // move tgt with Y\n      ayMagnetX = ayMagnetY;\n      }\n    }\n  // Attraction btwn XS and YS, Repulsion btwn YS and ZS:----------------------------------------------------\n  if (option==\"XYZ-NNS\"){ // distance btwn Y and Z shld be small but noticeable\n    // Z - falling while repelling Y above:\n    if (yMagnetZ > yBlockSize){\n      stageZ = option + \": Z falls while repelling Y above\";\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g - k*vyMagnetY - attractivepowerYZ;\n      }\n    // Z - hits ground:\n    else if (yMagnetZ <= yBlockSize/2){\n      stageZ = option + \": Z hits ground\";\n      yMagnetZ = yBlockSize/2;\n      vyMagnetZ = 0;\n      ayMagnetZ = 0;\n      }\n    // Y - falling while repelling Z below, and attracting X above:\n    if (yMagnetY > yMagnetZ + yBlockSize){\n      stageY = option + \": Y falls while repelling Z & attract X\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g-k*vyMagnetY + attractivepowerYZ/1.1;// + attractivepowerXY; // 1.1 to indicate mass\n      }\n    // Y - hits ground, above Z:\n    else if (yMagnetY <= yMagnetZ + yBlockSize){\n      stageY = \": Y hits Z, should repel while carrying X\";\n      yMagnetY = yMagnetZ + yBlockSize;\n      vyMagnetY = vyMagnetZ + 0.1; //+0.1 to seperate Y and Z\n      ayMagnetY = ayMagnetZ;\n      }\n    // Y - settles above Z after repelling: (Nope?)\n    \n    // X - falling while attracted to YN below:\n    if (yMagnetX > yMagnetY + yBlockSize){\n      stageX = option + \": X falls with magnetic force by Y (down)\";\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g - k*vyMagnetX - attractivepowerXY;\n      }\n    // X - Hit ground, above Y and Z:\n    else if (yMagnetX <= yMagnetY + yBlockSize){\n      stageX = option + \": X is resting on Y\";\n      yMagnetX = yMagnetY + yBlockSize;\n      vyMagnetX = vyMagnetY; // move tgt with Y\n      ayMagnetX = ayMagnetY;\n      }\n    }\n  // Repel XS+YS and YN+ZN:-------------------------------------------------------------------------------\n  if (option==\"XYZ-NSN\"){\n    // Z - Falls while repelling Y above:\n    if (yMagnetZ > yBlockSize){\n      stageZ = option + \": Z falls while repelling Y above\";\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g - k*vyMagnetY - attractivepowerYZ;\n      }\n    // Z - Hits ground:\n    else if (yMagnetZ <= yBlockSize/2){\n      stageZ = option + \": Z hits ground\";\n      yMagnetZ = yBlockSize/2;\n      vyMagnetZ = 0;\n      ayMagnetZ = 0;\n      }\n    // Y - Falls while repelling Z below and X above:\n    if (yMagnetY > yMagnetZ + yBlockSize){\n      stageY = option + \": Y falls while repelling Z below and X above\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g-k*vyMagnetY + (attractivepowerYZ*1.5) - attractivepowerXY; //1.5 repel against Z and negate X a little\n      }\n    else if (yMagnetY <= yMagnetZ + yBlockSize){\n      stageY = option + \": Y hits Z, shld repel\";\n      yMagnetY = yMagnetZ + yBlockSize;\n      vyMagnetY = vyMagnetZ + 0.1; // +0.1 to seperate Y and Z\n      ayMagnetY = ayMagnetZ;\n      }\n    // X - Falls while repelling Y below:\n    if (yMagnetX > yMagnetY + yBlockSize){\n      stageX = option + \": X falls while repelling Y below\";\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g-k*vyMagnetX + attractivepowerXY;\n      }\n    // X - Hits Y: \n    else if (yMagnetX <= yMagnetY + yBlockSize){\n      stageX = option + \": X hits Y, shld repel\";\n      yMagnetX = yMagnetY + yBlockSize;\n      vyMagnetX = vyMagnetY + 0.1; // +0.1 to seperate X and Y\n      ayMagnetX = ayMagnetY;\n      }\n    }\n  // Repel XS + YS, Attract YN + ZS:--------------------------------------------------------------------\n  if (option==\"XYZ-NSS\" || option==\"XYZ-SNN\"){\n    // Z - Falls while attracted to Y above:\n    if (yMagnetZ > yBlockSize){ // calculate Z first as it is the btm item\n      stageZ = option + \": Z falls with magnetic force by Y (above)\";\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g - k*vyMagnetZ + attractivepowerYZ;\n      }\n    // Z - hits ground:\n    else if (yMagnetZ <= yBlockSize/2){\n      stageZ = option + \":Z hits ground\";\n      yMagnetZ = yBlockSize/2;\n      vyMagnetZ = 0;\n      ayMagnetZ = 0;\n      }\n    // Y - Falls while attracted to Z below, repel X above:\n    if (yMagnetY > yMagnetZ + yBlockSize){\n      stageY = option + \": Y falls while attracted to Z & repel X\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g-k*vyMagnetY - attractivepowerYZ; // 1.1 to indicate mass\n      }\n    // Y - hits ground, above Z:\n    else if (yMagnetY <= yMagnetZ + yBlockSize){\n      stageY = \": Y hits Z, stays tgt\";\n      yMagnetY = yMagnetZ + yBlockSize;\n      vyMagnetY = vyMagnetZ; // move tgt with Z\n      ayMagnetY = ayMagnetZ;\n      }\n    // X - Falls while repelling Y below:\n    if (yMagnetX > yMagnetY + yBlockSize){\n      stageX = option + \": X falls while repelling Y below\";\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g-k*vyMagnetX + attractivepowerXY;\n      }\n    // X - Hits Y: \n    else if (yMagnetX <= yMagnetY + yBlockSize){\n      stageX = option + \": X hits Y, shld repel\";\n      yMagnetX = yMagnetY + yBlockSize;\n      vyMagnetX = vyMagnetY + 0.1; // +0.1 to seperate X and Y\n      ayMagnetX = ayMagnetY;\n      }\n    }\n// Falling of X, W and Y: ----------------------------------------------------------------------------------------------\n  if (option==\"XWY-N_N\"){\n    // Y - Falls to the btm:\n    if (yMagnetY > yBlockSize){\n      stageY = option + \": Y falls freely\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g - k*vyMagnetY;\n      }\n    // Y - Hits ground:\n    else if (yMagnetY <= yBlockSize/2){\n      stageY = option + \": Y hits ground\";\n      yMagnetY = yBlockSize/2;\n      vyMagnetY = 0; \n      ayMagnetY = 0;\n      }\n    // W - Falls to Y:\n    if (yWooden > yMagnetY + yBlockSize){\n      stageW = option+\": W falls to Y\";\n      vyWooden = vyWooden;\n      ayWooden = g - k*vyWooden;\n      }\n    // W - Hits Y, stays tgt:\n    else if (yWooden <= yMagnetY + yBlockSize){\n      stageW = option+\": W hits Y, stays tgt\";\n      yWooden = yMagnetY + yBlockSize;\n      vyWooden = vyMagnetY;\n      ayWooden = ayMagnetY;\n      }\n    // X - Falls to W:\n    if (yMagnetX > yWooden + yBlockSize){\n      stageX = option +\": X falls to W\";\n      vyMagnetX = vyMagnetX; \n      ayMagnetX = g - k*vyMagnetX;\n      }\n    // X - Hits W, stays tgt:\n    else if (yMagnetX <= yWooden + yBlockSize){\n      stageX = option + \":X hits W, stays tgt\";\n      yMagnetX = yWooden + yBlockSize;\n      vyMagnetX = vyWooden;\n      ayMagnetX = ayWooden;\n      }    \n    }\n// Falling of W and X, Repel XN and YN: --------------------------------------------------------------------------------\n  if (option==\"WXY-_NS\"){\n    // Y - Falls while repelling X above:\n    if (yMagnetY > yBlockSize){\n      stageY = option + \": Y falls while repelling X above\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g - k*vyMagnetY - attractivepowerXY;\n      }\n    // Y - Hits ground:\n    else if (yMagnetY <= yBlockSize/2){\n      stageY = option + \": Y hits ground\";\n      yMagnetY = yBlockSize/2;\n      vyMagnetY = 0;\n      ayMagnetY = 0;\n      }\n    // X - Falls while repelling Y below, carries W:\n    if (yMagnetX > yMagnetY + yBlockSize){\n      stageX = option + \":X falls while repelling Y below, with W\";\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g-k*vyMagnetY + attractivepowerXY/mass; // 1.1 to indicate mass\n      }\n    // X - hits Y, shld repel:\n    else if (yMagnetX <= yMagnetY + yBlockSize){\n      stageX = option + \"X hits Y, repelling while carrying W\";\n      yMagnetX = yMagnetY + yBlockSize;\n      vyMagnetX = vyMagnetY + 0.1; //+0.1 to seperate X and Y\n      ayMagnetX = ayMagnetY;\n      }\n    // W - falls freely to X:\n    if (yWooden > yMagnetX + yBlockSize){\n      stageW = option+\": W falls to X\";\n      vyWooden = vyWooden;\n      ayWooden = g - k*vyWooden;\n      }\n    // W - Hits Y, stays tgt:\n    else if (yWooden <= yMagnetX + yBlockSize){\n      stageW = option+\": W hits X, stays tgt\";\n      yWooden = yMagnetX + yBlockSize;\n      vyWooden = vyMagnetX;\n      ayWooden = ayMagnetX;\n      }\n    \n    }\n// Attraction btwn X, I and Y: --------------------------------------------------------------------------------\n  if (option==\"XIY-N_N\" || option==\"XIY-N_S\"){\n    // Y - falls while attracted to I above:\n    if (yMagnetY > yBlockSize){\n      stageY = option + \": Y falls while attracted to I above\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g - k*vyMagnetY + attractivepowerYI;\n      }\n    // Y - hits ground:\n    else if (yMagnetY <= yBlockSize/2){\n      stageY = option + \": Y hits ground\";\n      yMagnetY = yBlockSize/2;\n      vyMagnetY = 0;\n      ayMagnetY = 0;\n      }\n    // I - falls while attracted to both:\n    if (yIron > yMagnetY + yBlockSize || yIron < yMagnetX - yBlockSize){\n      stageI = option + \": I in btwn X and Y, falls with magnetism\";\n      vyIron = vyIron;\n      ayIron = g-k*vyIron - attractivepowerYI + attractivepowerXI;\n      }\n    // I - hits Y, stay attracted:\n    else if (yIron <= yMagnetY + yBlockSize){\n      stageI = option + \": I rests on Y while carrying X\";\n      yIron = yMagnetY + yBlockSize;\n      vyIron = vyMagnetY; //move tgt with Y\n      ayIron = ayMagnetY;\n      }\n    // X - falls while attracted to I below:\n    if (yMagnetX > yIron + yBlockSize){\n      stageX = option + \": X falls with I below\";\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g-k*vyMagnetX - attractivepowerXI;\n      }\n    // X - hits I, stays tgt: \n    else if (yMagnetX <= yIron + yBlockSize){\n      stageX = option + \": X rests on I\";\n      yMagnetX = yIron + yBlockSize;\n      vyMagnetX = vyIron;\n      ayMagnetX = ayIron;\n      }\n    }\n    \n//start of 4 objects =====================================================================\n  // Attraction btwn X Y , while W Z falls \n  if (option == \"XYWZ-NN_N\" || option==\"XYWZ-NN_S\"){\n    // Z - Falls to the ground:\n    if (yMagnetZ > yBlockSize){ // calculate Z first as it is the btm item\n      stageZ = option + \": Z falls with magnetic force by Y (above)\";\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g - k*vyMagnetZ;\n      }\n    // Z - Hits ground:\n    else if (yMagnetZ <= yBlockSize/2){\n      stageZ = option + \":Z hits ground\";\n      yMagnetZ = yBlockSize/2;\n      vyMagnetZ = 0;\n      ayMagnetZ = 0;\n      }\n    // W - Falls to Z:\n    if (yWooden > yMagnetZ + yBlockSize){\n      stageW = option+\": W falls to Z\";\n      vyWooden = vyWooden;\n      ayWooden = g - k*vyWooden;\n      }\n    // W - Hits Z, stays on top of Z:\n    else if (yWooden <= yMagnetZ + yBlockSize){\n      stageW = option+\": W hits Z, stays tgt\";\n      yWooden = yMagnetZ + yBlockSize;\n      vyWooden = vyMagnetZ;\n      ayWooden = ayMagnetZ;\n      }\n    // Y - Falls to W while attracting X above:\n    if (yMagnetY > yWooden + yBlockSize){\n      stageY = option + \": Y falls freely\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g - k*vyMagnetY + attractivepowerXY;\n      }\n    // Y - Hits W, stays on top of W:\n    else if (yMagnetY <= yWooden + yBlockSize){\n      stageY = option + \":Y hits W, stays tgt\";\n      yMagnetY = yWooden + yBlockSize;\n      vyMagnetY = vyWooden;\n      ayMagnetY = ayWooden;\n      }    \n    // X - Falls to Y:\n    if (yMagnetX > yMagnetY + yBlockSize){\n      stageX = option +\": X falls and attracts Y\";\n      vyMagnetX = vyMagnetX; \n      ayMagnetX = g - k*vyMagnetX - attractivepowerXY;\n      }\n    // X - Hits Y, attracted to Y:\n    else if (yMagnetX <= yMagnetY + yBlockSize){\n      stageX = option + \":X hits Y, stays tgt\";\n      yMagnetX = yMagnetY + yBlockSize;\n      vyMagnetX = vyMagnetY;\n      ayMagnetX = ayMagnetY;\n      }    \n    }\n    \n  // Repel XS+YS, while YWZ falls tgt -------------------------------------------------------------------------------\n  if (option==\"XYWZ-NS_N\"){\n    // Z - Falls to the ground:\n    if (yMagnetZ > yBlockSize){ // calculate Z first as it is the btm item\n      stageZ = option + \": Z falls with magnetic force by Y (above)\";\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g - k*vyMagnetZ;\n      }\n    // Z - Hits ground:\n    else if (yMagnetZ <= yBlockSize/2){\n      stageZ = option + \":Z hits ground\";\n      yMagnetZ = yBlockSize/2;\n      vyMagnetZ = 0;\n      ayMagnetZ = 0;\n      }\n    // W - Falls to Z:\n    if (yWooden > yMagnetZ + yBlockSize){\n      stageW = option+\": W falls to Z\";\n      vyWooden = vyWooden;\n      ayWooden = g - k*vyWooden;\n      }\n    // W - Hits Z, stays on top of Z:\n    else if (yWooden <= yMagnetZ + yBlockSize){\n      stageW = option+\": W hits Z, stays tgt\";\n      yWooden = yMagnetZ + yBlockSize;\n      vyWooden = vyMagnetZ;\n      ayWooden = ayMagnetZ;\n      }\n    // Y - Falls to W while repelling X above:\n    if (yMagnetY > yWooden + yBlockSize){\n      stageY = option + \": Y falls freely\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g - k*vyMagnetY - attractivepowerXY;\n      }\n    // Y - Hits W, stays on top of W:\n    else if (yMagnetY <= yWooden + yBlockSize){\n      stageY = option + \":Y hits W, stays tgt\";\n      yMagnetY = yWooden + yBlockSize;\n      vyMagnetY = vyWooden;\n      ayMagnetY = ayWooden;\n      }    \n    // X - Falls to Y:\n    if (yMagnetX > yMagnetY + yBlockSize){\n      stageX = option +\": X falls and attracts Y\";\n      vyMagnetX = vyMagnetX; \n      ayMagnetX = g - k*vyMagnetX + attractivepowerXY;\n      }\n    // X - Hits Y, repel Y:\n    else if (yMagnetX <= yMagnetY + yBlockSize){\n      stageX = option + \"X hits Y, repel\";\n      yMagnetX = yMagnetY + yBlockSize;\n      vyMagnetX = vyMagnetY + 0.1; //+0.1 to seperate X and Y\n      ayMagnetX = ayMagnetY;\n      }\n    }\n    \n  // Attraction btwn X Y Z and I (TBCC)---------------------------------------------------------------------------------------\n  if (option==\"XYIZ-NN_N\" || option==\"XYIZ-NN_S\"){\n    // Z - Falls to the ground:\n    // Z - Hits ground:\n    // I - Falls + attracted to Z below and Y above :\n    // I - Hits Z, stays on top of Z:\n    // Y - Falls to I while attracting I below and X above:\n    // Y - Hits I, stays on top of I:\n    // X - Falls to Y:\n    // X - Hits Y, attracted to Y:\n    }\n    \n  // Attraction btwn X I Y, repel YS+ZS (TBCC) --------------------------------------------------------------------------------------\n  if (option==\"XIYZ-N_NS\"){\n    // Z - Falls to the ground, repel YS:\n    // Z - Hits ground: \n    // Y - Falls to Z but repel Z below and attract Y above:\n    // Y - Hits Z, repel while carrying 2 other items:\n    // I - Falls to Y, attract Y below and X above:\n    // I - Hits Y, stay on top of Y:\n    // X - Falls to I:\n    // X - Hits I, stays tgt:\n    }\n\n//start of 5 objects =====================================================================\n  // Attraction btwn X Y I , W and Z fall\n  if (option==\"XYIWZ-NN__S\"){\n    // Z - Falls to the ground:\n    if (yMagnetZ > yBlockSize){ // calculate Z first as it is the btm item\n      stageZ = option + \": Z falls with magnetic force by Y (above)\";\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g - k*vyMagnetZ;\n      }\n    // Z - Hits ground:\n    else if (yMagnetZ <= yBlockSize/2){\n      stageZ = option + \":Z hits ground\";\n      yMagnetZ = yBlockSize/2;\n      vyMagnetZ = 0;\n      ayMagnetZ = 0;\n      }\n    // W - Falls to Z:\n    if (yWooden > yMagnetZ + yBlockSize){\n      stageW = option+\": W falls to Z\";\n      vyWooden = vyWooden;\n      ayWooden = g - k*vyWooden;\n      }\n    // W - Hits Z:\n    else if (yWooden <= yMagnetZ + yBlockSize){\n      stageW = option+\": W hits Z, stays tgt\";\n      yWooden = yMagnetZ + yBlockSize;\n      vyWooden = vyMagnetZ;\n      ayWooden = ayMagnetZ;\n      }\n    // I - Falls to W, attract Y above:\n    if (yIron > yWooden + yBlockSize){\n      stageI = option + \": I falls freely\";\n      vyIron = vyIron;\n      ayIron = g - k*vyIron + attractivepowerYI;\n      }\n    // I - Hits W:\n    else if (yIron <= yWooden + yBlockSize){\n      stageI = option + \":I hits W, stays tgt\";\n      yIron = yWooden + yBlockSize;\n      vyIron = vyWooden;\n      ayIron = ayWooden;\n      }    \n    // Y - Falls to I, attract I below & X above:\n    if (yMagnetY > yIron + yBlockSize){\n      stageY = option + \": Y falls freely to I\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g - k*vyMagnetY - attractivepowerYI + attractivepowerXY;\n      }\n    // Y - Hits I, stays:\n    else if (yMagnetY <= yIron + yBlockSize){\n      stageY = option + \":Y hits I, stays tgt\";\n      yMagnetY = yIron + yBlockSize;\n      vyMagnetY = vyIron;\n      ayMagnetY = ayIron;\n      }    \n    // X - Falls & attract Y:\n    if (yMagnetX > yMagnetY + yBlockSize){\n      stageX = option +\": X falls and attracts Y\";\n      vyMagnetX = vyMagnetX; \n      ayMagnetX = g - k*vyMagnetX - attractivepowerXY;\n      }\n    // X - Hits Y, stays:\n    else if (yMagnetX <= yMagnetY + yBlockSize){\n      stageX = option + \":X hits Y, stays tgt\";\n      yMagnetX = yMagnetY + yBlockSize;\n      vyMagnetX = vyMagnetY;\n      ayMagnetX = ayMagnetY;\n      }    \n    }\n  \n  // Attraction btwn X I Y, W and Z fall -------------------------------------------------------------------------------\n  if (option==\"XIYWZ-N_S_N\"){\n    // Z - Falls to the ground:\n    if (yMagnetZ > yBlockSize){ // calculate Z first as it is the btm item\n      stageZ = option + \": Z falls with magnetic force by Y (above)\";\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g - k*vyMagnetZ;\n      }\n    // Z - Hits ground:\n    else if (yMagnetZ <= yBlockSize/2){\n      stageZ = option + \":Z hits ground\";\n      yMagnetZ = yBlockSize/2;\n      vyMagnetZ = 0;\n      ayMagnetZ = 0;\n      }\n    // W - Falls to Z:\n    if (yWooden > yMagnetZ + yBlockSize){\n      stageW = option+\": W falls to Z\";\n      vyWooden = vyWooden;\n      ayWooden = g - k*vyWooden;\n      }\n    // W - Hits Z:\n    else if (yWooden <= yMagnetZ + yBlockSize){\n      stageW = option+\": W hits Z, stays tgt\";\n      yWooden = yMagnetZ + yBlockSize;\n      vyWooden = vyMagnetZ;\n      ayWooden = ayMagnetZ;\n      }\n    // Y - Falls to W, attract I above:\n    if (yMagnetY > yWooden + yBlockSize){\n      stageY = option + \": I falls freely\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g - k*vyMagnetY + attractivepowerYI;\n      }\n    // Y - Hits W, stays:\n    else if (yMagnetY <= yWooden + yBlockSize){\n      stageY = option + \":Y hits W, stays tgt\";\n      yMagnetY = yWooden + yBlockSize;\n      vyMagnetY = vyWooden;\n      ayMagnetY = ayWooden;\n      }    \n    // I - Falls to Y, attract Y below & X above:\n    if (yIron > yMagnetY + yBlockSize){\n      stageI = option + \": I falls freely to Y\";\n      vyIron = vyIron;\n      ayIron = g - k*vyIron - attractivepowerYI + attractivepowerXI;\n      }\n    // I - Hits Y, stays:\n    else if (yIron <= yMagnetY + yBlockSize){\n      stageI = option + \":I hits Y, stays tgt\";\n      yIron = yMagnetY + yBlockSize;\n      vyIron = vyMagnetY;\n      ayIron = ayMagnetY;\n      }\n    // X - Falls & attract I below:\n    if (yMagnetX > yIron + yBlockSize){\n      stageX = option +\": X falls and attracts I\";\n      vyMagnetX = vyMagnetX; \n      ayMagnetX = g - k*vyMagnetX - attractivepowerXI;\n      }\n    // X - Hits I, stays\n    else if (yMagnetX <= yIron + yBlockSize){\n      stageX = option + \":X hits I, stays tgt\";\n      yMagnetX = yIron + yBlockSize;\n      vyMagnetX = vyIron;\n      ayMagnetX = ayIron;\n      }    \n    }\n    \n  // Attract I X, repel XS+YS, falling of Y W Z ---------------------------------------------------------------------------\n  if (option==\"IXYWZ-_NS_N\"){\n    // Z - Falls to the ground:\n    if (yMagnetZ > yBlockSize){ // calculate Z first as it is the btm item\n      stageZ = option + \": Z falls with magnetic force by Y (above)\";\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g - k*vyMagnetZ;\n      }\n    // Z - Hits ground:\n    else if (yMagnetZ <= yBlockSize/2){\n      stageZ = option + \":Z hits ground\";\n      yMagnetZ = yBlockSize/2;\n      vyMagnetZ = 0;\n      ayMagnetZ = 0;\n      }\n    // W - Falls to Z:\n    if (yWooden > yMagnetZ + yBlockSize){\n      stageW = option+\": W falls to Z\";\n      vyWooden = vyWooden;\n      ayWooden = g - k*vyWooden;\n      }\n    // W - Hits Z:\n    else if (yWooden <= yMagnetZ + yBlockSize){\n      stageW = option+\": W hits Z, stays tgt\";\n      yWooden = yMagnetZ + yBlockSize;\n      vyWooden = vyMagnetZ;\n      ayWooden = ayMagnetZ;\n      }\n    // Y - Falls to W, repel X above:\n    if (yMagnetY > yWooden + yBlockSize){\n      stageY = option + \": I falls freely\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g - k*vyMagnetY - attractivepowerXY;\n      }\n    // Y - Hits W, stays:\n    else if (yMagnetY <= yWooden + yBlockSize){\n      stageY = option + \":Y hits W, stays tgt\";\n      yMagnetY = yWooden + yBlockSize;\n      vyMagnetY = vyWooden;\n      ayMagnetY = ayWooden;\n      }    \n    // X - Falls to Y, repel Y below and attract I above:\n    if (yMagnetX > yMagnetY + yBlockSize){\n      stageX = option +\": X falls, repel Y below and attracts I above\";\n      vyMagnetX = vyMagnetX; \n      ayMagnetX = g - k*vyMagnetX + attractivepowerXY/mass;// + attractivepowerXI;\n      }\n    // X - Hits Y, repel Y below while carrying I:\n    else if (yMagnetX <= yMagnetY + yBlockSize){\n      stageX = option + \"X hits Y, repel\";\n      yMagnetX = yMagnetY + yBlockSize;\n      vyMagnetX = vyMagnetY + 0.1; //+0.1 to seperate X and Y\n      ayMagnetX = ayMagnetY;\n      }\n    // I - Falls to X, attract X:\n    if (yIron > yMagnetX + yBlockSize){\n      stageI = option + \": I falls freely\";\n      vyIron = vyIron;\n      ayIron = g - k*vyIron - attractivepowerXI;\n      }\n    // I - Hits X, stays:\n    else if (yIron <= yMagnetX + yBlockSize){\n      stageI = option + \":I hits W, stays tgt\";\n      yIron = yMagnetX + yBlockSize;\n      vyIron = vyMagnetX;\n      ayIron = ayMagnetX;\n      }    \n    }\n    \n  }\n"
        },
        {
          "Name": "prelim 2",
          "Active": "true",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "Smooth forces, critical magnetic damping, and acceleration-level rigid contact support.",
          "Code": "function prelim () {\n  var onX = isPhysicsActive('X');\n  var onY = isPhysicsActive('Y');\n  var onZ = isPhysicsActive('Z');\n  var onW = isPhysicsActive('W');\n  var onI = isPhysicsActive('I');\n\n  // Smooth external forces only. Hard normal contact is solved separately.\n  // rodDrag is intentionally small; the dominant damping of a levitating\n  // repelling pair is the local critical damping in applyMagnetPair().\n  ayMagnetX = onX ? g-rodDrag*vyMagnetX : 0;\n  ayMagnetY = onY ? g-rodDrag*vyMagnetY : 0;\n  ayMagnetZ = onZ ? g-rodDrag*vyMagnetZ : 0;\n  ayWooden  = onW ? g-rodDrag*vyWooden  : 0;\n  ayIron    = onI ? g-rodDrag*vyIron    : 0;\n\n  // Pairwise magnetic superposition. Wood does not shield the field.\n  applyMagnetPair('X','Y',flipX,flipY);\n  applyMagnetPair('X','Z',flipX,flipZ);\n  applyMagnetPair('Y','Z',flipY,flipZ);\n\n  // Ferromagnetic iron is attracted by either pole.\n  applyMagnetIron('X');\n  applyMagnetIron('Y');\n  applyMagnetIron('Z');\n\n  // Acceleration-level unilateral constraints keep resting stacks together\n  // without fake overlap springs. A contact is released automatically whenever\n  // the unconstrained forces would pull the two bodies apart.\n  solveRestingContactAccelerations();\n\n  rodList = currentRodItems();\n  stageX = onX ? 'critical magnetic damping + rigid contact solver' : 'X in tray/dragged';\n  stageY = onY ? 'critical magnetic damping + rigid contact solver' : 'Y in tray/dragged';\n  stageZ = onZ ? 'critical magnetic damping + rigid contact solver' : 'Z in tray/dragged';\n  stageW = onW ? 'rigid contact payload' : 'W in tray/dragged';\n  stageI = onI ? 'ferromagnetic attraction + rigid contact' : 'I in tray/dragged';\n}"
        },
        {
          "Name": "MagnetismX",
          "Active": "false",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "Magnetism btwn recent magnet and Magnet X",
          "Code": "// Only when top magnet is X\nvar magnetTol = 2.5;\nfunction attractX(BtmMagnet){\n  // find out whether btm is x or y\n  // --------------------------------------------------------------------------------------\n  if (BtmMagnet=='Y'){\n    //distance = (yMagnetX - yMagnetY);\n    stageX = \"X is here for Y <3\";\n    // Attraction\n    if ( distanceXY>yBlockSize && distanceXY<=magnetTol && yMagnetX>=yMagnetY+yBlockSize ){\n      stageX = \"XY: Attraction\";\n      //vyMagnetX = vyMagnetY;\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g-k*vyMagnetX - attractivepowerXY;\n      //ayMagnetY = g-k*vyMagnetY;\n      if (yMagnetX<=yMagnetY+yBlockSize){// Makes sure Z is nicely placed on top\n        vyMagnetX = 0;ayMagnetX=0;\n        yMagnetX = yMagnetY + yBlockSize;}\n      }\n    //just fall till distance close up\n    else if (yMagnetX>yMagnetY+magnetTol){\n      stageX = \"XY: Falling only\";\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g-k*vyMagnetX;\n      }\n    //In contact\n    else{\n      vyMagnetX = 0;\n      ayMagnetX = 0;\n      yMagnetX = yMagnetY + yBlockSize; //\n      }\n    }\n  // --------------------------------------------------------------------------------------\n  else if (BtmMagnet=='Z'){\n    //distance = (yMagnetX - yMagnetZ);\n    stageX = \"X is here for Z <3\";\n    // Attraction\n    if ( distanceXZ>yBlockSize && distanceXZ<=magnetTol && yMagnetX>=yMagnetZ+yBlockSize ){\n      stageX = \"XZ: Attraction\";\n      //vyMagnetZ = vyMagnetX;\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g-k*vyMagnetX - attractivepowerXZ;\n      //ayMagnetY = g-k*vyMagnetY;\n      if (yMagnetX==yMagnetZ+yBlockSize){// Makes sure Z is nicely placed on top\n        vyMagnetX = 0;ayMagnetX=0;}\n      }\n    //just fall till distance close up\n    else if (yMagnetX>yMagnetZ+magnetTol){\n      stageX = \"XZ: Falling only\";\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g-k*vyMagnetX;\n      }\n    //In contact\n    else{\n      vyMagnetX = 0;\n      ayMagnetX = 0;\n      yMagnetX = yMagnetZ + yBlockSize; //\n      }\n    }\n  // --------------------------------------------------------------------------------------\n  else if (BtmMagnet=='I'){\n    //distance = (yMagnetX - yIron);\n    stageX = \"X is here for I <3\";\n    // Attraction\n    if ( distanceXI>yBlockSize && distanceXI<=magnetTol && yMagnetX>=yIron+yBlockSize ){\n      stageX = \"XI: Attraction\";\n      //vyMagnetX = vyIron;\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g-k*vyMagnetX-attractivepowerXI;\n      //ayIron = g-k*vyIron;\n      if (yMagnetX==yIron+yBlockSize){// Makes sure Z is nicely placed on top\n        vyMagnetX = 0;ayMagnetX=0;}\n      }\n    //just fall till distance close up\n    else if (yMagnetX>yIron+magnetTol){\n      stageX = \"XI: Falling only\";\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g-k*vyMagnetX;\n      }\n    //In contact\n    else{\n      stageX = \"X and I in contact\";\n      vyMagnetX = 0;\n      ayMagnetX = 0;\n      yMagnetX = yIron + yBlockSize; //\n      }\n    }\n  }\n// =========================================================================================\nfunction repelX(BtmMagnet){ // bug\n  if (BtmMagnet=='Y'){\n    //distance = (yMagnetX - yMagnetY);\n    stageX = \"X is here for Y!\";\n    if (distanceXY>yBlockSize && distanceXY<=magnetTol){\n      stageX = \"XY: Repel\";\n      ayMagnetX = g + attractivepowerXY - k*vyMagnetX - (mass*NumItemAbove(rodList,'X'));// Check for Physics\n      //ayMagnetY = g - attractivepowerXY - k*vyMagnetY;\n      //ayMagnetY = ayMagnetY - (mass*NumItemAbove(rodList,'Y'));\n      }\n    //just fall till distance close up\n    else if (yMagnetX>yMagnetY+magnetTol){\n      stageX = \"XY: Falling only\";\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g-k*vyMagnetX;\n      }\n    // If X overhits Y:\n    if (yMagnetX <= yMagnetY + yBlockSize){\n      stageX = \"XY: X hits Y\";\n      yMagnetX = yMagnetY + yBlockSize;\n      vyMagnetX = vyMagnetY + 0.1; // +0.1 to seperate X and Y\n      ayMagnetX = ayMagnetY;\n      }\n    }\n  // --------------------------------------------------------------------------------------\n  else if (BtmMagnet=='Z'){\n    //distanceXZ = (yMagnetX - yMagnetZ);\n    stageX = \"X is here for Z!\";\n    if (distanceXZ>yBlockSize && distanceXZ<=magnetTol){\n      stageX = \"XZ: Repel\";\n      //var attractivepower = 35;\n      ayMagnetX = g + attractivepowerXZ - k*vyMagnetX - (mass*NumItemAbove(rodList,'X')); //check for physics\n      //ayMagnetZ = g - attractivepowerXZ - k*vyMagnetZ; // Logic Error\n      //ayMagnetZ = ayMagnetZ - (mass*NumItemAbove(rodList,'Z'));\n      }\n    //just fall till distance close up\n    else if (yMagnetX>yMagnetZ+magnetTol){\n      stageX = \"XZ: Falling only\";\n      vyMagnetX = vyMagnetX;\n      ayMagnetX = g-k*vyMagnetX;\n      }\n    // If X overhits Z:\n    if (yMagnetX <= yMagnetZ + yBlockSize){\n      stageX = \"XZ: X hits Z\";\n      yMagnetX = yMagnetZ + yBlockSize;\n      vyMagnetX = vyMagnetZ + 0.1; // +0.1 to seperate X and Z\n      ayMagnetX = ayMagnetZ;\n      }\n    }\n  }\n\n    /* Reference:\n    repel:\nattractivepowerXY = -flipXnumber*30/(1+distanceXY); // try to make an function of distance\n // attractivepowerXY = 50;\nvyMagnetX =vyMagnetX;\nayMagnetX= g+attractivepowerXY-k*vyMagnetX; // g for downward as g =-10\nvyMagnetY =vyMagnetY;\nayMagnetY= g-attractivepowerXY-k*vyMagnetY; // g for downward as g =-10*/\n"
        },
        {
          "Name": "MagnetismY",
          "Active": "false",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "Magnetism btwn recent magnet and Magnet Y",
          "Code": "// Only when top magnet is Y\nvar magnetTol = 2.5;\nfunction attractY(BtmMagnet){\n  // find out whether btm is x or z\n  // --------------------------------------------------------------------------------------\n  if (BtmMagnet=='X'){\n    //distance = (yMagnetY - yMagnetX);\n    stageY = \"Y is here for X <3\";\n    // Attraction\n    if ( distanceXY>yBlockSize && distanceXY<=magnetTol && yMagnetY>yMagnetX+yBlockSize ){\n      stageY = \"YX: Attraction\";\n      //vyMagnetY = vyMagnetX;\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g-k*vyMagnetY-attractivepowerXY;\n      //ayMagnetX = g-k*vyMagnetX;\n      if (yMagnetY<=yMagnetX+yBlockSize){// Makes sure Y is nicely placed on top\n        stageY = \"Y: Attracts and stays tgt with X\";\n        vyMagnetY = 0;ayMagnetY=0;\n        yMagnetY = yMagnetX + yBlockSize;}\n      }\n    //just fall till distance closes up\n    else if (yMagnetY>yMagnetX+magnetTol){\n      stageY = \"YX: Falling only\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g-k*vyMagnetY;\n      }\n    //In contact\n    else{\n      vyMagnetY = 0;\n      ayMagnetY = 0;\n      yMagnetY = yMagnetX + yBlockSize;\n      }\n    }\n  // --------------------------------------------------------------------------------------\n  else if (BtmMagnet=='Z'){\n    //distance = (yMagnetY - yMagnetZ);\n    stageY = \"Y is here for Z <3\";\n    // Attraction\n    if ( distanceYZ>yBlockSize && distanceYZ<=magnetTol && yMagnetY>=yMagnetZ+yBlockSize ){\n      stageY = \"YZ: Attraction\";\n      //vyMagnetY = vyMagnetZ;\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g-k*vyMagnetY-attractivepowerYZ;\n      //ayMagnetZ = g-k*vyMagnetZ;\n      if (yMagnetY==yMagnetZ+yBlockSize){// Makes sure Z is nicely placed on top\n        vyMagnetY = 0;ayMagnetY=0;}\n      }\n    //just fall till distance close up\n    else if (yMagnetY>yMagnetZ+magnetTol){\n      stageY = \"YZ: Falling only\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g-k*vyMagnetY;\n      }\n    //In contact\n    else{\n      vyMagnetY = 0;\n      ayMagnetY = 0;\n      yMagnetY = yMagnetZ + yBlockSize; //\n      }\n    }\n  // --------------------------------------------------------------------------------------\n  else if (BtmMagnet=='I'){\n    //distance = (yMagnetY - yIron);\n    stage = \"Y is here for I <3\";\n    // Attraction\n    if ( distanceYI>yBlockSize && distanceYI<=magnetTol && yMagnetY>=yIron+yBlockSize ){\n      stageY = \"YI: Attraction\";\n      //vyMagnetY = vyIron;\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g-k*vyMagnetY-attractivepowerYI;\n      //ayIron = g-k*vyIron;\n      if (yMagnetY==yIron+yBlockSize){// Makes sure Y is nicely placed on top\n        vyMagnetY = 0;ayMagnetY=0;}\n      }\n    //just fall till distance close up\n    else if (yMagnetY>yIron+magnetTol){\n      stageY = \"YI: Falling only\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g-k*vyMagnetY;\n      }\n    //In contact\n    else{\n      stageY = \"Y and I in contact\";\n      vyMagnetY = 0;\n      ayMagnetY = 0;\n      yMagnetY = yIron + yBlockSize; //\n      }\n    }\n  }\n// ========================================================================================\nfunction repelY(BtmMagnet){\n  if (BtmMagnet=='X'){\n    //distance = (yMagnetY - yMagnetX);\n    stageY = \"Y is here for X!\";\n    if (distanceXY>yBlockSize && distanceXY<=magnetTol){\n      stageY = \"YX: Repel\";\n      //var attractivepower = 35;\n      ayMagnetY = g + attractivepowerXY - k*vyMagnetY - (mass*NumItemAbove(rodList,'Y'));\n      //ayMagnetX = g - attractivepowerXY - k*vyMagnetX;\n      //ayMagnetX = ayMagnetX - (mass*NumItemAbove(rodList,'X'));\n      }\n    //just fall till distance close up\n    else if (yMagnetY>yMagnetX+magnetTol){\n      stageY = \"YX: Falling only\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g-k*vyMagnetY;\n      }\n    // If Y overhits X:\n    if (yMagnetY <= yMagnetX + yBlockSize){\n      stageY = \"YX: Y hits X\";\n      yMagnetY = yMagnetX + yBlockSize;\n      vyMagnetY = vyMagnetX + 0.1; // +0.1 to seperate X and Y\n      ayMagnetY = ayMagnetX;\n      }\n    }\n  // --------------------------------------------------------------------------------------\n  else if (BtmMagnet=='Z'){\n    //distance = (yMagnetY - yMagnetZ);\n    stageY = \"Y is here for Z!\";\n    if (distanceYZ>yBlockSize && distanceYZ<=magnetTol){\n      stageY = \"YZ: Repel\";\n      //var attractivepower = 35;\n      ayMagnetY = g + attractivepowerYZ - k*vyMagnetY - (mass*NumItemAbove(rodList,'Y'));\n      //ayMagnetZ = g - attractivepowerYZ - k*vyMagnetZ;\n      //ayMagnetZ = ayMagnetZ - (mass*NumItemAbove(rodList,'Z'));\n      }\n    //just fall till distance close up\n    else if (yMagnetY>yMagnetZ+magnetTol){\n      stageY = \"YZ: Falling only\";\n      vyMagnetY = vyMagnetY;\n      ayMagnetY = g-k*vyMagnetY;\n      }\n    // If Y overhits Z:\n    if (yMagnetY <= yMagnetZ + yBlockSize){\n      stageY = \"YZ: Y hits Z\";\n      yMagnetY = yMagnetZ + yBlockSize;\n      vyMagnetY = vyMagnetZ + 0.1; // +0.1 to seperate Y and Z\n      ayMagnetY = ayMagnetZ;\n      }\n    }\n  }\n\n    /* Reference:\n    repel:\nattractivepowerXY = -flipXnumber*30/(1+distanceXY); // try to make an function of distance\n // attractivepowerXY = 50;\nvyMagnetX =vyMagnetX;\nayMagnetX= g+attractivepowerXY-k*vyMagnetX; // g for downward as g =-10\nvyMagnetY =vyMagnetY;\nayMagnetY= g-attractivepowerXY-k*vyMagnetY; // g for downward as g =-10*/\n"
        },
        {
          "Name": "MagnetismZ",
          "Active": "false",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "Magnetism btwn recent magnet and Magnet Z",
          "Code": "// Only when top magnet is Z\nvar magnetTol = 2.5;\nfunction attractZ(BtmMagnet){\n  // --------------------------------------------------------------------------------------\n  if (BtmMagnet=='X'){\n    //distance = (yMagnetZ - yMagnetX);\n    stageZ = \"Z is here for X <3\";\n    // Attraction\n    if ( distanceXZ>yBlockSize && distanceXZ<=magnetTol && yMagnetZ>=yMagnetX+yBlockSize ){\n      stageZ = \"ZX: Attraction\";\n      //vyMagnetZ = vyMagnetX;\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g-k*vyMagnetZ-attractivepowerXZ;\n      //ayMagnetX = g-k*vyMagnetX;\n      if (yMagnetZ==yMagnetX+yBlockSize){ // Makes sure Z is nicely placed on top\n        vyMagnetZ = 0;ayMagnetZ=0;}\n      }\n    //just fall till distance closes up\n    else if (yMagnetZ>yMagnetX+magnetTol){\n      stageZ = \"ZX: Falling only\";\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g-k*vyMagnetZ;\n      }\n    //In contact\n    else{\n      stageZ = \"Z and X in contact\";\n      vyMagnetZ = 0;\n      ayMagnetZ = 0;\n      yMagnetZ = yMagnetX + yBlockSize; //\n      }\n    }\n  // --------------------------------------------------------------------------------------\n  else if (BtmMagnet=='Y'){\n    //distance = (yMagnetZ - yMagnetY);\n    stageZ = \"Z is here for Y <3\";\n    // Attraction\n    if ( distanceYZ>yBlockSize && distanceYZ<=magnetTol && yMagnetZ>=yMagnetY+yBlockSize ){\n      stageZ = \"ZY: Attraction\";\n      //vyMagnetZ = vyMagnetY;\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g-k*vyMagnetZ-attractivepowerYZ;\n      //ayMagnetY = g-k*vyMagnetY;\n      if (yMagnetZ==yMagnetY+yBlockSize){// Makes sure Z is nicely placed on top\n        vyMagnetZ = 0;ayMagnetZ=0;}\n      }\n    //just fall till distance close up\n    else if (yMagnetZ>yMagnetY+magnetTol){\n      stageZ = \"ZY: Falling only\";\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g-k*vyMagnetZ;\n      }\n    //In contact\n    else{\n      vyMagnetZ = 0;\n      ayMagnetZ = 0;\n      yMagnetZ = yMagnetY + yBlockSize; //\n      }\n    }\n  // --------------------------------------------------------------------------------------\n  else if (BtmMagnet=='I'){\n    //distance = (yMagnetZ - yIron);\n    stageZ = \"Z is here for I <3\";\n    // Attraction\n    if ( distanceZI>yBlockSize && distanceZI<=magnetTol && yMagnetZ>=yIron+yBlockSize ){\n      stageZ = \"ZI: Attraction\";\n      //vyMagnetZ = vyMagnetX;\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g-k*vyMagnetZ-attractivepowerZI;\n      //ayMagnetY = g-k*vyMagnetY;\n      if (yMagnetZ==yIron+yBlockSize){// Makes sure Z is nicely placed on top\n        vyMagnetZ = 0;ayMagnetZ=0;}\n      }\n    //just fall till distance close up\n    else if (yMagnetZ>yIron+magnetTol){\n      stageZ = \"ZI: Falling only\";\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g-k*vyMagnetZ;\n      }\n    //In contact\n    else{\n      stageZ = \"Z and I in contact\";\n      vyMagnetZ = 0;\n      ayMagnetZ = 0;\n      yMagnetZ = yIron + yBlockSize; //\n      }\n    }\n  }\n// ========================================================================================\nfunction repelZ(BtmMagnet){\n  if (BtmMagnet=='X'){\n    //distance = (yMagnetZ - yMagnetX);\n    stageZ = \"Z is here for X!\";\n    if (distanceXZ>yBlockSize && distanceXZ<=magnetTol){\n      stageZ = \"ZX: Repel\";\n      //var attractivepower = 35;\n      ayMagnetZ = g + attractivepowerXZ - k*vyMagnetZ - (mass*NumItemAbove(rodList,'Z'));\n      //ayMagnetX = g - attractivepowerXZ - k*vyMagnetX;\n      //ayMagnetX = ayMagnetX - (mass*NumItemAbove(rodList,'X'));\n      }\n    //just fall till distance close up\n    else if (yMagnetZ>yMagnetX+magnetTol){\n      stageZ = \"ZX: Falling only\";\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g-k*vyMagnetZ;\n      }\n    // If Z overhits X:\n    if (yMagnetZ <= yMagnetX + yBlockSize){\n      stageZ = \"ZX: Z hits X\";\n      yMagnetZ = yMagnetX + yBlockSize;\n      vyMagnetZ = vyMagnetX + 0.1; // +0.1 to seperate Z and X\n      ayMagnetZ = ayMagnetX;\n      }\n    }\n  // --------------------------------------------------------------------------------------\n  else if (BtmMagnet=='Y'){\n    //distance = (yMagnetZ - yMagnetY);\n    stageZ = \"Z is here for Y!\";\n    if (distanceYZ>yBlockSize && distanceYZ<=magnetTol){\n      stageZ = \"ZY: Repel\";\n      //var attractivepower = 35;\n      ayMagnetZ = g + attractivepowerYZ - k*vyMagnetZ - (mass*NumItemAbove(rodList,'Z'));\n      //ayMagnetY = g - attractivepowerYZ - k*vyMagnetY;\n      //stageMaster = \"Num of Item Above Y = \"+NumItemAbove(rodList,'Y');\n      //ayMagnetY = ayMagnetY - (mass*NumItemAbove(rodList,'Y'));\n      }\n    //just fall till distance close up\n    else if (yMagnetZ>yMagnetY+magnetTol){\n      stageZ = \"ZY: Falling only\";\n      vyMagnetZ = vyMagnetZ;\n      ayMagnetZ = g-k*vyMagnetZ;\n      }\n    // If Z overhits Y:\n    if (yMagnetZ <= yMagnetY + yBlockSize){\n      stageZ = \"ZY: Z hits Y\";\n      yMagnetZ = yMagnetY + yBlockSize;\n      vyMagnetZ = vyMagnetY + 0.1; // +0.1 to seperate Z and Y\n      ayMagnetZ = ayMagnetY;\n      }\n    }\n  }\n\n    /* Reference:\n    repel:\nattractivepowerXY = -flipXnumber*30/(1+distanceXY); // try to make an function of distance\n // attractivepowerXY = 50;\nvyMagnetX =vyMagnetX;\nayMagnetX= g+attractivepowerXY-k*vyMagnetX; // g for downward as g =-10\nvyMagnetY =vyMagnetY;\nayMagnetY= g-attractivepowerXY-k*vyMagnetY; // g for downward as g =-10*/\n"
        },
        {
          "Name": "MagnetismI",
          "Active": "false",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "Magnetism btwn recent magnet and  I",
          "Code": "// Only when top is I\nvar magnetTol = 2.5;\nfunction attractI(BtmMagnet){\n  // --------------------------------------------------------------------------------------\n  if (BtmMagnet=='X'){\n    //distance = (yIron - yMagnetX);\n    stageI = \"I is here for X <3\";\n    // Attraction\n    if ( distanceXI>yBlockSize && distanceXI<=magnetTol && yIron>=yMagnetX+yBlockSize ){\n      stageI = \"IX: Attraction\";\n      //vyMagnetX = vyIron;\n      ayIron = g-k*vyIron-attractivepowerXI;\n      //ayMagnetX = g-k*vyIron;\n      if (yIron==yMagnetX+yBlockSize){ // Makes sure I is nicely placed on top\n        vyIron = 0;ayIron=0;}\n      }\n    //just fall till distance closes up\n    else if (yIron>yMagnetX+magnetTol){\n      stageI = \"IX: Falling only\";\n      vyIron = vyIron;\n      ayIron = g-k*vyIron;\n      }\n    //In contact\n    else{\n      stageI = \"I and X in contact\";\n      vyIron = 0;\n      ayIron = 0;\n      yIron = yMagnetX + yBlockSize; //\n      }\n    }\n  // --------------------------------------------------------------------------------------\n  else if (BtmMagnet=='Y'){\n    //distance = (yIron - yMagnetY);\n    stageI = \"I is here for Y <3\";\n    // Attraction\n    if ( distanceYI>yBlockSize && distanceYI<=magnetTol && yIron>=yMagnetY+yBlockSize ){\n      stageI = \"IY: Attraction\";\n      //vyMagnetY = vyIron;\n      ayIron = g-k*vyIron-attractivepowerYI;\n      if (yIron==yMagnetY+yBlockSize){// Makes sure I is nicely placed on top\n        vyIron = 0;ayIron=0;}\n      }\n    //just fall till distance close up\n    else if (yIron>yMagnetY+magnetTol){\n      stageI = \"IY: Falling only\";\n      vyIron = vyIron;\n      ayIron = g-k*vyIron;\n      }\n    //In contact\n    else{\n      stageI = \"I and Y in contact\";\n      vyIron = 0;\n      ayIron = 0;\n      yIron = yMagnetY + yBlockSize; //\n      }\n    }\n  // --------------------------------------------------------------------------------------\n  else if (BtmMagnet=='Z'){\n    //distance = (yIron - yMagnetZ);\n    stageI = \"I is here for Z <3\";\n    // Attraction\n    if ( distanceZI>yBlockSize && distanceZI<=magnetTol && yIron>=yMagnetZ+yBlockSize ){\n      stageI = \"IZ: Attraction\";\n      //vyMagnetZ = vyIron;\n      ayIron = g-k*vyIron-attractivepowerZI;\n      //ayMagnetZ = g-k*vyIron;\n      if (yIron==yMagnetZ+yBlockSize){// Makes sure I is nicely placed on top\n        vyIron = 0;ayIron=0;}\n      }\n    //just fall till distance close up\n    else if (yIron>yMagnetZ+magnetTol){\n      stageI = \"IZ: Falling only\";\n      vyIron = vyIron;\n      ayIron = g-k*vyIron;\n      }\n    //In contact\n    else{\n      stageI = \"I and Z in contact\";\n      vyIron = 0;\n      ayIron = 0;\n      yIron = yMagnetZ + yBlockSize; //\n      }\n    }\n  }\n\n\n"
        },
        {
          "Name": "fallTo",
          "Active": "false",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "When theres wooden ring",
          "Code": "// For wooden ring only:\nfunction WfallTo (btmItem) {\n  if (btmItem=='X'){\n    // fall till it reaches near MagnetX\n    if (yWooden > yMagnetX+yBlockSize) {\n      stageW = \"W is currently falling to X\";\n      ayWooden = g-k*vyWooden;\n      }\n    // reach near MagnetX\n    else{\n      stageW = \"W is above X\";\n      vyWooden = 0;ayWooden=0;\n      yWooden = yMagnetX+yBlockSize;\n      }\n    }\n  // ----------------------------------------------------------------------\n  else if (btmItem=='Y'){\n    // fall till it reaches near MagnetY\n    if (yWooden > yMagnetY+yBlockSize) {\n      stageW = \"W is currently falling to Y\";\n      ayWooden = g-k*vyWooden;\n      }\n    // reach near MagnetY\n    else{\n      stageW = \"W is above Y\";\n      vyWooden = 0;ayWooden=0;\n      yWooden = yMagnetY+yBlockSize;\n      }\n    }\n  // ----------------------------------------------------------------------\n  else if (btmItem=='Z'){\n    // fall till it reaches near MagnetZ\n    if (yWooden > yMagnetZ+yBlockSize) {\n      stageW = \"W is currently falling to Z\";\n      ayWooden = g-k*vyWooden;\n      }\n    // reach near MagnetZ\n    else{\n      stageW = \"W is above Z\";\n      vyWooden = 0;ayWooden=0;\n      yWooden = yMagnetZ+yBlockSize;\n      //vyWooden = vyMagnetZ;  // move tgt with Z\n      //ayWooden = ayMagnetZ;\n      }\n    }\n  // ----------------------------------------------------------------------\n  else if (btmItem=='I'){\n    // fall till it reaches near MagnetX\n    if (yWooden > yIron+yBlockSize) {\n      stageW = \"W is currently falling to I\";\n      ayWooden = g-k*vyWooden;\n      }\n    // reach near MagnetX\n    else{\n      stageW = \"W is above I\";\n      vyWooden = 0;ayWooden=0;\n      yWooden = yIron+yBlockSize;\n      }\n    }\n}\n// ========================================================================\n//For magnets and other items\nfunction fallToW(topItem){\n  if (topItem=='X'){\n    // fall till it reaches Wooden ring\n    if (yMagnetX > yWooden+yBlockSize){\n      stageX = \"X currently falling to W\";\n      ayMagnetX = g-k*vyMagnetX;\n      }\n    // reach Wooden ring\n    else{\n      stageX = \"X is above W\";\n      vyMagnetZ = 0;ayMagnetZ = 0;\n      yMagnetX = yWooden+yBlockSize;\n      }\n    }\n  // ----------------------------------------------------------------------\n  else if (topItem=='Y'){\n    // fall till it reaches Wooden ring\n    if (yMagnetY > yWooden+yBlockSize){\n      stageY = \"Y currently falling to W\";\n      ayMagnetY = g-k*vyMagnetY;\n      }\n    // reach Wooden ring\n    else{\n      stageY = \"Y is above W\";\n      vyMagnetY = 0;ayMagnetY = 0;\n      yMagnetY = yWooden+yBlockSize;\n      }\n    }\n  // ----------------------------------------------------------------------\n  else if (topItem=='Z'){\n    // fall till it reaches Wooden ring\n    if (yMagnetZ > yWooden+yBlockSize){\n      stageZ = \"Z currently falling to W\";\n      ayMagnetZ = g-k*vyMagnetZ;\n      }\n    // reach Wooden ring\n    else{\n      stageZ = \"Z is above W\";\n      vyMagnetZ = 0;ayWooden = 0;\n      yMagnetZ = yWooden+yBlockSize;\n      }\n    }\n  // ----------------------------------------------------------------------\n  else if (topItem=='I'){\n    // fall till it reaches Wooden ring\n    if (yIron > yWooden+yBlockSize){\n      stageI = \"I currently falling to W\";\n      ayIron = g-k*vyIron;\n      }\n    // reach Wooden ring\n    else{\n      stageI = \"I is above W\";\n      vyIron = 0;ayIron = 0;\n      yIron = yWooden+yBlockSize;\n      }\n    }\n  }\n"
        },
        {
          "Name": "rodList",
          "Active": "true",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "Enhanced 1-D magnetic rigid-body solver: critical pair damping, collision impulses, unilateral contact constraints, jitter suppression.",
          "Code": "// -----------------------------------------------------------------------------\n// 1-D rigid-body/contact and magnetic utility functions for the stacking model.\n//\n// Design goals:\n//   * smooth forces (gravity/magnetism/damping) are integrated by RK4;\n//   * collisions use momentum impulses, not velocity copying;\n//   * persistent contacts use unilateral normal constraints (lambda >= 0);\n//   * contact can push but never pull, so objects separate only when physics says so;\n//   * repelling magnetic gaps use local tangent stiffness to calculate c_crit;\n//   * a tiny contact slop + settling rule removes visible numerical chatter.\n// -----------------------------------------------------------------------------\n\nfunction normalizeRodList(list) {\n  var valid = {X:true, Y:true, Z:true, W:true, I:true};\n  var result = [];\n  var i, j, token, c;\n  if (typeof list === \"string\") list = [list];\n  if (!Array.isArray(list)) list = [];\n  for (i=0; i<list.length; i++) {\n    token = String(list[i]);\n    for (j=0; j<token.length; j++) {\n      c = token.charAt(j);\n      if (valid[c] && result.indexOf(c)<0) result.push(c);\n    }\n  }\n  return result;\n}\n\nfunction contains(list, item) {\n  return normalizeRodList(list).indexOf(item) >= 0;\n}\n\nfunction addToRod(item) {\n  var list = normalizeRodList(rodList);\n  if (list.indexOf(item)<0) list.push(item);\n  rodList = list;\n}\n\nfunction getItemX(item) {\n  if (item==='X') return xMagnetX;\n  if (item==='Y') return xMagnetY;\n  if (item==='Z') return xMagnetZ;\n  if (item==='W') return xWooden;\n  if (item==='I') return xIron;\n  return 9999;\n}\n\nfunction getItemY(item) {\n  if (item==='X') return yMagnetX;\n  if (item==='Y') return yMagnetY;\n  if (item==='Z') return yMagnetZ;\n  if (item==='W') return yWooden;\n  if (item==='I') return yIron;\n  return 0;\n}\n\nfunction setItemY(item, value) {\n  if (item==='X') yMagnetX=value;\n  else if (item==='Y') yMagnetY=value;\n  else if (item==='Z') yMagnetZ=value;\n  else if (item==='W') yWooden=value;\n  else if (item==='I') yIron=value;\n}\n\nfunction getItemV(item) {\n  if (item==='X') return vyMagnetX;\n  if (item==='Y') return vyMagnetY;\n  if (item==='Z') return vyMagnetZ;\n  if (item==='W') return vyWooden;\n  if (item==='I') return vyIron;\n  return 0;\n}\n\nfunction setItemV(item, value) {\n  if (item==='X') vyMagnetX=value;\n  else if (item==='Y') vyMagnetY=value;\n  else if (item==='Z') vyMagnetZ=value;\n  else if (item==='W') vyWooden=value;\n  else if (item==='I') vyIron=value;\n}\n\nfunction getItemA(item) {\n  if (item==='X') return ayMagnetX;\n  if (item==='Y') return ayMagnetY;\n  if (item==='Z') return ayMagnetZ;\n  if (item==='W') return ayWooden;\n  if (item==='I') return ayIron;\n  return 0;\n}\n\nfunction setItemA(item, value) {\n  if (item==='X') ayMagnetX=value;\n  else if (item==='Y') ayMagnetY=value;\n  else if (item==='Z') ayMagnetZ=value;\n  else if (item==='W') ayWooden=value;\n  else if (item==='I') ayIron=value;\n}\n\nfunction addItemA(item, delta) {\n  setItemA(item, getItemA(item)+delta);\n}\n\nfunction getItemMass(item) {\n  if (item==='X') return Math.max(0.01,mMagnetX);\n  if (item==='Y') return Math.max(0.01,mMagnetY);\n  if (item==='Z') return Math.max(0.01,mMagnetZ);\n  if (item==='W') return Math.max(0.01,mWooden);\n  if (item==='I') return Math.max(0.01,mIron);\n  return 1.0;\n}\n\nfunction getInvMass(item) {\n  return 1.0/getItemMass(item);\n}\n\nfunction isBeingDragged(item) {\n  if (item==='X') return xMove;\n  if (item==='Y') return yMove;\n  if (item==='Z') return zMove;\n  if (item==='W') return wMove;\n  if (item==='I') return iMove;\n  return false;\n}\n\nfunction isOnRod(item) {\n  return Math.abs(getItemX(item)-releasex) < 0.05;\n}\n\nfunction isPhysicsActive(item) {\n  return isOnRod(item) && !isBeingDragged(item);\n}\n\nfunction currentRodItems() {\n  var ids = ['X','Y','Z','W','I'];\n  var list = [];\n  var i;\n  for (i=0; i<ids.length; i++) if (isOnRod(ids[i])) list.push(ids[i]);\n  list.sort(function(a,b){ return getItemY(a)-getItemY(b); });\n  return list;\n}\n\nfunction currentPhysicsItems() {\n  var ids = ['X','Y','Z','W','I'];\n  var list = [];\n  var i;\n  for (i=0; i<ids.length; i++) if (isPhysicsActive(ids[i])) list.push(ids[i]);\n  list.sort(function(a,b){ return getItemY(a)-getItemY(b); });\n  return list;\n}\n\nfunction itemBelow(list, item) {\n  var a = normalizeRodList(list);\n  var i = a.indexOf(item);\n  if (i<=0) return '';\n  return a[i-1];\n}\n\nfunction NumItemAbove(list, item) {\n  var a = normalizeRodList(list);\n  var i = a.indexOf(item);\n  if (i<0) return 0;\n  return a.length-i-1;\n}\n\nfunction clampValue(x, lo, hi) {\n  return Math.max(lo,Math.min(hi,x));\n}\n\n// Qualitative axial dipole-like law.  The finite ring thickness imposes a\n// minimum centre spacing, so the force remains finite at solid contact.\nfunction magnetForce(distance) {\n  var d = Math.max(yBlockSize,Math.abs(distance));\n  return magnetStrength/Math.pow(d,4);\n}\n\n// Tangent stiffness |dF/dr|.  Around a levitation equilibrium this is the\n// linear spring stiffness used to construct a local critical damping value.\nfunction magnetTangentStiffness(distance) {\n  var d = Math.max(yBlockSize,Math.abs(distance));\n  return 4.0*magnetStrength/Math.pow(d,5);\n}\n\nfunction ironAttractionForce(distance) {\n  var d = Math.max(yBlockSize,Math.abs(distance));\n  return ironStrength/Math.pow(d,4);\n}\n\nfunction pairMatches(a,b,x,y) {\n  return (a===x && b===y) || (a===y && b===x);\n}\n\n// Mass of the rigidly touching island containing item, while deliberately\n// cutting the particular magnetic gap whose relative mode we are damping.\nfunction contactIslandInfo(item, cutA, cutB) {\n  var list = currentPhysicsItems();\n  var idx = list.indexOf(item);\n  var lo, hi, i, lower, upper, gap, total, floorTouch;\n  if (idx<0) return {mass:getItemMass(item), floor:false};\n  lo=idx; hi=idx;\n\n  while (lo>0) {\n    lower=list[lo-1]; upper=list[lo];\n    if (pairMatches(lower,upper,cutA,cutB)) break;\n    gap=getItemY(upper)-getItemY(lower)-yBlockSize;\n    if (gap>contactSlop) break;\n    lo--;\n  }\n  while (hi<list.length-1) {\n    lower=list[hi]; upper=list[hi+1];\n    if (pairMatches(lower,upper,cutA,cutB)) break;\n    gap=getItemY(upper)-getItemY(lower)-yBlockSize;\n    if (gap>contactSlop) break;\n    hi++;\n  }\n\n  total=0;\n  for (i=lo;i<=hi;i++) total += getItemMass(list[i]);\n  floorTouch = (getItemY(list[lo])-yBlockSize/2 <= contactSlop);\n  return {mass:Math.max(0.01,total), floor:floorTouch};\n}\n\nfunction effectiveRelativeMass(itemA,itemB) {\n  var A=contactIslandInfo(itemA,itemA,itemB);\n  var B=contactIslandInfo(itemB,itemA,itemB);\n  if (A.floor && !B.floor) return B.mass;\n  if (B.floor && !A.floor) return A.mass;\n  if (A.floor && B.floor) return Math.max(A.mass,B.mass);\n  return (A.mass*B.mass)/(A.mass+B.mass);\n}\n\nfunction applyMagnetPair(itemA, itemB, flipA, flipB) {\n  var dy, direction, distance, force, scalar, vSeparation;\n  var kt, mu, cCrit, damping, maxDamping;\n  var isRepelling;\n  if (!isPhysicsActive(itemA) || !isPhysicsActive(itemB)) return;\n\n  dy = getItemY(itemA)-getItemY(itemB);\n  if (Math.abs(dy)<1.0e-9) dy=1.0e-9;\n  direction=(dy>0)?1:-1;\n  distance=Math.abs(dy);\n  isRepelling=(flipA!==flipB);\n  force=magnetForce(distance);\n\n  if (isRepelling) {\n    // Relative coordinate r increases when the magnets separate.\n    vSeparation=direction*(getItemV(itemA)-getItemV(itemB));\n    kt=magnetTangentStiffness(distance);\n    mu=Math.max(0.001,effectiveRelativeMass(itemA,itemB));\n\n    // c_crit = 2 sqrt(k_tangent * m_eff).\n    // zeta=1 is locally critically damped about the current levitation gap.\n    cCrit=2.0*Math.sqrt(kt*mu);\n    damping=-magneticDampingRatio*cCrit*vSeparation;\n\n    // Critical damping is an effective dissipation model (rod friction,\n    // air/eddy/hysteretic losses), not an extra magnetic law.  The cap protects\n    // the fixed-step solver during unusually fast drag/drop impacts.\n    maxDamping=Math.max(1.0e-6,magneticDampingCap*force);\n    damping=clampValue(damping,-maxDamping,maxDamping);\n    scalar=force+damping;\n\n    addItemA(itemA, direction*scalar/getItemMass(itemA));\n    addItemA(itemB,-direction*scalar/getItemMass(itemB));\n  }\n  else {\n    // Unlike facing poles attract at every separation INCLUDING contact.\n    // The rigid-contact normal force balances this compression.  Keeping the\n    // attraction at contact also means a stuck pair resists being pulled apart.\n    scalar=-force;\n    addItemA(itemA, direction*scalar/getItemMass(itemA));\n    addItemA(itemB,-direction*scalar/getItemMass(itemB));\n  }\n}\n\nfunction applyMagnetIron(magnetItem) {\n  var dy, direction, distance, force;\n  if (!isPhysicsActive(magnetItem) || !isPhysicsActive('I')) return;\n  dy=getItemY(magnetItem)-getItemY('I');\n  if (Math.abs(dy)<1.0e-9) dy=1.0e-9;\n  direction=(dy>0)?1:-1;\n  distance=Math.abs(dy);\n  force=ironAttractionForce(distance);\n\n  // Attraction remains active at solid contact; normal force carries the\n  // compressive load and prevents interpenetration.\n  addItemA(magnetItem,-direction*force/getItemMass(magnetItem));\n  addItemA('I', direction*force/getItemMass('I'));\n}\n\nfunction makeActiveContacts() {\n  var list=currentPhysicsItems();\n  var contacts=[];\n  var i, lower, upper, gap, vrel;\n  if (list.length===0) return contacts;\n\n  // Floor contact.  Do not keep a body constrained if it is clearly departing.\n  if (getItemY(list[0])-yBlockSize/2 <= contactSlop && getItemV(list[0]) <= contactVelocityThreshold) {\n    contacts.push({floor:true,body:list[0],lambda:0});\n  }\n\n  for (i=1;i<list.length;i++) {\n    lower=list[i-1]; upper=list[i];\n    gap=getItemY(upper)-getItemY(lower)-yBlockSize;\n    vrel=getItemV(upper)-getItemV(lower);\n    if (gap<=contactSlop && vrel<=contactVelocityThreshold) {\n      contacts.push({floor:false,lower:lower,upper:upper,lambda:0});\n    }\n  }\n  return contacts;\n}\n\n// Projected Gauss-Seidel solve of unilateral normal forces at acceleration\n// level.  This is the key to keeping a payload on an oscillating magnet:\n// while support force is required, relative normal acceleration is constrained\n// to zero; when support would have to become tensile, lambda projects to zero\n// and the objects are free to separate.\nfunction solveRestingContactAccelerations() {\n  var contacts=makeActiveContacts();\n  var iterations=Math.max(4,Math.floor(contactIterations));\n  var iter,i,c,relA,invMass,newLambda,dLambda;\n\n  for (iter=0;iter<iterations;iter++) {\n    for (i=0;i<contacts.length;i++) {\n      c=contacts[i];\n      if (c.floor) {\n        relA=getItemA(c.body);\n        invMass=getInvMass(c.body);\n        newLambda=Math.max(0,c.lambda-relA/invMass);\n        dLambda=newLambda-c.lambda;\n        c.lambda=newLambda;\n        addItemA(c.body,dLambda*getInvMass(c.body));\n      }\n      else {\n        relA=getItemA(c.upper)-getItemA(c.lower);\n        invMass=getInvMass(c.upper)+getInvMass(c.lower);\n        newLambda=Math.max(0,c.lambda-relA/invMass);\n        dLambda=newLambda-c.lambda;\n        c.lambda=newLambda;\n        addItemA(c.upper, dLambda*getInvMass(c.upper));\n        addItemA(c.lower,-dLambda*getInvMass(c.lower));\n      }\n    }\n  }\n}\n\nfunction applyPairImpulse(lower,upper,impulse) {\n  setItemV(upper,getItemV(upper)+impulse*getInvMass(upper));\n  setItemV(lower,getItemV(lower)-impulse*getInvMass(lower));\n}\n\n// Impact impulses preserve linear momentum for ring-ring collisions.  A small\n// restitution gives a subtle real impact without creating perpetual bouncing.\nfunction solveImpactImpulses() {\n  var list=currentPhysicsItems();\n  var i,lower,upper,gap,vrel,invMass,j;\n  var e=clampValue(contactRestitution,0,0.5);\n  var impactTol=Math.max(contactSlop,0.002);\n\n  if (list.length===0) return;\n  if (getItemY(list[0])-yBlockSize/2 <= impactTol && getItemV(list[0]) < -contactVelocityThreshold) {\n    if (typeof recordLearningImpact==='function') recordLearningImpact(list[0],'BASE');\n    setItemV(list[0],-e*getItemV(list[0]));\n  }\n\n  for (i=1;i<list.length;i++) {\n    lower=list[i-1]; upper=list[i];\n    gap=getItemY(upper)-getItemY(lower)-yBlockSize;\n    vrel=getItemV(upper)-getItemV(lower);\n    if (gap<=impactTol && vrel < -contactVelocityThreshold) {\n      if (typeof recordLearningImpact==='function') recordLearningImpact(upper,lower);\n      invMass=getInvMass(lower)+getInvMass(upper);\n      j=-(1.0+e)*vrel/invMass;\n      applyPairImpulse(lower,upper,j);\n    }\n  }\n}\n\n// Remove any remaining closing velocity with perfectly inelastic constraint\n// impulses. Multiple passes are needed because an impulse at one contact alters\n// the velocity seen by neighbouring contacts in the same stack.\nfunction solveVelocityConstraints() {\n  var iterations=Math.max(4,Math.floor(contactIterations));\n  var iter,list,i,lower,upper,gap,vrel,invMass,j;\n  for (iter=0;iter<iterations;iter++) {\n    list=currentPhysicsItems();\n    if (list.length===0) return;\n\n    if (getItemY(list[0])-yBlockSize/2 <= contactSlop && getItemV(list[0])<0) {\n      setItemV(list[0],0);\n    }\n\n    for (i=1;i<list.length;i++) {\n      lower=list[i-1]; upper=list[i];\n      gap=getItemY(upper)-getItemY(lower)-yBlockSize;\n      if (gap<=contactSlop) {\n        vrel=getItemV(upper)-getItemV(lower);\n        if (vrel<0) {\n          invMass=getInvMass(lower)+getInvMass(upper);\n          j=-vrel/invMass;\n          applyPairImpulse(lower,upper,j);\n        }\n      }\n    }\n  }\n}\n\n// Nonlinear position projection corrects only actual overlap. Corrections are\n// mass weighted and iterated through the stack, rather than teleporting only\n// the upper ring as the legacy code did.\nfunction solvePositionConstraints() {\n  var iterations=Math.max(4,Math.floor(contactIterations));\n  var iter,list,i,lower,upper,gap,penetration,invL,invU,sum,moveL,moveU;\n  var floorY=yBlockSize/2;\n\n  for (iter=0;iter<iterations;iter++) {\n    list=currentPhysicsItems();\n    if (list.length===0) return;\n\n    if (getItemY(list[0])<floorY) setItemY(list[0],floorY);\n\n    for (i=1;i<list.length;i++) {\n      lower=list[i-1]; upper=list[i];\n      gap=getItemY(upper)-getItemY(lower)-yBlockSize;\n      if (gap<0) {\n        penetration=-gap;\n        invL=getInvMass(lower); invU=getInvMass(upper); sum=invL+invU;\n        moveL=penetration*invL/sum;\n        moveU=penetration*invU/sum;\n        setItemY(lower,getItemY(lower)-moveL);\n        setItemY(upper,getItemY(upper)+moveU);\n      }\n    }\n  }\n\n  // A final floor pass removes the tiny downward correction that a pair solve\n  // may have applied to the bottom object.\n  list=currentPhysicsItems();\n  if (list.length>0 && getItemY(list[0])<floorY) setItemY(list[0],floorY);\n}\n\n// Stick only contacts that are already dynamically supported. This removes the\n// sub-pixel gap/open/gap chatter responsible for a mass visibly jittering on a\n// levitating magnet. A repelling pair is NOT stuck because its relative\n// acceleration is positive when magnetic force wants to open the gap.\nfunction settleSupportedContacts() {\n  var list=currentPhysicsItems();\n  var i,lower,upper,gap,vrel,arel,invMass,j;\n  var floorY=yBlockSize/2;\n  if (list.length===0) return;\n\n  if (getItemY(list[0])-floorY <= contactSlop &&\n      Math.abs(getItemV(list[0])) <= contactVelocityThreshold &&\n      getItemA(list[0]) <= 0.05) {\n    setItemY(list[0],floorY);\n    setItemV(list[0],0);\n  }\n\n  for (i=1;i<list.length;i++) {\n    lower=list[i-1]; upper=list[i];\n    gap=getItemY(upper)-getItemY(lower)-yBlockSize;\n    vrel=getItemV(upper)-getItemV(lower);\n    arel=getItemA(upper)-getItemA(lower);\n    if (gap<=contactSlop && Math.abs(vrel)<=contactVelocityThreshold && arel<=0.05) {\n      // Remove the remaining relative velocity with a momentum-conserving impulse.\n      invMass=getInvMass(lower)+getInvMass(upper);\n      j=-vrel/invMass;\n      applyPairImpulse(lower,upper,j);\n      // Snap only within the very small persistence tolerance.\n      setItemY(upper,getItemY(lower)+yBlockSize);\n    }\n  }\n}\n\n// Called from Fixed Relations after each RK4 substep.\nfunction enforceRodContacts() {\n  solveImpactImpulses();\n  solveVelocityConstraints();\n  solvePositionConstraints();\n  settleSupportedContacts();\n  rodList=currentRodItems();\n}\n"
        },
        {
          "Name": "onDragbarrierX",
          "Active": "true",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "",
          "Code": "\nfunction onDragbarrierX () {\nif (xMagnetX>=1.5){// plottingpanel right boundary \n  xMagnetX=1.5\n  }\n  else if (xMagnetX<=-16){// plottingpanel left boundary \n    xMagnetX=-16\n    }\n\nif (yMagnetX >= 12){// plottingpanel top boundary \n  yMagnetX = 12\n  }\n  else if (yMagnetX <= 2){ // plottingpanel bottom boundary \n    yMagnetX = 2\n    }\n\n\n}\n"
        },
        {
          "Name": "onDragbarrierY",
          "Active": "true",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "",
          "Code": "\nfunction onDragbarrierY () {\nif (xMagnetY>=1.5){\n  xMagnetY=1.5\n  }\n  else if (xMagnetY<=-16){\n    xMagnetY=-16\n    }\n\nif (yMagnetY >= 12){\n  yMagnetY = 12\n  }\n  else if (yMagnetY <= 2){\n    yMagnetY = 2\n    }\n\n}\n"
        },
        {
          "Name": "onDragbarrierZ",
          "Active": "true",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "",
          "Code": "\nfunction onDragbarrierZ () {\nif (xMagnetZ>=1.5){\n  xMagnetZ=1.5\n  }\n  else if (xMagnetZ<=-16){\n    xMagnetZ=-16\n    }\n\nif (yMagnetZ >= 12){\n  yMagnetZ = 12\n  }\n  else if (yMagnetZ <= 2){\n    yMagnetZ = 2\n    }\n\n\n}\n"
        },
        {
          "Name": "learningGuidance",
          "Active": "true",
          "Internal": "false",
          "Type": "LIBRARY_EDITOR",
          "Comment": "Dynamic learner-facing productive-noticing messages.",
          "Code": "// -----------------------------------------------------------------------------\n// Dynamic productive-noticing guidance for the stacking-ring model.\n// The messages describe what the learner can presently see and connect it to\n// the intended learning outcomes without changing the dynamics.\n// -----------------------------------------------------------------------------\n\nfunction learningItemLabel(item) {\n  if (item==='X') return 'Magnet X';\n  if (item==='Y') return 'Magnet Y';\n  if (item==='Z') return 'Magnet Z';\n  if (item==='W') return 'wooden ring';\n  if (item==='I') return 'iron ring';\n  if (item==='BASE') return 'base';\n  return item;\n}\n\nfunction isLearningMagnet(item) {\n  return item==='X' || item==='Y' || item==='Z';\n}\n\nfunction learningFlip(item) {\n  if (item==='X') return flipX;\n  if (item==='Y') return flipY;\n  if (item==='Z') return flipZ;\n  return false;\n}\n\nfunction learningSetHint(mode,title,body) {\n  learningHintMode=mode;\n  learningHintHtml='<div style=\"font-size:2.0vh;line-height:1.35;padding:2px 4px;\">'\n    +'<b>'+title+'</b> &nbsp; '+body+'</div>';\n}\n\nfunction recordLearningImpact(a,b) {\n  var A=learningItemLabel(a), B=learningItemLabel(b);\n  impactHintText='<b>Collision / contact:</b> '+A+' meets '+B+'. '\n    +'A short contact force changes the motion and stops the solid objects from passing through each other.';\n  impactHintUntil=t+hintHoldSeconds;\n}\n\nfunction learningTouching(a,b) {\n  if (!isPhysicsActive(a) || !isPhysicsActive(b)) return false;\n  return Math.abs(Math.abs(getItemY(a)-getItemY(b))-yBlockSize) <= Math.max(contactSlop*2,0.012);\n}\n\nfunction learningHasTouchingNeighbour(item) {\n  var list=currentPhysicsItems(), i=list.indexOf(item), gap;\n  if (i<0) return false;\n  if (i===0 && getItemY(item)-yBlockSize/2 <= Math.max(contactSlop*2,0.012)) return true;\n  if (i>0) {\n    gap=getItemY(item)-getItemY(list[i-1])-yBlockSize;\n    if (gap<=Math.max(contactSlop*2,0.012)) return true;\n  }\n  if (i<list.length-1) {\n    gap=getItemY(list[i+1])-getItemY(item)-yBlockSize;\n    if (gap<=Math.max(contactSlop*2,0.012)) return true;\n  }\n  return false;\n}\n\nfunction learningPayloadAbove(item) {\n  var list=currentPhysicsItems(), i=list.indexOf(item), j, lower, upper, gap, payload=[];\n  if (i<0) return payload;\n  for (j=i+1;j<list.length;j++) {\n    lower=list[j-1]; upper=list[j];\n    gap=getItemY(upper)-getItemY(lower)-yBlockSize;\n    if (gap>Math.max(contactSlop*2,0.012)) break;\n    payload.push(upper);\n  }\n  return payload;\n}\n\nfunction learningStrongestMagnetPair() {\n  var mags=['X','Y','Z'], best=null, i,j,a,b,d,f,relv,rela;\n  for (i=0;i<mags.length;i++) for (j=i+1;j<mags.length;j++) {\n    a=mags[i]; b=mags[j];\n    if (!isPhysicsActive(a) || !isPhysicsActive(b)) continue;\n    d=Math.abs(getItemY(a)-getItemY(b));\n    f=magnetForce(d);\n    // Require a visibly meaningful interaction. The force threshold is low\n    // enough to cue noticing before the motion becomes dramatic.\n    if (f<0.18) continue;\n    relv=getItemV(a)-getItemV(b);\n    rela=getItemA(a)-getItemA(b);\n    if (!best || f>best.force) best={a:a,b:b,d:d,force:f,relv:relv,rela:rela,repel:(learningFlip(a)!==learningFlip(b))};\n  }\n  return best;\n}\n\nfunction learningClosestMagnetToIron() {\n  var mags=['X','Y','Z'], best=null, i,m,d,f;\n  if (!isPhysicsActive('I')) return null;\n  for (i=0;i<mags.length;i++) {\n    m=mags[i];\n    if (!isPhysicsActive(m)) continue;\n    d=Math.abs(getItemY(m)-yIron);\n    f=ironAttractionForce(d);\n    if (!best || f>best.force) best={mag:m,d:d,force:f};\n  }\n  return best;\n}\n\nfunction learningWoodBetweenMagnets() {\n  var mags=['X','Y','Z'], below=null, above=null, i,m;\n  if (!isPhysicsActive('W')) return null;\n  for (i=0;i<mags.length;i++) {\n    m=mags[i];\n    if (!isPhysicsActive(m)) continue;\n    if (getItemY(m)<yWooden && (!below || getItemY(m)>getItemY(below))) below=m;\n    if (getItemY(m)>yWooden && (!above || getItemY(m)<getItemY(above))) above=m;\n  }\n  if (below && above) return {below:below,above:above};\n  return null;\n}\n\nfunction learningDirectSupportOf(item) {\n  var list=currentPhysicsItems(), i=list.indexOf(item), lower, gap;\n  if (i<0) return '';\n  if (i===0) {\n    if (getItemY(item)-yBlockSize/2 <= Math.max(contactSlop*2,0.012)) return 'BASE';\n    return '';\n  }\n  lower=list[i-1];\n  gap=getItemY(item)-getItemY(lower)-yBlockSize;\n  if (gap<=Math.max(contactSlop*2,0.012)) return lower;\n  return '';\n}\n\nfunction updateLearningGuidance() {\n  var list, impactActive, ironInfo, woodBridge, pair, support, payload;\n  var i,item,a,freeCandidate=null, score, vrel, relA, gap;\n  var freeTol=0.45; // m/s^2: with rodDrag=0, isolated objects satisfy this closely.\n\n  if (!showLearningHints) return;\n\n  // Keep fast impact events readable for almost a second.\n  impactActive=(impactHintText!=='' && t<=impactHintUntil);\n  if (impactActive) {\n    learningHintMode='impact';\n    learningHintHtml='<div style=\"font-size:2.0vh;line-height:1.35;padding:2px 4px;\">'+impactHintText+'</div>';\n    return;\n  }\n\n  list=currentPhysicsItems();\n  if (list.length===0) {\n    learningSetHint('ready','What to notice:',\n      'Drag an object to <i>release here</i>. Ask: is its motion caused by gravity, a magnetic push/pull, or contact with another object?');\n    return;\n  }\n\n  // If a repelling magnet is carrying a touching payload, make that coupled\n  // motion the highest-priority explanation. This directly addresses the\n  // common observation that the load should travel with the oscillating magnet.\n  pair=learningStrongestMagnetPair();\n  if (pair && pair.repel) {\n    gap=pair.d-yBlockSize;\n    vrel=Math.abs(pair.relv);\n    relA=Math.abs(pair.rela);\n    payload=learningPayloadAbove((getItemY(pair.a)>getItemY(pair.b))?pair.a:pair.b);\n    if (payload.length>0 && vrel>=0.07) {\n      learningSetHint('repel-oscillation','Like poles repel \u2014 the magnet-and-load are oscillating.',\n        'Magnetic repulsion and gravity are competing. The load stays in contact with the magnet and moves with it; damping removes the up-down motion so the system settles toward equilibrium.');\n      return;\n    }\n    if (payload.length>0 && gap>0.02 && vrel<0.07 && relA<0.45) {\n      learningSetHint('repel-equilibrium','Like poles repel \u2014 magnetic push balances the magnet and its load.',\n        'The repelling magnets keep a gap between them. The upward magnetic push balances gravity on the upper magnet and the object resting on it, so the stack settles without the load repeatedly losing contact.');\n      return;\n    }\n  }\n\n  // Iron learning outcome: whichever pole is presented, iron is attracted.\n  ironInfo=learningClosestMagnetToIron();\n  if (ironInfo && ironInfo.force>=0.22) {\n    support=learningDirectSupportOf('I');\n    if (support===ironInfo.mag || learningTouching('I',ironInfo.mag)) {\n      learningSetHint('iron-contact','Iron is magnetic \u2014 it is attracted to a magnet.',\n        'The iron ring is touching '+learningItemLabel(ironInfo.mag)+'. Magnetic attraction pulls them together; the contact force prevents overlap. The attraction does not depend on which pole faces the iron.');\n    }\n    else {\n      learningSetHint('iron-attraction','Iron is magnetic \u2014 magnetic pull.',\n        learningItemLabel(ironInfo.mag)+' attracts the iron ring. Iron is attracted to a magnet whichever pole is facing it.');\n    }\n    return;\n  }\n\n  // Wood learning outcome. Wood can be between magnets without becoming magnetic.\n  woodBridge=learningWoodBetweenMagnets();\n  if (woodBridge) {\n    learningSetHint('wood-between','Wood is not a magnetic material.',\n      'The wooden ring is not pulled by either magnet. The magnets can still interact across the wood; the wood itself is supported only by gravity/contact forces.');\n    return;\n  }\n\n  support=learningDirectSupportOf('W');\n  if (support && support!=='BASE') {\n    if (isLearningMagnet(support)) {\n      learningSetHint('wood-supported','Wood is not magnetic.',\n        'The wooden ring is resting on '+learningItemLabel(support)+' because of the upward contact/support force \u2014 not because the magnet attracts the wood.');\n    }\n    else {\n      learningSetHint('wood-supported','Contact supports the wooden ring.',\n        'The wooden ring is not magnetic. It stays here because the object below pushes up on it.');\n    }\n    return;\n  }\n\n  // Magnet-magnet interaction gives the most direct evidence for push/pull.\n  pair=learningStrongestMagnetPair();\n  if (pair) {\n    gap=pair.d-yBlockSize;\n    vrel=Math.abs(pair.relv);\n    relA=Math.abs(pair.rela);\n    if (pair.repel) {\n      if (gap>0.02 && vrel<0.07 && relA<0.45) {\n        learningSetHint('repel-equilibrium','Like poles repel \u2014 magnetic push balances gravity.',\n          learningItemLabel(pair.a)+' and '+learningItemLabel(pair.b)+' have like poles facing. Repulsion keeps a gap between them because the magnetic push balances the gravitational load.');\n      }\n      else if (gap<=0.02) {\n        learningSetHint('repel-contact','Like poles repel \u2014 magnetic push.',\n          learningItemLabel(pair.a)+' and '+learningItemLabel(pair.b)+' have like poles facing. Even while they are very close, the magnetic force pushes them apart.');\n      }\n      else {\n        learningSetHint('repel','Like poles repel \u2014 magnetic push.',\n          learningItemLabel(pair.a)+' and '+learningItemLabel(pair.b)+' have like poles facing, so each magnet pushes the other away. Gravity may oppose this upward/downward motion.');\n      }\n    }\n    else {\n      if (gap<=0.02) {\n        learningSetHint('attract-contact','Unlike poles attract \u2014 magnetic pull.',\n          learningItemLabel(pair.a)+' and '+learningItemLabel(pair.b)+' have unlike poles facing. They pull together; solid contact prevents them from passing through each other.');\n      }\n      else {\n        learningSetHint('attract','Unlike poles attract \u2014 magnetic pull.',\n          learningItemLabel(pair.a)+' and '+learningItemLabel(pair.b)+' have unlike poles facing, so each magnet pulls the other toward it.');\n      }\n    }\n    return;\n  }\n\n  // Free fall: no support and measured acceleration essentially equals g.\n  // Choose the fastest clear example if several objects are falling.\n  for (i=0;i<list.length;i++) {\n    item=list[i];\n    if (learningHasTouchingNeighbour(item)) continue;\n    a=getItemA(item);\n    if (getItemV(item)<-0.08 && Math.abs(a-g)<=freeTol) {\n      score=Math.abs(getItemV(item));\n      if (!freeCandidate || score>freeCandidate.score) freeCandidate={item:item,score:score};\n    }\n  }\n  if (freeCandidate) {\n    item=freeCandidate.item;\n    if (item==='W') {\n      learningSetHint('freefall-wood','Free fall under gravity.',\n        'The wooden ring is falling because gravity pulls it downward. Wood is not magnetic, so there is no magnetic pull on it.');\n    }\n    else if (isLearningMagnet(item)) {\n      learningSetHint('freefall-magnet','Free fall under gravity.',\n        learningItemLabel(item)+' is falling with acceleration approximately <i>g</i>. At this moment no magnetic interaction is strong enough to noticeably change its fall.');\n    }\n    else {\n      learningSetHint('freefall','Falling under gravity.',\n        learningItemLabel(item)+' is moving downward because of gravity.');\n    }\n    return;\n  }\n\n  // Generic support/contact: useful when a payload moves with the object below.\n  for (i=list.length-1;i>=0;i--) {\n    item=list[i]; support=learningDirectSupportOf(item);\n    if (support && support!=='BASE') {\n      learningSetHint('supported','Contact force keeps the objects together.',\n        learningItemLabel(item)+' is supported by '+learningItemLabel(support)+'. The lower object pushes upward on it, so touching objects can move together instead of repeatedly separating and colliding.');\n      return;\n    }\n  }\n\n  learningSetHint('observe','Watch the forces change the motion.',\n    'Compare what you see with the learning outcomes: magnets can push or pull; wood is not magnetic; iron is attracted to a magnet.');\n}\n\n\n// -----------------------------------------------------------------------------\n// Object-focus guidance (mouse-over / pointer-over).\n// This complements, rather than replaces, the general yellow observation hint.\n// Each message answers two learner questions:\n//   1. What should I notice about THIS object right now?\n//   2. Which force/interaction explains what I see?\n// -----------------------------------------------------------------------------\n\nfunction setHoveredLearningItem(item) {\n  hoveredLearningItem=item;\n  updateHoveredObjectGuidance();\n}\n\nfunction clearHoveredLearningItem(item) {\n  // Only clear the focus if the pointer is leaving the object that currently\n  // owns the focus. This prevents flicker when moving between overlapping items.\n  if (hoveredLearningItem===item) {\n    hoveredLearningItem='';\n    hoverHintHtml='';\n  }\n}\n\nfunction hoverSetHint(item,title,observe,physics) {\n  hoverHintHtml='<div style=\"font-size:1.9vh;line-height:1.35;padding:2px 4px;\">'\n    +'<b>Object focus \u2014 '+learningItemLabel(item)+': '+title+'</b><br>'\n    +'<b>Observe:</b> '+observe+'<br>'\n    +'<b>Physics:</b> '+physics+'</div>';\n}\n\nfunction hoverNearestMagnet(item) {\n  var mags=['X','Y','Z'], best=null, i,m,d,f;\n  for (i=0;i<mags.length;i++) {\n    m=mags[i];\n    if (m===item || !isPhysicsActive(m)) continue;\n    d=Math.abs(getItemY(item)-getItemY(m));\n    f=magnetForce(d);\n    if (!best || f>best.force) best={item:m,d:d,force:f,repel:(isLearningMagnet(item) ? (learningFlip(item)!==learningFlip(m)) : false)};\n  }\n  return best;\n}\n\nfunction hoverNearestMagnetForIron() {\n  var mags=['X','Y','Z'], best=null, i,m,d,f;\n  for (i=0;i<mags.length;i++) {\n    m=mags[i];\n    if (!isPhysicsActive(m)) continue;\n    d=Math.abs(yIron-getItemY(m));\n    f=ironAttractionForce(d);\n    if (!best || f>best.force) best={item:m,d:d,force:f};\n  }\n  return best;\n}\n\nfunction hoverDirectObjectAbove(item) {\n  var list=currentPhysicsItems(), i=list.indexOf(item), upper, gap;\n  if (i<0 || i>=list.length-1) return '';\n  upper=list[i+1];\n  gap=getItemY(upper)-getItemY(item)-yBlockSize;\n  if (gap<=Math.max(contactSlop*2,0.012)) return upper;\n  return '';\n}\n\nfunction hoverIsFreeFall(item) {\n  if (!isPhysicsActive(item) || learningHasTouchingNeighbour(item)) return false;\n  return Math.abs(getItemA(item)-g)<0.50 && getItemV(item)<-0.05;\n}\n\nfunction hoverMotionDescription(item) {\n  var v=getItemV(item), a=getItemA(item);\n  if (Math.abs(v)>0.16) return (v>0 ? 'moving upward' : 'moving downward');\n  if (Math.abs(a)>0.55) return (a>0 ? 'accelerating upward' : 'accelerating downward');\n  return 'almost stationary';\n}\n\nfunction updateHoveredMagnetGuidance(item) {\n  var partner, support, above, payload, gap, relv, rela, upper, forceDirection;\n  var name=learningItemLabel(item);\n\n  if (!isOnRod(item)) {\n    hoverSetHint(item,'a magnet can push or pull.',\n      'Move it to the release area and compare what happens when its orientation is changed.',\n      'Magnets interact without touching. Unlike facing poles attract; like facing poles repel.');\n    return;\n  }\n\n  if (isBeingDragged(item)) {\n    hoverSetHint(item,'you are positioning the magnet.',\n      'Notice that its motion now follows your pointer rather than the forces in the model.',\n      'After release, gravity, magnetic forces and contact forces determine its motion.');\n    return;\n  }\n\n  partner=hoverNearestMagnet(item);\n  support=learningDirectSupportOf(item);\n  above=hoverDirectObjectAbove(item);\n  payload=learningPayloadAbove(item);\n\n  // Prioritise a meaningful magnet-magnet interaction because this maps most\n  // directly onto the stated learning outcome.\n  if (partner && partner.force>=0.18) {\n    gap=partner.d-yBlockSize;\n    relv=Math.abs(getItemV(item)-getItemV(partner.item));\n    rela=Math.abs(getItemA(item)-getItemA(partner.item));\n    upper=(getItemY(item)>getItemY(partner.item));\n\n    if (partner.repel) {\n      forceDirection=upper ? 'upward, away from '+learningItemLabel(partner.item) : 'downward, away from '+learningItemLabel(partner.item);\n      if (gap>0.02 && relv<0.07 && rela<0.45) {\n        hoverSetHint(item,'like poles repel \u2014 near equilibrium.',\n          name+' is '+hoverMotionDescription(item)+' with a visible gap to '+learningItemLabel(partner.item)+'.'+(payload.length ? ' It is also carrying '+payload.map(learningItemLabel).join(' and ')+'.' : ''),\n          'The facing poles are alike, so the magnetic push acts '+forceDirection+'. At equilibrium this push balances the gravitational load on this part of the stack.');\n      }\n      else if (relv>=0.07 || Math.abs(getItemV(item))>=0.12) {\n        hoverSetHint(item,'like poles repel \u2014 magnetic push is changing its motion.',\n          name+' is '+hoverMotionDescription(item)+'. Watch the gap to '+learningItemLabel(partner.item)+' change as the system settles.',\n          'The facing poles are alike, so the magnets push apart. Gravity competes with that magnetic push; critical damping removes the repeated up-down oscillation.');\n      }\n      else {\n        hoverSetHint(item,'like poles repel \u2014 magnetic push.',\n          'Look at the separation between '+name+' and '+learningItemLabel(partner.item)+'. They do not need to touch to interact.',\n          'The facing poles are alike, so the magnetic force pushes '+name+' '+forceDirection+'.');\n      }\n      return;\n    }\n    else {\n      if (gap<=0.02) {\n        hoverSetHint(item,'unlike poles attract \u2014 now in contact.',\n          name+' is touching '+learningItemLabel(partner.item)+'.',\n          'The unlike facing poles pull the magnets together. A contact force stops the solid rings from overlapping.');\n      }\n      else {\n        hoverSetHint(item,'unlike poles attract \u2014 magnetic pull.',\n          'Watch '+name+' move toward '+learningItemLabel(partner.item)+' even before they touch.',\n          'The facing poles are unlike, so the magnets pull toward each other.');\n      }\n      return;\n    }\n  }\n\n  // Iron can be the most important nearby magnetic interaction even when there\n  // is no second magnet close enough to dominate.\n  if (isPhysicsActive('I')) {\n    gap=Math.abs(getItemY(item)-yIron);\n    if (ironAttractionForce(gap)>=0.22) {\n      hoverSetHint(item,'this magnet attracts iron.',\n        'Notice the iron ring being pulled toward '+name+(learningTouching(item,'I') ? ' and remaining in contact with it.' : ' as the separation decreases.'),\n        'Iron is a magnetic material. It is attracted to a magnet regardless of whether the north-seeking or south-seeking pole faces the iron.');\n      return;\n    }\n  }\n\n  if (hoverIsFreeFall(item)) {\n    hoverSetHint(item,'free fall under gravity.',\n      name+' is moving downward and is not presently supported by another object.',\n      'With no strong nearby magnetic interaction, gravity is the dominant force and the acceleration is approximately g.');\n    return;\n  }\n\n  if (support) {\n    if (support==='BASE') {\n      hoverSetHint(item,'resting on the base.',\n        name+' is almost stationary at the bottom of the rod.',\n        'Gravity pulls downward and the base provides an upward contact force. The forces balance when the magnet is at rest.');\n    }\n    else {\n      hoverSetHint(item,'supported by '+learningItemLabel(support)+'.',\n        name+' is touching the object below and can move together with it while contact is maintained.',\n        'The lower object supplies an upward contact force. Contact can push, but it cannot pull; separation occurs only if the support can no longer maintain contact.');\n    }\n    return;\n  }\n\n  if (above) {\n    hoverSetHint(item,'supporting '+learningItemLabel(above)+'.',\n      learningItemLabel(above)+' is resting on '+name+' and follows its motion while contact is maintained.',\n      name+' experiences the downward load transmitted through the contact force in addition to its own weight.');\n    return;\n  }\n\n  hoverSetHint(item,'watch how its motion responds to forces.',\n    name+' is '+hoverMotionDescription(item)+'. Compare its motion with nearby magnets and objects.',\n    'A magnet may experience gravity, magnetic push/pull and contact forces at the same time.');\n}\n\nfunction updateHoveredWoodGuidance() {\n  var support, bridge, v;\n  if (!isOnRod('W')) {\n    hoverSetHint('W','wood is not a magnetic material.',\n      'Move the wooden ring near the magnets and compare it with the iron ring.',\n      'A magnet does not attract the wooden ring. Any support from a magnet is an ordinary contact force, not magnetic attraction.');\n    return;\n  }\n  if (isBeingDragged('W')) {\n    hoverSetHint('W','you are positioning the wooden ring.',\n      'Place it near or on a magnet and observe whether the magnet pulls it.',\n      'Wood is non-magnetic in this model, so after release its motion comes from gravity and contact, not a magnetic force.');\n    return;\n  }\n  bridge=learningWoodBetweenMagnets();\n  if (bridge) {\n    hoverSetHint('W','wood remains non-magnetic between magnets.',\n      'The wooden ring can sit between '+learningItemLabel(bridge.below)+' and '+learningItemLabel(bridge.above)+' without being magnetically attracted.',\n      'The magnets may still interact with each other across the wood. The wood itself experiences gravity and contact forces, not magnetic attraction.');\n    return;\n  }\n  support=learningDirectSupportOf('W');\n  if (support && support!=='BASE') {\n    hoverSetHint('W','supported by contact, not magnetism.',\n      'The wooden ring is resting on '+learningItemLabel(support)+' and moves with it while they remain in contact.',\n      'The object below pushes upward on the wood. Even when that object is a magnet, the wood is not magnetically attracted.');\n    return;\n  }\n  if (support==='BASE') {\n    hoverSetHint('W','resting on the base.',\n      'The wooden ring is stationary at the bottom of the rod.',\n      'Gravity pulls downward and the base pushes upward. Wood is still non-magnetic.');\n    return;\n  }\n  if (hoverIsFreeFall('W')) {\n    hoverSetHint('W','falling under gravity.',\n      'The wooden ring is moving downward through the air.',\n      'Wood is not magnetic, so no magnetic force is pulling it toward a magnet. Gravity is the dominant force until contact occurs.');\n    return;\n  }\n  v=hoverMotionDescription('W');\n  hoverSetHint('W','wood is non-magnetic.',\n    'The wooden ring is '+v+'. Look for a supporting contact if its motion changes.',\n    'Its motion is explained by gravity and contact forces, not attraction to a magnet.');\n}\n\nfunction updateHoveredIronGuidance() {\n  var near, support;\n  if (!isOnRod('I')) {\n    hoverSetHint('I','iron is a magnetic material.',\n      'Move the iron ring near either pole of a magnet and compare it with the wooden ring.',\n      'Iron is attracted to a magnet whichever pole faces it.');\n    return;\n  }\n  if (isBeingDragged('I')) {\n    hoverSetHint('I','you are positioning the iron ring.',\n      'Place it near either end of a magnet and release it.',\n      'Iron is magnetic: both the north-seeking and south-seeking poles attract it.');\n    return;\n  }\n  near=hoverNearestMagnetForIron();\n  if (near && near.force>=0.22) {\n    if (learningTouching('I',near.item)) {\n      hoverSetHint('I','attracted to '+learningItemLabel(near.item)+' and in contact.',\n        'The iron ring is touching the magnet and tends to remain pulled toward it.',\n        'Magnetic attraction pulls the iron and magnet together. Contact prevents the solid objects from overlapping; the attraction does not depend on which pole faces the iron.');\n    }\n    else {\n      hoverSetHint('I','magnetic attraction is changing its motion.',\n        'Watch the iron ring move toward '+learningItemLabel(near.item)+' as their separation decreases.',\n        'Iron is a magnetic material, so the magnet pulls it closer whichever pole is facing the iron.');\n    }\n    return;\n  }\n  support=learningDirectSupportOf('I');\n  if (support) {\n    if (support==='BASE') {\n      hoverSetHint('I','resting on the base.',\n        'The iron ring is stationary because it is supported from below.',\n        'Gravity is balanced by the base contact force. Iron remains magnetic, but no nearby magnetic pull is presently strong enough to dominate.');\n    }\n    else {\n      hoverSetHint('I','supported by '+learningItemLabel(support)+'.',\n        'The iron ring is resting on another object.',\n        'Contact provides support. If the supporting object is a magnet, magnetic attraction may also pull the iron toward it.');\n    }\n    return;\n  }\n  if (hoverIsFreeFall('I')) {\n    hoverSetHint('I','falling mainly under gravity.',\n      'The iron ring is moving downward and no magnet is presently close enough to produce a strong visible pull.',\n      'Iron is magnetic, but magnetic attraction depends strongly on distance; here gravity dominates.');\n    return;\n  }\n  hoverSetHint('I','iron can be attracted by either magnetic pole.',\n    'The iron ring is '+hoverMotionDescription('I')+'. Compare its behaviour as a magnet approaches.',\n    'Unlike magnet-magnet interactions, you do not need to choose a matching pole: either pole attracts the iron.');\n}\n\nfunction updateHoveredObjectGuidance() {\n  if (!showLearningHints || hoveredLearningItem==='') return;\n  if (isLearningMagnet(hoveredLearningItem)) updateHoveredMagnetGuidance(hoveredLearningItem);\n  else if (hoveredLearningItem==='W') updateHoveredWoodGuidance();\n  else if (hoveredLearningItem==='I') updateHoveredIronGuidance();\n}\n"
        }
      ]
    },
    "elements": {
      "list": []
    }
  },
  "view": {
    "Tree": [
      {
        "Name": "fullscreen",
        "Type": "Panel",
        "Expanded": "true",
        "Properties": [
          {
            "name": "Width",
            "value": "Width"
          }
        ],
        "Children": [
          {
            "Name": "control",
            "Type": "Panel",
            "Expanded": "true",
            "Properties": [
              {
                "name": "Background",
                "value": "\"rgba(192,235,192,1)\""
              },
              {
                "name": "BorderColor",
                "value": "\"black\""
              },
              {
                "name": "BorderWidth",
                "value": "1"
              },
              {
                "name": "Display",
                "value": "\"inline-block\""
              }
            ],
            "Children": [
              {
                "Name": "comboBox",
                "Type": "ComboBox",
                "Properties": [
                  {
                    "name": "Options",
                    "value": "[\"X-N\",\"X-S\",\"XY-NN\",\"XY-SS\",\"XY-NS\",\"XY-SN\",\"XYZ-NNN\",\"XYZ-NNS\",\"XYZ-NSN\",\"XYZ-NSS\",\"XYZ-SNN\",\"XWY-N_N\",\"WXY-_NS\",\"XIY-N_N\",\"XIY-N_S\",\"XYWZ-NN_N\",\"XYWZ-NN_S\",\"XYWZ-NS_N\",\"XYIZ-NN_N\",\"XYIZ-NN_S\",\"XIYZ-N_NS\",\"XYIWZ-NN__S\",\"XIYWZ-N_S_N\",\"IXYWZ-_NS_N\"]"
                  },
                  {
                    "name": "OnChange",
                    "value": "var opts = _view.comboBox.getProperty(\"SelectedOptions\");  // array of options\n    var option = (opts.length > 0)? opts[0]:\"\"; // selected option \n//[\"XY-NN\",\"XY-SS\",\"XY-NS\",\"XY-SN\"]\n\nif ( option==\"X-N\"){\n  xMagnetX=releasex;\n  yMagnetX=releasey;\n  flipX=false;\n  rodList = rodList+[\"X\"];\n  }\nelse  if ( option==\"X-S\"){\n  xMagnetX=releasex;\n  yMagnetX=releasey;\n  flipX=true;\n  rodList = rodList+[\"X\"];\n  }\n  \n else if ( option==\"Y-N\"){\n  xMagnetY=releasex;\n  yMagnetY=releasey;\n  flipY=false;\n  rodList = rodList+[\"Y\"];\n  }\nelse  if ( option==\"Y-S\"){\n  xMagnetY=releasex;\n  yMagnetY=releasey;\n  flipY=true;\n  rodList = rodList+[\"Y\"];\n  }\n  else if ( option==\"Z-N\"){\n  xMagnetZ=releasex;\n  yMagnetZ=releasey;\n  flipZ=false;\n  rodList = rodList+[\"Z\"];\n  }\nelse  if ( option==\"Z-S\"){\n  xMagnetZ=releasex;\n  yMagnetZ=releasey;\n  flipZ=true;\n  rodList = rodList+[\"Z\"];\n  }\n  //end of 1 object\n  \n // start of 2 magnets ==================================================\n   //Magnet X at the top:\n  else if ( option==\"XY-NN\"){\n  xMagnetX=releasex;\n  yMagnetX=releasey;\n  xMagnetY=releasex;\n  yMagnetY=releasey-yBlockSize;\n  flipX=false;\n  flipY=false;\n  rodList = [\"YX\"];//rodList+[\"Y\"]+[\"X\"];\n  }\n  \n else if ( option==\"XY-SS\"){\n  xMagnetX=releasex;\n  yMagnetX=releasey;\n  xMagnetY=releasex;\n  yMagnetY=releasey-yBlockSize;\n  flipX=true;\n  flipY=true;\n  rodList = [\"YX\"];//rodList+[\"Y\"]+[\"X\"];\n  }\n  else if ( option==\"XY-NS\"){ // like poles SS face each other\n  xMagnetX=releasex;\n  yMagnetX=releasey;\n  xMagnetY=releasex;\n  yMagnetY=releasey-yBlockSize;\n  flipX=true;\n  flipY=false;\n  rodList = [\"YX\"];//rodList+[\"Y\"]+[\"X\"];\n  }\n  else if ( option==\"XY-SN\"){\n  xMagnetX=releasex;\n  yMagnetX=releasey;\n  xMagnetY=releasex;\n  yMagnetY=releasey-yBlockSize;\n  flipX=false;\n  flipY=true;\n  rodList = [\"YX\"]; //rodList+[\"Y\"]+[\"X\"];\n  }\n  \n// start of 3 objects ==================================================\nelse if (option==\"XYZ-NNN\"){ // reminder that X is always the top\n  xMagnetX = releasex;\n  xMagnetY = releasex;\n  xMagnetZ = releasex;\n  \n  yMagnetX = releasey;\n  yMagnetY = releasey-yBlockSize;\n  yMagnetZ = releasey-(2*yBlockSize);\n  flipX=false;flipY=false;flipZ=false;\n  rodList = [\"ZYX\"];\n  }\n  \nelse if (option==\"XYZ-NNS\"){\n  xMagnetX=releasex;\n  xMagnetY=releasex;\n  xMagnetZ=releasex;\n  \n  yMagnetX = releasey;\n  yMagnetY = releasey-yBlockSize;\n  yMagnetZ = releasey-(2*yBlockSize);\n  flipX=false;flipY=false;flipZ=true;\n  rodList = [\"ZYX\"];\n  }\n  \nelse if (option==\"XYZ-NSN\"){\n  xMagnetX=releasex;\n  xMagnetY=releasex;\n  xMagnetZ=releasex;\n  \n  yMagnetX = releasey;\n  yMagnetY = releasey-yBlockSize;\n  yMagnetZ = releasey-(2*yBlockSize);\n  flipX=false;flipY=true;flipZ=false;\n  rodList = [\"ZYX\"];\n  }\n  \nelse if (option==\"XYZ-NSS\"){\n  xMagnetX=releasex;\n  xMagnetY=releasex;\n  xMagnetZ=releasex;\n  \n  yMagnetX = releasey;\n  yMagnetY = releasey-yBlockSize;\n  yMagnetZ = releasey-(2*yBlockSize);\n  flipX=false;flipY=true;flipZ=true;\n  rodList = [\"ZYX\"];\n  }\n  \nelse if (option==\"XYZ-SNN\"){\n  xMagnetX=releasex;\n  xMagnetY=releasex;\n  xMagnetZ=releasex;\n  \n  yMagnetX = releasey;\n  yMagnetY = releasey-yBlockSize;\n  yMagnetZ = releasey-(2*yBlockSize);\n  flipX=true;flipY=false;flipZ=false;\n  rodList = [\"ZYX\"];\n  }\n\nelse if (option==\"XWY-N_N\"){\n  xMagnetX = releasex;\n  xWooden = releasex;\n  xMagnetY = releasex;\n  \n  yMagnetX = releasey;\n  yWooden = releasey - yBlockSize;\n  yMagnetY = releasey - (2*yBlockSize);\n  flipX=false;flipY=false;\n  rodList = [\"YWX\"];\n  }\n  \nelse if (option==\"WXY-_NS\"){\n  xWooden = releasex;\n  xMagnetX = releasex;\n  xMagnetY = releasex;\n  \n  yWooden = releasey;\n  yMagnetX = releasey - yBlockSize;\n  yMagnetY = releasey - (2*yBlockSize);\n  flipX=false;flipY=true;\n  rodList = [\"YXW\"];\n  }\n  \nelse if (option==\"XIY-N_N\"){\n  xMagnetX = releasex;\n  xIron = releasex;\n  xMagnetY = releasex;\n  \n  yMagnetX = releasey;\n  yIron = releasey - yBlockSize;\n  yMagnetY = releasey - (2*yBlockSize);\n  flipX=false;flipY=false;\n  rodList = [\"YIX\"];\n  }\n  \nelse if (option==\"XIY-N_S\"){\n  xMagnetX = releasex;\n  xIron = releasex;\n  xMagnetY = releasex;\n  \n  yMagnetX = releasey;\n  yIron = releasey - yBlockSize;\n  yMagnetY = releasey - (2*yBlockSize);\n  flipX=false;flipY=true;\n  rodList = [\"YIX\"];\n  }\n  \n// start of 4 objects ==================================================\nelse if (option == \"XYWZ-NN_N\"){\n  xMagnetX=releasex;\n  xMagnetY=releasex;\n  xMagnetZ=releasex;\n  xWooden = releasex;\n  \n  yMagnetX = releasey;\n  yMagnetY = releasey-yBlockSize;\n  yWooden = releasey-(2*yBlockSize);\n  yMagnetZ = releasey-(3*yBlockSize);\n  \n  flipX=false; flipY=false; flipZ=false;\n  rodList = [\"ZWYX\"];\n  }\n  \nelse if (option == \"XYWZ-NN_S\"){\n  xMagnetX=releasex;\n  xMagnetY=releasex;\n  xMagnetZ=releasex;\n  xWooden = releasex;\n  \n  yMagnetX = releasey;\n  yMagnetY = releasey-yBlockSize;\n  yWooden = releasey-(2*yBlockSize);\n  yMagnetZ = releasey-(3*yBlockSize);\n  \n  flipX=false; flipY=false; flipZ=true;\n  rodList = [\"ZWYX\"];\n  }\n  \nelse if (option == \"XYWZ-NS_N\"){\n  xMagnetX=releasex;\n  xMagnetY=releasex;\n  xMagnetZ=releasex;\n  xWooden = releasex;\n  \n  yMagnetX = releasey;\n  yMagnetY = releasey-yBlockSize;\n  yWooden = releasey-(2*yBlockSize);\n  yMagnetZ = releasey-(3*yBlockSize);\n  \n  flipX=false; flipY=true; flipZ=false;\n  rodList = [\"ZWYX\"];\n  }\n  \n// start of 5 objects ==================================================\nelse if (option==\"XYIWZ-NN__S\"){\n  xMagnetX = releasex;\n  xMagnetY = releasex;\n  xMagnetZ = releasex;\n  xWooden = releasex;\n  xIron = releasex;\n  \n  yMagnetX = releasey;\n  yMagnetY = releasey-yBlockSize;\n  yIron = releasey-(2*yBlockSize);\n  yWooden = releasey-(3*yBlockSize);\n  yMagnetZ = releasey-(4*yBlockSize);\n  \n  flipX=false; flipY=false; flipZ=true;\n  rodList = [\"ZWIYX\"];\n  }\n\nelse if (option==\"XIYWZ-N_S_N\"){\n  xMagnetX = releasex;\n  xMagnetY = releasex;\n  xMagnetZ = releasex;\n  xWooden = releasex;\n  xIron = releasex;\n  \n  yMagnetX = releasey;\n  yIron = releasey-yBlockSize;\n  yMagnetY = releasey-(2*yBlockSize);\n  yWooden = releasey-(3*yBlockSize);\n  yMagnetZ = releasey-(4*yBlockSize);\n  \n  flipX=false; flipY=true; flipZ=false;\n  rodList = [\"ZWYIX\"];\n  }\n  \nelse if (option==\"IXYWZ-_NS_N\"){\n  xMagnetX = releasex;\n  xMagnetY = releasex;\n  xMagnetZ = releasex;\n  xWooden = releasex;\n  xIron = releasex;\n  \n  yIron = releasey;\n  yMagnetX = releasey-yBlockSize;\n  yMagnetY = releasey-(2*yBlockSize);\n  yWooden = releasey-(3*yBlockSize);\n  yMagnetZ = releasey-(4*yBlockSize);\n  \n  flipX=false; flipY=true; flipZ=false;\n  rodList = [\"ZWYIX\"];\n  }\n"
                  },
                  {
                    "name": "Visibility",
                    "value": "false"
                  },
                  {
                    "name": "Display",
                    "value": "\"none\""
                  }
                ]
              },
              {
                "Name": "flipping",
                "Type": "Panel",
                "Expanded": "false",
                "Properties": [
                  {
                    "name": "Tooltip",
                    "value": "\"Click the checkboxes to flip the sides of the selected items.\""
                  },
                  {
                    "name": "Display",
                    "value": "\"inline-block\""
                  }
                ],
                "Children": [
                  {
                    "Name": "flipMagnetX",
                    "Type": "CheckBox",
                    "Properties": [
                      {
                        "name": "OnCheckOff",
                        "value": "flipX=false;\n"
                      },
                      {
                        "name": "Checked",
                        "value": "flipX"
                      },
                      {
                        "name": "Text",
                        "value": "\"Flip Magnet X\""
                      },
                      {
                        "name": "OnCheckOn",
                        "value": "flipX=true;"
                      },
                      {
                        "name": "Font",
                        "value": "\"normal normal 3vh \""
                      }
                    ]
                  },
                  {
                    "Name": "flipMagnetY",
                    "Type": "CheckBox",
                    "Properties": [
                      {
                        "name": "OnCheckOff",
                        "value": "flipY=false;"
                      },
                      {
                        "name": "Checked",
                        "value": "flipY"
                      },
                      {
                        "name": "Text",
                        "value": "\"Flip Magnet Y\""
                      },
                      {
                        "name": "OnCheckOn",
                        "value": "flipY=true;"
                      },
                      {
                        "name": "Font",
                        "value": "\"normal normal 3vh \""
                      }
                    ]
                  },
                  {
                    "Name": "flipMagnetZ",
                    "Type": "CheckBox",
                    "Properties": [
                      {
                        "name": "OnCheckOff",
                        "value": "flipZ=false;"
                      },
                      {
                        "name": "Checked",
                        "value": "flipZ"
                      },
                      {
                        "name": "Text",
                        "value": "\"Flip Magnet Z\""
                      },
                      {
                        "name": "OnCheckOn",
                        "value": "flipZ=true;"
                      },
                      {
                        "name": "Font",
                        "value": "\"normal normal 3vh \""
                      }
                    ]
                  }
                ]
              },
              {
                "Name": "showHints",
                "Type": "CheckBox",
                "Properties": [
                  {
                    "name": "Checked",
                    "value": "showLearningHints"
                  },
                  {
                    "name": "Text",
                    "value": "\"Show learning hints\""
                  },
                  {
                    "name": "OnCheckOn",
                    "value": "showLearningHints=true; updateLearningGuidance();"
                  },
                  {
                    "name": "OnCheckOff",
                    "value": "showLearningHints=false;"
                  },
                  {
                    "name": "Font",
                    "value": "\"normal normal 2.2vh\""
                  },
                  {
                    "name": "Tooltip",
                    "value": "\"Show or hide explanations that connect the motion to gravity, magnetic push/pull and contact forces.\""
                  }
                ]
              },
              {
                "Name": "controlPanel",
                "Type": "Panel",
                "Expanded": "true",
                "Properties": [
                  {
                    "name": "Display",
                    "value": "\"inline-block\""
                  }
                ],
                "Children": [
                  {
                    "Name": "playPauseButton2",
                    "Type": "TwoStateButton",
                    "Properties": [
                      {
                        "name": "OffClick",
                        "value": "_pause();\n//speech (\"paused\");"
                      },
                      {
                        "name": "TextOn",
                        "value": "\"Play \u25b6\""
                      },
                      {
                        "name": "State",
                        "value": "_isPaused"
                      },
                      {
                        "name": "Tooltip",
                        "value": "\"Play/Pause\""
                      },
                      {
                        "name": "TextOff",
                        "value": "\"Pause \u275a\u275a\""
                      },
                      {
                        "name": "OnClick",
                        "value": "_play();\n//speech (\"play\");"
                      },
                      {
                        "name": "Width",
                        "value": "\"14vw\""
                      },
                      {
                        "name": "Font",
                        "value": "\"normal normal 3vh \""
                      }
                    ]
                  },
                  {
                    "Name": "stepButton2",
                    "Type": "Button",
                    "Properties": [
                      {
                        "name": "Text",
                        "value": "\"Next |\u25ba\""
                      },
                      {
                        "name": "OnClick",
                        "value": "_step()"
                      },
                      {
                        "name": "Width",
                        "value": "\"14vw\""
                      },
                      {
                        "name": "Font",
                        "value": "\"normal normal 3vh \""
                      }
                    ]
                  },
                  {
                    "Name": "resetButton3",
                    "Type": "Button",
                    "Properties": [
                      {
                        "name": "Text",
                        "value": "\"Reset \u21bb\""
                      },
                      {
                        "name": "Width",
                        "value": "\"14vw\""
                      },
                      {
                        "name": "OnClick",
                        "value": "_reset();\n//speechzh (\"\u4f60\u597d\");\n"
                      },
                      {
                        "name": "Font",
                        "value": "\"normal normal 3vh \""
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "Name": "panel",
            "Type": "Panel",
            "Expanded": "true",
            "Properties": [
              {
                "name": "Height",
                "value": "\"100%\""
              },
              {
                "name": "Width",
                "value": "\"100%\""
              }
            ],
            "Children": [
              {
                "Name": "plottingPanel",
                "Type": "PlottingPanel",
                "Expanded": "true",
                "Properties": [
                  {
                    "name": "Gutters",
                    "value": "[0,0,0,0]"
                  },
                  {
                    "name": "ShowAreaRectangle",
                    "value": "false"
                  },
                  {
                    "name": "YScalePrecision",
                    "value": "0"
                  },
                  {
                    "name": "XFixedTick",
                    "value": "0"
                  },
                  {
                    "name": "OnDoubleClick",
                    "value": "toggleFullScreen();"
                  },
                  {
                    "name": "AxisXShow",
                    "value": "false"
                  },
                  {
                    "name": "YFixedTick",
                    "value": "0"
                  },
                  {
                    "name": "XTickStep",
                    "value": "1"
                  },
                  {
                    "name": "YTickStep",
                    "value": "1"
                  },
                  {
                    "name": "XAutoTicks",
                    "value": "false"
                  },
                  {
                    "name": "Height",
                    "value": "%changeOrientation()%"
                  },
                  {
                    "name": "OnPress",
                    "value": "var position = _view.plottingPanel.getInteraction().getInteractionPoint();\n"
                  },
                  {
                    "name": "GridXShow",
                    "value": "false"
                  },
                  {
                    "name": "Width",
                    "value": "Width1"
                  },
                  {
                    "name": "Enabled",
                    "value": "true"
                  },
                  {
                    "name": "SquareAspect",
                    "value": "true"
                  },
                  {
                    "name": "MaximumY",
                    "value": "14"
                  },
                  {
                    "name": "MaximumX",
                    "value": "5"
                  },
                  {
                    "name": "YAutoTicks",
                    "value": "false"
                  },
                  {
                    "name": "GridYShow",
                    "value": "false"
                  },
                  {
                    "name": "MinimumX",
                    "value": "-16"
                  },
                  {
                    "name": "MinimumY",
                    "value": "-2.5"
                  },
                  {
                    "name": "AxisYShow",
                    "value": "false"
                  },
                  {
                    "name": "AutoScaleY",
                    "value": "false"
                  },
                  {
                    "name": "AutoScaleX",
                    "value": "false"
                  },
                  {
                    "name": "Visibility",
                    "value": "world===true"
                  },
                  {
                    "name": "XScalePrecision",
                    "value": "0"
                  }
                ],
                "Children": [
                  {
                    "Name": "labels",
                    "Type": "Group2D",
                    "Expanded": "false",
                    "Properties": [],
                    "Children": [
                      {
                        "Name": "tablecolour",
                        "Type": "Shape2D",
                        "Properties": [
                          {
                            "name": "FillColor",
                            "value": "\"rgba(235,192,235,1)\""
                          },
                          {
                            "name": "SizeX",
                            "value": "6"
                          },
                          {
                            "name": "ShapeType",
                            "value": "\"RECTANGLE\""
                          },
                          {
                            "name": "X",
                            "value": "-15"
                          },
                          {
                            "name": "LineColor",
                            "value": "\"white\""
                          },
                          {
                            "name": "Y",
                            "value": "6.5"
                          },
                          {
                            "name": "SizeY",
                            "value": "10"
                          }
                        ]
                      },
                      {
                        "Name": "magnetlabel",
                        "Type": "Group2D",
                        "Expanded": "false",
                        "Properties": [],
                        "Children": [
                          {
                            "Name": "MagnetXline",
                            "Type": "Segment2D",
                            "Properties": [
                              {
                                "name": "SizeX",
                                "value": "xLine"
                              },
                              {
                                "name": "X",
                                "value": "xMagnetX-3"
                              },
                              {
                                "name": "Y",
                                "value": "yMagnetX"
                              },
                              {
                                "name": "Visibility",
                                "value": "false"
                              },
                              {
                                "name": "SizeY",
                                "value": "0"
                              }
                            ]
                          },
                          {
                            "Name": "MagnetYText",
                            "Type": "Text2D",
                            "Properties": [
                              {
                                "name": "X",
                                "value": "-15"
                              },
                              {
                                "name": "Y",
                                "value": "8.5"
                              },
                              {
                                "name": "Text",
                                "value": "\"Magnet Y\""
                              },
                              {
                                "name": "Font",
                                "value": "font"
                              }
                            ]
                          },
                          {
                            "Name": "MagnetZText",
                            "Type": "Text2D",
                            "Properties": [
                              {
                                "name": "X",
                                "value": "-15"
                              },
                              {
                                "name": "Y",
                                "value": "6.5"
                              },
                              {
                                "name": "Text",
                                "value": "\"Magnet Z\""
                              },
                              {
                                "name": "Font",
                                "value": "font"
                              }
                            ]
                          },
                          {
                            "Name": "MagnetXText4",
                            "Type": "Text2D",
                            "Properties": [
                              {
                                "name": "X",
                                "value": "-15"
                              },
                              {
                                "name": "Y",
                                "value": "10.5"
                              },
                              {
                                "name": "Text",
                                "value": "\"Magnet X\""
                              },
                              {
                                "name": "Font",
                                "value": "font"
                              }
                            ]
                          },
                          {
                            "Name": "MagnetXText5",
                            "Type": "Text2D",
                            "Properties": [
                              {
                                "name": "X",
                                "value": "-15"
                              },
                              {
                                "name": "Y",
                                "value": "4.5"
                              },
                              {
                                "name": "Text",
                                "value": "\"Wooden ring\""
                              },
                              {
                                "name": "Font",
                                "value": "font"
                              }
                            ]
                          },
                          {
                            "Name": "MagnetXText",
                            "Type": "Text2D",
                            "Properties": [
                              {
                                "name": "X",
                                "value": "-15"
                              },
                              {
                                "name": "Y",
                                "value": "2.5"
                              },
                              {
                                "name": "Text",
                                "value": "\"Iron ring\""
                              },
                              {
                                "name": "Font",
                                "value": "font"
                              }
                            ]
                          }
                        ]
                      },
                      {
                        "Name": "table",
                        "Type": "Polygon2D",
                        "Properties": [
                          {
                            "name": "Points",
                            "value": "[[-5,1.5],[-18,1.5],[-18,11.5],[-5,11.5],[-5,1.5]]"
                          },
                          {
                            "name": "LineWidth",
                            "value": "3"
                          }
                        ]
                      },
                      {
                        "Name": "tableline",
                        "Type": "Polygon2D",
                        "Properties": [
                          {
                            "name": "Points",
                            "value": "[[-12,11.5],[-12,1.5]]"
                          },
                          {
                            "name": "LineWidth",
                            "value": "3"
                          }
                        ]
                      },
                      {
                        "Name": "tableline2",
                        "Type": "SegmentSet2D",
                        "Properties": [
                          {
                            "name": "NumberOfElements",
                            "value": "4"
                          },
                          {
                            "name": "SizeX",
                            "value": "13"
                          },
                          {
                            "name": "X",
                            "value": "-18"
                          },
                          {
                            "name": "Y",
                            "value": "[9.5,7.5,5.5,3.5]"
                          },
                          {
                            "name": "SizeY",
                            "value": "0"
                          },
                          {
                            "name": "LineWidth",
                            "value": "2"
                          }
                        ]
                      },
                      {
                        "Name": "border",
                        "Type": "Shape2D",
                        "Properties": [
                          {
                            "name": "FillColor",
                            "value": "\"rgba(238,238,238,0.9)\""
                          },
                          {
                            "name": "SizeX",
                            "value": "xBlockSize+1"
                          },
                          {
                            "name": "ShapeType",
                            "value": "\"RECTANGLE\""
                          },
                          {
                            "name": "X",
                            "value": "0"
                          },
                          {
                            "name": "LineColor",
                            "value": "\"rgba(0,0,0,0.5)\""
                          },
                          {
                            "name": "Y",
                            "value": "9.7"
                          },
                          {
                            "name": "Visibility",
                            "value": "false"
                          },
                          {
                            "name": "SizeY",
                            "value": "yBlockSize"
                          }
                        ]
                      },
                      {
                        "Name": "image",
                        "Type": "Image2D",
                        "Properties": [
                          {
                            "name": "SizeX",
                            "value": "releasedx"
                          },
                          {
                            "name": "RelativePosition",
                            "value": "\"CENTERED\""
                          },
                          {
                            "name": "X",
                            "value": "releasex"
                          },
                          {
                            "name": "ImageUrl",
                            "value": "\"./StackingMagnet/box.png\""
                          },
                          {
                            "name": "Y",
                            "value": "releasey"
                          },
                          {
                            "name": "SizeY",
                            "value": "releasedy"
                          }
                        ]
                      },
                      {
                        "Name": "rodtext",
                        "Type": "Text2D",
                        "Properties": [
                          {
                            "name": "RelativePosition",
                            "value": "\"CENTERED\""
                          },
                          {
                            "name": "X",
                            "value": "8.5"
                          },
                          {
                            "name": "Y",
                            "value": "1"
                          },
                          {
                            "name": "Text",
                            "value": "\"plastic \\n rod\""
                          },
                          {
                            "name": "Font",
                            "value": "font"
                          }
                        ]
                      },
                      {
                        "Name": "releasetext",
                        "Type": "Text2D",
                        "Properties": [
                          {
                            "name": "FillColor",
                            "value": "\"white\""
                          },
                          {
                            "name": "OutlineColor",
                            "value": "\"black\""
                          },
                          {
                            "name": "RelativePosition",
                            "value": "\"CENTERED\""
                          },
                          {
                            "name": "X",
                            "value": "0"
                          },
                          {
                            "name": "Y",
                            "value": "12"
                          },
                          {
                            "name": "Text",
                            "value": "\"release here\""
                          },
                          {
                            "name": "Font",
                            "value": "font"
                          }
                        ]
                      },
                      {
                        "Name": "rodliine",
                        "Type": "Segment2D",
                        "Properties": [
                          {
                            "name": "SizeX",
                            "value": "4"
                          },
                          {
                            "name": "X",
                            "value": "3"
                          },
                          {
                            "name": "Y",
                            "value": "-0.5"
                          },
                          {
                            "name": "SizeY",
                            "value": "1"
                          }
                        ]
                      }
                    ]
                  },
                  {
                    "Name": "plasticRod",
                    "Type": "Group2D",
                    "Expanded": "false",
                    "Properties": [],
                    "Children": [
                      {
                        "Name": "neck",
                        "Type": "Shape2D",
                        "Properties": [
                          {
                            "name": "FillColor",
                            "value": "\"rgba(236,239,248,1)\""
                          },
                          {
                            "name": "SizeX",
                            "value": "1.25"
                          },
                          {
                            "name": "RelativePosition",
                            "value": "\"SOUTH\""
                          },
                          {
                            "name": "ShapeType",
                            "value": "\"RECTANGLE\""
                          },
                          {
                            "name": "X",
                            "value": "basex"
                          },
                          {
                            "name": "LineColor",
                            "value": "\"black\""
                          },
                          {
                            "name": "Y",
                            "value": "basey"
                          },
                          {
                            "name": "SizeY",
                            "value": "10"
                          },
                          {
                            "name": "LineWidth",
                            "value": "3"
                          }
                        ]
                      },
                      {
                        "Name": "base",
                        "Type": "Shape2D",
                        "Properties": [
                          {
                            "name": "FillColor",
                            "value": "\"rgba(236,239,248,1)\""
                          },
                          {
                            "name": "SizeX",
                            "value": "6"
                          },
                          {
                            "name": "RelativePosition",
                            "value": "\"NORTH\""
                          },
                          {
                            "name": "ShapeType",
                            "value": "\"RECTANGLE\""
                          },
                          {
                            "name": "X",
                            "value": "basex"
                          },
                          {
                            "name": "LineColor",
                            "value": "\"black\""
                          },
                          {
                            "name": "Y",
                            "value": "basey"
                          },
                          {
                            "name": "SizeY",
                            "value": "1.5"
                          },
                          {
                            "name": "LineWidth",
                            "value": "3"
                          }
                        ]
                      }
                    ]
                  },
                  {
                    "Name": "magnets",
                    "Type": "Group2D",
                    "Expanded": "false",
                    "Properties": [],
                    "Children": [
                      {
                        "Name": "default",
                        "Type": "Group2D",
                        "Expanded": "false",
                        "Properties": [],
                        "Children": [
                          {
                            "Name": "magnetX",
                            "Type": "Group2D",
                            "Expanded": "false",
                            "Properties": [
                              {
                                "name": "Visibility",
                                "value": "flipX==false"
                              }
                            ],
                            "Children": [
                              {
                                "Name": "magnetX1",
                                "Type": "Shape2D",
                                "Properties": [
                                  {
                                    "name": "OnRelease",
                                    "value": "//vyMagnetX=0;\n\n"
                                  },
                                  {
                                    "name": "FillColor",
                                    "value": "blueC"
                                  },
                                  {
                                    "name": "Sensitivity",
                                    "value": "0"
                                  },
                                  {
                                    "name": "SizeX",
                                    "value": "xBlockSize"
                                  },
                                  {
                                    "name": "ShapeType",
                                    "value": "\"RECTANGLE\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetX"
                                  },
                                  {
                                    "name": "LineColor",
                                    "value": "\"black\""
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetX"
                                  },
                                  {
                                    "name": "SizeY",
                                    "value": "yBlockSize"
                                  },
                                  {
                                    "name": "LineWidth",
                                    "value": "0.5"
                                  },
                                  {
                                    "name": "EnabledPosition",
                                    "value": "xMagnetX!=0?\"ENABLED_ANY\":\"ENABLED_Y\""
                                  },
                                  {
                                    "name": "OnDrag",
                                    "value": "onDragX ();\nonDragbarrierX();"
                                  },
                                  {
                                    "name": "OnEnter",
                                    "value": "setHoveredLearningItem('X');"
                                  },
                                  {
                                    "name": "OnExit",
                                    "value": "clearHoveredLearningItem('X');"
                                  }
                                ]
                              },
                              {
                                "Name": "redUp",
                                "Type": "Shape2D",
                                "Properties": [
                                  {
                                    "name": "FillColor",
                                    "value": "\"Red\""
                                  },
                                  {
                                    "name": "SizeX",
                                    "value": "xBlockSize"
                                  },
                                  {
                                    "name": "ShapeType",
                                    "value": "\"RECTANGLE\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetX"
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetX+0.3"
                                  },
                                  {
                                    "name": "SizeY",
                                    "value": "yBlockSize/2"
                                  }
                                ]
                              },
                              {
                                "Name": "text",
                                "Type": "Text2D",
                                "Properties": [
                                  {
                                    "name": "FillColor",
                                    "value": "\"white\""
                                  },
                                  {
                                    "name": "OutlineColor",
                                    "value": "\"black\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetX"
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetX"
                                  },
                                  {
                                    "name": "Text",
                                    "value": "\"X\""
                                  },
                                  {
                                    "name": "Font",
                                    "value": "\"normal bold 1.5vw \\\"Comic Sans MS\\\", cursive, sans-serif\""
                                  }
                                ]
                              }
                            ]
                          },
                          {
                            "Name": "magnetY",
                            "Type": "Group2D",
                            "Expanded": "false",
                            "Properties": [
                              {
                                "name": "Visibility",
                                "value": "flipY==false"
                              }
                            ],
                            "Children": [
                              {
                                "Name": "magnetY1",
                                "Type": "Shape2D",
                                "Properties": [
                                  {
                                    "name": "FillColor",
                                    "value": "blueC"
                                  },
                                  {
                                    "name": "Sensitivity",
                                    "value": "0"
                                  },
                                  {
                                    "name": "SizeX",
                                    "value": "xBlockSize"
                                  },
                                  {
                                    "name": "ShapeType",
                                    "value": "\"RECTANGLE\""
                                  },
                                  {
                                    "name": "LineColor",
                                    "value": "\"black\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetY"
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetY"
                                  },
                                  {
                                    "name": "SizeY",
                                    "value": "yBlockSize"
                                  },
                                  {
                                    "name": "LineWidth",
                                    "value": "0.5"
                                  },
                                  {
                                    "name": "EnabledPosition",
                                    "value": "xMagnetY!=0?\"ENABLED_ANY\":\"ENABLED_Y\""
                                  },
                                  {
                                    "name": "OnDrag",
                                    "value": "onDragY ();\nonDragbarrierY ();\n/*\nif (xMagnetY>=5){\n  xMagnetY=5\n  }\n  else if (xMagnetY<=-16){\n    xMagnetY=-16\n    }\n\nif (yMagnetY >= 12){\n  yMagnetY = 12\n  }\n  else if (yMagnetY <= 2){\n    yMagnetY = 2\n    }\n*/"
                                  },
                                  {
                                    "name": "OnEnter",
                                    "value": "setHoveredLearningItem('Y');"
                                  },
                                  {
                                    "name": "OnExit",
                                    "value": "clearHoveredLearningItem('Y');"
                                  }
                                ]
                              },
                              {
                                "Name": "redUp2",
                                "Type": "Shape2D",
                                "Properties": [
                                  {
                                    "name": "FillColor",
                                    "value": "\"red\""
                                  },
                                  {
                                    "name": "SizeX",
                                    "value": "xBlockSize"
                                  },
                                  {
                                    "name": "ShapeType",
                                    "value": "\"RECTANGLE\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetY"
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetY+0.3"
                                  },
                                  {
                                    "name": "SizeY",
                                    "value": "yBlockSize/2"
                                  }
                                ]
                              },
                              {
                                "Name": "text2",
                                "Type": "Text2D",
                                "Properties": [
                                  {
                                    "name": "FillColor",
                                    "value": "\"white\""
                                  },
                                  {
                                    "name": "OutlineColor",
                                    "value": "\"black\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetY"
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetY"
                                  },
                                  {
                                    "name": "Text",
                                    "value": "\"Y\""
                                  },
                                  {
                                    "name": "Font",
                                    "value": "\"normal bold 1.5vw \\\"Comic Sans MS\\\", cursive, sans-serif\""
                                  }
                                ]
                              }
                            ]
                          },
                          {
                            "Name": "magnetZ",
                            "Type": "Group2D",
                            "Expanded": "false",
                            "Properties": [
                              {
                                "name": "Visibility",
                                "value": "flipZ==false"
                              }
                            ],
                            "Children": [
                              {
                                "Name": "magnetZ1",
                                "Type": "Shape2D",
                                "Properties": [
                                  {
                                    "name": "Sensitivity",
                                    "value": "0"
                                  },
                                  {
                                    "name": "FillColor",
                                    "value": "blueC"
                                  },
                                  {
                                    "name": "SizeX",
                                    "value": "xBlockSize"
                                  },
                                  {
                                    "name": "ShapeType",
                                    "value": "\"RECTANGLE\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetZ"
                                  },
                                  {
                                    "name": "LineColor",
                                    "value": "\"black\""
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetZ"
                                  },
                                  {
                                    "name": "SizeY",
                                    "value": "yBlockSize"
                                  },
                                  {
                                    "name": "LineWidth",
                                    "value": "0.5"
                                  },
                                  {
                                    "name": "EnabledPosition",
                                    "value": "xMagnetZ!=0?\"ENABLED_ANY\":\"ENABLED_Y\""
                                  },
                                  {
                                    "name": "OnDrag",
                                    "value": "onDragZ ();\nonDragbarrierZ ();\n\n"
                                  },
                                  {
                                    "name": "OnEnter",
                                    "value": "setHoveredLearningItem('Z');"
                                  },
                                  {
                                    "name": "OnExit",
                                    "value": "clearHoveredLearningItem('Z');"
                                  }
                                ]
                              },
                              {
                                "Name": "redUp3",
                                "Type": "Shape2D",
                                "Properties": [
                                  {
                                    "name": "FillColor",
                                    "value": "\"Red\""
                                  },
                                  {
                                    "name": "SizeX",
                                    "value": "xBlockSize"
                                  },
                                  {
                                    "name": "ShapeType",
                                    "value": "\"RECTANGLE\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetZ"
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetZ+0.3"
                                  },
                                  {
                                    "name": "SizeY",
                                    "value": "yBlockSize/2"
                                  }
                                ]
                              },
                              {
                                "Name": "text22",
                                "Type": "Text2D",
                                "Properties": [
                                  {
                                    "name": "FillColor",
                                    "value": "\"White\""
                                  },
                                  {
                                    "name": "OutlineColor",
                                    "value": "\"black\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetZ"
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetZ"
                                  },
                                  {
                                    "name": "Text",
                                    "value": "\"Z\""
                                  },
                                  {
                                    "name": "Font",
                                    "value": "\"normal bold 1.5vw \\\"Comic Sans MS\\\", cursive, sans-serif\""
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      },
                      {
                        "Name": "flipped",
                        "Type": "Group2D",
                        "Expanded": "false",
                        "Properties": [],
                        "Children": [
                          {
                            "Name": "magnetX2",
                            "Type": "Group2D",
                            "Expanded": "false",
                            "Properties": [
                              {
                                "name": "Visibility",
                                "value": "flipX==true"
                              }
                            ],
                            "Children": [
                              {
                                "Name": "magnetX12",
                                "Type": "Shape2D",
                                "Properties": [
                                  {
                                    "name": "OnRelease",
                                    "value": "xMove=false;\nvyMagnetX=0;"
                                  },
                                  {
                                    "name": "FillColor",
                                    "value": "\"rgba(0,128,255,1)\""
                                  },
                                  {
                                    "name": "Sensitivity",
                                    "value": "0"
                                  },
                                  {
                                    "name": "SizeX",
                                    "value": "xBlockSize"
                                  },
                                  {
                                    "name": "ShapeType",
                                    "value": "\"RECTANGLE\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetX"
                                  },
                                  {
                                    "name": "LineColor",
                                    "value": "\"black\""
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetX"
                                  },
                                  {
                                    "name": "SizeY",
                                    "value": "yBlockSize"
                                  },
                                  {
                                    "name": "LineWidth",
                                    "value": "0.5"
                                  },
                                  {
                                    "name": "EnabledPosition",
                                    "value": "xMagnetX!=0?\"ENABLED_ANY\":\"ENABLED_Y\""
                                  },
                                  {
                                    "name": "OnDrag",
                                    "value": "onDragX ();\nonDragbarrierX();\nxMove=true;"
                                  },
                                  {
                                    "name": "OnEnter",
                                    "value": "setHoveredLearningItem('X');"
                                  },
                                  {
                                    "name": "OnExit",
                                    "value": "clearHoveredLearningItem('X');"
                                  }
                                ]
                              },
                              {
                                "Name": "redUp4",
                                "Type": "Shape2D",
                                "Properties": [
                                  {
                                    "name": "FillColor",
                                    "value": "\"Red\""
                                  },
                                  {
                                    "name": "SizeX",
                                    "value": "xBlockSize"
                                  },
                                  {
                                    "name": "ShapeType",
                                    "value": "\"RECTANGLE\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetX"
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetX-0.3"
                                  },
                                  {
                                    "name": "SizeY",
                                    "value": "yBlockSize/2"
                                  }
                                ]
                              },
                              {
                                "Name": "text3",
                                "Type": "Text2D",
                                "Properties": [
                                  {
                                    "name": "FillColor",
                                    "value": "\"white\""
                                  },
                                  {
                                    "name": "OutlineColor",
                                    "value": "\"black\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetX"
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetX"
                                  },
                                  {
                                    "name": "Text",
                                    "value": "\"X\""
                                  },
                                  {
                                    "name": "Font",
                                    "value": "\"normal bold 1.5vw \\\"Comic Sans MS\\\", cursive, sans-serif\""
                                  }
                                ]
                              }
                            ]
                          },
                          {
                            "Name": "magnetY2",
                            "Type": "Group2D",
                            "Expanded": "false",
                            "Properties": [
                              {
                                "name": "Visibility",
                                "value": "flipY==true"
                              }
                            ],
                            "Children": [
                              {
                                "Name": "magnetY12",
                                "Type": "Shape2D",
                                "Properties": [
                                  {
                                    "name": "OnRelease",
                                    "value": "yMove=false;"
                                  },
                                  {
                                    "name": "FillColor",
                                    "value": "blueC"
                                  },
                                  {
                                    "name": "Sensitivity",
                                    "value": "0"
                                  },
                                  {
                                    "name": "SizeX",
                                    "value": "xBlockSize"
                                  },
                                  {
                                    "name": "ShapeType",
                                    "value": "\"RECTANGLE\""
                                  },
                                  {
                                    "name": "LineColor",
                                    "value": "\"black\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetY"
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetY"
                                  },
                                  {
                                    "name": "SizeY",
                                    "value": "yBlockSize"
                                  },
                                  {
                                    "name": "LineWidth",
                                    "value": "0.5"
                                  },
                                  {
                                    "name": "EnabledPosition",
                                    "value": "xMagnetY!=0?\"ENABLED_ANY\":\"ENABLED_Y\""
                                  },
                                  {
                                    "name": "OnDrag",
                                    "value": "onDragY ();\nonDragbarrierY ();"
                                  },
                                  {
                                    "name": "OnEnter",
                                    "value": "setHoveredLearningItem('Y');"
                                  },
                                  {
                                    "name": "OnExit",
                                    "value": "clearHoveredLearningItem('Y');"
                                  }
                                ]
                              },
                              {
                                "Name": "redUp22",
                                "Type": "Shape2D",
                                "Properties": [
                                  {
                                    "name": "FillColor",
                                    "value": "\"Red\""
                                  },
                                  {
                                    "name": "SizeX",
                                    "value": "xBlockSize"
                                  },
                                  {
                                    "name": "ShapeType",
                                    "value": "\"RECTANGLE\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetY"
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetY-0.3"
                                  },
                                  {
                                    "name": "SizeY",
                                    "value": "yBlockSize/2"
                                  }
                                ]
                              },
                              {
                                "Name": "text23",
                                "Type": "Text2D",
                                "Properties": [
                                  {
                                    "name": "FillColor",
                                    "value": "\"white\""
                                  },
                                  {
                                    "name": "OutlineColor",
                                    "value": "\"black\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetY"
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetY"
                                  },
                                  {
                                    "name": "Text",
                                    "value": "\"Y\""
                                  },
                                  {
                                    "name": "Font",
                                    "value": "\"normal bold 1.5vw \\\"Comic Sans MS\\\", cursive, sans-serif\""
                                  }
                                ]
                              }
                            ]
                          },
                          {
                            "Name": "magnetZ2",
                            "Type": "Group2D",
                            "Expanded": "false",
                            "Properties": [
                              {
                                "name": "Visibility",
                                "value": "flipZ==true"
                              }
                            ],
                            "Children": [
                              {
                                "Name": "magnetZ12",
                                "Type": "Shape2D",
                                "Properties": [
                                  {
                                    "name": "OnRelease",
                                    "value": "zMove=false;"
                                  },
                                  {
                                    "name": "Sensitivity",
                                    "value": "0"
                                  },
                                  {
                                    "name": "FillColor",
                                    "value": "blueC"
                                  },
                                  {
                                    "name": "SizeX",
                                    "value": "xBlockSize"
                                  },
                                  {
                                    "name": "ShapeType",
                                    "value": "\"RECTANGLE\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetZ"
                                  },
                                  {
                                    "name": "LineColor",
                                    "value": "\"black\""
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetZ"
                                  },
                                  {
                                    "name": "SizeY",
                                    "value": "yBlockSize"
                                  },
                                  {
                                    "name": "LineWidth",
                                    "value": "0.5"
                                  },
                                  {
                                    "name": "EnabledPosition",
                                    "value": "xMagnetZ!=0?\"ENABLED_ANY\":\"ENABLED_Y\""
                                  },
                                  {
                                    "name": "OnDrag",
                                    "value": "if (xMagnetZ>=5){\n  xMagnetZ=5\n  }\n  else if (xMagnetZ<=-16){\n    xMagnetZ=-16\n    }\n\nif (yMagnetZ >= 12){\n  yMagnetZ = 12\n  }\n  else if (yMagnetZ <= 2){\n    yMagnetZ = 2\n    }\nzMove=true;\nonDragZ ();"
                                  },
                                  {
                                    "name": "OnEnter",
                                    "value": "setHoveredLearningItem('Z');"
                                  },
                                  {
                                    "name": "OnExit",
                                    "value": "clearHoveredLearningItem('Z');"
                                  }
                                ]
                              },
                              {
                                "Name": "redUp32",
                                "Type": "Shape2D",
                                "Properties": [
                                  {
                                    "name": "FillColor",
                                    "value": "\"Red\""
                                  },
                                  {
                                    "name": "SizeX",
                                    "value": "xBlockSize"
                                  },
                                  {
                                    "name": "ShapeType",
                                    "value": "\"RECTANGLE\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetZ"
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetZ-0.3"
                                  },
                                  {
                                    "name": "SizeY",
                                    "value": "yBlockSize/2"
                                  }
                                ]
                              },
                              {
                                "Name": "text222",
                                "Type": "Text2D",
                                "Properties": [
                                  {
                                    "name": "FillColor",
                                    "value": "\"white\""
                                  },
                                  {
                                    "name": "OutlineColor",
                                    "value": "\"black\""
                                  },
                                  {
                                    "name": "X",
                                    "value": "xMagnetZ"
                                  },
                                  {
                                    "name": "Y",
                                    "value": "yMagnetZ"
                                  },
                                  {
                                    "name": "Text",
                                    "value": "\"Z\""
                                  },
                                  {
                                    "name": "Font",
                                    "value": "\"normal bold 1.5vw \\\"Comic Sans MS\\\", cursive, sans-serif\""
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  },
                  {
                    "Name": "rings",
                    "Type": "Group2D",
                    "Expanded": "false",
                    "Properties": [],
                    "Children": [
                      {
                        "Name": "wooden",
                        "Type": "Group2D",
                        "Expanded": "false",
                        "Properties": [],
                        "Children": [
                          {
                            "Name": "woodenring",
                            "Type": "Image2D",
                            "Properties": [
                              {
                                "name": "OnRelease",
                                "value": "wMove=false;\nvyWooden=0;\n"
                              },
                              {
                                "name": "Sensitivity",
                                "value": "0"
                              },
                              {
                                "name": "SizeX",
                                "value": "xBlockSize"
                              },
                              {
                                "name": "X",
                                "value": "xWooden"
                              },
                              {
                                "name": "ImageUrl",
                                "value": "\"./StackingMagnet/wood.png\""
                              },
                              {
                                "name": "Y",
                                "value": "yWooden"
                              },
                              {
                                "name": "SizeY",
                                "value": "yBlockSize"
                              },
                              {
                                "name": "EnabledPosition",
                                "value": "xWooden!=0?\"ENABLED_ANY\":\"ENABLED_Y\""
                              },
                              {
                                "name": "OnDrag",
                                "value": "if (xWooden>=1.5){\n  xWooden=1.5\n  }\n  else if (xWooden<=-16){\n    xWooden=-16\n    }\n\nif (yWooden >= 12){\n  yWooden = 12\n  }\n  else if (yWooden <= 2){\n    yWooden = 2\n    }\nwMove=true;\nonDragW();\n\n"
                              },
                              {
                                "name": "OnEnter",
                                "value": "setHoveredLearningItem('W');"
                              },
                              {
                                "name": "OnExit",
                                "value": "clearHoveredLearningItem('W');"
                              }
                            ]
                          }
                        ]
                      },
                      {
                        "Name": "iron",
                        "Type": "Group2D",
                        "Expanded": "false",
                        "Properties": [],
                        "Children": [
                          {
                            "Name": "ironring",
                            "Type": "Image2D",
                            "Properties": [
                              {
                                "name": "OnRelease",
                                "value": "iMove=false;\nvyIron=0;\n\n"
                              },
                              {
                                "name": "Sensitivity",
                                "value": "0"
                              },
                              {
                                "name": "SizeX",
                                "value": "xBlockSize"
                              },
                              {
                                "name": "X",
                                "value": "xIron"
                              },
                              {
                                "name": "Y",
                                "value": "yIron"
                              },
                              {
                                "name": "ImageUrl",
                                "value": "\"./StackingMagnet/iron.png\""
                              },
                              {
                                "name": "SizeY",
                                "value": "yBlockSize"
                              },
                              {
                                "name": "EnabledPosition",
                                "value": "xIron!=0?\"ENABLED_ANY\":\"ENABLED_Y\""
                              },
                              {
                                "name": "OnDrag",
                                "value": "if (xIron>=1.5){\n  xIron=1.5\n  }\n  else if (xIron<=-16){\n    xIron=-16\n    }\n\nif (yIron >= 12){\n  yIron = 12\n  }\n  else if (yIron <= 1.9){\n    yIron = 1.9\n    }\niMove=true;\nonDragI();"
                              },
                              {
                                "name": "OnEnter",
                                "value": "setHoveredLearningItem('I');"
                              },
                              {
                                "name": "OnExit",
                                "value": "clearHoveredLearningItem('I');"
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "Name": "learningHintPanel",
            "Type": "Panel",
            "Properties": [
              {
                "name": "Html",
                "value": "learningHintHtml"
              },
              {
                "name": "CSS",
                "value": "{padding:\"8px 14px\",boxSizing:\"border-box\",textAlign:\"left\"}"
              },
              {
                "name": "Background",
                "value": "\"rgba(255,249,214,0.98)\""
              },
              {
                "name": "BorderColor",
                "value": "\"rgba(120,100,20,0.65)\""
              },
              {
                "name": "BorderWidth",
                "value": "1"
              },
              {
                "name": "Width",
                "value": "\"100%\""
              },
              {
                "name": "Display",
                "value": "\"block\""
              },
              {
                "name": "Visibility",
                "value": "showLearningHints"
              }
            ]
          },
          {
            "Name": "hoverHintPanel",
            "Type": "Panel",
            "Properties": [
              {
                "name": "Html",
                "value": "hoverHintHtml"
              },
              {
                "name": "CSS",
                "value": "{padding:\"8px 14px\",boxSizing:\"border-box\",textAlign:\"left\",marginTop:\"4px\"}"
              },
              {
                "name": "Background",
                "value": "\"rgba(224,242,255,0.98)\""
              },
              {
                "name": "BorderColor",
                "value": "\"rgba(30,90,130,0.65)\""
              },
              {
                "name": "BorderWidth",
                "value": "1"
              },
              {
                "name": "Width",
                "value": "\"100%\""
              },
              {
                "name": "Display",
                "value": "\"block\""
              },
              {
                "name": "Visibility",
                "value": "showLearningHints && hoveredLearningItem!=\"\""
              }
            ]
          },
          {
            "Name": "html",
            "Type": "Panel",
            "Expanded": "true",
            "Properties": [],
            "Children": [
              {
                "Name": "Learning_outcomes",
                "Type": "Panel",
                "Properties": [
                  {
                    "name": "Html",
                    "value": "<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/FnM2FNsCoZk?si=otl0wj0sJONbJqZb\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen></iframe><h2>Learning Outcome</h2><p>Recognise that a magnet can exert a push or a pull and unlike poles attract and like poles repel.</p><p>Recognise that wood is not a magnetic material.</p><p>Recognise that iron is a magnetic material and it always attracts to a magnet.</p>"
                  }
                ]
              },
              {
                "Name": "description",
                "Type": "Panel",
                "Properties": [
                  {
                    "name": "Html",
                    "value": "<h2>Description</h2>\n<p><b>Object-focus hints:</b> Move the pointer over Magnet X, Y or Z, the wooden ring, or the iron ring. A blue panel explains what that particular object is doing, what to observe, and which force or magnetic idea explains it.</p>\n<p><b>Learning hints:</b> The yellow observation panel changes with the motion to identify gravity/free fall, magnetic attraction or repulsion, contact/collision, support and damped oscillation. Hide it with the checkbox if you want to predict first.</p>\n<p>This simulation shows the magnetism of different items in a plastic rod.</p>\n<p>On the left, there is a table of items where the user can click and drag the items to the dotted box labelled \"release here\".</p>\n<p>When an item is released on top of the plastic rod, the simulation will start and show its magnetism with regards to other items in the plastic rod.</p>\n<p>The user is able to flip the side of each magnets by clicking on the checkboxes at the top panel.</p>\n<p>The North-seeking pole of a magnet is coloured red, while the South-seeking pole of a magnet is coloured blue.</p>\n<p>In order to remove an item, the user will have to reset the whole setup by clicking the reset button.</p>\n<p></p>\n<p></p>\n"
                  }
                ]
              },
              {
                "Name": "controls",
                "Type": "Panel",
                "Properties": [
                  {
                    "name": "Html",
                    "value": "<h2>Controls</h2>\n<p>Play/Pause button starts and pauses the simulation.</p>\n<p>Next button forwards the simulation by one time step.</p>\n<p>Reset button puts the simulation back to its default state.</p>\n"
                  }
                ]
              }
            ]
          }
        ]
      }
    ],
    "RootProperties": []
  },
  "metadata": {
    "APP": "WebEJS",
    "CreatedWith": "WebEJS : The web version of Easy JavaScript Simulations",
    "MoreInfo": "WebEJS 1.1",
    "version": "https://www.um.es/fem/wikis/webejs/"
  }
}