'use strict'; // angle-conversion.cjs -- METHOD DECK (X063), reversible plane angle unit conversion. // The radian is the SI coherent unit for plane angle; degree, gradian, arcminute, and arcsecond // are non-SI units accepted for use with the SI, per the BIPM SI Brochure (9th edition, 2019). function roundSig(x, sig) { if (x === 0) return { value: 0, decimals: 0 }; const neg = x < 0; const ax = Math.abs(x); let exp = Math.floor(Math.log10(ax)); let decimals = Math.max(sig - exp - 1, 0); let factor = Math.pow(10, decimals); let value = Math.round(ax * factor) / factor; const newExp = value === 0 ? exp : Math.floor(Math.log10(value)); if (newExp !== exp) { decimals = Math.max(sig - newExp - 1, 0); factor = Math.pow(10, decimals); value = Math.round(ax * factor) / factor; } return { value: neg ? -value : value, decimals }; } function fmt(x, decimals) { return x.toLocaleString('en-US', { minimumFractionDigits: decimals, maximumFractionDigits: decimals }); } function fmtSig(x, sig) { const r = roundSig(x, sig); return fmt(r.value, r.decimals); } // Radians per 1 unit. const TO_RAD = { degree: Math.PI / 180, radian: 1, gradian: Math.PI / 200, arcminute: Math.PI / (180 * 60), arcsecond: Math.PI / (180 * 3600), }; const UNITS = Object.keys(TO_RAD); module.exports = { slug: 'angle-conversion', title: 'Angle conversion', deck_category: 'units', description: 'Converts a plane angle between degree, radian, gradian, arcminute, and arcsecond per the BIPM SI Brochure definitions.', inputs: [ { name: 'value', type: 'number', unit: 'from_unit', required: true, description: 'The angle to convert' }, { name: 'from_unit', type: 'string', required: true, description: 'Unit of the input value', enum: UNITS }, { name: 'to_unit', type: 'string', required: true, description: 'Unit to convert into', enum: UNITS }, ], outputs: [ { name: 'result', unit: 'to_unit', description: 'The converted angle' } ], steps: [ 'Look up the exact radian-equivalent of from_unit and of to_unit: degree = pi/180 rad; gradian = pi/200 rad; arcminute = pi/(180*60) rad; arcsecond = pi/(180*3600) rad.', 'Convert the input to radians: radians = value * rad_per(from_unit).', 'Convert radians to the target unit: result = radians / rad_per(to_unit).', 'Round result to 6 significant figures.', ], constants: [ { name: 'degree', value: Math.PI / 180, unit: 'rad', source: 0 }, { name: 'radian', value: 1, unit: 'rad', source: 0 }, { name: 'gradian', value: Math.PI / 200, unit: 'rad', source: 0 }, { name: 'arcminute', value: Math.PI / (180 * 60), unit: 'rad', source: 0 }, { name: 'arcsecond', value: Math.PI / (180 * 3600), unit: 'rad', source: 0 }, ], sources: [ { kind: 'standard', value: 'BIPM SI Brochure, 9th edition (2019), Table 8, "Non-SI units accepted for use with the SI": degree = (pi/180) rad; minute = (pi/10800) rad; second = (pi/648000) rad; gon/gradian = (pi/200) rad', title: 'The International System of Units (SI Brochure)', publisher: 'Bureau International des Poids et Mesures (BIPM)', retrieved_utc: '2026-09-30T19:29:48Z', note: '360 degrees = 400 gradians = 2*pi radians, all exact ratios of pi.' }, ], disclaimer: null, questionText(inputs) { return `How many ${inputs.to_unit} are in ${inputs.value} ${inputs.from_unit}?`; }, run(inputs) { const { value, from_unit, to_unit } = inputs || {}; if (typeof value !== 'number' || !isFinite(value)) throw new Error('value must be a finite number'); if (!TO_RAD.hasOwnProperty(from_unit)) throw new Error('from_unit must be one of: ' + UNITS.join(', ')); if (!TO_RAD.hasOwnProperty(to_unit)) throw new Error('to_unit must be one of: ' + UNITS.join(', ')); const rad = value * TO_RAD[from_unit]; const result = rad / TO_RAD[to_unit]; return { answer: `${fmtSig(result, 6)} ${to_unit}`, values: { result } }; }, examples: [ { name: 'worked example', inputs: { value: 180, from_unit: 'degree', to_unit: 'radian' }, expected: { answer: '3.14159 radian' }, check: 'By definition 180 degrees = pi radians = 3.14159265...; rounded to 6 significant figures is 3.14159.' }, { name: 'test vector: gradians to degrees', inputs: { value: 100, from_unit: 'gradian', to_unit: 'degree' }, expected: { answer: '90.0000 degree' }, check: 'By definition 400 gradians = 360 degrees, so 100 gradians = 90 degrees exactly.' }, { name: 'test vector: degree to arcminute', inputs: { value: 1, from_unit: 'degree', to_unit: 'arcminute' }, expected: { answer: '60.0000 arcminute' }, check: 'By definition 1 degree = 60 arcminutes exactly.' }, ], };