export const MODEL_VERSION='1.0.0',DEFAULTS=Object.freeze({mode:'voltage',voltage:1.5,sourceResistance:1000,voltageRange:2,Rx:1500,multiplier:1,battery:1.5,zeroFactor:1}); export function validateParameters(p){if(!['voltage','resistance'].includes(p.mode)||![2,20,200].includes(p.voltageRange)||![1,10,100].includes(p.multiplier))throw new RangeError('功能/量程');for(const[k,a,b]of[['voltage',0,200],['sourceResistance',1,1e6],['Rx',0,1e6],['battery',.8,1.6],['zeroFactor',.5,1.2]])if(!Number.isFinite(p[k])||p[k]b)throw new RangeError(k);return{...p};} export function response(p){validateParameters(p);const rv=1e7,loaded=p.voltage*rv/(rv+p.sourceResistance),analogrv=20000*p.voltageRange,analogVoltage=p.voltage*analogrv/(analogrv+p.sourceResistance),step=p.voltageRange/2000,digitalVoltage=Math.round(loaded/step)*step,base=1500*p.multiplier,fraction=(p.battery/1.5)/(p.zeroFactor+p.Rx/base);return{mode:p.mode,digitalVoltage,analogVoltage,fraction,indicatedResistance:base*(1/fraction-1),inputLoadedVoltage:loaded,overrange:loaded>p.voltageRange,ohmOverZero:fraction>1};} export function plots(p){const rs=Array.from({length:201},(_,i)=>1e6*i/200),base=1500*p.multiplier;return[{caption:'串联欧姆表的非均匀刻度',xLabel:'Rx / Rb',yLabel:'偏转 I / Ig',curves:[{points:Array.from({length:201},(_,i)=>{const q=20*i/200;return[q,(p.battery/1.5)/(p.zeroFactor+q)];})}],selected:[p.Rx/base,response(p).fraction]},{caption:'源内阻对数字与指针电压表加载的影响',xLabel:'源内阻 Rs / Ω',yLabel:'电压读数 / V',legend:'实线:数字表 虚线:指针表',curves:['digitalVoltage','analogVoltage'].map(key=>({points:rs.map(sourceResistance=>[sourceResistance||1,response({...p,sourceResistance:sourceResistance||1})[key]])}))}];} export function analyzeRecords(rows,p){const s=rows.filter(r=>r.parameters.mode===p.mode);if(!s.length)return'选择功能和量程,读数前检查是否越量程;欧姆测量先短接调零。';const r=s.at(-1).readings;return p.mode==='voltage'?(r.overrange?'电压越量程,当前数值不是可读取的表内示值,请升档。':'已记录电压,比较源内阻造成的两表加载。'):(r.ohmOverZero?'指针越零,请短接调零。':'欧姆基准刻度示值 '+r.indicatedResistance.toFixed(5)+' Ω;教学真实电阻 '+s.at(-1).parameters.Rx+' Ω。');}