import{readVerniers,dualDifference,wrap}from'./angles.mjs';export{readVerniers,dualDifference,wrap};export const MODEL_VERSION='1.0.0',EXPERIMENT_ID='course-04/prism-apex';export const DEFAULTS=Object.freeze({apex_deg:60,zero_deg:10,eccentricity_arcmin:5}); export function validateParameters(p){for(const[k,l,h]of[['apex_deg',40,80],['zero_deg',0,360],['eccentricity_arcmin',0,10]])if(!Number.isFinite(p[k])||p[k]h)throw new RangeError(`${k}须在${l}–${h}`);return{...p};} export function forward(p){validateParameters(p);return{reference_deg:0,target_deg:2*p.apex_deg,apex_deg:p.apex_deg,true_value:p.apex_deg,unit:'deg'};} export function inverse(delta,p){validateParameters(p);return Math.abs(delta)/2;} 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};}