| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8" /> |
| <meta name="viewport" content="width=device-width,initial-scale=1" /> |
| <title>Substrate Physics Translation Simulator v0.1</title> |
| <style> |
| :root{ |
| --bg:#07090d;--panel:#0f1420;--panel2:#121a2a;--ink:#eef5ff;--muted:#a9b6cc;--line:#263347; |
| --green:#49d17c;--yellow:#ffd166;--orange:#ff9f43;--red:#ff5c7a;--blue:#65b8ff;--violet:#a78bfa;--cyan:#58e6d9; |
| --shadow:0 18px 60px rgba(0,0,0,.35); |
| } |
| *{box-sizing:border-box} |
| body{ |
| margin:0;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:var(--ink); |
| background: |
| radial-gradient(circle at 10% 10%,rgba(101,184,255,.16),transparent 28%), |
| radial-gradient(circle at 86% 12%,rgba(167,139,250,.14),transparent 30%), |
| radial-gradient(circle at 50% 105%,rgba(88,230,217,.08),transparent 42%), |
| var(--bg); |
| } |
| header{ |
| padding:28px 24px 18px;border-bottom:1px solid var(--line); |
| background:linear-gradient(180deg,rgba(18,26,42,.94),rgba(7,9,13,.72)); |
| position:sticky;top:0;z-index:20;backdrop-filter:blur(12px); |
| } |
| .wrap{max-width:1480px;margin:0 auto} |
| h1{margin:0 0 6px;font-size:clamp(24px,3vw,42px);letter-spacing:-.04em} |
| .subtitle{color:var(--muted);font-size:15px;line-height:1.45;max-width:1120px} |
| .tagrow{display:flex;gap:8px;flex-wrap:wrap;margin-top:14px} |
| .tag{border:1px solid var(--line);background:rgba(255,255,255,.04);color:#dbeafe;padding:6px 9px;border-radius:999px;font-size:12px} |
| main{padding:22px 24px 34px} |
| .grid{display:grid;grid-template-columns:390px minmax(0,1fr) 420px;gap:18px;align-items:start} |
| .panel{ |
| background:linear-gradient(180deg,rgba(18,26,42,.96),rgba(15,20,32,.96)); |
| border:1px solid var(--line);border-radius:20px;box-shadow:var(--shadow);overflow:hidden; |
| } |
| .panel h2{margin:0;padding:16px 18px;border-bottom:1px solid var(--line);font-size:16px;letter-spacing:-.02em} |
| .body{padding:16px 18px} |
| label{display:block;font-size:12px;color:var(--muted);margin-bottom:8px} |
| select,button,textarea,input[type=text]{ |
| width:100%;border:1px solid var(--line);background:#0a0f19;color:var(--ink);border-radius:12px;padding:11px 12px;font-size:14px;outline:none; |
| } |
| textarea{min-height:105px;resize:vertical;line-height:1.4} |
| button{cursor:pointer;transition:.18s ease transform,.18s ease border-color,.18s ease background;font-weight:800} |
| button:hover{transform:translateY(-1px);border-color:#46658f;background:#0c1422} |
| button.primary{background:linear-gradient(135deg,#1f6feb,#5b8cff);border-color:#65b8ff} |
| button.good{background:linear-gradient(135deg,#116e43,#24a861);border-color:#49d17c} |
| button.warn{background:linear-gradient(135deg,#865b0b,#b98200);border-color:#ffd166} |
| .controls{display:grid;gap:14px} |
| .sliderRow{border:1px solid var(--line);border-radius:16px;padding:12px;background:rgba(255,255,255,.03)} |
| .sliderTop{display:flex;justify-content:space-between;gap:8px;align-items:center;margin-bottom:8px} |
| .sliderTop strong{font-size:13px} |
| .val{font-variant-numeric:tabular-nums;color:#dbeafe;font-size:12px} |
| input[type=range]{width:100%;accent-color:#65b8ff} |
| .hint{font-size:12px;color:var(--muted);line-height:1.35;margin-top:6px} |
| .buttons{display:grid;grid-template-columns:1fr 1fr;gap:10px} |
| .metricGrid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:18px} |
| .metric{background:rgba(255,255,255,.035);border:1px solid var(--line);border-radius:18px;padding:14px;min-height:104px} |
| .metric .name{font-size:12px;color:var(--muted)} |
| .metric .num{font-size:22px;font-weight:900;margin:4px 0;letter-spacing:-.03em;line-height:1.05} |
| .metric .desc{font-size:12px;color:var(--muted);line-height:1.35} |
| .output{display:grid;gap:14px} |
| .card{border:1px solid var(--line);border-radius:18px;background:rgba(255,255,255,.035);padding:14px} |
| .card h3{margin:0 0 8px;font-size:15px} |
| .card p{margin:0 0 10px;color:#dce8f7;line-height:1.48} |
| .card ul{margin:8px 0 0 20px;color:#dce8f7;line-height:1.45;padding:0} |
| .card li{margin:4px 0} |
| .small{font-size:12px;color:var(--muted);line-height:1.35} |
| .eq{ |
| font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;background:#080d15;border:1px solid var(--line);border-radius:18px; |
| padding:14px;color:#d8f3ff;margin-bottom:18px;line-height:1.55;overflow:auto; |
| } |
| .pill{display:inline-block;border:1px solid var(--line);border-radius:999px;padding:5px 8px;font-size:11px;font-weight:800;margin:3px 4px 3px 0} |
| .blue{color:var(--blue)}.green{color:var(--green)}.yellow{color:var(--yellow)}.orange{color:var(--orange)}.red{color:var(--red)}.violet{color:var(--violet)}.cyan{color:var(--cyan)} |
| #physicsCanvas{width:100%;height:180px;border:1px solid var(--line);border-radius:16px;background:#0a0f19;display:block} |
| .log{max-height:560px;overflow:auto;display:flex;flex-direction:column;gap:9px;padding-right:4px} |
| .logItem{border:1px solid var(--line);border-radius:14px;padding:10px 11px;background:rgba(255,255,255,.035)} |
| .logItem .time{font-size:11px;color:#8190a8;margin-bottom:5px} |
| .logItem .msg{font-size:12px;line-height:1.35;color:#dce8f7} |
| .footerNote{margin:18px auto 0;color:var(--muted);line-height:1.45;font-size:13px;border:1px solid var(--line);background:rgba(255,255,255,.03);border-radius:18px;padding:14px} |
| .descBox{font-size:12px;color:var(--muted);line-height:1.35;border:1px solid var(--line);border-radius:14px;padding:10px;background:rgba(255,255,255,.03);min-height:54px;margin-top:8px} |
| .previewBox{border:1px solid var(--line);border-radius:16px;padding:12px;background:rgba(255,255,255,.03)} |
| hr{border:0;border-top:1px solid var(--line);margin:10px 0} |
| @media(max-width:1240px){.grid{grid-template-columns:1fr}header{position:static}.metricGrid{grid-template-columns:repeat(2,1fr)}} |
| @media(max-width:760px){.metricGrid{grid-template-columns:1fr}.buttons{grid-template-columns:1fr}} |
| </style> |
| </head> |
| <body> |
| <header> |
| <div class="wrap"> |
| <h1>Substrate Physics Translation Simulator <span class="blue">v0.1</span></h1> |
| <div class="subtitle"> |
| A non-diagnostic learning translator that explains core physics concepts through different cognition styles. |
| Select a physics topic, choose an explanation route, tune support preferences, and generate a dignity-preserving explanation. |
| <br><strong>Physics stays physics. The translation route changes so the learner can meet it.</strong> |
| </div> |
| <div class="tagrow"> |
| <span class="tag">Physics translation, not replacement</span> |
| <span class="tag">Cognition-aware learning</span> |
| <span class="tag">No diagnosis</span> |
| <span class="tag">No forced closure</span> |
| <span class="tag">Substrate education layer</span> |
| </div> |
| </div> |
| </header> |
|
|
| <main> |
| <div class="wrap grid"> |
| <section class="panel"> |
| <h2>Learning Input</h2> |
| <div class="body controls"> |
| <div> |
| <label for="topic">Physics topic</label> |
| <select id="topic"></select> |
| <div id="topicDesc" class="descBox"></div> |
| </div> |
|
|
| <div> |
| <label for="mode">Cognition / explanation mode</label> |
| <select id="mode"></select> |
| <div id="modeDesc" class="descBox"></div> |
| </div> |
|
|
| <div> |
| <label for="selfDesc">Optional learner note</label> |
| <textarea id="selfDesc" placeholder="Example: I need concrete examples first. I get lost if equations come before the picture. I like the proof boundaries clearly marked."></textarea> |
| <div class="hint">Self-described support only. This is not diagnosis or assessment.</div> |
| </div> |
|
|
| <div class="sliderRow"> |
| <div class="sliderTop"><strong>Abstraction Tolerance</strong><span class="val" id="vAbs"></span></div> |
| <input id="abstraction" type="range" min="0" max="1" step="0.01" value="0.52"> |
| <div class="hint">Lower = concrete first. Higher = theory first.</div> |
| </div> |
|
|
| <div class="sliderRow"> |
| <div class="sliderTop"><strong>Example Need</strong><span class="val" id="vEx"></span></div> |
| <input id="examples" type="range" min="0" max="1" step="0.01" value="0.76"> |
| <div class="hint">How much the explanation should lean on everyday examples.</div> |
| </div> |
|
|
| <div class="sliderRow"> |
| <div class="sliderTop"><strong>Equation Density</strong><span class="val" id="vEq"></span></div> |
| <input id="equation" type="range" min="0" max="1" step="0.01" value="0.46"> |
| <div class="hint">Controls how much formula language appears.</div> |
| </div> |
|
|
| <div class="sliderRow"> |
| <div class="sliderTop"><strong>Metaphor Density</strong><span class="val" id="vMet"></span></div> |
| <input id="metaphor" type="range" min="0" max="1" step="0.01" value="0.60"> |
| <div class="hint">Controls analogy, imagery, and story language.</div> |
| </div> |
|
|
| <div class="sliderRow"> |
| <div class="sliderTop"><strong>Pacing / Scaffold</strong><span class="val" id="vPace"></span></div> |
| <input id="pacing" type="range" min="0" max="1" step="0.01" value="0.72"> |
| <div class="hint">Higher = slower sequencing and more definitions.</div> |
| </div> |
|
|
| <div class="buttons"> |
| <button class="primary" id="generateBtn">Generate Physics Translation</button> |
| <button id="randomBtn">Try Sample Learner</button> |
| </div> |
|
|
| <div class="buttons"> |
| <button class="good" id="exportJSON">Export JSON</button> |
| <button class="warn" id="copyBtn">Copy Output</button> |
| </div> |
| </div> |
| </section> |
|
|
| <section> |
| <div class="metricGrid"> |
| <div class="metric"> |
| <div class="name">Learning Accessibility</div> |
| <div class="num" id="accessScore">0.00</div> |
| <div class="desc">How well supports match the chosen cognition route.</div> |
| </div> |
| <div class="metric"> |
| <div class="name">Understanding Layer</div> |
| <div class="num" id="closureState">FIRST PASS</div> |
| <div class="desc">Whether the output targets intuition, working model, or formal layer.</div> |
| </div> |
| <div class="metric"> |
| <div class="name">Translation Route</div> |
| <div class="num" id="routeName">—</div> |
| <div class="desc">The cognitive route used for this explanation.</div> |
| </div> |
| </div> |
|
|
| <div class="eq"> |
| <div><strong>Physics translation pressure form:</strong></div> |
| <div>S_learning,t = A_translation,t × B_physics,t − P_mismatch,t</div> |
| <div><strong>Rule:</strong> preserve the physics, adapt the explanation route.</div> |
| <hr> |
| <div id="liveEq"></div> |
| <div id="formulaLine" style="margin-top:8px;color:#eef5ff"></div> |
| </div> |
|
|
| <div class="panel" style="margin-bottom:18px"> |
| <h2>Physics Signal Field</h2> |
| <div class="body"> |
| <canvas id="physicsCanvas" width="760" height="200"></canvas> |
| <div class="hint" style="text-align:center;margin-top:10px"> |
| Concept = signal · Cognition route = receiver geometry · Translation = coupling path. |
| </div> |
| </div> |
| </div> |
|
|
| <div class="panel"> |
| <h2>Generated Physics Explanation</h2> |
| <div class="body output" id="output"></div> |
| </div> |
|
|
| <div class="footerNote"> |
| <strong>Boundary statement:</strong> This simulator is an educational translation prototype. It does not replace textbooks, |
| labs, teachers, formal derivations, or domain expertise. It does not diagnose cognition or rank intelligence. |
| It adapts explanations so physics concepts can become more readable across cognition styles. |
| </div> |
| </section> |
|
|
| <aside class="panel"> |
| <h2>Learning Steward Log</h2> |
| <div class="body"> |
| <div class="previewBox" style="margin-bottom:12px"> |
| <div class="small"><strong>Steward function:</strong> preserve the concept, translate the route, mark uncertainty, and prevent confusion from being treated as failure.</div> |
| </div> |
| <div class="log" id="log"></div> |
| </div> |
| </aside> |
| </div> |
| </main> |
|
|
| <footer class="footerNote wrap"> |
| <strong>Substrate education principle:</strong> A learner should not be made to feel stupid because the explanation arrives in the wrong format. |
| The format should adapt while the physics remains honest. |
| </footer> |
|
|
| <script> |
| const modes = { |
| visual_map:{label:"Visual / map-based",route:"VISUAL_MAP",desc:"Prefers diagrams, spatial layout, layers, arrows, and seeing how parts connect.",bias:{abstraction:.55,examples:.70,equation:.35,metaphor:.72,pacing:.62}}, |
| concrete_examples:{label:"Concrete examples first",route:"CONCRETE_EXAMPLES",desc:"Prefers ordinary-life examples before theory.",bias:{abstraction:.28,examples:.94,equation:.25,metaphor:.52,pacing:.78}}, |
| technical_math:{label:"Technical / math-forward",route:"TECHNICAL_MATH",desc:"Prefers equations, units, variables, derivation hints, and formal relationships.",bias:{abstraction:.86,examples:.46,equation:.92,metaphor:.20,pacing:.46}}, |
| story_metaphor:{label:"Story / metaphor",route:"STORY_METAPHOR",desc:"Prefers image-rich explanation, analogies, and narrative movement.",bias:{abstraction:.48,examples:.68,equation:.22,metaphor:.94,pacing:.68}}, |
| stepwise_literal:{label:"Stepwise / literal",route:"STEPWISE_LITERAL",desc:"Prefers definitions, direct sequencing, and one idea at a time.",bias:{abstraction:.34,examples:.80,equation:.44,metaphor:.18,pacing:.95}}, |
| fast_associative:{label:"Fast associative / pattern-jump",route:"FAST_ASSOCIATIVE",desc:"Prefers rapid links across topics and seeing the whole field quickly.",bias:{abstraction:.78,examples:.60,equation:.56,metaphor:.82,pacing:.26}}, |
| skeptical_redteam:{label:"Skeptical / red-team",route:"SKEPTICAL_REDTEAM",desc:"Prefers boundaries, failure modes, misconception checks, and what the model cannot claim.",bias:{abstraction:.66,examples:.62,equation:.62,metaphor:.22,pacing:.58}}, |
| lived_context:{label:"Lived-context / practical stakes",route:"LIVED_CONTEXT",desc:"Prefers human-scale consequences, practical stakes, agency, safety, and real-world meaning.",bias:{abstraction:.42,examples:.88,equation:.28,metaphor:.70,pacing:.78}}, |
| teacher_scaffold:{label:"Teacher / scaffolded lesson",route:"TEACHER_SCAFFOLD",desc:"Prefers objective, definitions, examples, check-for-understanding, and takeaway.",bias:{abstraction:.48,examples:.84,equation:.46,metaphor:.44,pacing:.88}} |
| }; |
| |
| const topics = { |
| motion:{ |
| label:"Motion", |
| desc:"How position, velocity, and acceleration describe change over time.", |
| formula:"v = Δx / Δt ; a = Δv / Δt", |
| plain:"Motion is how an object's position changes over time. Velocity says how fast position changes. Acceleration says how fast velocity changes.", |
| example:"A car speeding up from a stop is changing velocity, so it is accelerating.", |
| misconception:"Speed and acceleration are not the same. You can move fast with zero acceleration if your velocity is steady." |
| }, |
| forces:{ |
| label:"Forces", |
| desc:"How pushes and pulls change motion.", |
| formula:"F = m a", |
| plain:"A force is an interaction that can change motion. More mass needs more force for the same acceleration.", |
| example:"An empty shopping cart is easier to accelerate than a full one because the full cart has more mass.", |
| misconception:"Force is not the same as motion. An object can keep moving even when no net force is acting on it." |
| }, |
| energy:{ |
| label:"Energy", |
| desc:"How systems store, transfer, and transform the ability to do work.", |
| formula:"K = ½ m v² ; ΔE_system = energy in − energy out", |
| plain:"Energy is a conserved accounting system for change. It can move or transform, but it is not created from nothing inside a closed system.", |
| example:"A roller coaster trades gravitational potential energy for kinetic energy as it drops.", |
| misconception:"Energy is not a vague feeling in physics. It is a measurable quantity with units and conservation rules." |
| }, |
| heat:{ |
| label:"Heat / thermal energy", |
| desc:"How thermal energy transfers because of temperature differences.", |
| formula:"Q = m c ΔT", |
| plain:"Heat is energy transferred because of a temperature difference. Temperature describes average microscopic motion; heat describes transfer.", |
| example:"A hot mug warms your hand because energy flows from the hotter mug to the cooler hand.", |
| misconception:"Heat and temperature are related, but not identical. A bathtub of warm water can contain more thermal energy than a tiny spark at higher temperature." |
| }, |
| waves:{ |
| label:"Waves", |
| desc:"How disturbances carry energy and information through space or a medium.", |
| formula:"v = f λ", |
| plain:"A wave is a repeating disturbance that transfers energy without requiring the material itself to travel the whole distance.", |
| example:"A stadium wave moves around the arena, but each person mostly moves up and down.", |
| misconception:"The wave pattern can move while the medium mostly oscillates locally." |
| }, |
| electricity:{ |
| label:"Electricity", |
| desc:"How charge, voltage, current, resistance, and fields relate.", |
| formula:"V = I R ; P = I V", |
| plain:"Electricity involves charge behavior organized by electric fields. Voltage pushes, current flows, resistance limits, and power measures energy transfer rate.", |
| example:"A lamp turns electrical energy into light and heat when current moves through its circuit.", |
| misconception:"Electricity is not just tiny stuff flowing inside a wire; the surrounding electromagnetic field is part of the energy transfer story." |
| }, |
| light:{ |
| label:"Light", |
| desc:"How electromagnetic radiation carries energy and information.", |
| formula:"c = f λ ; E = h f", |
| plain:"Light is electromagnetic radiation. It behaves like waves in many situations and exchanges energy in quantized packets called photons.", |
| example:"Blue light has higher frequency than red light, so each photon carries more energy.", |
| misconception:"Light is not simply particles or simply waves. Which model is useful depends on the experiment." |
| }, |
| gravity:{ |
| label:"Gravity", |
| desc:"How mass-energy shapes motion and attraction.", |
| formula:"F = G m₁m₂ / r² ; near Earth: W = m g", |
| plain:"Gravity is the interaction that makes masses attract in Newton's model. Near Earth, weight is the gravitational force on mass.", |
| example:"You weigh less on the Moon because the Moon's gravitational field at the surface is weaker than Earth's.", |
| misconception:"Mass and weight are not the same. Mass is how much matter/inertia; weight is gravitational force." |
| }, |
| quantum:{ |
| label:"Quantum basics", |
| desc:"How very small systems require probability, quantization, and measurement-aware models.", |
| formula:"E = h f ; Δx Δp ≥ ℏ / 2", |
| plain:"Quantum physics describes systems where energy, measurement, probability, and state cannot always be treated like everyday objects with definite classical properties.", |
| example:"An electron in an atom can occupy allowed energy levels rather than any arbitrary energy.", |
| misconception:"Quantum does not mean magic or anything-goes. It has strict math, predictions, and experimental boundaries." |
| } |
| }; |
| |
| const ids=["abstraction","examples","equation","metaphor","pacing"]; |
| const els=Object.fromEntries(ids.map(id=>[id,document.getElementById(id)])); |
| let lastRecord=null, logRecords=[], phase=0; |
| |
| function fmt(n){return Number(n).toFixed(2)} |
| function iso(){return new Date().toISOString()} |
| function now(){return new Date().toLocaleTimeString([], {hour:"2-digit",minute:"2-digit",second:"2-digit"})} |
| |
| function initSelects(){ |
| const topicSel=document.getElementById("topic"); |
| Object.entries(topics).forEach(([k,t])=>{ |
| const opt=document.createElement("option"); opt.value=k; opt.textContent=t.label; opt.title=t.desc; topicSel.appendChild(opt); |
| }); |
| topicSel.value="forces"; |
| const modeSel=document.getElementById("mode"); |
| Object.entries(modes).forEach(([k,m])=>{ |
| const opt=document.createElement("option"); opt.value=k; opt.textContent=m.label; opt.title=m.desc; modeSel.appendChild(opt); |
| }); |
| modeSel.value="visual_map"; |
| updateDescriptions(); |
| } |
| function updateDescriptions(){ |
| const t=topics[document.getElementById("topic").value]; |
| const m=modes[document.getElementById("mode").value]; |
| document.getElementById("topicDesc").textContent=t.desc; |
| document.getElementById("modeDesc").textContent=m.desc; |
| } |
| function updateLabels(){ |
| document.getElementById("vAbs").textContent=fmt(els.abstraction.value); |
| document.getElementById("vEx").textContent=fmt(els.examples.value); |
| document.getElementById("vEq").textContent=fmt(els.equation.value); |
| document.getElementById("vMet").textContent=fmt(els.metaphor.value); |
| document.getElementById("vPace").textContent=fmt(els.pacing.value); |
| } |
| function getState(){ |
| const topic=document.getElementById("topic").value; |
| const mode=document.getElementById("mode").value; |
| return { |
| topic, topicLabel:topics[topic].label, |
| mode, modeLabel:modes[mode].label, |
| learnerNote:document.getElementById("selfDesc").value.trim(), |
| abstraction:parseFloat(els.abstraction.value), |
| examples:parseFloat(els.examples.value), |
| equation:parseFloat(els.equation.value), |
| metaphor:parseFloat(els.metaphor.value), |
| pacing:parseFloat(els.pacing.value) |
| }; |
| } |
| function score(s){ |
| const b=modes[s.mode].bias; |
| let dist=0; ids.forEach(k=>dist+=Math.abs(s[k]-b[k])); |
| const match=Math.max(0,1-dist/5); |
| const A_translation=match; |
| const B_physics=.88; |
| const P_mismatch=(1-match)*.62; |
| const S=(A_translation*B_physics)-P_mismatch; |
| return {match,A_translation,B_physics,P_mismatch,S}; |
| } |
| function layer(S){ |
| if(S>.62)return ["FORMAL_READY","FORMAL + INTUITIVE"]; |
| if(S>.44)return ["WORKING_MODEL","WORKING MODEL"]; |
| if(S>.22)return ["FIRST_PASS","FIRST PASS"]; |
| return ["OPEN_LOOP","NEEDS RETRANSLATION"]; |
| } |
| function addLog(msg){ |
| const item=document.createElement("div"); item.className="logItem"; |
| const t=now(); |
| item.innerHTML=`<div class="time">${t}</div><div class="msg">${msg}</div>`; |
| document.getElementById("log").prepend(item); |
| logRecords.push({timestamp:iso(),displayTime:t,message:msg}); |
| } |
| function generate(){ |
| const s=getState(), t=topics[s.topic], m=modes[s.mode], sc=score(s), [closure, layerName]=layer(sc.S); |
| document.getElementById("accessScore").textContent=fmt(sc.match); |
| document.getElementById("accessScore").style.color=sc.match>.75?"var(--green)":sc.match>.55?"var(--yellow)":"var(--orange)"; |
| document.getElementById("closureState").textContent=layerName; |
| document.getElementById("closureState").style.color=layerName.includes("FORMAL")?"var(--green)":layerName==="WORKING MODEL"?"var(--yellow)":"var(--orange)"; |
| document.getElementById("routeName").textContent=m.route; |
| document.getElementById("routeName").style.color="var(--blue)"; |
| document.getElementById("liveEq").innerHTML=`S_learning,t = (${fmt(sc.A_translation)} × ${fmt(sc.B_physics)}) − ${fmt(sc.P_mismatch)} ≈ <strong>${fmt(sc.S)}</strong>`; |
| document.getElementById("formulaLine").innerHTML=`Topic formula: <strong>${t.formula}</strong>`; |
| const out=buildOutput(s,t,m,sc,layerName); |
| renderOutput(out); |
| lastRecord={metadata:{title:"Substrate Physics Translation Simulator",version:"v0.1",timestamp:iso(),boundary:"Educational translation prototype; not diagnosis or replacement for formal instruction."},state:s,metrics:sc,understandingLayer:layerName,output:out}; |
| addLog(`Generated ${t.label} through ${m.route}: ${layerName}. Concept preserved; route adapted.`); |
| draw(); |
| } |
| function buildOutput(s,t,m,sc,layerName){ |
| return { |
| topic:t.label, mode:m.label, route:m.route, understandingLayer:layerName, |
| sections:[ |
| {title:"1. Main idea", text:modeIntro(s,t)}, |
| {title:"2. Physics relationship", text:relationshipText(s,t)}, |
| {title:"3. How to picture it", text:pictureText(s,t)}, |
| {title:"4. Everyday example", text:exampleText(s,t)}, |
| {title:"5. Misconception guardrail", text:guardrailText(s,t)}, |
| {title:"6. Check-for-understanding", text:checkText(s,t)}, |
| {title:"7. Closure boundary", text:closureText(layerName)} |
| ], |
| supports:supports(s,sc) |
| }; |
| } |
| function modeIntro(s,t){ |
| const map={ |
| visual_map:`Map it as a field: the concept is the center node, the formula is the spine, examples are the outer nodes, and the misconception is the boundary marker. For ${t.label}, the map starts here: ${t.plain}`, |
| concrete_examples:`Start with the real-world version: ${t.example} From there, the physics idea is: ${t.plain}`, |
| technical_math:`Formal read: ${t.formula}. The concept is ${t.label}. The plain-language interpretation is: ${t.plain}`, |
| story_metaphor:`Imagine the concept as a character crossing a landscape of cause and effect. For ${t.label}, the path is: ${t.plain}`, |
| stepwise_literal:`Step 1: the topic is ${t.label}. Step 2: the core relationship is ${t.formula}. Step 3: the meaning is: ${t.plain}`, |
| fast_associative:`Pattern bridge: ${t.label} links formula, field, transfer, constraint, and measurement. Core: ${t.plain}`, |
| skeptical_redteam:`Bounded claim: this explanation gives a first-pass model of ${t.label}, not the whole discipline. The formula ${t.formula} is useful inside its assumptions. Core: ${t.plain}`, |
| lived_context:`Human-scale read: ${t.label} matters because it changes what we can build, predict, repair, or stay safe around. The core idea is: ${t.plain}`, |
| teacher_scaffold:`Learning objective: explain ${t.label} in plain language and connect it to ${t.formula}. Main idea: ${t.plain}` |
| }; |
| return map[s.mode]; |
| } |
| function relationshipText(s,t){ |
| let text=`The key relationship is ${t.formula}. `; |
| if(s.equation>.65) text+=`Read the symbols as a compact map of dependency: change one variable and the system response changes according to the relationship. `; |
| else text+=`You do not have to start by solving it. First, treat it as a sentence that says which quantities depend on each other. `; |
| if(s.pacing>.72) text+=`Name the quantities before using the formula. Then ask what changes, what stays fixed, and what the units mean.`; |
| return text; |
| } |
| function pictureText(s,t){ |
| if(s.mode==="visual_map") return `Draw ${t.label} as arrows and boundaries. Label the source, the object/system, the interaction, and the measured result. Put the formula on the spine of the map.`; |
| if(s.mode==="story_metaphor") return `Picture ${t.label} as a transfer story: something acts, something responds, and the formula tracks what remains consistent.`; |
| if(s.mode==="technical_math") return `Picture it as a state relation: variables constrain possible system behavior. The diagram is secondary to the dependency structure.`; |
| return `Picture the system first, then attach the formula. The picture prevents the equation from floating without meaning.`; |
| } |
| function exampleText(s,t){ |
| let text=t.example; |
| if(s.examples>.72) text+=` Ask: what is the system, what is changing, and what quantity would I measure?`; |
| if(s.metaphor>.72) text+=` The example is a bridge, not the full territory: use it to enter the concept, then return to the physics.`; |
| return text; |
| } |
| function guardrailText(s,t){ |
| let text=t.misconception; |
| if(s.mode==="skeptical_redteam") text+=` Red-team rule: do not apply the formula outside the assumptions that make it valid.`; |
| if(s.pacing>.72) text+=` This is where the loop should stay open until the distinction is clear.`; |
| return text; |
| } |
| function checkText(s,t){ |
| const checks={ |
| motion:"If a car moves at constant speed in a straight line, is it accelerating?", |
| forces:"If an object is moving, does that automatically mean a net force is acting on it right now?", |
| energy:"When a roller coaster drops, what energy store decreases and what energy store increases?", |
| heat:"Can two objects have the same temperature but different total thermal energy?", |
| waves:"In a stadium wave, does each person travel around the stadium?", |
| electricity:"What is the difference between voltage, current, and resistance in one sentence each?", |
| light:"Why can red and blue light behave similarly as waves but carry different photon energies?", |
| gravity:"How are mass and weight different?", |
| quantum:"Why does quantum uncertainty not mean anything can happen?" |
| }; |
| return checks[s.topic] || "Can you explain the topic without using the formula first?"; |
| } |
| function closureText(layerName){ |
| if(layerName.includes("FORMAL")) return "This translation can close at both the first-pass and working-model layers. Formal proof still remains open to textbook/lab validation."; |
| if(layerName==="WORKING MODEL") return "This translation can close as a working model. Keep the formal derivation layer open."; |
| if(layerName==="FIRST PASS") return "This translation can close as a first-pass explanation. Keep examples, units, and formal problem-solving open."; |
| return "This loop should remain open. The explanation route needs retranslation before claiming understanding."; |
| } |
| function supports(s,sc){ |
| const arr=[]; |
| if(s.examples>.65) arr.push("Use an everyday example before the formula."); |
| if(s.pacing>.70) arr.push("Define each variable and unit before solving."); |
| if(s.equation>.60) arr.push("Show equation structure and assumptions."); |
| if(s.metaphor>.65) arr.push("Use analogy, but mark where the analogy stops."); |
| if(s.abstraction>.70) arr.push("Give the general law before the example."); |
| if(sc.P_mismatch>.25) arr.push("Mismatch pressure remains: do not force closure; try another route."); |
| arr.push("Confusion is not failure. It is a signal that the explanation route may need adjustment."); |
| return arr; |
| } |
| function renderOutput(o){ |
| const box=document.getElementById("output"); box.innerHTML=""; |
| const head=document.createElement("div"); head.className="card"; |
| head.innerHTML=`<h3>${o.topic} via <span class="blue">${o.route}</span></h3> |
| <p><strong>Selected mode:</strong> ${o.mode}</p> |
| <p><strong>Understanding layer:</strong> ${o.understandingLayer}. This is an explanation route, not a learner diagnosis.</p>`; |
| box.appendChild(head); |
| o.sections.forEach(sec=>{ |
| const div=document.createElement("div"); div.className="card"; |
| div.innerHTML=`<h3>${sec.title}</h3><p>${sec.text}</p>`; |
| box.appendChild(div); |
| }); |
| const sup=document.createElement("div"); sup.className="card"; |
| sup.innerHTML=`<h3>Recommended supports</h3><ul>${o.supports.map(x=>`<li>${x}</li>`).join("")}</ul>`; |
| box.appendChild(sup); |
| } |
| function copyOutput(){ |
| if(!lastRecord)generate(); |
| const lines=[]; |
| lines.push("Substrate Physics Translation Simulator v0.1"); |
| lines.push(`Topic: ${lastRecord.output.topic}`); |
| lines.push(`Mode: ${lastRecord.output.mode}`); |
| lines.push(`Route: ${lastRecord.output.route}`); |
| lines.push(`Understanding layer: ${lastRecord.output.understandingLayer}`); |
| lines.push(""); |
| lastRecord.output.sections.forEach(s=>{lines.push(s.title);lines.push(s.text);lines.push("");}); |
| lines.push("Recommended supports:"); |
| lastRecord.output.supports.forEach(x=>lines.push("- "+x)); |
| navigator.clipboard.writeText(lines.join("\n")).then(()=>addLog("Copied generated physics translation to clipboard.")); |
| } |
| function exportJSON(){ |
| if(!lastRecord)generate(); |
| const data={...lastRecord, steward_log:logRecords}; |
| const blob=new Blob([JSON.stringify(data,null,2)],{type:"application/json"}); |
| const url=URL.createObjectURL(blob); |
| const a=document.createElement("a"); a.href=url; a.download=`substrate-physics-translation-${Date.now()}.json`; |
| document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(url); |
| } |
| function trySample(){ |
| const modeKeys=Object.keys(modes), topicKeys=Object.keys(topics); |
| const mk=modeKeys[Math.floor(Math.random()*modeKeys.length)]; |
| const tk=topicKeys[Math.floor(Math.random()*topicKeys.length)]; |
| document.getElementById("mode").value=mk; document.getElementById("topic").value=tk; |
| const b=modes[mk].bias; ids.forEach(id=>els[id].value=b[id]); |
| const samples=[ |
| "I need the picture before the equation.", |
| "I trust the equation when I know its assumptions.", |
| "Examples first, then the formal rule.", |
| "I move quickly across patterns and need the whole map.", |
| "Please slow it down and define the words before combining them." |
| ]; |
| document.getElementById("selfDesc").value=samples[Math.floor(Math.random()*samples.length)]; |
| updateLabels(); updateDescriptions(); generate(); |
| } |
| function draw(){ |
| const c=document.getElementById("physicsCanvas"), ctx=c.getContext("2d"), w=c.width,h=c.height; |
| const s=getState(), sc=score(s), t=topics[s.topic]; |
| phase+=.035; |
| ctx.clearRect(0,0,w,h); |
| const bg=ctx.createLinearGradient(0,0,w,h); bg.addColorStop(0,"#080d15"); bg.addColorStop(1,"#0f1420"); ctx.fillStyle=bg; ctx.fillRect(0,0,w,h); |
| const color=sc.S>.62?"#49d17c":sc.S>.44?"#ffd166":sc.S>.22?"#ff9f43":"#ff5c7a"; |
| const yMid=h*.56, amp=10+(1-sc.match)*42; |
| for(let layer=0;layer<4;layer++){ |
| ctx.beginPath(); |
| for(let x=0;x<=w;x+=5){ |
| const y=yMid+Math.sin((x+phase*90+layer*25)/(45-layer*4))*(amp*(1-layer*.14)); |
| if(x===0)ctx.moveTo(x,y); else ctx.lineTo(x,y); |
| } |
| ctx.strokeStyle=layer===0?color:`rgba(101,184,255,${.12+layer*.05})`; |
| ctx.lineWidth=layer===0?2.8:1.2; ctx.stroke(); |
| } |
| const nodes=["concept","formula","example","units","misconception","check","closure"]; |
| nodes.forEach((n,i)=>{ |
| const x=58+i*(w-116)/(nodes.length-1); |
| const y=yMid+Math.sin((x+phase*90)/45)*amp; |
| ctx.beginPath(); ctx.arc(x,y,6+s.examples*3,0,Math.PI*2); |
| ctx.fillStyle=`rgba(88,230,217,${.28+s.pacing*.34})`; ctx.fill(); |
| ctx.strokeStyle=color; ctx.lineWidth=1.5; ctx.stroke(); |
| ctx.fillStyle="rgba(238,245,255,.72)"; ctx.font="11px ui-monospace,monospace"; ctx.textAlign="center"; ctx.fillText(n,x,y-14); |
| }); |
| ctx.fillStyle="rgba(238,245,255,.84)"; ctx.font="12px ui-monospace,monospace"; ctx.textAlign="center"; |
| ctx.fillText(`${t.label}: ${t.formula}`,w/2,32); |
| ctx.fillText(`S_learning ≈ ${fmt(sc.S)} · route match ${fmt(sc.match)}`,w/2,52); |
| } |
| function loop(){draw();requestAnimationFrame(loop);} |
| |
| ids.forEach(id=>els[id].addEventListener("input",()=>{updateLabels();generate();})); |
| document.getElementById("topic").addEventListener("change",()=>{updateDescriptions();generate();}); |
| document.getElementById("mode").addEventListener("change",()=>{updateDescriptions();generate();}); |
| document.getElementById("generateBtn").addEventListener("click",generate); |
| document.getElementById("randomBtn").addEventListener("click",trySample); |
| document.getElementById("copyBtn").addEventListener("click",copyOutput); |
| document.getElementById("exportJSON").addEventListener("click",exportJSON); |
| |
| initSelects(); updateLabels(); |
| addLog("Simulator initialized. Physics concept preserved; cognition route adapted."); |
| generate(); loop(); |
| </script> |
| </body> |
| </html> |
|
|