PHYSIQUE BTS FED
ACTIVITÉ CALCULS DE CHALEUR
ENTRER
ACTIVITÉ CALCULS DE CHALEUR
Quel est ton prénom ?
suivant
§classe§: *2
C'est parti !
Quelle est ta classe ?
§nom§: *3
* ATTENTION : ce prénom sera écrit sur ton diplôme à la fin
1. LE RÉCHAUFFEMENT
?$CAL1|=|1
?$CALEX1|=|1&CALEX2|=|1&CALEX3|=|1&CALEX4|=|1&CAL1|=|1&CAL2|=|1&CAL3|=|1
Bravo
CLIQUER POUR VOIR LE DIPLÔME
2. LE CHANGEMENT D'ÉTAT
?$CAL2|=|1
3. MESURES de la CHALEUR TOTALE
?$CAL3|=|1
4. EXERCICES
?$CALEX1|=|1&CALEX2|=|1&CALEX3|=|1&CALEX4|=|1
FORMULES
$CAL1|=|1
Elle dépend de :
$CAL2|=|1
<div id="universal-sim-v29-data" style="width: 100%; max-width: 1265px; background: #ffffff; border: 1px solid #ccc; border-radius: 18px; padding: 30px; font-family: 'Segoe UI', sans-serif; color: #333; margin: auto; box-sizing: border-box;">
<div style="display: flex; flex-wrap: wrap; gap: 30px; justify-content: center;">
<div style="flex: 1.4; min-width: 450px; text-align: center; display: flex; flex-direction: column; gap: 20px;">
<canvas id="beakerCanvas" width="460" height="380" style="border: 2px solid #999; background: #fff; border-radius: 12px; width: 100%; height: auto;"></canvas>
<canvas id="graphCanvas" width="460" height="350" style="border: 1px solid #ccc; background: #fafafa; border-radius: 10px; width: 100%; height: auto;"></canvas>
</div>
<div style="flex: 1.6; min-width: 370px; display: flex; flex-direction: column; gap: 15px;">
<div style="display: flex; gap: 10px;">
<select id="substance_select" onchange="initSubstance()" style="flex: 3; padding: 12px; border-radius: 10px; border: 2px solid #333; font-weight: bold; font-size: 1.1em; cursor: pointer;">
<option value="eau" selected>Eau (H₂O)</option>
<option value="ammoniac">Ammoniac (NH₃)</option>
<option value="isobutane">Isobutane (C₄H₁₀)</option>
<option value="r32">R32 (Difluorométhane)</option>
<option value="r1234yf">R1234yf (Tétrafluoropropène)</option>
</select>
<button id="unitBtn" onclick="toggleUnit()" style="flex: 1; padding: 10px; border-radius: 10px; border: 2px solid #333; background: #333; color: white; font-weight: bold; cursor: pointer;">UNITÉ : °C</button>
</div>
<div id="dataPanel" style="background: #f1f8e9; border: 1px solid #c5e1a5; border-radius: 12px; padding: 12px; font-size: 0.9em;">
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; text-align: center;">
<div><small>c<sub>s</sub></small><br><strong id="val_cs">-</strong> <small>J/kg·K</small></div>
<div><small>c<sub>l</sub></small><br><strong id="val_cl">-</strong> <small>J/kg·K</small></div>
<div><small>c<sub>g</sub></small><br><strong id="val_cg">-</strong> <small>J/kg·K</small></div>
<div style="border-top: 1px solid #c5e1a5; padding-top: 5px;"><small>L<sub>f</sub></small><br><strong id="val_lf">-</strong> <small>kJ/kg</small></div>
<div style="border-top: 1px solid #c5e1a5; padding-top: 5px;"><small>L<sub>v</sub></small><br><strong id="val_lv">-</strong> <small>kJ/kg</small></div>
<div style="border-top: 1px solid #c5e1a5; padding-top: 5px;"><small>T<sub>f</sub> / T<sub>vap</sub></small><br><strong id="val_temps">-</strong></div>
</div>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: #eee; padding: 10px; border-radius: 12px;">
<div style="text-align:center;">
<label style="font-size: 0.8em; font-weight: bold;">T. INITIALE (<span class="unitLabel">°C</span>)</label><br>
<input type="number" id="t_start_val" value="-150" min="-273.15" step="10" onchange="checkAbsoluteZero(this)" style="width: 80%; padding: 8px; font-weight: bold; text-align: center; border-radius: 5px; border: 1px solid #999;">
</div>
<div style="text-align:center;">
<label style="font-size: 0.8em; font-weight: bold;">T. FINALE (<span class="unitLabel">°C</span>)</label><br>
<input type="number" id="t_end_val" value="150" min="-272" step="10" style="width: 80%; padding: 8px; font-weight: bold; text-align: center; border-radius: 5px; border: 1px solid #999;">
</div>
</div>
<div id="tempDisp" style="font-size: 3.5em; font-weight: bold; text-align: center; border-radius: 15px; padding: 10px; border: 4px solid #ccc; background: #f8f9fa;">0.0 °C</div>
<div style="background: #fdfdfd; padding: 15px; border-radius: 15px; border: 1px solid #ddd;">
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 15px;">
<div>Masse : <input type="number" id="m_val" value="1.0" min="0.1" max="50" step="0.5" style="width: 65px; font-weight: bold; padding: 5px;"> <strong>kg</strong></div>
<div>Puissance : <input type="number" id="p_val" value="2000" min="500" max="10000" step="500" style="width: 80px; font-weight: bold; padding: 5px;"> <strong>W</strong></div>
</div>
<div style="display: flex; gap: 15px; align-items: center;">
<select id="speed_select" style="flex:1; padding: 10px; border-radius: 6px; font-weight: bold;">
<option value="4">Lent</option>
<option value="15" selected>Normal</option>
<option value="100">Rapide</option>
</select>
<button id="mainBtn" onclick="handleBtn()" style="flex:1.5; padding: 15px; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 1.1em; text-transform: uppercase;">DÉMARRER</button>
</div>
</div>
<div id="formulas" style="font-size: 1.05em; display: flex; flex-direction: column; gap: 8px;">
<div id="f1" style="padding: 10px; border-left: 6px solid #ccc; background: #fff; border-radius: 6px; position: relative;"><span class="step-arrow" style="position: absolute; left: -25px; color: #d32f2f; display: none;">➤</span><strong>1. Chauffage Solide :</strong> Q = m · cₛ · ΔT <span id="d1" style="color:#d32f2f; font-weight:bold; float:right;"></span></div>
<div id="f2" style="padding: 10px; border-left: 6px solid #ccc; background: #fff; border-radius: 6px; position: relative;"><span class="step-arrow" style="position: absolute; left: -25px; color: #d32f2f; display: none;">➤</span><strong>2. Fusion :</strong> Q = m · Lբ <span id="d2" style="color:#d32f2f; font-weight:bold; float:right;"></span></div>
<div id="f3" style="padding: 10px; border-left: 6px solid #ccc; background: #fff; border-radius: 6px; position: relative;"><span class="step-arrow" style="position: absolute; left: -25px; color: #d32f2f; display: none;">➤</span><strong>3. Chauffage Liquide :</strong> Q = m · cₗ · ΔT <span id="d3" style="color:#d32f2f; font-weight:bold; float:right;"></span></div>
<div id="f4" style="padding: 10px; border-left: 6px solid #ccc; background: #fff; border-radius: 6px; position: relative;"><span class="step-arrow" style="position: absolute; left: -25px; color: #d32f2f; display: none;">➤</span><strong>4. Vaporisation :</strong> Q = m · Lᵥ <span id="d4" style="color:#d32f2f; font-weight:bold; float:right;"></span></div>
<div id="f5" style="padding: 10px; border-left: 6px solid #ccc; background: #fff; border-radius: 6px; position: relative;"><span class="step-arrow" style="position: absolute; left: -25px; color: #d32f2f; display: none;">➤</span><strong>5. Chauffage Gaz :</strong> Q = m · cₚ · ΔT <span id="d5" style="color:#d32f2f; font-weight:bold; float:right;"></span></div>
<div style="padding: 15px; background: #263238; color: #ffca28; border-radius: 12px; text-align: center; border: 2px solid #ffca28;"><strong>TOTAL : <span id="total_q" style="font-size: 1.6em;">0</span> J</strong></div>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerCanvas'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphCanvas'), gCtx = gC.getContext('2d');
const BK = { x: 115, y: 40, w: 230, h: 300, baseH: 70 };
const MARGIN = 18;
const data = {
eau: { cs:2090, cl:4185, cg:2010, lf:334000, lv:2260000, tf:0, tv:100, color:"#1565c0", bg:"#e3f2fd" },
ammoniac: { cs:2100, cl:4700, cg:2100, lf:331000, lv:1371000, tf:-77.7, tv:-33.3, color:"#fbc02d", bg:"#fff9c4" },
isobutane: { cs:1600, cl:2350, cg:1650, lf:78000, lv:366000, tf:-159.6, tv:-11.7, color:"#e65100", bg:"#fff3e0" },
r32: { cs:1200, cl:1900, cg:1500, lf:110000, lv:380000, tf:-136, tv:-51.7, color:"#6a1b9a", bg:"#f3e5f5" },
r1234yf: { cs:1050, cl:1390, cg:1100, lf:85000, lv:180000, tf:-152.2, tv:-29.5, color:"#455a64", bg:"#eceff1" }
};
let sub, m, p, energy=0, isPaused=false, isRunning = false, points=[], mols=[], temp, t_start, t_end, maxE, liquidOpacity = 0;
let useKelvin = false;
window.checkAbsoluteZero = function(el) { if(parseFloat(el.value) < -273.15) el.value = -273.15; };
window.toggleUnit = function() {
useKelvin = !useKelvin;
document.getElementById('unitBtn').innerText = useKelvin ? "UNITÉ : K" : "UNITÉ : °C";
document.querySelectorAll('.unitLabel').forEach(l => l.innerText = useKelvin ? "K" : "°C");
updateDisplay();
updateDataPanel();
};
function formatTemp(t) {
if(useKelvin) return (t + 273.15).toFixed(1) + (arguments[1] ? "" : " K");
return t.toFixed(1) + (arguments[1] ? "" : " °C");
}
window.initSubstance = function() {
sub = data[document.getElementById('substance_select').value];
t_start = parseFloat(document.getElementById('t_start_val').value);
t_end = parseFloat(document.getElementById('t_end_val').value);
temp = t_start; energy = 0; isRunning = false; isPaused = false; points = [];
updateDisplay();
updateDataPanel();
document.getElementById('mainBtn').style.backgroundColor = sub.color;
document.getElementById('mainBtn').innerText = "DÉMARRER";
document.querySelectorAll('span[id^="d"]').forEach(s => s.innerText = "");
document.querySelectorAll('.step-arrow').forEach(a => a.style.display = 'none');
document.querySelectorAll('#formulas > div').forEach(d => { if(d.id) d.style.background = "#fff"; });
initVisualState();
};
function updateDataPanel() {
document.getElementById('val_cs').innerText = sub.cs;
document.getElementById('val_cl').innerText = sub.cl;
document.getElementById('val_cg').innerText = sub.cg;
document.getElementById('val_lf').innerText = (sub.lf/1000).toFixed(0);
document.getElementById('val_lv').innerText = (sub.lv/1000).toFixed(0);
document.getElementById('val_temps').innerText = formatTemp(sub.tf, true) + " / " + formatTemp(sub.tv, true);
}
function updateDisplay() {
const disp = document.getElementById('tempDisp');
disp.innerText = formatTemp(temp);
disp.style.color = sub.color; disp.style.backgroundColor = sub.bg; disp.style.borderColor = sub.color;
}
function initVisualState() {
mols = [];
let state = (temp < sub.tf) ? 'solid' : (temp < sub.tv) ? 'liquid' : 'gas';
liquidOpacity = (state === 'solid') ? 0 : (state === 'liquid') ? 1 : 0;
for(let i=0; i<45; i++) {
mols.push({
ox: BK.x + MARGIN + Math.random()*(BK.w - 2*MARGIN),
oy: BK.y + BK.h - BK.baseH + MARGIN + Math.random()*(BK.baseH - 2*MARGIN),
vx: (Math.random()-0.5)*4.5, vy: (Math.random()-0.5)*4.5, state: state
});
}
}
window.handleBtn = function() {
if(!isRunning || temp >= t_end) {
t_start = parseFloat(document.getElementById('t_start_val').value);
t_end = parseFloat(document.getElementById('t_end_val').value);
m = parseFloat(document.getElementById('m_val').value);
p = parseFloat(document.getElementById('p_val').value);
if(t_start < -273.15) t_start = -273.15;
if(t_start >= t_end) { alert("T. initiale doit être < T. finale !"); return; }
let q1 = (t_start < sub.tf) ? m*sub.cs*(Math.min(t_end, sub.tf) - t_start) : 0;
let q2 = (t_start <= sub.tf && t_end > sub.tf) ? m*sub.lf : 0;
let q3 = (t_end > sub.tf) ? m*sub.cl*(Math.min(t_end, sub.tv) - Math.max(t_start, sub.tf)) : 0;
if(q3 < 0) q3 = 0;
let q4 = (t_start <= sub.tv && t_end > sub.tv) ? m*sub.lv : 0;
let q5 = (t_end > sub.tv) ? m*sub.cg*(t_end - Math.max(t_start, sub.tv)) : 0;
maxE = q1 + q2 + q3 + q4 + q5;
temp = t_start; energy = 0; points = []; isRunning = true; isPaused = false;
document.getElementById('mainBtn').innerText = "PAUSE";
} else {
isPaused = !isPaused;
document.getElementById('mainBtn').innerText = isPaused ? "REPRENDRE" : "PAUSE";
}
};
function update() {
if(!isRunning || isPaused || temp >= t_end) return;
energy += p * (parseFloat(document.getElementById('speed_select').value) * 0.15);
let q1 = (t_start < sub.tf) ? m*sub.cs*(sub.tf - t_start) : 0;
let q2 = (t_start <= sub.tf) ? m*sub.lf : 0;
let q3 = (t_start < sub.tv) ? m*sub.cl*(sub.tv - Math.max(t_start, sub.tf)) : 0;
let q4 = (t_start <= sub.tv) ? m*sub.lv : 0;
document.querySelectorAll('#formulas > div').forEach(d => { if(d.id) d.style.background = "#fff"; });
if (t_start < sub.tf && energy < q1) {
temp = t_start + energy/(m*sub.cs); setArrow('f1');
document.getElementById('f1').style.background = sub.bg;
document.getElementById('d1').innerText = Math.round(energy).toLocaleString() + " J";
} else if (t_start <= sub.tf && energy < q1+q2) {
temp = sub.tf; let pr = (energy-q1)/q2; setArrow('f2');
liquidOpacity = pr; mols.forEach((mo, i) => mo.state = (i/mols.length < pr) ? 'liquid' : 'solid');
document.getElementById('f2').style.background = sub.bg;
document.getElementById('d2').innerText = Math.round(energy-q1).toLocaleString() + " J";
} else if (energy < q1+q2+q3) {
temp = Math.max(t_start, sub.tf) + (energy-q1-q2)/(m*sub.cl); setArrow('f3');
liquidOpacity = 1; mols.forEach(mo => mo.state='liquid');
document.getElementById('f3').style.background = sub.bg;
document.getElementById('d3').innerText = Math.round(energy-q1-q2).toLocaleString() + " J";
} else if (t_end > sub.tv && energy < q1+q2+q3+q4) {
temp = sub.tv; let prV = (energy-(q1+q2+q3))/q4; setArrow('f4');
liquidOpacity = 1 - prV; mols.forEach((mo, i) => mo.state = (i/mols.length < prV) ? 'gas' : 'liquid');
document.getElementById('f4').style.background = sub.bg;
document.getElementById('d4').innerText = Math.round(energy-q1-q2-q3).toLocaleString() + " J";
} else {
temp = Math.max(t_start, sub.tv) + (energy-q1-q2-q3-q4)/(m*sub.cg); setArrow('f5');
liquidOpacity = 0; mols.forEach(mo => mo.state = 'gas');
document.getElementById('f5').style.background = sub.bg;
document.getElementById('d5').innerText = Math.round(Math.min(energy-(q1+q2+q3+q4), maxE-(q1+q2+q3+q4))).toLocaleString() + " J";
}
if (temp >= t_end) { temp = t_end; isRunning = false; document.getElementById('mainBtn').innerText = "REDÉMARRER"; }
updateDisplay();
document.getElementById('total_q').innerText = Math.round(Math.min(energy, maxE)).toLocaleString();
points.push({e: energy, t: temp});
}
function setArrow(id) {
document.querySelectorAll('.step-arrow').forEach(a => a.style.display = 'none');
if(id) document.querySelector('#'+id+' .step-arrow').style.display = 'inline';
}
function draw() {
bCtx.clearRect(0,0,bC.width,bC.height);
const heating = isRunning && !isPaused && temp < t_end;
bCtx.fillStyle = heating ? "#d32f2f" : "#1976d2";
bCtx.fillRect(BK.x, BK.y+BK.h, BK.w, 25);
bCtx.fillStyle = "#fff"; bCtx.font="bold 20px Arial"; bCtx.fillText("♨", BK.x+BK.w/2-10, BK.y+BK.h+19);
if (liquidOpacity > 0 || temp < sub.tf) {
bCtx.fillStyle = (temp < sub.tf) ? "rgba(200,200,200,0.3)" : sub.color + "44";
let h = (BK.baseH-5) * (temp < sub.tf ? 1 : liquidOpacity);
bCtx.fillRect(BK.x+8, BK.y+BK.h-h, BK.w-16, h);
}
bCtx.strokeStyle="#333"; bCtx.lineWidth=12; bCtx.strokeRect(BK.x, BK.y, BK.w, BK.h);
mols.forEach(mo => {
let s = (mo.state==='solid')?0.6 : (mo.state==='liquid')?2.8 : 13;
if(mo.state==='solid') { mo.x=mo.ox+(Math.random()-0.5)*2; mo.y=mo.oy+(Math.random()-0.5)*2; }
else { mo.ox+=mo.vx*s*0.1; mo.oy+=mo.vy*s*0.1;
if(mo.ox<BK.x+MARGIN || mo.ox>BK.x+BK.w-MARGIN) mo.vx*=-1;
let top = (mo.state==='liquid')?BK.y+BK.h-(BK.baseH*liquidOpacity)+8 : BK.y+MARGIN;
if(mo.oy<top || mo.oy>BK.y+BK.h-MARGIN) mo.vy*=-1;
mo.x=mo.ox; mo.y=mo.oy;
}
bCtx.fillStyle=sub.color; bCtx.beginPath(); bCtx.arc(mo.x, mo.y, 5, 0, Math.PI*2); bCtx.fill();
});
gCtx.clearRect(0,0,gC.width,gC.height);
const OX=65, OY=300; gCtx.strokeStyle="#333"; gCtx.lineWidth=2;
gCtx.beginPath(); gCtx.moveTo(OX,320); gCtx.lineTo(OX,15); gCtx.lineTo(OX-5,25); gCtx.moveTo(OX,15); gCtx.lineTo(OX+5,25);
gCtx.moveTo(40,OY); gCtx.lineTo(445,OY); gCtx.lineTo(435,OY-5); gCtx.moveTo(445,OY); gCtx.lineTo(435,OY+5); gCtx.stroke();
gCtx.fillStyle="#000"; gCtx.fillText(useKelvin ? "T (K)" : "T (°C)", 20, 15); gCtx.fillText("Q (J)", 415, OY+20);
[t_start, sub.tf, sub.tv, t_end].filter(v => v >= t_start && v <= t_end).forEach(v => {
let y = OY - ((v-t_start)/(t_end-t_start))*260;
let val = useKelvin ? Math.round(v + 273.15) : Math.round(v);
gCtx.fillText(val, OX-35, y+5);
gCtx.beginPath(); gCtx.moveTo(OX-5,y); gCtx.lineTo(OX+5,y); gCtx.stroke();
});
if(points.length > 1) {
gCtx.beginPath(); gCtx.strokeStyle=sub.color; gCtx.lineWidth=3.5;
points.forEach((p, i) => {
let px = OX + (p.e/maxE)*350;
let py = OY - ((p.t-t_start)/(t_end-t_start))*260;
if(i===0) gCtx.moveTo(px,py); else gCtx.lineTo(px,py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance(); loop();
})();
</script>
$CAL3|=|1
<div id="sim-thermo-fixed-final" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd; flex-wrap: wrap; gap: 15px;">
<div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;">
<div>
<label style="font-weight: bold; color: #444;">Choix :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #1565c0; cursor: pointer;">
<option value="subA">Substance A</option>
<option value="subB">Substance B</option>
<option value="subC">Substance C</option>
<option value="subD">Substance D</option>
<option value="subE">Substance E</option>
</select>
</div>
<div>
<label style="font-weight: bold; color: #444;">Masse :</label>
<select id="selectMasse" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; cursor: pointer;">
<option value="1">1 kg</option>
<option value="2">2 kg</option>
<option value="5">5 kg</option>
<option value="10">10 kg</option>
</select>
</div>
</div>
<div id="temp-grand" style="font-size: 3.2em; font-weight: bold; color: #d32f2f; font-family: monospace; background: #fff; padding: 5px 15px; border-radius: 10px; border: 1px solid #ccc; min-width: 200px; text-align: center;">-200.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.4em; font-weight: bold; color: #1565c0; text-align: center;">-</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.2em; margin-bottom: 10px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-bottom: 8px;">FORMULE APPLIQUÉE</div>
<div id="q-val" style="font-size: 1.6em; color: #ffeb3b; margin-bottom: 8px;">0 J</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; border-top: 1px solid #333; padding-top: 8px;">Q = m · cₛ · ΔT</div>
</div>
</div>
<div style="flex: 2; min-width: 450px; display: flex; flex-direction: column;">
<canvas id="graphSim" width="600" height="420" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 10px; margin-top: 20px; justify-content: flex-end;">
<button id="btnPlay" onclick="toggleSim()" style="width: 160px; padding: 15px; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 1.1em; box-shadow: 0 4px #1b5e20;">DÉMARRER</button>
<button onclick="resetSim()" style="padding: 15px; background: #546e7a; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const selectF = document.getElementById('selectFluide'), selectM = document.getElementById('selectMasse');
const db = {
subA: { label: "Substance A", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114, tv: 78, isCO2: false, colorL: "#e3f2fd", colorS: "#64b5f6" },
subB: { label: "Substance B", cs: 850, cg: 840, ls: 571000, ts: -78.5, isCO2: true, colorS: "#eeeeee" },
subC: { label: "Substance C", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155, tv: -82, isCO2: false, colorL: "#e0f7fa", colorS: "#4dd0e1" },
subD: { label: "Substance D", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -188, tv: -42, isCO2: false, colorL: "#fff3e0", colorS: "#ffb74d" },
subE: { label: "Substance E", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152, tv: -29, isCO2: false, colorL: "#f1f8e9", colorS: "#aed581" }
};
let s, temp, energy, masse, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 4500, tStart = -200, tEnd = 200;
let gasParticles = [];
window.initSubstance = function() {
s = db[selectF.value];
masse = parseFloat(selectM.value);
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER";
document.getElementById('btnPlay').style.background = "#2e7d32";
gasParticles = [];
updateUI();
};
window.toggleSim = function() {
if(temp >= tEnd && isRunning) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
window.resetSim = function() { initSubstance(); };
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.label + " (" + masse + " kg)";
}
function update() {
if(!isRunning || temp >= tEnd) { heater.style.background = "#333"; return; }
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 8) % 2 === 0) ? "#d32f2f" : "#333";
energy += pwr * 15;
const fText = document.getElementById('formule-text');
const eText = document.getElementById('etat-text');
if (s.isCO2) {
let q1 = masse * s.cs * (s.ts - tStart), q2 = masse * s.ls;
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
eText.innerText = "ÉTAT : SOLIDE"; fText.innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.ts;
eText.innerText = "ÉTAT : SUBLIMATION"; fText.innerHTML = "Q = m · Lₛ";
} else {
temp = s.ts + (energy - q1 - q2)/(masse*s.cg);
eText.innerText = "ÉTAT : GAZ"; fText.innerHTML = "Q = m · cₚ · ΔT";
}
} else {
let q1 = masse * s.cs * (s.tf - tStart), q2 = masse * s.lf;
let q3 = masse * s.cl * (s.tv - s.tf), q4 = masse * s.lv;
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
eText.innerText = "ÉTAT : SOLIDE"; fText.innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.tf;
eText.innerText = "ÉTAT : FUSION"; fText.innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = s.tf + (energy - q1 - q2)/(masse*s.cl);
eText.innerText = "ÉTAT : LIQUIDE"; fText.innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = s.tv;
eText.innerText = "ÉTAT : ÉBULLITION"; fText.innerHTML = "Q = m · Lv";
} else {
temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg);
eText.innerText = "ÉTAT : GAZ"; fText.innerHTML = "Q = m · cₚ · ΔT";
}
}
pts.push({x: energy, y: temp});
updateUI();
if(gasParticles.length > 0) {
let speed = 0.5 + ((temp + 200) * 0.015);
gasParticles.forEach(p => {
p.x += p.vx * speed; p.y += p.vy * speed;
if(p.x < 5 || p.x > 215) p.vx *= -1; if(p.y < 5 || p.y > 295) p.vy *= -1;
});
}
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 40 + (masse * 12);
if(s.isCO2) {
let q1 = masse * s.cs * (s.ts - tStart), q2 = masse * s.ls;
if (temp < s.ts) {
bCtx.fillStyle = s.colorS; bCtx.fillRect(40, 300-hMax, 140, hMax);
} else if (temp === s.ts) {
let r = Math.min(1, (energy-q1)/q2);
bCtx.fillStyle = s.colorS; bCtx.fillRect(40, 300-(hMax*(1-r)), 140, hMax*(1-r));
if(gasParticles.length < Math.floor(r*70)) gasParticles.push({x: 110, y: 280, vx: Math.random()*2-1, vy: -Math.random()*2, r: 3});
bCtx.fillStyle = "rgba(200,200,200,0.4)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); });
} else {
if(gasParticles.length < 70) gasParticles.push({x: 110, y: 150, vx: Math.random()*3-1.5, vy: Math.random()*3-1.5, r: 3});
bCtx.fillStyle = "rgba(180,180,180,0.5)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); });
}
} else {
let q1 = masse * s.cs * (s.tf - tStart), q2 = masse * s.lf, q3 = masse * s.cl * (s.tv - s.tf);
if(temp < s.tf) {
bCtx.fillStyle = s.colorS; bCtx.fillRect(40, 300-hMax, 140, hMax);
} else if (temp === s.tf) {
let r = Math.min(1, (energy-q1)/q2);
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*r), 220, hMax*r);
bCtx.fillStyle = s.colorS; bCtx.fillRect(40, 300-hMax, 140, hMax*(1-r));
} else if (temp < s.tv) {
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax);
} else if (temp === s.tv) {
let rV = Math.min(1, (energy-q1-q2-q3)/(masse * 835000)); // Calibrage visuel
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*(1-rV)), 220, hMax*(1-rV));
if(gasParticles.length < 60) gasParticles.push({x: 110, y: 150, vx: Math.random()*4-2, vy: Math.random()*4-2, r: 2.5});
bCtx.fillStyle = "rgba(180,210,255,0.4)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); });
} else {
bCtx.fillStyle = "rgba(160,200,255,0.5)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r+1, 0, 7); bCtx.fill(); });
}
}
gCtx.clearRect(0,0,600,420);
gCtx.strokeStyle = "#444"; gCtx.lineWidth = 2;
// Axe Y
gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(60, 20); gCtx.stroke();
gCtx.beginPath(); gCtx.moveTo(55, 30); gCtx.lineTo(60, 15); gCtx.lineTo(65, 30); gCtx.fill();
gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (°C)", 35, 25);
// Axe X
gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(580, 390); gCtx.stroke();
gCtx.beginPath(); gCtx.moveTo(575, 385); gCtx.lineTo(590, 390); gCtx.lineTo(575, 395); gCtx.fill();
gCtx.fillText("Q (Joules)", 520, 410);
let xMax = masse * 1500000;
for(let t=-200; t<=200; t+=50) {
let y = 390 - ((t+200)/400)*350;
gCtx.fillStyle = "#888"; gCtx.font = "10px Arial";
gCtx.fillText(t, 30, y+4);
gCtx.beginPath(); gCtx.moveTo(55,y); gCtx.lineTo(60,y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = "#1565c0"; gCtx.lineWidth = 3;
pts.forEach((p, i) => {
let px = 60 + (p.x / xMax) * 500;
let py = 390 - ((p.y + 200) / 400) * 350;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
substance X
Identifie chaque substance et déplace l'étiquette au bon endroit dans le tableau
exercices
?$F1|=|1&F2|=|1&F3|=|1&F4|=|1
CHALLENGE FINAL
exercice 1
exercice 3
exercice 4
exercice 2
?$CALEX2|=|1
?$CALEX1|=|1
?$CALEX3|=|1
?$CALEX4|=|1
<div id="sim-eau-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;">
<h2 style="margin: 0; color: #1565c0; font-size: 1.4em;">🔬 Analyse Thermique : Eau (H₂O)</h2>
<div style="display: flex; align-items: center; gap: 15px;">
<div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;">
<button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #1565c0; color: white;">°C</button>
<button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button>
</div>
<div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-50.0 °C</div>
</div>
</div>
<div style="display: flex; gap: 25px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 200px; height: 302px;">
<canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas>
<div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div>
</div>
<div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #1565c0; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div>
<div style="width: 100%; margin-top: 20px; background: #1a237e; color: #e8eaf6; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;">
<div style="color: #9fa8da; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #303f9f;">Énergie Totale Transférée</div>
<div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #00e5ff;">0 J</div>
<div style="color: #9fa8da; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #303f9f;">Formule en cours</div>
<div id="formule-display" style="font-size: 1.1em; color: #ffeb3b; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div>
</div>
<div id="specs" style="margin-top: 20px; background: #e3f2fd; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #bbdefb; color: #333;">
<div style="display: flex; flex-direction: column; gap: 5px;">
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>2090 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>334 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>4185 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>2260 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>1850 J/(kg·K)</span></div>
</div>
</div>
</div>
<div style="flex: 2; min-width: 400px;">
<canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas>
<div style="display: flex; gap: 10px; margin-top: 20px;">
<button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button>
<button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const etatLabel = document.getElementById('etat-text');
const tempDisp = document.getElementById('temp-grand');
const qTotalDisp = document.getElementById('q-total-display');
const formuleDisp = document.getElementById('formule-display');
// Propriétés Eau
const sub = { cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100 };
let temp = -50, energy = 0, isRunning = false, pts = [];
let isKelvin = false;
const pwr = 4500, masse = 1, maxEnergy = 3500000;
let heatStep = 0;
window.setUnit = function(k) {
isKelvin = k;
document.getElementById('btnKel').style.background = k ? '#1565c0' : '#fff';
document.getElementById('btnKel').style.color = k ? '#fff' : '#333';
document.getElementById('btnDeg').style.background = k ? '#fff' : '#1565c0';
document.getElementById('btnDeg').style.color = k ? '#333' : '#fff';
updateDisplay();
};
window.toggleSim = function() {
if(temp >= 150) return;
isRunning = !isRunning;
document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateDisplay() {
tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C";
qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J";
}
function update() {
if(!isRunning) return;
if(temp >= 150) {
temp = 150.0; isRunning = false;
heater.style.background = "#444";
document.getElementById('btnStart').innerText = "TERMINÉ";
document.getElementById('btnStart').style.background = "#999";
return;
}
heatStep++;
heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c";
energy += pwr * 1.5;
let q1 = masse * sub.cs * (sub.tf - (-50));
let q2 = masse * sub.lf;
let q3 = masse * sub.cl * (sub.tv - sub.tf);
let q4 = masse * sub.lv;
if (energy < q1) {
temp = -50 + energy/(masse*sub.cs);
etatLabel.innerText = "SOLIDE";
formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT";
}
else if (energy < q1+q2) {
temp = sub.tf;
etatLabel.innerText = "FUSION";
formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>";
}
else if (energy < q1+q2+q3) {
temp = sub.tf + (energy-q1-q2)/(masse*sub.cl);
etatLabel.innerText = "LIQUIDE";
formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT";
}
else if (energy < q1+q2+q3+q4) {
temp = sub.tv;
etatLabel.innerText = "ÉBULLITION";
formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>";
}
else {
temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg);
if(temp > 150) temp = 150;
etatLabel.innerText = "GAZ";
formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT";
}
pts.push({x: energy, y: temp});
updateDisplay();
}
function drawArrows(ctx, x, y, angle) {
ctx.save(); ctx.translate(x, y); ctx.rotate(angle);
ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke();
ctx.restore();
}
function draw() {
bCtx.clearRect(0,0,200,280);
let level = 120, bBottom = 280, bWidth = 200;
let q1 = masse*sub.cs*50, q2 = masse*sub.lf, q3 = masse*sub.cl*100, q4 = masse*sub.lv;
if (temp < 0) { bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(15, bBottom - level, 170, level); }
else if (temp === 0) {
let r = (energy-q1)/q2;
bCtx.fillStyle = "#1565c0"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r);
bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r));
} else if (temp < 100) { bCtx.fillStyle = "#1565c0"; bCtx.fillRect(0, bBottom-level, bWidth, level); }
else if (temp === 100) {
let rv = (energy-(q1+q2+q3))/q4;
bCtx.fillStyle = "#1565c0"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv));
bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom);
} else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); }
gCtx.clearRect(0,0,600,400);
gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1;
const marks = [-50, 0, 100, 150];
marks.forEach((tVal) => {
let y = 350 - ((tVal + 50) / 200) * 300;
gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke();
let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C";
gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5);
});
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke();
drawArrows(gCtx, 50, 20, -Math.PI/2);
gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke();
drawArrows(gCtx, 580, 350, 0);
gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial";
gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25);
gCtx.fillText("Q (Joules)", 510, 340);
if(pts.length > 1) {
gCtx.beginPath(); gCtx.strokeStyle = "#1565c0"; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let x = 50 + (p.x / maxEnergy) * 520;
let y = 350 - ((p.y + 50) / 200) * 300;
if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
loop();
})();
</script>
<div id="sim-eau-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;">
<h2 style="margin: 0; color: #1565c0; font-size: 1.4em;">🔬 Analyse Thermique : Eau (H₂O)</h2>
<div style="display: flex; align-items: center; gap: 15px;">
<div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;">
<button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #1565c0; color: white;">°C</button>
<button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button>
</div>
<div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-50.0 °C</div>
</div>
</div>
<div style="display: flex; gap: 25px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 200px; height: 302px;">
<canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas>
<div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div>
</div>
<div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #1565c0; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div>
<div style="width: 100%; margin-top: 20px; background: #1a237e; color: #e8eaf6; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;">
<div style="color: #9fa8da; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #303f9f;">Énergie Totale Transférée</div>
<div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #00e5ff;">0 J</div>
<div style="color: #9fa8da; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #303f9f;">Formule en cours</div>
<div id="formule-display" style="font-size: 1.1em; color: #ffeb3b; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div>
</div>
<div id="specs" style="margin-top: 20px; background: #e3f2fd; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #bbdefb; color: #333;">
<div style="display: flex; flex-direction: column; gap: 5px;">
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>2090 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>334 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>4185 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>2260 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>1850 J/(kg·K)</span></div>
</div>
</div>
</div>
<div style="flex: 2; min-width: 400px;">
<canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas>
<div style="display: flex; gap: 10px; margin-top: 20px;">
<button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button>
<button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const etatLabel = document.getElementById('etat-text');
const tempDisp = document.getElementById('temp-grand');
const qTotalDisp = document.getElementById('q-total-display');
const formuleDisp = document.getElementById('formule-display');
// Propriétés Eau
const sub = { cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100 };
let temp = -50, energy = 0, isRunning = false, pts = [];
let isKelvin = false;
const pwr = 4500, masse = 1, maxEnergy = 3500000;
let heatStep = 0;
window.setUnit = function(k) {
isKelvin = k;
document.getElementById('btnKel').style.background = k ? '#1565c0' : '#fff';
document.getElementById('btnKel').style.color = k ? '#fff' : '#333';
document.getElementById('btnDeg').style.background = k ? '#fff' : '#1565c0';
document.getElementById('btnDeg').style.color = k ? '#333' : '#fff';
updateDisplay();
};
window.toggleSim = function() {
if(temp >= 150) return;
isRunning = !isRunning;
document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateDisplay() {
tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C";
qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J";
}
function update() {
if(!isRunning) return;
if(temp >= 150) {
temp = 150.0; isRunning = false;
heater.style.background = "#444";
document.getElementById('btnStart').innerText = "TERMINÉ";
document.getElementById('btnStart').style.background = "#999";
formuleDisp.innerHTML = ""; // Suppression de la formule à la fin
return;
}
heatStep++;
heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c";
energy += pwr * 1.5;
let q1 = masse * sub.cs * (sub.tf - (-50));
let q2 = masse * sub.lf;
let q3 = masse * sub.cl * (sub.tv - sub.tf);
let q4 = masse * sub.lv;
if (energy < q1) {
temp = -50 + energy/(masse*sub.cs);
etatLabel.innerText = "SOLIDE";
formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT";
}
else if (energy < q1+q2) {
temp = sub.tf;
etatLabel.innerText = "FUSION";
formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>";
}
else if (energy < q1+q2+q3) {
temp = sub.tf + (energy-q1-q2)/(masse*sub.cl);
etatLabel.innerText = "LIQUIDE";
formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT";
}
else if (energy < q1+q2+q3+q4) {
temp = sub.tv;
etatLabel.innerText = "ÉBULLITION";
formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>";
}
else {
temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg);
if(temp > 150) temp = 150;
etatLabel.innerText = "GAZ";
formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT";
}
pts.push({x: energy, y: temp});
updateDisplay();
}
function drawArrows(ctx, x, y, angle) {
ctx.save(); ctx.translate(x, y); ctx.rotate(angle);
ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke();
ctx.restore();
}
function draw() {
bCtx.clearRect(0,0,200,280);
let level = 120, bBottom = 280, bWidth = 200;
let q1 = masse*sub.cs*50, q2 = masse*sub.lf, q3 = masse*sub.cl*100, q4 = masse*sub.lv;
if (temp < 0) { bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(15, bBottom - level, 170, level); }
else if (temp === 0) {
let r = (energy-q1)/q2;
bCtx.fillStyle = "#1565c0"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r);
bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r));
} else if (temp < 100) { bCtx.fillStyle = "#1565c0"; bCtx.fillRect(0, bBottom-level, bWidth, level); }
else if (temp === 100) {
let rv = (energy-(q1+q2+q3))/q4;
bCtx.fillStyle = "#1565c0"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv));
bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom);
} else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); }
gCtx.clearRect(0,0,600,400);
gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1;
const marks = [-50, 0, 100, 150];
marks.forEach((tVal) => {
let y = 350 - ((tVal + 50) / 200) * 300;
gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke();
let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C";
gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5);
});
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke();
drawArrows(gCtx, 50, 20, -Math.PI/2);
gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke();
drawArrows(gCtx, 580, 350, 0);
gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial";
gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25);
gCtx.fillText("Q (Joules)", 510, 340);
if(pts.length > 1) {
gCtx.beginPath(); gCtx.strokeStyle = "#1565c0"; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let x = 50 + (p.x / maxEnergy) * 520;
let y = 350 - ((p.y + 50) / 200) * 300;
if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
loop();
})();
</script>
$CALEX1|=|1
Relever la température de fusion Tf = et la température d'ébullition Tvap = Identifier la substance : Pourquoi la température reste-t-elle bloquée par moments ? Calculer l'énergie nécessaire pour vaporiser 4 kg de cette substance Q = = =
- eau
- ammoniac
- méthane
- isobutane
- difluorométhane
- tétrafluoropropène
- L'énergie sert à briser les liaisons
- Il y a une panne du système de chauffe
- Le capteur de mesure est bloqué
VALIDER
non
<div id="sim-ammoniac-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;">
<h2 style="margin: 0; color: #689f38; font-size: 1.4em;">🔬 Analyse Thermique : Ammoniac (NH₃)</h2>
<div style="display: flex; align-items: center; gap: 15px;">
<div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;">
<button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #689f38; color: white;">°C</button>
<button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button>
</div>
<div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-100.0 °C</div>
</div>
</div>
<div style="display: flex; gap: 25px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 200px; height: 302px;">
<canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas>
<div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div>
</div>
<div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #689f38; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div>
<div style="width: 100%; margin-top: 20px; background: #263238; color: #eceff1; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;">
<div style="color: #81c784; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #455a64;">Énergie Totale Transférée</div>
<div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #ffeb3b;">0 J</div>
<div style="color: #81c784; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #455a64;">Formule en cours</div>
<div id="formule-display" style="font-size: 1.1em; color: #fb8c00; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div>
</div>
<div id="specs" style="margin-top: 20px; background: #f1f8e9; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #dcedc8; color: #333;">
<div style="display: flex; flex-direction: column; gap: 5px;">
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>2100 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>332 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>4700 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>1370 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>2050 J/(kg·K)</span></div>
<hr style="border: 0; border-top: 1px solid #dcedc8; margin: 5px 0;">
<div style="display: flex; justify-content: space-between;"><span><b>Puissance P</b></span> <span>4500 W</span></div>
</div>
</div>
</div>
<div style="flex: 2; min-width: 400px;">
<canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas>
<div style="display: flex; gap: 10px; margin-top: 20px;">
<button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button>
<button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const etatLabel = document.getElementById('etat-text');
const tempDisp = document.getElementById('temp-grand');
const qTotalDisp = document.getElementById('q-total-display');
const formuleDisp = document.getElementById('formule-display');
const sub = { cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3 };
let temp = -100, energy = 0, isRunning = false, pts = [];
let isKelvin = false;
const pwr = 4500, masse = 1, maxEnergy = 2500000;
let heatStep = 0;
window.setUnit = function(k) {
isKelvin = k;
document.getElementById('btnKel').style.background = k ? '#689f38' : '#fff';
document.getElementById('btnKel').style.color = k ? '#fff' : '#333';
document.getElementById('btnDeg').style.background = k ? '#fff' : '#689f38';
document.getElementById('btnDeg').style.color = k ? '#333' : '#fff';
updateDisplay();
};
window.toggleSim = function() {
if(temp >= 100) return;
isRunning = !isRunning;
document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateDisplay() {
tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C";
qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J";
}
function update() {
if(!isRunning) return;
if(temp >= 100) {
temp = 100.0; isRunning = false;
heater.style.background = "#444";
document.getElementById('btnStart').innerText = "TERMINÉ";
document.getElementById('btnStart').style.background = "#999";
return;
}
heatStep++;
heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c";
energy += pwr * 1.5;
let q1 = masse * sub.cs * (sub.tf - (-100));
let q2 = masse * sub.lf;
let q3 = masse * sub.cl * (sub.tv - sub.tf);
let q4 = masse * sub.lv;
if (energy < q1) {
temp = -100 + energy/(masse*sub.cs);
etatLabel.innerText = "SOLIDE";
formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT";
}
else if (energy < q1+q2) {
temp = sub.tf;
etatLabel.innerText = "FUSION";
formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>";
}
else if (energy < q1+q2+q3) {
temp = sub.tf + (energy-q1-q2)/(masse*sub.cl);
etatLabel.innerText = "LIQUIDE";
formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT";
}
else if (energy < q1+q2+q3+q4) {
temp = sub.tv;
etatLabel.innerText = "ÉBULLITION";
formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>";
}
else {
temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg);
if(temp > 100) temp = 100;
etatLabel.innerText = "GAZ";
formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT";
}
pts.push({x: energy, y: temp});
updateDisplay();
}
function drawArrows(ctx, x, y, angle) {
ctx.save(); ctx.translate(x, y); ctx.rotate(angle);
ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke();
ctx.restore();
}
function draw() {
bCtx.clearRect(0,0,200,280);
let level = 120, bBottom = 280, bWidth = 200;
let q1 = masse*sub.cs*(sub.tf - (-100)), q2 = masse*sub.lf, q3 = masse*sub.cl*(sub.tv-sub.tf), q4 = masse*sub.lv;
if (temp < sub.tf) { bCtx.fillStyle = "#dcedc8"; bCtx.fillRect(15, bBottom - level, 170, level); }
else if (temp === sub.tf) {
let r = (energy-q1)/q2;
bCtx.fillStyle = "#689f38"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r);
bCtx.fillStyle = "#dcedc8"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r));
} else if (temp < sub.tv) { bCtx.fillStyle = "#689f38"; bCtx.fillRect(0, bBottom-level, bWidth, level); }
else if (temp === sub.tv) {
let rv = (energy-(q1+q2+q3))/q4;
bCtx.fillStyle = "#689f38"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv));
bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom);
} else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); }
gCtx.clearRect(0,0,600,400);
gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1;
const marks = [-100, sub.tf, sub.tv, 50, 100];
marks.forEach((tVal) => {
let y = 350 - ((tVal + 100) / 200) * 300;
gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke();
let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C";
gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5);
});
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke();
drawArrows(gCtx, 50, 20, -Math.PI/2);
gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke();
drawArrows(gCtx, 580, 350, 0);
gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial";
gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25);
gCtx.fillText("Q (Joules)", 510, 340);
if(pts.length > 1) {
gCtx.beginPath(); gCtx.strokeStyle = "#689f38"; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let x = 50 + (p.x / maxEnergy) * 520;
let y = 350 - ((p.y + 100) / 200) * 300;
if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
loop();
})();
</script>
$CALEX2|=|1
<div id="sim-ammoniac-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;">
<h2 style="margin: 0; color: #689f38; font-size: 1.4em;">🔬 Analyse Thermique : Ammoniac (NH₃)</h2>
<div style="display: flex; align-items: center; gap: 15px;">
<div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;">
<button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #689f38; color: white;">°C</button>
<button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button>
</div>
<div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-100.0 °C</div>
</div>
</div>
<div style="display: flex; gap: 25px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 200px; height: 302px;">
<canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas>
<div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div>
</div>
<div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #689f38; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div>
<div style="width: 100%; margin-top: 20px; background: #263238; color: #eceff1; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;">
<div style="color: #81c784; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #455a64;">Énergie Totale Transférée</div>
<div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #ffeb3b;">0 J</div>
<div style="color: #81c784; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #455a64;">Formule en cours</div>
<div id="formule-display" style="font-size: 1.1em; color: #fb8c00; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div>
</div>
<div id="specs" style="margin-top: 20px; background: #f1f8e9; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #dcedc8; color: #333;">
<div style="display: flex; flex-direction: column; gap: 5px;">
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>2100 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>332 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>4700 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>1370 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>2050 J/(kg·K)</span></div>
<hr style="border: 0; border-top: 1px solid #dcedc8; margin: 5px 0;">
<div style="display: flex; justify-content: space-between;"><span><b>Puissance P</b></span> <span>4500 W</span></div>
</div>
</div>
</div>
<div style="flex: 2; min-width: 400px;">
<canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas>
<div style="display: flex; gap: 10px; margin-top: 20px;">
<button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button>
<button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const etatLabel = document.getElementById('etat-text');
const tempDisp = document.getElementById('temp-grand');
const qTotalDisp = document.getElementById('q-total-display');
const formuleDisp = document.getElementById('formule-display');
const sub = { cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3 };
let temp = -100, energy = 0, isRunning = false, pts = [];
let isKelvin = false;
const pwr = 4500, masse = 1, maxEnergy = 2500000;
let heatStep = 0;
window.setUnit = function(k) {
isKelvin = k;
document.getElementById('btnKel').style.background = k ? '#689f38' : '#fff';
document.getElementById('btnKel').style.color = k ? '#fff' : '#333';
document.getElementById('btnDeg').style.background = k ? '#fff' : '#689f38';
document.getElementById('btnDeg').style.color = k ? '#333' : '#fff';
updateDisplay();
};
window.toggleSim = function() {
if(temp >= 100) return;
isRunning = !isRunning;
document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateDisplay() {
tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C";
qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J";
}
function update() {
if(!isRunning) return;
// CONDITION DE FIN : Suppression de la formule
if(temp >= 100) {
temp = 100.0; isRunning = false;
heater.style.background = "#444";
document.getElementById('btnStart').innerText = "TERMINÉ";
document.getElementById('btnStart').style.background = "#999";
formuleDisp.innerHTML = ""; // Efface la formule ici
return;
}
heatStep++;
heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c";
energy += pwr * 1.5;
let q1 = masse * sub.cs * (sub.tf - (-100));
let q2 = masse * sub.lf;
let q3 = masse * sub.cl * (sub.tv - sub.tf);
let q4 = masse * sub.lv;
if (energy < q1) {
temp = -100 + energy/(masse*sub.cs);
etatLabel.innerText = "SOLIDE";
formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT";
}
else if (energy < q1+q2) {
temp = sub.tf;
etatLabel.innerText = "FUSION";
formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>";
}
else if (energy < q1+q2+q3) {
temp = sub.tf + (energy-q1-q2)/(masse*sub.cl);
etatLabel.innerText = "LIQUIDE";
formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT";
}
else if (energy < q1+q2+q3+q4) {
temp = sub.tv;
etatLabel.innerText = "ÉBULLITION";
formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>";
}
else {
temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg);
if(temp > 100) temp = 100;
etatLabel.innerText = "GAZ";
formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT";
}
pts.push({x: energy, y: temp});
updateDisplay();
}
function drawArrows(ctx, x, y, angle) {
ctx.save(); ctx.translate(x, y); ctx.rotate(angle);
ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke();
ctx.restore();
}
function draw() {
bCtx.clearRect(0,0,200,280);
let level = 120, bBottom = 280, bWidth = 200;
let q1 = masse*sub.cs*(sub.tf - (-100)), q2 = masse*sub.lf, q3 = masse*sub.cl*(sub.tv-sub.tf), q4 = masse*sub.lv;
if (temp < sub.tf) { bCtx.fillStyle = "#dcedc8"; bCtx.fillRect(15, bBottom - level, 170, level); }
else if (temp === sub.tf) {
let r = (energy-q1)/q2;
bCtx.fillStyle = "#689f38"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r);
bCtx.fillStyle = "#dcedc8"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r));
} else if (temp < sub.tv) { bCtx.fillStyle = "#689f38"; bCtx.fillRect(0, bBottom-level, bWidth, level); }
else if (temp === sub.tv) {
let rv = (energy-(q1+q2+q3))/q4;
bCtx.fillStyle = "#689f38"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv));
bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom);
} else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); }
gCtx.clearRect(0,0,600,400);
gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1;
const marks = [-100, sub.tf, sub.tv, 50, 100];
marks.forEach((tVal) => {
let y = 350 - ((tVal + 100) / 200) * 300;
gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke();
let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C";
gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5);
});
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke();
drawArrows(gCtx, 50, 20, -Math.PI/2);
gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke();
drawArrows(gCtx, 580, 350, 0);
gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial";
gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25);
gCtx.fillText("Q (Joules)", 510, 340);
if(pts.length > 1) {
gCtx.beginPath(); gCtx.strokeStyle = "#689f38"; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let x = 50 + (p.x / maxEnergy) * 520;
let y = 350 - ((p.y + 100) / 200) * 300;
if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
loop();
})();
</script>
Relever la température de fusion Tf = et la température d'ébullition Tvap = Identifier la substance : Que signifie le terme QV : Calculer l'énergie Qv nécessaire pour faire fondre une masse de 500g : Q = = =
$CALEX2|=|1
- ammoniac
- méthane
- isobutane
- difluorométhane
- eau
- tétrafluoropropène
- Chaleur de vaporisation
- Chaleur de fusion
- Quantité de froid
- Quotient de vitesse
- 0,5 .332
- 500.332
- 500 .1700
- 0,5.1700
- 166kJ
- 166000kJ
- 850kJ
- 850000kJ
VALIDER
non
<div id="sim-isobutane-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;">
<h2 style="margin: 0; color: #e65100; font-size: 1.4em;">🔬 Analyse Thermique : Isobutane (C₄H₁₀)</h2>
<div style="display: flex; align-items: center; gap: 15px;">
<div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;">
<button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #e65100; color: white;">°C</button>
<button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button>
</div>
<div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-180.0 °C</div>
</div>
</div>
<div style="display: flex; gap: 25px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 200px; height: 302px;">
<canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas>
<div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div>
</div>
<div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #e65100; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div>
<div style="width: 100%; margin-top: 20px; background: #3e2723; color: #efebe9; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;">
<div style="color: #d7ccc8; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #5d4037;">Énergie Totale Transférée</div>
<div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #ffab91;">0 J</div>
<div style="color: #d7ccc8; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #5d4037;">Formule en cours</div>
<div id="formule-display" style="font-size: 1.1em; color: #ffd54f; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div>
</div>
<div id="specs" style="margin-top: 20px; background: #fff3e0; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #ffe0b2; color: #333;">
<div style="display: flex; flex-direction: column; gap: 5px;">
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>1650 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>78 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>2350 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>366 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>1700 J/(kg·K)</span></div>
</div>
</div>
</div>
<div style="flex: 2; min-width: 400px;">
<canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas>
<div style="display: flex; gap: 10px; margin-top: 20px;">
<button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button>
<button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const etatLabel = document.getElementById('etat-text');
const tempDisp = document.getElementById('temp-grand');
const qTotalDisp = document.getElementById('q-total-display');
const formuleDisp = document.getElementById('formule-display');
// Propriétés Isobutane
const sub = { cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7 };
let temp = -180, energy = 0, isRunning = false, pts = [];
let isKelvin = false;
const pwr = 4500, masse = 1, maxEnergy = 1350000;
let heatStep = 0;
window.setUnit = function(k) {
isKelvin = k;
document.getElementById('btnKel').style.background = k ? '#e65100' : '#fff';
document.getElementById('btnKel').style.color = k ? '#fff' : '#333';
document.getElementById('btnDeg').style.background = k ? '#fff' : '#e65100';
document.getElementById('btnDeg').style.color = k ? '#333' : '#fff';
updateDisplay();
};
window.toggleSim = function() {
if(temp >= 150) return;
isRunning = !isRunning;
document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateDisplay() {
tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C";
qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J";
}
function update() {
if(!isRunning) return;
if(temp >= 150) {
temp = 150.0; isRunning = false;
heater.style.background = "#444";
document.getElementById('btnStart').innerText = "TERMINÉ";
document.getElementById('btnStart').style.background = "#999";
return;
}
heatStep++;
heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c";
energy += pwr * 1.5;
let q1 = masse * sub.cs * (sub.tf - (-180));
let q2 = masse * sub.lf;
let q3 = masse * sub.cl * (sub.tv - sub.tf);
let q4 = masse * sub.lv;
if (energy < q1) {
temp = -180 + energy/(masse*sub.cs);
etatLabel.innerText = "SOLIDE";
formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT";
}
else if (energy < q1+q2) {
temp = sub.tf;
etatLabel.innerText = "FUSION";
formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>";
}
else if (energy < q1+q2+q3) {
temp = sub.tf + (energy-q1-q2)/(masse*sub.cl);
etatLabel.innerText = "LIQUIDE";
formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT";
}
else if (energy < q1+q2+q3+q4) {
temp = sub.tv;
etatLabel.innerText = "ÉBULLITION";
formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>";
}
else {
temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg);
if(temp > 150) temp = 150;
etatLabel.innerText = "GAZ";
formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT";
}
pts.push({x: energy, y: temp});
updateDisplay();
}
function drawArrows(ctx, x, y, angle) {
ctx.save(); ctx.translate(x, y); ctx.rotate(angle);
ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke();
ctx.restore();
}
function draw() {
bCtx.clearRect(0,0,200,280);
let level = 120, bBottom = 280, bWidth = 200;
let q1 = masse*sub.cs*(sub.tf - (-180)), q2 = masse*sub.lf, q3 = masse*sub.cl*(sub.tv-sub.tf), q4 = masse*sub.lv;
if (temp < sub.tf) { bCtx.fillStyle = "#ffccbc"; bCtx.fillRect(15, bBottom - level, 170, level); }
else if (temp === sub.tf) {
let r = (energy-q1)/q2;
bCtx.fillStyle = "#e65100"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r);
bCtx.fillStyle = "#ffccbc"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r));
} else if (temp < sub.tv) { bCtx.fillStyle = "#e65100"; bCtx.fillRect(0, bBottom-level, bWidth, level); }
else if (temp === sub.tv) {
let rv = (energy-(q1+q2+q3))/q4;
bCtx.fillStyle = "#e65100"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv));
bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom);
} else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); }
gCtx.clearRect(0,0,600,400);
gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1;
const marks = [-180, sub.tf, sub.tv, 50, 150];
marks.forEach((tVal) => {
let y = 350 - ((tVal + 180) / 330) * 300;
gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke();
let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C";
gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5);
});
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke();
drawArrows(gCtx, 50, 20, -Math.PI/2);
gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke();
drawArrows(gCtx, 580, 350, 0);
gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial";
gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25);
gCtx.fillText("Q (Joules)", 510, 340);
if(pts.length > 1) {
gCtx.beginPath(); gCtx.strokeStyle = "#e65100"; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let x = 50 + (p.x / maxEnergy) * 520;
let y = 350 - ((p.y + 180) / 330) * 300;
if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
loop();
})();
</script>
$CALEX3|=|1
- -159,6°C
- -180°C
- -11,7°C
- 50°C
<div id="sim-isobutane-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;">
<h2 style="margin: 0; color: #e65100; font-size: 1.4em;">🔬 Analyse Thermique : Isobutane (C₄H₁₀)</h2>
<div style="display: flex; align-items: center; gap: 15px;">
<div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;">
<button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #e65100; color: white;">°C</button>
<button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button>
</div>
<div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-180.0 °C</div>
</div>
</div>
<div style="display: flex; gap: 25px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 200px; height: 302px;">
<canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas>
<div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div>
</div>
<div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #e65100; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div>
<div style="width: 100%; margin-top: 20px; background: #3e2723; color: #efebe9; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;">
<div style="color: #d7ccc8; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #5d4037;">Énergie Totale Transférée</div>
<div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #ffab91;">0 J</div>
<div style="color: #d7ccc8; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #5d4037;">Formule en cours</div>
<div id="formule-display" style="font-size: 1.1em; color: #ffd54f; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div>
</div>
<div id="specs" style="margin-top: 20px; background: #fff3e0; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #ffe0b2; color: #333;">
<div style="display: flex; flex-direction: column; gap: 5px;">
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>1650 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>78 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>2350 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>366 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>1700 J/(kg·K)</span></div>
</div>
</div>
</div>
<div style="flex: 2; min-width: 400px;">
<canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas>
<div style="display: flex; gap: 10px; margin-top: 20px;">
<button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button>
<button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const etatLabel = document.getElementById('etat-text');
const tempDisp = document.getElementById('temp-grand');
const qTotalDisp = document.getElementById('q-total-display');
const formuleDisp = document.getElementById('formule-display');
// Propriétés Isobutane
const sub = { cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7 };
let temp = -180, energy = 0, isRunning = false, pts = [];
let isKelvin = false;
const pwr = 4500, masse = 1, maxEnergy = 1350000;
let heatStep = 0;
window.setUnit = function(k) {
isKelvin = k;
document.getElementById('btnKel').style.background = k ? '#e65100' : '#fff';
document.getElementById('btnKel').style.color = k ? '#fff' : '#333';
document.getElementById('btnDeg').style.background = k ? '#fff' : '#e65100';
document.getElementById('btnDeg').style.color = k ? '#333' : '#fff';
updateDisplay();
};
window.toggleSim = function() {
if(temp >= 150) return;
isRunning = !isRunning;
document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateDisplay() {
tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C";
qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J";
}
function update() {
if(!isRunning) return;
// CONDITION DE FIN : Suppression de la formule
if(temp >= 150) {
temp = 150.0; isRunning = false;
heater.style.background = "#444";
document.getElementById('btnStart').innerText = "TERMINÉ";
document.getElementById('btnStart').style.background = "#999";
formuleDisp.innerHTML = ""; // Efface la formule
return;
}
heatStep++;
heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c";
energy += pwr * 1.5;
let q1 = masse * sub.cs * (sub.tf - (-180));
let q2 = masse * sub.lf;
let q3 = masse * sub.cl * (sub.tv - sub.tf);
let q4 = masse * sub.lv;
if (energy < q1) {
temp = -180 + energy/(masse*sub.cs);
etatLabel.innerText = "SOLIDE";
formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT";
}
else if (energy < q1+q2) {
temp = sub.tf;
etatLabel.innerText = "FUSION";
formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>";
}
else if (energy < q1+q2+q3) {
temp = sub.tf + (energy-q1-q2)/(masse*sub.cl);
etatLabel.innerText = "LIQUIDE";
formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT";
}
else if (energy < q1+q2+q3+q4) {
temp = sub.tv;
etatLabel.innerText = "ÉBULLITION";
formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>";
}
else {
temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg);
if(temp > 150) temp = 150;
etatLabel.innerText = "GAZ";
formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT";
}
pts.push({x: energy, y: temp});
updateDisplay();
}
function drawArrows(ctx, x, y, angle) {
ctx.save(); ctx.translate(x, y); ctx.rotate(angle);
ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke();
ctx.restore();
}
function draw() {
bCtx.clearRect(0,0,200,280);
let level = 120, bBottom = 280, bWidth = 200;
let q1 = masse*sub.cs*(sub.tf - (-180)), q2 = masse*sub.lf, q3 = masse*sub.cl*(sub.tv-sub.tf), q4 = masse*sub.lv;
if (temp < sub.tf) { bCtx.fillStyle = "#ffccbc"; bCtx.fillRect(15, bBottom - level, 170, level); }
else if (temp === sub.tf) {
let r = (energy-q1)/q2;
bCtx.fillStyle = "#e65100"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r);
bCtx.fillStyle = "#ffccbc"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r));
} else if (temp < sub.tv) { bCtx.fillStyle = "#e65100"; bCtx.fillRect(0, bBottom-level, bWidth, level); }
else if (temp === sub.tv) {
let rv = (energy-(q1+q2+q3))/q4;
bCtx.fillStyle = "#e65100"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv));
bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom);
} else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); }
gCtx.clearRect(0,0,600,400);
gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1;
const marks = [-180, sub.tf, sub.tv, 50, 150];
marks.forEach((tVal) => {
let y = 350 - ((tVal + 180) / 330) * 300;
gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke();
let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C";
gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5);
});
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke();
drawArrows(gCtx, 50, 20, -Math.PI/2);
gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke();
drawArrows(gCtx, 580, 350, 0);
gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial";
gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25);
gCtx.fillText("Q (Joules)", 510, 340);
if(pts.length > 1) {
gCtx.beginPath(); gCtx.strokeStyle = "#e65100"; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let x = 50 + (p.x / maxEnergy) * 520;
let y = 350 - ((p.y + 180) / 330) * 300;
if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
loop();
})();
</script>
Relever la température de fusion Tf = et la température d'ébullition Tvap = Identifier la substance : La pente entre deux paliers dépend de quelle propriété ? Calculer l'énergie nécessaire pour chauffer 2 kg de cette substance liquide de -20°C à -10 °C Q = = =
- isobutane
- méthane
- ammoniac
- difluorométhane
- eau
- tétrafluoropropène
- La capacité thermique
- La couleur de la substance
- Seulement de la puissance
- 2 . 2350 . 10
- 2 . 1650 . 10
- 2 . 75 . 10
- 2 . 366 . 10
- 2 . 1700 .10
VALIDER
non
<div id="sim-difluoro-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;">
<h2 style="margin: 0; color: #00796b; font-size: 1.4em;">🔬 Analyse Thermique : Difluorométhane (CH₂F₂)</h2>
<div style="display: flex; align-items: center; gap: 15px;">
<div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;">
<button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #00796b; color: white;">°C</button>
<button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button>
</div>
<div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-160.0 °C</div>
</div>
</div>
<div style="display: flex; gap: 25px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 200px; height: 302px;">
<canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas>
<div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div>
</div>
<div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #00796b; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div>
<div style="width: 100%; margin-top: 20px; background: #004d40; color: #e0f2f1; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;">
<div style="color: #80cbc4; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #00695c;">Énergie Totale Transférée</div>
<div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #4dd0e1;">0 J</div>
<div style="color: #80cbc4; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #00695c;">Formule en cours</div>
<div id="formule-display" style="font-size: 1.1em; color: #ffeb3b; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div>
</div>
<div id="specs" style="margin-top: 20px; background: #e0f2f1; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #b2dfdb; color: #333;">
<div style="display: flex; flex-direction: column; gap: 5px;">
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>1450 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>133 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>1910 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>390 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>840 J/(kg·K)</span></div>
</div>
</div>
</div>
<div style="flex: 2; min-width: 400px;">
<canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas>
<div style="display: flex; gap: 10px; margin-top: 20px;">
<button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button>
<button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const etatLabel = document.getElementById('etat-text');
const tempDisp = document.getElementById('temp-grand');
const qTotalDisp = document.getElementById('q-total-display');
const formuleDisp = document.getElementById('formule-display');
// Propriétés Difluorométhane (R-32)
const sub = { cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136.0, tv: -51.7 };
let temp = -160, energy = 0, isRunning = false, pts = [];
let isKelvin = false;
const pwr = 4500, masse = 1, maxEnergy = 1100000;
let heatStep = 0;
window.setUnit = function(k) {
isKelvin = k;
document.getElementById('btnKel').style.background = k ? '#00796b' : '#fff';
document.getElementById('btnKel').style.color = k ? '#fff' : '#333';
document.getElementById('btnDeg').style.background = k ? '#fff' : '#00796b';
document.getElementById('btnDeg').style.color = k ? '#333' : '#fff';
updateDisplay();
};
window.toggleSim = function() {
if(temp >= 150) return;
isRunning = !isRunning;
document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateDisplay() {
tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C";
qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J";
}
function update() {
if(!isRunning) return;
// CONDITION DE FIN : Suppression de la formule ici
if(temp >= 150) {
temp = 150.0;
isRunning = false;
heater.style.background = "#444";
document.getElementById('btnStart').innerText = "TERMINÉ";
document.getElementById('btnStart').style.background = "#999";
formuleDisp.innerHTML = ""; // La formule disparaît
return;
}
heatStep++;
heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c";
energy += pwr * 1.5;
let q1 = masse * sub.cs * (sub.tf - (-160));
let q2 = masse * sub.lf;
let q3 = masse * sub.cl * (sub.tv - sub.tf);
let q4 = masse * sub.lv;
if (energy < q1) {
temp = -160 + energy/(masse*sub.cs);
etatLabel.innerText = "SOLIDE";
formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT";
}
else if (energy < q1+q2) {
temp = sub.tf;
etatLabel.innerText = "FUSION";
formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>";
}
else if (energy < q1+q2+q3) {
temp = sub.tf + (energy-q1-q2)/(masse*sub.cl);
etatLabel.innerText = "LIQUIDE";
formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT";
}
else if (energy < q1+q2+q3+q4) {
temp = sub.tv;
etatLabel.innerText = "ÉBULLITION";
formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>";
}
else {
temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg);
if(temp > 150) temp = 150;
etatLabel.innerText = "GAZ";
formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT";
}
pts.push({x: energy, y: temp});
updateDisplay();
}
function drawArrows(ctx, x, y, angle) {
ctx.save(); ctx.translate(x, y); ctx.rotate(angle);
ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke();
ctx.restore();
}
function draw() {
bCtx.clearRect(0,0,200,280);
let level = 120, bBottom = 280, bWidth = 200;
let q1 = masse*sub.cs*(sub.tf - (-160)), q2 = masse*sub.lf, q3 = masse*sub.cl*(sub.tv-sub.tf), q4 = masse*sub.lv;
if (temp < sub.tf) { bCtx.fillStyle = "#b2dfdb"; bCtx.fillRect(15, bBottom - level, 170, level); }
else if (temp === sub.tf) {
let r = (energy-q1)/q2;
bCtx.fillStyle = "#00796b"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r);
bCtx.fillStyle = "#b2dfdb"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r));
} else if (temp < sub.tv) { bCtx.fillStyle = "#00796b"; bCtx.fillRect(0, bBottom-level, bWidth, level); }
else if (temp === sub.tv) {
let rv = (energy-(q1+q2+q3))/q4;
bCtx.fillStyle = "#00796b"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv));
bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom);
} else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); }
gCtx.clearRect(0,0,600,400);
gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1;
const marks = [-160, sub.tf, sub.tv, 50, 150];
marks.forEach((tVal) => {
let y = 350 - ((tVal + 160) / 310) * 300;
gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke();
let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C";
gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5);
});
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke();
drawArrows(gCtx, 50, 20, -Math.PI/2);
gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke();
drawArrows(gCtx, 580, 350, 0);
gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial";
gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25);
gCtx.fillText("Q (Joules)", 510, 340);
if(pts.length > 1) {
gCtx.beginPath(); gCtx.strokeStyle = "#00796b"; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let x = 50 + (p.x / maxEnergy) * 520;
let y = 350 - ((p.y + 160) / 310) * 300;
if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
loop();
})();
</script>
<div id="sim-difluoro-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;">
<h2 style="margin: 0; color: #00796b; font-size: 1.4em;">🔬 Analyse Thermique : Difluorométhane (CH₂F₂)</h2>
<div style="display: flex; align-items: center; gap: 15px;">
<div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;">
<button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #00796b; color: white;">°C</button>
<button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button>
</div>
<div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-160.0 °C</div>
</div>
</div>
<div style="display: flex; gap: 25px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 200px; height: 302px;">
<canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas>
<div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div>
</div>
<div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #00796b; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div>
<div style="width: 100%; margin-top: 20px; background: #004d40; color: #e0f2f1; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;">
<div style="color: #80cbc4; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #00695c;">Énergie Totale Transférée</div>
<div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #4dd0e1;">0 J</div>
<div style="color: #80cbc4; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #00695c;">Formule en cours</div>
<div id="formule-display" style="font-size: 1.1em; color: #ffeb3b; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div>
</div>
<div id="specs" style="margin-top: 20px; background: #e0f2f1; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #b2dfdb; color: #333;">
<div style="display: flex; flex-direction: column; gap: 5px;">
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>1450 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>133 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>1910 J/(kg·K)</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>390 kJ/kg</span></div>
<div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>840 J/(kg·K)</span></div>
</div>
</div>
</div>
<div style="flex: 2; min-width: 400px;">
<canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas>
<div style="display: flex; gap: 10px; margin-top: 20px;">
<button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button>
<button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const etatLabel = document.getElementById('etat-text');
const tempDisp = document.getElementById('temp-grand');
const qTotalDisp = document.getElementById('q-total-display');
const formuleDisp = document.getElementById('formule-display');
// Propriétés Difluorométhane (R-32)
const sub = { cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136.0, tv: -51.7 };
let temp = -160, energy = 0, isRunning = false, pts = [];
let isKelvin = false;
const pwr = 4500, masse = 1, maxEnergy = 1100000;
let heatStep = 0;
window.setUnit = function(k) {
isKelvin = k;
document.getElementById('btnKel').style.background = k ? '#00796b' : '#fff';
document.getElementById('btnKel').style.color = k ? '#fff' : '#333';
document.getElementById('btnDeg').style.background = k ? '#fff' : '#00796b';
document.getElementById('btnDeg').style.color = k ? '#333' : '#fff';
updateDisplay();
};
window.toggleSim = function() {
if(temp >= 150) return;
isRunning = !isRunning;
document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateDisplay() {
tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C";
qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J";
}
function update() {
if(!isRunning) return;
if(temp >= 150) {
temp = 150.0; isRunning = false;
heater.style.background = "#444";
document.getElementById('btnStart').innerText = "TERMINÉ";
document.getElementById('btnStart').style.background = "#999";
return;
}
heatStep++;
heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c";
energy += pwr * 1.5;
let q1 = masse * sub.cs * (sub.tf - (-160));
let q2 = masse * sub.lf;
let q3 = masse * sub.cl * (sub.tv - sub.tf);
let q4 = masse * sub.lv;
if (energy < q1) {
temp = -160 + energy/(masse*sub.cs);
etatLabel.innerText = "SOLIDE";
formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT";
}
else if (energy < q1+q2) {
temp = sub.tf;
etatLabel.innerText = "FUSION";
formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>";
}
else if (energy < q1+q2+q3) {
temp = sub.tf + (energy-q1-q2)/(masse*sub.cl);
etatLabel.innerText = "LIQUIDE";
formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT";
}
else if (energy < q1+q2+q3+q4) {
temp = sub.tv;
etatLabel.innerText = "ÉBULLITION";
formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>";
}
else {
temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg);
if(temp > 150) temp = 150;
etatLabel.innerText = "GAZ";
formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT";
}
pts.push({x: energy, y: temp});
updateDisplay();
}
function drawArrows(ctx, x, y, angle) {
ctx.save(); ctx.translate(x, y); ctx.rotate(angle);
ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke();
ctx.restore();
}
function draw() {
bCtx.clearRect(0,0,200,280);
let level = 120, bBottom = 280, bWidth = 200;
let q1 = masse*sub.cs*(sub.tf - (-160)), q2 = masse*sub.lf, q3 = masse*sub.cl*(sub.tv-sub.tf), q4 = masse*sub.lv;
if (temp < sub.tf) { bCtx.fillStyle = "#b2dfdb"; bCtx.fillRect(15, bBottom - level, 170, level); }
else if (temp === sub.tf) {
let r = (energy-q1)/q2;
bCtx.fillStyle = "#00796b"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r);
bCtx.fillStyle = "#b2dfdb"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r));
} else if (temp < sub.tv) { bCtx.fillStyle = "#00796b"; bCtx.fillRect(0, bBottom-level, bWidth, level); }
else if (temp === sub.tv) {
let rv = (energy-(q1+q2+q3))/q4;
bCtx.fillStyle = "#00796b"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv));
bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom);
} else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); }
gCtx.clearRect(0,0,600,400);
gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1;
const marks = [-160, sub.tf, sub.tv, 50, 150];
marks.forEach((tVal) => {
let y = 350 - ((tVal + 160) / 310) * 300;
gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke();
let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C";
gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5);
});
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke();
drawArrows(gCtx, 50, 20, -Math.PI/2);
gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke();
drawArrows(gCtx, 580, 350, 0);
gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial";
gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25);
gCtx.fillText("Q (Joules)", 510, 340);
if(pts.length > 1) {
gCtx.beginPath(); gCtx.strokeStyle = "#00796b"; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let x = 50 + (p.x / maxEnergy) * 520;
let y = 350 - ((p.y + 160) / 310) * 300;
if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
loop();
})();
</script>
Relever la température de fusion Tf = et la température d'ébullition Tvap = Identifier la substance : Si l'on double la puissance du chauffage P en Watt, alors diminue de moitié. Calculer l'énergie nécessaire pour chauffer 300g de cette substance liquide sous forme de gaz de 20°C à 40°C. Q = = =
$CALEX4|=|1
- difluorométhane
- méthane
- ammoniac
- isobutane
- eau
- tétrafluoropropène
- le temps nécessaire
- la longueurs des paliers
- l'énergie totale
- 0,3 . 840 . 20
- 0,3 . 1450 . 20
- 0,3 . 1910 . 20
- 0,3 . 133 . 20
- 0,3 . 390 . 20
- 5,04kJ
- 8,7kJ
- 11,4kJ
- 2340kJ
- 0,798kJ
VALIDER
non
Spécialiste calorimetrie
?$CALEX1|=|1&CALEX2|=|1&CALEX3|=|1&CALEX4|=|1&CAL1|=|1&CAL2|=|1&CAL3|=|1
§nom§
ANNEE
<div id="sim-thermo-challenge-final" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd; flex-wrap: wrap; gap: 15px;">
<div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;">
<div>
<label style="font-weight: bold; color: #444;">Choix :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #1565c0; cursor: pointer;">
<option value="subA">Substance A</option>
<option value="subB">Substance B</option>
<option value="subC">Substance C</option>
<option value="subD">Substance D</option>
<option value="subE">Substance E</option>
</select>
</div>
<div>
<label style="font-weight: bold; color: #444;">Masse :</label>
<select id="selectMasse" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; cursor: pointer;">
<option value="1">1 kg</option>
<option value="2">2 kg</option>
<option value="5">5 kg</option>
<option value="10">10 kg</option>
</select>
</div>
</div>
<div id="temp-grand" style="font-size: 3.2em; font-weight: bold; color: #d32f2f; font-family: monospace; background: #fff; padding: 5px 15px; border-radius: 10px; border: 1px solid #ccc; min-width: 200px; text-align: center;">-200.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.4em; font-weight: bold; color: #1565c0; text-align: center;">-</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.2em; margin-bottom: 10px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-bottom: 8px;">FORMULE APPLIQUÉE</div>
<div id="q-val" style="font-size: 1.6em; color: #ffeb3b; margin-bottom: 8px;">0 J</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; border-top: 1px solid #333; padding-top: 8px;">Q = m · cₛ · ΔT</div>
</div>
</div>
<div style="flex: 2; min-width: 450px; display: flex; flex-direction: column;">
<canvas id="graphSim" width="600" height="420" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 10px; margin-top: 20px; justify-content: flex-end;">
<button id="btnPlay" onclick="toggleSim()" style="width: 160px; padding: 15px; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 1.1em; box-shadow: 0 4px #1b5e20;">DÉMARRER</button>
<button onclick="resetSim()" style="padding: 15px; background: #546e7a; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const selectF = document.getElementById('selectFluide'), selectM = document.getElementById('selectMasse');
const db = {
subA: { label: "Substance A", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114, tv: 78, isCO2: false },
subB: { label: "Substance B", cs: 850, cg: 840, ls: 571000, ts: -78.5, isCO2: true },
subC: { label: "Substance C", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155, tv: -82, isCO2: false },
subD: { label: "Substance D", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -188, tv: -42, isCO2: false },
subE: { label: "Substance E", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152, tv: -29, isCO2: false }
};
let s, temp, energy, masse, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 4500, tStart = -200, tEnd = 200;
let gasParticles = [];
window.initSubstance = function() {
s = db[selectF.value];
masse = parseFloat(selectM.value);
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER";
document.getElementById('btnPlay').style.background = "#2e7d32";
gasParticles = [];
updateUI();
};
window.toggleSim = function() {
if(temp >= tEnd && isRunning) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
window.resetSim = function() { initSubstance(); };
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.label + " (" + masse + " kg)";
}
function update() {
if(!isRunning || temp >= tEnd) { heater.style.background = "#333"; return; }
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 8) % 2 === 0) ? "#d32f2f" : "#333";
energy += pwr * 15;
const fText = document.getElementById('formule-text');
const eText = document.getElementById('etat-text');
if (s.isCO2) {
let q1 = masse * s.cs * (s.ts - tStart);
let q2 = masse * s.ls;
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
eText.innerText = "ÉTAT : SOLIDE"; fText.innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.ts;
eText.innerText = "ÉTAT : SUBLIMATION"; fText.innerHTML = "Q = m · Lₛ";
} else {
temp = s.ts + (energy - q1 - q2)/(masse*s.cg);
eText.innerText = "ÉTAT : GAZ"; fText.innerHTML = "Q = m · cₚ · ΔT";
}
} else {
let q1 = masse * s.cs * (s.tf - tStart), q2 = masse * s.lf;
let q3 = masse * s.cl * (s.tv - s.tf), q4 = masse * s.lv;
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
eText.innerText = "ÉTAT : SOLIDE"; fText.innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.tf;
eText.innerText = "ÉTAT : FUSION"; fText.innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = s.tf + (energy - q1 - q2)/(masse*s.cl);
eText.innerText = "ÉTAT : LIQUIDE"; fText.innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = s.tv;
eText.innerText = "ÉTAT : ÉBULLITION"; fText.innerHTML = "Q = m · Lv";
} else {
temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg);
eText.innerText = "ÉTAT : GAZ"; fText.innerHTML = "Q = m · cₚ · ΔT";
}
}
pts.push({x: energy, y: temp});
updateUI();
if(gasParticles.length > 0) {
let speed = 0.5 + ((temp + 200) * 0.015);
gasParticles.forEach(p => {
p.x += p.vx * speed; p.y += p.vy * speed;
if(p.x < 10 || p.x > 210) p.vx *= -1; if(p.y < 10 || p.y > 290) p.vy *= -1;
});
}
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 40 + (masse * 15);
if(s.isCO2) {
let q1 = masse * s.cs * (s.ts - tStart), q2 = masse * s.ls;
if (temp < s.ts) {
bCtx.fillStyle = "#ccc"; bCtx.fillRect(40, 300-hMax, 140, hMax);
} else if (temp === s.ts) {
let r = Math.min(1, (energy-q1)/q2);
bCtx.fillStyle = "#ccc"; bCtx.fillRect(40, 300-hMax, 140, hMax*(1-r));
if(gasParticles.length < Math.floor(r*60)) gasParticles.push({x: 110, y: 250, vx: Math.random()*2-1, vy: -Math.random()*2, r: 3});
bCtx.fillStyle = "rgba(220,220,220,0.5)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); });
} else {
bCtx.fillStyle = "rgba(200,200,200,0.6)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r+1, 0, 7); bCtx.fill(); });
}
} else {
let q1 = masse * s.cs * (s.tf - tStart), q2 = masse * s.lf, q3 = masse * s.cl * (s.tv - s.tf);
if(temp < s.tf) {
bCtx.fillStyle = "#64b5f6"; bCtx.fillRect(40, 300-hMax, 140, hMax);
} else if (temp === s.tf) {
let r = Math.min(1, (energy-q1)/q2);
bCtx.fillStyle = "#e3f2fd"; bCtx.fillRect(10, 300-(hMax*r), 220, hMax*r);
bCtx.fillStyle = "#64b5f6"; bCtx.fillRect(40, 300-hMax, 140, hMax*(1-r));
} else if (temp < s.tv) {
bCtx.fillStyle = "#e3f2fd"; bCtx.fillRect(10, 300-hMax, 200, hMax);
} else {
if(gasParticles.length < 60) gasParticles.push({x: 110, y: 200, vx: Math.random()*4-2, vy: Math.random()*4-2, r: 2.5});
bCtx.fillStyle = "rgba(180,210,255,0.5)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); });
}
}
gCtx.clearRect(0,0,600,420);
gCtx.strokeStyle = "#444"; gCtx.lineWidth = 2;
// Axe Y avec flèche
gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(60, 20); gCtx.stroke();
gCtx.beginPath(); gCtx.moveTo(55, 30); gCtx.lineTo(60, 15); gCtx.lineTo(65, 30); gCtx.fill();
gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T", 40, 25);
// Axe X avec flèche
gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(580, 390); gCtx.stroke();
gCtx.beginPath(); gCtx.moveTo(575, 385); gCtx.lineTo(590, 390); gCtx.lineTo(575, 395); gCtx.fill();
gCtx.fillText("Q", 580, 410);
let xMax = masse * 1500000;
for(let t=-200; t<=200; t+=50) {
let y = 390 - ((t+200)/400)*350;
gCtx.fillStyle = "#888"; gCtx.font = "10px Arial";
gCtx.fillText(t, 30, y+4);
gCtx.beginPath(); gCtx.moveTo(55,y); gCtx.lineTo(60,y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = "#1565c0"; gCtx.lineWidth = 3;
pts.forEach((p, i) => {
let px = 60 + (p.x / xMax) * 500;
let py = 390 - ((p.y + 200) / 400) * 350;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-co2-fix" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd; flex-wrap: wrap; gap: 15px;">
<div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;">
<div>
<label style="font-weight: bold; color: #444;">Choix :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #1565c0; cursor: pointer;">
<option value="subA">Substance A</option>
<option value="subB">Substance B</option>
<option value="subC">Substance C</option>
<option value="subD">Substance D</option>
<option value="subE">Substance E</option>
</select>
</div>
<div>
<label style="font-weight: bold; color: #444;">Masse :</label>
<select id="selectMasse" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; cursor: pointer;">
<option value="1">1 kg</option>
<option value="2">2 kg</option>
<option value="5">5 kg</option>
<option value="10">10 kg</option>
</select>
</div>
</div>
<div id="temp-grand" style="font-size: 3.2em; font-weight: bold; color: #d32f2f; font-family: monospace; background: #fff; padding: 5px 15px; border-radius: 10px; border: 1px solid #ccc; min-width: 200px; text-align: center;">-200.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.4em; font-weight: bold; color: #1565c0; text-align: center;">-</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.2em; margin-bottom: 10px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-bottom: 8px;">FORMULE APPLIQUÉE</div>
<div id="q-val" style="font-size: 1.6em; color: #ffeb3b; margin-bottom: 8px;">0 J</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; border-top: 1px solid #333; padding-top: 8px;">Q = m · cₛ · ΔT</div>
</div>
</div>
<div style="flex: 2; min-width: 450px; display: flex; flex-direction: column;">
<canvas id="graphSim" width="600" height="420" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 10px; margin-top: 20px; justify-content: flex-end;">
<button id="btnPlay" onclick="toggleSim()" style="width: 160px; padding: 15px; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 1.1em; box-shadow: 0 4px #1b5e20;">DÉMARRER</button>
<button onclick="resetSim()" style="padding: 15px; background: #546e7a; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const selectF = document.getElementById('selectFluide'), selectM = document.getElementById('selectMasse');
const db = {
subA: { label: "Substance A", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114, tv: 78, isCO2: false },
subB: { label: "Substance B", cs: 850, cg: 840, ls: 571000, ts: -78.5, isCO2: true }, // CO2 : Sublimation directe
subC: { label: "Substance C", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155, tv: -82, isCO2: false },
subD: { label: "Substance D", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -188, tv: -42, isCO2: false },
subE: { label: "Substance E", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152, tv: -29, isCO2: false }
};
let s, temp, energy, masse, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 4500, tStart = -200, tEnd = 200;
let gasParticles = [];
window.initSubstance = function() {
s = db[selectF.value];
masse = parseFloat(selectM.value);
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER";
document.getElementById('btnPlay').style.background = "#2e7d32";
gasParticles = [];
updateUI();
};
window.toggleSim = function() {
if(temp >= tEnd && isRunning) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
window.resetSim = function() { initSubstance(); };
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.label + " (" + masse + " kg)";
}
function update() {
if(!isRunning || temp >= tEnd) { heater.style.background = "#333"; return; }
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 8) % 2 === 0) ? "#d32f2f" : "#333";
energy += pwr * 15;
const fText = document.getElementById('formule-text');
const eText = document.getElementById('etat-text');
if (s.isCO2) {
let q1 = masse * s.cs * (s.ts - tStart);
let q2 = masse * s.ls;
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
eText.innerText = "ÉTAT : SOLIDE"; fText.innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.ts;
eText.innerText = "ÉTAT : SUBLIMATION"; fText.innerHTML = "Q = m · Lₛ";
} else {
temp = s.ts + (energy - q1 - q2)/(masse*s.cg);
eText.innerText = "ÉTAT : GAZ"; fText.innerHTML = "Q = m · cₚ · ΔT";
}
} else {
let q1 = masse * s.cs * (s.tf - tStart), q2 = masse * s.lf;
let q3 = masse * s.cl * (s.tv - s.tf), q4 = masse * s.lv;
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
eText.innerText = "ÉTAT : SOLIDE"; fText.innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.tf;
eText.innerText = "ÉTAT : FUSION"; fText.innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = s.tf + (energy - q1 - q2)/(masse*s.cl);
eText.innerText = "ÉTAT : LIQUIDE"; fText.innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = s.tv;
eText.innerText = "ÉTAT : ÉBULLITION"; fText.innerHTML = "Q = m · Lv";
} else {
temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg);
eText.innerText = "ÉTAT : GAZ"; fText.innerHTML = "Q = m · cₚ · ΔT";
}
}
pts.push({x: energy, y: temp});
updateUI();
if(gasParticles.length > 0) {
let speed = 0.5 + ((temp + 200) * 0.015);
gasParticles.forEach(p => {
p.x += p.vx * speed; p.y += p.vy * speed;
if(p.x < 10 || p.x > 210) p.vx *= -1; if(p.y < 10 || p.y > 290) p.vy *= -1;
});
}
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 40 + (masse * 15);
if(s.isCO2) {
let q1 = masse * s.cs * (s.ts - tStart), q2 = masse * s.ls;
if (temp < s.ts) {
bCtx.fillStyle = "#ccc"; bCtx.fillRect(40, 300-hMax, 140, hMax); // Glace carbonique
} else if (temp === s.ts) {
let r = Math.min(1, (energy-q1)/q2);
bCtx.fillStyle = "#ccc"; bCtx.fillRect(40, 300-hMax, 140, hMax*(1-r));
if(gasParticles.length < Math.floor(r*60)) gasParticles.push({x: 110, y: 250, vx: Math.random()*2-1, vy: -Math.random()*2, r: 3});
bCtx.fillStyle = "rgba(220,220,220,0.5)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); });
} else {
bCtx.fillStyle = "rgba(200,200,200,0.6)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r+1, 0, 7); bCtx.fill(); });
}
} else {
// Dessin standard (Solide -> Liquide -> Gaz)
let q1 = masse * s.cs * (s.tf - tStart), q2 = masse * s.lf, q3 = masse * s.cl * (s.tv - s.tf);
if(temp < s.tf) {
bCtx.fillStyle = "#64b5f6"; bCtx.fillRect(40, 300-hMax, 140, hMax);
} else if (temp === s.tf) {
let r = Math.min(1, (energy-q1)/q2);
bCtx.fillStyle = "#e3f2fd"; bCtx.fillRect(10, 300-(hMax*r), 200, hMax*r);
bCtx.fillStyle = "#64b5f6"; bCtx.fillRect(40, 300-hMax, 140, hMax*(1-r));
} else if (temp < s.tv) {
bCtx.fillStyle = "#e3f2fd"; bCtx.fillRect(10, 300-hMax, 200, hMax);
} else {
if(gasParticles.length < 60) gasParticles.push({x: 110, y: 200, vx: Math.random()*4-2, vy: Math.random()*4-2, r: 2.5});
bCtx.fillStyle = "rgba(180,210,255,0.5)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); });
}
}
gCtx.clearRect(0,0,600,420);
gCtx.strokeStyle = "#444"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(60, 20); gCtx.stroke();
gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(580, 390); gCtx.stroke();
let xMax = masse * 1500000;
for(let t=-200; t<=200; t+=50) {
let y = 390 - ((t+200)/400)*350;
gCtx.fillStyle = "#888"; gCtx.font = "10px Arial";
gCtx.fillText(t, 30, y+4);
gCtx.beginPath(); gCtx.moveTo(55,y); gCtx.lineTo(60,y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = "#1565c0"; gCtx.lineWidth = 3;
pts.forEach((p, i) => {
let px = 60 + (p.x / xMax) * 500;
let py = 390 - ((p.y + 200) / 400) * 350;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-mystere" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd; flex-wrap: wrap; gap: 15px;">
<div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;">
<div>
<label style="font-weight: bold; color: #444;">Choix :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #1565c0; cursor: pointer;">
<option value="subA">Substance A</option>
<option value="subB">Substance B</option>
<option value="subC">Substance C</option>
<option value="subD">Substance D</option>
<option value="subE">Substance E</option>
</select>
</div>
<div>
<label style="font-weight: bold; color: #444;">Masse :</label>
<select id="selectMasse" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; cursor: pointer;">
<option value="1">1 kg</option>
<option value="2">2 kg</option>
<option value="4">4 kg</option>
<option value="6">6 kg</option>
<option value="8">8 kg</option>
<option value="10">10 kg</option>
</select>
</div>
</div>
<div id="temp-grand" style="font-size: 3.2em; font-weight: bold; color: #d32f2f; font-family: monospace; background: #fff; padding: 5px 15px; border-radius: 10px; border: 1px solid #ccc; min-width: 200px; text-align: center;">-200.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.4em; font-weight: bold; color: #1565c0; text-align: center;">-</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.2em; margin-bottom: 10px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-bottom: 8px;">ÉNERGIE (Q)</div>
<div id="q-val" style="font-size: 1.6em; color: #ffeb3b; margin-bottom: 8px;">0 J</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; border-top: 1px solid #333; padding-top: 8px;">Q = m · cₛ · ΔT</div>
</div>
</div>
<div style="flex: 2; min-width: 450px; display: flex; flex-direction: column;">
<canvas id="graphSim" width="600" height="420" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 10px; margin-top: 20px; justify-content: flex-end;">
<button id="btnPlay" onclick="toggleSim()" style="width: 160px; padding: 15px; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 1.1em; box-shadow: 0 4px #1b5e20;">DÉMARRER</button>
<button onclick="resetSim()" style="padding: 15px; background: #546e7a; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const selectF = document.getElementById('selectFluide'), selectM = document.getElementById('selectMasse');
// Les données réelles sont conservées mais les noms sont masqués
const db = {
subA: { label: "Substance A", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114.1, tv: 78.3, colorL: "#e3f2fd", colorS: "#64b5f6" },
subB: { label: "Substance B", cs: 850, cl: 2000, cg: 840, lf: 199000, lv: 571000, tf: -56.6, tv: -78.5, colorL: "#f5f5f5", colorS: "#bdbdbd" },
subC: { label: "Substance C", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155.1, tv: -82.1, colorL: "#e0f7fa", colorS: "#4dd0e1" },
subD: { label: "Substance D", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -187.7, tv: -42.1, colorL: "#fff3e0", colorS: "#ffb74d" },
subE: { label: "Substance E", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152.2, tv: -29.4, colorL: "#f1f8e9", colorS: "#aed581" }
};
let s, temp, energy, masse, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 4500, tStart = -200, tEnd = 200;
let gasParticles = [];
window.initSubstance = function() {
s = db[selectF.value];
masse = parseFloat(selectM.value);
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER";
document.getElementById('btnPlay').style.background = "#2e7d32";
gasParticles = [];
updateUI();
};
window.toggleSim = function() {
if(temp >= tEnd && isRunning) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
window.resetSim = function() { initSubstance(); };
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.label + " (" + masse + " kg)";
}
function update() {
if(isRunning && temp < tEnd) {
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 8) % 2 === 0) ? "#d32f2f" : "#333";
energy += pwr * 12;
let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20);
let q1 = masse * s.cs * (tFus - tStart);
let q2 = masse * s.lf;
let q3 = masse * s.cl * (tVap - tFus);
let q4 = masse * s.lv;
const fText = document.getElementById('formule-text');
const eText = document.getElementById('etat-text');
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
eText.innerText = "ÉTAT : SOLIDE";
fText.innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = tFus;
eText.innerText = "ÉTAT : FUSION";
fText.innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = tFus + (energy - q1 - q2)/(masse*s.cl);
eText.innerText = "ÉTAT : LIQUIDE";
fText.innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = tVap;
eText.innerText = "ÉTAT : ÉBULLITION";
fText.innerHTML = "Q = m · Lv";
} else {
temp = tVap + (energy - q1 - q2 - q3 - q4)/(masse*s.cg);
eText.innerText = "ÉTAT : GAZ";
fText.innerHTML = "Q = m · cₚ · ΔT";
}
if(temp > tEnd) { temp = tEnd; isRunning = false; }
pts.push({x: energy, y: temp});
updateUI();
} else { heater.style.background = "#333"; }
if(gasParticles.length > 0) {
let speedFactor = 0.5 + ((temp + 200) * 0.015);
gasParticles.forEach(p => {
p.x += p.vx * speedFactor; p.y += p.vy * speedFactor;
if(p.x < 10 || p.x > 210) p.vx *= -1;
if(p.y < 10 || p.y > 290) p.vy *= -1;
});
}
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 40 + (masse * 20);
let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20);
let q1 = masse * s.cs * (tFus - tStart), q2 = masse * s.lf, q3 = masse * s.cl * (tVap - tFus);
if(temp < tFus) {
bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax);
} else if (temp === tFus) {
let r = Math.min(1, (energy-q1)/q2);
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*r), 220, hMax*r);
bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax*(1-r));
} else if (temp < tVap) {
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax);
} else if (temp === tVap) {
let rV = Math.min(1, (energy-q1-q2-q3)/(masse*s.lv));
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*(1-rV)), 220, hMax*(1-rV));
if(gasParticles.length < Math.floor(rV*60)) {
gasParticles.push({x: 110, y: 150, vx: Math.random()*3-1.5, vy: Math.random()*3-1.5, r: 2.5});
}
bCtx.fillStyle = "rgba(180,210,255,0.4)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); });
} else {
if(gasParticles.length < 60) gasParticles.push({x: 110, y: 150, vx: Math.random()*3-1.5, vy: Math.random()*3-1.5, r: 2.5});
bCtx.fillStyle = "rgba(160,200,255,0.6)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r+1, 0, 7); bCtx.fill(); });
}
gCtx.clearRect(0,0,600,420);
gCtx.strokeStyle = "#444"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(60, 20); gCtx.stroke();
gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(580, 390); gCtx.stroke();
let xMax = masse * 1500000;
gCtx.fillStyle = "#000"; gCtx.font = "bold 12px Arial";
gCtx.fillText("T (°C)", 15, 25); gCtx.fillText("Énergie Q (Joules)", 480, 410);
gCtx.font = "10px Arial"; gCtx.fillStyle = "#888";
for(let t=-200; t<=200; t+=50) {
let y = 390 - ((t+200)/400)*350;
gCtx.fillText(t, 30, y+4);
gCtx.beginPath(); gCtx.moveTo(55,y); gCtx.lineTo(60,y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.colorS; gCtx.lineWidth = 3;
pts.forEach((p, i) => {
let px = 60 + (p.x / xMax) * 500;
let py = 390 - ((p.y + 200) / 400) * 350;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-final-formule" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd; flex-wrap: wrap; gap: 15px;">
<div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;">
<div>
<label style="font-weight: bold; color: #444;">Fluide :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #1565c0; cursor: pointer;">
<option value="ethanol">A : Éthanol</option>
<option value="co2">B : Dioxyde de Carbone</option>
<option value="r23">C : Trifluorométhane (R-23)</option>
<option value="propane">D : Propane (R-290)</option>
<option value="hfo">E : HFO-1234yf (Moderne)</option>
</select>
</div>
<div>
<label style="font-weight: bold; color: #444;">Masse :</label>
<select id="selectMasse" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; cursor: pointer;">
<option value="1">1 kg</option>
<option value="2">2 kg</option>
<option value="3">3 kg</option>
<option value="4">4 kg</option>
<option value="5">5 kg</option>
<option value="6">6 kg</option>
<option value="7">7 kg</option>
<option value="8">8 kg</option>
<option value="9">9 kg</option>
<option value="10">10 kg</option>
</select>
</div>
</div>
<div id="temp-grand" style="font-size: 3.2em; font-weight: bold; color: #d32f2f; font-family: monospace; background: #fff; padding: 5px 15px; border-radius: 10px; border: 1px solid #ccc; min-width: 200px; text-align: center;">-200.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.4em; font-weight: bold; color: #1565c0; text-align: center;">-</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.2em; margin-bottom: 10px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-bottom: 8px;">CALCUL DE L'ÉNERGIE (Q)</div>
<div id="q-val" style="font-size: 1.6em; color: #ffeb3b; margin-bottom: 8px;">0 J</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; border-top: 1px solid #333; padding-top: 8px;">Q = m · cₛ · ΔT</div>
</div>
</div>
<div style="flex: 2; min-width: 450px; display: flex; flex-direction: column;">
<canvas id="graphSim" width="600" height="420" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 10px; margin-top: 20px; justify-content: flex-end;">
<button id="btnPlay" onclick="toggleSim()" style="width: 160px; padding: 15px; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 1.1em; box-shadow: 0 4px #1b5e20;">DÉMARRER</button>
<button onclick="resetSim()" style="padding: 15px; background: #546e7a; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const selectF = document.getElementById('selectFluide'), selectM = document.getElementById('selectMasse');
const db = {
ethanol: { nom: "ÉTHANOL", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114.1, tv: 78.3, colorL: "#e3f2fd", colorS: "#64b5f6" },
co2: { nom: "DIOXYDE DE CARBONE", cs: 850, cl: 2000, cg: 840, lf: 199000, lv: 571000, tf: -56.6, tv: -78.5, colorL: "#f5f5f5", colorS: "#bdbdbd" },
r23: { nom: "TRIFLUOROMÉTHANE (R-23)", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155.1, tv: -82.1, colorL: "#e0f7fa", colorS: "#4dd0e1" },
propane: { nom: "PROPANE (R-290)", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -187.7, tv: -42.1, colorL: "#fff3e0", colorS: "#ffb74d" },
hfo: { nom: "HFO-1234yf", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152.2, tv: -29.4, colorL: "#f1f8e9", colorS: "#aed581" }
};
let s, temp, energy, masse, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 4500, tStart = -200, tEnd = 200;
let gasParticles = [];
window.initSubstance = function() {
s = db[selectF.value];
masse = parseFloat(selectM.value);
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER";
document.getElementById('btnPlay').style.background = "#2e7d32";
gasParticles = [];
updateUI();
};
window.toggleSim = function() {
if(temp >= tEnd && isRunning) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
window.resetSim = function() { initSubstance(); };
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.nom + " (" + masse + " kg)";
}
function update() {
if(isRunning && temp < tEnd) {
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 8) % 2 === 0) ? "#d32f2f" : "#333";
energy += pwr * 12;
let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20);
let q1 = masse * s.cs * (tFus - tStart);
let q2 = masse * s.lf;
let q3 = masse * s.cl * (tVap - tFus);
let q4 = masse * s.lv;
const fText = document.getElementById('formule-text');
const eText = document.getElementById('etat-text');
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
eText.innerText = "ÉTAT : SOLIDE";
fText.innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = tFus;
eText.innerText = "ÉTAT : FUSION";
fText.innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = tFus + (energy - q1 - q2)/(masse*s.cl);
eText.innerText = "ÉTAT : LIQUIDE";
fText.innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = tVap;
eText.innerText = "ÉTAT : ÉBULLITION";
fText.innerHTML = "Q = m · Lv";
} else {
temp = tVap + (energy - q1 - q2 - q3 - q4)/(masse*s.cg);
eText.innerText = "ÉTAT : GAZ";
fText.innerHTML = "Q = m · cₚ · ΔT";
}
if(temp > tEnd) { temp = tEnd; isRunning = false; }
pts.push({x: energy, y: temp});
updateUI();
} else { heater.style.background = "#333"; }
if(gasParticles.length > 0) {
let speedFactor = 0.5 + ((temp + 200) * 0.015);
gasParticles.forEach(p => {
p.x += p.vx * speedFactor; p.y += p.vy * speedFactor;
if(p.x < 10 || p.x > 210) p.vx *= -1;
if(p.y < 10 || p.y > 290) p.vy *= -1;
});
}
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 40 + (masse * 20);
let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20);
let q1 = masse * s.cs * (tFus - tStart), q2 = masse * s.lf, q3 = masse * s.cl * (tVap - tFus);
if(temp < tFus) {
bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax);
} else if (temp === tFus) {
let r = Math.min(1, (energy-q1)/q2);
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*r), 220, hMax*r);
bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax*(1-r));
} else if (temp < tVap) {
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax);
} else if (temp === tVap) {
let rV = Math.min(1, (energy-q1-q2-q3)/(masse*s.lv));
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*(1-rV)), 220, hMax*(1-rV));
if(gasParticles.length < Math.floor(rV*60)) {
gasParticles.push({x: 110, y: 150, vx: Math.random()*3-1.5, vy: Math.random()*3-1.5, r: 2.5});
}
bCtx.fillStyle = "rgba(180,210,255,0.4)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); });
} else {
if(gasParticles.length < 60) gasParticles.push({x: 110, y: 150, vx: Math.random()*3-1.5, vy: Math.random()*3-1.5, r: 2.5});
bCtx.fillStyle = "rgba(160,200,255,0.6)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r+1, 0, 7); bCtx.fill(); });
}
gCtx.clearRect(0,0,600,420);
gCtx.strokeStyle = "#444"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(60, 20); gCtx.stroke();
gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(580, 390); gCtx.stroke();
let xMax = masse * 1500000;
gCtx.fillStyle = "#000"; gCtx.font = "bold 12px Arial";
gCtx.fillText("T (°C)", 15, 25); gCtx.fillText("Énergie Q (Joules)", 480, 410);
gCtx.font = "10px Arial"; gCtx.fillStyle = "#888";
for(let t=-200; t<=200; t+=50) {
let y = 390 - ((t+200)/400)*350;
gCtx.fillText(t, 30, y+4);
gCtx.beginPath(); gCtx.moveTo(55,y); gCtx.lineTo(60,y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.colorS; gCtx.lineWidth = 3;
pts.forEach((p, i) => {
let px = 60 + (p.x / xMax) * 500;
let py = 390 - ((p.y + 200) / 400) * 350;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-final" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd; flex-wrap: wrap; gap: 15px;">
<div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;">
<div>
<label style="font-weight: bold; color: #444;">Fluide :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #1565c0; cursor: pointer;">
<option value="ethanol">A : Éthanol</option>
<option value="co2">B : Dioxyde de Carbone</option>
<option value="r23">C : Trifluorométhane (R-23)</option>
<option value="propane">D : Propane (R-290)</option>
<option value="hfo">E : HFO-1234yf (Moderne)</option>
</select>
</div>
<div>
<label style="font-weight: bold; color: #444;">Masse :</label>
<select id="selectMasse" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; cursor: pointer;">
<option value="1">1 kg</option>
<option value="2">2 kg</option>
<option value="4">4 kg</option>
<option value="6">6 kg</option>
<option value="8">8 kg</option>
<option value="10">10 kg</option>
</select>
</div>
</div>
<div id="temp-grand" style="font-size: 3.2em; font-weight: bold; color: #d32f2f; font-family: monospace; background: #fff; padding: 5px 15px; border-radius: 10px; border: 1px solid #ccc; min-width: 200px; text-align: center;">-200.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.4em; font-weight: bold; color: #1565c0; text-align: center;">-</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.2em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444; text-align: center;">
<div style="color: #4db6ac; font-size: 0.8em; margin-bottom: 5px;">ÉNERGIE (Q)</div>
<div id="q-val" style="font-size: 1.6em; color: #ffeb3b;">0 J</div>
</div>
</div>
<div style="flex: 2; min-width: 450px; display: flex; flex-direction: column;">
<canvas id="graphSim" width="600" height="420" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 10px; margin-top: 20px; justify-content: flex-end;">
<button id="btnPlay" onclick="toggleSim()" style="width: 160px; padding: 15px; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 1.1em; box-shadow: 0 4px #1b5e20;">DÉMARRER</button>
<button onclick="resetSim()" style="padding: 15px; background: #546e7a; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const selectF = document.getElementById('selectFluide'), selectM = document.getElementById('selectMasse');
const db = {
ethanol: { nom: "ÉTHANOL", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114.1, tv: 78.3, colorL: "#e3f2fd", colorS: "#64b5f6" },
co2: { nom: "DIOXYDE DE CARBONE", cs: 850, cl: 2000, cg: 840, lf: 199000, lv: 571000, tf: -56.6, tv: -78.5, colorL: "#f5f5f5", colorS: "#bdbdbd" },
r23: { nom: "TRIFLUOROMÉTHANE (R-23)", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155.1, tv: -82.1, colorL: "#e0f7fa", colorS: "#4dd0e1" },
propane: { nom: "PROPANE (R-290)", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -187.7, tv: -42.1, colorL: "#fff3e0", colorS: "#ffb74d" },
hfo: { nom: "HFO-1234yf", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152.2, tv: -29.4, colorL: "#f1f8e9", colorS: "#aed581" }
};
let s, temp, energy, masse, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 4500, tStart = -200, tEnd = 200;
let gasParticles = [];
window.initSubstance = function() {
s = db[selectF.value];
masse = parseFloat(selectM.value);
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER";
document.getElementById('btnPlay').style.background = "#2e7d32";
gasParticles = [];
updateUI();
};
window.toggleSim = function() {
if(temp >= tEnd && isRunning) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
window.resetSim = function() { initSubstance(); };
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.nom + " (" + masse + " kg)";
}
function update() {
if(isRunning && temp < tEnd) {
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 8) % 2 === 0) ? "#d32f2f" : "#333";
energy += pwr * 12; // Vitesse de simulation adaptée aux fortes masses
let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20);
let q1 = masse * s.cs * (tFus - tStart);
let q2 = masse * s.lf;
let q3 = masse * s.cl * (tVap - tFus);
let q4 = masse * s.lv;
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
} else if (energy < q1 + q2) {
temp = tFus;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
} else if (energy < q1 + q2 + q3) {
temp = tFus + (energy - q1 - q2)/(masse*s.cl);
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
} else if (energy < q1 + q2 + q3 + q4) {
temp = tVap;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
} else {
temp = tVap + (energy - q1 - q2 - q3 - q4)/(masse*s.cg);
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
}
if(temp > tEnd) { temp = tEnd; isRunning = false; }
pts.push({x: energy, y: temp});
updateUI();
} else { heater.style.background = "#333"; }
// Agitation thermique (perpétuelle)
if(gasParticles.length > 0) {
let speedFactor = 0.5 + ((temp + 200) * 0.015);
gasParticles.forEach(p => {
p.x += p.vx * speedFactor; p.y += p.vy * speedFactor;
if(p.x < 10 || p.x > 210) p.vx *= -1;
if(p.y < 10 || p.y > 290) p.vy *= -1;
});
}
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 40 + (masse * 20);
let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20);
let q1 = masse * s.cs * (tFus - tStart), q2 = masse * s.lf, q3 = masse * s.cl * (tVap - tFus);
if(temp < tFus) {
bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax);
} else if (temp === tFus) {
let r = Math.min(1, (energy-q1)/q2);
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*r), 220, hMax*r);
bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax*(1-r));
} else if (temp < tVap) {
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax);
} else if (temp === tVap) {
let rV = Math.min(1, (energy-q1-q2-q3)/(masse*s.lv));
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*(1-rV)), 220, hMax*(1-rV));
if(gasParticles.length < Math.floor(rV*60)) {
gasParticles.push({x: 110, y: 150, vx: Math.random()*3-1.5, vy: Math.random()*3-1.5, r: 2.5});
}
bCtx.fillStyle = "rgba(180,210,255,0.4)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); });
} else {
if(gasParticles.length < 60) gasParticles.push({x: 110, y: 150, vx: Math.random()*3-1.5, vy: Math.random()*3-1.5, r: 2.5});
bCtx.fillStyle = "rgba(160,200,255,0.6)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r+1, 0, 7); bCtx.fill(); });
}
gCtx.clearRect(0,0,600,420);
gCtx.strokeStyle = "#444"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(60, 20); gCtx.stroke();
gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(580, 390); gCtx.stroke();
// X-Max dynamique : s'ajuste à la masse pour que le graphique soit toujours beau
let xMax = masse * 1500000;
gCtx.fillStyle = "#000"; gCtx.font = "bold 12px Arial";
gCtx.fillText("T (°C)", 15, 25); gCtx.fillText("Énergie Q (Joules)", 480, 410);
gCtx.font = "10px Arial"; gCtx.fillStyle = "#888";
for(let t=-200; t<=200; t+=50) {
let y = 390 - ((t+200)/400)*350;
gCtx.fillText(t, 30, y+4);
gCtx.beginPath(); gCtx.moveTo(55,y); gCtx.lineTo(60,y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.colorS; gCtx.lineWidth = 3;
pts.forEach((p, i) => {
let px = 60 + (p.x / xMax) * 500;
let py = 390 - ((p.y + 200) / 400) * 350;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-mass" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;">
<div style="display: flex; gap: 15px; align-items: center;">
<label style="font-weight: bold; color: #555;">Substance :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #1565c0; min-width: 250px;">
<option value="ethanol">A : Éthanol</option>
<option value="co2">B : Dioxyde de Carbone</option>
<option value="r23">C : Trifluorométhane (R-23)</option>
<option value="propane">D : Propane (R-290)</option>
<option value="hfo">E : HFO-1234yf (Moderne)</option>
</select>
</div>
<div id="temp-grand" style="font-size: 3.2em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 220px; text-align: right;">-300.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.6em; font-weight: bold; color: #1565c0; text-align: center;">-</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.3em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div>
<div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · c · ΔT</div>
</div>
</div>
<div style="flex: 2; min-width: 450px; display: flex; flex-direction: column;">
<canvas id="graphSim" width="600" height="420" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 10px; margin-top: 20px; align-items: center; justify-content: flex-end; background: #f8f9fa; padding: 10px; border-radius: 12px;">
<div style="display: flex; align-items: center; gap: 8px; margin-right: auto;">
<span style="font-weight: bold; color: #666;">Masse :</span>
<select id="selectMasse" onchange="initSubstance()" style="padding: 8px; border-radius: 6px; border: 1px solid #ccc; font-weight: bold;">
<option value="0.5">0.5 kg</option>
<option value="1.0" selected>1.0 kg</option>
<option value="1.5">1.5 kg</option>
<option value="2.0">2.0 kg</option>
<option value="3.0">3.0 kg</option>
</select>
</div>
<button id="btnPlay" onclick="toggleSim()" style="width: 130px; padding: 12px; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 8px; cursor: pointer;">DÉMARRER</button>
<button onclick="resetSim()" style="padding: 12px; background: #546e7a; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">RAZ</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const selectF = document.getElementById('selectFluide');
const selectM = document.getElementById('selectMasse');
const db = {
ethanol: { nom: "ÉTHANOL", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114.1, tv: 78.3, colorL: "#e3f2fd", colorS: "#64b5f6" },
co2: { nom: "DIOXYDE DE CARBONE", cs: 850, cl: 2000, cg: 840, lf: 199000, lv: 571000, tf: -56.6, tv: -78.5, colorL: "#f5f5f5", colorS: "#bdbdbd" },
r23: { nom: "TRIFLUOROMÉTHANE (R-23)", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155.1, tv: -82.1, colorL: "#e0f7fa", colorS: "#4dd0e1" },
propane: { nom: "PROPANE (R-290)", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -187.7, tv: -42.1, colorL: "#fff3e0", colorS: "#ffb74d" },
hfo: { nom: "HFO-1234yf", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152.2, tv: -29.4, colorL: "#f1f8e9", colorS: "#aed581" }
};
let s, temp, energy, masse, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 4500;
const tStart = -300, tEnd = 200;
let gasParticles = [];
const numGasMax = 60;
window.initSubstance = function() {
s = db[selectF.value];
masse = parseFloat(selectM.value);
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER";
document.getElementById('btnPlay').style.background = "#2e7d32";
gasParticles = [];
updateUI();
};
window.toggleSim = function() {
if(temp >= tEnd && isRunning) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
window.resetSim = function() { initSubstance(); };
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.nom + " (" + masse + "kg)";
}
function addGasParticle() {
gasParticles.push({
x: Math.random() * 200 + 10, y: Math.random() * 290 + 5,
vx: (Math.random() - 0.5) * 4, vy: (Math.random() - 0.5) * 4, r: 2.5
});
}
function update() {
if(isRunning && temp < tEnd) {
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#d32f2f" : "#333";
energy += pwr * 4;
let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20);
let q1 = masse * s.cs * (tFus - tStart);
let q2 = masse * s.lf;
let q3 = masse * s.cl * (tVap - tFus);
let q4 = masse * s.lv;
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
} else if (energy < q1 + q2) {
temp = tFus;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
} else if (energy < q1 + q2 + q3) {
temp = tFus + (energy - q1 - q2)/(masse*s.cl);
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
} else if (energy < q1 + q2 + q3 + q4) {
temp = tVap;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
} else {
temp = tVap + (energy - q1 - q2 - q3 - q4)/(masse*s.cg);
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
}
if(temp > tEnd) { temp = tEnd; isRunning = false; }
pts.push({x: energy, y: temp});
updateUI();
} else { heater.style.background = "#333"; }
if(gasParticles.length > 0) {
let speed = 0.5 + (Math.max(0, temp - s.tv + 100) * 0.02);
gasParticles.forEach(p => {
p.x += p.vx * speed; p.y += p.vy * speed;
if(p.x < 10 || p.x > 210) p.vx *= -1;
if(p.y < 10 || p.y > 290) p.vy *= -1;
});
}
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 60 + (masse * 40); // La hauteur du fluide dépend de la masse
let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20);
let q1 = masse * s.cs * (tFus - tStart), q2 = masse * s.lf, q3 = masse * s.cl * (tVap - tFus);
if(temp < tFus) {
bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax);
} else if (temp === tFus) {
let r = Math.min(1, (energy-q1)/q2);
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*r), 220, hMax*r);
bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax*(1-r));
} else if (temp < tVap) {
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax);
} else if (temp === tVap) {
let rV = Math.min(1, (energy-q1-q2-q3)/(masse*s.lv));
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*(1-rV)), 220, hMax*(1-rV));
while(gasParticles.length < Math.floor(rV*numGasMax)) addGasParticle();
bCtx.fillStyle = "rgba(200,220,255,0.4)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); });
} else {
if(gasParticles.length < numGasMax) while(gasParticles.length < numGasMax) addGasParticle();
bCtx.fillStyle = "rgba(180,210,255,0.6)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r+1, 0, 7); bCtx.fill(); });
}
// GRAPHIQUE - Échelle dynamique sur X (énergie)
gCtx.clearRect(0,0,600,420);
gCtx.strokeStyle = "#444"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(60, 20); gCtx.stroke(); // Y
gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(580, 390); gCtx.stroke(); // X
let xMax = 6000000; // Adapté aux grosses masses
gCtx.fillStyle = "#000"; gCtx.font = "bold 12px Arial";
gCtx.fillText("T (°C)", 15, 25); gCtx.fillText("Q (Joules)", 520, 410);
gCtx.font = "10px Arial"; gCtx.fillStyle = "#888";
for(let t=-300; t<=200; t+=50) {
let y = 390 - ((t+300)/500)*350;
gCtx.fillText(t, 30, y+4);
gCtx.beginPath(); gCtx.moveTo(55,y); gCtx.lineTo(60,y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.colorS; gCtx.lineWidth = 3;
pts.forEach((p, i) => {
let px = 60 + (p.x / xMax) * 500;
let py = 390 - ((p.y + 300) / 500) * 350;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-v3" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; flex-direction: column; gap: 15px; margin-bottom: 20px; background: #f8f9fa; padding: 20px; border-radius: 12px; border: 1px solid #ddd;">
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;">
<div style="display: flex; gap: 10px; align-items: center;">
<label style="font-weight: bold; color: #333;">Substance :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 220px;">
<option value="ethanol">A : Éthanol</option>
<option value="co2">B : Dioxyde de Carbone</option>
<option value="r23">C : Trifluorométhane (R-23)</option>
<option value="propane">D : Propane (R-290)</option>
<option value="hfo">E : HFO-1234yf (Moderne)</option>
</select>
</div>
<div style="flex-grow: 1; max-width: 400px; display: flex; flex-direction: column; gap: 5px;">
<div style="display: flex; justify-content: space-between;">
<label style="font-weight: bold; color: #d32f2f;">Puissance de chauffe (P) :</label>
<span id="pwr-val" style="font-weight: bold; color: #d32f2f;">2500 W</span>
</div>
<input type="range" id="pwrSlider" min="1000" max="5000" step="500" value="2500" oninput="updatePower()" style="width: 100%; cursor: pointer;">
</div>
<div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #333; font-family: monospace; background: #eee; padding: 5px 15px; border-radius: 8px; border: 2px solid #ccc;">-300.0 °C</div>
</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 30px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: bold; margin-left: -5px; transition: background 0.2s; z-index: 1;">PLAQUE CHAUFFANTE</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.6em; font-weight: bold; color: #1565c0; text-align: center;">-</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div>
<div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · c · ΔT</div>
</div>
</div>
<div style="flex: 2; min-width: 450px;">
<canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 15px; margin-top: 25px;">
<button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER</button>
<button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const pwrSlider = document.getElementById('pwrSlider');
const pwrLabel = document.getElementById('pwr-val');
const db = {
ethanol: { nom: "ÉTHANOL", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114.1, tv: 78.3, colorL: "#e3f2fd", colorS: "#64b5f6", maxQ: 2800000 },
co2: { nom: "DIOXYDE DE CARBONE", cs: 850, cl: 2000, cg: 840, lf: 199000, lv: 571000, tf: -56.6, tv: -78.5, colorL: "#f5f5f5", colorS: "#bdbdbd", maxQ: 2000000 },
r23: { nom: "TRIFLUOROMÉTHANE (R-23)", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155.1, tv: -82.1, colorL: "#e0f7fa", colorS: "#4dd0e1", maxQ: 1800000 },
propane: { nom: "PROPANE (R-290)", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -187.7, tv: -42.1, colorL: "#fff3e0", colorS: "#ffb74d", maxQ: 2200000 },
hfo: { nom: "HFO-1234yf", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152.2, tv: -29.4, colorL: "#f1f8e9", colorS: "#aed581", maxQ: 1800000 }
};
let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0;
let currentPwr = 2500;
const tStart = -300, tEnd = 200;
let gasParticles = [];
const numGasMax = 70;
window.updatePower = function() {
currentPwr = parseInt(pwrSlider.value);
pwrLabel.innerText = currentPwr + " W";
};
window.initSubstance = function() {
s = db[document.getElementById('selectFluide').value];
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER";
document.getElementById('btnPlay').style.background = "#2e7d32";
gasParticles = [];
updateUI();
};
window.toggleSim = function() {
if(temp >= tEnd && isRunning) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
window.resetSim = function() { initSubstance(); };
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.nom;
}
function addGasParticle() {
gasParticles.push({
x: Math.random() * 200 + 10,
y: Math.random() * 290 + 5,
vx: (Math.random() - 0.5) * 4,
vy: (Math.random() - 0.5) * 4,
r: Math.random() * 2 + 2
});
}
function update() {
if(isRunning && temp < tEnd) {
blinkFrame++;
// L'intensité du rouge de la plaque dépend de la puissance
let intensity = Math.floor(100 + (currentPwr/5000)*155);
heater.style.background = (Math.floor(blinkFrame / 8) % 2 === 0) ? `rgb(${intensity}, 40, 40)` : "#333";
energy += currentPwr * 3.5; // Vitesse d'exécution
let tFusion = s.tf;
let tVap = Math.max(s.tv, tFusion + 20); // Correction visuelle pour CO2
let q1 = 1 * s.cs * (tFusion - tStart);
let q2 = 1 * s.lf;
let q3 = 1 * s.cl * (tVap - tFusion);
let q4 = 1 * s.lv;
if (energy < q1) {
temp = tStart + energy/s.cs;
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = tFusion;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
document.getElementById('formule-text').innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = tFusion + (energy - q1 - q2)/s.cl;
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = tVap;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
document.getElementById('formule-text').innerHTML = "Q = m · Lv";
} else {
temp = tVap + (energy - q1 - q2 - q3 - q4)/s.cg;
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT";
}
if(temp > tEnd) { temp = tEnd; isRunning = false; }
pts.push({x: energy, y: temp});
updateUI();
} else {
heater.style.background = "#333";
}
if(gasParticles.length > 0) {
let speedFactor = 0.4 + (Math.max(0, temp - s.tv + 150) * 0.015);
gasParticles.forEach(p => {
p.x += p.vx * speedFactor;
p.y += p.vy * speedFactor;
if(p.x < 8 || p.x > 212) p.vx *= -1;
if(p.y < 5 || p.y > 295) p.vy *= -1;
});
}
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 180;
let tFusion = s.tf;
let tVap = Math.max(s.tv, tFusion + 20);
let q1 = 1 * s.cs * (tFusion - tStart);
let q2 = 1 * s.lf;
let q3 = 1 * s.cl * (tVap - tFusion);
if(temp < tFusion) {
bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax);
} else if (temp === tFusion) {
let ratio = Math.min(1, (energy - q1) / q2);
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio);
bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300 - (hMax * (1-ratio)), 160, hMax * (1-ratio));
} else if (temp < tVap) {
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax);
} else if (temp === tVap) {
let ratioV = Math.min(1, (energy - q1 - q2 - q3) / s.lv);
let currentH = hMax * (1 - ratioV);
bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-currentH, 220, currentH);
let target = Math.floor(ratioV * numGasMax);
while(gasParticles.length < target) addGasParticle();
bCtx.fillStyle = "rgba(200,220,255,0.5)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); });
} else {
if(gasParticles.length < numGasMax) while(gasParticles.length < numGasMax) addGasParticle();
bCtx.fillStyle = "rgba(180,210,255,0.6)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r + 0.5, 0, 7); bCtx.fill(); });
}
// GRAPHIQUE
gCtx.clearRect(0,0,600,450);
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 420); gCtx.lineTo(60, 20); gCtx.lineTo(55, 30); gCtx.moveTo(60, 20); gCtx.lineTo(65, 30); gCtx.stroke(); // Y
gCtx.beginPath(); gCtx.moveTo(40, 400); gCtx.lineTo(580, 400); gCtx.lineTo(570, 395); gCtx.moveTo(580, 400); gCtx.lineTo(570, 405); gCtx.stroke(); // X
gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial";
gCtx.fillText("T (°C)", 20, 25); gCtx.fillText("Q (J)", 560, 425);
gCtx.font = "10px Arial"; gCtx.fillStyle = "#666";
for(let t = -300; t <= 200; t += 50) {
let y = 400 - ((t - tStart) / 500) * 340;
gCtx.fillText(t, 30, y + 5);
gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(60, y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.colorS; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let px = 60 + (p.x / s.maxQ) * 500;
let py = 400 - ((p.y - tStart) / 500) * 340;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-cryo" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;">
<div style="display: flex; gap: 10px; align-items: center;">
<label style="font-weight: bold; color: #555;">Substance :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 250px;">
<option value="ethanol">A : Éthanol</option>
<option value="co2">B : Dioxyde de Carbone</option>
<option value="r23">C : Trifluorométhane (R-23)</option>
<option value="propane">D : Propane (R-290)</option>
<option value="hfo">E : HFO-1234yf (Moderne)</option>
</select>
</div>
<div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-200.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.6em; font-weight: bold; color: #1565c0; text-align: center;">-</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div>
<div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div>
</div>
</div>
<div style="flex: 2; min-width: 450px;">
<canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 15px; margin-top: 25px;">
<button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER</button>
<button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const select = document.getElementById('selectFluide');
const db = {
ethanol: { nom: "ÉTHANOL", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114.1, tv: 78.3, colorL: "#e3f2fd", colorS: "#64b5f6", maxQ: 2500000 },
co2: { nom: "DIOXYDE DE CARBONE", cs: 850, cl: 2000, cg: 840, lf: 199000, lv: 571000, tf: -56.6, tv: -78.5, colorL: "#f5f5f5", colorS: "#bdbdbd", maxQ: 1800000 }, // tv < tf car sublimation, mais on inverse pour simu
r23: { nom: "TRIFLUOROMÉTHANE (R-23)", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155.1, tv: -82.1, colorL: "#e0f7fa", colorS: "#4dd0e1", maxQ: 1500000 },
propane: { nom: "PROPANE (R-290)", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -187.7, tv: -42.1, colorL: "#fff3e0", colorS: "#ffb74d", maxQ: 2000000 },
hfo: { nom: "HFO-1234yf", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152.2, tv: -29.4, colorL: "#f1f8e9", colorS: "#aed581", maxQ: 1500000 }
};
let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 5000, tStart = -200, tEnd = 200;
let gasParticles = [];
const numGasMax = 70;
window.initSubstance = function() {
s = db[select.value];
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER";
document.getElementById('btnPlay').style.background = "#2e7d32";
gasParticles = [];
updateUI();
};
window.toggleSim = function() {
if(temp >= tEnd && isRunning) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
window.resetSim = function() { initSubstance(); };
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.nom;
}
function addGasParticle() {
gasParticles.push({
x: Math.random() * 200 + 10,
y: Math.random() * 290 + 5,
vx: (Math.random() - 0.5) * 4,
vy: (Math.random() - 0.5) * 4,
r: Math.random() * 2 + 2
});
}
function update() {
if(isRunning && temp < tEnd) {
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c";
energy += pwr * 2.5;
let tFusion = s.tf;
let tVap = s.tv;
if(tVap < tFusion) tVap = tFusion + 20; // Correctif pour CO2 en simu liquide
let q1 = 1 * s.cs * (tFusion - tStart);
let q2 = 1 * s.lf;
let q3 = 1 * s.cl * (tVap - tFusion);
let q4 = 1 * s.lv;
if (energy < q1) {
temp = tStart + energy/s.cs;
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = tFusion;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
document.getElementById('formule-text').innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = tFusion + (energy - q1 - q2)/s.cl;
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = tVap;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
document.getElementById('formule-text').innerHTML = "Q = m · Lv";
} else {
temp = tVap + (energy - q1 - q2 - q3 - q4)/s.cg;
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT";
}
if(temp > tEnd) { temp = tEnd; isRunning = false; }
pts.push({x: energy, y: temp});
updateUI();
} else {
heater.style.background = "#333";
}
// Agitation thermique persistante
if(gasParticles.length > 0) {
let tBase = s.tv;
let speedFactor = 0.5 + (Math.max(0, temp - tBase + 100) * 0.02);
gasParticles.forEach(p => {
p.x += p.vx * speedFactor;
p.y += p.vy * speedFactor;
if(p.x < 8 || p.x > 212) p.vx *= -1;
if(p.y < 5 || p.y > 295) p.vy *= -1;
});
}
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 180;
let tFusion = s.tf;
let tVap = Math.max(s.tv, s.tf + 20);
let q1 = 1 * s.cs * (tFusion - tStart);
let q2 = 1 * s.lf;
let q3 = 1 * s.cl * (tVap - tFusion);
if(temp < tFusion) {
bCtx.fillStyle = s.colorS;
bCtx.fillRect(30, 300-hMax, 160, hMax);
} else if (temp === tFusion) {
let ratio = Math.min(1, (energy - q1) / q2);
bCtx.fillStyle = s.colorL;
bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio);
bCtx.fillStyle = s.colorS;
bCtx.fillRect(30, 300 - (hMax * (1-ratio)), 160, hMax * (1-ratio));
} else if (temp < tVap) {
bCtx.fillStyle = s.colorL;
bCtx.fillRect(0, 300-hMax, 220, hMax);
} else if (temp === tVap) {
let ratioV = Math.min(1, (energy - q1 - q2 - q3) / s.lv);
let currentH = hMax * (1 - ratioV);
bCtx.fillStyle = s.colorL;
bCtx.fillRect(0, 300-currentH, 220, currentH);
let target = Math.floor(ratioV * numGasMax);
while(gasParticles.length < target) addGasParticle();
bCtx.fillStyle = "rgba(200,220,255,0.5)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); });
} else {
if(gasParticles.length < numGasMax) while(gasParticles.length < numGasMax) addGasParticle();
bCtx.fillStyle = "rgba(180,210,255,0.6)";
gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r + 0.5, 0, 7); bCtx.fill(); });
}
// GRAPHIQUE
gCtx.clearRect(0,0,600,450);
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 420); gCtx.lineTo(60, 20); gCtx.stroke(); // Y
gCtx.beginPath(); gCtx.moveTo(40, 400); gCtx.lineTo(580, 400); gCtx.stroke(); // X
gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial";
gCtx.fillText("T (°C)", 20, 25); gCtx.fillText("Q (J)", 560, 425);
gCtx.font = "10px Arial"; gCtx.fillStyle = "#666";
for(let t = -200; t <= 200; t += 50) {
let y = 400 - ((t - tStart) / 400) * 340;
gCtx.fillText(t, 35, y + 5);
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.colorS; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let px = 60 + (p.x / s.maxQ) * 500;
let py = 400 - ((p.y - tStart) / 400) * 340;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-physics-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;">
<div style="display: flex; gap: 10px; align-items: center;">
<label style="font-weight: bold; color: #555;">Substance :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;">
<option value="eau">Eau (H₂O)</option>
<option value="ammoniac">Ammoniac (NH₃)</option>
<option value="isobutane">Isobutane (C₄H₁₀)</option>
<option value="difluoro">Difluorométhane (R-32)</option>
</select>
</div>
<div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-200.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; transition: background 0.3s; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div>
<div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div>
</div>
</div>
<div style="flex: 2; min-width: 450px;">
<canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 15px; margin-top: 25px;">
<button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button>
<button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const select = document.getElementById('selectFluide');
const db = {
eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, colorL: "#e1f5fe", colorS: "#4fc3f7", maxQ: 4800000 },
ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, colorL: "#e8f5e9", colorS: "#81c784", maxQ: 3800000 },
isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, colorL: "#fff3e0", colorS: "#ffb74d", maxQ: 2500000 },
difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, colorL: "#e0f2f1", colorS: "#4db6ac", maxQ: 2200000 }
};
let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 4500, masse = 1, tStart = -200, tEnd = 200;
let gasParticles = [];
const numGasMax = 65;
window.initSubstance = function() {
s = db[select.value];
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION";
document.getElementById('btnPlay').style.background = "#2e7d32";
heater.style.background = "#333";
gasParticles = [];
updateUI();
};
window.toggleSim = function() {
if(temp >= tEnd && isRunning) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.nom;
}
function addGasParticle() {
gasParticles.push({
x: Math.random() * 200 + 10,
y: Math.random() * 290 + 5,
vx: (Math.random() - 0.5) * 3.5,
vy: (Math.random() - 0.5) * 3.5,
r: Math.random() * 2.5 + 2
});
}
function update() {
// GESTION DU CALCUL THERMIQUE (seulement si isRunning)
if(isRunning && temp < tEnd) {
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c";
energy += pwr * 2.8;
let q1 = 1 * s.cs * (s.tf - tStart);
let q2 = 1 * s.lf;
let q3 = 1 * s.cl * (s.tv - s.tf);
let q4 = 1 * s.lv;
if (energy < q1) {
temp = tStart + energy/s.cs;
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.tf;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
document.getElementById('formule-text').innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = s.tf + (energy - q1 - q2)/s.cl;
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = s.tv;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
document.getElementById('formule-text').innerHTML = "Q = m · Lv";
} else {
temp = s.tv + (energy - q1 - q2 - q3 - q4)/s.cg;
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT";
}
if(temp > tEnd) { temp = tEnd; isRunning = false; }
pts.push({x: energy, y: temp});
updateUI();
} else {
heater.style.background = "#333";
}
// ANIMATION DES MOLÉCULES (Indépendante de isRunning pour le mouvement perpétuel)
if(gasParticles.length > 0) {
let tDiff = Math.max(0, temp - s.tv);
let speedFactor = 1.0 + (tDiff * 0.04);
gasParticles.forEach(p => {
p.x += p.vx * speedFactor;
p.y += p.vy * speedFactor;
if(p.x < 8 || p.x > 212) p.vx *= -1;
if(p.y < 5 || p.y > 295) p.vy *= -1;
});
}
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 180;
let q1 = 1 * s.cs * (s.tf - tStart);
let q2 = 1 * s.lf;
let q3 = 1 * s.cl * (s.tv - s.tf);
if(temp < s.tf) {
bCtx.fillStyle = s.colorS;
bCtx.fillRect(30, 300-hMax, 160, hMax);
}
else if (temp === s.tf) {
let ratio = (energy - q1) / q2;
bCtx.fillStyle = s.colorL;
bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio);
bCtx.fillStyle = s.colorS;
bCtx.fillRect(30, 300 - (hMax * (1-ratio)), 160, hMax * (1-ratio));
}
else if(temp < s.tv) {
bCtx.fillStyle = s.colorL;
bCtx.fillRect(0, 300-hMax, 220, hMax);
}
else if (temp === s.tv) {
let ratioV = (energy - q1 - q2 - q3) / s.lv;
let currentLiquidH = hMax * (1 - ratioV);
bCtx.fillStyle = s.colorL;
bCtx.fillRect(0, 300-currentLiquidH, 220, currentLiquidH);
let targetParticles = Math.floor(ratioV * numGasMax);
while(gasParticles.length < targetParticles) addGasParticle();
bCtx.fillStyle = "rgba(230,235,255, 0.45)";
gasParticles.forEach(p => {
bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill();
});
if(isRunning) {
bCtx.fillStyle = "rgba(255,255,255,0.7)";
for(let i=0; i<8; i++) {
let bx = Math.random()*200 + 5;
let by = (300-currentLiquidH) + Math.random()*currentLiquidH;
bCtx.beginPath(); bCtx.arc(bx, by, Math.random()*3+1, 0, 7); bCtx.fill();
}
}
}
else {
if(gasParticles.length < numGasMax) {
while(gasParticles.length < numGasMax) addGasParticle();
}
bCtx.fillStyle = "rgba(215,225,255, 0.6)";
gasParticles.forEach(p => {
bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r + 0.5, 0, 7); bCtx.fill();
});
}
// GRAPHIQUE
gCtx.clearRect(0,0,600,450);
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 420); gCtx.lineTo(60, 20); gCtx.lineTo(55, 30); gCtx.moveTo(60, 20); gCtx.lineTo(65, 30); gCtx.stroke();
gCtx.beginPath(); gCtx.moveTo(40, 400); gCtx.lineTo(580, 400); gCtx.lineTo(570, 395); gCtx.moveTo(580, 400); gCtx.lineTo(570, 405); gCtx.stroke();
gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial";
gCtx.fillText("T (°C)", 20, 25); gCtx.fillText("Q (J)", 560, 430);
gCtx.font = "10px Arial"; gCtx.fillStyle = "#666";
for(let t = -200; t <= 200; t += 50) {
let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340;
gCtx.fillText(t, 35, y + 5);
gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.colorS; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let px = 60 + (p.x / s.maxQ) * 500;
let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-physics-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;">
<div style="display: flex; gap: 10px; align-items: center;">
<label style="font-weight: bold; color: #555;">Substance :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;">
<option value="eau">Eau (H₂O)</option>
<option value="ammoniac">Ammoniac (NH₃)</option>
<option value="isobutane">Isobutane (C₄H₁₀)</option>
<option value="difluoro">Difluorométhane (R-32)</option>
</select>
</div>
<div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-200.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; transition: background 0.3s; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div>
<div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div>
</div>
</div>
<div style="flex: 2; min-width: 450px;">
<canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 15px; margin-top: 25px;">
<button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button>
<button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const select = document.getElementById('selectFluide');
// Config des couleurs douces (colorS = Solide moyen / colorL = Liquide très clair)
const db = {
eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, colorL: "#e1f5fe", colorS: "#4fc3f7", maxQ: 4800000 },
ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, colorL: "#e8f5e9", colorS: "#81c784", maxQ: 3800000 },
isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, colorL: "#fff3e0", colorS: "#ffb74d", maxQ: 2500000 },
difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, colorL: "#e0f2f1", colorS: "#4db6ac", maxQ: 2200000 }
};
let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 4500, masse = 1, tStart = -200, tEnd = 200;
// Structure pour gérer les molécules de gaz animées
let gasParticles = [];
const numGasMax = 60; // Nombre max de molécules quand tout est vaporisé
window.initSubstance = function() {
s = db[select.value];
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION";
document.getElementById('btnPlay').style.background = "#2e7d32";
heater.style.background = "#333";
gasParticles = []; // Réinit molécules
updateUI();
};
window.resetSim = function() { initSubstance(); };
window.toggleSim = function() {
if(temp >= tEnd) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.nom;
}
function update() {
if(!isRunning) return;
if(temp >= tEnd) { isRunning = false; heater.style.background = "#333"; return; }
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c";
energy += pwr * 2.8;
let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0;
let q2 = (s.tf > tStart) ? masse * s.lf : 0;
let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf));
let q4 = masse * s.lv;
// --- GESTION DE LA PHYSIQUE ET DES ÉTATS ---
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.tf;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
document.getElementById('formule-text').innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = Math.max(tStart, s.tf) + (energy - q1 - q2)/(masse*s.cl);
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = s.tv;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
document.getElementById('formule-text').innerHTML = "Q = m · Lv";
} else {
temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg);
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT";
}
if(temp > tEnd) temp = tEnd;
pts.push({x: energy, y: temp});
updateUI();
// --- MISE À JOUR DE L'AGITATION DES MOLÉCULES DE GAZ ---
if(gasParticles.length > 0) {
// Facteur de vitesse : augmente avec la température au-delà de tv
let tDiff = Math.max(0, temp - s.tv);
let speedFactor = 1.0 + (tDiff * 0.05); // Plus il fait chaud, plus ça va vite
gasParticles.forEach(p => {
p.x += p.vx * speedFactor;
p.y += p.vy * speedFactor;
// Rebond sur les parois
if(p.x < 10 || p.x > 210) p.vx *= -1;
if(p.y < 5 || p.y > 295) p.vy *= -1;
});
}
}
// Fonction pour ajouter une molécule de gaz (initialisation aléatoire)
function addGasParticle() {
gasParticles.push({
x: Math.random() * 200 + 10,
y: Math.random() * 290 + 5,
vx: (Math.random() - 0.5) * 4,
vy: (Math.random() - 0.5) * 4,
r: Math.random() * 3 + 2
});
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 180;
let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0;
let q2 = (s.tf > tStart) ? masse * s.lf : 0;
let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf));
// --- DESSIN DU BÉCHER ET DE LA MATIÈRE ---
if(temp < s.tf) {
bCtx.fillStyle = s.colorS;
bCtx.fillRect(30, 300-hMax, 160, hMax); // Solide pur (tons proches)
}
else if (temp === s.tf) {
// FUSION PROGRESSIVE
let ratio = (energy - q1) / s.lf;
bCtx.fillStyle = s.colorL;
bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio);
bCtx.fillStyle = s.colorS;
// Solide diminue par le haut
bCtx.fillRect(30, 300 - (hMax * (1-ratio)), 160, hMax * (1-ratio));
}
else if(temp < s.tv) {
bCtx.fillStyle = s.colorL;
bCtx.fillRect(0, 300-hMax, 220, hMax); // Liquide très clair
}
else if (temp === s.tv) {
// ÉBULLITION : Niveau baisse, de plus en plus de molécules
let ratioV = (energy - q1 - q2 - q3) / s.lv;
let currentLiquidH = hMax * (1 - ratioV);
bCtx.fillStyle = s.colorL;
bCtx.fillRect(0, 300-currentLiquidH, 220, currentLiquidH);
// Ajouter progressivement des molécules au gaz
let targetParticles = Math.floor(ratioV * numGasMax);
while(gasParticles.length < targetParticles) {
addGasParticle();
}
// Dessiner les molécules de gaz claires
bCtx.fillStyle = "rgba(230,235,255, 0.4)";
gasParticles.forEach(p => {
bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, Math.PI*2); bCtx.fill();
});
// Bulles d'ébullition dans le liquide
bCtx.fillStyle = "rgba(255,255,255,0.7)";
for(let i=0; i<10; i++) {
let bx = Math.random()*200 + 5;
let by = (300-currentLiquidH) + Math.random()*currentLiquidH;
bCtx.beginPath(); bCtx.arc(bx, by, Math.random()*3+1, 0, Math.PI*2); bCtx.fill();
}
}
else {
// GAZ TOTAL : Agitation maximale (dépend de la vitesse gérée dans update)
if(gasParticles.length < numGasMax) {
while(gasParticles.length < numGasMax) addGasParticle();
}
bCtx.fillStyle = "rgba(220,230,255, 0.6)";
gasParticles.forEach(p => {
bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r + 1, 0, Math.PI*2); bCtx.fill();
});
}
// --- DESSIN DU GRAPHIQUE ---
gCtx.clearRect(0,0,600,450);
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
// Axe Y (Température)
gCtx.beginPath();
gCtx.moveTo(60, 420); gCtx.lineTo(60, 20); // Ligne
gCtx.lineTo(55, 30); gCtx.moveTo(60, 20); gCtx.lineTo(65, 30); // Flèche
gCtx.stroke();
// Axe X (Énergie)
gCtx.beginPath();
gCtx.moveTo(40, 400); gCtx.lineTo(580, 400); // Ligne
gCtx.lineTo(570, 395); gCtx.moveTo(580, 400); gCtx.lineTo(570, 405); // Flèche
gCtx.stroke();
// Labels Axes
gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial";
gCtx.fillText("T (°C)", 20, 25);
gCtx.fillText("Q (J)", 560, 430);
gCtx.font = "10px Arial";
gCtx.fillStyle = "#666";
for(let t = -200; t <= 200; t += 50) {
let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340;
gCtx.fillText(t, 35, y + 5);
gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.colorS; // Utilise la couleur moyenne
gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let px = 60 + (p.x / s.maxQ) * 500;
let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;">
<div style="display: flex; gap: 10px; align-items: center;">
<label style="font-weight: bold; color: #555;">Substance :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;">
<option value="eau">Eau (H₂O)</option>
<option value="ammoniac">Ammoniac (NH₃)</option>
<option value="isobutane">Isobutane (C₄H₁₀)</option>
<option value="difluoro">Difluorométhane (R-32)</option>
</select>
</div>
<div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-200.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div>
<div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div>
</div>
</div>
<div style="flex: 2; min-width: 450px;">
<canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 15px; margin-top: 25px;">
<button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button>
<button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const select = document.getElementById('selectFluide');
// Configuration des couleurs harmonisées (Sombre pour Solide / Clair pour Liquide)
const db = {
eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, colorL: "#4fc3f7", colorS: "#0d47a1", maxQ: 4800000 },
ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, colorL: "#81c784", colorS: "#1b5e20", maxQ: 3800000 },
isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, colorL: "#ffb74d", colorS: "#a0522d", maxQ: 2500000 },
difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, colorL: "#4db6ac", colorS: "#004d40", maxQ: 2200000 }
};
let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 4500, tStart = -200, tEnd = 200;
window.initSubstance = function() {
s = db[select.value];
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION";
document.getElementById('btnPlay').style.background = "#2e7d32";
heater.style.background = "#333";
updateUI();
};
window.resetSim = function() { initSubstance(); };
window.toggleSim = function() {
if(temp >= tEnd) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.nom;
}
function update() {
if(!isRunning) return;
if(temp >= tEnd) { isRunning = false; heater.style.background = "#333"; return; }
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c";
energy += pwr * 3.0;
let q1 = 1 * s.cs * (s.tf - tStart);
let q2 = 1 * s.lf;
let q3 = 1 * s.cl * (s.tv - s.tf);
let q4 = 1 * s.lv;
if (energy < q1) {
temp = tStart + energy/s.cs;
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.tf;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
document.getElementById('formule-text').innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = s.tf + (energy - q1 - q2)/s.cl;
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = s.tv;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
document.getElementById('formule-text').innerHTML = "Q = m · Lv";
} else {
temp = s.tv + (energy - q1 - q2 - q3 - q4)/s.cg;
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT";
}
if(temp > tEnd) temp = tEnd;
pts.push({x: energy, y: temp});
updateUI();
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 180;
let q1 = 1 * s.cs * (s.tf - tStart);
let q2 = 1 * s.lf;
let q3 = 1 * s.cl * (s.tv - s.tf);
if(temp < s.tf) {
bCtx.fillStyle = s.colorS;
bCtx.fillRect(35, 300-hMax, 150, hMax);
}
else if (temp === s.tf) {
let ratio = (energy - q1) / q2;
bCtx.fillStyle = s.colorL;
bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio);
bCtx.fillStyle = s.colorS;
bCtx.fillRect(35, 300 - (hMax * (1-ratio)), 150, hMax * (1-ratio));
}
else if(temp < s.tv) {
bCtx.fillStyle = s.colorL;
bCtx.fillRect(0, 300-hMax, 220, hMax);
}
else if (temp === s.tv) {
let ratioV = (energy - q1 - q2 - q3) / (1 * s.lv);
let currentLiquidH = hMax * (1 - ratioV);
bCtx.fillStyle = s.colorL;
bCtx.fillRect(0, 300-currentLiquidH, 220, currentLiquidH);
// Gaz particules claires
for(let i=0; i<30; i++) {
let pOpacity = ratioV * 0.4;
bCtx.fillStyle = "rgba(230,235,255," + pOpacity + ")";
let px = Math.random()*210;
let py = Math.random()*280;
bCtx.beginPath(); bCtx.arc(px, py, Math.random()*5+2, 0, 7); bCtx.fill();
}
bCtx.fillStyle = "rgba(255,255,255,0.7)";
for(let i=0; i<10; i++) {
let bx = Math.random()*200 + 5;
let by = (300-currentLiquidH) + Math.random()*currentLiquidH;
bCtx.beginPath(); bCtx.arc(bx, by, Math.random()*3+1, 0, 7); bCtx.fill();
}
}
else {
for(let i=0; i<50; i++) {
bCtx.fillStyle = "rgba(210,225,255,0.5)";
let px = Math.random()*210;
let py = Math.random()*290;
bCtx.beginPath(); bCtx.arc(px, py, 4, 0, 7); bCtx.fill();
}
}
gCtx.clearRect(0,0,600,450);
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath();
gCtx.moveTo(60, 420); gCtx.lineTo(60, 20);
gCtx.lineTo(55, 30); gCtx.moveTo(60, 20); gCtx.lineTo(65, 30);
gCtx.stroke();
gCtx.beginPath();
gCtx.moveTo(40, 400); gCtx.lineTo(580, 400);
gCtx.lineTo(570, 395); gCtx.moveTo(580, 400); gCtx.lineTo(570, 405);
gCtx.stroke();
gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial";
gCtx.fillText("T (°C)", 20, 25);
gCtx.fillText("Q (J)", 560, 430);
gCtx.font = "10px Arial";
gCtx.fillStyle = "#666";
for(let t = -200; t <= 200; t += 50) {
let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340;
gCtx.fillText(t, 35, y + 5);
gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.colorL; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let px = 60 + (p.x / s.maxQ) * 500;
let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;">
<div style="display: flex; gap: 10px; align-items: center;">
<label style="font-weight: bold; color: #555;">Substance :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;">
<option value="eau">Eau (H₂O)</option>
<option value="ammoniac">Ammoniac (NH₃)</option>
<option value="isobutane">Isobutane (C₄H₁₀)</option>
<option value="difluoro">Difluorométhane (R-32)</option>
</select>
</div>
<div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-200.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div>
<div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div>
</div>
</div>
<div style="flex: 2; min-width: 450px;">
<canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 15px; margin-top: 25px;">
<button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button>
<button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const select = document.getElementById('selectFluide');
const db = {
eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, color: "#2196f3", maxQ: 4800000 },
ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, color: "#4caf50", maxQ: 3800000 },
isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, color: "#ff9800", maxQ: 2500000 },
difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, color: "#009688", maxQ: 2200000 }
};
let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 4500, tStart = -200, tEnd = 200;
window.initSubstance = function() {
s = db[select.value];
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION";
document.getElementById('btnPlay').style.background = "#2e7d32";
heater.style.background = "#333";
updateUI();
};
window.resetSim = function() { initSubstance(); };
window.toggleSim = function() {
if(temp >= tEnd) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.nom;
}
function update() {
if(!isRunning) return;
if(temp >= tEnd) { isRunning = false; heater.style.background = "#333"; return; }
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c";
energy += pwr * 2.8;
let q1 = 1 * s.cs * (s.tf - tStart);
let q2 = 1 * s.lf;
let q3 = 1 * s.cl * (s.tv - s.tf);
let q4 = 1 * s.lv;
if (energy < q1) {
temp = tStart + energy/s.cs;
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.tf;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
document.getElementById('formule-text').innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = s.tf + (energy - q1 - q2)/s.cl;
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = s.tv;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
document.getElementById('formule-text').innerHTML = "Q = m · Lv";
} else {
temp = s.tv + (energy - q1 - q2 - q3 - q4)/s.cg;
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT";
}
if(temp > tEnd) temp = tEnd;
pts.push({x: energy, y: temp});
updateUI();
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 180;
let q1 = 1 * s.cs * (s.tf - tStart);
let q2 = 1 * s.lf;
let q3 = 1 * s.cl * (s.tv - s.tf);
if(temp < s.tf) {
// SOLIDE
bCtx.fillStyle = "#bbdefb";
bCtx.fillRect(35, 300-hMax, 150, hMax);
}
else if (temp === s.tf) {
// FUSION : Disparition par le haut
let ratio = (energy - q1) / q2;
bCtx.fillStyle = s.color;
bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio);
bCtx.fillStyle = "#bbdefb";
// Le solide reste collé au fond, mais sa hauteur diminue
bCtx.fillRect(35, 300 - (hMax * (1-ratio)), 150, hMax * (1-ratio));
}
else if(temp < s.tv) {
// LIQUIDE
bCtx.fillStyle = s.color;
bCtx.fillRect(0, 300-hMax, 220, hMax);
}
else if (temp === s.tv) {
// ÉBULLITION
let ratioV = (energy - q1 - q2 - q3) / (1 * s.lv);
let currentLiquidH = hMax * (1 - ratioV);
// Liquide restant
bCtx.fillStyle = s.color;
bCtx.fillRect(0, 300-currentLiquidH, 220, currentLiquidH);
// Gaz particules claires (occupent tout le bécher)
for(let i=0; i<30; i++) {
let pOpacity = ratioV * 0.4;
bCtx.fillStyle = "rgba(220,230,255," + pOpacity + ")";
let px = Math.random()*210;
let py = Math.random()*280;
bCtx.beginPath(); bCtx.arc(px, py, Math.random()*5+2, 0, 7); bCtx.fill();
}
// Bulles dans le liquide
bCtx.fillStyle = "rgba(255,255,255,0.8)";
for(let i=0; i<10; i++) {
let bx = Math.random()*200 + 5;
let by = (300-currentLiquidH) + Math.random()*currentLiquidH;
bCtx.beginPath(); bCtx.arc(bx, by, Math.random()*3+1, 0, 7); bCtx.fill();
}
}
else {
// GAZ TOTAL : Agitation
for(let i=0; i<60; i++) {
bCtx.fillStyle = "rgba(200,220,255,0.5)";
let px = Math.random()*210;
let py = Math.random()*290;
bCtx.beginPath(); bCtx.arc(px, py, 4, 0, 7); bCtx.fill();
}
}
// --- GRAPHIQUE AVEC FLÈCHES ET LABELS ---
gCtx.clearRect(0,0,600,450);
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
// Axe Y (Température)
gCtx.beginPath();
gCtx.moveTo(60, 420); gCtx.lineTo(60, 20); // Ligne
gCtx.lineTo(55, 30); gCtx.moveTo(60, 20); gCtx.lineTo(65, 30); // Flèche
gCtx.stroke();
// Axe X (Énergie)
gCtx.beginPath();
gCtx.moveTo(40, 400); gCtx.lineTo(580, 400); // Ligne
gCtx.lineTo(570, 395); gCtx.moveTo(580, 400); gCtx.lineTo(570, 405); // Flèche
gCtx.stroke();
// Labels Axes
gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial";
gCtx.fillText("T (°C)", 20, 25);
gCtx.fillText("Q (J)", 560, 430);
// Graduations
gCtx.font = "10px Arial";
gCtx.fillStyle = "#666";
for(let t = -200; t <= 200; t += 50) {
let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340;
gCtx.fillText(t, 35, y + 5);
gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let px = 60 + (p.x / s.maxQ) * 500;
let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;">
<div style="display: flex; gap: 10px; align-items: center;">
<label style="font-weight: bold; color: #555;">Substance :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;">
<option value="eau">Eau (H₂O)</option>
<option value="ammoniac">Ammoniac (NH₃)</option>
<option value="isobutane">Isobutane (C₄H₁₀)</option>
<option value="difluoro">Difluorométhane (R-32)</option>
</select>
</div>
<div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-200.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div>
<div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div>
</div>
</div>
<div style="flex: 2; min-width: 450px;">
<canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 15px; margin-top: 25px;">
<button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button>
<button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const select = document.getElementById('selectFluide');
const db = {
eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, color: "#2196f3", maxQ: 4800000 },
ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, color: "#4caf50", maxQ: 3800000 },
isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, color: "#ff9800", maxQ: 2500000 },
difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, color: "#009688", maxQ: 2200000 }
};
let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 4500, tStart = -200, tEnd = 200;
window.initSubstance = function() {
s = db[select.value];
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION";
document.getElementById('btnPlay').style.background = "#2e7d32";
heater.style.background = "#333";
updateUI();
};
window.resetSim = function() { initSubstance(); };
window.toggleSim = function() {
if(temp >= tEnd) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
if(!isRunning) heater.style.background = "#333";
};
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.nom;
}
function update() {
if(!isRunning) return;
if(temp >= tEnd) { isRunning = false; heater.style.background = "#333"; return; }
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c";
energy += pwr * 3.0; // Vitesse augmentée pour le confort
let q1 = 1 * s.cs * (s.tf - tStart);
let q2 = 1 * s.lf;
let q3 = 1 * s.cl * (s.tv - s.tf);
let q4 = 1 * s.lv;
if (energy < q1) {
temp = tStart + energy/s.cs;
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.tf;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
document.getElementById('formule-text').innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = s.tf + (energy - q1 - q2)/s.cl;
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = s.tv;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
document.getElementById('formule-text').innerHTML = "Q = m · Lv";
} else {
temp = s.tv + (energy - q1 - q2 - q3 - q4)/s.cg;
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT";
}
if(temp > tEnd) temp = tEnd;
pts.push({x: energy, y: temp});
updateUI();
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 180;
let q1 = 1 * s.cs * (s.tf - tStart);
let q2 = 1 * s.lf;
let q3 = 1 * s.cl * (s.tv - s.tf);
if(temp < s.tf) {
bCtx.fillStyle = "#bbdefb";
bCtx.fillRect(35, 300-hMax, 150, hMax); // Bloc solide stable
}
else if (temp === s.tf) {
let ratio = (energy - q1) / q2;
bCtx.fillStyle = s.color;
bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio); // Liquide monte
bCtx.fillStyle = "#bbdefb";
bCtx.fillRect(35, 300-hMax, 150, hMax * (1-ratio)); // Solide descend (fond)
}
else if(temp < s.tv) {
bCtx.fillStyle = s.color;
bCtx.fillRect(0, 300-hMax, 220, hMax); // Liquide plein
}
else if (temp === s.tv) {
let ratioV = (energy - q1 - q2 - q3) / (1 * s.lv);
let currentLiquidH = hMax * (1 - ratioV);
bCtx.fillStyle = s.color;
bCtx.fillRect(0, 300-currentLiquidH, 220, currentLiquidH); // Liquide baisse
// Gaz progressif (nappe qui monte et s'opacifie)
let gasOpacity = 0.1 + (ratioV * 0.5);
let gasHeight = (300 - currentLiquidH);
bCtx.fillStyle = "rgba(180,180,180," + gasOpacity + ")";
bCtx.fillRect(0, 300 - hMax, 220, hMax - currentLiquidH);
bCtx.fillStyle = "rgba(255,255,255,0.8)";
for(let i=0; i<15; i++) {
let bx = Math.random()*210;
let by = (300-currentLiquidH) + Math.random()*currentLiquidH;
bCtx.beginPath(); bCtx.arc(bx, by, Math.random()*3+1, 0, 7); bCtx.fill();
}
}
else {
bCtx.fillStyle = "rgba(180,180,180,0.8)";
bCtx.fillRect(0, 0, 220, 300); // Gaz total
}
gCtx.clearRect(0,0,600,450);
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke();
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke();
gCtx.fillStyle = "#666"; gCtx.font = "10px Arial";
for(let t = -200; t <= 200; t += 50) {
let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340;
gCtx.fillText(t + "°", 25, y + 5);
gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let px = 60 + (p.x / s.maxQ) * 500;
let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-physics" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;">
<div style="display: flex; gap: 10px; align-items: center;">
<label style="font-weight: bold; color: #555;">Substance :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;">
<option value="eau">Eau (H₂O)</option>
<option value="ammoniac">Ammoniac (NH₃)</option>
<option value="isobutane">Isobutane (C₄H₁₀)</option>
<option value="difluoro">Difluorométhane (R-32)</option>
</select>
</div>
<div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-150.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; transition: background 0.3s; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div>
<div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div>
</div>
</div>
<div style="flex: 2; min-width: 450px;">
<canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 15px; margin-top: 25px;">
<button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button>
<button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const select = document.getElementById('selectFluide');
const db = {
eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, color: "#2196f3", maxQ: 4200000 },
ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, color: "#4caf50", maxQ: 3200000 },
isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, color: "#ff9800", maxQ: 1800000 },
difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, color: "#009688", maxQ: 1500000 }
};
let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 4500, masse = 1, tStart = -150, tEnd = 150;
window.initSubstance = function() {
s = db[select.value];
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION";
document.getElementById('btnPlay').style.background = "#2e7d32";
heater.style.background = "#333";
updateUI();
};
window.resetSim = function() { initSubstance(); };
window.toggleSim = function() {
if(temp >= tEnd) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
if(!isRunning) heater.style.background = "#333";
};
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.nom;
}
function update() {
if(!isRunning) return;
if(temp >= tEnd) { isRunning = false; heater.style.background = "#333"; return; }
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c";
energy += pwr * 2.5;
let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0;
let q2 = (s.tf > tStart) ? masse * s.lf : 0;
let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf));
let q4 = masse * s.lv;
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.tf;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
document.getElementById('formule-text').innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = Math.max(tStart, s.tf) + (energy - q1 - q2)/(masse*s.cl);
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = s.tv;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
document.getElementById('formule-text').innerHTML = "Q = m · Lv";
} else {
temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg);
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT";
}
if(temp > tEnd) temp = tEnd;
pts.push({x: energy, y: temp});
updateUI();
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 180;
let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0;
let q2 = (s.tf > tStart) ? masse * s.lf : 0;
let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf));
// --- DESSIN DE LA MATIÈRE ---
if(temp < s.tf) {
// SOLIDE PUR : Bloc centré
bCtx.fillStyle = "#bbdefb";
bCtx.fillRect(30, 300-hMax, 160, hMax);
}
else if (temp === s.tf) {
// FUSION : Le solide diminue, le liquide monte
let ratio = (energy - q1) / s.lf;
// Liquide (remplit tout le bécher)
bCtx.fillStyle = s.color;
bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio);
// Solide restant (diminue en hauteur)
bCtx.fillStyle = "#bbdefb";
bCtx.fillRect(30, 300-hMax, 160, hMax * (1-ratio));
}
else if(temp < s.tv) {
// LIQUIDE PUR : Remplit les parois
bCtx.fillStyle = s.color;
bCtx.fillRect(0, 300-hMax, 220, hMax);
}
else if (temp === s.tv) {
// ÉBULLITION : Niveau baisse, gaz occupe le haut progressivement
let ratioV = (energy - q1 - q2 - q3) / s.lv;
let currentLiquidH = hMax * (1 - ratioV);
// Liquide restant
bCtx.fillStyle = s.color;
bCtx.fillRect(0, 300-currentLiquidH, 220, currentLiquidH);
// Gaz progressif (monte vers le haut du bécher)
bCtx.fillStyle = "rgba(180,180,180," + (0.3 + ratioV*0.4) + ")";
bCtx.fillRect(0, 0, 220, 300 - currentLiquidH);
// Bulles d'ébullition
bCtx.fillStyle = "rgba(255,255,255,0.7)";
for(let i=0; i<12; i++) {
let bx = Math.random()*200 + 10;
let by = (300-currentLiquidH) + Math.random()*currentLiquidH;
bCtx.beginPath(); bCtx.arc(bx, by, Math.random()*4, 0, Math.PI*2); bCtx.fill();
}
}
else {
// GAZ PUR : Occupe tout le bécher
bCtx.fillStyle = "rgba(180,180,180,0.7)";
bCtx.fillRect(0, 0, 220, 300);
// Petits points pour simuler l'agitation gazeuse
bCtx.fillStyle = "rgba(100,100,100,0.2)";
for(let i=0; i<20; i++) {
bCtx.fillRect(Math.random()*210, Math.random()*290, 2, 2);
}
}
// --- DESSIN DU GRAPHIQUE ---
gCtx.clearRect(0,0,600,450);
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke();
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke();
gCtx.fillStyle = "#666"; gCtx.font = "10px Arial";
for(let t = -150; t <= 150; t += 50) {
let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340;
gCtx.fillText(t + "°", 30, y + 5);
gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let px = 60 + (p.x / s.maxQ) * 500;
let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-final" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;">
<div style="display: flex; gap: 10px; align-items: center;">
<label style="font-weight: bold; color: #555;">Substance :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;">
<option value="eau">Eau (H₂O)</option>
<option value="ammoniac">Ammoniac (NH₃)</option>
<option value="isobutane">Isobutane (C₄H₁₀)</option>
<option value="difluoro">Difluorométhane (R-32)</option>
</select>
</div>
<div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-150.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; transition: background 0.3s; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div>
<div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div>
</div>
</div>
<div style="flex: 2; min-width: 450px;">
<canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 15px; margin-top: 25px;">
<button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button>
<button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const select = document.getElementById('selectFluide');
const db = {
eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, color: "#2196f3", maxQ: 4200000 },
ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, color: "#4caf50", maxQ: 3200000 },
isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, color: "#ff9800", maxQ: 1800000 },
difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, color: "#009688", maxQ: 1500000 }
};
let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 4500, masse = 1, tStart = -150, tEnd = 150;
window.initSubstance = function() {
s = db[select.value];
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION";
document.getElementById('btnPlay').style.background = "#2e7d32";
heater.style.background = "#333";
updateUI();
};
window.resetSim = function() { initSubstance(); };
window.toggleSim = function() {
if(temp >= tEnd) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
if(!isRunning) heater.style.background = "#333";
};
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.nom;
}
function update() {
if(!isRunning) return;
if(temp >= tEnd) { isRunning = false; heater.style.background = "#333"; return; }
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c";
energy += pwr * 2.2;
let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0;
let q2 = (s.tf > tStart) ? masse * s.lf : 0;
let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf));
let q4 = masse * s.lv;
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.tf;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
document.getElementById('formule-text').innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = Math.max(tStart, s.tf) + (energy - q1 - q2)/(masse*s.cl);
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = s.tv;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
document.getElementById('formule-text').innerHTML = "Q = m · Lv";
} else {
temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg);
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT";
}
if(temp > tEnd) temp = tEnd;
pts.push({x: energy, y: temp});
updateUI();
}
function draw() {
bCtx.clearRect(0,0,220,300);
let hMax = 180;
let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0;
let q2 = (s.tf > tStart) ? masse * s.lf : 0;
let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf));
// 1. DESSIN DU SOLIDE / LIQUIDE
if(temp < s.tf) {
// SOLIDE : Bloc avec espace sur les côtés
bCtx.fillStyle = "#bbdefb";
bCtx.fillRect(20, 300-hMax, 180, hMax);
} else if (temp === s.tf) {
// FUSION : Le solide fond, le liquide commence à remplir les bords
let ratio = (energy - q1) / s.lf;
// Fond liquide (remplit tout le bécher)
bCtx.fillStyle = s.color;
bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio);
// Reste solide (forme propre)
bCtx.fillStyle = "#bbdefb";
bCtx.fillRect(20, 300-hMax, 180, hMax * (1-ratio));
} else if(temp < s.tv) {
// LIQUIDE : Remplit tout le bécher (pas d'espace)
bCtx.fillStyle = s.color;
bCtx.fillRect(0, 300-hMax, 220, hMax);
} else if (temp === s.tv) {
// ÉBULLITION : Le niveau baisse, le gaz apparaît en haut
let ratioV = (energy - q1 - q2 - q3) / s.lv;
let currentH = hMax * (1 - ratioV);
// Liquide restant
bCtx.fillStyle = s.color;
bCtx.fillRect(0, 300-currentH, 220, currentH);
// Gaz qui apparaît (opacité progressive)
bCtx.fillStyle = "rgba(180,180,180," + (0.2 + ratioV*0.5) + ")";
bCtx.fillRect(0, 300-hMax, 220, hMax - currentH);
// Bulles aléatoires
bCtx.fillStyle = "rgba(255,255,255,0.6)";
for(let i=0; i<10; i++) {
let bx = Math.random()*200 + 10;
let by = (300-currentH) + Math.random()*currentH;
bCtx.beginPath(); bCtx.arc(bx, by, 3, 0, Math.PI*2); bCtx.fill();
}
} else {
// GAZ : Remplit tout le bécher uniformément
bCtx.fillStyle = "rgba(180,180,180,0.6)";
bCtx.fillRect(0, 0, 220, 300);
}
// 2. DESSIN DU GRAPHIQUE
gCtx.clearRect(0,0,600,450);
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke();
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke();
gCtx.fillStyle = "#666"; gCtx.font = "10px Arial";
for(let t = -150; t <= 150; t += 50) {
let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340;
gCtx.fillText(t + "°", 30, y + 5);
gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let px = 60 + (p.x / s.maxQ) * 500;
let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-final" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;">
<div style="display: flex; gap: 10px; align-items: center;">
<label style="font-weight: bold; color: #555;">Substance :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;">
<option value="eau">Eau (H₂O)</option>
<option value="ammoniac">Ammoniac (NH₃)</option>
<option value="isobutane">Isobutane (C₄H₁₀)</option>
<option value="difluoro">Difluorométhane (R-32)</option>
</select>
</div>
<div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-150.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; transition: background 0.3s; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div>
<div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div>
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-top: 15px;">FORMULE APPLIQUÉE</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px;">Q = m · cₛ · ΔT</div>
</div>
<div id="specs-box" style="width: 100%; margin-top: 15px; background: #f9f9f9; padding: 15px; border-radius: 10px; border: 1px dashed #ccc; font-size: 0.85em;">
<b>Propriétés :</b> m = 1kg | P = 4500W<br>
<span id="data-list"></span>
</div>
</div>
<div style="flex: 2; min-width: 450px;">
<canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 15px; margin-top: 25px;">
<button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button>
<button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const heater = document.getElementById('heater');
const select = document.getElementById('selectFluide');
const db = {
eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, color: "#2196f3", maxQ: 4200000 },
ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, color: "#4caf50", maxQ: 3200000 },
isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, color: "#ff9800", maxQ: 1800000 },
difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, color: "#009688", maxQ: 1500000 }
};
let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0;
const pwr = 4500, masse = 1, tStart = -150, tEnd = 150;
window.initSubstance = function() {
s = db[select.value];
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION";
document.getElementById('btnPlay').style.background = "#2e7d32";
heater.style.background = "#333";
updateUI();
};
window.resetSim = function() { initSubstance(); };
window.toggleSim = function() {
if(temp >= tEnd) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
if(!isRunning) heater.style.background = "#333";
};
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.nom;
document.getElementById('data-list').innerHTML = `cs = ${s.cs} J/kgK | Lf = ${s.lf/1000} kJ/kg | cl = ${s.cl} J/kgK | Lv = ${s.lv/1000} kJ/kg`;
}
function update() {
if(!isRunning) return;
if(temp >= tEnd) { isRunning = false; heater.style.background = "#333"; return; }
// Animation plaque
blinkFrame++;
heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c";
energy += pwr * 2.2;
let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0;
let q2 = (s.tf > tStart) ? masse * s.lf : 0;
let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf));
let q4 = masse * s.lv;
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.tf;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
document.getElementById('formule-text').innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = Math.max(tStart, s.tf) + (energy - q1 - q2)/(masse*s.cl);
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = s.tv;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
document.getElementById('formule-text').innerHTML = "Q = m · Lv";
} else {
temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg);
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT";
}
if(temp > tEnd) temp = tEnd;
pts.push({x: energy, y: temp});
updateUI();
}
function draw() {
bCtx.clearRect(0,0,220,300);
let h = 180; // Hauteur du fluide
// Ajustement des blocs au bécher (largeur 200px entre les parois de 10px)
if(temp < s.tf) {
bCtx.fillStyle = "#bbdefb"; // Aspect glace
bCtx.fillRect(6, 300-h, 208, h);
} else if (temp === s.tf) {
// Animation fusion (mélange solide/liquide)
let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0;
let ratio = (energy - q1) / s.lf;
bCtx.fillStyle = s.color; bCtx.fillRect(6, 300-(h*ratio), 208, h*ratio);
bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(6, 300-h, 208, h*(1-ratio));
} else if(temp < s.tv) {
bCtx.fillStyle = s.color;
bCtx.fillRect(6, 300-h, 208, h);
} else if (temp === s.tv) {
// Animation ébullition
let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0;
let q2 = (s.tf > tStart) ? masse * s.lf : 0;
let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf));
let ratioV = (energy - q1 - q2 - q3) / s.lv;
bCtx.fillStyle = s.color; bCtx.globalAlpha = 1 - ratioV;
bCtx.fillRect(6, 300-h, 208, h);
bCtx.globalAlpha = 1.0;
bCtx.fillStyle = "rgba(200,200,200,0.4)"; // Vapeur
bCtx.fillRect(6, 0, 208, 300);
} else {
bCtx.fillStyle = "rgba(180,180,180,0.5)"; // Gaz pur
bCtx.fillRect(6, 0, 208, 300);
}
// Graphique
gCtx.clearRect(0,0,600,450);
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke();
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke();
gCtx.fillStyle = "#666"; gCtx.font = "10px Arial";
for(let t = -150; t <= 150; t += 50) {
let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340;
gCtx.fillText(t + "°", 30, y + 5);
gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let px = 60 + (p.x / s.maxQ) * 500;
let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-fixed" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;">
<div style="display: flex; gap: 10px; align-items: center;">
<label style="font-weight: bold; color: #555;">Substance :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;">
<option value="eau">Eau (H₂O)</option>
<option value="ammoniac">Ammoniac (NH₃)</option>
<option value="isobutane">Isobutane (C₄H₁₀)</option>
<option value="difluoro">Difluorométhane (R-32)</option>
</select>
</div>
<div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-150.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #555; border-right: 6px solid #555; border-bottom: 6px solid #555; background: #fff; border-radius: 0 0 15px 15px;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; margin-left: -5px;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div>
<div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div>
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-top: 15px;">FORMULE APPLIQUÉE</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px;">Q = m · cₛ · ΔT</div>
</div>
<div id="specs-box" style="width: 100%; margin-top: 15px; background: #f9f9f9; padding: 15px; border-radius: 10px; border: 1px dashed #ccc; font-size: 0.85em;">
<b>Propriétés :</b> m = 1kg | P = 4500W<br>
<span id="data-list"></span>
</div>
</div>
<div style="flex: 2; min-width: 450px;">
<canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 15px; margin-top: 25px;">
<button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button>
<button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
<div style="margin-top: 15px; font-size: 0.9em; color: #666; font-style: italic;">
Note : La simulation couvre la plage de -150°C à +150°C pour toutes les substances.
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const select = document.getElementById('selectFluide');
const db = {
eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, color: "#1565c0", maxQ: 4200000 },
ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, color: "#689f38", maxQ: 3200000 },
isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, color: "#e65100", maxQ: 1800000 },
difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, color: "#00796b", maxQ: 1500000 }
};
let s, temp, energy, isRunning = false, pts = [];
const pwr = 4500, masse = 1, tStart = -150, tEnd = 150;
window.initSubstance = function() {
s = db[select.value];
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION";
document.getElementById('btnPlay').style.background = "#2e7d32";
updateUI();
};
window.resetSim = function() {
initSubstance();
};
window.toggleSim = function() {
if(temp >= tEnd) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.nom;
document.getElementById('data-list').innerHTML = `cs = ${s.cs} J/kgK | Lf = ${s.lf/1000} kJ/kg | cl = ${s.cl} J/kgK | Lv = ${s.lv/1000} kJ/kg`;
}
function update() {
if(!isRunning) return;
if(temp >= tEnd) { isRunning = false; return; }
energy += pwr * 2.0;
// Calcul des paliers d'énergie
// 1. Solide de tStart à tf (si tStart < tf)
let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0;
// 2. Fusion
let q2 = (s.tf > tStart) ? masse * s.lf : 0;
// 3. Liquide de tf à tv
let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf));
// 4. Vaporisation
let q4 = masse * s.lv;
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.tf;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
document.getElementById('formule-text').innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = Math.max(tStart, s.tf) + (energy - q1 - q2)/(masse*s.cl);
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = s.tv;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
document.getElementById('formule-text').innerHTML = "Q = m · Lv";
} else {
temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg);
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT";
}
if(temp > tEnd) temp = tEnd;
pts.push({x: energy, y: temp});
updateUI();
}
function draw() {
bCtx.clearRect(0,0,220,300);
let h = 140;
if(temp < s.tf) bCtx.fillStyle = "#e3f2fd";
else if(temp < s.tv) bCtx.fillStyle = s.color;
else bCtx.fillStyle = "rgba(150,150,150,0.4)";
bCtx.fillRect(10, 300-h, 200, h);
gCtx.clearRect(0,0,600,450);
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke(); // Y
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke(); // X
// Graduation Y
gCtx.fillStyle = "#666"; gCtx.font = "10px Arial";
for(let t = -150; t <= 150; t += 50) {
let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340;
gCtx.fillText(t + "°", 30, y + 5);
gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let px = 60 + (p.x / s.maxQ) * 500;
let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px;"> <div style="display: flex; gap: 10px; align-items: center;"> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b;"> <option value="eau">Eau (H₂O)</option> <option value="ammoniac">Ammoniac (NH₃)</option> <option value="isobutane">Isobutane (C₄H₁₀)</option> <option value="difluoro">Difluorométhane (R-32)</option> </select> <button id="btnMystere" onclick="toggleMystere()" style="padding: 10px 15px; background: #673ab7; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">🕵️ MODE MYSTÈRE : OFF</button> </div> <div style="display: flex; align-items: center; gap: 20px;"> <div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-50.0 °C</div> </div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #555; border-right: 6px solid #555; border-bottom: 6px solid #555; background: #fff; border-radius: 0 0 15px 15px;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; margin-left: -5px;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-top: 15px;">FORMULE APPLIQUÉE</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px;">Q = m · cₛ · ΔT</div> </div> <div id="specs-box" style="width: 100%; margin-top: 15px; background: #f9f9f9; padding: 15px; border-radius: 10px; border: 1px dashed #ccc; font-size: 0.85em;"> <b>Données :</b> m = 1kg | P = 4500W<br> <span id="data-list">cₛ = 2090 J/kgK | Lf = 334 kJ/kg</span> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button> <button onclick="location.reload()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> <div id="mystery-hint" style="display:none; margin-top: 15px; padding: 15px; background: #fff9c4; border-left: 5px solid #fbc02d; border-radius: 5px;"> <b>🕵️ DÉFI :</b> Identifiez la substance en observant les températures de paliers (lignes horizontales) et les pentes ! </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const db = { eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, t0: -50, tEnd: 150, color: "#1565c0", maxQ: 3500000 }, ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, t0: -100, tEnd: 50, color: "#689f38", maxQ: 2500000 }, isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, t0: -180, tEnd: 100, color: "#e65100", maxQ: 1500000 }, difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, t0: -160, tEnd: 80, color: "#00796b", maxQ: 1200000 } }; let s, temp, energy, isRunning = false, pts = [], isMystere = false; const pwr = 4500, masse = 1; window.initSubstance = function() { const val = document.getElementById('selectFluide').value; s = db[val]; temp = s.t0; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION"; document.getElementById('btnPlay').style.background = "#2e7d32"; updateUI(); }; window.toggleMystere = function() { isMystere = !isMystere; document.getElementById('btnMystere').innerText = isMystere ? "🕵️ MODE MYSTÈRE : ON" : "🕵️ MODE MYSTÈRE : OFF"; document.getElementById('btnMystere').style.background = isMystere ? "#f44336" : "#673ab7"; document.getElementById('mystery-hint').style.display = isMystere ? "block" : "none"; document.getElementById('specs-box').style.visibility = isMystere ? "hidden" : "visible"; updateUI(); }; window.toggleSim = function() { if(temp >= s.tEnd) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = isMystere ? "SUBSTANCE MYSTÈRE" : s.nom; document.getElementById('data-list').innerHTML = `cs = ${s.cs} J/kgK | Lf = ${s.lf/1000} kJ/kg | cl = ${s.cl} J/kgK | Lv = ${s.lv/1000} kJ/kg`; } function update() { if(!isRunning) return; if(temp >= s.tEnd) { isRunning = false; return; } energy += pwr * 2.0; let q1 = masse * s.cs * (s.tf - s.t0); let q2 = masse * s.lf; let q3 = masse * s.cl * (s.tv - s.tf); let q4 = masse * s.lv; if(energy < q1) { temp = s.t0 + energy/(masse*s.cs); document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if(energy < q1+q2) { temp = s.tf; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if(energy < q1+q2+q3) { temp = s.tf + (energy-q1-q2)/(masse*s.cl); document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if(energy < q1+q2+q3+q4) { temp = s.tv; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy-q1-q2-q3-q4)/(masse*s.cg); document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } pts.push({x: energy, y: temp}); updateUI(); } function draw() { bCtx.clearRect(0,0,220,300); // Dessin du fluide let h = 140; if(temp < s.tf) bCtx.fillStyle = "#e3f2fd"; else if(temp < s.tv) bCtx.fillStyle = s.color; else bCtx.fillStyle = "rgba(100,100,100,0.3)"; bCtx.fillRect(10, 300-h, 200, h); gCtx.clearRect(0,0,600,450); // Axes gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke(); // Y gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke(); // X // Tracé courbe if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - s.t0) / (s.tEnd - s.t0)) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-challenge-integrated" style="width: 100%; max-width: 1280px; background: #f4f4f9; border: 2px solid #333; border-radius: 20px; padding: 25px; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #222; margin: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: 20px;">
<div style="text-align: center; background: #333; color: #ffca28; padding: 15px; border-radius: 12px; border-bottom: 4px solid #ffca28;">
<h2 style="margin: 0; text-transform: uppercase; letter-spacing: 2px;">🧪 ÉVALUATION : THERMODYNAMIQUE APPLIQUÉE</h2>
<p style="margin: 5px 0 0 0; font-weight: bold; color: #fff;">SUBSTANCE MYSTÈRE — MODE CHALLENGE ACTIVÉ</p>
</div>
<div style="display: flex; flex-wrap: wrap; gap: 25px;">
<div style="flex: 1.2; min-width: 450px; display: flex; flex-direction: column; gap: 15px;">
<div style="display: flex; gap: 10px; background: #fff; padding: 10px; border-radius: 10px; border: 1px solid #ccc;">
<canvas id="beakerCanvas" width="220" height="300" style="background: #fff; border-radius: 8px; flex: 1;"></canvas>
<canvas id="graphCanvas" width="300" height="300" style="background: #fafafa; border-radius: 8px; flex: 1.5;"></canvas>
</div>
<div id="dataPanel" style="background: #e8f5e9; border: 2px solid #2e7d32; border-radius: 12px; padding: 10px;">
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; text-align: center; font-size: 0.85em;">
<div style="background:#fff; padding:5px; border-radius:5px;">c<sub>s</sub>: <strong id="val_cs">-</strong><br><small>J/kg·K</small></div>
<div style="background:#fff; padding:5px; border-radius:5px;">c<sub>l</sub>: <strong id="val_cl">-</strong><br><small>J/kg·K</small></div>
<div style="background:#fff; padding:5px; border-radius:5px;">c<sub>g</sub>: <strong id="val_cg">-</strong><br><small>J/kg·K</small></div>
<div style="background:#fff; padding:5px; border-radius:5px;">L<sub>f</sub>: <strong id="val_lf">-</strong><br><small>kJ/kg</small></div>
<div style="background:#fff; padding:5px; border-radius:5px;">L<sub>v</sub>: <strong id="val_lv">-</strong><br><small>kJ/kg</small></div>
<div style="background:#fff; padding:5px; border-radius:5px;">T<sub>f</sub>/T<sub>v</sub>:<br><strong id="val_temps">-</strong></div>
</div>
</div>
<div style="background: #eee; padding: 15px; border-radius: 12px; display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
<div style="text-align:center;">T. Init: <input type="number" id="t_start_val" value="-60" style="width:60px; font-weight:bold;"></div>
<div style="text-align:center;">Masse: <input type="number" id="m_val" value="1.0" step="0.1" style="width:60px; font-weight:bold;"> kg</div>
<div style="grid-column: span 2; display: flex; gap: 10px;">
<button id="mainBtn" onclick="handleBtn()" style="flex:1; padding: 12px; background: #2e7d32; color:white; border:none; border-radius:8px; font-weight:bold; cursor:pointer;">LANCER LA SIMULATION</button>
<button id="revealBtn" onclick="revealResults()" style="padding: 12px; background: #d32f2f; color:white; border:none; border-radius:8px; font-weight:bold; cursor:pointer; display:none;">RÉVÉLER</button>
</div>
</div>
<div id="tempDisp" style="font-size: 2.5em; font-weight: bold; text-align: center; border: 3px solid #333; background: #fff; border-radius: 10px;">-- °C</div>
</div>
<div style="flex: 1; min-width: 350px; background: #fff; border-radius: 15px; border: 1px solid #ccc; padding: 20px; display: flex; flex-direction: column; gap: 15px;">
<h3 style="margin-top: 0; color: #d32f2f; border-bottom: 2px solid #eee; padding-bottom: 10px;">📝 QUESTIONS DE RÉFLEXION</h3>
<div id="quiz-container" style="overflow-y: auto; max-height: 500px; padding-right: 10px;">
<div class="q-box" style="margin-bottom: 20px; padding: 10px; border-bottom: 1px solid #eee;">
<p style="font-weight: bold; margin-bottom: 8px;">1. Pourquoi la température reste-t-elle bloquée par moments ?</p>
<select id="q1" style="width: 100%; padding: 5px;">
<option value="">-- Choisir --</option>
<option value="correct">Changement d'état (Energie de liaison)</option>
<option value="wrong">Panne du système de chauffe</option>
<option value="wrong">Le capteur est bloqué</option>
</select>
</div>
<div class="q-box" style="margin-bottom: 20px; padding: 10px; border-bottom: 1px solid #eee;">
<p style="font-weight: bold; margin-bottom: 8px;">2. Quelle constante est utilisée pour chauffer le SOLIDE ?</p>
<select id="q2" style="width: 100%; padding: 5px;">
<option value="">-- Choisir --</option>
<option value="correct">c_s (capacité thermique solide)</option>
<option value="wrong">L_f (chaleur latente de fusion)</option>
<option value="wrong">c_l (capacité thermique liquide)</option>
</select>
</div>
<div class="q-box" style="margin-bottom: 20px; padding: 10px; border-bottom: 1px solid #eee;">
<p style="font-weight: bold; margin-bottom: 8px;">3. Si P=2000W pendant 100s, quelle est l'énergie Q ?</p>
<select id="q3" style="width: 100%; padding: 5px;">
<option value="">-- Choisir --</option>
<option value="wrong">20 kJ</option>
<option value="correct">200 kJ</option>
<option value="wrong">2000 J</option>
</select>
</div>
<div class="q-box" style="margin-bottom: 20px; padding: 10px; border-bottom: 1px solid #eee;">
<p style="font-weight: bold; margin-bottom: 8px;">4. La pente dépend de quelle propriété ?</p>
<select id="q4" style="width: 100%; padding: 5px;">
<option value="">-- Choisir --</option>
<option value="correct">La capacité thermique massique (c)</option>
<option value="wrong">La couleur de la substance</option>
<option value="wrong">Seulement de la puissance</option>
</select>
</div>
<div class="q-box" style="margin-bottom: 20px; padding: 10px; border-bottom: 1px solid #eee;">
<p style="font-weight: bold; margin-bottom: 8px;">5. Un palier plus long sur le graph signifie :</p>
<select id="q5" style="width: 100%; padding: 5px;">
<option value="">-- Choisir --</option>
<option value="wrong">Une température plus basse</option>
<option value="correct">Une chaleur latente (L) plus élevée</option>
<option value="wrong">Une masse plus petite</option>
</select>
</div>
</div>
<button onclick="checkQuiz()" style="width: 100%; padding: 15px; background: #333; color: #ffca28; border: none; border-radius: 8px; font-weight: bold; cursor: pointer; font-size: 1.1em;">VÉRIFIER MES RÉPONSES</button>
<div id="quiz-feedback" style="text-align: center; font-weight: bold; font-size: 1.2em; padding: 10px; border-radius: 8px; display: none;"></div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerCanvas'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphCanvas'), gCtx = gC.getContext('2d');
const BK = { x: 45, y: 30, w: 130, h: 220, baseH: 60 };
const substances = [
{ id:"Eau", cs:2090, cl:4185, cg:2010, lf:334000, lv:2260000, tf:0, tv:100, color:"#1565c0" },
{ id:"Ammoniac", cs:2100, cl:4700, cg:2100, lf:331000, lv:1371000, tf:-77.7, tv:-33.3, color:"#fbc02d" },
{ id:"Isobutane", cs:1600, cl:2350, cg:1650, lf:78000, lv:366000, tf:-159.6, tv:-11.7, color:"#e65100" }
];
let sub, m, p=2000, energy=0, isRunning=false, points=[], temp, t_start, t_end=150, maxE;
window.initSubstance = function() {
sub = substances[Math.floor(Math.random() * substances.length)];
t_start = parseFloat(document.getElementById('t_start_val').value);
temp = t_start; energy = 0; isRunning = false; points = [];
document.getElementById('dataPanel').style.borderColor = sub.color;
updateDisplay();
updateDataPanel();
};
function updateDataPanel() {
document.getElementById('val_cs').innerText = sub.cs;
document.getElementById('val_cl').innerText = sub.cl;
document.getElementById('val_cg').innerText = sub.cg;
document.getElementById('val_lf').innerText = (sub.lf/1000).toFixed(0);
document.getElementById('val_lv').innerText = (sub.lv/1000).toFixed(0);
document.getElementById('val_temps').innerText = sub.tf + " / " + sub.tv;
}
window.handleBtn = function() {
if(!isRunning || temp >= t_end) {
m = parseFloat(document.getElementById('m_val').value);
t_start = parseFloat(document.getElementById('t_start_val').value);
let q1 = (t_start < sub.tf) ? m*sub.cs*(Math.min(t_end, sub.tf) - t_start) : 0;
let q2 = (t_start <= sub.tf && t_end > sub.tf) ? m*sub.lf : 0;
let q3 = (t_end > sub.tf) ? m*sub.cl*(Math.min(t_end, sub.tv) - Math.max(t_start, sub.tf)) : 0;
let q4 = (t_start <= sub.tv && t_end > sub.tv) ? m*sub.lv : 0;
let q5 = (t_end > sub.tv) ? m*sub.cg*(t_end - Math.max(t_start, sub.tv)) : 0;
maxE = q1+q2+q3+q4+q5;
temp = t_start; energy = 0; points = []; isRunning = true;
document.getElementById('mainBtn').innerText = "EN COURS...";
document.getElementById('revealBtn').style.display = "none";
}
};
window.revealResults = function() {
alert("La substance était : " + sub.id + "\nChaleur totale : " + Math.round(maxE).toLocaleString() + " Joules");
};
window.checkQuiz = function() {
let score = 0;
for(let i=1; i<=5; i++) {
if(document.getElementById('q'+i).value === 'correct') score++;
}
const feedback = document.getElementById('quiz-feedback');
feedback.style.display = 'block';
feedback.innerText = "Score : " + score + "/5";
feedback.style.background = score === 5 ? "#c8e6c9" : "#ffcdd2";
feedback.style.color = score === 5 ? "#2e7d32" : "#c62828";
};
function update() {
if(!isRunning || temp >= t_end) return;
energy += p * 3;
let q1 = (t_start < sub.tf) ? m*sub.cs*(sub.tf - t_start) : 0;
let q2 = (t_start <= sub.tf) ? m*sub.lf : 0;
let q3 = (t_start < sub.tv) ? m*sub.cl*(sub.tv - Math.max(t_start, sub.tf)) : 0;
let q4 = (t_start <= sub.tv) ? m*sub.lv : 0;
if (t_start < sub.tf && energy < q1) temp = t_start + energy/(m*sub.cs);
else if (t_start <= sub.tf && energy < q1+q2) temp = sub.tf;
else if (energy < q1+q2+q3) temp = Math.max(t_start, sub.tf) + (energy-q1-q2)/(m*sub.cl);
else if (t_end > sub.tv && energy < q1+q2+q3+q4) temp = sub.tv;
else temp = Math.max(t_start, sub.tv) + (energy-q1-q2-q3-q4)/(m*sub.cg);
if (temp >= t_end) {
temp = t_end; isRunning = false;
document.getElementById('mainBtn').innerText = "TERMINÉ";
document.getElementById('revealBtn').style.display = "inline-block";
}
updateDisplay();
points.push({e: energy, t: temp});
}
function updateDisplay() {
document.getElementById('tempDisp').innerText = temp.toFixed(1) + " °C";
document.getElementById('tempDisp').style.color = sub.color;
}
function draw() {
bCtx.clearRect(0,0,bC.width,bC.height);
bCtx.strokeStyle="#333"; bCtx.lineWidth=6; bCtx.strokeRect(BK.x, BK.y, BK.w, BK.h);
bCtx.fillStyle = sub.color + "44";
let fillH = (temp < sub.tf) ? 40 : (temp < sub.tv) ? 100 : 20;
bCtx.fillRect(BK.x+5, BK.y+BK.h-fillH, BK.w-10, fillH);
gCtx.clearRect(0,0,gC.width,gC.height);
gCtx.beginPath(); gCtx.strokeStyle="#ccc"; gCtx.moveTo(40,280); gCtx.lineTo(40,20); gCtx.moveTo(40,280); gCtx.lineTo(290,280); gCtx.stroke();
if(points.length > 1) {
gCtx.beginPath(); gCtx.strokeStyle=sub.color; gCtx.lineWidth=2;
points.forEach((p, i) => {
let px = 40 + (p.e/maxE)*240;
let py = 280 - ((p.t-t_start)/(t_end-t_start))*240;
if(i===0) gCtx.moveTo(px,py); else gCtx.lineTo(px,py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance(); loop();
})();
</script>
<div id="thermo-ultra-challenge" style="width: 100%; max-width: 1280px; background: #fff; border: 3px solid #333; border-radius: 20px; overflow: hidden; font-family: 'Segoe UI', sans-serif; margin: auto; display: flex; flex-direction: column; box-shadow: 0 15px 50px rgba(0,0,0,0.3);">
<div id="level-header" style="background: #1565c0; color: white; padding: 20px; display: flex; justify-content: space-between; align-items: center;">
<h2 style="margin:0;">NIVEAU <span id="lvl-num">1</span> : <span id="lvl-name">SUBSTANCE MYSTÈRE</span></h2>
<div style="font-weight: bold; background: rgba(0,0,0,0.2); padding: 8px 15px; border-radius: 8px;">
Masse: <span id="display-mass">1.0</span> kg | Puissance: 2000 W
</div>
</div>
<div style="display: flex; flex-wrap: wrap;">
<div style="flex: 1.5; min-width: 500px; padding: 25px; background: #f0f2f5; border-right: 2px solid #ddd;">
<div style="display: flex; gap: 20px; margin-bottom: 20px;">
<canvas id="beakerCanvas" width="180" height="380" style="background: #fff; border: 2px solid #555; border-radius: 10px;"></canvas>
<canvas id="graphCanvas" width="480" height="380" style="background: #fff; border: 2px solid #555; border-radius: 10px; flex-grow:1;"></canvas>
</div>
<div style="display: grid; grid-template-columns: 1.5fr 1fr; gap: 20px;">
<div id="dataPanel" style="background: #e3f2fd; padding: 15px; border-radius: 12px; border-left: 10px solid #1565c0;">
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; font-weight: bold;">
<div>cₛ: <span id="v_cs">-</span> J/kg·K</div>
<div>cₗ: <span id="v_cl">-</span> J/kg·K</div>
<div>c_g: <span id="v_cg">-</span> J/kg·K</div>
<div>L_f: <span id="v_lf">-</span> kJ/kg</div>
<div>L_v: <span id="v_lv">-</span> kJ/kg</div>
<div style="color:#d32f2f">Paliers: <span id="v_pal">-</span> °C</div>
</div>
</div>
<div style="text-align: center; display: flex; flex-direction: column; justify-content: center;">
<div id="tempDisp" style="font-size: 3.5em; font-weight: bold; color: #1565c0; font-family: monospace;">-- °C</div>
<button id="mainBtn" onclick="startSim()" style="padding: 15px; background: #1565c0; color: white; border: none; border-radius: 10px; font-weight: bold; cursor: pointer; font-size: 1.2em;">LANCER LE CHAUFFAGE</button>
</div>
</div>
</div>
<div style="flex: 1; min-width: 380px; padding: 25px; background: white;">
<h3 style="margin-top: 0; color: #1565c0; border-bottom: 2px solid #eee; padding-bottom: 10px;">FEUILLE DE ROUTE</h3>
<div id="quiz-box" style="margin-top: 10px;"></div>
<div id="feedback" style="margin-top: 15px; padding: 12px; border-radius: 8px; font-weight: bold; display: none; text-align: center;"></div>
<button id="valBtn" onclick="checkAll()" style="width: 100%; padding: 20px; margin-top: 20px; background: #222; color: #ffca28; border: none; border-radius: 10px; font-weight: bold; cursor: pointer; font-size: 1.1em;">VALIDER LE NIVEAU</button>
<button id="nextBtn" onclick="goNext()" style="width: 100%; padding: 20px; margin-top: 20px; background: #2e7d32; color: white; border: none; border-radius: 10px; font-weight: bold; cursor: pointer; display: none;">PASSER À LA SUITE ➔</button>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerCanvas'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphCanvas'), gCtx = gC.getContext('2d');
const levels = [
{ name: "Eau", mass: 1.0, color: "#0d47a1", data: {cs:2090, cl:4185, cg:2010, lf:334, lv:2260, tf:0, tv:100},
qs: [
{q: "1. Quelle est cette substance ?", o: ["Eau", "Ammoniac", "Méthane"], a: "Eau"},
{q: "2. Que signifie Qf ?", o: ["Fusion", "Froid", "Force"], a: "Fusion"},
{q: "3. Calcul Qv (1kg) ?", o: ["2260 kJ", "334 kJ", "4185 J"], a: "2260 kJ"},
{q: "4. Pourquoi un palier ?", o: ["Rupture liaisons", "Panne chauffe", "Capteur bloqué"], a: "Rupture liaisons"},
{q: "5. Pente dépend de :", o: ["Capacité c", "Couleur", "Puissance"], a: "Capacité c"}
]
},
{ name: "Ammoniac", mass: 0.5, color: "#ffa000", data: {cs:2100, cl:4700, cg:2100, lf:331, lv:1371, tf:-77.7, tv:-33.3},
qs: [
{q: "1. Température de fusion ?", o: ["-77.7°C", "-33.3°C", "0°C"], a: "-77.7°C"},
{q: "2. Qv est-il < à l'eau ?", o: ["Oui", "Non"], a: "Oui"},
{q: "3. Calcul Qv (0.5kg) ?", o: ["685.5 kJ", "1371 kJ", "331 kJ"], a: "685.5 kJ"},
{q: "4. Pourquoi le palier est horizontal ?", o: ["Changement état", "Thermomètre cassé"], a: "Changement état"},
{q: "5. Si P=2000W, t=100s, Q= ?", o: ["200 kJ", "20 kJ", "2000 J"], a: "200 kJ"}
]
}
];
let cur = 0, pts = [], energy = 0, temp = 0, isRunning = false, mols = [];
const P = 2000;
function init() {
const l = levels[cur];
document.getElementById('lvl-num').innerText = cur+1;
document.getElementById('lvl-name').innerText = "SUBSTANCE MYSTÈRE";
document.getElementById('display-mass').innerText = l.mass;
document.getElementById('v_cs').innerText = l.data.cs;
document.getElementById('v_cl').innerText = l.data.cl;
document.getElementById('v_cg').innerText = l.data.cg;
document.getElementById('v_lf').innerText = l.data.lf;
document.getElementById('v_lv').innerText = l.data.lv;
document.getElementById('v_pal').innerText = l.data.tf + " / " + l.data.tv;
temp = l.data.tf - 50; energy = 0; pts = []; isRunning = false;
document.getElementById('mainBtn').innerText = "LANCER LE CHAUFFAGE";
mols = Array.from({length: 40}, () => ({x: 50+Math.random()*80, y: 280+Math.random()*60, vx: Math.random()-0.5, vy: Math.random()-0.5}));
document.getElementById('quiz-box').innerHTML = l.qs.map((q, i) => `
<div style="margin-bottom:12px; padding:10px; background:#f9f9f9; border-radius:5px;">
<p style="margin:0 0 5px 0; font-size:0.9em; font-weight:bold;">${q.q}</p>
<select id="ans${i}" style="width:100%; padding:5px; border-radius:4px;">
<option value="">-- Choisir --</option>
${q.o.map(opt => `<option value="${opt}">${opt}</option>`).join('')}
</select>
</div>
`).join('');
document.getElementById('feedback').style.display = 'none';
document.getElementById('nextBtn').style.display = 'none';
document.getElementById('valBtn').style.display = 'block';
}
window.startSim = function() { if(!isRunning) isRunning = true; };
window.checkAll = function() {
const l = levels[cur];
let ok = l.qs.every((q, i) => document.getElementById('ans'+i).value === q.a);
const fb = document.getElementById('feedback');
fb.style.display = 'block';
if(ok) {
fb.innerText = "BRAVO ! La substance était bien : " + l.name;
fb.style.background = "#e8f5e9"; fb.style.color = "#2e7d32";
document.getElementById('lvl-name').innerText = l.name;
document.getElementById('valBtn').style.display = 'none';
document.getElementById('nextBtn').style.display = 'block';
} else {
fb.innerText = "Il y a des erreurs. Vérifiez vos calculs !";
fb.style.background = "#ffebee"; fb.style.color = "#c62828";
}
};
window.goNext = function() { cur = (cur+1)%levels.length; init(); };
function update() {
if(!isRunning) return;
const l = levels[cur], m = l.mass;
energy += P * 3;
let q1 = m * l.data.cs * 50, q2 = m * l.data.lf * 1000, q3 = m * l.data.cl * (l.data.tv - l.data.tf), q4 = m * l.data.lv * 1000;
if (energy < q1) temp = (l.data.tf-50) + energy/(m*l.data.cs);
else if (energy < q1+q2) temp = l.data.tf;
else if (energy < q1+q2+q3) temp = l.data.tf + (energy-q1-q2)/(m*l.data.cl);
else if (energy < q1+q2+q3+q4) temp = l.data.tv;
else temp = l.data.tv + (energy-q1-q2-q3-q4)/(m*l.data.cg);
if(temp > l.data.tv + 50) isRunning = false;
document.getElementById('tempDisp').innerText = temp.toFixed(1) + " °C";
pts.push({e: energy, t: temp});
// Animation molécules
let speed = (temp + 200) / 100;
mols.forEach(mo => {
mo.x += mo.vx * speed; mo.y += mo.vy * speed;
if(mo.x<45 || mo.x>135) mo.vx *= -1;
if(mo.y< (temp > l.data.tv ? 40 : temp > l.data.tf ? 150 : 250) || mo.y>315) mo.vy *= -1;
});
}
function draw() {
const l = levels[cur];
bCtx.clearRect(0,0,180,380);
bCtx.strokeStyle="#333"; bCtx.lineWidth=5; bCtx.strokeRect(40,40,100,280);
bCtx.fillStyle = l.color;
mols.forEach(mo => {
bCtx.beginPath(); bCtx.arc(mo.x, mo.y, 4, 0, 7); bCtx.fill();
});
gCtx.clearRect(0,0,480,380);
gCtx.beginPath(); gCtx.strokeStyle="#aaa"; gCtx.moveTo(50,20); gCtx.lineTo(50,340); gCtx.lineTo(460,340); gCtx.stroke();
gCtx.fillStyle="#d32f2f"; gCtx.font="bold 12px Arial";
let yf = 340 - ((l.data.tf - (l.data.tf-50))/150)*300, yv = 340 - ((l.data.tv - (l.data.tf-50))/150)*300;
gCtx.fillText(l.data.tf+"°", 10, yf); gCtx.fillText(l.data.tv+"°", 10, yv);
if(pts.length>1) {
gCtx.beginPath(); gCtx.strokeStyle=l.color; gCtx.lineWidth=4;
let totalE = (m*l.data.cs*50) + (m*l.data.lf*1000) + (m*l.data.cl*(l.data.tv-l.data.tf)) + (m*l.data.lv*1000) + (m*l.data.cg*50);
pts.forEach((p, i) => {
let x = 50 + (p.e/totalE)*380, y = 340 - ((p.t-(l.data.tf-50))/150)*300;
if(i===0) gCtx.moveTo(x,y); else gCtx.lineTo(x,y);
});
gCtx.stroke();
}
}
setInterval(() => { update(); draw(); }, 30);
init();
})();
</script>
1. Pourquoi la température reste-t-elle bloquée par moments ?
-- Choisir --
Changement d'état (Energie de liaison)
Panne du système de chauffe
Le capteur est bloqué
2. Quelle constante est utilisée pour chauffer le SOLIDE ?
-- Choisir --
c_s (capacité thermique solide)
L_f (chaleur latente de fusion)
c_l (capacité thermique liquide)
3. Si P=2000W pendant 100s, quelle est l'énergie Q ?
-- Choisir --
20 kJ
200 kJ
2000 J
4. La pente dépend de quelle propriété ?
-- Choisir --
La capacité thermique massique (c)
La couleur de la substance
Seulement de la puissance
5. Un palier plus long sur le graph signifie :
" et remets un menu deroulant pour les reponses on voit pas la courbe ni le chauffage
<div id="thermo-pro-adventure" style="width: 100%; max-width: 1280px; background: #ffffff; border: 2px solid #333; border-radius: 15px; overflow: hidden; font-family: 'Segoe UI', sans-serif; margin: auto; box-sizing: border-box; display: flex; flex-direction: column; box-shadow: 0 10px 30px rgba(0,0,0,0.1);">
<div id="level-header" style="background: #1565c0; color: white; padding: 20px; display: flex; justify-content: space-between; align-items: center; border-bottom: 4px solid rgba(0,0,0,0.1);">
<div>
<h2 style="margin:0; text-transform: uppercase; letter-spacing: 1px;">Défi Thermodynamique : Niveau <span id="current-lvl-num">1</span></h2>
<p id="substance-display-name" style="margin:5px 0 0 0; font-weight: bold; background: rgba(0,0,0,0.2); display: inline-block; padding: 2px 10px; border-radius: 4px;">Substance Mystère</p>
</div>
<div style="text-align: right;">
<div style="font-size: 0.8em; opacity: 0.8;">Statut</div>
<div id="step-name" style="font-weight: bold;">ANALYSE EN COURS</div>
</div>
</div>
<div style="display: flex; flex-wrap: wrap; gap: 0;">
<div style="flex: 1.3; min-width: 450px; padding: 20px; background: #fdfdfd; border-right: 1px solid #eee;">
<div style="display: flex; flex-direction: column; gap: 15px;">
<div style="display: flex; gap: 10px; height: 350px;">
<canvas id="beakerCanvas" width="160" height="340" style="background: #fff; border-radius: 8px; border: 1px solid #ddd;"></canvas>
<canvas id="graphCanvas" width="450" height="340" style="background: #fff; border-radius: 8px; border: 1px solid #ddd; flex-grow: 1;"></canvas>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; background: #f1f3f5; padding: 15px; border-radius: 12px;">
<div id="dataPanel" style="background: white; border-left: 5px solid #1565c0; padding: 10px; border-radius: 4px; box-shadow: 0 2px 5px rgba(0,0,0,0.05);">
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 5px; font-size: 0.9em;">
<div>c<sub>s</sub>: <b id="val_cs">-</b></div>
<div>c<sub>l</sub>: <b id="val_cl">-</b></div>
<div>c<sub>g</sub>: <b id="val_cg">-</b></div>
<div>L<sub>f</sub>: <b id="val_lf">-</b> kJ/kg</div>
<div>L<sub>v</sub>: <b id="val_lv">-</b> kJ/kg</div>
<div><b>Puissance</b>: 2000 W</div>
</div>
</div>
<div style="display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 10px;">
<div style="font-size: 1.1em; font-weight: bold;">Masse : <span id="fixed-mass" style="color: #d32f2f;">1.0</span> kg</div>
<button id="mainBtn" onclick="handleBtn()" style="width: 100%; padding: 12px; background: #1565c0; color: white; border: none; border-radius: 6px; font-weight: bold; cursor: pointer; text-transform: uppercase;">Chauffer</button>
<div id="tempDisp" style="font-size: 2.2em; font-weight: bold; font-family: monospace;">-- °C</div>
</div>
</div>
</div>
</div>
<div id="quiz-zone" style="flex: 1; min-width: 350px; padding: 25px; display: flex; flex-direction: column; background: white;">
<h3 style="margin: 0 0 20px 0; border-bottom: 2px solid #f1f3f5; padding-bottom: 10px; color: #333;">Questions de validation</h3>
<div id="quiz-content" style="flex-grow: 1;">
</div>
<div id="feedback" style="margin-top: 15px; padding: 12px; border-radius: 6px; font-weight: bold; display: none; font-size: 0.9em;"></div>
<button onclick="checkAnswers()" id="validateBtn" style="width: 100%; padding: 15px; margin-top: 15px; background: #333; color: #ffca28; border: none; border-radius: 6px; font-weight: bold; cursor: pointer;">VÉRIFIER MES RÉPONSES</button>
<button onclick="nextLevel()" id="nextLvlBtn" style="width: 100%; padding: 15px; margin-top: 10px; background: #2e7d32; color: white; border: none; border-radius: 6px; font-weight: bold; cursor: pointer; display: none;">NIVEAU SUIVANT ➔</button>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerCanvas'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphCanvas'), gCtx = gC.getContext('2d');
const levels = [
{
name: "Eau (H₂O)", mass: 1.0, color: "#1565c0",
data: { cs:2090, cl:4185, cg:2010, lf:334, lv:2260, tf:0, tv:100 },
questions: [
{ q: "1. En observant les paliers de température, quelle est cette substance ?", options: ["Ammoniac", "Eau", "Éthanol"], correct: "Eau" },
{ q: "2. Que représente physiquement le terme 'Qf' ?", options: ["La chaleur de fusion", "La puissance du froid", "La quantité de liquide"], correct: "La chaleur de fusion" },
{ q: "3. Calculez l'énergie nécessaire pour vaporiser la masse totale ?", options: ["334 kJ", "2260 kJ", "4185 kJ"], correct: "2260 kJ" },
{ q: "4. Pourquoi observe-t-on un palier horizontal ?", options: ["La puissance se coupe", "L'énergie est utilisée pour le changement d'état", "Le liquide ne peut pas dépasser 100°C"], correct: "L'énergie est utilisée pour le changement d'état" }
]
},
{
name: "Ammoniac (NH₃)", mass: 0.5, color: "#f9a825",
data: { cs:2100, cl:4700, cg:2100, lf:331, lv:1371, tf:-77.7, tv:-33.3 },
questions: [
{ q: "1. À quelle température l'ammoniac commence-t-il sa fusion ?", options: ["-33.3°C", "0°C", "-77.7°C"], correct: "-77.7°C" },
{ q: "2. Comparez les chaleurs latentes de vaporisation. Celle de l'ammoniac est-elle plus faible que celle de l'eau ?", options: ["Non", "Oui", "Elles sont égales"], correct: "Oui" },
{ q: "3. Calculez l'énergie Qv nécessaire pour vaporiser la masse présente (0.5 kg) ?", options: ["1371 kJ", "685.5 kJ", "331 kJ"], correct: "685.5 kJ" },
{ q: "4. Le palier de vaporisation est-il plus court ou plus long que celui de l'eau ?", options: ["Plus court", "Plus long", "Identique"], correct: "Plus court" }
]
},
{
name: "Isobutane (C₄H₁₀)", mass: 0.8, color: "#e65100",
data: { cs:1600, cl:2350, cg:1650, lf:78, lv:366, tf:-159.6, tv:-11.7 },
questions: [
{ q: "1. La substance est-elle liquide ou gazeuse à la température de 0°C ?", options: ["Gazeuse", "Liquide", "Solide"], correct: "Gazeuse" },
{ q: "2. Comment jugez-vous la chaleur latente de fusion par rapport aux autres niveaux ?", options: ["Moyenne", "Très élevée", "Très faible"], correct: "Très faible" },
{ q: "3. Calculez l'énergie Qf nécessaire pour faire fondre l'échantillon ?", options: ["78 kJ", "62.4 kJ", "159.6 kJ"], correct: "62.4 kJ" },
{ q: "4. Comparée à l'eau, comment est la pente de montée en température de ce liquide ?", options: ["Identique", "Plus abrupte (chauffe plus vite)", "Plus douce"], correct: "Plus abrupte (chauffe plus vite)" }
]
}
];
let currentLvl = 0;
let points = [], energy = 0, temp = 0, isRunning = false;
const P = 2000;
function initLevel() {
const lvl = levels[currentLvl];
document.getElementById('current-lvl-num').innerText = currentLvl + 1;
document.getElementById('substance-display-name').innerText = "Substance Mystère";
document.getElementById('level-header').style.background = lvl.color;
document.getElementById('dataPanel').style.borderLeftColor = lvl.color;
document.getElementById('fixed-mass').innerText = lvl.mass;
document.getElementById('val_cs').innerText = lvl.data.cs;
document.getElementById('val_cl').innerText = lvl.data.cl;
document.getElementById('val_cg').innerText = lvl.data.cg;
document.getElementById('val_lf').innerText = lvl.data.lf;
document.getElementById('val_lv').innerText = lvl.data.lv;
temp = lvl.data.tf - 40; energy = 0; points = []; isRunning = false;
document.getElementById('mainBtn').innerText = "Chauffer";
document.getElementById('mainBtn').style.background = lvl.color;
const qContainer = document.getElementById('quiz-content');
qContainer.innerHTML = lvl.questions.map((q, i) => `
<div style="margin-bottom: 18px;">
<p style="font-weight: bold; font-size: 0.9em; margin: 0 0 8px 0; line-height: 1.3;">${q.q}</p>
<div style="display: flex; flex-direction: column; gap: 5px;">
${q.options.map(opt => `
<label style="font-size: 0.85em; cursor: pointer; background: #f8f9fa; padding: 8px; border-radius: 4px; border: 1px solid #eee;">
<input type="radio" name="q${i}" value="${opt}"> ${opt}
</label>
`).join('')}
</div>
</div>
`).join('');
document.getElementById('feedback').style.display = 'none';
document.getElementById('nextLvlBtn').style.display = 'none';
document.getElementById('validateBtn').style.display = 'block';
}
window.handleBtn = function() {
if(isRunning) return;
isRunning = true;
document.getElementById('mainBtn').innerText = "En cours...";
};
window.checkAnswers = function() {
const lvl = levels[currentLvl];
let score = 0;
lvl.questions.forEach((q, i) => {
const selected = document.querySelector(`input[name="q${i}"]:checked`);
if(selected && selected.value === q.correct) score++;
});
const fb = document.getElementById('feedback');
fb.style.display = 'block';
if(score === lvl.questions.length) {
fb.innerText = "EXCELLENT ! Tous les calculs et observations sont corrects.";
fb.style.background = "#e8f5e9"; fb.style.color = "#2e7d32";
document.getElementById('validateBtn').style.display = 'none';
document.getElementById('nextLvlBtn').style.display = 'block';
document.getElementById('substance-display-name').innerText = lvl.name;
} else {
fb.innerText = "Erreur : " + score + "/" + lvl.questions.length + " correctes. Regardez bien les données et le graphique.";
fb.style.background = "#ffebee"; fb.style.color = "#c62828";
}
};
window.nextLevel = function() {
currentLvl++;
if(currentLvl >= levels.length) {
alert("Bravo ! Vous avez validé toutes les substances !");
currentLvl = 0;
}
initLevel();
};
function update() {
if(!isRunning) return;
const lvl = levels[currentLvl];
const m = lvl.mass;
energy += P * 2;
let q1 = m * lvl.data.cs * 40;
let q2 = m * lvl.data.lf * 1000;
let q3 = m * lvl.data.cl * (lvl.data.tv - lvl.data.tf);
let q4 = m * lvl.data.lv * 1000;
if (energy < q1) temp = (lvl.data.tf - 40) + energy/(m * lvl.data.cs);
else if (energy < q1+q2) temp = lvl.data.tf;
else if (energy < q1+q2+q3) temp = lvl.data.tf + (energy-q1-q2)/(m * lvl.data.cl);
else if (energy < q1+q2+q3+q4) temp = lvl.data.tv;
else temp = lvl.data.tv + (energy-q1-q2-q3-q4)/(m * lvl.data.cg);
if(temp > lvl.data.tv + 40) isRunning = false;
document.getElementById('tempDisp').innerText = temp.toFixed(1) + " °C";
points.push({e: energy, t: temp});
}
function draw() {
const lvl = levels[currentLvl];
bCtx.clearRect(0,0,bC.width,bC.height);
bCtx.strokeStyle = "#333"; bCtx.lineWidth = 3;
bCtx.strokeRect(30, 30, 100, 280);
bCtx.fillStyle = lvl.color + "44";
let fillH = (temp < lvl.data.tf) ? 60 : (temp < lvl.data.tv) ? 140 : 40;
bCtx.fillRect(33, 310-fillH, 94, fillH);
gCtx.clearRect(0,0,gC.width,gC.height);
gCtx.strokeStyle = "#bbb"; gCtx.lineWidth = 1;
gCtx.beginPath();
gCtx.moveTo(50, 20); gCtx.lineTo(50, 310); gCtx.lineTo(430, 310); gCtx.stroke();
gCtx.fillStyle = "#333"; gCtx.font = "bold 11px Arial";
let y_tf = 310 - ((lvl.data.tf - (lvl.data.tf-40))/130) * 260;
let y_tv = 310 - ((lvl.data.tv - (lvl.data.tf-40))/130) * 260;
gCtx.fillText(lvl.data.tf + "°", 10, y_tf);
gCtx.fillText(lvl.data.tv + "°", 10, y_tv);
if(points.length > 1) {
gCtx.beginPath(); gCtx.strokeStyle = lvl.color; gCtx.lineWidth = 3;
let total_e = (m * lvl.data.cs * 40) + (m * lvl.data.lf * 1000) + (m * lvl.data.cl * (lvl.data.tv-lvl.data.tf)) + (m * lvl.data.lv * 1000) + (m * lvl.data.cg * 40);
points.forEach((p, i) => {
let x = 50 + (p.e / total_e) * 360;
let y = 310 - ((p.t - (lvl.data.tf-40))/130) * 260;
if(i===0) gCtx.moveTo(x,y); else gCtx.lineTo(x,y);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initLevel(); loop();
})();
</script>
<div id="thermo-challenge-adventure" style="width: 100%; max-width: 1280px; background: #ffffff; border: 2px solid #222; border-radius: 20px; overflow: hidden; font-family: 'Segoe UI', sans-serif; margin: auto; box-sizing: border-box; display: flex; flex-direction: column;">
<div id="level-header" style="background: #1565c0; color: white; padding: 20px; display: flex; justify-content: space-between; align-items: center;">
<div>
<h2 style="margin:0; text-transform: uppercase;">Niveau <span id="current-lvl-num">1</span> : <span id="lvl-title">L'Eau (H₂O)</span></h2>
<p style="margin:5px 0 0 0; opacity: 0.9;">Objectif : Répondre aux 4 questions pour débloquer la suite.</p>
</div>
<div id="badge-container" style="background: rgba(255,255,255,0.2); padding: 10px 20px; border-radius: 50px; font-weight: bold;">
ÉTAPE : <span id="step-name">INITIATION</span>
</div>
</div>
<div style="display: flex; flex-wrap: wrap; gap: 0;">
<div style="flex: 1.2; min-width: 450px; padding: 25px; background: #f8f9fa; border-right: 1px solid #ddd;">
<div style="display: flex; gap: 15px; margin-bottom: 20px;">
<canvas id="beakerCanvas" width="200" height="280" style="background: white; border-radius: 10px; border: 1px solid #ccc;"></canvas>
<div style="flex: 1;">
<canvas id="graphCanvas" width="350" height="280" style="background: white; border-radius: 10px; border: 1px solid #ccc; width: 100%;"></canvas>
<p style="font-size: 0.8em; color: #666; text-align: center; margin-top: 5px;"><i>Astuce : Lisez les températures de palier sur l'axe vertical.</i></p>
</div>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
<div id="dataPanel" style="background: white; border: 2px solid #1565c0; border-radius: 12px; padding: 15px;">
<h4 style="margin:0 0 10px 0; color: #1565c0; text-align: center;">Propriétés Physiques</h4>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px; font-size: 0.85em;">
<div>c<sub>s</sub>: <b id="val_cs">-</b></div>
<div>c<sub>l</sub>: <b id="val_cl">-</b></div>
<div>c<sub>g</sub>: <b id="val_cg">-</b></div>
<div>L<sub>f</sub>: <b id="val_lf">-</b> kJ/kg</div>
<div>L<sub>v</sub>: <b id="val_lv">-</b> kJ/kg</div>
<div>Puis.: <b>2000 W</b></div>
</div>
</div>
<div style="display: flex; flex-direction: column; gap: 10px; justify-content: center;">
<div style="text-align: center; font-size: 0.9em;">Masse fixée : <b id="fixed-mass">1.0</b> kg</div>
<button id="mainBtn" onclick="handleBtn()" style="padding: 15px; background: #1565c0; color: white; border: none; border-radius: 8px; font-weight: bold; cursor: pointer; transition: 0.3s;">LANCER L'EXPÉRIENCE</button>
<div id="tempDisp" style="font-size: 2em; font-weight: bold; text-align: center; color: #1565c0;">-- °C</div>
</div>
</div>
</div>
<div id="quiz-zone" style="flex: 1; min-width: 350px; padding: 25px; background: white;">
<div id="quiz-content">
</div>
<button onclick="checkAnswers()" id="validateBtn" style="width: 100%; padding: 18px; margin-top: 20px; background: #222; color: #ffca28; border: none; border-radius: 8px; font-weight: bold; cursor: pointer; font-size: 1.1em;">VÉRIFIER MES RÉPONSES</button>
<div id="feedback" style="margin-top: 15px; padding: 15px; border-radius: 8px; text-align: center; font-weight: bold; display: none;"></div>
<button onclick="nextLevel()" id="nextLvlBtn" style="width: 100%; padding: 18px; margin-top: 10px; background: #2e7d32; color: white; border: none; border-radius: 8px; font-weight: bold; cursor: pointer; display: none;">PASSER AU NIVEAU SUIVANT ➔</button>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerCanvas'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphCanvas'), gCtx = gC.getContext('2d');
const levels = [
{
name: "Eau (H₂O)", mass: 1.0, color: "#1565c0",
data: { cs:2090, cl:4185, cg:2010, lf:334, lv:2260, tf:0, tv:100 },
questions: [
{ q: "1. Quelle est cette substance d'après ses paliers (0°C et 100°C) ?", options: ["Eau", "Ammoniac", "Éthanol"], correct: "Eau" },
{ q: "2. Que signifie le terme 'Qf' dans le calcul ?", options: ["Chaleur de Fusion", "Quantité de Froid", "Quotient de Force"], correct: "Chaleur de Fusion" },
{ q: "3. Calcul : Énergie pour vaporiser 1kg (Qv = m × Lv) ?", options: ["2260 kJ", "334 kJ", "4185 J"], correct: "2260 kJ" },
{ q: "4. Pourquoi la température n'augmente pas pendant un palier ?", options: ["L'énergie sert à briser les liaisons", "Le thermomètre est cassé", "La puissance s'arrête"], correct: "L'énergie sert à briser les liaisons" }
]
},
{
name: "Ammoniac (NH₃)", mass: 0.5, color: "#fbc02d",
data: { cs:2100, cl:4700, cg:2100, lf:331, lv:1371, tf:-77.7, tv:-33.3 },
questions: [
{ q: "1. À quelle température l'ammoniac devient-il liquide (Tf) ?", options: ["0°C", "-77.7°C", "-33.3°C"], correct: "-77.7°C" },
{ q: "2. La chaleur latente Lv est-elle plus petite que pour l'eau ?", options: ["Oui (1371 < 2260)", "Non", "C'est la même"], correct: "Oui (1371 < 2260)" },
{ q: "3. Calcul : Énergie pour vaporiser 0.5kg (0.5 × 1371) ?", options: ["685.5 kJ", "1371 kJ", "2742 kJ"], correct: "685.5 kJ" },
{ q: "4. Le palier de vaporisation est-il plus court que celui de l'eau ?", options: ["Oui", "Non", "Identique"], correct: "Oui" }
]
},
{
name: "Isobutane (C₄H₁₀)", mass: 0.8, color: "#e65100",
data: { cs:1600, cl:2350, cg:1650, lf:78, lv:366, tf:-159.6, tv:-11.7 },
questions: [
{ q: "1. Cette substance est-elle gazeuse à 0°C ?", options: ["Oui (Tv = -11.7°C)", "Non", "Seulement si on chauffe"], correct: "Oui (Tv = -11.7°C)" },
{ q: "2. Sa chaleur de fusion est-elle très faible ?", options: ["Oui (78 kJ/kg)", "Non (780 kJ/kg)", "Élevée"], correct: "Oui (78 kJ/kg)" },
{ q: "3. Calcul : Énergie de fusion pour 0.8kg (0.8 × 78) ?", options: ["62.4 kJ", "78 kJ", "156 kJ"], correct: "62.4 kJ" },
{ q: "4. Comment est la pente du liquide (cl=2350) comparée à l'eau ?", options: ["Plus raide (chauffe plus vite)", "Moins raide", "Identique"], correct: "Plus raide (chauffe plus vite)" }
]
}
];
let currentLvl = 0;
let points = [], energy = 0, temp = -180, isRunning = false;
const P = 2000;
function initLevel() {
const lvl = levels[currentLvl];
document.getElementById('current-lvl-num').innerText = currentLvl + 1;
document.getElementById('lvl-title').innerText = currentLvl === 0 ? "Substance Mystère 1" : "Niveau " + (currentLvl+1);
document.getElementById('level-header').style.background = lvl.color;
document.getElementById('dataPanel').style.borderColor = lvl.color;
document.getElementById('fixed-mass').innerText = lvl.mass;
// Données du tableau
document.getElementById('val_cs').innerText = lvl.data.cs;
document.getElementById('val_cl').innerText = lvl.data.cl;
document.getElementById('val_cg').innerText = lvl.data.cg;
document.getElementById('val_lf').innerText = lvl.data.lf;
document.getElementById('val_lv').innerText = lvl.data.lv;
// Reset Sim
temp = lvl.data.tf - 50; energy = 0; points = []; isRunning = false;
document.getElementById('mainBtn').innerText = "LANCER L'EXPÉRIENCE";
document.getElementById('mainBtn').style.background = lvl.color;
// Reset Quiz
const qContainer = document.getElementById('quiz-content');
qContainer.innerHTML = lvl.questions.map((q, i) => `
<div style="margin-bottom: 15px; border-bottom: 1px solid #eee; padding-bottom: 10px;">
<p style="font-weight: bold; font-size: 0.95em; margin-bottom: 8px;">${q.q}</p>
${q.options.map(opt => `
<label style="display: block; margin-bottom: 4px; font-size: 0.9em; cursor: pointer;">
<input type="radio" name="q${i}" value="${opt}"> ${opt}
</label>
`).join('')}
</div>
`).join('');
document.getElementById('feedback').style.display = 'none';
document.getElementById('nextLvlBtn').style.display = 'none';
document.getElementById('validateBtn').style.display = 'block';
}
window.handleBtn = function() {
if(isRunning) return;
isRunning = true;
document.getElementById('mainBtn').innerText = "CHAUFFAGE EN COURS...";
};
window.checkAnswers = function() {
const lvl = levels[currentLvl];
let score = 0;
lvl.questions.forEach((q, i) => {
const selected = document.querySelector(`input[name="q${i}"]:checked`);
if(selected && selected.value === q.correct) score++;
});
const fb = document.getElementById('feedback');
fb.style.display = 'block';
if(score === lvl.questions.length) {
fb.innerText = "PARFAIT ! Vous avez compris les propriétés de cette substance.";
fb.style.background = "#c8e6c9"; fb.style.color = "#2e7d32";
document.getElementById('validateBtn').style.display = 'none';
document.getElementById('nextLvlBtn').style.display = 'block';
document.getElementById('lvl-title').innerText = lvl.name; // On révèle le nom
} else {
fb.innerText = "Il y a des erreurs (" + score + "/" + lvl.questions.length + "). Observez bien les paliers sur le graph.";
fb.style.background = "#ffcdd2"; fb.style.color = "#c62828";
}
};
window.nextLevel = function() {
currentLvl++;
if(currentLvl >= levels.length) {
alert("Félicitations ! Vous avez terminé tous les défis thermodynamiques !");
currentLvl = 0;
}
initLevel();
};
function update() {
if(!isRunning) return;
const lvl = levels[currentLvl];
const m = lvl.mass;
const dt = 1.5; // Vitesse sim
energy += P * dt;
let q1 = m * lvl.data.cs * (lvl.data.tf - (lvl.data.tf - 50));
let q2 = m * lvl.data.lf * 1000;
let q3 = m * lvl.data.cl * (lvl.data.tv - lvl.data.tf);
let q4 = m * lvl.data.lv * 1000;
if (energy < q1) temp = (lvl.data.tf - 50) + energy/(m * lvl.data.cs);
else if (energy < q1+q2) temp = lvl.data.tf;
else if (energy < q1+q2+q3) temp = lvl.data.tf + (energy-q1-q2)/(m * lvl.data.cl);
else if (energy < q1+q2+q3+q4) temp = lvl.data.tv;
else temp = lvl.data.tv + (energy-q1-q2-q3-q4)/(m * lvl.data.cg);
if(temp > lvl.data.tv + 50) isRunning = false;
document.getElementById('tempDisp').innerText = temp.toFixed(1) + " °C";
points.push({e: energy, t: temp});
}
function draw() {
const lvl = levels[currentLvl];
bCtx.clearRect(0,0,bC.width,bC.height);
// Beaker
bCtx.strokeStyle = "#333"; bCtx.lineWidth = 4;
bCtx.strokeRect(40, 40, 120, 200);
bCtx.fillStyle = lvl.color + "44";
let h = (temp < lvl.data.tf) ? 40 : (temp < lvl.data.tv) ? 100 : 20;
bCtx.fillRect(44, 240-h, 112, h);
gCtx.clearRect(0,0,gC.width,gC.height);
// Axes
gCtx.strokeStyle = "#999"; gCtx.beginPath();
gCtx.moveTo(40, 20); gCtx.lineTo(40, 260); gCtx.lineTo(330, 260); gCtx.stroke();
// Paliers Text
gCtx.fillStyle = "#666"; gCtx.font = "10px Arial";
let y_tf = 260 - ((lvl.data.tf - (lvl.data.tf-50))/150) * 200;
let y_tv = 260 - ((lvl.data.tv - (lvl.data.tf-50))/150) * 200;
gCtx.fillText(lvl.data.tf + "°C", 5, y_tf);
gCtx.fillText(lvl.data.tv + "°C", 5, y_tv);
if(points.length > 1) {
gCtx.beginPath(); gCtx.strokeStyle = lvl.color; gCtx.lineWidth = 3;
let max_e = (m * lvl.data.cs * 50) + (m * lvl.data.lf * 1000) + (m * lvl.data.cl * (lvl.data.tv-lvl.data.tf)) + (m * lvl.data.lv * 1000) + (m * lvl.data.cg * 50);
points.forEach((p, i) => {
let x = 40 + (p.e / max_e) * 280;
let y = 260 - ((p.t - (lvl.data.tf-50))/150) * 200;
if(i===0) gCtx.moveTo(x,y); else gCtx.lineTo(x,y);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initLevel(); loop();
})();
</script>
<div id="sim-thermo-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px;">
<div style="display: flex; gap: 10px; align-items: center;">
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b;">
<option value="eau">Eau (H₂O)</option>
<option value="ammoniac">Ammoniac (NH₃)</option>
<option value="isobutane">Isobutane (C₄H₁₀)</option>
<option value="difluoro">Difluorométhane (R-32)</option>
</select>
<button id="btnMystere" onclick="toggleMystere()" style="padding: 10px 15px; background: #673ab7; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">🕵️ MODE MYSTÈRE : OFF</button>
</div>
<div style="display: flex; align-items: center; gap: 20px;">
<div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-50.0 °C</div>
</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #555; border-right: 6px solid #555; border-bottom: 6px solid #555; background: #fff; border-radius: 0 0 15px 15px;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; margin-left: -5px;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div>
<div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div>
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-top: 15px;">FORMULE APPLIQUÉE</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px;">Q = m · cₛ · ΔT</div>
</div>
<div id="specs-box" style="width: 100%; margin-top: 15px; background: #f9f9f9; padding: 15px; border-radius: 10px; border: 1px dashed #ccc; font-size: 0.85em;">
<b>Données :</b> m = 1kg | P = 4500W<br>
<span id="data-list">cₛ = 2090 J/kgK | Lf = 334 kJ/kg</span>
</div>
</div>
<div style="flex: 2; min-width: 450px;">
<canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 15px; margin-top: 25px;">
<button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button>
<button onclick="location.reload()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
<div id="mystery-hint" style="display:none; margin-top: 15px; padding: 15px; background: #fff9c4; border-left: 5px solid #fbc02d; border-radius: 5px;">
<b>🕵️ DÉFI :</b> Identifiez la substance en observant les températures de paliers (lignes horizontales) et les pentes !
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const db = {
eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, t0: -50, tEnd: 150, color: "#1565c0", maxQ: 3500000 },
ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, t0: -100, tEnd: 50, color: "#689f38", maxQ: 2500000 },
isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, t0: -180, tEnd: 100, color: "#e65100", maxQ: 1500000 },
difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, t0: -160, tEnd: 80, color: "#00796b", maxQ: 1200000 }
};
let s, temp, energy, isRunning = false, pts = [], isMystere = false;
const pwr = 4500, masse = 1;
window.initSubstance = function() {
const val = document.getElementById('selectFluide').value;
s = db[val];
temp = s.t0; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION";
document.getElementById('btnPlay').style.background = "#2e7d32";
updateUI();
};
window.toggleMystere = function() {
isMystere = !isMystere;
document.getElementById('btnMystere').innerText = isMystere ? "🕵️ MODE MYSTÈRE : ON" : "🕵️ MODE MYSTÈRE : OFF";
document.getElementById('btnMystere').style.background = isMystere ? "#f44336" : "#673ab7";
document.getElementById('mystery-hint').style.display = isMystere ? "block" : "none";
document.getElementById('specs-box').style.visibility = isMystere ? "hidden" : "visible";
updateUI();
};
window.toggleSim = function() {
if(temp >= s.tEnd) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = isMystere ? "SUBSTANCE MYSTÈRE" : s.nom;
document.getElementById('data-list').innerHTML = `cs = ${s.cs} J/kgK | Lf = ${s.lf/1000} kJ/kg | cl = ${s.cl} J/kgK | Lv = ${s.lv/1000} kJ/kg`;
}
function update() {
if(!isRunning) return;
if(temp >= s.tEnd) { isRunning = false; return; }
energy += pwr * 2.0;
let q1 = masse * s.cs * (s.tf - s.t0);
let q2 = masse * s.lf;
let q3 = masse * s.cl * (s.tv - s.tf);
let q4 = masse * s.lv;
if(energy < q1) {
temp = s.t0 + energy/(masse*s.cs);
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT";
} else if(energy < q1+q2) {
temp = s.tf;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
document.getElementById('formule-text').innerHTML = "Q = m · Lf";
} else if(energy < q1+q2+q3) {
temp = s.tf + (energy-q1-q2)/(masse*s.cl);
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT";
} else if(energy < q1+q2+q3+q4) {
temp = s.tv;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
document.getElementById('formule-text').innerHTML = "Q = m · Lv";
} else {
temp = s.tv + (energy-q1-q2-q3-q4)/(masse*s.cg);
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT";
}
pts.push({x: energy, y: temp});
updateUI();
}
function draw() {
bCtx.clearRect(0,0,220,300);
// Dessin du fluide
let h = 140;
if(temp < s.tf) bCtx.fillStyle = "#e3f2fd";
else if(temp < s.tv) bCtx.fillStyle = s.color;
else bCtx.fillStyle = "rgba(100,100,100,0.3)";
bCtx.fillRect(10, 300-h, 200, h);
gCtx.clearRect(0,0,600,450);
// Axes
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke(); // Y
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke(); // X
// Tracé courbe
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let px = 60 + (p.x / s.maxQ) * 500;
let py = 400 - ((p.y - s.t0) / (s.tEnd - s.t0)) * 340;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;">
<div style="display: flex; gap: 10px; align-items: center;">
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;">
</select>
<button id="btnMystere" onclick="toggleMystere()" style="padding: 10px 15px; background: #673ab7; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold; transition: 0.3s;">🕵️ MODE MYSTÈRE : OFF</button>
</div>
<div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-50.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #555; border-right: 6px solid #555; border-bottom: 6px solid #555; background: #fff; border-radius: 0 0 15px 15px;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; margin-left: -5px;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center; min-height: 1.2em;">EAU (H₂O)</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div>
<div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div>
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-top: 15px;">FORMULE APPLIQUÉE</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px;">Q = m · cₛ · ΔT</div>
</div>
<div id="specs-box" style="width: 100%; margin-top: 15px; background: #f9f9f9; padding: 15px; border-radius: 10px; border: 1px dashed #ccc; font-size: 0.85em;">
<b>Données techniques :</b><br>
<span id="data-list">m = 1kg | P = 4500W | Lf = 334 kJ/kg</span>
</div>
</div>
<div style="flex: 2; min-width: 450px;">
<canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 15px; margin-top: 25px;">
<button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER</button>
<button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
<div id="mystery-hint" style="display:none; margin-top: 15px; padding: 15px; background: #fff9c4; border-left: 5px solid #fbc02d; border-radius: 5px; font-size: 0.9em;">
<b>🕵️ MISSION ENQUÊTE :</b> Observez les températures de paliers (lignes horizontales) et calculez l'énergie consommée pour identifier la substance.
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const select = document.getElementById('selectFluide');
const db = {
eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, t0: -50, tEnd: 150, color: "#1565c0", maxQ: 3500000, alias: "Substance A" },
ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, t0: -100, tEnd: 50, color: "#689f38", maxQ: 2500000, alias: "Substance B" },
isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, t0: -180, tEnd: 100, color: "#e65100", maxQ: 1500000, alias: "Substance C" },
difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, t0: -160, tEnd: 80, color: "#00796b", maxQ: 1200000, alias: "Substance D" }
};
let s, temp, energy, isRunning = false, pts = [], isMystere = false;
const pwr = 4500, masse = 1;
function populateSelect() {
const currentVal = select.value || "eau";
select.innerHTML = "";
Object.keys(db).forEach(key => {
const opt = document.createElement('option');
opt.value = key;
opt.innerText = isMystere ? db[key].alias : db[key].nom;
if(key === currentVal) opt.selected = true;
select.appendChild(opt);
});
}
window.initSubstance = function() {
s = db[select.value];
temp = s.t0; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER";
document.getElementById('btnPlay').style.background = "#2e7d32";
updateUI();
};
window.toggleMystere = function() {
isMystere = !isMystere;
populateSelect();
document.getElementById('btnMystere').innerText = isMystere ? "🕵️ MODE MYSTÈRE : ON" : "🕵️ MODE MYSTÈRE : OFF";
document.getElementById('btnMystere').style.background = isMystere ? "#f44336" : "#673ab7";
document.getElementById('mystery-hint').style.display = isMystere ? "block" : "none";
document.getElementById('specs-box').style.visibility = isMystere ? "hidden" : "visible";
updateUI();
};
window.resetSim = function() {
initSubstance();
};
window.toggleSim = function() {
if(temp >= s.tEnd) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = isMystere ? "SUBSTANCE MYSTÈRE" : s.nom;
document.getElementById('data-list').innerHTML = `m = 1kg | P = 4500W | Lf = ${s.lf/1000} kJ/kg | cl = ${s.cl} J/kgK`;
}
function update() {
if(!isRunning) return;
if(temp >= s.tEnd) { isRunning = false; return; }
energy += pwr * 1.8;
let q1 = masse * s.cs * (s.tf - s.t0);
let q2 = masse * s.lf;
let q3 = masse * s.cl * (s.tv - s.tf);
let q4 = masse * s.lv;
if(energy < q1) {
temp = s.t0 + energy/(masse*s.cs);
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT";
} else if(energy < q1+q2) {
temp = s.tf;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
document.getElementById('formule-text').innerHTML = "Q = m · Lf";
} else if(energy < q1+q2+q3) {
temp = s.tf + (energy-q1-q2)/(masse*s.cl);
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT";
} else if(energy < q1+q2+q3+q4) {
temp = s.tv;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
document.getElementById('formule-text').innerHTML = "Q = m · Lv";
} else {
temp = s.tv + (energy-q1-q2-q3-q4)/(masse*s.cg);
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT";
}
pts.push({x: energy, y: temp});
updateUI();
}
function draw() {
bCtx.clearRect(0,0,220,300);
let h = 140;
if(temp < s.tf) bCtx.fillStyle = "#e3f2fd";
else if(temp < s.tv) bCtx.fillStyle = s.color;
else bCtx.fillStyle = "rgba(200,200,200,0.5)";
bCtx.fillRect(10, 300-h, 200, h);
gCtx.clearRect(0,0,600,450);
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke();
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke();
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let px = 60 + (p.x / s.maxQ) * 500;
let py = 400 - ((p.y - s.t0) / (s.tEnd - s.t0)) * 340;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
populateSelect();
initSubstance();
loop();
})();
</script>
<div id="sim-thermo-fixed" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;">
<div style="display: flex; gap: 10px; align-items: center;">
<label style="font-weight: bold; color: #555;">Substance :</label>
<select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;">
<option value="eau">Eau (H₂O)</option>
<option value="ammoniac">Ammoniac (NH₃)</option>
<option value="isobutane">Isobutane (C₄H₁₀)</option>
<option value="difluoro">Difluorométhane (R-32)</option>
</select>
</div>
<div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-150.0 °C</div>
</div>
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;">
<div style="position: relative; width: 220px; height: 320px;">
<canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #555; border-right: 6px solid #555; border-bottom: 6px solid #555; background: #fff; border-radius: 0 0 15px 15px;"></canvas>
<div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; margin-left: -5px;">PLAQUE CHAUFFANTE (4500W)</div>
</div>
<div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div>
<div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div>
<div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;">
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div>
<div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div>
<div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-top: 15px;">FORMULE APPLIQUÉE</div>
<div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px;">Q = m · cₛ · ΔT</div>
</div>
<div id="specs-box" style="width: 100%; margin-top: 15px; background: #f9f9f9; padding: 15px; border-radius: 10px; border: 1px dashed #ccc; font-size: 0.85em;">
<b>Propriétés :</b> m = 1kg | P = 4500W<br>
<span id="data-list"></span>
</div>
</div>
<div style="flex: 2; min-width: 450px;">
<canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas>
<div style="display: flex; gap: 15px; margin-top: 25px;">
<button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button>
<button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button>
</div>
<div style="margin-top: 15px; font-size: 0.9em; color: #666; font-style: italic;">
Note : La simulation couvre la plage de -150°C à +150°C pour toutes les substances.
</div>
</div>
</div>
</div>
<script>
(function() {
const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d');
const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d');
const select = document.getElementById('selectFluide');
const db = {
eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, color: "#1565c0", maxQ: 4200000 },
ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, color: "#689f38", maxQ: 3200000 },
isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, color: "#e65100", maxQ: 1800000 },
difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, color: "#00796b", maxQ: 1500000 }
};
let s, temp, energy, isRunning = false, pts = [];
const pwr = 4500, masse = 1, tStart = -150, tEnd = 150;
window.initSubstance = function() {
s = db[select.value];
temp = tStart; energy = 0; pts = []; isRunning = false;
document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION";
document.getElementById('btnPlay').style.background = "#2e7d32";
updateUI();
};
window.resetSim = function() {
initSubstance();
};
window.toggleSim = function() {
if(temp >= tEnd) return;
isRunning = !isRunning;
document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE";
document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32";
};
function updateUI() {
document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C";
document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J";
document.getElementById('nom-substance').innerText = s.nom;
document.getElementById('data-list').innerHTML = `cs = ${s.cs} J/kgK | Lf = ${s.lf/1000} kJ/kg | cl = ${s.cl} J/kgK | Lv = ${s.lv/1000} kJ/kg`;
}
function update() {
if(!isRunning) return;
if(temp >= tEnd) { isRunning = false; return; }
energy += pwr * 2.0;
// Calcul des paliers d'énergie
// 1. Solide de tStart à tf (si tStart < tf)
let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0;
// 2. Fusion
let q2 = (s.tf > tStart) ? masse * s.lf : 0;
// 3. Liquide de tf à tv
let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf));
// 4. Vaporisation
let q4 = masse * s.lv;
if (energy < q1) {
temp = tStart + energy/(masse*s.cs);
document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT";
} else if (energy < q1 + q2) {
temp = s.tf;
document.getElementById('etat-text').innerText = "ÉTAT : FUSION";
document.getElementById('formule-text').innerHTML = "Q = m · Lf";
} else if (energy < q1 + q2 + q3) {
temp = Math.max(tStart, s.tf) + (energy - q1 - q2)/(masse*s.cl);
document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE";
document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT";
} else if (energy < q1 + q2 + q3 + q4) {
temp = s.tv;
document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION";
document.getElementById('formule-text').innerHTML = "Q = m · Lv";
} else {
temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg);
document.getElementById('etat-text').innerText = "ÉTAT : GAZ";
document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT";
}
if(temp > tEnd) temp = tEnd;
pts.push({x: energy, y: temp});
updateUI();
}
function draw() {
bCtx.clearRect(0,0,220,300);
let h = 140;
if(temp < s.tf) bCtx.fillStyle = "#e3f2fd";
else if(temp < s.tv) bCtx.fillStyle = s.color;
else bCtx.fillStyle = "rgba(150,150,150,0.4)";
bCtx.fillRect(10, 300-h, 200, h);
gCtx.clearRect(0,0,600,450);
gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2;
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke(); // Y
gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke(); // X
// Graduation Y
gCtx.fillStyle = "#666"; gCtx.font = "10px Arial";
for(let t = -150; t <= 150; t += 50) {
let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340;
gCtx.fillText(t + "°", 30, y + 5);
gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke();
}
if(pts.length > 0) {
gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4;
pts.forEach((p, i) => {
let px = 60 + (p.x / s.maxQ) * 500;
let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340;
if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py);
});
gCtx.stroke();
}
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
initSubstance();
loop();
})();
</script>
PPCL TABLEAU
geogebra TABLEAU
https://www.pccl.fr/physique_chimie_college_lycee/lycee/seconde/tableau_avancement_reactif_limitant_proportions_stoechiometriques_exces_bilan_matiere_flash.htm
https://www.geogebra.org/m/fjxrxuuu
https://gayrard.netboard.me/mod6lisationdun/?tab=85756
https://physique-chimie.ac-normandie.fr/IMG/tableau_avancement/TA.htm
https://physique-chimie.ac-normandie.fr/spip.php?article188
https://laboiteaphysique.fr/site2/files/unites/co/module_Unites%20et%20puissances%20de%20dix_2.html
https://view.genially.com/60cba2a3df0d240ddc7ea29e/interactive-content-tableau-davancement
https://laboiteaphysique.fr/site2/index.php/les-fondamentaux#jl_magic_tabs_equilibrer_une_equation_chimique_gix5
https://qcm-sciencesphysiques.blogspot.com/p/1ere-s-qcm-7.html
minimal
Contextualize your topic
https://profed.fr/pro-ani.php?file=uploads_animations%2F1763910197_Eude+avancement+transformation+totale%281%29.swf
QUIZ
minimal
Contextualize your topic
https://www.quizz.biz/quizz-917291.html#google_vignette
https://profed.fr/pro-ani.php?file=uploads_animations%2F1763910197_Eude+avancement+transformation+totale%281%29.swf
https://chimie.ostralo.net/avancement/
QUIZ
minimal
Contextualize your topic
Contextualize your topic
https://www.ostralo.net/equationschimiques/pages/p2b.htm
https://profed.fr/pro-ani.php?file=uploads_animations%2F1763910197_Eude+avancement+transformation+totale%281%29.swf
EQUATION BILAN
https://qcm-sciencesphysiques.blogspot.com/p/1ere-s-qcm-7.html
https://www.ostralo.net/equationschimiques/pages/p2b.htm
EQUATION BILAN
https://profed.fr/pro-ani.php?file=uploads_animations%2F1763910197_Eude+avancement+transformation+totale%281%29.swf
ACTIVITE BTS CHAP 2 CHALEUR
COLLEGE SOUTINE
Created on August 9, 2025
Start designing with a free template
Discover more than 1500 professional designs like these:
View
Essential Business Proposal
View
Project Roadmap Timeline
View
Step-by-Step Timeline: How to Develop an Idea
View
Artificial Intelligence History Timeline
View
Mobile Phone Call
View
Momentum: Onboarding Escape Game
View
Momentum: Manager Guide
Explore all templates
Transcript
PHYSIQUE BTS FED
ACTIVITÉ CALCULS DE CHALEUR
ENTRER
ACTIVITÉ CALCULS DE CHALEUR
Quel est ton prénom ?
suivant
§classe§: *2
C'est parti !
Quelle est ta classe ?
§nom§: *3
* ATTENTION : ce prénom sera écrit sur ton diplôme à la fin
1. LE RÉCHAUFFEMENT
?$CAL1|=|1
?$CALEX1|=|1&CALEX2|=|1&CALEX3|=|1&CALEX4|=|1&CAL1|=|1&CAL2|=|1&CAL3|=|1
Bravo
CLIQUER POUR VOIR LE DIPLÔME
2. LE CHANGEMENT D'ÉTAT
?$CAL2|=|1
3. MESURES de la CHALEUR TOTALE
?$CAL3|=|1
4. EXERCICES
?$CALEX1|=|1&CALEX2|=|1&CALEX3|=|1&CALEX4|=|1
FORMULES
$CAL1|=|1
Elle dépend de :
$CAL2|=|1
<div id="universal-sim-v29-data" style="width: 100%; max-width: 1265px; background: #ffffff; border: 1px solid #ccc; border-radius: 18px; padding: 30px; font-family: 'Segoe UI', sans-serif; color: #333; margin: auto; box-sizing: border-box;"> <div style="display: flex; flex-wrap: wrap; gap: 30px; justify-content: center;"> <div style="flex: 1.4; min-width: 450px; text-align: center; display: flex; flex-direction: column; gap: 20px;"> <canvas id="beakerCanvas" width="460" height="380" style="border: 2px solid #999; background: #fff; border-radius: 12px; width: 100%; height: auto;"></canvas> <canvas id="graphCanvas" width="460" height="350" style="border: 1px solid #ccc; background: #fafafa; border-radius: 10px; width: 100%; height: auto;"></canvas> </div> <div style="flex: 1.6; min-width: 370px; display: flex; flex-direction: column; gap: 15px;"> <div style="display: flex; gap: 10px;"> <select id="substance_select" onchange="initSubstance()" style="flex: 3; padding: 12px; border-radius: 10px; border: 2px solid #333; font-weight: bold; font-size: 1.1em; cursor: pointer;"> <option value="eau" selected>Eau (H₂O)</option> <option value="ammoniac">Ammoniac (NH₃)</option> <option value="isobutane">Isobutane (C₄H₁₀)</option> <option value="r32">R32 (Difluorométhane)</option> <option value="r1234yf">R1234yf (Tétrafluoropropène)</option> </select> <button id="unitBtn" onclick="toggleUnit()" style="flex: 1; padding: 10px; border-radius: 10px; border: 2px solid #333; background: #333; color: white; font-weight: bold; cursor: pointer;">UNITÉ : °C</button> </div> <div id="dataPanel" style="background: #f1f8e9; border: 1px solid #c5e1a5; border-radius: 12px; padding: 12px; font-size: 0.9em;"> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; text-align: center;"> <div><small>c<sub>s</sub></small><br><strong id="val_cs">-</strong> <small>J/kg·K</small></div> <div><small>c<sub>l</sub></small><br><strong id="val_cl">-</strong> <small>J/kg·K</small></div> <div><small>c<sub>g</sub></small><br><strong id="val_cg">-</strong> <small>J/kg·K</small></div> <div style="border-top: 1px solid #c5e1a5; padding-top: 5px;"><small>L<sub>f</sub></small><br><strong id="val_lf">-</strong> <small>kJ/kg</small></div> <div style="border-top: 1px solid #c5e1a5; padding-top: 5px;"><small>L<sub>v</sub></small><br><strong id="val_lv">-</strong> <small>kJ/kg</small></div> <div style="border-top: 1px solid #c5e1a5; padding-top: 5px;"><small>T<sub>f</sub> / T<sub>vap</sub></small><br><strong id="val_temps">-</strong></div> </div> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: #eee; padding: 10px; border-radius: 12px;"> <div style="text-align:center;"> <label style="font-size: 0.8em; font-weight: bold;">T. INITIALE (<span class="unitLabel">°C</span>)</label><br> <input type="number" id="t_start_val" value="-150" min="-273.15" step="10" onchange="checkAbsoluteZero(this)" style="width: 80%; padding: 8px; font-weight: bold; text-align: center; border-radius: 5px; border: 1px solid #999;"> </div> <div style="text-align:center;"> <label style="font-size: 0.8em; font-weight: bold;">T. FINALE (<span class="unitLabel">°C</span>)</label><br> <input type="number" id="t_end_val" value="150" min="-272" step="10" style="width: 80%; padding: 8px; font-weight: bold; text-align: center; border-radius: 5px; border: 1px solid #999;"> </div> </div> <div id="tempDisp" style="font-size: 3.5em; font-weight: bold; text-align: center; border-radius: 15px; padding: 10px; border: 4px solid #ccc; background: #f8f9fa;">0.0 °C</div> <div style="background: #fdfdfd; padding: 15px; border-radius: 15px; border: 1px solid #ddd;"> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 15px;"> <div>Masse : <input type="number" id="m_val" value="1.0" min="0.1" max="50" step="0.5" style="width: 65px; font-weight: bold; padding: 5px;"> <strong>kg</strong></div> <div>Puissance : <input type="number" id="p_val" value="2000" min="500" max="10000" step="500" style="width: 80px; font-weight: bold; padding: 5px;"> <strong>W</strong></div> </div> <div style="display: flex; gap: 15px; align-items: center;"> <select id="speed_select" style="flex:1; padding: 10px; border-radius: 6px; font-weight: bold;"> <option value="4">Lent</option> <option value="15" selected>Normal</option> <option value="100">Rapide</option> </select> <button id="mainBtn" onclick="handleBtn()" style="flex:1.5; padding: 15px; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 1.1em; text-transform: uppercase;">DÉMARRER</button> </div> </div> <div id="formulas" style="font-size: 1.05em; display: flex; flex-direction: column; gap: 8px;"> <div id="f1" style="padding: 10px; border-left: 6px solid #ccc; background: #fff; border-radius: 6px; position: relative;"><span class="step-arrow" style="position: absolute; left: -25px; color: #d32f2f; display: none;">➤</span><strong>1. Chauffage Solide :</strong> Q = m · cₛ · ΔT <span id="d1" style="color:#d32f2f; font-weight:bold; float:right;"></span></div> <div id="f2" style="padding: 10px; border-left: 6px solid #ccc; background: #fff; border-radius: 6px; position: relative;"><span class="step-arrow" style="position: absolute; left: -25px; color: #d32f2f; display: none;">➤</span><strong>2. Fusion :</strong> Q = m · Lբ <span id="d2" style="color:#d32f2f; font-weight:bold; float:right;"></span></div> <div id="f3" style="padding: 10px; border-left: 6px solid #ccc; background: #fff; border-radius: 6px; position: relative;"><span class="step-arrow" style="position: absolute; left: -25px; color: #d32f2f; display: none;">➤</span><strong>3. Chauffage Liquide :</strong> Q = m · cₗ · ΔT <span id="d3" style="color:#d32f2f; font-weight:bold; float:right;"></span></div> <div id="f4" style="padding: 10px; border-left: 6px solid #ccc; background: #fff; border-radius: 6px; position: relative;"><span class="step-arrow" style="position: absolute; left: -25px; color: #d32f2f; display: none;">➤</span><strong>4. Vaporisation :</strong> Q = m · Lᵥ <span id="d4" style="color:#d32f2f; font-weight:bold; float:right;"></span></div> <div id="f5" style="padding: 10px; border-left: 6px solid #ccc; background: #fff; border-radius: 6px; position: relative;"><span class="step-arrow" style="position: absolute; left: -25px; color: #d32f2f; display: none;">➤</span><strong>5. Chauffage Gaz :</strong> Q = m · cₚ · ΔT <span id="d5" style="color:#d32f2f; font-weight:bold; float:right;"></span></div> <div style="padding: 15px; background: #263238; color: #ffca28; border-radius: 12px; text-align: center; border: 2px solid #ffca28;"><strong>TOTAL : <span id="total_q" style="font-size: 1.6em;">0</span> J</strong></div> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerCanvas'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphCanvas'), gCtx = gC.getContext('2d'); const BK = { x: 115, y: 40, w: 230, h: 300, baseH: 70 }; const MARGIN = 18; const data = { eau: { cs:2090, cl:4185, cg:2010, lf:334000, lv:2260000, tf:0, tv:100, color:"#1565c0", bg:"#e3f2fd" }, ammoniac: { cs:2100, cl:4700, cg:2100, lf:331000, lv:1371000, tf:-77.7, tv:-33.3, color:"#fbc02d", bg:"#fff9c4" }, isobutane: { cs:1600, cl:2350, cg:1650, lf:78000, lv:366000, tf:-159.6, tv:-11.7, color:"#e65100", bg:"#fff3e0" }, r32: { cs:1200, cl:1900, cg:1500, lf:110000, lv:380000, tf:-136, tv:-51.7, color:"#6a1b9a", bg:"#f3e5f5" }, r1234yf: { cs:1050, cl:1390, cg:1100, lf:85000, lv:180000, tf:-152.2, tv:-29.5, color:"#455a64", bg:"#eceff1" } }; let sub, m, p, energy=0, isPaused=false, isRunning = false, points=[], mols=[], temp, t_start, t_end, maxE, liquidOpacity = 0; let useKelvin = false; window.checkAbsoluteZero = function(el) { if(parseFloat(el.value) < -273.15) el.value = -273.15; }; window.toggleUnit = function() { useKelvin = !useKelvin; document.getElementById('unitBtn').innerText = useKelvin ? "UNITÉ : K" : "UNITÉ : °C"; document.querySelectorAll('.unitLabel').forEach(l => l.innerText = useKelvin ? "K" : "°C"); updateDisplay(); updateDataPanel(); }; function formatTemp(t) { if(useKelvin) return (t + 273.15).toFixed(1) + (arguments[1] ? "" : " K"); return t.toFixed(1) + (arguments[1] ? "" : " °C"); } window.initSubstance = function() { sub = data[document.getElementById('substance_select').value]; t_start = parseFloat(document.getElementById('t_start_val').value); t_end = parseFloat(document.getElementById('t_end_val').value); temp = t_start; energy = 0; isRunning = false; isPaused = false; points = []; updateDisplay(); updateDataPanel(); document.getElementById('mainBtn').style.backgroundColor = sub.color; document.getElementById('mainBtn').innerText = "DÉMARRER"; document.querySelectorAll('span[id^="d"]').forEach(s => s.innerText = ""); document.querySelectorAll('.step-arrow').forEach(a => a.style.display = 'none'); document.querySelectorAll('#formulas > div').forEach(d => { if(d.id) d.style.background = "#fff"; }); initVisualState(); }; function updateDataPanel() { document.getElementById('val_cs').innerText = sub.cs; document.getElementById('val_cl').innerText = sub.cl; document.getElementById('val_cg').innerText = sub.cg; document.getElementById('val_lf').innerText = (sub.lf/1000).toFixed(0); document.getElementById('val_lv').innerText = (sub.lv/1000).toFixed(0); document.getElementById('val_temps').innerText = formatTemp(sub.tf, true) + " / " + formatTemp(sub.tv, true); } function updateDisplay() { const disp = document.getElementById('tempDisp'); disp.innerText = formatTemp(temp); disp.style.color = sub.color; disp.style.backgroundColor = sub.bg; disp.style.borderColor = sub.color; } function initVisualState() { mols = []; let state = (temp < sub.tf) ? 'solid' : (temp < sub.tv) ? 'liquid' : 'gas'; liquidOpacity = (state === 'solid') ? 0 : (state === 'liquid') ? 1 : 0; for(let i=0; i<45; i++) { mols.push({ ox: BK.x + MARGIN + Math.random()*(BK.w - 2*MARGIN), oy: BK.y + BK.h - BK.baseH + MARGIN + Math.random()*(BK.baseH - 2*MARGIN), vx: (Math.random()-0.5)*4.5, vy: (Math.random()-0.5)*4.5, state: state }); } } window.handleBtn = function() { if(!isRunning || temp >= t_end) { t_start = parseFloat(document.getElementById('t_start_val').value); t_end = parseFloat(document.getElementById('t_end_val').value); m = parseFloat(document.getElementById('m_val').value); p = parseFloat(document.getElementById('p_val').value); if(t_start < -273.15) t_start = -273.15; if(t_start >= t_end) { alert("T. initiale doit être < T. finale !"); return; } let q1 = (t_start < sub.tf) ? m*sub.cs*(Math.min(t_end, sub.tf) - t_start) : 0; let q2 = (t_start <= sub.tf && t_end > sub.tf) ? m*sub.lf : 0; let q3 = (t_end > sub.tf) ? m*sub.cl*(Math.min(t_end, sub.tv) - Math.max(t_start, sub.tf)) : 0; if(q3 < 0) q3 = 0; let q4 = (t_start <= sub.tv && t_end > sub.tv) ? m*sub.lv : 0; let q5 = (t_end > sub.tv) ? m*sub.cg*(t_end - Math.max(t_start, sub.tv)) : 0; maxE = q1 + q2 + q3 + q4 + q5; temp = t_start; energy = 0; points = []; isRunning = true; isPaused = false; document.getElementById('mainBtn').innerText = "PAUSE"; } else { isPaused = !isPaused; document.getElementById('mainBtn').innerText = isPaused ? "REPRENDRE" : "PAUSE"; } }; function update() { if(!isRunning || isPaused || temp >= t_end) return; energy += p * (parseFloat(document.getElementById('speed_select').value) * 0.15); let q1 = (t_start < sub.tf) ? m*sub.cs*(sub.tf - t_start) : 0; let q2 = (t_start <= sub.tf) ? m*sub.lf : 0; let q3 = (t_start < sub.tv) ? m*sub.cl*(sub.tv - Math.max(t_start, sub.tf)) : 0; let q4 = (t_start <= sub.tv) ? m*sub.lv : 0; document.querySelectorAll('#formulas > div').forEach(d => { if(d.id) d.style.background = "#fff"; }); if (t_start < sub.tf && energy < q1) { temp = t_start + energy/(m*sub.cs); setArrow('f1'); document.getElementById('f1').style.background = sub.bg; document.getElementById('d1').innerText = Math.round(energy).toLocaleString() + " J"; } else if (t_start <= sub.tf && energy < q1+q2) { temp = sub.tf; let pr = (energy-q1)/q2; setArrow('f2'); liquidOpacity = pr; mols.forEach((mo, i) => mo.state = (i/mols.length < pr) ? 'liquid' : 'solid'); document.getElementById('f2').style.background = sub.bg; document.getElementById('d2').innerText = Math.round(energy-q1).toLocaleString() + " J"; } else if (energy < q1+q2+q3) { temp = Math.max(t_start, sub.tf) + (energy-q1-q2)/(m*sub.cl); setArrow('f3'); liquidOpacity = 1; mols.forEach(mo => mo.state='liquid'); document.getElementById('f3').style.background = sub.bg; document.getElementById('d3').innerText = Math.round(energy-q1-q2).toLocaleString() + " J"; } else if (t_end > sub.tv && energy < q1+q2+q3+q4) { temp = sub.tv; let prV = (energy-(q1+q2+q3))/q4; setArrow('f4'); liquidOpacity = 1 - prV; mols.forEach((mo, i) => mo.state = (i/mols.length < prV) ? 'gas' : 'liquid'); document.getElementById('f4').style.background = sub.bg; document.getElementById('d4').innerText = Math.round(energy-q1-q2-q3).toLocaleString() + " J"; } else { temp = Math.max(t_start, sub.tv) + (energy-q1-q2-q3-q4)/(m*sub.cg); setArrow('f5'); liquidOpacity = 0; mols.forEach(mo => mo.state = 'gas'); document.getElementById('f5').style.background = sub.bg; document.getElementById('d5').innerText = Math.round(Math.min(energy-(q1+q2+q3+q4), maxE-(q1+q2+q3+q4))).toLocaleString() + " J"; } if (temp >= t_end) { temp = t_end; isRunning = false; document.getElementById('mainBtn').innerText = "REDÉMARRER"; } updateDisplay(); document.getElementById('total_q').innerText = Math.round(Math.min(energy, maxE)).toLocaleString(); points.push({e: energy, t: temp}); } function setArrow(id) { document.querySelectorAll('.step-arrow').forEach(a => a.style.display = 'none'); if(id) document.querySelector('#'+id+' .step-arrow').style.display = 'inline'; } function draw() { bCtx.clearRect(0,0,bC.width,bC.height); const heating = isRunning && !isPaused && temp < t_end; bCtx.fillStyle = heating ? "#d32f2f" : "#1976d2"; bCtx.fillRect(BK.x, BK.y+BK.h, BK.w, 25); bCtx.fillStyle = "#fff"; bCtx.font="bold 20px Arial"; bCtx.fillText("♨", BK.x+BK.w/2-10, BK.y+BK.h+19); if (liquidOpacity > 0 || temp < sub.tf) { bCtx.fillStyle = (temp < sub.tf) ? "rgba(200,200,200,0.3)" : sub.color + "44"; let h = (BK.baseH-5) * (temp < sub.tf ? 1 : liquidOpacity); bCtx.fillRect(BK.x+8, BK.y+BK.h-h, BK.w-16, h); } bCtx.strokeStyle="#333"; bCtx.lineWidth=12; bCtx.strokeRect(BK.x, BK.y, BK.w, BK.h); mols.forEach(mo => { let s = (mo.state==='solid')?0.6 : (mo.state==='liquid')?2.8 : 13; if(mo.state==='solid') { mo.x=mo.ox+(Math.random()-0.5)*2; mo.y=mo.oy+(Math.random()-0.5)*2; } else { mo.ox+=mo.vx*s*0.1; mo.oy+=mo.vy*s*0.1; if(mo.ox<BK.x+MARGIN || mo.ox>BK.x+BK.w-MARGIN) mo.vx*=-1; let top = (mo.state==='liquid')?BK.y+BK.h-(BK.baseH*liquidOpacity)+8 : BK.y+MARGIN; if(mo.oy<top || mo.oy>BK.y+BK.h-MARGIN) mo.vy*=-1; mo.x=mo.ox; mo.y=mo.oy; } bCtx.fillStyle=sub.color; bCtx.beginPath(); bCtx.arc(mo.x, mo.y, 5, 0, Math.PI*2); bCtx.fill(); }); gCtx.clearRect(0,0,gC.width,gC.height); const OX=65, OY=300; gCtx.strokeStyle="#333"; gCtx.lineWidth=2; gCtx.beginPath(); gCtx.moveTo(OX,320); gCtx.lineTo(OX,15); gCtx.lineTo(OX-5,25); gCtx.moveTo(OX,15); gCtx.lineTo(OX+5,25); gCtx.moveTo(40,OY); gCtx.lineTo(445,OY); gCtx.lineTo(435,OY-5); gCtx.moveTo(445,OY); gCtx.lineTo(435,OY+5); gCtx.stroke(); gCtx.fillStyle="#000"; gCtx.fillText(useKelvin ? "T (K)" : "T (°C)", 20, 15); gCtx.fillText("Q (J)", 415, OY+20); [t_start, sub.tf, sub.tv, t_end].filter(v => v >= t_start && v <= t_end).forEach(v => { let y = OY - ((v-t_start)/(t_end-t_start))*260; let val = useKelvin ? Math.round(v + 273.15) : Math.round(v); gCtx.fillText(val, OX-35, y+5); gCtx.beginPath(); gCtx.moveTo(OX-5,y); gCtx.lineTo(OX+5,y); gCtx.stroke(); }); if(points.length > 1) { gCtx.beginPath(); gCtx.strokeStyle=sub.color; gCtx.lineWidth=3.5; points.forEach((p, i) => { let px = OX + (p.e/maxE)*350; let py = OY - ((p.t-t_start)/(t_end-t_start))*260; if(i===0) gCtx.moveTo(px,py); else gCtx.lineTo(px,py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
$CAL3|=|1
<div id="sim-thermo-fixed-final" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd; flex-wrap: wrap; gap: 15px;"> <div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;"> <div> <label style="font-weight: bold; color: #444;">Choix :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #1565c0; cursor: pointer;"> <option value="subA">Substance A</option> <option value="subB">Substance B</option> <option value="subC">Substance C</option> <option value="subD">Substance D</option> <option value="subE">Substance E</option> </select> </div> <div> <label style="font-weight: bold; color: #444;">Masse :</label> <select id="selectMasse" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; cursor: pointer;"> <option value="1">1 kg</option> <option value="2">2 kg</option> <option value="5">5 kg</option> <option value="10">10 kg</option> </select> </div> </div> <div id="temp-grand" style="font-size: 3.2em; font-weight: bold; color: #d32f2f; font-family: monospace; background: #fff; padding: 5px 15px; border-radius: 10px; border: 1px solid #ccc; min-width: 200px; text-align: center;">-200.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.4em; font-weight: bold; color: #1565c0; text-align: center;">-</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.2em; margin-bottom: 10px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-bottom: 8px;">FORMULE APPLIQUÉE</div> <div id="q-val" style="font-size: 1.6em; color: #ffeb3b; margin-bottom: 8px;">0 J</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; border-top: 1px solid #333; padding-top: 8px;">Q = m · cₛ · ΔT</div> </div> </div> <div style="flex: 2; min-width: 450px; display: flex; flex-direction: column;"> <canvas id="graphSim" width="600" height="420" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 10px; margin-top: 20px; justify-content: flex-end;"> <button id="btnPlay" onclick="toggleSim()" style="width: 160px; padding: 15px; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 1.1em; box-shadow: 0 4px #1b5e20;">DÉMARRER</button> <button onclick="resetSim()" style="padding: 15px; background: #546e7a; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const selectF = document.getElementById('selectFluide'), selectM = document.getElementById('selectMasse'); const db = { subA: { label: "Substance A", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114, tv: 78, isCO2: false, colorL: "#e3f2fd", colorS: "#64b5f6" }, subB: { label: "Substance B", cs: 850, cg: 840, ls: 571000, ts: -78.5, isCO2: true, colorS: "#eeeeee" }, subC: { label: "Substance C", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155, tv: -82, isCO2: false, colorL: "#e0f7fa", colorS: "#4dd0e1" }, subD: { label: "Substance D", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -188, tv: -42, isCO2: false, colorL: "#fff3e0", colorS: "#ffb74d" }, subE: { label: "Substance E", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152, tv: -29, isCO2: false, colorL: "#f1f8e9", colorS: "#aed581" } }; let s, temp, energy, masse, isRunning = false, pts = [], blinkFrame = 0; const pwr = 4500, tStart = -200, tEnd = 200; let gasParticles = []; window.initSubstance = function() { s = db[selectF.value]; masse = parseFloat(selectM.value); temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER"; document.getElementById('btnPlay').style.background = "#2e7d32"; gasParticles = []; updateUI(); }; window.toggleSim = function() { if(temp >= tEnd && isRunning) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; window.resetSim = function() { initSubstance(); }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.label + " (" + masse + " kg)"; } function update() { if(!isRunning || temp >= tEnd) { heater.style.background = "#333"; return; } blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 8) % 2 === 0) ? "#d32f2f" : "#333"; energy += pwr * 15; const fText = document.getElementById('formule-text'); const eText = document.getElementById('etat-text'); if (s.isCO2) { let q1 = masse * s.cs * (s.ts - tStart), q2 = masse * s.ls; if (energy < q1) { temp = tStart + energy/(masse*s.cs); eText.innerText = "ÉTAT : SOLIDE"; fText.innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.ts; eText.innerText = "ÉTAT : SUBLIMATION"; fText.innerHTML = "Q = m · Lₛ"; } else { temp = s.ts + (energy - q1 - q2)/(masse*s.cg); eText.innerText = "ÉTAT : GAZ"; fText.innerHTML = "Q = m · cₚ · ΔT"; } } else { let q1 = masse * s.cs * (s.tf - tStart), q2 = masse * s.lf; let q3 = masse * s.cl * (s.tv - s.tf), q4 = masse * s.lv; if (energy < q1) { temp = tStart + energy/(masse*s.cs); eText.innerText = "ÉTAT : SOLIDE"; fText.innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.tf; eText.innerText = "ÉTAT : FUSION"; fText.innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = s.tf + (energy - q1 - q2)/(masse*s.cl); eText.innerText = "ÉTAT : LIQUIDE"; fText.innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = s.tv; eText.innerText = "ÉTAT : ÉBULLITION"; fText.innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg); eText.innerText = "ÉTAT : GAZ"; fText.innerHTML = "Q = m · cₚ · ΔT"; } } pts.push({x: energy, y: temp}); updateUI(); if(gasParticles.length > 0) { let speed = 0.5 + ((temp + 200) * 0.015); gasParticles.forEach(p => { p.x += p.vx * speed; p.y += p.vy * speed; if(p.x < 5 || p.x > 215) p.vx *= -1; if(p.y < 5 || p.y > 295) p.vy *= -1; }); } } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 40 + (masse * 12); if(s.isCO2) { let q1 = masse * s.cs * (s.ts - tStart), q2 = masse * s.ls; if (temp < s.ts) { bCtx.fillStyle = s.colorS; bCtx.fillRect(40, 300-hMax, 140, hMax); } else if (temp === s.ts) { let r = Math.min(1, (energy-q1)/q2); bCtx.fillStyle = s.colorS; bCtx.fillRect(40, 300-(hMax*(1-r)), 140, hMax*(1-r)); if(gasParticles.length < Math.floor(r*70)) gasParticles.push({x: 110, y: 280, vx: Math.random()*2-1, vy: -Math.random()*2, r: 3}); bCtx.fillStyle = "rgba(200,200,200,0.4)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); }); } else { if(gasParticles.length < 70) gasParticles.push({x: 110, y: 150, vx: Math.random()*3-1.5, vy: Math.random()*3-1.5, r: 3}); bCtx.fillStyle = "rgba(180,180,180,0.5)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); }); } } else { let q1 = masse * s.cs * (s.tf - tStart), q2 = masse * s.lf, q3 = masse * s.cl * (s.tv - s.tf); if(temp < s.tf) { bCtx.fillStyle = s.colorS; bCtx.fillRect(40, 300-hMax, 140, hMax); } else if (temp === s.tf) { let r = Math.min(1, (energy-q1)/q2); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*r), 220, hMax*r); bCtx.fillStyle = s.colorS; bCtx.fillRect(40, 300-hMax, 140, hMax*(1-r)); } else if (temp < s.tv) { bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax); } else if (temp === s.tv) { let rV = Math.min(1, (energy-q1-q2-q3)/(masse * 835000)); // Calibrage visuel bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*(1-rV)), 220, hMax*(1-rV)); if(gasParticles.length < 60) gasParticles.push({x: 110, y: 150, vx: Math.random()*4-2, vy: Math.random()*4-2, r: 2.5}); bCtx.fillStyle = "rgba(180,210,255,0.4)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); }); } else { bCtx.fillStyle = "rgba(160,200,255,0.5)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r+1, 0, 7); bCtx.fill(); }); } } gCtx.clearRect(0,0,600,420); gCtx.strokeStyle = "#444"; gCtx.lineWidth = 2; // Axe Y gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(60, 20); gCtx.stroke(); gCtx.beginPath(); gCtx.moveTo(55, 30); gCtx.lineTo(60, 15); gCtx.lineTo(65, 30); gCtx.fill(); gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (°C)", 35, 25); // Axe X gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(580, 390); gCtx.stroke(); gCtx.beginPath(); gCtx.moveTo(575, 385); gCtx.lineTo(590, 390); gCtx.lineTo(575, 395); gCtx.fill(); gCtx.fillText("Q (Joules)", 520, 410); let xMax = masse * 1500000; for(let t=-200; t<=200; t+=50) { let y = 390 - ((t+200)/400)*350; gCtx.fillStyle = "#888"; gCtx.font = "10px Arial"; gCtx.fillText(t, 30, y+4); gCtx.beginPath(); gCtx.moveTo(55,y); gCtx.lineTo(60,y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = "#1565c0"; gCtx.lineWidth = 3; pts.forEach((p, i) => { let px = 60 + (p.x / xMax) * 500; let py = 390 - ((p.y + 200) / 400) * 350; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
substance X
Identifie chaque substance et déplace l'étiquette au bon endroit dans le tableau
exercices
?$F1|=|1&F2|=|1&F3|=|1&F4|=|1
CHALLENGE FINAL
exercice 1
exercice 3
exercice 4
exercice 2
?$CALEX2|=|1
?$CALEX1|=|1
?$CALEX3|=|1
?$CALEX4|=|1
<div id="sim-eau-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;"> <h2 style="margin: 0; color: #1565c0; font-size: 1.4em;">🔬 Analyse Thermique : Eau (H₂O)</h2> <div style="display: flex; align-items: center; gap: 15px;"> <div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;"> <button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #1565c0; color: white;">°C</button> <button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button> </div> <div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-50.0 °C</div> </div> </div> <div style="display: flex; gap: 25px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 200px; height: 302px;"> <canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas> <div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div> </div> <div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #1565c0; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div> <div style="width: 100%; margin-top: 20px; background: #1a237e; color: #e8eaf6; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;"> <div style="color: #9fa8da; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #303f9f;">Énergie Totale Transférée</div> <div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #00e5ff;">0 J</div> <div style="color: #9fa8da; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #303f9f;">Formule en cours</div> <div id="formule-display" style="font-size: 1.1em; color: #ffeb3b; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div> </div> <div id="specs" style="margin-top: 20px; background: #e3f2fd; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #bbdefb; color: #333;"> <div style="display: flex; flex-direction: column; gap: 5px;"> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>2090 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>334 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>4185 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>2260 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>1850 J/(kg·K)</span></div> </div> </div> </div> <div style="flex: 2; min-width: 400px;"> <canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas> <div style="display: flex; gap: 10px; margin-top: 20px;"> <button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button> <button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const etatLabel = document.getElementById('etat-text'); const tempDisp = document.getElementById('temp-grand'); const qTotalDisp = document.getElementById('q-total-display'); const formuleDisp = document.getElementById('formule-display'); // Propriétés Eau const sub = { cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100 }; let temp = -50, energy = 0, isRunning = false, pts = []; let isKelvin = false; const pwr = 4500, masse = 1, maxEnergy = 3500000; let heatStep = 0; window.setUnit = function(k) { isKelvin = k; document.getElementById('btnKel').style.background = k ? '#1565c0' : '#fff'; document.getElementById('btnKel').style.color = k ? '#fff' : '#333'; document.getElementById('btnDeg').style.background = k ? '#fff' : '#1565c0'; document.getElementById('btnDeg').style.color = k ? '#333' : '#fff'; updateDisplay(); }; window.toggleSim = function() { if(temp >= 150) return; isRunning = !isRunning; document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateDisplay() { tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C"; qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J"; } function update() { if(!isRunning) return; if(temp >= 150) { temp = 150.0; isRunning = false; heater.style.background = "#444"; document.getElementById('btnStart').innerText = "TERMINÉ"; document.getElementById('btnStart').style.background = "#999"; return; } heatStep++; heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c"; energy += pwr * 1.5; let q1 = masse * sub.cs * (sub.tf - (-50)); let q2 = masse * sub.lf; let q3 = masse * sub.cl * (sub.tv - sub.tf); let q4 = masse * sub.lv; if (energy < q1) { temp = -50 + energy/(masse*sub.cs); etatLabel.innerText = "SOLIDE"; formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT"; } else if (energy < q1+q2) { temp = sub.tf; etatLabel.innerText = "FUSION"; formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>"; } else if (energy < q1+q2+q3) { temp = sub.tf + (energy-q1-q2)/(masse*sub.cl); etatLabel.innerText = "LIQUIDE"; formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT"; } else if (energy < q1+q2+q3+q4) { temp = sub.tv; etatLabel.innerText = "ÉBULLITION"; formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>"; } else { temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg); if(temp > 150) temp = 150; etatLabel.innerText = "GAZ"; formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT"; } pts.push({x: energy, y: temp}); updateDisplay(); } function drawArrows(ctx, x, y, angle) { ctx.save(); ctx.translate(x, y); ctx.rotate(angle); ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke(); ctx.restore(); } function draw() { bCtx.clearRect(0,0,200,280); let level = 120, bBottom = 280, bWidth = 200; let q1 = masse*sub.cs*50, q2 = masse*sub.lf, q3 = masse*sub.cl*100, q4 = masse*sub.lv; if (temp < 0) { bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(15, bBottom - level, 170, level); } else if (temp === 0) { let r = (energy-q1)/q2; bCtx.fillStyle = "#1565c0"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r); bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r)); } else if (temp < 100) { bCtx.fillStyle = "#1565c0"; bCtx.fillRect(0, bBottom-level, bWidth, level); } else if (temp === 100) { let rv = (energy-(q1+q2+q3))/q4; bCtx.fillStyle = "#1565c0"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv)); bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom); } else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); } gCtx.clearRect(0,0,600,400); gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1; const marks = [-50, 0, 100, 150]; marks.forEach((tVal) => { let y = 350 - ((tVal + 50) / 200) * 300; gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke(); let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C"; gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5); }); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke(); drawArrows(gCtx, 50, 20, -Math.PI/2); gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke(); drawArrows(gCtx, 580, 350, 0); gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25); gCtx.fillText("Q (Joules)", 510, 340); if(pts.length > 1) { gCtx.beginPath(); gCtx.strokeStyle = "#1565c0"; gCtx.lineWidth = 4; pts.forEach((p, i) => { let x = 50 + (p.x / maxEnergy) * 520; let y = 350 - ((p.y + 50) / 200) * 300; if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } loop(); })(); </script>
<div id="sim-eau-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;"> <h2 style="margin: 0; color: #1565c0; font-size: 1.4em;">🔬 Analyse Thermique : Eau (H₂O)</h2> <div style="display: flex; align-items: center; gap: 15px;"> <div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;"> <button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #1565c0; color: white;">°C</button> <button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button> </div> <div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-50.0 °C</div> </div> </div> <div style="display: flex; gap: 25px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 200px; height: 302px;"> <canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas> <div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div> </div> <div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #1565c0; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div> <div style="width: 100%; margin-top: 20px; background: #1a237e; color: #e8eaf6; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;"> <div style="color: #9fa8da; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #303f9f;">Énergie Totale Transférée</div> <div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #00e5ff;">0 J</div> <div style="color: #9fa8da; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #303f9f;">Formule en cours</div> <div id="formule-display" style="font-size: 1.1em; color: #ffeb3b; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div> </div> <div id="specs" style="margin-top: 20px; background: #e3f2fd; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #bbdefb; color: #333;"> <div style="display: flex; flex-direction: column; gap: 5px;"> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>2090 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>334 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>4185 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>2260 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>1850 J/(kg·K)</span></div> </div> </div> </div> <div style="flex: 2; min-width: 400px;"> <canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas> <div style="display: flex; gap: 10px; margin-top: 20px;"> <button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button> <button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const etatLabel = document.getElementById('etat-text'); const tempDisp = document.getElementById('temp-grand'); const qTotalDisp = document.getElementById('q-total-display'); const formuleDisp = document.getElementById('formule-display'); // Propriétés Eau const sub = { cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100 }; let temp = -50, energy = 0, isRunning = false, pts = []; let isKelvin = false; const pwr = 4500, masse = 1, maxEnergy = 3500000; let heatStep = 0; window.setUnit = function(k) { isKelvin = k; document.getElementById('btnKel').style.background = k ? '#1565c0' : '#fff'; document.getElementById('btnKel').style.color = k ? '#fff' : '#333'; document.getElementById('btnDeg').style.background = k ? '#fff' : '#1565c0'; document.getElementById('btnDeg').style.color = k ? '#333' : '#fff'; updateDisplay(); }; window.toggleSim = function() { if(temp >= 150) return; isRunning = !isRunning; document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateDisplay() { tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C"; qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J"; } function update() { if(!isRunning) return; if(temp >= 150) { temp = 150.0; isRunning = false; heater.style.background = "#444"; document.getElementById('btnStart').innerText = "TERMINÉ"; document.getElementById('btnStart').style.background = "#999"; formuleDisp.innerHTML = ""; // Suppression de la formule à la fin return; } heatStep++; heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c"; energy += pwr * 1.5; let q1 = masse * sub.cs * (sub.tf - (-50)); let q2 = masse * sub.lf; let q3 = masse * sub.cl * (sub.tv - sub.tf); let q4 = masse * sub.lv; if (energy < q1) { temp = -50 + energy/(masse*sub.cs); etatLabel.innerText = "SOLIDE"; formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT"; } else if (energy < q1+q2) { temp = sub.tf; etatLabel.innerText = "FUSION"; formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>"; } else if (energy < q1+q2+q3) { temp = sub.tf + (energy-q1-q2)/(masse*sub.cl); etatLabel.innerText = "LIQUIDE"; formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT"; } else if (energy < q1+q2+q3+q4) { temp = sub.tv; etatLabel.innerText = "ÉBULLITION"; formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>"; } else { temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg); if(temp > 150) temp = 150; etatLabel.innerText = "GAZ"; formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT"; } pts.push({x: energy, y: temp}); updateDisplay(); } function drawArrows(ctx, x, y, angle) { ctx.save(); ctx.translate(x, y); ctx.rotate(angle); ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke(); ctx.restore(); } function draw() { bCtx.clearRect(0,0,200,280); let level = 120, bBottom = 280, bWidth = 200; let q1 = masse*sub.cs*50, q2 = masse*sub.lf, q3 = masse*sub.cl*100, q4 = masse*sub.lv; if (temp < 0) { bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(15, bBottom - level, 170, level); } else if (temp === 0) { let r = (energy-q1)/q2; bCtx.fillStyle = "#1565c0"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r); bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r)); } else if (temp < 100) { bCtx.fillStyle = "#1565c0"; bCtx.fillRect(0, bBottom-level, bWidth, level); } else if (temp === 100) { let rv = (energy-(q1+q2+q3))/q4; bCtx.fillStyle = "#1565c0"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv)); bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom); } else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); } gCtx.clearRect(0,0,600,400); gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1; const marks = [-50, 0, 100, 150]; marks.forEach((tVal) => { let y = 350 - ((tVal + 50) / 200) * 300; gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke(); let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C"; gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5); }); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke(); drawArrows(gCtx, 50, 20, -Math.PI/2); gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke(); drawArrows(gCtx, 580, 350, 0); gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25); gCtx.fillText("Q (Joules)", 510, 340); if(pts.length > 1) { gCtx.beginPath(); gCtx.strokeStyle = "#1565c0"; gCtx.lineWidth = 4; pts.forEach((p, i) => { let x = 50 + (p.x / maxEnergy) * 520; let y = 350 - ((p.y + 50) / 200) * 300; if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } loop(); })(); </script>
$CALEX1|=|1
Relever la température de fusion Tf = et la température d'ébullition Tvap = Identifier la substance : Pourquoi la température reste-t-elle bloquée par moments ? Calculer l'énergie nécessaire pour vaporiser 4 kg de cette substance Q = = =
VALIDER
non
<div id="sim-ammoniac-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;"> <h2 style="margin: 0; color: #689f38; font-size: 1.4em;">🔬 Analyse Thermique : Ammoniac (NH₃)</h2> <div style="display: flex; align-items: center; gap: 15px;"> <div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;"> <button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #689f38; color: white;">°C</button> <button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button> </div> <div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-100.0 °C</div> </div> </div> <div style="display: flex; gap: 25px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 200px; height: 302px;"> <canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas> <div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div> </div> <div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #689f38; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div> <div style="width: 100%; margin-top: 20px; background: #263238; color: #eceff1; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;"> <div style="color: #81c784; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #455a64;">Énergie Totale Transférée</div> <div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #ffeb3b;">0 J</div> <div style="color: #81c784; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #455a64;">Formule en cours</div> <div id="formule-display" style="font-size: 1.1em; color: #fb8c00; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div> </div> <div id="specs" style="margin-top: 20px; background: #f1f8e9; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #dcedc8; color: #333;"> <div style="display: flex; flex-direction: column; gap: 5px;"> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>2100 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>332 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>4700 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>1370 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>2050 J/(kg·K)</span></div> <hr style="border: 0; border-top: 1px solid #dcedc8; margin: 5px 0;"> <div style="display: flex; justify-content: space-between;"><span><b>Puissance P</b></span> <span>4500 W</span></div> </div> </div> </div> <div style="flex: 2; min-width: 400px;"> <canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas> <div style="display: flex; gap: 10px; margin-top: 20px;"> <button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button> <button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const etatLabel = document.getElementById('etat-text'); const tempDisp = document.getElementById('temp-grand'); const qTotalDisp = document.getElementById('q-total-display'); const formuleDisp = document.getElementById('formule-display'); const sub = { cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3 }; let temp = -100, energy = 0, isRunning = false, pts = []; let isKelvin = false; const pwr = 4500, masse = 1, maxEnergy = 2500000; let heatStep = 0; window.setUnit = function(k) { isKelvin = k; document.getElementById('btnKel').style.background = k ? '#689f38' : '#fff'; document.getElementById('btnKel').style.color = k ? '#fff' : '#333'; document.getElementById('btnDeg').style.background = k ? '#fff' : '#689f38'; document.getElementById('btnDeg').style.color = k ? '#333' : '#fff'; updateDisplay(); }; window.toggleSim = function() { if(temp >= 100) return; isRunning = !isRunning; document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateDisplay() { tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C"; qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J"; } function update() { if(!isRunning) return; if(temp >= 100) { temp = 100.0; isRunning = false; heater.style.background = "#444"; document.getElementById('btnStart').innerText = "TERMINÉ"; document.getElementById('btnStart').style.background = "#999"; return; } heatStep++; heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c"; energy += pwr * 1.5; let q1 = masse * sub.cs * (sub.tf - (-100)); let q2 = masse * sub.lf; let q3 = masse * sub.cl * (sub.tv - sub.tf); let q4 = masse * sub.lv; if (energy < q1) { temp = -100 + energy/(masse*sub.cs); etatLabel.innerText = "SOLIDE"; formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT"; } else if (energy < q1+q2) { temp = sub.tf; etatLabel.innerText = "FUSION"; formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>"; } else if (energy < q1+q2+q3) { temp = sub.tf + (energy-q1-q2)/(masse*sub.cl); etatLabel.innerText = "LIQUIDE"; formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT"; } else if (energy < q1+q2+q3+q4) { temp = sub.tv; etatLabel.innerText = "ÉBULLITION"; formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>"; } else { temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg); if(temp > 100) temp = 100; etatLabel.innerText = "GAZ"; formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT"; } pts.push({x: energy, y: temp}); updateDisplay(); } function drawArrows(ctx, x, y, angle) { ctx.save(); ctx.translate(x, y); ctx.rotate(angle); ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke(); ctx.restore(); } function draw() { bCtx.clearRect(0,0,200,280); let level = 120, bBottom = 280, bWidth = 200; let q1 = masse*sub.cs*(sub.tf - (-100)), q2 = masse*sub.lf, q3 = masse*sub.cl*(sub.tv-sub.tf), q4 = masse*sub.lv; if (temp < sub.tf) { bCtx.fillStyle = "#dcedc8"; bCtx.fillRect(15, bBottom - level, 170, level); } else if (temp === sub.tf) { let r = (energy-q1)/q2; bCtx.fillStyle = "#689f38"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r); bCtx.fillStyle = "#dcedc8"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r)); } else if (temp < sub.tv) { bCtx.fillStyle = "#689f38"; bCtx.fillRect(0, bBottom-level, bWidth, level); } else if (temp === sub.tv) { let rv = (energy-(q1+q2+q3))/q4; bCtx.fillStyle = "#689f38"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv)); bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom); } else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); } gCtx.clearRect(0,0,600,400); gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1; const marks = [-100, sub.tf, sub.tv, 50, 100]; marks.forEach((tVal) => { let y = 350 - ((tVal + 100) / 200) * 300; gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke(); let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C"; gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5); }); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke(); drawArrows(gCtx, 50, 20, -Math.PI/2); gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke(); drawArrows(gCtx, 580, 350, 0); gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25); gCtx.fillText("Q (Joules)", 510, 340); if(pts.length > 1) { gCtx.beginPath(); gCtx.strokeStyle = "#689f38"; gCtx.lineWidth = 4; pts.forEach((p, i) => { let x = 50 + (p.x / maxEnergy) * 520; let y = 350 - ((p.y + 100) / 200) * 300; if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } loop(); })(); </script>
$CALEX2|=|1
<div id="sim-ammoniac-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;"> <h2 style="margin: 0; color: #689f38; font-size: 1.4em;">🔬 Analyse Thermique : Ammoniac (NH₃)</h2> <div style="display: flex; align-items: center; gap: 15px;"> <div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;"> <button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #689f38; color: white;">°C</button> <button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button> </div> <div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-100.0 °C</div> </div> </div> <div style="display: flex; gap: 25px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 200px; height: 302px;"> <canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas> <div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div> </div> <div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #689f38; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div> <div style="width: 100%; margin-top: 20px; background: #263238; color: #eceff1; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;"> <div style="color: #81c784; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #455a64;">Énergie Totale Transférée</div> <div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #ffeb3b;">0 J</div> <div style="color: #81c784; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #455a64;">Formule en cours</div> <div id="formule-display" style="font-size: 1.1em; color: #fb8c00; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div> </div> <div id="specs" style="margin-top: 20px; background: #f1f8e9; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #dcedc8; color: #333;"> <div style="display: flex; flex-direction: column; gap: 5px;"> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>2100 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>332 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>4700 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>1370 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>2050 J/(kg·K)</span></div> <hr style="border: 0; border-top: 1px solid #dcedc8; margin: 5px 0;"> <div style="display: flex; justify-content: space-between;"><span><b>Puissance P</b></span> <span>4500 W</span></div> </div> </div> </div> <div style="flex: 2; min-width: 400px;"> <canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas> <div style="display: flex; gap: 10px; margin-top: 20px;"> <button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button> <button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const etatLabel = document.getElementById('etat-text'); const tempDisp = document.getElementById('temp-grand'); const qTotalDisp = document.getElementById('q-total-display'); const formuleDisp = document.getElementById('formule-display'); const sub = { cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3 }; let temp = -100, energy = 0, isRunning = false, pts = []; let isKelvin = false; const pwr = 4500, masse = 1, maxEnergy = 2500000; let heatStep = 0; window.setUnit = function(k) { isKelvin = k; document.getElementById('btnKel').style.background = k ? '#689f38' : '#fff'; document.getElementById('btnKel').style.color = k ? '#fff' : '#333'; document.getElementById('btnDeg').style.background = k ? '#fff' : '#689f38'; document.getElementById('btnDeg').style.color = k ? '#333' : '#fff'; updateDisplay(); }; window.toggleSim = function() { if(temp >= 100) return; isRunning = !isRunning; document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateDisplay() { tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C"; qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J"; } function update() { if(!isRunning) return; // CONDITION DE FIN : Suppression de la formule if(temp >= 100) { temp = 100.0; isRunning = false; heater.style.background = "#444"; document.getElementById('btnStart').innerText = "TERMINÉ"; document.getElementById('btnStart').style.background = "#999"; formuleDisp.innerHTML = ""; // Efface la formule ici return; } heatStep++; heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c"; energy += pwr * 1.5; let q1 = masse * sub.cs * (sub.tf - (-100)); let q2 = masse * sub.lf; let q3 = masse * sub.cl * (sub.tv - sub.tf); let q4 = masse * sub.lv; if (energy < q1) { temp = -100 + energy/(masse*sub.cs); etatLabel.innerText = "SOLIDE"; formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT"; } else if (energy < q1+q2) { temp = sub.tf; etatLabel.innerText = "FUSION"; formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>"; } else if (energy < q1+q2+q3) { temp = sub.tf + (energy-q1-q2)/(masse*sub.cl); etatLabel.innerText = "LIQUIDE"; formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT"; } else if (energy < q1+q2+q3+q4) { temp = sub.tv; etatLabel.innerText = "ÉBULLITION"; formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>"; } else { temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg); if(temp > 100) temp = 100; etatLabel.innerText = "GAZ"; formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT"; } pts.push({x: energy, y: temp}); updateDisplay(); } function drawArrows(ctx, x, y, angle) { ctx.save(); ctx.translate(x, y); ctx.rotate(angle); ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke(); ctx.restore(); } function draw() { bCtx.clearRect(0,0,200,280); let level = 120, bBottom = 280, bWidth = 200; let q1 = masse*sub.cs*(sub.tf - (-100)), q2 = masse*sub.lf, q3 = masse*sub.cl*(sub.tv-sub.tf), q4 = masse*sub.lv; if (temp < sub.tf) { bCtx.fillStyle = "#dcedc8"; bCtx.fillRect(15, bBottom - level, 170, level); } else if (temp === sub.tf) { let r = (energy-q1)/q2; bCtx.fillStyle = "#689f38"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r); bCtx.fillStyle = "#dcedc8"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r)); } else if (temp < sub.tv) { bCtx.fillStyle = "#689f38"; bCtx.fillRect(0, bBottom-level, bWidth, level); } else if (temp === sub.tv) { let rv = (energy-(q1+q2+q3))/q4; bCtx.fillStyle = "#689f38"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv)); bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom); } else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); } gCtx.clearRect(0,0,600,400); gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1; const marks = [-100, sub.tf, sub.tv, 50, 100]; marks.forEach((tVal) => { let y = 350 - ((tVal + 100) / 200) * 300; gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke(); let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C"; gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5); }); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke(); drawArrows(gCtx, 50, 20, -Math.PI/2); gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke(); drawArrows(gCtx, 580, 350, 0); gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25); gCtx.fillText("Q (Joules)", 510, 340); if(pts.length > 1) { gCtx.beginPath(); gCtx.strokeStyle = "#689f38"; gCtx.lineWidth = 4; pts.forEach((p, i) => { let x = 50 + (p.x / maxEnergy) * 520; let y = 350 - ((p.y + 100) / 200) * 300; if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } loop(); })(); </script>
Relever la température de fusion Tf = et la température d'ébullition Tvap = Identifier la substance : Que signifie le terme QV : Calculer l'énergie Qv nécessaire pour faire fondre une masse de 500g : Q = = =
$CALEX2|=|1
VALIDER
non
<div id="sim-isobutane-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;"> <h2 style="margin: 0; color: #e65100; font-size: 1.4em;">🔬 Analyse Thermique : Isobutane (C₄H₁₀)</h2> <div style="display: flex; align-items: center; gap: 15px;"> <div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;"> <button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #e65100; color: white;">°C</button> <button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button> </div> <div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-180.0 °C</div> </div> </div> <div style="display: flex; gap: 25px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 200px; height: 302px;"> <canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas> <div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div> </div> <div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #e65100; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div> <div style="width: 100%; margin-top: 20px; background: #3e2723; color: #efebe9; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;"> <div style="color: #d7ccc8; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #5d4037;">Énergie Totale Transférée</div> <div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #ffab91;">0 J</div> <div style="color: #d7ccc8; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #5d4037;">Formule en cours</div> <div id="formule-display" style="font-size: 1.1em; color: #ffd54f; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div> </div> <div id="specs" style="margin-top: 20px; background: #fff3e0; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #ffe0b2; color: #333;"> <div style="display: flex; flex-direction: column; gap: 5px;"> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>1650 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>78 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>2350 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>366 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>1700 J/(kg·K)</span></div> </div> </div> </div> <div style="flex: 2; min-width: 400px;"> <canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas> <div style="display: flex; gap: 10px; margin-top: 20px;"> <button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button> <button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const etatLabel = document.getElementById('etat-text'); const tempDisp = document.getElementById('temp-grand'); const qTotalDisp = document.getElementById('q-total-display'); const formuleDisp = document.getElementById('formule-display'); // Propriétés Isobutane const sub = { cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7 }; let temp = -180, energy = 0, isRunning = false, pts = []; let isKelvin = false; const pwr = 4500, masse = 1, maxEnergy = 1350000; let heatStep = 0; window.setUnit = function(k) { isKelvin = k; document.getElementById('btnKel').style.background = k ? '#e65100' : '#fff'; document.getElementById('btnKel').style.color = k ? '#fff' : '#333'; document.getElementById('btnDeg').style.background = k ? '#fff' : '#e65100'; document.getElementById('btnDeg').style.color = k ? '#333' : '#fff'; updateDisplay(); }; window.toggleSim = function() { if(temp >= 150) return; isRunning = !isRunning; document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateDisplay() { tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C"; qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J"; } function update() { if(!isRunning) return; if(temp >= 150) { temp = 150.0; isRunning = false; heater.style.background = "#444"; document.getElementById('btnStart').innerText = "TERMINÉ"; document.getElementById('btnStart').style.background = "#999"; return; } heatStep++; heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c"; energy += pwr * 1.5; let q1 = masse * sub.cs * (sub.tf - (-180)); let q2 = masse * sub.lf; let q3 = masse * sub.cl * (sub.tv - sub.tf); let q4 = masse * sub.lv; if (energy < q1) { temp = -180 + energy/(masse*sub.cs); etatLabel.innerText = "SOLIDE"; formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT"; } else if (energy < q1+q2) { temp = sub.tf; etatLabel.innerText = "FUSION"; formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>"; } else if (energy < q1+q2+q3) { temp = sub.tf + (energy-q1-q2)/(masse*sub.cl); etatLabel.innerText = "LIQUIDE"; formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT"; } else if (energy < q1+q2+q3+q4) { temp = sub.tv; etatLabel.innerText = "ÉBULLITION"; formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>"; } else { temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg); if(temp > 150) temp = 150; etatLabel.innerText = "GAZ"; formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT"; } pts.push({x: energy, y: temp}); updateDisplay(); } function drawArrows(ctx, x, y, angle) { ctx.save(); ctx.translate(x, y); ctx.rotate(angle); ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke(); ctx.restore(); } function draw() { bCtx.clearRect(0,0,200,280); let level = 120, bBottom = 280, bWidth = 200; let q1 = masse*sub.cs*(sub.tf - (-180)), q2 = masse*sub.lf, q3 = masse*sub.cl*(sub.tv-sub.tf), q4 = masse*sub.lv; if (temp < sub.tf) { bCtx.fillStyle = "#ffccbc"; bCtx.fillRect(15, bBottom - level, 170, level); } else if (temp === sub.tf) { let r = (energy-q1)/q2; bCtx.fillStyle = "#e65100"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r); bCtx.fillStyle = "#ffccbc"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r)); } else if (temp < sub.tv) { bCtx.fillStyle = "#e65100"; bCtx.fillRect(0, bBottom-level, bWidth, level); } else if (temp === sub.tv) { let rv = (energy-(q1+q2+q3))/q4; bCtx.fillStyle = "#e65100"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv)); bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom); } else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); } gCtx.clearRect(0,0,600,400); gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1; const marks = [-180, sub.tf, sub.tv, 50, 150]; marks.forEach((tVal) => { let y = 350 - ((tVal + 180) / 330) * 300; gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke(); let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C"; gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5); }); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke(); drawArrows(gCtx, 50, 20, -Math.PI/2); gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke(); drawArrows(gCtx, 580, 350, 0); gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25); gCtx.fillText("Q (Joules)", 510, 340); if(pts.length > 1) { gCtx.beginPath(); gCtx.strokeStyle = "#e65100"; gCtx.lineWidth = 4; pts.forEach((p, i) => { let x = 50 + (p.x / maxEnergy) * 520; let y = 350 - ((p.y + 180) / 330) * 300; if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } loop(); })(); </script>
$CALEX3|=|1
<div id="sim-isobutane-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;"> <h2 style="margin: 0; color: #e65100; font-size: 1.4em;">🔬 Analyse Thermique : Isobutane (C₄H₁₀)</h2> <div style="display: flex; align-items: center; gap: 15px;"> <div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;"> <button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #e65100; color: white;">°C</button> <button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button> </div> <div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-180.0 °C</div> </div> </div> <div style="display: flex; gap: 25px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 200px; height: 302px;"> <canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas> <div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div> </div> <div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #e65100; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div> <div style="width: 100%; margin-top: 20px; background: #3e2723; color: #efebe9; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;"> <div style="color: #d7ccc8; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #5d4037;">Énergie Totale Transférée</div> <div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #ffab91;">0 J</div> <div style="color: #d7ccc8; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #5d4037;">Formule en cours</div> <div id="formule-display" style="font-size: 1.1em; color: #ffd54f; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div> </div> <div id="specs" style="margin-top: 20px; background: #fff3e0; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #ffe0b2; color: #333;"> <div style="display: flex; flex-direction: column; gap: 5px;"> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>1650 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>78 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>2350 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>366 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>1700 J/(kg·K)</span></div> </div> </div> </div> <div style="flex: 2; min-width: 400px;"> <canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas> <div style="display: flex; gap: 10px; margin-top: 20px;"> <button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button> <button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const etatLabel = document.getElementById('etat-text'); const tempDisp = document.getElementById('temp-grand'); const qTotalDisp = document.getElementById('q-total-display'); const formuleDisp = document.getElementById('formule-display'); // Propriétés Isobutane const sub = { cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7 }; let temp = -180, energy = 0, isRunning = false, pts = []; let isKelvin = false; const pwr = 4500, masse = 1, maxEnergy = 1350000; let heatStep = 0; window.setUnit = function(k) { isKelvin = k; document.getElementById('btnKel').style.background = k ? '#e65100' : '#fff'; document.getElementById('btnKel').style.color = k ? '#fff' : '#333'; document.getElementById('btnDeg').style.background = k ? '#fff' : '#e65100'; document.getElementById('btnDeg').style.color = k ? '#333' : '#fff'; updateDisplay(); }; window.toggleSim = function() { if(temp >= 150) return; isRunning = !isRunning; document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateDisplay() { tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C"; qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J"; } function update() { if(!isRunning) return; // CONDITION DE FIN : Suppression de la formule if(temp >= 150) { temp = 150.0; isRunning = false; heater.style.background = "#444"; document.getElementById('btnStart').innerText = "TERMINÉ"; document.getElementById('btnStart').style.background = "#999"; formuleDisp.innerHTML = ""; // Efface la formule return; } heatStep++; heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c"; energy += pwr * 1.5; let q1 = masse * sub.cs * (sub.tf - (-180)); let q2 = masse * sub.lf; let q3 = masse * sub.cl * (sub.tv - sub.tf); let q4 = masse * sub.lv; if (energy < q1) { temp = -180 + energy/(masse*sub.cs); etatLabel.innerText = "SOLIDE"; formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT"; } else if (energy < q1+q2) { temp = sub.tf; etatLabel.innerText = "FUSION"; formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>"; } else if (energy < q1+q2+q3) { temp = sub.tf + (energy-q1-q2)/(masse*sub.cl); etatLabel.innerText = "LIQUIDE"; formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT"; } else if (energy < q1+q2+q3+q4) { temp = sub.tv; etatLabel.innerText = "ÉBULLITION"; formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>"; } else { temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg); if(temp > 150) temp = 150; etatLabel.innerText = "GAZ"; formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT"; } pts.push({x: energy, y: temp}); updateDisplay(); } function drawArrows(ctx, x, y, angle) { ctx.save(); ctx.translate(x, y); ctx.rotate(angle); ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke(); ctx.restore(); } function draw() { bCtx.clearRect(0,0,200,280); let level = 120, bBottom = 280, bWidth = 200; let q1 = masse*sub.cs*(sub.tf - (-180)), q2 = masse*sub.lf, q3 = masse*sub.cl*(sub.tv-sub.tf), q4 = masse*sub.lv; if (temp < sub.tf) { bCtx.fillStyle = "#ffccbc"; bCtx.fillRect(15, bBottom - level, 170, level); } else if (temp === sub.tf) { let r = (energy-q1)/q2; bCtx.fillStyle = "#e65100"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r); bCtx.fillStyle = "#ffccbc"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r)); } else if (temp < sub.tv) { bCtx.fillStyle = "#e65100"; bCtx.fillRect(0, bBottom-level, bWidth, level); } else if (temp === sub.tv) { let rv = (energy-(q1+q2+q3))/q4; bCtx.fillStyle = "#e65100"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv)); bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom); } else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); } gCtx.clearRect(0,0,600,400); gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1; const marks = [-180, sub.tf, sub.tv, 50, 150]; marks.forEach((tVal) => { let y = 350 - ((tVal + 180) / 330) * 300; gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke(); let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C"; gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5); }); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke(); drawArrows(gCtx, 50, 20, -Math.PI/2); gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke(); drawArrows(gCtx, 580, 350, 0); gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25); gCtx.fillText("Q (Joules)", 510, 340); if(pts.length > 1) { gCtx.beginPath(); gCtx.strokeStyle = "#e65100"; gCtx.lineWidth = 4; pts.forEach((p, i) => { let x = 50 + (p.x / maxEnergy) * 520; let y = 350 - ((p.y + 180) / 330) * 300; if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } loop(); })(); </script>
Relever la température de fusion Tf = et la température d'ébullition Tvap = Identifier la substance : La pente entre deux paliers dépend de quelle propriété ? Calculer l'énergie nécessaire pour chauffer 2 kg de cette substance liquide de -20°C à -10 °C Q = = =
VALIDER
non
<div id="sim-difluoro-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;"> <h2 style="margin: 0; color: #00796b; font-size: 1.4em;">🔬 Analyse Thermique : Difluorométhane (CH₂F₂)</h2> <div style="display: flex; align-items: center; gap: 15px;"> <div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;"> <button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #00796b; color: white;">°C</button> <button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button> </div> <div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-160.0 °C</div> </div> </div> <div style="display: flex; gap: 25px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 200px; height: 302px;"> <canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas> <div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div> </div> <div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #00796b; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div> <div style="width: 100%; margin-top: 20px; background: #004d40; color: #e0f2f1; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;"> <div style="color: #80cbc4; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #00695c;">Énergie Totale Transférée</div> <div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #4dd0e1;">0 J</div> <div style="color: #80cbc4; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #00695c;">Formule en cours</div> <div id="formule-display" style="font-size: 1.1em; color: #ffeb3b; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div> </div> <div id="specs" style="margin-top: 20px; background: #e0f2f1; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #b2dfdb; color: #333;"> <div style="display: flex; flex-direction: column; gap: 5px;"> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>1450 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>133 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>1910 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>390 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>840 J/(kg·K)</span></div> </div> </div> </div> <div style="flex: 2; min-width: 400px;"> <canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas> <div style="display: flex; gap: 10px; margin-top: 20px;"> <button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button> <button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const etatLabel = document.getElementById('etat-text'); const tempDisp = document.getElementById('temp-grand'); const qTotalDisp = document.getElementById('q-total-display'); const formuleDisp = document.getElementById('formule-display'); // Propriétés Difluorométhane (R-32) const sub = { cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136.0, tv: -51.7 }; let temp = -160, energy = 0, isRunning = false, pts = []; let isKelvin = false; const pwr = 4500, masse = 1, maxEnergy = 1100000; let heatStep = 0; window.setUnit = function(k) { isKelvin = k; document.getElementById('btnKel').style.background = k ? '#00796b' : '#fff'; document.getElementById('btnKel').style.color = k ? '#fff' : '#333'; document.getElementById('btnDeg').style.background = k ? '#fff' : '#00796b'; document.getElementById('btnDeg').style.color = k ? '#333' : '#fff'; updateDisplay(); }; window.toggleSim = function() { if(temp >= 150) return; isRunning = !isRunning; document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateDisplay() { tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C"; qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J"; } function update() { if(!isRunning) return; // CONDITION DE FIN : Suppression de la formule ici if(temp >= 150) { temp = 150.0; isRunning = false; heater.style.background = "#444"; document.getElementById('btnStart').innerText = "TERMINÉ"; document.getElementById('btnStart').style.background = "#999"; formuleDisp.innerHTML = ""; // La formule disparaît return; } heatStep++; heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c"; energy += pwr * 1.5; let q1 = masse * sub.cs * (sub.tf - (-160)); let q2 = masse * sub.lf; let q3 = masse * sub.cl * (sub.tv - sub.tf); let q4 = masse * sub.lv; if (energy < q1) { temp = -160 + energy/(masse*sub.cs); etatLabel.innerText = "SOLIDE"; formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT"; } else if (energy < q1+q2) { temp = sub.tf; etatLabel.innerText = "FUSION"; formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>"; } else if (energy < q1+q2+q3) { temp = sub.tf + (energy-q1-q2)/(masse*sub.cl); etatLabel.innerText = "LIQUIDE"; formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT"; } else if (energy < q1+q2+q3+q4) { temp = sub.tv; etatLabel.innerText = "ÉBULLITION"; formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>"; } else { temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg); if(temp > 150) temp = 150; etatLabel.innerText = "GAZ"; formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT"; } pts.push({x: energy, y: temp}); updateDisplay(); } function drawArrows(ctx, x, y, angle) { ctx.save(); ctx.translate(x, y); ctx.rotate(angle); ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke(); ctx.restore(); } function draw() { bCtx.clearRect(0,0,200,280); let level = 120, bBottom = 280, bWidth = 200; let q1 = masse*sub.cs*(sub.tf - (-160)), q2 = masse*sub.lf, q3 = masse*sub.cl*(sub.tv-sub.tf), q4 = masse*sub.lv; if (temp < sub.tf) { bCtx.fillStyle = "#b2dfdb"; bCtx.fillRect(15, bBottom - level, 170, level); } else if (temp === sub.tf) { let r = (energy-q1)/q2; bCtx.fillStyle = "#00796b"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r); bCtx.fillStyle = "#b2dfdb"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r)); } else if (temp < sub.tv) { bCtx.fillStyle = "#00796b"; bCtx.fillRect(0, bBottom-level, bWidth, level); } else if (temp === sub.tv) { let rv = (energy-(q1+q2+q3))/q4; bCtx.fillStyle = "#00796b"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv)); bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom); } else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); } gCtx.clearRect(0,0,600,400); gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1; const marks = [-160, sub.tf, sub.tv, 50, 150]; marks.forEach((tVal) => { let y = 350 - ((tVal + 160) / 310) * 300; gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke(); let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C"; gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5); }); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke(); drawArrows(gCtx, 50, 20, -Math.PI/2); gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke(); drawArrows(gCtx, 580, 350, 0); gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25); gCtx.fillText("Q (Joules)", 510, 340); if(pts.length > 1) { gCtx.beginPath(); gCtx.strokeStyle = "#00796b"; gCtx.lineWidth = 4; pts.forEach((p, i) => { let x = 50 + (p.x / maxEnergy) * 520; let y = 350 - ((p.y + 160) / 310) * 300; if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } loop(); })(); </script>
<div id="sim-difluoro-dynamique" style="width: 100%; max-width: 1050px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #ccc; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 12px; border: 1px solid #eee;"> <h2 style="margin: 0; color: #00796b; font-size: 1.4em;">🔬 Analyse Thermique : Difluorométhane (CH₂F₂)</h2> <div style="display: flex; align-items: center; gap: 15px;"> <div style="display: flex; background: #eee; padding: 5px; border-radius: 8px; gap: 5px;"> <button id="btnDeg" onclick="setUnit(false)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #00796b; color: white;">°C</button> <button id="btnKel" onclick="setUnit(true)" style="padding: 8px 15px; cursor: pointer; border: none; border-radius: 5px; font-weight: bold; background: #fff; color: #333;">K</button> </div> <div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 180px; text-align: right;">-160.0 °C</div> </div> </div> <div style="display: flex; gap: 25px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 280px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 200px; height: 302px;"> <canvas id="beakerSimple" width="200" height="280" style="border-left: 5px solid #777; border-right: 5px solid #777; border-bottom: 5px solid #777; background: #fff; position: relative; z-index: 2; border-radius: 0 0 10px 10px;"></canvas> <div id="heater" style="width: 210px; height: 22px; background: #444; border-radius: 4px 4px 12px 12px; margin-top: -2px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold; margin-left: -5px;">CHAUFFAGE</div> </div> <div id="etat-text" style="margin-top: 15px; font-weight: bold; color: #00796b; font-size: 1.6em; text-transform: uppercase;">SOLIDE</div> <div style="width: 100%; margin-top: 20px; background: #004d40; color: #e0f2f1; padding: 15px; border-radius: 12px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); font-family: 'Courier New', monospace;"> <div style="color: #80cbc4; font-size: 0.8em; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #00695c;">Énergie Totale Transférée</div> <div id="q-total-display" style="font-size: 1.5em; font-weight: bold; color: #4dd0e1;">0 J</div> <div style="color: #80cbc4; font-size: 0.8em; margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; border-bottom: 1px solid #00695c;">Formule en cours</div> <div id="formule-display" style="font-size: 1.1em; color: #ffeb3b; min-height: 1.2em;">Q = m · c<sub>s</sub> · ΔT</div> </div> <div id="specs" style="margin-top: 20px; background: #e0f2f1; padding: 15px; border-radius: 12px; width: 100%; font-size: 0.85em; border: 1px solid #b2dfdb; color: #333;"> <div style="display: flex; flex-direction: column; gap: 5px;"> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>s</sub></b> (Solide)</span> <span>1450 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>f</sub></b> (Fusion)</span> <span>133 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>l</sub></b> (Liquide)</span> <span>1910 J/(kg·K)</span></div> <div style="display: flex; justify-content: space-between;"><span><b>L<sub>v</sub></b> (Vaporisation)</span> <span>390 kJ/kg</span></div> <div style="display: flex; justify-content: space-between;"><span><b>c<sub>p</sub></b> (Gaz)</span> <span>840 J/(kg·K)</span></div> </div> </div> </div> <div style="flex: 2; min-width: 400px;"> <canvas id="graphSimple" width="600" height="400" style="width: 100%; border-radius: 10px;"></canvas> <div style="display: flex; gap: 10px; margin-top: 20px;"> <button id="btnStart" onclick="toggleSim()" style="flex: 2; padding: 18px; font-size: 1.1em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 10px; cursor: pointer; box-shadow: 0 4px 0 #1b5e20;">DÉMARRER</button> <button onclick="location.reload()" style="flex: 1; padding: 18px; background: #607d8b; color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold;">RESET</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSimple'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSimple'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const etatLabel = document.getElementById('etat-text'); const tempDisp = document.getElementById('temp-grand'); const qTotalDisp = document.getElementById('q-total-display'); const formuleDisp = document.getElementById('formule-display'); // Propriétés Difluorométhane (R-32) const sub = { cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136.0, tv: -51.7 }; let temp = -160, energy = 0, isRunning = false, pts = []; let isKelvin = false; const pwr = 4500, masse = 1, maxEnergy = 1100000; let heatStep = 0; window.setUnit = function(k) { isKelvin = k; document.getElementById('btnKel').style.background = k ? '#00796b' : '#fff'; document.getElementById('btnKel').style.color = k ? '#fff' : '#333'; document.getElementById('btnDeg').style.background = k ? '#fff' : '#00796b'; document.getElementById('btnDeg').style.color = k ? '#333' : '#fff'; updateDisplay(); }; window.toggleSim = function() { if(temp >= 150) return; isRunning = !isRunning; document.getElementById('btnStart').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnStart').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateDisplay() { tempDisp.innerText = isKelvin ? (temp + 273.15).toFixed(1) + " K" : temp.toFixed(1) + " °C"; qTotalDisp.innerText = Math.floor(energy).toLocaleString() + " J"; } function update() { if(!isRunning) return; if(temp >= 150) { temp = 150.0; isRunning = false; heater.style.background = "#444"; document.getElementById('btnStart').innerText = "TERMINÉ"; document.getElementById('btnStart').style.background = "#999"; return; } heatStep++; heater.style.background = (Math.floor(heatStep/10) % 2 === 0) ? "#ff1744" : "#b71c1c"; energy += pwr * 1.5; let q1 = masse * sub.cs * (sub.tf - (-160)); let q2 = masse * sub.lf; let q3 = masse * sub.cl * (sub.tv - sub.tf); let q4 = masse * sub.lv; if (energy < q1) { temp = -160 + energy/(masse*sub.cs); etatLabel.innerText = "SOLIDE"; formuleDisp.innerHTML = "Q<sub>chauffage solide</sub> = m · c<sub>s</sub> · ΔT"; } else if (energy < q1+q2) { temp = sub.tf; etatLabel.innerText = "FUSION"; formuleDisp.innerHTML = "Q<sub>f</sub> = m · L<sub>f</sub>"; } else if (energy < q1+q2+q3) { temp = sub.tf + (energy-q1-q2)/(masse*sub.cl); etatLabel.innerText = "LIQUIDE"; formuleDisp.innerHTML = "Q<sub>chauffage liquide</sub> = m · c<sub>l</sub> · ΔT"; } else if (energy < q1+q2+q3+q4) { temp = sub.tv; etatLabel.innerText = "ÉBULLITION"; formuleDisp.innerHTML = "Q<sub>v</sub> = m · L<sub>v</sub>"; } else { temp = sub.tv + (energy-q1-q2-q3-q4)/(masse*sub.cg); if(temp > 150) temp = 150; etatLabel.innerText = "GAZ"; formuleDisp.innerHTML = "Q<sub>chauffage gaz</sub> = m · c<sub>p</sub> · ΔT"; } pts.push({x: energy, y: temp}); updateDisplay(); } function drawArrows(ctx, x, y, angle) { ctx.save(); ctx.translate(x, y); ctx.rotate(angle); ctx.beginPath(); ctx.moveTo(-10, -5); ctx.lineTo(0, 0); ctx.lineTo(-10, 5); ctx.stroke(); ctx.restore(); } function draw() { bCtx.clearRect(0,0,200,280); let level = 120, bBottom = 280, bWidth = 200; let q1 = masse*sub.cs*(sub.tf - (-160)), q2 = masse*sub.lf, q3 = masse*sub.cl*(sub.tv-sub.tf), q4 = masse*sub.lv; if (temp < sub.tf) { bCtx.fillStyle = "#b2dfdb"; bCtx.fillRect(15, bBottom - level, 170, level); } else if (temp === sub.tf) { let r = (energy-q1)/q2; bCtx.fillStyle = "#00796b"; bCtx.fillRect(0, bBottom-level*r, bWidth, level*r); bCtx.fillStyle = "#b2dfdb"; bCtx.fillRect(15+(170*(1-r))/2, bBottom-level, 170*r, level*(1-r)); } else if (temp < sub.tv) { bCtx.fillStyle = "#00796b"; bCtx.fillRect(0, bBottom-level, bWidth, level); } else if (temp === sub.tv) { let rv = (energy-(q1+q2+q3))/q4; bCtx.fillStyle = "#00796b"; bCtx.fillRect(0, bBottom-level*(1-rv), bWidth, level*(1-rv)); bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(0, 0, bWidth, bBottom); } else { bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, bWidth, bBottom); } gCtx.clearRect(0,0,600,400); gCtx.strokeStyle = "#eee"; gCtx.lineWidth = 1; const marks = [-160, sub.tf, sub.tv, 50, 150]; marks.forEach((tVal) => { let y = 350 - ((tVal + 160) / 310) * 300; gCtx.beginPath(); gCtx.moveTo(50, y); gCtx.lineTo(570, y); gCtx.stroke(); let lab = isKelvin ? (tVal+273.15).toFixed(0)+"K" : tVal.toFixed(1)+"°C"; gCtx.fillStyle = "#999"; gCtx.fillText(lab, 5, y + 5); }); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(50, 360); gCtx.lineTo(50, 20); gCtx.stroke(); drawArrows(gCtx, 50, 20, -Math.PI/2); gCtx.beginPath(); gCtx.moveTo(40, 350); gCtx.lineTo(580, 350); gCtx.stroke(); drawArrows(gCtx, 580, 350, 0); gCtx.fillStyle = "#333"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (" + (isKelvin?"K":"°C") + ")", 65, 25); gCtx.fillText("Q (Joules)", 510, 340); if(pts.length > 1) { gCtx.beginPath(); gCtx.strokeStyle = "#00796b"; gCtx.lineWidth = 4; pts.forEach((p, i) => { let x = 50 + (p.x / maxEnergy) * 520; let y = 350 - ((p.y + 160) / 310) * 300; if(i === 0) gCtx.moveTo(x, y); else gCtx.lineTo(x, y); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } loop(); })(); </script>
Relever la température de fusion Tf = et la température d'ébullition Tvap = Identifier la substance : Si l'on double la puissance du chauffage P en Watt, alors diminue de moitié. Calculer l'énergie nécessaire pour chauffer 300g de cette substance liquide sous forme de gaz de 20°C à 40°C. Q = = =
$CALEX4|=|1
VALIDER
non
Spécialiste calorimetrie
?$CALEX1|=|1&CALEX2|=|1&CALEX3|=|1&CALEX4|=|1&CAL1|=|1&CAL2|=|1&CAL3|=|1
§nom§
ANNEE
<div id="sim-thermo-challenge-final" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd; flex-wrap: wrap; gap: 15px;"> <div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;"> <div> <label style="font-weight: bold; color: #444;">Choix :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #1565c0; cursor: pointer;"> <option value="subA">Substance A</option> <option value="subB">Substance B</option> <option value="subC">Substance C</option> <option value="subD">Substance D</option> <option value="subE">Substance E</option> </select> </div> <div> <label style="font-weight: bold; color: #444;">Masse :</label> <select id="selectMasse" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; cursor: pointer;"> <option value="1">1 kg</option> <option value="2">2 kg</option> <option value="5">5 kg</option> <option value="10">10 kg</option> </select> </div> </div> <div id="temp-grand" style="font-size: 3.2em; font-weight: bold; color: #d32f2f; font-family: monospace; background: #fff; padding: 5px 15px; border-radius: 10px; border: 1px solid #ccc; min-width: 200px; text-align: center;">-200.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.4em; font-weight: bold; color: #1565c0; text-align: center;">-</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.2em; margin-bottom: 10px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-bottom: 8px;">FORMULE APPLIQUÉE</div> <div id="q-val" style="font-size: 1.6em; color: #ffeb3b; margin-bottom: 8px;">0 J</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; border-top: 1px solid #333; padding-top: 8px;">Q = m · cₛ · ΔT</div> </div> </div> <div style="flex: 2; min-width: 450px; display: flex; flex-direction: column;"> <canvas id="graphSim" width="600" height="420" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 10px; margin-top: 20px; justify-content: flex-end;"> <button id="btnPlay" onclick="toggleSim()" style="width: 160px; padding: 15px; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 1.1em; box-shadow: 0 4px #1b5e20;">DÉMARRER</button> <button onclick="resetSim()" style="padding: 15px; background: #546e7a; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const selectF = document.getElementById('selectFluide'), selectM = document.getElementById('selectMasse'); const db = { subA: { label: "Substance A", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114, tv: 78, isCO2: false }, subB: { label: "Substance B", cs: 850, cg: 840, ls: 571000, ts: -78.5, isCO2: true }, subC: { label: "Substance C", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155, tv: -82, isCO2: false }, subD: { label: "Substance D", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -188, tv: -42, isCO2: false }, subE: { label: "Substance E", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152, tv: -29, isCO2: false } }; let s, temp, energy, masse, isRunning = false, pts = [], blinkFrame = 0; const pwr = 4500, tStart = -200, tEnd = 200; let gasParticles = []; window.initSubstance = function() { s = db[selectF.value]; masse = parseFloat(selectM.value); temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER"; document.getElementById('btnPlay').style.background = "#2e7d32"; gasParticles = []; updateUI(); }; window.toggleSim = function() { if(temp >= tEnd && isRunning) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; window.resetSim = function() { initSubstance(); }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.label + " (" + masse + " kg)"; } function update() { if(!isRunning || temp >= tEnd) { heater.style.background = "#333"; return; } blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 8) % 2 === 0) ? "#d32f2f" : "#333"; energy += pwr * 15; const fText = document.getElementById('formule-text'); const eText = document.getElementById('etat-text'); if (s.isCO2) { let q1 = masse * s.cs * (s.ts - tStart); let q2 = masse * s.ls; if (energy < q1) { temp = tStart + energy/(masse*s.cs); eText.innerText = "ÉTAT : SOLIDE"; fText.innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.ts; eText.innerText = "ÉTAT : SUBLIMATION"; fText.innerHTML = "Q = m · Lₛ"; } else { temp = s.ts + (energy - q1 - q2)/(masse*s.cg); eText.innerText = "ÉTAT : GAZ"; fText.innerHTML = "Q = m · cₚ · ΔT"; } } else { let q1 = masse * s.cs * (s.tf - tStart), q2 = masse * s.lf; let q3 = masse * s.cl * (s.tv - s.tf), q4 = masse * s.lv; if (energy < q1) { temp = tStart + energy/(masse*s.cs); eText.innerText = "ÉTAT : SOLIDE"; fText.innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.tf; eText.innerText = "ÉTAT : FUSION"; fText.innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = s.tf + (energy - q1 - q2)/(masse*s.cl); eText.innerText = "ÉTAT : LIQUIDE"; fText.innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = s.tv; eText.innerText = "ÉTAT : ÉBULLITION"; fText.innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg); eText.innerText = "ÉTAT : GAZ"; fText.innerHTML = "Q = m · cₚ · ΔT"; } } pts.push({x: energy, y: temp}); updateUI(); if(gasParticles.length > 0) { let speed = 0.5 + ((temp + 200) * 0.015); gasParticles.forEach(p => { p.x += p.vx * speed; p.y += p.vy * speed; if(p.x < 10 || p.x > 210) p.vx *= -1; if(p.y < 10 || p.y > 290) p.vy *= -1; }); } } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 40 + (masse * 15); if(s.isCO2) { let q1 = masse * s.cs * (s.ts - tStart), q2 = masse * s.ls; if (temp < s.ts) { bCtx.fillStyle = "#ccc"; bCtx.fillRect(40, 300-hMax, 140, hMax); } else if (temp === s.ts) { let r = Math.min(1, (energy-q1)/q2); bCtx.fillStyle = "#ccc"; bCtx.fillRect(40, 300-hMax, 140, hMax*(1-r)); if(gasParticles.length < Math.floor(r*60)) gasParticles.push({x: 110, y: 250, vx: Math.random()*2-1, vy: -Math.random()*2, r: 3}); bCtx.fillStyle = "rgba(220,220,220,0.5)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); }); } else { bCtx.fillStyle = "rgba(200,200,200,0.6)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r+1, 0, 7); bCtx.fill(); }); } } else { let q1 = masse * s.cs * (s.tf - tStart), q2 = masse * s.lf, q3 = masse * s.cl * (s.tv - s.tf); if(temp < s.tf) { bCtx.fillStyle = "#64b5f6"; bCtx.fillRect(40, 300-hMax, 140, hMax); } else if (temp === s.tf) { let r = Math.min(1, (energy-q1)/q2); bCtx.fillStyle = "#e3f2fd"; bCtx.fillRect(10, 300-(hMax*r), 220, hMax*r); bCtx.fillStyle = "#64b5f6"; bCtx.fillRect(40, 300-hMax, 140, hMax*(1-r)); } else if (temp < s.tv) { bCtx.fillStyle = "#e3f2fd"; bCtx.fillRect(10, 300-hMax, 200, hMax); } else { if(gasParticles.length < 60) gasParticles.push({x: 110, y: 200, vx: Math.random()*4-2, vy: Math.random()*4-2, r: 2.5}); bCtx.fillStyle = "rgba(180,210,255,0.5)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); }); } } gCtx.clearRect(0,0,600,420); gCtx.strokeStyle = "#444"; gCtx.lineWidth = 2; // Axe Y avec flèche gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(60, 20); gCtx.stroke(); gCtx.beginPath(); gCtx.moveTo(55, 30); gCtx.lineTo(60, 15); gCtx.lineTo(65, 30); gCtx.fill(); gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T", 40, 25); // Axe X avec flèche gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(580, 390); gCtx.stroke(); gCtx.beginPath(); gCtx.moveTo(575, 385); gCtx.lineTo(590, 390); gCtx.lineTo(575, 395); gCtx.fill(); gCtx.fillText("Q", 580, 410); let xMax = masse * 1500000; for(let t=-200; t<=200; t+=50) { let y = 390 - ((t+200)/400)*350; gCtx.fillStyle = "#888"; gCtx.font = "10px Arial"; gCtx.fillText(t, 30, y+4); gCtx.beginPath(); gCtx.moveTo(55,y); gCtx.lineTo(60,y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = "#1565c0"; gCtx.lineWidth = 3; pts.forEach((p, i) => { let px = 60 + (p.x / xMax) * 500; let py = 390 - ((p.y + 200) / 400) * 350; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-co2-fix" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd; flex-wrap: wrap; gap: 15px;"> <div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;"> <div> <label style="font-weight: bold; color: #444;">Choix :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #1565c0; cursor: pointer;"> <option value="subA">Substance A</option> <option value="subB">Substance B</option> <option value="subC">Substance C</option> <option value="subD">Substance D</option> <option value="subE">Substance E</option> </select> </div> <div> <label style="font-weight: bold; color: #444;">Masse :</label> <select id="selectMasse" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; cursor: pointer;"> <option value="1">1 kg</option> <option value="2">2 kg</option> <option value="5">5 kg</option> <option value="10">10 kg</option> </select> </div> </div> <div id="temp-grand" style="font-size: 3.2em; font-weight: bold; color: #d32f2f; font-family: monospace; background: #fff; padding: 5px 15px; border-radius: 10px; border: 1px solid #ccc; min-width: 200px; text-align: center;">-200.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.4em; font-weight: bold; color: #1565c0; text-align: center;">-</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.2em; margin-bottom: 10px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-bottom: 8px;">FORMULE APPLIQUÉE</div> <div id="q-val" style="font-size: 1.6em; color: #ffeb3b; margin-bottom: 8px;">0 J</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; border-top: 1px solid #333; padding-top: 8px;">Q = m · cₛ · ΔT</div> </div> </div> <div style="flex: 2; min-width: 450px; display: flex; flex-direction: column;"> <canvas id="graphSim" width="600" height="420" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 10px; margin-top: 20px; justify-content: flex-end;"> <button id="btnPlay" onclick="toggleSim()" style="width: 160px; padding: 15px; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 1.1em; box-shadow: 0 4px #1b5e20;">DÉMARRER</button> <button onclick="resetSim()" style="padding: 15px; background: #546e7a; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const selectF = document.getElementById('selectFluide'), selectM = document.getElementById('selectMasse'); const db = { subA: { label: "Substance A", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114, tv: 78, isCO2: false }, subB: { label: "Substance B", cs: 850, cg: 840, ls: 571000, ts: -78.5, isCO2: true }, // CO2 : Sublimation directe subC: { label: "Substance C", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155, tv: -82, isCO2: false }, subD: { label: "Substance D", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -188, tv: -42, isCO2: false }, subE: { label: "Substance E", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152, tv: -29, isCO2: false } }; let s, temp, energy, masse, isRunning = false, pts = [], blinkFrame = 0; const pwr = 4500, tStart = -200, tEnd = 200; let gasParticles = []; window.initSubstance = function() { s = db[selectF.value]; masse = parseFloat(selectM.value); temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER"; document.getElementById('btnPlay').style.background = "#2e7d32"; gasParticles = []; updateUI(); }; window.toggleSim = function() { if(temp >= tEnd && isRunning) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; window.resetSim = function() { initSubstance(); }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.label + " (" + masse + " kg)"; } function update() { if(!isRunning || temp >= tEnd) { heater.style.background = "#333"; return; } blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 8) % 2 === 0) ? "#d32f2f" : "#333"; energy += pwr * 15; const fText = document.getElementById('formule-text'); const eText = document.getElementById('etat-text'); if (s.isCO2) { let q1 = masse * s.cs * (s.ts - tStart); let q2 = masse * s.ls; if (energy < q1) { temp = tStart + energy/(masse*s.cs); eText.innerText = "ÉTAT : SOLIDE"; fText.innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.ts; eText.innerText = "ÉTAT : SUBLIMATION"; fText.innerHTML = "Q = m · Lₛ"; } else { temp = s.ts + (energy - q1 - q2)/(masse*s.cg); eText.innerText = "ÉTAT : GAZ"; fText.innerHTML = "Q = m · cₚ · ΔT"; } } else { let q1 = masse * s.cs * (s.tf - tStart), q2 = masse * s.lf; let q3 = masse * s.cl * (s.tv - s.tf), q4 = masse * s.lv; if (energy < q1) { temp = tStart + energy/(masse*s.cs); eText.innerText = "ÉTAT : SOLIDE"; fText.innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.tf; eText.innerText = "ÉTAT : FUSION"; fText.innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = s.tf + (energy - q1 - q2)/(masse*s.cl); eText.innerText = "ÉTAT : LIQUIDE"; fText.innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = s.tv; eText.innerText = "ÉTAT : ÉBULLITION"; fText.innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg); eText.innerText = "ÉTAT : GAZ"; fText.innerHTML = "Q = m · cₚ · ΔT"; } } pts.push({x: energy, y: temp}); updateUI(); if(gasParticles.length > 0) { let speed = 0.5 + ((temp + 200) * 0.015); gasParticles.forEach(p => { p.x += p.vx * speed; p.y += p.vy * speed; if(p.x < 10 || p.x > 210) p.vx *= -1; if(p.y < 10 || p.y > 290) p.vy *= -1; }); } } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 40 + (masse * 15); if(s.isCO2) { let q1 = masse * s.cs * (s.ts - tStart), q2 = masse * s.ls; if (temp < s.ts) { bCtx.fillStyle = "#ccc"; bCtx.fillRect(40, 300-hMax, 140, hMax); // Glace carbonique } else if (temp === s.ts) { let r = Math.min(1, (energy-q1)/q2); bCtx.fillStyle = "#ccc"; bCtx.fillRect(40, 300-hMax, 140, hMax*(1-r)); if(gasParticles.length < Math.floor(r*60)) gasParticles.push({x: 110, y: 250, vx: Math.random()*2-1, vy: -Math.random()*2, r: 3}); bCtx.fillStyle = "rgba(220,220,220,0.5)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); }); } else { bCtx.fillStyle = "rgba(200,200,200,0.6)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r+1, 0, 7); bCtx.fill(); }); } } else { // Dessin standard (Solide -> Liquide -> Gaz) let q1 = masse * s.cs * (s.tf - tStart), q2 = masse * s.lf, q3 = masse * s.cl * (s.tv - s.tf); if(temp < s.tf) { bCtx.fillStyle = "#64b5f6"; bCtx.fillRect(40, 300-hMax, 140, hMax); } else if (temp === s.tf) { let r = Math.min(1, (energy-q1)/q2); bCtx.fillStyle = "#e3f2fd"; bCtx.fillRect(10, 300-(hMax*r), 200, hMax*r); bCtx.fillStyle = "#64b5f6"; bCtx.fillRect(40, 300-hMax, 140, hMax*(1-r)); } else if (temp < s.tv) { bCtx.fillStyle = "#e3f2fd"; bCtx.fillRect(10, 300-hMax, 200, hMax); } else { if(gasParticles.length < 60) gasParticles.push({x: 110, y: 200, vx: Math.random()*4-2, vy: Math.random()*4-2, r: 2.5}); bCtx.fillStyle = "rgba(180,210,255,0.5)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); }); } } gCtx.clearRect(0,0,600,420); gCtx.strokeStyle = "#444"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(60, 20); gCtx.stroke(); gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(580, 390); gCtx.stroke(); let xMax = masse * 1500000; for(let t=-200; t<=200; t+=50) { let y = 390 - ((t+200)/400)*350; gCtx.fillStyle = "#888"; gCtx.font = "10px Arial"; gCtx.fillText(t, 30, y+4); gCtx.beginPath(); gCtx.moveTo(55,y); gCtx.lineTo(60,y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = "#1565c0"; gCtx.lineWidth = 3; pts.forEach((p, i) => { let px = 60 + (p.x / xMax) * 500; let py = 390 - ((p.y + 200) / 400) * 350; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-mystere" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd; flex-wrap: wrap; gap: 15px;"> <div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;"> <div> <label style="font-weight: bold; color: #444;">Choix :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #1565c0; cursor: pointer;"> <option value="subA">Substance A</option> <option value="subB">Substance B</option> <option value="subC">Substance C</option> <option value="subD">Substance D</option> <option value="subE">Substance E</option> </select> </div> <div> <label style="font-weight: bold; color: #444;">Masse :</label> <select id="selectMasse" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; cursor: pointer;"> <option value="1">1 kg</option> <option value="2">2 kg</option> <option value="4">4 kg</option> <option value="6">6 kg</option> <option value="8">8 kg</option> <option value="10">10 kg</option> </select> </div> </div> <div id="temp-grand" style="font-size: 3.2em; font-weight: bold; color: #d32f2f; font-family: monospace; background: #fff; padding: 5px 15px; border-radius: 10px; border: 1px solid #ccc; min-width: 200px; text-align: center;">-200.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.4em; font-weight: bold; color: #1565c0; text-align: center;">-</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.2em; margin-bottom: 10px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-bottom: 8px;">ÉNERGIE (Q)</div> <div id="q-val" style="font-size: 1.6em; color: #ffeb3b; margin-bottom: 8px;">0 J</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; border-top: 1px solid #333; padding-top: 8px;">Q = m · cₛ · ΔT</div> </div> </div> <div style="flex: 2; min-width: 450px; display: flex; flex-direction: column;"> <canvas id="graphSim" width="600" height="420" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 10px; margin-top: 20px; justify-content: flex-end;"> <button id="btnPlay" onclick="toggleSim()" style="width: 160px; padding: 15px; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 1.1em; box-shadow: 0 4px #1b5e20;">DÉMARRER</button> <button onclick="resetSim()" style="padding: 15px; background: #546e7a; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const selectF = document.getElementById('selectFluide'), selectM = document.getElementById('selectMasse'); // Les données réelles sont conservées mais les noms sont masqués const db = { subA: { label: "Substance A", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114.1, tv: 78.3, colorL: "#e3f2fd", colorS: "#64b5f6" }, subB: { label: "Substance B", cs: 850, cl: 2000, cg: 840, lf: 199000, lv: 571000, tf: -56.6, tv: -78.5, colorL: "#f5f5f5", colorS: "#bdbdbd" }, subC: { label: "Substance C", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155.1, tv: -82.1, colorL: "#e0f7fa", colorS: "#4dd0e1" }, subD: { label: "Substance D", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -187.7, tv: -42.1, colorL: "#fff3e0", colorS: "#ffb74d" }, subE: { label: "Substance E", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152.2, tv: -29.4, colorL: "#f1f8e9", colorS: "#aed581" } }; let s, temp, energy, masse, isRunning = false, pts = [], blinkFrame = 0; const pwr = 4500, tStart = -200, tEnd = 200; let gasParticles = []; window.initSubstance = function() { s = db[selectF.value]; masse = parseFloat(selectM.value); temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER"; document.getElementById('btnPlay').style.background = "#2e7d32"; gasParticles = []; updateUI(); }; window.toggleSim = function() { if(temp >= tEnd && isRunning) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; window.resetSim = function() { initSubstance(); }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.label + " (" + masse + " kg)"; } function update() { if(isRunning && temp < tEnd) { blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 8) % 2 === 0) ? "#d32f2f" : "#333"; energy += pwr * 12; let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20); let q1 = masse * s.cs * (tFus - tStart); let q2 = masse * s.lf; let q3 = masse * s.cl * (tVap - tFus); let q4 = masse * s.lv; const fText = document.getElementById('formule-text'); const eText = document.getElementById('etat-text'); if (energy < q1) { temp = tStart + energy/(masse*s.cs); eText.innerText = "ÉTAT : SOLIDE"; fText.innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = tFus; eText.innerText = "ÉTAT : FUSION"; fText.innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = tFus + (energy - q1 - q2)/(masse*s.cl); eText.innerText = "ÉTAT : LIQUIDE"; fText.innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = tVap; eText.innerText = "ÉTAT : ÉBULLITION"; fText.innerHTML = "Q = m · Lv"; } else { temp = tVap + (energy - q1 - q2 - q3 - q4)/(masse*s.cg); eText.innerText = "ÉTAT : GAZ"; fText.innerHTML = "Q = m · cₚ · ΔT"; } if(temp > tEnd) { temp = tEnd; isRunning = false; } pts.push({x: energy, y: temp}); updateUI(); } else { heater.style.background = "#333"; } if(gasParticles.length > 0) { let speedFactor = 0.5 + ((temp + 200) * 0.015); gasParticles.forEach(p => { p.x += p.vx * speedFactor; p.y += p.vy * speedFactor; if(p.x < 10 || p.x > 210) p.vx *= -1; if(p.y < 10 || p.y > 290) p.vy *= -1; }); } } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 40 + (masse * 20); let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20); let q1 = masse * s.cs * (tFus - tStart), q2 = masse * s.lf, q3 = masse * s.cl * (tVap - tFus); if(temp < tFus) { bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax); } else if (temp === tFus) { let r = Math.min(1, (energy-q1)/q2); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*r), 220, hMax*r); bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax*(1-r)); } else if (temp < tVap) { bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax); } else if (temp === tVap) { let rV = Math.min(1, (energy-q1-q2-q3)/(masse*s.lv)); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*(1-rV)), 220, hMax*(1-rV)); if(gasParticles.length < Math.floor(rV*60)) { gasParticles.push({x: 110, y: 150, vx: Math.random()*3-1.5, vy: Math.random()*3-1.5, r: 2.5}); } bCtx.fillStyle = "rgba(180,210,255,0.4)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); }); } else { if(gasParticles.length < 60) gasParticles.push({x: 110, y: 150, vx: Math.random()*3-1.5, vy: Math.random()*3-1.5, r: 2.5}); bCtx.fillStyle = "rgba(160,200,255,0.6)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r+1, 0, 7); bCtx.fill(); }); } gCtx.clearRect(0,0,600,420); gCtx.strokeStyle = "#444"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(60, 20); gCtx.stroke(); gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(580, 390); gCtx.stroke(); let xMax = masse * 1500000; gCtx.fillStyle = "#000"; gCtx.font = "bold 12px Arial"; gCtx.fillText("T (°C)", 15, 25); gCtx.fillText("Énergie Q (Joules)", 480, 410); gCtx.font = "10px Arial"; gCtx.fillStyle = "#888"; for(let t=-200; t<=200; t+=50) { let y = 390 - ((t+200)/400)*350; gCtx.fillText(t, 30, y+4); gCtx.beginPath(); gCtx.moveTo(55,y); gCtx.lineTo(60,y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.colorS; gCtx.lineWidth = 3; pts.forEach((p, i) => { let px = 60 + (p.x / xMax) * 500; let py = 390 - ((p.y + 200) / 400) * 350; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-final-formule" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd; flex-wrap: wrap; gap: 15px;"> <div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;"> <div> <label style="font-weight: bold; color: #444;">Fluide :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #1565c0; cursor: pointer;"> <option value="ethanol">A : Éthanol</option> <option value="co2">B : Dioxyde de Carbone</option> <option value="r23">C : Trifluorométhane (R-23)</option> <option value="propane">D : Propane (R-290)</option> <option value="hfo">E : HFO-1234yf (Moderne)</option> </select> </div> <div> <label style="font-weight: bold; color: #444;">Masse :</label> <select id="selectMasse" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; cursor: pointer;"> <option value="1">1 kg</option> <option value="2">2 kg</option> <option value="3">3 kg</option> <option value="4">4 kg</option> <option value="5">5 kg</option> <option value="6">6 kg</option> <option value="7">7 kg</option> <option value="8">8 kg</option> <option value="9">9 kg</option> <option value="10">10 kg</option> </select> </div> </div> <div id="temp-grand" style="font-size: 3.2em; font-weight: bold; color: #d32f2f; font-family: monospace; background: #fff; padding: 5px 15px; border-radius: 10px; border: 1px solid #ccc; min-width: 200px; text-align: center;">-200.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.4em; font-weight: bold; color: #1565c0; text-align: center;">-</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.2em; margin-bottom: 10px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-bottom: 8px;">CALCUL DE L'ÉNERGIE (Q)</div> <div id="q-val" style="font-size: 1.6em; color: #ffeb3b; margin-bottom: 8px;">0 J</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; border-top: 1px solid #333; padding-top: 8px;">Q = m · cₛ · ΔT</div> </div> </div> <div style="flex: 2; min-width: 450px; display: flex; flex-direction: column;"> <canvas id="graphSim" width="600" height="420" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 10px; margin-top: 20px; justify-content: flex-end;"> <button id="btnPlay" onclick="toggleSim()" style="width: 160px; padding: 15px; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 1.1em; box-shadow: 0 4px #1b5e20;">DÉMARRER</button> <button onclick="resetSim()" style="padding: 15px; background: #546e7a; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const selectF = document.getElementById('selectFluide'), selectM = document.getElementById('selectMasse'); const db = { ethanol: { nom: "ÉTHANOL", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114.1, tv: 78.3, colorL: "#e3f2fd", colorS: "#64b5f6" }, co2: { nom: "DIOXYDE DE CARBONE", cs: 850, cl: 2000, cg: 840, lf: 199000, lv: 571000, tf: -56.6, tv: -78.5, colorL: "#f5f5f5", colorS: "#bdbdbd" }, r23: { nom: "TRIFLUOROMÉTHANE (R-23)", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155.1, tv: -82.1, colorL: "#e0f7fa", colorS: "#4dd0e1" }, propane: { nom: "PROPANE (R-290)", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -187.7, tv: -42.1, colorL: "#fff3e0", colorS: "#ffb74d" }, hfo: { nom: "HFO-1234yf", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152.2, tv: -29.4, colorL: "#f1f8e9", colorS: "#aed581" } }; let s, temp, energy, masse, isRunning = false, pts = [], blinkFrame = 0; const pwr = 4500, tStart = -200, tEnd = 200; let gasParticles = []; window.initSubstance = function() { s = db[selectF.value]; masse = parseFloat(selectM.value); temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER"; document.getElementById('btnPlay').style.background = "#2e7d32"; gasParticles = []; updateUI(); }; window.toggleSim = function() { if(temp >= tEnd && isRunning) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; window.resetSim = function() { initSubstance(); }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.nom + " (" + masse + " kg)"; } function update() { if(isRunning && temp < tEnd) { blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 8) % 2 === 0) ? "#d32f2f" : "#333"; energy += pwr * 12; let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20); let q1 = masse * s.cs * (tFus - tStart); let q2 = masse * s.lf; let q3 = masse * s.cl * (tVap - tFus); let q4 = masse * s.lv; const fText = document.getElementById('formule-text'); const eText = document.getElementById('etat-text'); if (energy < q1) { temp = tStart + energy/(masse*s.cs); eText.innerText = "ÉTAT : SOLIDE"; fText.innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = tFus; eText.innerText = "ÉTAT : FUSION"; fText.innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = tFus + (energy - q1 - q2)/(masse*s.cl); eText.innerText = "ÉTAT : LIQUIDE"; fText.innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = tVap; eText.innerText = "ÉTAT : ÉBULLITION"; fText.innerHTML = "Q = m · Lv"; } else { temp = tVap + (energy - q1 - q2 - q3 - q4)/(masse*s.cg); eText.innerText = "ÉTAT : GAZ"; fText.innerHTML = "Q = m · cₚ · ΔT"; } if(temp > tEnd) { temp = tEnd; isRunning = false; } pts.push({x: energy, y: temp}); updateUI(); } else { heater.style.background = "#333"; } if(gasParticles.length > 0) { let speedFactor = 0.5 + ((temp + 200) * 0.015); gasParticles.forEach(p => { p.x += p.vx * speedFactor; p.y += p.vy * speedFactor; if(p.x < 10 || p.x > 210) p.vx *= -1; if(p.y < 10 || p.y > 290) p.vy *= -1; }); } } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 40 + (masse * 20); let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20); let q1 = masse * s.cs * (tFus - tStart), q2 = masse * s.lf, q3 = masse * s.cl * (tVap - tFus); if(temp < tFus) { bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax); } else if (temp === tFus) { let r = Math.min(1, (energy-q1)/q2); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*r), 220, hMax*r); bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax*(1-r)); } else if (temp < tVap) { bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax); } else if (temp === tVap) { let rV = Math.min(1, (energy-q1-q2-q3)/(masse*s.lv)); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*(1-rV)), 220, hMax*(1-rV)); if(gasParticles.length < Math.floor(rV*60)) { gasParticles.push({x: 110, y: 150, vx: Math.random()*3-1.5, vy: Math.random()*3-1.5, r: 2.5}); } bCtx.fillStyle = "rgba(180,210,255,0.4)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); }); } else { if(gasParticles.length < 60) gasParticles.push({x: 110, y: 150, vx: Math.random()*3-1.5, vy: Math.random()*3-1.5, r: 2.5}); bCtx.fillStyle = "rgba(160,200,255,0.6)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r+1, 0, 7); bCtx.fill(); }); } gCtx.clearRect(0,0,600,420); gCtx.strokeStyle = "#444"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(60, 20); gCtx.stroke(); gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(580, 390); gCtx.stroke(); let xMax = masse * 1500000; gCtx.fillStyle = "#000"; gCtx.font = "bold 12px Arial"; gCtx.fillText("T (°C)", 15, 25); gCtx.fillText("Énergie Q (Joules)", 480, 410); gCtx.font = "10px Arial"; gCtx.fillStyle = "#888"; for(let t=-200; t<=200; t+=50) { let y = 390 - ((t+200)/400)*350; gCtx.fillText(t, 30, y+4); gCtx.beginPath(); gCtx.moveTo(55,y); gCtx.lineTo(60,y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.colorS; gCtx.lineWidth = 3; pts.forEach((p, i) => { let px = 60 + (p.x / xMax) * 500; let py = 390 - ((p.y + 200) / 400) * 350; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-final" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd; flex-wrap: wrap; gap: 15px;"> <div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;"> <div> <label style="font-weight: bold; color: #444;">Fluide :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #1565c0; cursor: pointer;"> <option value="ethanol">A : Éthanol</option> <option value="co2">B : Dioxyde de Carbone</option> <option value="r23">C : Trifluorométhane (R-23)</option> <option value="propane">D : Propane (R-290)</option> <option value="hfo">E : HFO-1234yf (Moderne)</option> </select> </div> <div> <label style="font-weight: bold; color: #444;">Masse :</label> <select id="selectMasse" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; cursor: pointer;"> <option value="1">1 kg</option> <option value="2">2 kg</option> <option value="4">4 kg</option> <option value="6">6 kg</option> <option value="8">8 kg</option> <option value="10">10 kg</option> </select> </div> </div> <div id="temp-grand" style="font-size: 3.2em; font-weight: bold; color: #d32f2f; font-family: monospace; background: #fff; padding: 5px 15px; border-radius: 10px; border: 1px solid #ccc; min-width: 200px; text-align: center;">-200.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.4em; font-weight: bold; color: #1565c0; text-align: center;">-</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.2em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444; text-align: center;"> <div style="color: #4db6ac; font-size: 0.8em; margin-bottom: 5px;">ÉNERGIE (Q)</div> <div id="q-val" style="font-size: 1.6em; color: #ffeb3b;">0 J</div> </div> </div> <div style="flex: 2; min-width: 450px; display: flex; flex-direction: column;"> <canvas id="graphSim" width="600" height="420" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 10px; margin-top: 20px; justify-content: flex-end;"> <button id="btnPlay" onclick="toggleSim()" style="width: 160px; padding: 15px; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 1.1em; box-shadow: 0 4px #1b5e20;">DÉMARRER</button> <button onclick="resetSim()" style="padding: 15px; background: #546e7a; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const selectF = document.getElementById('selectFluide'), selectM = document.getElementById('selectMasse'); const db = { ethanol: { nom: "ÉTHANOL", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114.1, tv: 78.3, colorL: "#e3f2fd", colorS: "#64b5f6" }, co2: { nom: "DIOXYDE DE CARBONE", cs: 850, cl: 2000, cg: 840, lf: 199000, lv: 571000, tf: -56.6, tv: -78.5, colorL: "#f5f5f5", colorS: "#bdbdbd" }, r23: { nom: "TRIFLUOROMÉTHANE (R-23)", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155.1, tv: -82.1, colorL: "#e0f7fa", colorS: "#4dd0e1" }, propane: { nom: "PROPANE (R-290)", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -187.7, tv: -42.1, colorL: "#fff3e0", colorS: "#ffb74d" }, hfo: { nom: "HFO-1234yf", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152.2, tv: -29.4, colorL: "#f1f8e9", colorS: "#aed581" } }; let s, temp, energy, masse, isRunning = false, pts = [], blinkFrame = 0; const pwr = 4500, tStart = -200, tEnd = 200; let gasParticles = []; window.initSubstance = function() { s = db[selectF.value]; masse = parseFloat(selectM.value); temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER"; document.getElementById('btnPlay').style.background = "#2e7d32"; gasParticles = []; updateUI(); }; window.toggleSim = function() { if(temp >= tEnd && isRunning) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; window.resetSim = function() { initSubstance(); }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.nom + " (" + masse + " kg)"; } function update() { if(isRunning && temp < tEnd) { blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 8) % 2 === 0) ? "#d32f2f" : "#333"; energy += pwr * 12; // Vitesse de simulation adaptée aux fortes masses let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20); let q1 = masse * s.cs * (tFus - tStart); let q2 = masse * s.lf; let q3 = masse * s.cl * (tVap - tFus); let q4 = masse * s.lv; if (energy < q1) { temp = tStart + energy/(masse*s.cs); document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; } else if (energy < q1 + q2) { temp = tFus; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; } else if (energy < q1 + q2 + q3) { temp = tFus + (energy - q1 - q2)/(masse*s.cl); document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; } else if (energy < q1 + q2 + q3 + q4) { temp = tVap; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; } else { temp = tVap + (energy - q1 - q2 - q3 - q4)/(masse*s.cg); document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; } if(temp > tEnd) { temp = tEnd; isRunning = false; } pts.push({x: energy, y: temp}); updateUI(); } else { heater.style.background = "#333"; } // Agitation thermique (perpétuelle) if(gasParticles.length > 0) { let speedFactor = 0.5 + ((temp + 200) * 0.015); gasParticles.forEach(p => { p.x += p.vx * speedFactor; p.y += p.vy * speedFactor; if(p.x < 10 || p.x > 210) p.vx *= -1; if(p.y < 10 || p.y > 290) p.vy *= -1; }); } } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 40 + (masse * 20); let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20); let q1 = masse * s.cs * (tFus - tStart), q2 = masse * s.lf, q3 = masse * s.cl * (tVap - tFus); if(temp < tFus) { bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax); } else if (temp === tFus) { let r = Math.min(1, (energy-q1)/q2); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*r), 220, hMax*r); bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax*(1-r)); } else if (temp < tVap) { bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax); } else if (temp === tVap) { let rV = Math.min(1, (energy-q1-q2-q3)/(masse*s.lv)); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*(1-rV)), 220, hMax*(1-rV)); if(gasParticles.length < Math.floor(rV*60)) { gasParticles.push({x: 110, y: 150, vx: Math.random()*3-1.5, vy: Math.random()*3-1.5, r: 2.5}); } bCtx.fillStyle = "rgba(180,210,255,0.4)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); }); } else { if(gasParticles.length < 60) gasParticles.push({x: 110, y: 150, vx: Math.random()*3-1.5, vy: Math.random()*3-1.5, r: 2.5}); bCtx.fillStyle = "rgba(160,200,255,0.6)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r+1, 0, 7); bCtx.fill(); }); } gCtx.clearRect(0,0,600,420); gCtx.strokeStyle = "#444"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(60, 20); gCtx.stroke(); gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(580, 390); gCtx.stroke(); // X-Max dynamique : s'ajuste à la masse pour que le graphique soit toujours beau let xMax = masse * 1500000; gCtx.fillStyle = "#000"; gCtx.font = "bold 12px Arial"; gCtx.fillText("T (°C)", 15, 25); gCtx.fillText("Énergie Q (Joules)", 480, 410); gCtx.font = "10px Arial"; gCtx.fillStyle = "#888"; for(let t=-200; t<=200; t+=50) { let y = 390 - ((t+200)/400)*350; gCtx.fillText(t, 30, y+4); gCtx.beginPath(); gCtx.moveTo(55,y); gCtx.lineTo(60,y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.colorS; gCtx.lineWidth = 3; pts.forEach((p, i) => { let px = 60 + (p.x / xMax) * 500; let py = 390 - ((p.y + 200) / 400) * 350; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-mass" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;"> <div style="display: flex; gap: 15px; align-items: center;"> <label style="font-weight: bold; color: #555;">Substance :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #1565c0; min-width: 250px;"> <option value="ethanol">A : Éthanol</option> <option value="co2">B : Dioxyde de Carbone</option> <option value="r23">C : Trifluorométhane (R-23)</option> <option value="propane">D : Propane (R-290)</option> <option value="hfo">E : HFO-1234yf (Moderne)</option> </select> </div> <div id="temp-grand" style="font-size: 3.2em; font-weight: bold; color: #d32f2f; font-family: monospace; min-width: 220px; text-align: right;">-300.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.6em; font-weight: bold; color: #1565c0; text-align: center;">-</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.3em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · c · ΔT</div> </div> </div> <div style="flex: 2; min-width: 450px; display: flex; flex-direction: column;"> <canvas id="graphSim" width="600" height="420" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 10px; margin-top: 20px; align-items: center; justify-content: flex-end; background: #f8f9fa; padding: 10px; border-radius: 12px;"> <div style="display: flex; align-items: center; gap: 8px; margin-right: auto;"> <span style="font-weight: bold; color: #666;">Masse :</span> <select id="selectMasse" onchange="initSubstance()" style="padding: 8px; border-radius: 6px; border: 1px solid #ccc; font-weight: bold;"> <option value="0.5">0.5 kg</option> <option value="1.0" selected>1.0 kg</option> <option value="1.5">1.5 kg</option> <option value="2.0">2.0 kg</option> <option value="3.0">3.0 kg</option> </select> </div> <button id="btnPlay" onclick="toggleSim()" style="width: 130px; padding: 12px; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 8px; cursor: pointer;">DÉMARRER</button> <button onclick="resetSim()" style="padding: 12px; background: #546e7a; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">RAZ</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const selectF = document.getElementById('selectFluide'); const selectM = document.getElementById('selectMasse'); const db = { ethanol: { nom: "ÉTHANOL", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114.1, tv: 78.3, colorL: "#e3f2fd", colorS: "#64b5f6" }, co2: { nom: "DIOXYDE DE CARBONE", cs: 850, cl: 2000, cg: 840, lf: 199000, lv: 571000, tf: -56.6, tv: -78.5, colorL: "#f5f5f5", colorS: "#bdbdbd" }, r23: { nom: "TRIFLUOROMÉTHANE (R-23)", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155.1, tv: -82.1, colorL: "#e0f7fa", colorS: "#4dd0e1" }, propane: { nom: "PROPANE (R-290)", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -187.7, tv: -42.1, colorL: "#fff3e0", colorS: "#ffb74d" }, hfo: { nom: "HFO-1234yf", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152.2, tv: -29.4, colorL: "#f1f8e9", colorS: "#aed581" } }; let s, temp, energy, masse, isRunning = false, pts = [], blinkFrame = 0; const pwr = 4500; const tStart = -300, tEnd = 200; let gasParticles = []; const numGasMax = 60; window.initSubstance = function() { s = db[selectF.value]; masse = parseFloat(selectM.value); temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER"; document.getElementById('btnPlay').style.background = "#2e7d32"; gasParticles = []; updateUI(); }; window.toggleSim = function() { if(temp >= tEnd && isRunning) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; window.resetSim = function() { initSubstance(); }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.nom + " (" + masse + "kg)"; } function addGasParticle() { gasParticles.push({ x: Math.random() * 200 + 10, y: Math.random() * 290 + 5, vx: (Math.random() - 0.5) * 4, vy: (Math.random() - 0.5) * 4, r: 2.5 }); } function update() { if(isRunning && temp < tEnd) { blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#d32f2f" : "#333"; energy += pwr * 4; let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20); let q1 = masse * s.cs * (tFus - tStart); let q2 = masse * s.lf; let q3 = masse * s.cl * (tVap - tFus); let q4 = masse * s.lv; if (energy < q1) { temp = tStart + energy/(masse*s.cs); document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; } else if (energy < q1 + q2) { temp = tFus; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; } else if (energy < q1 + q2 + q3) { temp = tFus + (energy - q1 - q2)/(masse*s.cl); document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; } else if (energy < q1 + q2 + q3 + q4) { temp = tVap; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; } else { temp = tVap + (energy - q1 - q2 - q3 - q4)/(masse*s.cg); document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; } if(temp > tEnd) { temp = tEnd; isRunning = false; } pts.push({x: energy, y: temp}); updateUI(); } else { heater.style.background = "#333"; } if(gasParticles.length > 0) { let speed = 0.5 + (Math.max(0, temp - s.tv + 100) * 0.02); gasParticles.forEach(p => { p.x += p.vx * speed; p.y += p.vy * speed; if(p.x < 10 || p.x > 210) p.vx *= -1; if(p.y < 10 || p.y > 290) p.vy *= -1; }); } } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 60 + (masse * 40); // La hauteur du fluide dépend de la masse let tFus = s.tf, tVap = Math.max(s.tv, tFus + 20); let q1 = masse * s.cs * (tFus - tStart), q2 = masse * s.lf, q3 = masse * s.cl * (tVap - tFus); if(temp < tFus) { bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax); } else if (temp === tFus) { let r = Math.min(1, (energy-q1)/q2); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*r), 220, hMax*r); bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax*(1-r)); } else if (temp < tVap) { bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax); } else if (temp === tVap) { let rV = Math.min(1, (energy-q1-q2-q3)/(masse*s.lv)); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax*(1-rV)), 220, hMax*(1-rV)); while(gasParticles.length < Math.floor(rV*numGasMax)) addGasParticle(); bCtx.fillStyle = "rgba(200,220,255,0.4)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); }); } else { if(gasParticles.length < numGasMax) while(gasParticles.length < numGasMax) addGasParticle(); bCtx.fillStyle = "rgba(180,210,255,0.6)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r+1, 0, 7); bCtx.fill(); }); } // GRAPHIQUE - Échelle dynamique sur X (énergie) gCtx.clearRect(0,0,600,420); gCtx.strokeStyle = "#444"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(60, 20); gCtx.stroke(); // Y gCtx.beginPath(); gCtx.moveTo(60, 390); gCtx.lineTo(580, 390); gCtx.stroke(); // X let xMax = 6000000; // Adapté aux grosses masses gCtx.fillStyle = "#000"; gCtx.font = "bold 12px Arial"; gCtx.fillText("T (°C)", 15, 25); gCtx.fillText("Q (Joules)", 520, 410); gCtx.font = "10px Arial"; gCtx.fillStyle = "#888"; for(let t=-300; t<=200; t+=50) { let y = 390 - ((t+300)/500)*350; gCtx.fillText(t, 30, y+4); gCtx.beginPath(); gCtx.moveTo(55,y); gCtx.lineTo(60,y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.colorS; gCtx.lineWidth = 3; pts.forEach((p, i) => { let px = 60 + (p.x / xMax) * 500; let py = 390 - ((p.y + 300) / 500) * 350; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-v3" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; flex-direction: column; gap: 15px; margin-bottom: 20px; background: #f8f9fa; padding: 20px; border-radius: 12px; border: 1px solid #ddd;"> <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;"> <div style="display: flex; gap: 10px; align-items: center;"> <label style="font-weight: bold; color: #333;">Substance :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 220px;"> <option value="ethanol">A : Éthanol</option> <option value="co2">B : Dioxyde de Carbone</option> <option value="r23">C : Trifluorométhane (R-23)</option> <option value="propane">D : Propane (R-290)</option> <option value="hfo">E : HFO-1234yf (Moderne)</option> </select> </div> <div style="flex-grow: 1; max-width: 400px; display: flex; flex-direction: column; gap: 5px;"> <div style="display: flex; justify-content: space-between;"> <label style="font-weight: bold; color: #d32f2f;">Puissance de chauffe (P) :</label> <span id="pwr-val" style="font-weight: bold; color: #d32f2f;">2500 W</span> </div> <input type="range" id="pwrSlider" min="1000" max="5000" step="500" value="2500" oninput="updatePower()" style="width: 100%; cursor: pointer;"> </div> <div id="temp-grand" style="font-size: 3em; font-weight: bold; color: #333; font-family: monospace; background: #eee; padding: 5px 15px; border-radius: 8px; border: 2px solid #ccc;">-300.0 °C</div> </div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 30px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: bold; margin-left: -5px; transition: background 0.2s; z-index: 1;">PLAQUE CHAUFFANTE</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.6em; font-weight: bold; color: #1565c0; text-align: center;">-</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · c · ΔT</div> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER</button> <button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const pwrSlider = document.getElementById('pwrSlider'); const pwrLabel = document.getElementById('pwr-val'); const db = { ethanol: { nom: "ÉTHANOL", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114.1, tv: 78.3, colorL: "#e3f2fd", colorS: "#64b5f6", maxQ: 2800000 }, co2: { nom: "DIOXYDE DE CARBONE", cs: 850, cl: 2000, cg: 840, lf: 199000, lv: 571000, tf: -56.6, tv: -78.5, colorL: "#f5f5f5", colorS: "#bdbdbd", maxQ: 2000000 }, r23: { nom: "TRIFLUOROMÉTHANE (R-23)", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155.1, tv: -82.1, colorL: "#e0f7fa", colorS: "#4dd0e1", maxQ: 1800000 }, propane: { nom: "PROPANE (R-290)", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -187.7, tv: -42.1, colorL: "#fff3e0", colorS: "#ffb74d", maxQ: 2200000 }, hfo: { nom: "HFO-1234yf", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152.2, tv: -29.4, colorL: "#f1f8e9", colorS: "#aed581", maxQ: 1800000 } }; let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0; let currentPwr = 2500; const tStart = -300, tEnd = 200; let gasParticles = []; const numGasMax = 70; window.updatePower = function() { currentPwr = parseInt(pwrSlider.value); pwrLabel.innerText = currentPwr + " W"; }; window.initSubstance = function() { s = db[document.getElementById('selectFluide').value]; temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER"; document.getElementById('btnPlay').style.background = "#2e7d32"; gasParticles = []; updateUI(); }; window.toggleSim = function() { if(temp >= tEnd && isRunning) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; window.resetSim = function() { initSubstance(); }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.nom; } function addGasParticle() { gasParticles.push({ x: Math.random() * 200 + 10, y: Math.random() * 290 + 5, vx: (Math.random() - 0.5) * 4, vy: (Math.random() - 0.5) * 4, r: Math.random() * 2 + 2 }); } function update() { if(isRunning && temp < tEnd) { blinkFrame++; // L'intensité du rouge de la plaque dépend de la puissance let intensity = Math.floor(100 + (currentPwr/5000)*155); heater.style.background = (Math.floor(blinkFrame / 8) % 2 === 0) ? `rgb(${intensity}, 40, 40)` : "#333"; energy += currentPwr * 3.5; // Vitesse d'exécution let tFusion = s.tf; let tVap = Math.max(s.tv, tFusion + 20); // Correction visuelle pour CO2 let q1 = 1 * s.cs * (tFusion - tStart); let q2 = 1 * s.lf; let q3 = 1 * s.cl * (tVap - tFusion); let q4 = 1 * s.lv; if (energy < q1) { temp = tStart + energy/s.cs; document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = tFusion; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = tFusion + (energy - q1 - q2)/s.cl; document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = tVap; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = tVap + (energy - q1 - q2 - q3 - q4)/s.cg; document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } if(temp > tEnd) { temp = tEnd; isRunning = false; } pts.push({x: energy, y: temp}); updateUI(); } else { heater.style.background = "#333"; } if(gasParticles.length > 0) { let speedFactor = 0.4 + (Math.max(0, temp - s.tv + 150) * 0.015); gasParticles.forEach(p => { p.x += p.vx * speedFactor; p.y += p.vy * speedFactor; if(p.x < 8 || p.x > 212) p.vx *= -1; if(p.y < 5 || p.y > 295) p.vy *= -1; }); } } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 180; let tFusion = s.tf; let tVap = Math.max(s.tv, tFusion + 20); let q1 = 1 * s.cs * (tFusion - tStart); let q2 = 1 * s.lf; let q3 = 1 * s.cl * (tVap - tFusion); if(temp < tFusion) { bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax); } else if (temp === tFusion) { let ratio = Math.min(1, (energy - q1) / q2); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio); bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300 - (hMax * (1-ratio)), 160, hMax * (1-ratio)); } else if (temp < tVap) { bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax); } else if (temp === tVap) { let ratioV = Math.min(1, (energy - q1 - q2 - q3) / s.lv); let currentH = hMax * (1 - ratioV); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-currentH, 220, currentH); let target = Math.floor(ratioV * numGasMax); while(gasParticles.length < target) addGasParticle(); bCtx.fillStyle = "rgba(200,220,255,0.5)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); }); } else { if(gasParticles.length < numGasMax) while(gasParticles.length < numGasMax) addGasParticle(); bCtx.fillStyle = "rgba(180,210,255,0.6)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r + 0.5, 0, 7); bCtx.fill(); }); } // GRAPHIQUE gCtx.clearRect(0,0,600,450); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 420); gCtx.lineTo(60, 20); gCtx.lineTo(55, 30); gCtx.moveTo(60, 20); gCtx.lineTo(65, 30); gCtx.stroke(); // Y gCtx.beginPath(); gCtx.moveTo(40, 400); gCtx.lineTo(580, 400); gCtx.lineTo(570, 395); gCtx.moveTo(580, 400); gCtx.lineTo(570, 405); gCtx.stroke(); // X gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (°C)", 20, 25); gCtx.fillText("Q (J)", 560, 425); gCtx.font = "10px Arial"; gCtx.fillStyle = "#666"; for(let t = -300; t <= 200; t += 50) { let y = 400 - ((t - tStart) / 500) * 340; gCtx.fillText(t, 30, y + 5); gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(60, y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.colorS; gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - tStart) / 500) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-cryo" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;"> <div style="display: flex; gap: 10px; align-items: center;"> <label style="font-weight: bold; color: #555;">Substance :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 250px;"> <option value="ethanol">A : Éthanol</option> <option value="co2">B : Dioxyde de Carbone</option> <option value="r23">C : Trifluorométhane (R-23)</option> <option value="propane">D : Propane (R-290)</option> <option value="hfo">E : HFO-1234yf (Moderne)</option> </select> </div> <div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-200.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.6em; font-weight: bold; color: #1565c0; text-align: center;">-</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER</button> <button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const select = document.getElementById('selectFluide'); const db = { ethanol: { nom: "ÉTHANOL", cs: 2420, cl: 2460, cg: 1700, lf: 109000, lv: 835000, tf: -114.1, tv: 78.3, colorL: "#e3f2fd", colorS: "#64b5f6", maxQ: 2500000 }, co2: { nom: "DIOXYDE DE CARBONE", cs: 850, cl: 2000, cg: 840, lf: 199000, lv: 571000, tf: -56.6, tv: -78.5, colorL: "#f5f5f5", colorS: "#bdbdbd", maxQ: 1800000 }, // tv < tf car sublimation, mais on inverse pour simu r23: { nom: "TRIFLUOROMÉTHANE (R-23)", cs: 1000, cl: 1500, cg: 700, lf: 110000, lv: 240000, tf: -155.1, tv: -82.1, colorL: "#e0f7fa", colorS: "#4dd0e1", maxQ: 1500000 }, propane: { nom: "PROPANE (R-290)", cs: 1600, cl: 2400, cg: 1600, lf: 79000, lv: 425000, tf: -187.7, tv: -42.1, colorL: "#fff3e0", colorS: "#ffb74d", maxQ: 2000000 }, hfo: { nom: "HFO-1234yf", cs: 1100, cl: 1390, cg: 900, lf: 100000, lv: 180000, tf: -152.2, tv: -29.4, colorL: "#f1f8e9", colorS: "#aed581", maxQ: 1500000 } }; let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0; const pwr = 5000, tStart = -200, tEnd = 200; let gasParticles = []; const numGasMax = 70; window.initSubstance = function() { s = db[select.value]; temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER"; document.getElementById('btnPlay').style.background = "#2e7d32"; gasParticles = []; updateUI(); }; window.toggleSim = function() { if(temp >= tEnd && isRunning) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; window.resetSim = function() { initSubstance(); }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.nom; } function addGasParticle() { gasParticles.push({ x: Math.random() * 200 + 10, y: Math.random() * 290 + 5, vx: (Math.random() - 0.5) * 4, vy: (Math.random() - 0.5) * 4, r: Math.random() * 2 + 2 }); } function update() { if(isRunning && temp < tEnd) { blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c"; energy += pwr * 2.5; let tFusion = s.tf; let tVap = s.tv; if(tVap < tFusion) tVap = tFusion + 20; // Correctif pour CO2 en simu liquide let q1 = 1 * s.cs * (tFusion - tStart); let q2 = 1 * s.lf; let q3 = 1 * s.cl * (tVap - tFusion); let q4 = 1 * s.lv; if (energy < q1) { temp = tStart + energy/s.cs; document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = tFusion; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = tFusion + (energy - q1 - q2)/s.cl; document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = tVap; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = tVap + (energy - q1 - q2 - q3 - q4)/s.cg; document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } if(temp > tEnd) { temp = tEnd; isRunning = false; } pts.push({x: energy, y: temp}); updateUI(); } else { heater.style.background = "#333"; } // Agitation thermique persistante if(gasParticles.length > 0) { let tBase = s.tv; let speedFactor = 0.5 + (Math.max(0, temp - tBase + 100) * 0.02); gasParticles.forEach(p => { p.x += p.vx * speedFactor; p.y += p.vy * speedFactor; if(p.x < 8 || p.x > 212) p.vx *= -1; if(p.y < 5 || p.y > 295) p.vy *= -1; }); } } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 180; let tFusion = s.tf; let tVap = Math.max(s.tv, s.tf + 20); let q1 = 1 * s.cs * (tFusion - tStart); let q2 = 1 * s.lf; let q3 = 1 * s.cl * (tVap - tFusion); if(temp < tFusion) { bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax); } else if (temp === tFusion) { let ratio = Math.min(1, (energy - q1) / q2); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio); bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300 - (hMax * (1-ratio)), 160, hMax * (1-ratio)); } else if (temp < tVap) { bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax); } else if (temp === tVap) { let ratioV = Math.min(1, (energy - q1 - q2 - q3) / s.lv); let currentH = hMax * (1 - ratioV); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-currentH, 220, currentH); let target = Math.floor(ratioV * numGasMax); while(gasParticles.length < target) addGasParticle(); bCtx.fillStyle = "rgba(200,220,255,0.5)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); }); } else { if(gasParticles.length < numGasMax) while(gasParticles.length < numGasMax) addGasParticle(); bCtx.fillStyle = "rgba(180,210,255,0.6)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r + 0.5, 0, 7); bCtx.fill(); }); } // GRAPHIQUE gCtx.clearRect(0,0,600,450); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 420); gCtx.lineTo(60, 20); gCtx.stroke(); // Y gCtx.beginPath(); gCtx.moveTo(40, 400); gCtx.lineTo(580, 400); gCtx.stroke(); // X gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (°C)", 20, 25); gCtx.fillText("Q (J)", 560, 425); gCtx.font = "10px Arial"; gCtx.fillStyle = "#666"; for(let t = -200; t <= 200; t += 50) { let y = 400 - ((t - tStart) / 400) * 340; gCtx.fillText(t, 35, y + 5); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.colorS; gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - tStart) / 400) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-physics-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;"> <div style="display: flex; gap: 10px; align-items: center;"> <label style="font-weight: bold; color: #555;">Substance :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;"> <option value="eau">Eau (H₂O)</option> <option value="ammoniac">Ammoniac (NH₃)</option> <option value="isobutane">Isobutane (C₄H₁₀)</option> <option value="difluoro">Difluorométhane (R-32)</option> </select> </div> <div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-200.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; transition: background 0.3s; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button> <button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const select = document.getElementById('selectFluide'); const db = { eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, colorL: "#e1f5fe", colorS: "#4fc3f7", maxQ: 4800000 }, ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, colorL: "#e8f5e9", colorS: "#81c784", maxQ: 3800000 }, isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, colorL: "#fff3e0", colorS: "#ffb74d", maxQ: 2500000 }, difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, colorL: "#e0f2f1", colorS: "#4db6ac", maxQ: 2200000 } }; let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0; const pwr = 4500, masse = 1, tStart = -200, tEnd = 200; let gasParticles = []; const numGasMax = 65; window.initSubstance = function() { s = db[select.value]; temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION"; document.getElementById('btnPlay').style.background = "#2e7d32"; heater.style.background = "#333"; gasParticles = []; updateUI(); }; window.toggleSim = function() { if(temp >= tEnd && isRunning) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.nom; } function addGasParticle() { gasParticles.push({ x: Math.random() * 200 + 10, y: Math.random() * 290 + 5, vx: (Math.random() - 0.5) * 3.5, vy: (Math.random() - 0.5) * 3.5, r: Math.random() * 2.5 + 2 }); } function update() { // GESTION DU CALCUL THERMIQUE (seulement si isRunning) if(isRunning && temp < tEnd) { blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c"; energy += pwr * 2.8; let q1 = 1 * s.cs * (s.tf - tStart); let q2 = 1 * s.lf; let q3 = 1 * s.cl * (s.tv - s.tf); let q4 = 1 * s.lv; if (energy < q1) { temp = tStart + energy/s.cs; document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.tf; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = s.tf + (energy - q1 - q2)/s.cl; document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = s.tv; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy - q1 - q2 - q3 - q4)/s.cg; document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } if(temp > tEnd) { temp = tEnd; isRunning = false; } pts.push({x: energy, y: temp}); updateUI(); } else { heater.style.background = "#333"; } // ANIMATION DES MOLÉCULES (Indépendante de isRunning pour le mouvement perpétuel) if(gasParticles.length > 0) { let tDiff = Math.max(0, temp - s.tv); let speedFactor = 1.0 + (tDiff * 0.04); gasParticles.forEach(p => { p.x += p.vx * speedFactor; p.y += p.vy * speedFactor; if(p.x < 8 || p.x > 212) p.vx *= -1; if(p.y < 5 || p.y > 295) p.vy *= -1; }); } } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 180; let q1 = 1 * s.cs * (s.tf - tStart); let q2 = 1 * s.lf; let q3 = 1 * s.cl * (s.tv - s.tf); if(temp < s.tf) { bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax); } else if (temp === s.tf) { let ratio = (energy - q1) / q2; bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio); bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300 - (hMax * (1-ratio)), 160, hMax * (1-ratio)); } else if(temp < s.tv) { bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax); } else if (temp === s.tv) { let ratioV = (energy - q1 - q2 - q3) / s.lv; let currentLiquidH = hMax * (1 - ratioV); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-currentLiquidH, 220, currentLiquidH); let targetParticles = Math.floor(ratioV * numGasMax); while(gasParticles.length < targetParticles) addGasParticle(); bCtx.fillStyle = "rgba(230,235,255, 0.45)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, 7); bCtx.fill(); }); if(isRunning) { bCtx.fillStyle = "rgba(255,255,255,0.7)"; for(let i=0; i<8; i++) { let bx = Math.random()*200 + 5; let by = (300-currentLiquidH) + Math.random()*currentLiquidH; bCtx.beginPath(); bCtx.arc(bx, by, Math.random()*3+1, 0, 7); bCtx.fill(); } } } else { if(gasParticles.length < numGasMax) { while(gasParticles.length < numGasMax) addGasParticle(); } bCtx.fillStyle = "rgba(215,225,255, 0.6)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r + 0.5, 0, 7); bCtx.fill(); }); } // GRAPHIQUE gCtx.clearRect(0,0,600,450); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 420); gCtx.lineTo(60, 20); gCtx.lineTo(55, 30); gCtx.moveTo(60, 20); gCtx.lineTo(65, 30); gCtx.stroke(); gCtx.beginPath(); gCtx.moveTo(40, 400); gCtx.lineTo(580, 400); gCtx.lineTo(570, 395); gCtx.moveTo(580, 400); gCtx.lineTo(570, 405); gCtx.stroke(); gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (°C)", 20, 25); gCtx.fillText("Q (J)", 560, 430); gCtx.font = "10px Arial"; gCtx.fillStyle = "#666"; for(let t = -200; t <= 200; t += 50) { let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340; gCtx.fillText(t, 35, y + 5); gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.colorS; gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-physics-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;"> <div style="display: flex; gap: 10px; align-items: center;"> <label style="font-weight: bold; color: #555;">Substance :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;"> <option value="eau">Eau (H₂O)</option> <option value="ammoniac">Ammoniac (NH₃)</option> <option value="isobutane">Isobutane (C₄H₁₀)</option> <option value="difluoro">Difluorométhane (R-32)</option> </select> </div> <div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-200.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; transition: background 0.3s; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button> <button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const select = document.getElementById('selectFluide'); // Config des couleurs douces (colorS = Solide moyen / colorL = Liquide très clair) const db = { eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, colorL: "#e1f5fe", colorS: "#4fc3f7", maxQ: 4800000 }, ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, colorL: "#e8f5e9", colorS: "#81c784", maxQ: 3800000 }, isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, colorL: "#fff3e0", colorS: "#ffb74d", maxQ: 2500000 }, difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, colorL: "#e0f2f1", colorS: "#4db6ac", maxQ: 2200000 } }; let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0; const pwr = 4500, masse = 1, tStart = -200, tEnd = 200; // Structure pour gérer les molécules de gaz animées let gasParticles = []; const numGasMax = 60; // Nombre max de molécules quand tout est vaporisé window.initSubstance = function() { s = db[select.value]; temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION"; document.getElementById('btnPlay').style.background = "#2e7d32"; heater.style.background = "#333"; gasParticles = []; // Réinit molécules updateUI(); }; window.resetSim = function() { initSubstance(); }; window.toggleSim = function() { if(temp >= tEnd) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.nom; } function update() { if(!isRunning) return; if(temp >= tEnd) { isRunning = false; heater.style.background = "#333"; return; } blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c"; energy += pwr * 2.8; let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0; let q2 = (s.tf > tStart) ? masse * s.lf : 0; let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf)); let q4 = masse * s.lv; // --- GESTION DE LA PHYSIQUE ET DES ÉTATS --- if (energy < q1) { temp = tStart + energy/(masse*s.cs); document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.tf; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = Math.max(tStart, s.tf) + (energy - q1 - q2)/(masse*s.cl); document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = s.tv; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg); document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } if(temp > tEnd) temp = tEnd; pts.push({x: energy, y: temp}); updateUI(); // --- MISE À JOUR DE L'AGITATION DES MOLÉCULES DE GAZ --- if(gasParticles.length > 0) { // Facteur de vitesse : augmente avec la température au-delà de tv let tDiff = Math.max(0, temp - s.tv); let speedFactor = 1.0 + (tDiff * 0.05); // Plus il fait chaud, plus ça va vite gasParticles.forEach(p => { p.x += p.vx * speedFactor; p.y += p.vy * speedFactor; // Rebond sur les parois if(p.x < 10 || p.x > 210) p.vx *= -1; if(p.y < 5 || p.y > 295) p.vy *= -1; }); } } // Fonction pour ajouter une molécule de gaz (initialisation aléatoire) function addGasParticle() { gasParticles.push({ x: Math.random() * 200 + 10, y: Math.random() * 290 + 5, vx: (Math.random() - 0.5) * 4, vy: (Math.random() - 0.5) * 4, r: Math.random() * 3 + 2 }); } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 180; let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0; let q2 = (s.tf > tStart) ? masse * s.lf : 0; let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf)); // --- DESSIN DU BÉCHER ET DE LA MATIÈRE --- if(temp < s.tf) { bCtx.fillStyle = s.colorS; bCtx.fillRect(30, 300-hMax, 160, hMax); // Solide pur (tons proches) } else if (temp === s.tf) { // FUSION PROGRESSIVE let ratio = (energy - q1) / s.lf; bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio); bCtx.fillStyle = s.colorS; // Solide diminue par le haut bCtx.fillRect(30, 300 - (hMax * (1-ratio)), 160, hMax * (1-ratio)); } else if(temp < s.tv) { bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax); // Liquide très clair } else if (temp === s.tv) { // ÉBULLITION : Niveau baisse, de plus en plus de molécules let ratioV = (energy - q1 - q2 - q3) / s.lv; let currentLiquidH = hMax * (1 - ratioV); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-currentLiquidH, 220, currentLiquidH); // Ajouter progressivement des molécules au gaz let targetParticles = Math.floor(ratioV * numGasMax); while(gasParticles.length < targetParticles) { addGasParticle(); } // Dessiner les molécules de gaz claires bCtx.fillStyle = "rgba(230,235,255, 0.4)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r, 0, Math.PI*2); bCtx.fill(); }); // Bulles d'ébullition dans le liquide bCtx.fillStyle = "rgba(255,255,255,0.7)"; for(let i=0; i<10; i++) { let bx = Math.random()*200 + 5; let by = (300-currentLiquidH) + Math.random()*currentLiquidH; bCtx.beginPath(); bCtx.arc(bx, by, Math.random()*3+1, 0, Math.PI*2); bCtx.fill(); } } else { // GAZ TOTAL : Agitation maximale (dépend de la vitesse gérée dans update) if(gasParticles.length < numGasMax) { while(gasParticles.length < numGasMax) addGasParticle(); } bCtx.fillStyle = "rgba(220,230,255, 0.6)"; gasParticles.forEach(p => { bCtx.beginPath(); bCtx.arc(p.x, p.y, p.r + 1, 0, Math.PI*2); bCtx.fill(); }); } // --- DESSIN DU GRAPHIQUE --- gCtx.clearRect(0,0,600,450); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; // Axe Y (Température) gCtx.beginPath(); gCtx.moveTo(60, 420); gCtx.lineTo(60, 20); // Ligne gCtx.lineTo(55, 30); gCtx.moveTo(60, 20); gCtx.lineTo(65, 30); // Flèche gCtx.stroke(); // Axe X (Énergie) gCtx.beginPath(); gCtx.moveTo(40, 400); gCtx.lineTo(580, 400); // Ligne gCtx.lineTo(570, 395); gCtx.moveTo(580, 400); gCtx.lineTo(570, 405); // Flèche gCtx.stroke(); // Labels Axes gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (°C)", 20, 25); gCtx.fillText("Q (J)", 560, 430); gCtx.font = "10px Arial"; gCtx.fillStyle = "#666"; for(let t = -200; t <= 200; t += 50) { let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340; gCtx.fillText(t, 35, y + 5); gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.colorS; // Utilise la couleur moyenne gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;"> <div style="display: flex; gap: 10px; align-items: center;"> <label style="font-weight: bold; color: #555;">Substance :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;"> <option value="eau">Eau (H₂O)</option> <option value="ammoniac">Ammoniac (NH₃)</option> <option value="isobutane">Isobutane (C₄H₁₀)</option> <option value="difluoro">Difluorométhane (R-32)</option> </select> </div> <div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-200.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button> <button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const select = document.getElementById('selectFluide'); // Configuration des couleurs harmonisées (Sombre pour Solide / Clair pour Liquide) const db = { eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, colorL: "#4fc3f7", colorS: "#0d47a1", maxQ: 4800000 }, ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, colorL: "#81c784", colorS: "#1b5e20", maxQ: 3800000 }, isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, colorL: "#ffb74d", colorS: "#a0522d", maxQ: 2500000 }, difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, colorL: "#4db6ac", colorS: "#004d40", maxQ: 2200000 } }; let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0; const pwr = 4500, tStart = -200, tEnd = 200; window.initSubstance = function() { s = db[select.value]; temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION"; document.getElementById('btnPlay').style.background = "#2e7d32"; heater.style.background = "#333"; updateUI(); }; window.resetSim = function() { initSubstance(); }; window.toggleSim = function() { if(temp >= tEnd) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.nom; } function update() { if(!isRunning) return; if(temp >= tEnd) { isRunning = false; heater.style.background = "#333"; return; } blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c"; energy += pwr * 3.0; let q1 = 1 * s.cs * (s.tf - tStart); let q2 = 1 * s.lf; let q3 = 1 * s.cl * (s.tv - s.tf); let q4 = 1 * s.lv; if (energy < q1) { temp = tStart + energy/s.cs; document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.tf; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = s.tf + (energy - q1 - q2)/s.cl; document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = s.tv; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy - q1 - q2 - q3 - q4)/s.cg; document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } if(temp > tEnd) temp = tEnd; pts.push({x: energy, y: temp}); updateUI(); } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 180; let q1 = 1 * s.cs * (s.tf - tStart); let q2 = 1 * s.lf; let q3 = 1 * s.cl * (s.tv - s.tf); if(temp < s.tf) { bCtx.fillStyle = s.colorS; bCtx.fillRect(35, 300-hMax, 150, hMax); } else if (temp === s.tf) { let ratio = (energy - q1) / q2; bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio); bCtx.fillStyle = s.colorS; bCtx.fillRect(35, 300 - (hMax * (1-ratio)), 150, hMax * (1-ratio)); } else if(temp < s.tv) { bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-hMax, 220, hMax); } else if (temp === s.tv) { let ratioV = (energy - q1 - q2 - q3) / (1 * s.lv); let currentLiquidH = hMax * (1 - ratioV); bCtx.fillStyle = s.colorL; bCtx.fillRect(0, 300-currentLiquidH, 220, currentLiquidH); // Gaz particules claires for(let i=0; i<30; i++) { let pOpacity = ratioV * 0.4; bCtx.fillStyle = "rgba(230,235,255," + pOpacity + ")"; let px = Math.random()*210; let py = Math.random()*280; bCtx.beginPath(); bCtx.arc(px, py, Math.random()*5+2, 0, 7); bCtx.fill(); } bCtx.fillStyle = "rgba(255,255,255,0.7)"; for(let i=0; i<10; i++) { let bx = Math.random()*200 + 5; let by = (300-currentLiquidH) + Math.random()*currentLiquidH; bCtx.beginPath(); bCtx.arc(bx, by, Math.random()*3+1, 0, 7); bCtx.fill(); } } else { for(let i=0; i<50; i++) { bCtx.fillStyle = "rgba(210,225,255,0.5)"; let px = Math.random()*210; let py = Math.random()*290; bCtx.beginPath(); bCtx.arc(px, py, 4, 0, 7); bCtx.fill(); } } gCtx.clearRect(0,0,600,450); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 420); gCtx.lineTo(60, 20); gCtx.lineTo(55, 30); gCtx.moveTo(60, 20); gCtx.lineTo(65, 30); gCtx.stroke(); gCtx.beginPath(); gCtx.moveTo(40, 400); gCtx.lineTo(580, 400); gCtx.lineTo(570, 395); gCtx.moveTo(580, 400); gCtx.lineTo(570, 405); gCtx.stroke(); gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (°C)", 20, 25); gCtx.fillText("Q (J)", 560, 430); gCtx.font = "10px Arial"; gCtx.fillStyle = "#666"; for(let t = -200; t <= 200; t += 50) { let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340; gCtx.fillText(t, 35, y + 5); gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.colorL; gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;"> <div style="display: flex; gap: 10px; align-items: center;"> <label style="font-weight: bold; color: #555;">Substance :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;"> <option value="eau">Eau (H₂O)</option> <option value="ammoniac">Ammoniac (NH₃)</option> <option value="isobutane">Isobutane (C₄H₁₀)</option> <option value="difluoro">Difluorométhane (R-32)</option> </select> </div> <div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-200.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button> <button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const select = document.getElementById('selectFluide'); const db = { eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, color: "#2196f3", maxQ: 4800000 }, ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, color: "#4caf50", maxQ: 3800000 }, isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, color: "#ff9800", maxQ: 2500000 }, difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, color: "#009688", maxQ: 2200000 } }; let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0; const pwr = 4500, tStart = -200, tEnd = 200; window.initSubstance = function() { s = db[select.value]; temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION"; document.getElementById('btnPlay').style.background = "#2e7d32"; heater.style.background = "#333"; updateUI(); }; window.resetSim = function() { initSubstance(); }; window.toggleSim = function() { if(temp >= tEnd) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.nom; } function update() { if(!isRunning) return; if(temp >= tEnd) { isRunning = false; heater.style.background = "#333"; return; } blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c"; energy += pwr * 2.8; let q1 = 1 * s.cs * (s.tf - tStart); let q2 = 1 * s.lf; let q3 = 1 * s.cl * (s.tv - s.tf); let q4 = 1 * s.lv; if (energy < q1) { temp = tStart + energy/s.cs; document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.tf; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = s.tf + (energy - q1 - q2)/s.cl; document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = s.tv; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy - q1 - q2 - q3 - q4)/s.cg; document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } if(temp > tEnd) temp = tEnd; pts.push({x: energy, y: temp}); updateUI(); } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 180; let q1 = 1 * s.cs * (s.tf - tStart); let q2 = 1 * s.lf; let q3 = 1 * s.cl * (s.tv - s.tf); if(temp < s.tf) { // SOLIDE bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(35, 300-hMax, 150, hMax); } else if (temp === s.tf) { // FUSION : Disparition par le haut let ratio = (energy - q1) / q2; bCtx.fillStyle = s.color; bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio); bCtx.fillStyle = "#bbdefb"; // Le solide reste collé au fond, mais sa hauteur diminue bCtx.fillRect(35, 300 - (hMax * (1-ratio)), 150, hMax * (1-ratio)); } else if(temp < s.tv) { // LIQUIDE bCtx.fillStyle = s.color; bCtx.fillRect(0, 300-hMax, 220, hMax); } else if (temp === s.tv) { // ÉBULLITION let ratioV = (energy - q1 - q2 - q3) / (1 * s.lv); let currentLiquidH = hMax * (1 - ratioV); // Liquide restant bCtx.fillStyle = s.color; bCtx.fillRect(0, 300-currentLiquidH, 220, currentLiquidH); // Gaz particules claires (occupent tout le bécher) for(let i=0; i<30; i++) { let pOpacity = ratioV * 0.4; bCtx.fillStyle = "rgba(220,230,255," + pOpacity + ")"; let px = Math.random()*210; let py = Math.random()*280; bCtx.beginPath(); bCtx.arc(px, py, Math.random()*5+2, 0, 7); bCtx.fill(); } // Bulles dans le liquide bCtx.fillStyle = "rgba(255,255,255,0.8)"; for(let i=0; i<10; i++) { let bx = Math.random()*200 + 5; let by = (300-currentLiquidH) + Math.random()*currentLiquidH; bCtx.beginPath(); bCtx.arc(bx, by, Math.random()*3+1, 0, 7); bCtx.fill(); } } else { // GAZ TOTAL : Agitation for(let i=0; i<60; i++) { bCtx.fillStyle = "rgba(200,220,255,0.5)"; let px = Math.random()*210; let py = Math.random()*290; bCtx.beginPath(); bCtx.arc(px, py, 4, 0, 7); bCtx.fill(); } } // --- GRAPHIQUE AVEC FLÈCHES ET LABELS --- gCtx.clearRect(0,0,600,450); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; // Axe Y (Température) gCtx.beginPath(); gCtx.moveTo(60, 420); gCtx.lineTo(60, 20); // Ligne gCtx.lineTo(55, 30); gCtx.moveTo(60, 20); gCtx.lineTo(65, 30); // Flèche gCtx.stroke(); // Axe X (Énergie) gCtx.beginPath(); gCtx.moveTo(40, 400); gCtx.lineTo(580, 400); // Ligne gCtx.lineTo(570, 395); gCtx.moveTo(580, 400); gCtx.lineTo(570, 405); // Flèche gCtx.stroke(); // Labels Axes gCtx.fillStyle = "#000"; gCtx.font = "bold 14px Arial"; gCtx.fillText("T (°C)", 20, 25); gCtx.fillText("Q (J)", 560, 430); // Graduations gCtx.font = "10px Arial"; gCtx.fillStyle = "#666"; for(let t = -200; t <= 200; t += 50) { let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340; gCtx.fillText(t, 35, y + 5); gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;"> <div style="display: flex; gap: 10px; align-items: center;"> <label style="font-weight: bold; color: #555;">Substance :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;"> <option value="eau">Eau (H₂O)</option> <option value="ammoniac">Ammoniac (NH₃)</option> <option value="isobutane">Isobutane (C₄H₁₀)</option> <option value="difluoro">Difluorométhane (R-32)</option> </select> </div> <div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-200.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button> <button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const select = document.getElementById('selectFluide'); const db = { eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, color: "#2196f3", maxQ: 4800000 }, ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, color: "#4caf50", maxQ: 3800000 }, isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, color: "#ff9800", maxQ: 2500000 }, difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, color: "#009688", maxQ: 2200000 } }; let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0; const pwr = 4500, tStart = -200, tEnd = 200; window.initSubstance = function() { s = db[select.value]; temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION"; document.getElementById('btnPlay').style.background = "#2e7d32"; heater.style.background = "#333"; updateUI(); }; window.resetSim = function() { initSubstance(); }; window.toggleSim = function() { if(temp >= tEnd) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; if(!isRunning) heater.style.background = "#333"; }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.nom; } function update() { if(!isRunning) return; if(temp >= tEnd) { isRunning = false; heater.style.background = "#333"; return; } blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c"; energy += pwr * 3.0; // Vitesse augmentée pour le confort let q1 = 1 * s.cs * (s.tf - tStart); let q2 = 1 * s.lf; let q3 = 1 * s.cl * (s.tv - s.tf); let q4 = 1 * s.lv; if (energy < q1) { temp = tStart + energy/s.cs; document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.tf; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = s.tf + (energy - q1 - q2)/s.cl; document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = s.tv; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy - q1 - q2 - q3 - q4)/s.cg; document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } if(temp > tEnd) temp = tEnd; pts.push({x: energy, y: temp}); updateUI(); } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 180; let q1 = 1 * s.cs * (s.tf - tStart); let q2 = 1 * s.lf; let q3 = 1 * s.cl * (s.tv - s.tf); if(temp < s.tf) { bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(35, 300-hMax, 150, hMax); // Bloc solide stable } else if (temp === s.tf) { let ratio = (energy - q1) / q2; bCtx.fillStyle = s.color; bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio); // Liquide monte bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(35, 300-hMax, 150, hMax * (1-ratio)); // Solide descend (fond) } else if(temp < s.tv) { bCtx.fillStyle = s.color; bCtx.fillRect(0, 300-hMax, 220, hMax); // Liquide plein } else if (temp === s.tv) { let ratioV = (energy - q1 - q2 - q3) / (1 * s.lv); let currentLiquidH = hMax * (1 - ratioV); bCtx.fillStyle = s.color; bCtx.fillRect(0, 300-currentLiquidH, 220, currentLiquidH); // Liquide baisse // Gaz progressif (nappe qui monte et s'opacifie) let gasOpacity = 0.1 + (ratioV * 0.5); let gasHeight = (300 - currentLiquidH); bCtx.fillStyle = "rgba(180,180,180," + gasOpacity + ")"; bCtx.fillRect(0, 300 - hMax, 220, hMax - currentLiquidH); bCtx.fillStyle = "rgba(255,255,255,0.8)"; for(let i=0; i<15; i++) { let bx = Math.random()*210; let by = (300-currentLiquidH) + Math.random()*currentLiquidH; bCtx.beginPath(); bCtx.arc(bx, by, Math.random()*3+1, 0, 7); bCtx.fill(); } } else { bCtx.fillStyle = "rgba(180,180,180,0.8)"; bCtx.fillRect(0, 0, 220, 300); // Gaz total } gCtx.clearRect(0,0,600,450); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke(); gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke(); gCtx.fillStyle = "#666"; gCtx.font = "10px Arial"; for(let t = -200; t <= 200; t += 50) { let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340; gCtx.fillText(t + "°", 25, y + 5); gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-physics" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;"> <div style="display: flex; gap: 10px; align-items: center;"> <label style="font-weight: bold; color: #555;">Substance :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;"> <option value="eau">Eau (H₂O)</option> <option value="ammoniac">Ammoniac (NH₃)</option> <option value="isobutane">Isobutane (C₄H₁₀)</option> <option value="difluoro">Difluorométhane (R-32)</option> </select> </div> <div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-150.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; transition: background 0.3s; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button> <button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const select = document.getElementById('selectFluide'); const db = { eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, color: "#2196f3", maxQ: 4200000 }, ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, color: "#4caf50", maxQ: 3200000 }, isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, color: "#ff9800", maxQ: 1800000 }, difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, color: "#009688", maxQ: 1500000 } }; let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0; const pwr = 4500, masse = 1, tStart = -150, tEnd = 150; window.initSubstance = function() { s = db[select.value]; temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION"; document.getElementById('btnPlay').style.background = "#2e7d32"; heater.style.background = "#333"; updateUI(); }; window.resetSim = function() { initSubstance(); }; window.toggleSim = function() { if(temp >= tEnd) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; if(!isRunning) heater.style.background = "#333"; }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.nom; } function update() { if(!isRunning) return; if(temp >= tEnd) { isRunning = false; heater.style.background = "#333"; return; } blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c"; energy += pwr * 2.5; let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0; let q2 = (s.tf > tStart) ? masse * s.lf : 0; let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf)); let q4 = masse * s.lv; if (energy < q1) { temp = tStart + energy/(masse*s.cs); document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.tf; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = Math.max(tStart, s.tf) + (energy - q1 - q2)/(masse*s.cl); document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = s.tv; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg); document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } if(temp > tEnd) temp = tEnd; pts.push({x: energy, y: temp}); updateUI(); } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 180; let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0; let q2 = (s.tf > tStart) ? masse * s.lf : 0; let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf)); // --- DESSIN DE LA MATIÈRE --- if(temp < s.tf) { // SOLIDE PUR : Bloc centré bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(30, 300-hMax, 160, hMax); } else if (temp === s.tf) { // FUSION : Le solide diminue, le liquide monte let ratio = (energy - q1) / s.lf; // Liquide (remplit tout le bécher) bCtx.fillStyle = s.color; bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio); // Solide restant (diminue en hauteur) bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(30, 300-hMax, 160, hMax * (1-ratio)); } else if(temp < s.tv) { // LIQUIDE PUR : Remplit les parois bCtx.fillStyle = s.color; bCtx.fillRect(0, 300-hMax, 220, hMax); } else if (temp === s.tv) { // ÉBULLITION : Niveau baisse, gaz occupe le haut progressivement let ratioV = (energy - q1 - q2 - q3) / s.lv; let currentLiquidH = hMax * (1 - ratioV); // Liquide restant bCtx.fillStyle = s.color; bCtx.fillRect(0, 300-currentLiquidH, 220, currentLiquidH); // Gaz progressif (monte vers le haut du bécher) bCtx.fillStyle = "rgba(180,180,180," + (0.3 + ratioV*0.4) + ")"; bCtx.fillRect(0, 0, 220, 300 - currentLiquidH); // Bulles d'ébullition bCtx.fillStyle = "rgba(255,255,255,0.7)"; for(let i=0; i<12; i++) { let bx = Math.random()*200 + 10; let by = (300-currentLiquidH) + Math.random()*currentLiquidH; bCtx.beginPath(); bCtx.arc(bx, by, Math.random()*4, 0, Math.PI*2); bCtx.fill(); } } else { // GAZ PUR : Occupe tout le bécher bCtx.fillStyle = "rgba(180,180,180,0.7)"; bCtx.fillRect(0, 0, 220, 300); // Petits points pour simuler l'agitation gazeuse bCtx.fillStyle = "rgba(100,100,100,0.2)"; for(let i=0; i<20; i++) { bCtx.fillRect(Math.random()*210, Math.random()*290, 2, 2); } } // --- DESSIN DU GRAPHIQUE --- gCtx.clearRect(0,0,600,450); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke(); gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke(); gCtx.fillStyle = "#666"; gCtx.font = "10px Arial"; for(let t = -150; t <= 150; t += 50) { let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340; gCtx.fillText(t + "°", 30, y + 5); gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-final" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;"> <div style="display: flex; gap: 10px; align-items: center;"> <label style="font-weight: bold; color: #555;">Substance :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;"> <option value="eau">Eau (H₂O)</option> <option value="ammoniac">Ammoniac (NH₃)</option> <option value="isobutane">Isobutane (C₄H₁₀)</option> <option value="difluoro">Difluorométhane (R-32)</option> </select> </div> <div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-150.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; transition: background 0.3s; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px; border-top: 1px solid #333; padding-top: 10px;">Q = m · cₛ · ΔT</div> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button> <button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const select = document.getElementById('selectFluide'); const db = { eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, color: "#2196f3", maxQ: 4200000 }, ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, color: "#4caf50", maxQ: 3200000 }, isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, color: "#ff9800", maxQ: 1800000 }, difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, color: "#009688", maxQ: 1500000 } }; let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0; const pwr = 4500, masse = 1, tStart = -150, tEnd = 150; window.initSubstance = function() { s = db[select.value]; temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION"; document.getElementById('btnPlay').style.background = "#2e7d32"; heater.style.background = "#333"; updateUI(); }; window.resetSim = function() { initSubstance(); }; window.toggleSim = function() { if(temp >= tEnd) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; if(!isRunning) heater.style.background = "#333"; }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.nom; } function update() { if(!isRunning) return; if(temp >= tEnd) { isRunning = false; heater.style.background = "#333"; return; } blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c"; energy += pwr * 2.2; let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0; let q2 = (s.tf > tStart) ? masse * s.lf : 0; let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf)); let q4 = masse * s.lv; if (energy < q1) { temp = tStart + energy/(masse*s.cs); document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.tf; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = Math.max(tStart, s.tf) + (energy - q1 - q2)/(masse*s.cl); document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = s.tv; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg); document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } if(temp > tEnd) temp = tEnd; pts.push({x: energy, y: temp}); updateUI(); } function draw() { bCtx.clearRect(0,0,220,300); let hMax = 180; let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0; let q2 = (s.tf > tStart) ? masse * s.lf : 0; let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf)); // 1. DESSIN DU SOLIDE / LIQUIDE if(temp < s.tf) { // SOLIDE : Bloc avec espace sur les côtés bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(20, 300-hMax, 180, hMax); } else if (temp === s.tf) { // FUSION : Le solide fond, le liquide commence à remplir les bords let ratio = (energy - q1) / s.lf; // Fond liquide (remplit tout le bécher) bCtx.fillStyle = s.color; bCtx.fillRect(0, 300-(hMax * ratio), 220, hMax * ratio); // Reste solide (forme propre) bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(20, 300-hMax, 180, hMax * (1-ratio)); } else if(temp < s.tv) { // LIQUIDE : Remplit tout le bécher (pas d'espace) bCtx.fillStyle = s.color; bCtx.fillRect(0, 300-hMax, 220, hMax); } else if (temp === s.tv) { // ÉBULLITION : Le niveau baisse, le gaz apparaît en haut let ratioV = (energy - q1 - q2 - q3) / s.lv; let currentH = hMax * (1 - ratioV); // Liquide restant bCtx.fillStyle = s.color; bCtx.fillRect(0, 300-currentH, 220, currentH); // Gaz qui apparaît (opacité progressive) bCtx.fillStyle = "rgba(180,180,180," + (0.2 + ratioV*0.5) + ")"; bCtx.fillRect(0, 300-hMax, 220, hMax - currentH); // Bulles aléatoires bCtx.fillStyle = "rgba(255,255,255,0.6)"; for(let i=0; i<10; i++) { let bx = Math.random()*200 + 10; let by = (300-currentH) + Math.random()*currentH; bCtx.beginPath(); bCtx.arc(bx, by, 3, 0, Math.PI*2); bCtx.fill(); } } else { // GAZ : Remplit tout le bécher uniformément bCtx.fillStyle = "rgba(180,180,180,0.6)"; bCtx.fillRect(0, 0, 220, 300); } // 2. DESSIN DU GRAPHIQUE gCtx.clearRect(0,0,600,450); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke(); gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke(); gCtx.fillStyle = "#666"; gCtx.font = "10px Arial"; for(let t = -150; t <= 150; t += 50) { let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340; gCtx.fillText(t + "°", 30, y + 5); gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-final" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;"> <div style="display: flex; gap: 10px; align-items: center;"> <label style="font-weight: bold; color: #555;">Substance :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;"> <option value="eau">Eau (H₂O)</option> <option value="ammoniac">Ammoniac (NH₃)</option> <option value="isobutane">Isobutane (C₄H₁₀)</option> <option value="difluoro">Difluorométhane (R-32)</option> </select> </div> <div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-150.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #777; border-right: 6px solid #777; border-bottom: 6px solid #777; background: #fff; border-radius: 0 0 15px 15px; position: relative; z-index: 2;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; margin-left: -5px; transition: background 0.3s; z-index: 1;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-top: 15px;">FORMULE APPLIQUÉE</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px;">Q = m · cₛ · ΔT</div> </div> <div id="specs-box" style="width: 100%; margin-top: 15px; background: #f9f9f9; padding: 15px; border-radius: 10px; border: 1px dashed #ccc; font-size: 0.85em;"> <b>Propriétés :</b> m = 1kg | P = 4500W<br> <span id="data-list"></span> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button> <button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const heater = document.getElementById('heater'); const select = document.getElementById('selectFluide'); const db = { eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, color: "#2196f3", maxQ: 4200000 }, ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, color: "#4caf50", maxQ: 3200000 }, isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, color: "#ff9800", maxQ: 1800000 }, difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, color: "#009688", maxQ: 1500000 } }; let s, temp, energy, isRunning = false, pts = [], blinkFrame = 0; const pwr = 4500, masse = 1, tStart = -150, tEnd = 150; window.initSubstance = function() { s = db[select.value]; temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION"; document.getElementById('btnPlay').style.background = "#2e7d32"; heater.style.background = "#333"; updateUI(); }; window.resetSim = function() { initSubstance(); }; window.toggleSim = function() { if(temp >= tEnd) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; if(!isRunning) heater.style.background = "#333"; }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.nom; document.getElementById('data-list').innerHTML = `cs = ${s.cs} J/kgK | Lf = ${s.lf/1000} kJ/kg | cl = ${s.cl} J/kgK | Lv = ${s.lv/1000} kJ/kg`; } function update() { if(!isRunning) return; if(temp >= tEnd) { isRunning = false; heater.style.background = "#333"; return; } // Animation plaque blinkFrame++; heater.style.background = (Math.floor(blinkFrame / 10) % 2 === 0) ? "#f44336" : "#b71c1c"; energy += pwr * 2.2; let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0; let q2 = (s.tf > tStart) ? masse * s.lf : 0; let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf)); let q4 = masse * s.lv; if (energy < q1) { temp = tStart + energy/(masse*s.cs); document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.tf; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = Math.max(tStart, s.tf) + (energy - q1 - q2)/(masse*s.cl); document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = s.tv; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg); document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } if(temp > tEnd) temp = tEnd; pts.push({x: energy, y: temp}); updateUI(); } function draw() { bCtx.clearRect(0,0,220,300); let h = 180; // Hauteur du fluide // Ajustement des blocs au bécher (largeur 200px entre les parois de 10px) if(temp < s.tf) { bCtx.fillStyle = "#bbdefb"; // Aspect glace bCtx.fillRect(6, 300-h, 208, h); } else if (temp === s.tf) { // Animation fusion (mélange solide/liquide) let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0; let ratio = (energy - q1) / s.lf; bCtx.fillStyle = s.color; bCtx.fillRect(6, 300-(h*ratio), 208, h*ratio); bCtx.fillStyle = "#bbdefb"; bCtx.fillRect(6, 300-h, 208, h*(1-ratio)); } else if(temp < s.tv) { bCtx.fillStyle = s.color; bCtx.fillRect(6, 300-h, 208, h); } else if (temp === s.tv) { // Animation ébullition let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0; let q2 = (s.tf > tStart) ? masse * s.lf : 0; let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf)); let ratioV = (energy - q1 - q2 - q3) / s.lv; bCtx.fillStyle = s.color; bCtx.globalAlpha = 1 - ratioV; bCtx.fillRect(6, 300-h, 208, h); bCtx.globalAlpha = 1.0; bCtx.fillStyle = "rgba(200,200,200,0.4)"; // Vapeur bCtx.fillRect(6, 0, 208, 300); } else { bCtx.fillStyle = "rgba(180,180,180,0.5)"; // Gaz pur bCtx.fillRect(6, 0, 208, 300); } // Graphique gCtx.clearRect(0,0,600,450); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke(); gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke(); gCtx.fillStyle = "#666"; gCtx.font = "10px Arial"; for(let t = -150; t <= 150; t += 50) { let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340; gCtx.fillText(t + "°", 30, y + 5); gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-fixed" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;"> <div style="display: flex; gap: 10px; align-items: center;"> <label style="font-weight: bold; color: #555;">Substance :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;"> <option value="eau">Eau (H₂O)</option> <option value="ammoniac">Ammoniac (NH₃)</option> <option value="isobutane">Isobutane (C₄H₁₀)</option> <option value="difluoro">Difluorométhane (R-32)</option> </select> </div> <div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-150.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #555; border-right: 6px solid #555; border-bottom: 6px solid #555; background: #fff; border-radius: 0 0 15px 15px;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; margin-left: -5px;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-top: 15px;">FORMULE APPLIQUÉE</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px;">Q = m · cₛ · ΔT</div> </div> <div id="specs-box" style="width: 100%; margin-top: 15px; background: #f9f9f9; padding: 15px; border-radius: 10px; border: 1px dashed #ccc; font-size: 0.85em;"> <b>Propriétés :</b> m = 1kg | P = 4500W<br> <span id="data-list"></span> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button> <button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> <div style="margin-top: 15px; font-size: 0.9em; color: #666; font-style: italic;"> Note : La simulation couvre la plage de -150°C à +150°C pour toutes les substances. </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const select = document.getElementById('selectFluide'); const db = { eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, color: "#1565c0", maxQ: 4200000 }, ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, color: "#689f38", maxQ: 3200000 }, isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, color: "#e65100", maxQ: 1800000 }, difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, color: "#00796b", maxQ: 1500000 } }; let s, temp, energy, isRunning = false, pts = []; const pwr = 4500, masse = 1, tStart = -150, tEnd = 150; window.initSubstance = function() { s = db[select.value]; temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION"; document.getElementById('btnPlay').style.background = "#2e7d32"; updateUI(); }; window.resetSim = function() { initSubstance(); }; window.toggleSim = function() { if(temp >= tEnd) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.nom; document.getElementById('data-list').innerHTML = `cs = ${s.cs} J/kgK | Lf = ${s.lf/1000} kJ/kg | cl = ${s.cl} J/kgK | Lv = ${s.lv/1000} kJ/kg`; } function update() { if(!isRunning) return; if(temp >= tEnd) { isRunning = false; return; } energy += pwr * 2.0; // Calcul des paliers d'énergie // 1. Solide de tStart à tf (si tStart < tf) let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0; // 2. Fusion let q2 = (s.tf > tStart) ? masse * s.lf : 0; // 3. Liquide de tf à tv let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf)); // 4. Vaporisation let q4 = masse * s.lv; if (energy < q1) { temp = tStart + energy/(masse*s.cs); document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.tf; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = Math.max(tStart, s.tf) + (energy - q1 - q2)/(masse*s.cl); document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = s.tv; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg); document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } if(temp > tEnd) temp = tEnd; pts.push({x: energy, y: temp}); updateUI(); } function draw() { bCtx.clearRect(0,0,220,300); let h = 140; if(temp < s.tf) bCtx.fillStyle = "#e3f2fd"; else if(temp < s.tv) bCtx.fillStyle = s.color; else bCtx.fillStyle = "rgba(150,150,150,0.4)"; bCtx.fillRect(10, 300-h, 200, h); gCtx.clearRect(0,0,600,450); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke(); // Y gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke(); // X // Graduation Y gCtx.fillStyle = "#666"; gCtx.font = "10px Arial"; for(let t = -150; t <= 150; t += 50) { let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340; gCtx.fillText(t + "°", 30, y + 5); gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px;"> <div style="display: flex; gap: 10px; align-items: center;"> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b;"> <option value="eau">Eau (H₂O)</option> <option value="ammoniac">Ammoniac (NH₃)</option> <option value="isobutane">Isobutane (C₄H₁₀)</option> <option value="difluoro">Difluorométhane (R-32)</option> </select> <button id="btnMystere" onclick="toggleMystere()" style="padding: 10px 15px; background: #673ab7; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">🕵️ MODE MYSTÈRE : OFF</button> </div> <div style="display: flex; align-items: center; gap: 20px;"> <div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-50.0 °C</div> </div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #555; border-right: 6px solid #555; border-bottom: 6px solid #555; background: #fff; border-radius: 0 0 15px 15px;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; margin-left: -5px;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-top: 15px;">FORMULE APPLIQUÉE</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px;">Q = m · cₛ · ΔT</div> </div> <div id="specs-box" style="width: 100%; margin-top: 15px; background: #f9f9f9; padding: 15px; border-radius: 10px; border: 1px dashed #ccc; font-size: 0.85em;"> <b>Données :</b> m = 1kg | P = 4500W<br> <span id="data-list">cₛ = 2090 J/kgK | Lf = 334 kJ/kg</span> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button> <button onclick="location.reload()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> <div id="mystery-hint" style="display:none; margin-top: 15px; padding: 15px; background: #fff9c4; border-left: 5px solid #fbc02d; border-radius: 5px;"> <b>🕵️ DÉFI :</b> Identifiez la substance en observant les températures de paliers (lignes horizontales) et les pentes ! </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const db = { eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, t0: -50, tEnd: 150, color: "#1565c0", maxQ: 3500000 }, ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, t0: -100, tEnd: 50, color: "#689f38", maxQ: 2500000 }, isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, t0: -180, tEnd: 100, color: "#e65100", maxQ: 1500000 }, difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, t0: -160, tEnd: 80, color: "#00796b", maxQ: 1200000 } }; let s, temp, energy, isRunning = false, pts = [], isMystere = false; const pwr = 4500, masse = 1; window.initSubstance = function() { const val = document.getElementById('selectFluide').value; s = db[val]; temp = s.t0; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION"; document.getElementById('btnPlay').style.background = "#2e7d32"; updateUI(); }; window.toggleMystere = function() { isMystere = !isMystere; document.getElementById('btnMystere').innerText = isMystere ? "🕵️ MODE MYSTÈRE : ON" : "🕵️ MODE MYSTÈRE : OFF"; document.getElementById('btnMystere').style.background = isMystere ? "#f44336" : "#673ab7"; document.getElementById('mystery-hint').style.display = isMystere ? "block" : "none"; document.getElementById('specs-box').style.visibility = isMystere ? "hidden" : "visible"; updateUI(); }; window.toggleSim = function() { if(temp >= s.tEnd) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = isMystere ? "SUBSTANCE MYSTÈRE" : s.nom; document.getElementById('data-list').innerHTML = `cs = ${s.cs} J/kgK | Lf = ${s.lf/1000} kJ/kg | cl = ${s.cl} J/kgK | Lv = ${s.lv/1000} kJ/kg`; } function update() { if(!isRunning) return; if(temp >= s.tEnd) { isRunning = false; return; } energy += pwr * 2.0; let q1 = masse * s.cs * (s.tf - s.t0); let q2 = masse * s.lf; let q3 = masse * s.cl * (s.tv - s.tf); let q4 = masse * s.lv; if(energy < q1) { temp = s.t0 + energy/(masse*s.cs); document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if(energy < q1+q2) { temp = s.tf; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if(energy < q1+q2+q3) { temp = s.tf + (energy-q1-q2)/(masse*s.cl); document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if(energy < q1+q2+q3+q4) { temp = s.tv; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy-q1-q2-q3-q4)/(masse*s.cg); document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } pts.push({x: energy, y: temp}); updateUI(); } function draw() { bCtx.clearRect(0,0,220,300); // Dessin du fluide let h = 140; if(temp < s.tf) bCtx.fillStyle = "#e3f2fd"; else if(temp < s.tv) bCtx.fillStyle = s.color; else bCtx.fillStyle = "rgba(100,100,100,0.3)"; bCtx.fillRect(10, 300-h, 200, h); gCtx.clearRect(0,0,600,450); // Axes gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke(); // Y gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke(); // X // Tracé courbe if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - s.t0) / (s.tEnd - s.t0)) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-challenge-integrated" style="width: 100%; max-width: 1280px; background: #f4f4f9; border: 2px solid #333; border-radius: 20px; padding: 25px; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #222; margin: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: 20px;"> <div style="text-align: center; background: #333; color: #ffca28; padding: 15px; border-radius: 12px; border-bottom: 4px solid #ffca28;"> <h2 style="margin: 0; text-transform: uppercase; letter-spacing: 2px;">🧪 ÉVALUATION : THERMODYNAMIQUE APPLIQUÉE</h2> <p style="margin: 5px 0 0 0; font-weight: bold; color: #fff;">SUBSTANCE MYSTÈRE — MODE CHALLENGE ACTIVÉ</p> </div> <div style="display: flex; flex-wrap: wrap; gap: 25px;"> <div style="flex: 1.2; min-width: 450px; display: flex; flex-direction: column; gap: 15px;"> <div style="display: flex; gap: 10px; background: #fff; padding: 10px; border-radius: 10px; border: 1px solid #ccc;"> <canvas id="beakerCanvas" width="220" height="300" style="background: #fff; border-radius: 8px; flex: 1;"></canvas> <canvas id="graphCanvas" width="300" height="300" style="background: #fafafa; border-radius: 8px; flex: 1.5;"></canvas> </div> <div id="dataPanel" style="background: #e8f5e9; border: 2px solid #2e7d32; border-radius: 12px; padding: 10px;"> <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; text-align: center; font-size: 0.85em;"> <div style="background:#fff; padding:5px; border-radius:5px;">c<sub>s</sub>: <strong id="val_cs">-</strong><br><small>J/kg·K</small></div> <div style="background:#fff; padding:5px; border-radius:5px;">c<sub>l</sub>: <strong id="val_cl">-</strong><br><small>J/kg·K</small></div> <div style="background:#fff; padding:5px; border-radius:5px;">c<sub>g</sub>: <strong id="val_cg">-</strong><br><small>J/kg·K</small></div> <div style="background:#fff; padding:5px; border-radius:5px;">L<sub>f</sub>: <strong id="val_lf">-</strong><br><small>kJ/kg</small></div> <div style="background:#fff; padding:5px; border-radius:5px;">L<sub>v</sub>: <strong id="val_lv">-</strong><br><small>kJ/kg</small></div> <div style="background:#fff; padding:5px; border-radius:5px;">T<sub>f</sub>/T<sub>v</sub>:<br><strong id="val_temps">-</strong></div> </div> </div> <div style="background: #eee; padding: 15px; border-radius: 12px; display: grid; grid-template-columns: 1fr 1fr; gap: 10px;"> <div style="text-align:center;">T. Init: <input type="number" id="t_start_val" value="-60" style="width:60px; font-weight:bold;"></div> <div style="text-align:center;">Masse: <input type="number" id="m_val" value="1.0" step="0.1" style="width:60px; font-weight:bold;"> kg</div> <div style="grid-column: span 2; display: flex; gap: 10px;"> <button id="mainBtn" onclick="handleBtn()" style="flex:1; padding: 12px; background: #2e7d32; color:white; border:none; border-radius:8px; font-weight:bold; cursor:pointer;">LANCER LA SIMULATION</button> <button id="revealBtn" onclick="revealResults()" style="padding: 12px; background: #d32f2f; color:white; border:none; border-radius:8px; font-weight:bold; cursor:pointer; display:none;">RÉVÉLER</button> </div> </div> <div id="tempDisp" style="font-size: 2.5em; font-weight: bold; text-align: center; border: 3px solid #333; background: #fff; border-radius: 10px;">-- °C</div> </div> <div style="flex: 1; min-width: 350px; background: #fff; border-radius: 15px; border: 1px solid #ccc; padding: 20px; display: flex; flex-direction: column; gap: 15px;"> <h3 style="margin-top: 0; color: #d32f2f; border-bottom: 2px solid #eee; padding-bottom: 10px;">📝 QUESTIONS DE RÉFLEXION</h3> <div id="quiz-container" style="overflow-y: auto; max-height: 500px; padding-right: 10px;"> <div class="q-box" style="margin-bottom: 20px; padding: 10px; border-bottom: 1px solid #eee;"> <p style="font-weight: bold; margin-bottom: 8px;">1. Pourquoi la température reste-t-elle bloquée par moments ?</p> <select id="q1" style="width: 100%; padding: 5px;"> <option value="">-- Choisir --</option> <option value="correct">Changement d'état (Energie de liaison)</option> <option value="wrong">Panne du système de chauffe</option> <option value="wrong">Le capteur est bloqué</option> </select> </div> <div class="q-box" style="margin-bottom: 20px; padding: 10px; border-bottom: 1px solid #eee;"> <p style="font-weight: bold; margin-bottom: 8px;">2. Quelle constante est utilisée pour chauffer le SOLIDE ?</p> <select id="q2" style="width: 100%; padding: 5px;"> <option value="">-- Choisir --</option> <option value="correct">c_s (capacité thermique solide)</option> <option value="wrong">L_f (chaleur latente de fusion)</option> <option value="wrong">c_l (capacité thermique liquide)</option> </select> </div> <div class="q-box" style="margin-bottom: 20px; padding: 10px; border-bottom: 1px solid #eee;"> <p style="font-weight: bold; margin-bottom: 8px;">3. Si P=2000W pendant 100s, quelle est l'énergie Q ?</p> <select id="q3" style="width: 100%; padding: 5px;"> <option value="">-- Choisir --</option> <option value="wrong">20 kJ</option> <option value="correct">200 kJ</option> <option value="wrong">2000 J</option> </select> </div> <div class="q-box" style="margin-bottom: 20px; padding: 10px; border-bottom: 1px solid #eee;"> <p style="font-weight: bold; margin-bottom: 8px;">4. La pente dépend de quelle propriété ?</p> <select id="q4" style="width: 100%; padding: 5px;"> <option value="">-- Choisir --</option> <option value="correct">La capacité thermique massique (c)</option> <option value="wrong">La couleur de la substance</option> <option value="wrong">Seulement de la puissance</option> </select> </div> <div class="q-box" style="margin-bottom: 20px; padding: 10px; border-bottom: 1px solid #eee;"> <p style="font-weight: bold; margin-bottom: 8px;">5. Un palier plus long sur le graph signifie :</p> <select id="q5" style="width: 100%; padding: 5px;"> <option value="">-- Choisir --</option> <option value="wrong">Une température plus basse</option> <option value="correct">Une chaleur latente (L) plus élevée</option> <option value="wrong">Une masse plus petite</option> </select> </div> </div> <button onclick="checkQuiz()" style="width: 100%; padding: 15px; background: #333; color: #ffca28; border: none; border-radius: 8px; font-weight: bold; cursor: pointer; font-size: 1.1em;">VÉRIFIER MES RÉPONSES</button> <div id="quiz-feedback" style="text-align: center; font-weight: bold; font-size: 1.2em; padding: 10px; border-radius: 8px; display: none;"></div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerCanvas'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphCanvas'), gCtx = gC.getContext('2d'); const BK = { x: 45, y: 30, w: 130, h: 220, baseH: 60 }; const substances = [ { id:"Eau", cs:2090, cl:4185, cg:2010, lf:334000, lv:2260000, tf:0, tv:100, color:"#1565c0" }, { id:"Ammoniac", cs:2100, cl:4700, cg:2100, lf:331000, lv:1371000, tf:-77.7, tv:-33.3, color:"#fbc02d" }, { id:"Isobutane", cs:1600, cl:2350, cg:1650, lf:78000, lv:366000, tf:-159.6, tv:-11.7, color:"#e65100" } ]; let sub, m, p=2000, energy=0, isRunning=false, points=[], temp, t_start, t_end=150, maxE; window.initSubstance = function() { sub = substances[Math.floor(Math.random() * substances.length)]; t_start = parseFloat(document.getElementById('t_start_val').value); temp = t_start; energy = 0; isRunning = false; points = []; document.getElementById('dataPanel').style.borderColor = sub.color; updateDisplay(); updateDataPanel(); }; function updateDataPanel() { document.getElementById('val_cs').innerText = sub.cs; document.getElementById('val_cl').innerText = sub.cl; document.getElementById('val_cg').innerText = sub.cg; document.getElementById('val_lf').innerText = (sub.lf/1000).toFixed(0); document.getElementById('val_lv').innerText = (sub.lv/1000).toFixed(0); document.getElementById('val_temps').innerText = sub.tf + " / " + sub.tv; } window.handleBtn = function() { if(!isRunning || temp >= t_end) { m = parseFloat(document.getElementById('m_val').value); t_start = parseFloat(document.getElementById('t_start_val').value); let q1 = (t_start < sub.tf) ? m*sub.cs*(Math.min(t_end, sub.tf) - t_start) : 0; let q2 = (t_start <= sub.tf && t_end > sub.tf) ? m*sub.lf : 0; let q3 = (t_end > sub.tf) ? m*sub.cl*(Math.min(t_end, sub.tv) - Math.max(t_start, sub.tf)) : 0; let q4 = (t_start <= sub.tv && t_end > sub.tv) ? m*sub.lv : 0; let q5 = (t_end > sub.tv) ? m*sub.cg*(t_end - Math.max(t_start, sub.tv)) : 0; maxE = q1+q2+q3+q4+q5; temp = t_start; energy = 0; points = []; isRunning = true; document.getElementById('mainBtn').innerText = "EN COURS..."; document.getElementById('revealBtn').style.display = "none"; } }; window.revealResults = function() { alert("La substance était : " + sub.id + "\nChaleur totale : " + Math.round(maxE).toLocaleString() + " Joules"); }; window.checkQuiz = function() { let score = 0; for(let i=1; i<=5; i++) { if(document.getElementById('q'+i).value === 'correct') score++; } const feedback = document.getElementById('quiz-feedback'); feedback.style.display = 'block'; feedback.innerText = "Score : " + score + "/5"; feedback.style.background = score === 5 ? "#c8e6c9" : "#ffcdd2"; feedback.style.color = score === 5 ? "#2e7d32" : "#c62828"; }; function update() { if(!isRunning || temp >= t_end) return; energy += p * 3; let q1 = (t_start < sub.tf) ? m*sub.cs*(sub.tf - t_start) : 0; let q2 = (t_start <= sub.tf) ? m*sub.lf : 0; let q3 = (t_start < sub.tv) ? m*sub.cl*(sub.tv - Math.max(t_start, sub.tf)) : 0; let q4 = (t_start <= sub.tv) ? m*sub.lv : 0; if (t_start < sub.tf && energy < q1) temp = t_start + energy/(m*sub.cs); else if (t_start <= sub.tf && energy < q1+q2) temp = sub.tf; else if (energy < q1+q2+q3) temp = Math.max(t_start, sub.tf) + (energy-q1-q2)/(m*sub.cl); else if (t_end > sub.tv && energy < q1+q2+q3+q4) temp = sub.tv; else temp = Math.max(t_start, sub.tv) + (energy-q1-q2-q3-q4)/(m*sub.cg); if (temp >= t_end) { temp = t_end; isRunning = false; document.getElementById('mainBtn').innerText = "TERMINÉ"; document.getElementById('revealBtn').style.display = "inline-block"; } updateDisplay(); points.push({e: energy, t: temp}); } function updateDisplay() { document.getElementById('tempDisp').innerText = temp.toFixed(1) + " °C"; document.getElementById('tempDisp').style.color = sub.color; } function draw() { bCtx.clearRect(0,0,bC.width,bC.height); bCtx.strokeStyle="#333"; bCtx.lineWidth=6; bCtx.strokeRect(BK.x, BK.y, BK.w, BK.h); bCtx.fillStyle = sub.color + "44"; let fillH = (temp < sub.tf) ? 40 : (temp < sub.tv) ? 100 : 20; bCtx.fillRect(BK.x+5, BK.y+BK.h-fillH, BK.w-10, fillH); gCtx.clearRect(0,0,gC.width,gC.height); gCtx.beginPath(); gCtx.strokeStyle="#ccc"; gCtx.moveTo(40,280); gCtx.lineTo(40,20); gCtx.moveTo(40,280); gCtx.lineTo(290,280); gCtx.stroke(); if(points.length > 1) { gCtx.beginPath(); gCtx.strokeStyle=sub.color; gCtx.lineWidth=2; points.forEach((p, i) => { let px = 40 + (p.e/maxE)*240; let py = 280 - ((p.t-t_start)/(t_end-t_start))*240; if(i===0) gCtx.moveTo(px,py); else gCtx.lineTo(px,py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="thermo-ultra-challenge" style="width: 100%; max-width: 1280px; background: #fff; border: 3px solid #333; border-radius: 20px; overflow: hidden; font-family: 'Segoe UI', sans-serif; margin: auto; display: flex; flex-direction: column; box-shadow: 0 15px 50px rgba(0,0,0,0.3);"> <div id="level-header" style="background: #1565c0; color: white; padding: 20px; display: flex; justify-content: space-between; align-items: center;"> <h2 style="margin:0;">NIVEAU <span id="lvl-num">1</span> : <span id="lvl-name">SUBSTANCE MYSTÈRE</span></h2> <div style="font-weight: bold; background: rgba(0,0,0,0.2); padding: 8px 15px; border-radius: 8px;"> Masse: <span id="display-mass">1.0</span> kg | Puissance: 2000 W </div> </div> <div style="display: flex; flex-wrap: wrap;"> <div style="flex: 1.5; min-width: 500px; padding: 25px; background: #f0f2f5; border-right: 2px solid #ddd;"> <div style="display: flex; gap: 20px; margin-bottom: 20px;"> <canvas id="beakerCanvas" width="180" height="380" style="background: #fff; border: 2px solid #555; border-radius: 10px;"></canvas> <canvas id="graphCanvas" width="480" height="380" style="background: #fff; border: 2px solid #555; border-radius: 10px; flex-grow:1;"></canvas> </div> <div style="display: grid; grid-template-columns: 1.5fr 1fr; gap: 20px;"> <div id="dataPanel" style="background: #e3f2fd; padding: 15px; border-radius: 12px; border-left: 10px solid #1565c0;"> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; font-weight: bold;"> <div>cₛ: <span id="v_cs">-</span> J/kg·K</div> <div>cₗ: <span id="v_cl">-</span> J/kg·K</div> <div>c_g: <span id="v_cg">-</span> J/kg·K</div> <div>L_f: <span id="v_lf">-</span> kJ/kg</div> <div>L_v: <span id="v_lv">-</span> kJ/kg</div> <div style="color:#d32f2f">Paliers: <span id="v_pal">-</span> °C</div> </div> </div> <div style="text-align: center; display: flex; flex-direction: column; justify-content: center;"> <div id="tempDisp" style="font-size: 3.5em; font-weight: bold; color: #1565c0; font-family: monospace;">-- °C</div> <button id="mainBtn" onclick="startSim()" style="padding: 15px; background: #1565c0; color: white; border: none; border-radius: 10px; font-weight: bold; cursor: pointer; font-size: 1.2em;">LANCER LE CHAUFFAGE</button> </div> </div> </div> <div style="flex: 1; min-width: 380px; padding: 25px; background: white;"> <h3 style="margin-top: 0; color: #1565c0; border-bottom: 2px solid #eee; padding-bottom: 10px;">FEUILLE DE ROUTE</h3> <div id="quiz-box" style="margin-top: 10px;"></div> <div id="feedback" style="margin-top: 15px; padding: 12px; border-radius: 8px; font-weight: bold; display: none; text-align: center;"></div> <button id="valBtn" onclick="checkAll()" style="width: 100%; padding: 20px; margin-top: 20px; background: #222; color: #ffca28; border: none; border-radius: 10px; font-weight: bold; cursor: pointer; font-size: 1.1em;">VALIDER LE NIVEAU</button> <button id="nextBtn" onclick="goNext()" style="width: 100%; padding: 20px; margin-top: 20px; background: #2e7d32; color: white; border: none; border-radius: 10px; font-weight: bold; cursor: pointer; display: none;">PASSER À LA SUITE ➔</button> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerCanvas'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphCanvas'), gCtx = gC.getContext('2d'); const levels = [ { name: "Eau", mass: 1.0, color: "#0d47a1", data: {cs:2090, cl:4185, cg:2010, lf:334, lv:2260, tf:0, tv:100}, qs: [ {q: "1. Quelle est cette substance ?", o: ["Eau", "Ammoniac", "Méthane"], a: "Eau"}, {q: "2. Que signifie Qf ?", o: ["Fusion", "Froid", "Force"], a: "Fusion"}, {q: "3. Calcul Qv (1kg) ?", o: ["2260 kJ", "334 kJ", "4185 J"], a: "2260 kJ"}, {q: "4. Pourquoi un palier ?", o: ["Rupture liaisons", "Panne chauffe", "Capteur bloqué"], a: "Rupture liaisons"}, {q: "5. Pente dépend de :", o: ["Capacité c", "Couleur", "Puissance"], a: "Capacité c"} ] }, { name: "Ammoniac", mass: 0.5, color: "#ffa000", data: {cs:2100, cl:4700, cg:2100, lf:331, lv:1371, tf:-77.7, tv:-33.3}, qs: [ {q: "1. Température de fusion ?", o: ["-77.7°C", "-33.3°C", "0°C"], a: "-77.7°C"}, {q: "2. Qv est-il < à l'eau ?", o: ["Oui", "Non"], a: "Oui"}, {q: "3. Calcul Qv (0.5kg) ?", o: ["685.5 kJ", "1371 kJ", "331 kJ"], a: "685.5 kJ"}, {q: "4. Pourquoi le palier est horizontal ?", o: ["Changement état", "Thermomètre cassé"], a: "Changement état"}, {q: "5. Si P=2000W, t=100s, Q= ?", o: ["200 kJ", "20 kJ", "2000 J"], a: "200 kJ"} ] } ]; let cur = 0, pts = [], energy = 0, temp = 0, isRunning = false, mols = []; const P = 2000; function init() { const l = levels[cur]; document.getElementById('lvl-num').innerText = cur+1; document.getElementById('lvl-name').innerText = "SUBSTANCE MYSTÈRE"; document.getElementById('display-mass').innerText = l.mass; document.getElementById('v_cs').innerText = l.data.cs; document.getElementById('v_cl').innerText = l.data.cl; document.getElementById('v_cg').innerText = l.data.cg; document.getElementById('v_lf').innerText = l.data.lf; document.getElementById('v_lv').innerText = l.data.lv; document.getElementById('v_pal').innerText = l.data.tf + " / " + l.data.tv; temp = l.data.tf - 50; energy = 0; pts = []; isRunning = false; document.getElementById('mainBtn').innerText = "LANCER LE CHAUFFAGE"; mols = Array.from({length: 40}, () => ({x: 50+Math.random()*80, y: 280+Math.random()*60, vx: Math.random()-0.5, vy: Math.random()-0.5})); document.getElementById('quiz-box').innerHTML = l.qs.map((q, i) => ` <div style="margin-bottom:12px; padding:10px; background:#f9f9f9; border-radius:5px;"> <p style="margin:0 0 5px 0; font-size:0.9em; font-weight:bold;">${q.q}</p> <select id="ans${i}" style="width:100%; padding:5px; border-radius:4px;"> <option value="">-- Choisir --</option> ${q.o.map(opt => `<option value="${opt}">${opt}</option>`).join('')} </select> </div> `).join(''); document.getElementById('feedback').style.display = 'none'; document.getElementById('nextBtn').style.display = 'none'; document.getElementById('valBtn').style.display = 'block'; } window.startSim = function() { if(!isRunning) isRunning = true; }; window.checkAll = function() { const l = levels[cur]; let ok = l.qs.every((q, i) => document.getElementById('ans'+i).value === q.a); const fb = document.getElementById('feedback'); fb.style.display = 'block'; if(ok) { fb.innerText = "BRAVO ! La substance était bien : " + l.name; fb.style.background = "#e8f5e9"; fb.style.color = "#2e7d32"; document.getElementById('lvl-name').innerText = l.name; document.getElementById('valBtn').style.display = 'none'; document.getElementById('nextBtn').style.display = 'block'; } else { fb.innerText = "Il y a des erreurs. Vérifiez vos calculs !"; fb.style.background = "#ffebee"; fb.style.color = "#c62828"; } }; window.goNext = function() { cur = (cur+1)%levels.length; init(); }; function update() { if(!isRunning) return; const l = levels[cur], m = l.mass; energy += P * 3; let q1 = m * l.data.cs * 50, q2 = m * l.data.lf * 1000, q3 = m * l.data.cl * (l.data.tv - l.data.tf), q4 = m * l.data.lv * 1000; if (energy < q1) temp = (l.data.tf-50) + energy/(m*l.data.cs); else if (energy < q1+q2) temp = l.data.tf; else if (energy < q1+q2+q3) temp = l.data.tf + (energy-q1-q2)/(m*l.data.cl); else if (energy < q1+q2+q3+q4) temp = l.data.tv; else temp = l.data.tv + (energy-q1-q2-q3-q4)/(m*l.data.cg); if(temp > l.data.tv + 50) isRunning = false; document.getElementById('tempDisp').innerText = temp.toFixed(1) + " °C"; pts.push({e: energy, t: temp}); // Animation molécules let speed = (temp + 200) / 100; mols.forEach(mo => { mo.x += mo.vx * speed; mo.y += mo.vy * speed; if(mo.x<45 || mo.x>135) mo.vx *= -1; if(mo.y< (temp > l.data.tv ? 40 : temp > l.data.tf ? 150 : 250) || mo.y>315) mo.vy *= -1; }); } function draw() { const l = levels[cur]; bCtx.clearRect(0,0,180,380); bCtx.strokeStyle="#333"; bCtx.lineWidth=5; bCtx.strokeRect(40,40,100,280); bCtx.fillStyle = l.color; mols.forEach(mo => { bCtx.beginPath(); bCtx.arc(mo.x, mo.y, 4, 0, 7); bCtx.fill(); }); gCtx.clearRect(0,0,480,380); gCtx.beginPath(); gCtx.strokeStyle="#aaa"; gCtx.moveTo(50,20); gCtx.lineTo(50,340); gCtx.lineTo(460,340); gCtx.stroke(); gCtx.fillStyle="#d32f2f"; gCtx.font="bold 12px Arial"; let yf = 340 - ((l.data.tf - (l.data.tf-50))/150)*300, yv = 340 - ((l.data.tv - (l.data.tf-50))/150)*300; gCtx.fillText(l.data.tf+"°", 10, yf); gCtx.fillText(l.data.tv+"°", 10, yv); if(pts.length>1) { gCtx.beginPath(); gCtx.strokeStyle=l.color; gCtx.lineWidth=4; let totalE = (m*l.data.cs*50) + (m*l.data.lf*1000) + (m*l.data.cl*(l.data.tv-l.data.tf)) + (m*l.data.lv*1000) + (m*l.data.cg*50); pts.forEach((p, i) => { let x = 50 + (p.e/totalE)*380, y = 340 - ((p.t-(l.data.tf-50))/150)*300; if(i===0) gCtx.moveTo(x,y); else gCtx.lineTo(x,y); }); gCtx.stroke(); } } setInterval(() => { update(); draw(); }, 30); init(); })(); </script>
1. Pourquoi la température reste-t-elle bloquée par moments ? -- Choisir -- Changement d'état (Energie de liaison) Panne du système de chauffe Le capteur est bloqué 2. Quelle constante est utilisée pour chauffer le SOLIDE ? -- Choisir -- c_s (capacité thermique solide) L_f (chaleur latente de fusion) c_l (capacité thermique liquide) 3. Si P=2000W pendant 100s, quelle est l'énergie Q ? -- Choisir -- 20 kJ 200 kJ 2000 J 4. La pente dépend de quelle propriété ? -- Choisir -- La capacité thermique massique (c) La couleur de la substance Seulement de la puissance 5. Un palier plus long sur le graph signifie : " et remets un menu deroulant pour les reponses on voit pas la courbe ni le chauffage
<div id="thermo-pro-adventure" style="width: 100%; max-width: 1280px; background: #ffffff; border: 2px solid #333; border-radius: 15px; overflow: hidden; font-family: 'Segoe UI', sans-serif; margin: auto; box-sizing: border-box; display: flex; flex-direction: column; box-shadow: 0 10px 30px rgba(0,0,0,0.1);"> <div id="level-header" style="background: #1565c0; color: white; padding: 20px; display: flex; justify-content: space-between; align-items: center; border-bottom: 4px solid rgba(0,0,0,0.1);"> <div> <h2 style="margin:0; text-transform: uppercase; letter-spacing: 1px;">Défi Thermodynamique : Niveau <span id="current-lvl-num">1</span></h2> <p id="substance-display-name" style="margin:5px 0 0 0; font-weight: bold; background: rgba(0,0,0,0.2); display: inline-block; padding: 2px 10px; border-radius: 4px;">Substance Mystère</p> </div> <div style="text-align: right;"> <div style="font-size: 0.8em; opacity: 0.8;">Statut</div> <div id="step-name" style="font-weight: bold;">ANALYSE EN COURS</div> </div> </div> <div style="display: flex; flex-wrap: wrap; gap: 0;"> <div style="flex: 1.3; min-width: 450px; padding: 20px; background: #fdfdfd; border-right: 1px solid #eee;"> <div style="display: flex; flex-direction: column; gap: 15px;"> <div style="display: flex; gap: 10px; height: 350px;"> <canvas id="beakerCanvas" width="160" height="340" style="background: #fff; border-radius: 8px; border: 1px solid #ddd;"></canvas> <canvas id="graphCanvas" width="450" height="340" style="background: #fff; border-radius: 8px; border: 1px solid #ddd; flex-grow: 1;"></canvas> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; background: #f1f3f5; padding: 15px; border-radius: 12px;"> <div id="dataPanel" style="background: white; border-left: 5px solid #1565c0; padding: 10px; border-radius: 4px; box-shadow: 0 2px 5px rgba(0,0,0,0.05);"> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 5px; font-size: 0.9em;"> <div>c<sub>s</sub>: <b id="val_cs">-</b></div> <div>c<sub>l</sub>: <b id="val_cl">-</b></div> <div>c<sub>g</sub>: <b id="val_cg">-</b></div> <div>L<sub>f</sub>: <b id="val_lf">-</b> kJ/kg</div> <div>L<sub>v</sub>: <b id="val_lv">-</b> kJ/kg</div> <div><b>Puissance</b>: 2000 W</div> </div> </div> <div style="display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 10px;"> <div style="font-size: 1.1em; font-weight: bold;">Masse : <span id="fixed-mass" style="color: #d32f2f;">1.0</span> kg</div> <button id="mainBtn" onclick="handleBtn()" style="width: 100%; padding: 12px; background: #1565c0; color: white; border: none; border-radius: 6px; font-weight: bold; cursor: pointer; text-transform: uppercase;">Chauffer</button> <div id="tempDisp" style="font-size: 2.2em; font-weight: bold; font-family: monospace;">-- °C</div> </div> </div> </div> </div> <div id="quiz-zone" style="flex: 1; min-width: 350px; padding: 25px; display: flex; flex-direction: column; background: white;"> <h3 style="margin: 0 0 20px 0; border-bottom: 2px solid #f1f3f5; padding-bottom: 10px; color: #333;">Questions de validation</h3> <div id="quiz-content" style="flex-grow: 1;"> </div> <div id="feedback" style="margin-top: 15px; padding: 12px; border-radius: 6px; font-weight: bold; display: none; font-size: 0.9em;"></div> <button onclick="checkAnswers()" id="validateBtn" style="width: 100%; padding: 15px; margin-top: 15px; background: #333; color: #ffca28; border: none; border-radius: 6px; font-weight: bold; cursor: pointer;">VÉRIFIER MES RÉPONSES</button> <button onclick="nextLevel()" id="nextLvlBtn" style="width: 100%; padding: 15px; margin-top: 10px; background: #2e7d32; color: white; border: none; border-radius: 6px; font-weight: bold; cursor: pointer; display: none;">NIVEAU SUIVANT ➔</button> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerCanvas'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphCanvas'), gCtx = gC.getContext('2d'); const levels = [ { name: "Eau (H₂O)", mass: 1.0, color: "#1565c0", data: { cs:2090, cl:4185, cg:2010, lf:334, lv:2260, tf:0, tv:100 }, questions: [ { q: "1. En observant les paliers de température, quelle est cette substance ?", options: ["Ammoniac", "Eau", "Éthanol"], correct: "Eau" }, { q: "2. Que représente physiquement le terme 'Qf' ?", options: ["La chaleur de fusion", "La puissance du froid", "La quantité de liquide"], correct: "La chaleur de fusion" }, { q: "3. Calculez l'énergie nécessaire pour vaporiser la masse totale ?", options: ["334 kJ", "2260 kJ", "4185 kJ"], correct: "2260 kJ" }, { q: "4. Pourquoi observe-t-on un palier horizontal ?", options: ["La puissance se coupe", "L'énergie est utilisée pour le changement d'état", "Le liquide ne peut pas dépasser 100°C"], correct: "L'énergie est utilisée pour le changement d'état" } ] }, { name: "Ammoniac (NH₃)", mass: 0.5, color: "#f9a825", data: { cs:2100, cl:4700, cg:2100, lf:331, lv:1371, tf:-77.7, tv:-33.3 }, questions: [ { q: "1. À quelle température l'ammoniac commence-t-il sa fusion ?", options: ["-33.3°C", "0°C", "-77.7°C"], correct: "-77.7°C" }, { q: "2. Comparez les chaleurs latentes de vaporisation. Celle de l'ammoniac est-elle plus faible que celle de l'eau ?", options: ["Non", "Oui", "Elles sont égales"], correct: "Oui" }, { q: "3. Calculez l'énergie Qv nécessaire pour vaporiser la masse présente (0.5 kg) ?", options: ["1371 kJ", "685.5 kJ", "331 kJ"], correct: "685.5 kJ" }, { q: "4. Le palier de vaporisation est-il plus court ou plus long que celui de l'eau ?", options: ["Plus court", "Plus long", "Identique"], correct: "Plus court" } ] }, { name: "Isobutane (C₄H₁₀)", mass: 0.8, color: "#e65100", data: { cs:1600, cl:2350, cg:1650, lf:78, lv:366, tf:-159.6, tv:-11.7 }, questions: [ { q: "1. La substance est-elle liquide ou gazeuse à la température de 0°C ?", options: ["Gazeuse", "Liquide", "Solide"], correct: "Gazeuse" }, { q: "2. Comment jugez-vous la chaleur latente de fusion par rapport aux autres niveaux ?", options: ["Moyenne", "Très élevée", "Très faible"], correct: "Très faible" }, { q: "3. Calculez l'énergie Qf nécessaire pour faire fondre l'échantillon ?", options: ["78 kJ", "62.4 kJ", "159.6 kJ"], correct: "62.4 kJ" }, { q: "4. Comparée à l'eau, comment est la pente de montée en température de ce liquide ?", options: ["Identique", "Plus abrupte (chauffe plus vite)", "Plus douce"], correct: "Plus abrupte (chauffe plus vite)" } ] } ]; let currentLvl = 0; let points = [], energy = 0, temp = 0, isRunning = false; const P = 2000; function initLevel() { const lvl = levels[currentLvl]; document.getElementById('current-lvl-num').innerText = currentLvl + 1; document.getElementById('substance-display-name').innerText = "Substance Mystère"; document.getElementById('level-header').style.background = lvl.color; document.getElementById('dataPanel').style.borderLeftColor = lvl.color; document.getElementById('fixed-mass').innerText = lvl.mass; document.getElementById('val_cs').innerText = lvl.data.cs; document.getElementById('val_cl').innerText = lvl.data.cl; document.getElementById('val_cg').innerText = lvl.data.cg; document.getElementById('val_lf').innerText = lvl.data.lf; document.getElementById('val_lv').innerText = lvl.data.lv; temp = lvl.data.tf - 40; energy = 0; points = []; isRunning = false; document.getElementById('mainBtn').innerText = "Chauffer"; document.getElementById('mainBtn').style.background = lvl.color; const qContainer = document.getElementById('quiz-content'); qContainer.innerHTML = lvl.questions.map((q, i) => ` <div style="margin-bottom: 18px;"> <p style="font-weight: bold; font-size: 0.9em; margin: 0 0 8px 0; line-height: 1.3;">${q.q}</p> <div style="display: flex; flex-direction: column; gap: 5px;"> ${q.options.map(opt => ` <label style="font-size: 0.85em; cursor: pointer; background: #f8f9fa; padding: 8px; border-radius: 4px; border: 1px solid #eee;"> <input type="radio" name="q${i}" value="${opt}"> ${opt} </label> `).join('')} </div> </div> `).join(''); document.getElementById('feedback').style.display = 'none'; document.getElementById('nextLvlBtn').style.display = 'none'; document.getElementById('validateBtn').style.display = 'block'; } window.handleBtn = function() { if(isRunning) return; isRunning = true; document.getElementById('mainBtn').innerText = "En cours..."; }; window.checkAnswers = function() { const lvl = levels[currentLvl]; let score = 0; lvl.questions.forEach((q, i) => { const selected = document.querySelector(`input[name="q${i}"]:checked`); if(selected && selected.value === q.correct) score++; }); const fb = document.getElementById('feedback'); fb.style.display = 'block'; if(score === lvl.questions.length) { fb.innerText = "EXCELLENT ! Tous les calculs et observations sont corrects."; fb.style.background = "#e8f5e9"; fb.style.color = "#2e7d32"; document.getElementById('validateBtn').style.display = 'none'; document.getElementById('nextLvlBtn').style.display = 'block'; document.getElementById('substance-display-name').innerText = lvl.name; } else { fb.innerText = "Erreur : " + score + "/" + lvl.questions.length + " correctes. Regardez bien les données et le graphique."; fb.style.background = "#ffebee"; fb.style.color = "#c62828"; } }; window.nextLevel = function() { currentLvl++; if(currentLvl >= levels.length) { alert("Bravo ! Vous avez validé toutes les substances !"); currentLvl = 0; } initLevel(); }; function update() { if(!isRunning) return; const lvl = levels[currentLvl]; const m = lvl.mass; energy += P * 2; let q1 = m * lvl.data.cs * 40; let q2 = m * lvl.data.lf * 1000; let q3 = m * lvl.data.cl * (lvl.data.tv - lvl.data.tf); let q4 = m * lvl.data.lv * 1000; if (energy < q1) temp = (lvl.data.tf - 40) + energy/(m * lvl.data.cs); else if (energy < q1+q2) temp = lvl.data.tf; else if (energy < q1+q2+q3) temp = lvl.data.tf + (energy-q1-q2)/(m * lvl.data.cl); else if (energy < q1+q2+q3+q4) temp = lvl.data.tv; else temp = lvl.data.tv + (energy-q1-q2-q3-q4)/(m * lvl.data.cg); if(temp > lvl.data.tv + 40) isRunning = false; document.getElementById('tempDisp').innerText = temp.toFixed(1) + " °C"; points.push({e: energy, t: temp}); } function draw() { const lvl = levels[currentLvl]; bCtx.clearRect(0,0,bC.width,bC.height); bCtx.strokeStyle = "#333"; bCtx.lineWidth = 3; bCtx.strokeRect(30, 30, 100, 280); bCtx.fillStyle = lvl.color + "44"; let fillH = (temp < lvl.data.tf) ? 60 : (temp < lvl.data.tv) ? 140 : 40; bCtx.fillRect(33, 310-fillH, 94, fillH); gCtx.clearRect(0,0,gC.width,gC.height); gCtx.strokeStyle = "#bbb"; gCtx.lineWidth = 1; gCtx.beginPath(); gCtx.moveTo(50, 20); gCtx.lineTo(50, 310); gCtx.lineTo(430, 310); gCtx.stroke(); gCtx.fillStyle = "#333"; gCtx.font = "bold 11px Arial"; let y_tf = 310 - ((lvl.data.tf - (lvl.data.tf-40))/130) * 260; let y_tv = 310 - ((lvl.data.tv - (lvl.data.tf-40))/130) * 260; gCtx.fillText(lvl.data.tf + "°", 10, y_tf); gCtx.fillText(lvl.data.tv + "°", 10, y_tv); if(points.length > 1) { gCtx.beginPath(); gCtx.strokeStyle = lvl.color; gCtx.lineWidth = 3; let total_e = (m * lvl.data.cs * 40) + (m * lvl.data.lf * 1000) + (m * lvl.data.cl * (lvl.data.tv-lvl.data.tf)) + (m * lvl.data.lv * 1000) + (m * lvl.data.cg * 40); points.forEach((p, i) => { let x = 50 + (p.e / total_e) * 360; let y = 310 - ((p.t - (lvl.data.tf-40))/130) * 260; if(i===0) gCtx.moveTo(x,y); else gCtx.lineTo(x,y); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initLevel(); loop(); })(); </script>
<div id="thermo-challenge-adventure" style="width: 100%; max-width: 1280px; background: #ffffff; border: 2px solid #222; border-radius: 20px; overflow: hidden; font-family: 'Segoe UI', sans-serif; margin: auto; box-sizing: border-box; display: flex; flex-direction: column;"> <div id="level-header" style="background: #1565c0; color: white; padding: 20px; display: flex; justify-content: space-between; align-items: center;"> <div> <h2 style="margin:0; text-transform: uppercase;">Niveau <span id="current-lvl-num">1</span> : <span id="lvl-title">L'Eau (H₂O)</span></h2> <p style="margin:5px 0 0 0; opacity: 0.9;">Objectif : Répondre aux 4 questions pour débloquer la suite.</p> </div> <div id="badge-container" style="background: rgba(255,255,255,0.2); padding: 10px 20px; border-radius: 50px; font-weight: bold;"> ÉTAPE : <span id="step-name">INITIATION</span> </div> </div> <div style="display: flex; flex-wrap: wrap; gap: 0;"> <div style="flex: 1.2; min-width: 450px; padding: 25px; background: #f8f9fa; border-right: 1px solid #ddd;"> <div style="display: flex; gap: 15px; margin-bottom: 20px;"> <canvas id="beakerCanvas" width="200" height="280" style="background: white; border-radius: 10px; border: 1px solid #ccc;"></canvas> <div style="flex: 1;"> <canvas id="graphCanvas" width="350" height="280" style="background: white; border-radius: 10px; border: 1px solid #ccc; width: 100%;"></canvas> <p style="font-size: 0.8em; color: #666; text-align: center; margin-top: 5px;"><i>Astuce : Lisez les températures de palier sur l'axe vertical.</i></p> </div> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <div id="dataPanel" style="background: white; border: 2px solid #1565c0; border-radius: 12px; padding: 15px;"> <h4 style="margin:0 0 10px 0; color: #1565c0; text-align: center;">Propriétés Physiques</h4> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px; font-size: 0.85em;"> <div>c<sub>s</sub>: <b id="val_cs">-</b></div> <div>c<sub>l</sub>: <b id="val_cl">-</b></div> <div>c<sub>g</sub>: <b id="val_cg">-</b></div> <div>L<sub>f</sub>: <b id="val_lf">-</b> kJ/kg</div> <div>L<sub>v</sub>: <b id="val_lv">-</b> kJ/kg</div> <div>Puis.: <b>2000 W</b></div> </div> </div> <div style="display: flex; flex-direction: column; gap: 10px; justify-content: center;"> <div style="text-align: center; font-size: 0.9em;">Masse fixée : <b id="fixed-mass">1.0</b> kg</div> <button id="mainBtn" onclick="handleBtn()" style="padding: 15px; background: #1565c0; color: white; border: none; border-radius: 8px; font-weight: bold; cursor: pointer; transition: 0.3s;">LANCER L'EXPÉRIENCE</button> <div id="tempDisp" style="font-size: 2em; font-weight: bold; text-align: center; color: #1565c0;">-- °C</div> </div> </div> </div> <div id="quiz-zone" style="flex: 1; min-width: 350px; padding: 25px; background: white;"> <div id="quiz-content"> </div> <button onclick="checkAnswers()" id="validateBtn" style="width: 100%; padding: 18px; margin-top: 20px; background: #222; color: #ffca28; border: none; border-radius: 8px; font-weight: bold; cursor: pointer; font-size: 1.1em;">VÉRIFIER MES RÉPONSES</button> <div id="feedback" style="margin-top: 15px; padding: 15px; border-radius: 8px; text-align: center; font-weight: bold; display: none;"></div> <button onclick="nextLevel()" id="nextLvlBtn" style="width: 100%; padding: 18px; margin-top: 10px; background: #2e7d32; color: white; border: none; border-radius: 8px; font-weight: bold; cursor: pointer; display: none;">PASSER AU NIVEAU SUIVANT ➔</button> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerCanvas'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphCanvas'), gCtx = gC.getContext('2d'); const levels = [ { name: "Eau (H₂O)", mass: 1.0, color: "#1565c0", data: { cs:2090, cl:4185, cg:2010, lf:334, lv:2260, tf:0, tv:100 }, questions: [ { q: "1. Quelle est cette substance d'après ses paliers (0°C et 100°C) ?", options: ["Eau", "Ammoniac", "Éthanol"], correct: "Eau" }, { q: "2. Que signifie le terme 'Qf' dans le calcul ?", options: ["Chaleur de Fusion", "Quantité de Froid", "Quotient de Force"], correct: "Chaleur de Fusion" }, { q: "3. Calcul : Énergie pour vaporiser 1kg (Qv = m × Lv) ?", options: ["2260 kJ", "334 kJ", "4185 J"], correct: "2260 kJ" }, { q: "4. Pourquoi la température n'augmente pas pendant un palier ?", options: ["L'énergie sert à briser les liaisons", "Le thermomètre est cassé", "La puissance s'arrête"], correct: "L'énergie sert à briser les liaisons" } ] }, { name: "Ammoniac (NH₃)", mass: 0.5, color: "#fbc02d", data: { cs:2100, cl:4700, cg:2100, lf:331, lv:1371, tf:-77.7, tv:-33.3 }, questions: [ { q: "1. À quelle température l'ammoniac devient-il liquide (Tf) ?", options: ["0°C", "-77.7°C", "-33.3°C"], correct: "-77.7°C" }, { q: "2. La chaleur latente Lv est-elle plus petite que pour l'eau ?", options: ["Oui (1371 < 2260)", "Non", "C'est la même"], correct: "Oui (1371 < 2260)" }, { q: "3. Calcul : Énergie pour vaporiser 0.5kg (0.5 × 1371) ?", options: ["685.5 kJ", "1371 kJ", "2742 kJ"], correct: "685.5 kJ" }, { q: "4. Le palier de vaporisation est-il plus court que celui de l'eau ?", options: ["Oui", "Non", "Identique"], correct: "Oui" } ] }, { name: "Isobutane (C₄H₁₀)", mass: 0.8, color: "#e65100", data: { cs:1600, cl:2350, cg:1650, lf:78, lv:366, tf:-159.6, tv:-11.7 }, questions: [ { q: "1. Cette substance est-elle gazeuse à 0°C ?", options: ["Oui (Tv = -11.7°C)", "Non", "Seulement si on chauffe"], correct: "Oui (Tv = -11.7°C)" }, { q: "2. Sa chaleur de fusion est-elle très faible ?", options: ["Oui (78 kJ/kg)", "Non (780 kJ/kg)", "Élevée"], correct: "Oui (78 kJ/kg)" }, { q: "3. Calcul : Énergie de fusion pour 0.8kg (0.8 × 78) ?", options: ["62.4 kJ", "78 kJ", "156 kJ"], correct: "62.4 kJ" }, { q: "4. Comment est la pente du liquide (cl=2350) comparée à l'eau ?", options: ["Plus raide (chauffe plus vite)", "Moins raide", "Identique"], correct: "Plus raide (chauffe plus vite)" } ] } ]; let currentLvl = 0; let points = [], energy = 0, temp = -180, isRunning = false; const P = 2000; function initLevel() { const lvl = levels[currentLvl]; document.getElementById('current-lvl-num').innerText = currentLvl + 1; document.getElementById('lvl-title').innerText = currentLvl === 0 ? "Substance Mystère 1" : "Niveau " + (currentLvl+1); document.getElementById('level-header').style.background = lvl.color; document.getElementById('dataPanel').style.borderColor = lvl.color; document.getElementById('fixed-mass').innerText = lvl.mass; // Données du tableau document.getElementById('val_cs').innerText = lvl.data.cs; document.getElementById('val_cl').innerText = lvl.data.cl; document.getElementById('val_cg').innerText = lvl.data.cg; document.getElementById('val_lf').innerText = lvl.data.lf; document.getElementById('val_lv').innerText = lvl.data.lv; // Reset Sim temp = lvl.data.tf - 50; energy = 0; points = []; isRunning = false; document.getElementById('mainBtn').innerText = "LANCER L'EXPÉRIENCE"; document.getElementById('mainBtn').style.background = lvl.color; // Reset Quiz const qContainer = document.getElementById('quiz-content'); qContainer.innerHTML = lvl.questions.map((q, i) => ` <div style="margin-bottom: 15px; border-bottom: 1px solid #eee; padding-bottom: 10px;"> <p style="font-weight: bold; font-size: 0.95em; margin-bottom: 8px;">${q.q}</p> ${q.options.map(opt => ` <label style="display: block; margin-bottom: 4px; font-size: 0.9em; cursor: pointer;"> <input type="radio" name="q${i}" value="${opt}"> ${opt} </label> `).join('')} </div> `).join(''); document.getElementById('feedback').style.display = 'none'; document.getElementById('nextLvlBtn').style.display = 'none'; document.getElementById('validateBtn').style.display = 'block'; } window.handleBtn = function() { if(isRunning) return; isRunning = true; document.getElementById('mainBtn').innerText = "CHAUFFAGE EN COURS..."; }; window.checkAnswers = function() { const lvl = levels[currentLvl]; let score = 0; lvl.questions.forEach((q, i) => { const selected = document.querySelector(`input[name="q${i}"]:checked`); if(selected && selected.value === q.correct) score++; }); const fb = document.getElementById('feedback'); fb.style.display = 'block'; if(score === lvl.questions.length) { fb.innerText = "PARFAIT ! Vous avez compris les propriétés de cette substance."; fb.style.background = "#c8e6c9"; fb.style.color = "#2e7d32"; document.getElementById('validateBtn').style.display = 'none'; document.getElementById('nextLvlBtn').style.display = 'block'; document.getElementById('lvl-title').innerText = lvl.name; // On révèle le nom } else { fb.innerText = "Il y a des erreurs (" + score + "/" + lvl.questions.length + "). Observez bien les paliers sur le graph."; fb.style.background = "#ffcdd2"; fb.style.color = "#c62828"; } }; window.nextLevel = function() { currentLvl++; if(currentLvl >= levels.length) { alert("Félicitations ! Vous avez terminé tous les défis thermodynamiques !"); currentLvl = 0; } initLevel(); }; function update() { if(!isRunning) return; const lvl = levels[currentLvl]; const m = lvl.mass; const dt = 1.5; // Vitesse sim energy += P * dt; let q1 = m * lvl.data.cs * (lvl.data.tf - (lvl.data.tf - 50)); let q2 = m * lvl.data.lf * 1000; let q3 = m * lvl.data.cl * (lvl.data.tv - lvl.data.tf); let q4 = m * lvl.data.lv * 1000; if (energy < q1) temp = (lvl.data.tf - 50) + energy/(m * lvl.data.cs); else if (energy < q1+q2) temp = lvl.data.tf; else if (energy < q1+q2+q3) temp = lvl.data.tf + (energy-q1-q2)/(m * lvl.data.cl); else if (energy < q1+q2+q3+q4) temp = lvl.data.tv; else temp = lvl.data.tv + (energy-q1-q2-q3-q4)/(m * lvl.data.cg); if(temp > lvl.data.tv + 50) isRunning = false; document.getElementById('tempDisp').innerText = temp.toFixed(1) + " °C"; points.push({e: energy, t: temp}); } function draw() { const lvl = levels[currentLvl]; bCtx.clearRect(0,0,bC.width,bC.height); // Beaker bCtx.strokeStyle = "#333"; bCtx.lineWidth = 4; bCtx.strokeRect(40, 40, 120, 200); bCtx.fillStyle = lvl.color + "44"; let h = (temp < lvl.data.tf) ? 40 : (temp < lvl.data.tv) ? 100 : 20; bCtx.fillRect(44, 240-h, 112, h); gCtx.clearRect(0,0,gC.width,gC.height); // Axes gCtx.strokeStyle = "#999"; gCtx.beginPath(); gCtx.moveTo(40, 20); gCtx.lineTo(40, 260); gCtx.lineTo(330, 260); gCtx.stroke(); // Paliers Text gCtx.fillStyle = "#666"; gCtx.font = "10px Arial"; let y_tf = 260 - ((lvl.data.tf - (lvl.data.tf-50))/150) * 200; let y_tv = 260 - ((lvl.data.tv - (lvl.data.tf-50))/150) * 200; gCtx.fillText(lvl.data.tf + "°C", 5, y_tf); gCtx.fillText(lvl.data.tv + "°C", 5, y_tv); if(points.length > 1) { gCtx.beginPath(); gCtx.strokeStyle = lvl.color; gCtx.lineWidth = 3; let max_e = (m * lvl.data.cs * 50) + (m * lvl.data.lf * 1000) + (m * lvl.data.cl * (lvl.data.tv-lvl.data.tf)) + (m * lvl.data.lv * 1000) + (m * lvl.data.cg * 50); points.forEach((p, i) => { let x = 40 + (p.e / max_e) * 280; let y = 260 - ((p.t - (lvl.data.tf-50))/150) * 200; if(i===0) gCtx.moveTo(x,y); else gCtx.lineTo(x,y); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initLevel(); loop(); })(); </script>
<div id="sim-thermo-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px;"> <div style="display: flex; gap: 10px; align-items: center;"> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b;"> <option value="eau">Eau (H₂O)</option> <option value="ammoniac">Ammoniac (NH₃)</option> <option value="isobutane">Isobutane (C₄H₁₀)</option> <option value="difluoro">Difluorométhane (R-32)</option> </select> <button id="btnMystere" onclick="toggleMystere()" style="padding: 10px 15px; background: #673ab7; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold;">🕵️ MODE MYSTÈRE : OFF</button> </div> <div style="display: flex; align-items: center; gap: 20px;"> <div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-50.0 °C</div> </div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #555; border-right: 6px solid #555; border-bottom: 6px solid #555; background: #fff; border-radius: 0 0 15px 15px;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; margin-left: -5px;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-top: 15px;">FORMULE APPLIQUÉE</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px;">Q = m · cₛ · ΔT</div> </div> <div id="specs-box" style="width: 100%; margin-top: 15px; background: #f9f9f9; padding: 15px; border-radius: 10px; border: 1px dashed #ccc; font-size: 0.85em;"> <b>Données :</b> m = 1kg | P = 4500W<br> <span id="data-list">cₛ = 2090 J/kgK | Lf = 334 kJ/kg</span> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button> <button onclick="location.reload()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> <div id="mystery-hint" style="display:none; margin-top: 15px; padding: 15px; background: #fff9c4; border-left: 5px solid #fbc02d; border-radius: 5px;"> <b>🕵️ DÉFI :</b> Identifiez la substance en observant les températures de paliers (lignes horizontales) et les pentes ! </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const db = { eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, t0: -50, tEnd: 150, color: "#1565c0", maxQ: 3500000 }, ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, t0: -100, tEnd: 50, color: "#689f38", maxQ: 2500000 }, isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, t0: -180, tEnd: 100, color: "#e65100", maxQ: 1500000 }, difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, t0: -160, tEnd: 80, color: "#00796b", maxQ: 1200000 } }; let s, temp, energy, isRunning = false, pts = [], isMystere = false; const pwr = 4500, masse = 1; window.initSubstance = function() { const val = document.getElementById('selectFluide').value; s = db[val]; temp = s.t0; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION"; document.getElementById('btnPlay').style.background = "#2e7d32"; updateUI(); }; window.toggleMystere = function() { isMystere = !isMystere; document.getElementById('btnMystere').innerText = isMystere ? "🕵️ MODE MYSTÈRE : ON" : "🕵️ MODE MYSTÈRE : OFF"; document.getElementById('btnMystere').style.background = isMystere ? "#f44336" : "#673ab7"; document.getElementById('mystery-hint').style.display = isMystere ? "block" : "none"; document.getElementById('specs-box').style.visibility = isMystere ? "hidden" : "visible"; updateUI(); }; window.toggleSim = function() { if(temp >= s.tEnd) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = isMystere ? "SUBSTANCE MYSTÈRE" : s.nom; document.getElementById('data-list').innerHTML = `cs = ${s.cs} J/kgK | Lf = ${s.lf/1000} kJ/kg | cl = ${s.cl} J/kgK | Lv = ${s.lv/1000} kJ/kg`; } function update() { if(!isRunning) return; if(temp >= s.tEnd) { isRunning = false; return; } energy += pwr * 2.0; let q1 = masse * s.cs * (s.tf - s.t0); let q2 = masse * s.lf; let q3 = masse * s.cl * (s.tv - s.tf); let q4 = masse * s.lv; if(energy < q1) { temp = s.t0 + energy/(masse*s.cs); document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if(energy < q1+q2) { temp = s.tf; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if(energy < q1+q2+q3) { temp = s.tf + (energy-q1-q2)/(masse*s.cl); document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if(energy < q1+q2+q3+q4) { temp = s.tv; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy-q1-q2-q3-q4)/(masse*s.cg); document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } pts.push({x: energy, y: temp}); updateUI(); } function draw() { bCtx.clearRect(0,0,220,300); // Dessin du fluide let h = 140; if(temp < s.tf) bCtx.fillStyle = "#e3f2fd"; else if(temp < s.tv) bCtx.fillStyle = s.color; else bCtx.fillStyle = "rgba(100,100,100,0.3)"; bCtx.fillRect(10, 300-h, 200, h); gCtx.clearRect(0,0,600,450); // Axes gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke(); // Y gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke(); // X // Tracé courbe if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - s.t0) / (s.tEnd - s.t0)) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
<div id="sim-thermo-expert" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;"> <div style="display: flex; gap: 10px; align-items: center;"> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;"> </select> <button id="btnMystere" onclick="toggleMystere()" style="padding: 10px 15px; background: #673ab7; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold; transition: 0.3s;">🕵️ MODE MYSTÈRE : OFF</button> </div> <div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-50.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #555; border-right: 6px solid #555; border-bottom: 6px solid #555; background: #fff; border-radius: 0 0 15px 15px;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; margin-left: -5px;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center; min-height: 1.2em;">EAU (H₂O)</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-top: 15px;">FORMULE APPLIQUÉE</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px;">Q = m · cₛ · ΔT</div> </div> <div id="specs-box" style="width: 100%; margin-top: 15px; background: #f9f9f9; padding: 15px; border-radius: 10px; border: 1px dashed #ccc; font-size: 0.85em;"> <b>Données techniques :</b><br> <span id="data-list">m = 1kg | P = 4500W | Lf = 334 kJ/kg</span> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER</button> <button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> <div id="mystery-hint" style="display:none; margin-top: 15px; padding: 15px; background: #fff9c4; border-left: 5px solid #fbc02d; border-radius: 5px; font-size: 0.9em;"> <b>🕵️ MISSION ENQUÊTE :</b> Observez les températures de paliers (lignes horizontales) et calculez l'énergie consommée pour identifier la substance. </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const select = document.getElementById('selectFluide'); const db = { eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, t0: -50, tEnd: 150, color: "#1565c0", maxQ: 3500000, alias: "Substance A" }, ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, t0: -100, tEnd: 50, color: "#689f38", maxQ: 2500000, alias: "Substance B" }, isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, t0: -180, tEnd: 100, color: "#e65100", maxQ: 1500000, alias: "Substance C" }, difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, t0: -160, tEnd: 80, color: "#00796b", maxQ: 1200000, alias: "Substance D" } }; let s, temp, energy, isRunning = false, pts = [], isMystere = false; const pwr = 4500, masse = 1; function populateSelect() { const currentVal = select.value || "eau"; select.innerHTML = ""; Object.keys(db).forEach(key => { const opt = document.createElement('option'); opt.value = key; opt.innerText = isMystere ? db[key].alias : db[key].nom; if(key === currentVal) opt.selected = true; select.appendChild(opt); }); } window.initSubstance = function() { s = db[select.value]; temp = s.t0; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER"; document.getElementById('btnPlay').style.background = "#2e7d32"; updateUI(); }; window.toggleMystere = function() { isMystere = !isMystere; populateSelect(); document.getElementById('btnMystere').innerText = isMystere ? "🕵️ MODE MYSTÈRE : ON" : "🕵️ MODE MYSTÈRE : OFF"; document.getElementById('btnMystere').style.background = isMystere ? "#f44336" : "#673ab7"; document.getElementById('mystery-hint').style.display = isMystere ? "block" : "none"; document.getElementById('specs-box').style.visibility = isMystere ? "hidden" : "visible"; updateUI(); }; window.resetSim = function() { initSubstance(); }; window.toggleSim = function() { if(temp >= s.tEnd) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = isMystere ? "SUBSTANCE MYSTÈRE" : s.nom; document.getElementById('data-list').innerHTML = `m = 1kg | P = 4500W | Lf = ${s.lf/1000} kJ/kg | cl = ${s.cl} J/kgK`; } function update() { if(!isRunning) return; if(temp >= s.tEnd) { isRunning = false; return; } energy += pwr * 1.8; let q1 = masse * s.cs * (s.tf - s.t0); let q2 = masse * s.lf; let q3 = masse * s.cl * (s.tv - s.tf); let q4 = masse * s.lv; if(energy < q1) { temp = s.t0 + energy/(masse*s.cs); document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if(energy < q1+q2) { temp = s.tf; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if(energy < q1+q2+q3) { temp = s.tf + (energy-q1-q2)/(masse*s.cl); document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if(energy < q1+q2+q3+q4) { temp = s.tv; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy-q1-q2-q3-q4)/(masse*s.cg); document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } pts.push({x: energy, y: temp}); updateUI(); } function draw() { bCtx.clearRect(0,0,220,300); let h = 140; if(temp < s.tf) bCtx.fillStyle = "#e3f2fd"; else if(temp < s.tv) bCtx.fillStyle = s.color; else bCtx.fillStyle = "rgba(200,200,200,0.5)"; bCtx.fillRect(10, 300-h, 200, h); gCtx.clearRect(0,0,600,450); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke(); gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke(); if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - s.t0) / (s.tEnd - s.t0)) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } populateSelect(); initSubstance(); loop(); })(); </script>
<div id="sim-thermo-fixed" style="width: 100%; max-width: 1100px; margin: auto; font-family: 'Segoe UI', sans-serif; background: #ffffff; border: 2px solid #333; padding: 25px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.2);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #f1f3f4; padding: 15px; border-radius: 12px; border: 1px solid #ddd;"> <div style="display: flex; gap: 10px; align-items: center;"> <label style="font-weight: bold; color: #555;">Substance :</label> <select id="selectFluide" onchange="initSubstance()" style="padding: 10px; border-radius: 8px; font-weight: bold; border: 2px solid #607d8b; min-width: 200px;"> <option value="eau">Eau (H₂O)</option> <option value="ammoniac">Ammoniac (NH₃)</option> <option value="isobutane">Isobutane (C₄H₁₀)</option> <option value="difluoro">Difluorométhane (R-32)</option> </select> </div> <div id="temp-grand" style="font-size: 3.5em; font-weight: bold; color: #d32f2f; font-family: monospace;">-150.0 °C</div> </div> <div style="display: flex; gap: 30px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 300px; display: flex; flex-direction: column; align-items: center;"> <div style="position: relative; width: 220px; height: 320px;"> <canvas id="beakerSim" width="220" height="300" style="border-left: 6px solid #555; border-right: 6px solid #555; border-bottom: 6px solid #555; background: #fff; border-radius: 0 0 15px 15px;"></canvas> <div id="heater" style="width: 230px; height: 25px; background: #333; border-radius: 5px 5px 15px 15px; margin-top: -2px; color: white; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; margin-left: -5px;">PLAQUE CHAUFFANTE (4500W)</div> </div> <div id="nom-substance" style="margin-top: 20px; font-size: 1.8em; font-weight: bold; color: #1565c0; text-align: center;">EAU (H₂O)</div> <div id="etat-text" style="font-weight: bold; color: #ff5722; font-size: 1.4em; margin-bottom: 15px; text-transform: uppercase;">ÉTAT : SOLIDE</div> <div style="width: 100%; background: #212121; color: #fff; padding: 15px; border-radius: 12px; font-family: monospace; border: 2px solid #444;"> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px;">ÉNERGIE TRANSFÉRÉE (Q)</div> <div id="q-val" style="font-size: 1.8em; color: #ffeb3b; margin: 5px 0;">0 J</div> <div style="color: #4db6ac; font-size: 0.8em; border-bottom: 1px solid #333; padding-bottom: 5px; margin-top: 15px;">FORMULE APPLIQUÉE</div> <div id="formule-text" style="font-size: 1.1em; color: #ffa726; margin-top: 5px;">Q = m · cₛ · ΔT</div> </div> <div id="specs-box" style="width: 100%; margin-top: 15px; background: #f9f9f9; padding: 15px; border-radius: 10px; border: 1px dashed #ccc; font-size: 0.85em;"> <b>Propriétés :</b> m = 1kg | P = 4500W<br> <span id="data-list"></span> </div> </div> <div style="flex: 2; min-width: 450px;"> <canvas id="graphSim" width="600" height="450" style="width: 100%; background: #fafafa; border-radius: 15px; border: 1px solid #eee;"></canvas> <div style="display: flex; gap: 15px; margin-top: 25px;"> <button id="btnPlay" onclick="toggleSim()" style="flex: 2; padding: 20px; font-size: 1.2em; font-weight: bold; background: #2e7d32; color: white; border: none; border-radius: 12px; cursor: pointer; box-shadow: 0 4px #1b5e20;">DÉMARRER LA SIMULATION</button> <button onclick="resetSim()" style="flex: 1; padding: 20px; background: #546e7a; color: white; border: none; border-radius: 12px; cursor: pointer; font-weight: bold;">RÉINITIALISER</button> </div> <div style="margin-top: 15px; font-size: 0.9em; color: #666; font-style: italic;"> Note : La simulation couvre la plage de -150°C à +150°C pour toutes les substances. </div> </div> </div> </div> <script> (function() { const bC = document.getElementById('beakerSim'), bCtx = bC.getContext('2d'); const gC = document.getElementById('graphSim'), gCtx = gC.getContext('2d'); const select = document.getElementById('selectFluide'); const db = { eau: { nom: "EAU (H₂O)", cs: 2090, cl: 4185, cg: 1850, lf: 334000, lv: 2260000, tf: 0, tv: 100, color: "#1565c0", maxQ: 4200000 }, ammoniac: { nom: "AMMONIAC (NH₃)", cs: 2100, cl: 4700, cg: 2050, lf: 332000, lv: 1370000, tf: -77.7, tv: -33.3, color: "#689f38", maxQ: 3200000 }, isobutane: { nom: "ISOBUTANE (C₄H₁₀)", cs: 1650, cl: 2350, cg: 1700, lf: 78000, lv: 366000, tf: -159.6, tv: -11.7, color: "#e65100", maxQ: 1800000 }, difluoro: { nom: "DIFLUOROMÉTHANE (R-32)", cs: 1450, cl: 1910, cg: 840, lf: 133000, lv: 390000, tf: -136, tv: -51.7, color: "#00796b", maxQ: 1500000 } }; let s, temp, energy, isRunning = false, pts = []; const pwr = 4500, masse = 1, tStart = -150, tEnd = 150; window.initSubstance = function() { s = db[select.value]; temp = tStart; energy = 0; pts = []; isRunning = false; document.getElementById('btnPlay').innerText = "DÉMARRER LA SIMULATION"; document.getElementById('btnPlay').style.background = "#2e7d32"; updateUI(); }; window.resetSim = function() { initSubstance(); }; window.toggleSim = function() { if(temp >= tEnd) return; isRunning = !isRunning; document.getElementById('btnPlay').innerText = isRunning ? "PAUSE" : "REPRENDRE"; document.getElementById('btnPlay').style.background = isRunning ? "#f57c00" : "#2e7d32"; }; function updateUI() { document.getElementById('temp-grand').innerText = temp.toFixed(1) + " °C"; document.getElementById('q-val').innerText = Math.floor(energy).toLocaleString() + " J"; document.getElementById('nom-substance').innerText = s.nom; document.getElementById('data-list').innerHTML = `cs = ${s.cs} J/kgK | Lf = ${s.lf/1000} kJ/kg | cl = ${s.cl} J/kgK | Lv = ${s.lv/1000} kJ/kg`; } function update() { if(!isRunning) return; if(temp >= tEnd) { isRunning = false; return; } energy += pwr * 2.0; // Calcul des paliers d'énergie // 1. Solide de tStart à tf (si tStart < tf) let q1 = (s.tf > tStart) ? masse * s.cs * (s.tf - tStart) : 0; // 2. Fusion let q2 = (s.tf > tStart) ? masse * s.lf : 0; // 3. Liquide de tf à tv let q3 = masse * s.cl * (s.tv - Math.max(tStart, s.tf)); // 4. Vaporisation let q4 = masse * s.lv; if (energy < q1) { temp = tStart + energy/(masse*s.cs); document.getElementById('etat-text').innerText = "ÉTAT : SOLIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₛ · ΔT"; } else if (energy < q1 + q2) { temp = s.tf; document.getElementById('etat-text').innerText = "ÉTAT : FUSION"; document.getElementById('formule-text').innerHTML = "Q = m · Lf"; } else if (energy < q1 + q2 + q3) { temp = Math.max(tStart, s.tf) + (energy - q1 - q2)/(masse*s.cl); document.getElementById('etat-text').innerText = "ÉTAT : LIQUIDE"; document.getElementById('formule-text').innerHTML = "Q = m · cₗ · ΔT"; } else if (energy < q1 + q2 + q3 + q4) { temp = s.tv; document.getElementById('etat-text').innerText = "ÉTAT : ÉBULLITION"; document.getElementById('formule-text').innerHTML = "Q = m · Lv"; } else { temp = s.tv + (energy - q1 - q2 - q3 - q4)/(masse*s.cg); document.getElementById('etat-text').innerText = "ÉTAT : GAZ"; document.getElementById('formule-text').innerHTML = "Q = m · cₚ · ΔT"; } if(temp > tEnd) temp = tEnd; pts.push({x: energy, y: temp}); updateUI(); } function draw() { bCtx.clearRect(0,0,220,300); let h = 140; if(temp < s.tf) bCtx.fillStyle = "#e3f2fd"; else if(temp < s.tv) bCtx.fillStyle = s.color; else bCtx.fillStyle = "rgba(150,150,150,0.4)"; bCtx.fillRect(10, 300-h, 200, h); gCtx.clearRect(0,0,600,450); gCtx.strokeStyle = "#333"; gCtx.lineWidth = 2; gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(60, 40); gCtx.stroke(); // Y gCtx.beginPath(); gCtx.moveTo(60, 400); gCtx.lineTo(580, 400); gCtx.stroke(); // X // Graduation Y gCtx.fillStyle = "#666"; gCtx.font = "10px Arial"; for(let t = -150; t <= 150; t += 50) { let y = 400 - ((t - tStart) / (tEnd - tStart)) * 340; gCtx.fillText(t + "°", 30, y + 5); gCtx.beginPath(); gCtx.moveTo(55, y); gCtx.lineTo(65, y); gCtx.stroke(); } if(pts.length > 0) { gCtx.beginPath(); gCtx.strokeStyle = s.color; gCtx.lineWidth = 4; pts.forEach((p, i) => { let px = 60 + (p.x / s.maxQ) * 500; let py = 400 - ((p.y - tStart) / (tEnd - tStart)) * 340; if(i===0) gCtx.moveTo(px, py); else gCtx.lineTo(px, py); }); gCtx.stroke(); } } function loop() { update(); draw(); requestAnimationFrame(loop); } initSubstance(); loop(); })(); </script>
PPCL TABLEAU
geogebra TABLEAU
https://www.pccl.fr/physique_chimie_college_lycee/lycee/seconde/tableau_avancement_reactif_limitant_proportions_stoechiometriques_exces_bilan_matiere_flash.htm
https://www.geogebra.org/m/fjxrxuuu
https://gayrard.netboard.me/mod6lisationdun/?tab=85756
https://physique-chimie.ac-normandie.fr/IMG/tableau_avancement/TA.htm
https://physique-chimie.ac-normandie.fr/spip.php?article188
https://laboiteaphysique.fr/site2/files/unites/co/module_Unites%20et%20puissances%20de%20dix_2.html
https://view.genially.com/60cba2a3df0d240ddc7ea29e/interactive-content-tableau-davancement
https://laboiteaphysique.fr/site2/index.php/les-fondamentaux#jl_magic_tabs_equilibrer_une_equation_chimique_gix5
https://qcm-sciencesphysiques.blogspot.com/p/1ere-s-qcm-7.html
minimal
Contextualize your topic
https://profed.fr/pro-ani.php?file=uploads_animations%2F1763910197_Eude+avancement+transformation+totale%281%29.swf
QUIZ
minimal
Contextualize your topic
https://www.quizz.biz/quizz-917291.html#google_vignette
https://profed.fr/pro-ani.php?file=uploads_animations%2F1763910197_Eude+avancement+transformation+totale%281%29.swf
https://chimie.ostralo.net/avancement/
QUIZ
minimal
Contextualize your topic
Contextualize your topic
https://www.ostralo.net/equationschimiques/pages/p2b.htm
https://profed.fr/pro-ani.php?file=uploads_animations%2F1763910197_Eude+avancement+transformation+totale%281%29.swf
EQUATION BILAN
https://qcm-sciencesphysiques.blogspot.com/p/1ere-s-qcm-7.html
https://www.ostralo.net/equationschimiques/pages/p2b.htm
EQUATION BILAN
https://profed.fr/pro-ani.php?file=uploads_animations%2F1763910197_Eude+avancement+transformation+totale%281%29.swf