import{readVerniers,dualDifference,wrap}from'./angles.mjs';export{readVerniers,dualDifference,wrap};export const MODEL_VERSION='1.0.0',EXPERIMENT_ID='course-04/grazing-refraction';export const DEFAULTS=Object.freeze({liquid_index:1.33,prism_index:1.5425,zero_deg:10,eccentricity_arcmin:5}); export function validateParameters(p){for(const[k,l,h]of[['liquid_index',1.25,1.45],['prism_index',1.5,1.55],['zero_deg',0,360],['eccentricity_arcmin',0,10]])if(!Number.isFinite(p[k])||p[k]h)throw new RangeError(`${k}须在${l}–${h}`);const delta=p.prism_index**2-p.liquid_index**2;if(delta<=0||delta>=1)throw new RangeError('需要液体折射率低于棱镜且出射角存在');return{...p};} export function forward(p){validateParameters(p);return{reference_deg:0,target_deg:Math.asin(Math.sqrt(p.prism_index**2-p.liquid_index**2))*180/Math.PI,true_value:p.liquid_index,unit:'1',apex_deg:90};} export function inverse(delta,p){validateParameters(p);if(!Number.isFinite(delta)||Math.abs(delta)>=90)throw new RangeError('出射角须在−90°至90°之间');const radicand=p.prism_index**2-Math.sin(delta*Math.PI/180)**2;if(radicand<=0)throw new RangeError('反演条件不成立');return Math.sqrt(radicand);} export function measurement(p,source='ideal-model',start=null,end=null){validateParameters(p);if(!['ideal-model','manual-telescope'].includes(source))throw new RangeError('记录身份无效');const f=forward(p),a=source==='ideal-model'?readVerniers(f.reference_deg,p):start,b=source==='ideal-model'?readVerniers(f.target_deg,p):end;if(!a||!b)throw new RangeError('先保存基准与目标方向');const diff=dualDifference(a,b);return{experiment_id:EXPERIMENT_ID,model_version:MODEL_VERSION,source,parameters:{...p},start:a,end:b,...diff,estimate:inverse(diff.average_difference_deg,p),expected:f.true_value,unit:f.unit};}