diff --git a/README.md b/README.md index 7af9363..a1ea479 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # BallisticCalculator -LGPL library for small arms ballistic calculations (JavaScript ES6+) +ISC library for small arms ballistic calculations (JavaScript ES6+) ### Table of contents * **[Installation](#installation)** diff --git a/__tests__/conditions.spec.js b/__tests__/conditions.spec.js new file mode 100644 index 0000000..35b9e6f --- /dev/null +++ b/__tests__/conditions.spec.js @@ -0,0 +1,76 @@ +import { + Atmo, + Wind, + Shot, + Unit, + calcSettings, + Distance, + Angular, + cStandardPressure, + cStandardTemperature +} from "../src/index"; + + +describe('Conditions', () => { + + describe("Atmo create", () => { + const atmo = Atmo.icao() + + test("Atmo altitude check", () => { + expect(atmo.altitude.in(Unit.Foot)).toBeCloseTo(0, 4); + }); + + test("Atmo pressure check", () => { + expect(atmo.pressure.in(Unit.InHg)).toBeCloseTo(cStandardPressure, 4); + }); + + test("Atmo temperature check", () => { + expect(atmo.temperature.in(Unit.Fahrenheit)).toBeCloseTo(cStandardTemperature, 4); + }); + + // FIXME: add methods tests + + }); + + describe("Wind create", () => { + const wind = new Wind(10, 10, 1000) + + test("Wind velocity check", () => { + expect(wind.velocity.in(calcSettings.Units.velocity)).toBeCloseTo(10, 4); + }); + + test("Wind direction check", () => { + expect(wind.directionFrom.in(calcSettings.Units.angular)).toBeCloseTo(10, 4); + }); + + test("Wind distance check", () => { + expect(wind.untilDistance.in(calcSettings.Units.distance)).toBeCloseTo(1000, 4); + }); + + // FIXME: add methods tests + + }); + + describe("Shot create", () => { + const shot = new Shot() + const atmo = Atmo.icao() + const winds = [new Wind()] + + test("Shot create check", () => { + expect(shot).toEqual( + { + maxRange: new Distance(1000, calcSettings.Units.distance), + zeroAngle: new Angular(0, calcSettings.Units.angular), + relativeAngle: new Angular(0, calcSettings.Units.angular), + cantAngle: new Angular(0, calcSettings.Units.angular), + atmo: atmo, + winds: winds + } + ); + }); + + // FIXME: add methods tests + + }); + +}); \ No newline at end of file diff --git a/__tests__/drag_tables.spec.js b/__tests__/drag_tables.spec.js new file mode 100644 index 0000000..c36b6ec --- /dev/null +++ b/__tests__/drag_tables.spec.js @@ -0,0 +1,9 @@ +import { DragTable } from "../src/index"; + +describe("Drag Tables", () => { + test("First element of TableG1 should have Mach: 0.00 and CD: 0.2629", () => { + const firstElement = DragTable.G1[0]; + expect(firstElement.Mach).toBeCloseTo(0.00, 4); // Adjust the precision as needed + expect(firstElement.CD).toBeCloseTo(0.2629, 4); // Adjust the precision as needed + }); +}); \ No newline at end of file diff --git a/__tests__/settings.spec.js b/__tests__/settings.spec.js new file mode 100644 index 0000000..b8d872c --- /dev/null +++ b/__tests__/settings.spec.js @@ -0,0 +1,32 @@ +import { Distance, calcSettings } from '../src/index'; + + +describe('Settings', () => { + + test('should initialize with default values', () => { + expect(calcSettings.USE_POWDER_SENSITIVITY).toBe(false); + expect(calcSettings._MAX_CALC_STEP_SIZE).toBe(1); + // Add more assertions for default unit values if needed + }); + + test('should set MAX_CALC_STEP_SIZE', () => { + const distanceValue = new Distance(100, Distance.Meter); // Replace with an appropriate value + calcSettings.setMaxCalcStepSize(distanceValue); + // Adjust the expectation based on the calculation in your implementation + expect(calcSettings._MAX_CALC_STEP_SIZE).toEqual(new Distance(100, Distance.Meter)); + }); + + test('should set MAX_CALC_STEP_SIZE', () => { + const distanceValue = 100; // Replace with an appropriate value + calcSettings.setMaxCalcStepSize(distanceValue); + // Adjust the expectation based on the calculation in your implementation + expect(calcSettings._MAX_CALC_STEP_SIZE).toEqual(new Distance(100, calcSettings.Units.distance)); + }); + + test('should modify USE_POWDER_SENSITIVITY', () => { + calcSettings.USE_POWDER_SENSITIVITY = true; + expect(calcSettings.USE_POWDER_SENSITIVITY).toBe(true); + }); + + // Add more tests as needed for other methods or scenarios +}); diff --git a/__tests__/units.spec.js b/__tests__/units.spec.js index 9723b95..71f951b 100644 --- a/__tests__/units.spec.js +++ b/__tests__/units.spec.js @@ -1,4 +1,4 @@ -import { AbstractUnit, Angular, Distance, Velocity, Weight, Temperature, Pressure, Energy, Unit, UnitPropsDict } from "../src/units.js"; +import { Angular, Distance, Velocity, Weight, Temperature, Pressure, Energy } from "../src/index"; describe('Ballistics Library Tests', () => { diff --git a/doc/units.md b/doc/units.md new file mode 100644 index 0000000..89d186a --- /dev/null +++ b/doc/units.md @@ -0,0 +1,241 @@ +# Units Module Documentation + +- [AbstractUnit Class](#abstractunit-class) + - [Constructor](#constructor) + - [Methods](#methods) + - [`toString(): string`](#tostring-string) + - [`_unit_support_error(value: number, units: Unit): number`](#_unit_support_error-value-number-units-unit-number) + - [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + - [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + - [`to(units: Unit): AbstractUnit`](#to-units-unit-abstractunit) + - [`in(units: Unit): number`](#in-units-unit-number) + - [`get units: Unit`](#get-units-unit) + - [`get rawValue: number`](#get-rawvalue-number) + +- [Angular Class (extends AbstractUnit)](#angular-class-extends-abstractunit) + - [Methods](#methods-1) + - [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + - [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + +- [Distance Class (extends AbstractUnit)](#distance-class-extends-abstractunit) + - [Methods](#methods-2) + - [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + - [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + +- [Velocity Class (extends AbstractUnit)](#velocity-class-extends-abstractunit) + - [Methods](#methods-3) + - [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + - [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + +- [Weight Class (extends AbstractUnit)](#weight-class-extends-abstractunit) + - [Methods](#methods-4) + - [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + - [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + +- [Pressure Class (extends AbstractUnit)](#pressure-class-extends-abstractunit) + - [Methods](#methods-5) + - [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + - [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + +- [Temperature Class (extends AbstractUnit)](#temperature-class-extends-abstractunit) + - [Methods](#methods-6) + - [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + - [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + +- [Energy Class (extends AbstractUnit)](#energy-class-extends-abstractunit) + - [Methods](#methods-7) + - [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + - [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + +- [Unit Enum](#unit-enum) +- [UnitPropsDict Object](#unitpropsdict-object) +- [unitTypeCoerce](#unittypecoerce) + + +## [AbstractUnit Class](#abstractunit-class) + +An abstract class for unit of measure instance definition. It stores the defined unit and value, and applies conversions to other units. + +### Constructor + +- **Parameters:** + - `value` (number): Numeric value of the unit. + - `units` (Unit): Unit as a Unit enum. + +### Methods + +#### [`toString(): string`](#tostring-string) + +Returns a human-readable representation of the value with its unit. + +#### [`_unit_support_error(value: number, units: Unit): number`](#_unit_support_error-value-number-units-unit-number) + +Validates the units. +- Parameters: + - `value` (number): Value of the unit. + - `units` (Unit): Unit enum type. +- Returns: number +- Throws: + - `TypeError` when the provided units are not of the expected type. + - `Error` when the provided units are not supported. + +#### [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + +Converts value with specified units to a raw value. + +#### [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + +Converts raw value to specified units. + +#### [`to(units: Unit): AbstractUnit`](#to-units-unit-abstractunit) + +Returns a new unit instance in specified units. + +#### [`in(units: Unit): number`](#in-units-unit-number) + +Returns value in specified units. + +#### [`get units: Unit`](#get-units-unit) + +Returns defined units. + +#### [`get rawValue: number`](#get-rawvalue-number) + +Raw unit value getter. + +--- + +## Angular Class (extends AbstractUnit) + +Angular unit class, extending [AbstractUnit](#abstractunit-class). + +### Methods + +#### [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + +Overrides the method in AbstractUnit to provide Angular-specific conversion logic. + +#### [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + +Overrides the method in AbstractUnit to provide Angular-specific conversion logic. + +--- + +## Distance Class (extends AbstractUnit) + +Distance unit class, extending [AbstractUnit](#abstractunit-class). + +### Methods + +#### [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + +Overrides the method in AbstractUnit to provide Distance-specific conversion logic. + +#### [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + +Overrides the method in AbstractUnit to provide Distance-specific conversion logic. + +--- + +## Velocity Class (extends AbstractUnit) + +Velocity unit class, extending [AbstractUnit](#abstractunit-class). + +### Methods + +#### [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + +Overrides the method in AbstractUnit to provide Velocity-specific conversion logic. + +#### [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + +Overrides the method in AbstractUnit to provide Velocity-specific conversion logic. + +--- + +## Weight Class (extends AbstractUnit) + +Weight unit class, extending [AbstractUnit](#abstractunit-class). + +### Methods + +#### [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + +Overrides the method in AbstractUnit to provide Weight-specific conversion logic. + +#### [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + +Overrides the method in AbstractUnit to provide Weight-specific conversion logic. + +--- + +## Pressure Class (extends AbstractUnit) + +Pressure unit class, extending [AbstractUnit](#abstractunit-class). + +### Methods + +#### [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + +Overrides the method in AbstractUnit to provide Pressure-specific conversion logic. + +#### [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + +Overrides the method in AbstractUnit to provide Pressure-specific conversion logic. + +--- + +## Temperature Class (extends AbstractUnit) + +Temperature unit class, extending [AbstractUnit](#abstractunit-class). + +### Methods + +#### [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + +Overrides the method in AbstractUnit to provide Temperature-specific conversion logic. + +#### [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + +Overrides the method in AbstractUnit to provide Temperature-specific conversion logic. + +--- + +## Energy Class (extends AbstractUnit) + +Energy unit class, extending [AbstractUnit](#abstractunit-class). + +### Methods + +#### [`toRaw(value: number, units: Unit): number`](#toraw-value-number-units-unit-number) + +Overrides the method in AbstractUnit to provide Energy-specific conversion logic. + +#### [`fromRaw(value: number, units: Unit): number`](#fromraw-value-number-units-unit-number) + +Overrides the method in AbstractUnit to provide Energy-specific conversion logic. + +--- + +## Unit Enum + +An enum representing unit types. + +--- + +## UnitPropsDict Object + +A dictionary of properties for the Unit enum type. + +--- + +## unitTypeCoerce + +Coerces the given instance to the specified class type or creates a new instance. +- Parameters: + - `instance` (Object): The instance to coerce or create. + - `expectedClass` (Class): The expected class type. + - `defaultUnit` (Unit): The default unit for creating a new instance. +- Returns: `AbstractUnit` or `Object` +- Throws: + - `TypeError` if the instance is \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7c525a3..a2d2970 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "js-ballistics", - "version": "1.0.2", + "version": "1.0.3-alpha.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "js-ballistics", - "version": "1.0.2", + "version": "1.0.3-alpha.2", "license": "ISC", "devDependencies": { "@babel/core": "^7.23.6", diff --git a/package.json b/package.json index c710cfe..3c50254 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "js-ballistics", - "version": "1.0.2", + "version": "1.0.3-alpha.2", "description": "ISC library for small arms ballistic calculations (JavaScript ES6+)", "main": "src/index.js", "scripts": { diff --git a/src/conditions.js b/src/conditions.js new file mode 100644 index 0000000..54b7165 --- /dev/null +++ b/src/conditions.js @@ -0,0 +1,222 @@ +// Classes to define zeroing or current environment conditions + +import calcSettings from './settings'; +import { Distance, Pressure, Temperature, Unit, Velocity, unitTypeCoerce, Angular } from './units.js'; + +// Constants for standard atmospheric conditions +export const cIcaoStandardTemperatureR = 518.67; +export const cIcaoFreezingPointTemperatureR = 459.67; +export const cTemperatureGradient = -3.56616e-03; +export const cIcaoStandardHumidity = 0.0; +export const cPressureExponent = -5.255876; +export const cSpeedOfSound = 49.0223; +export const cA0 = 1.24871; +export const cA1 = 0.0988438; +export const cA2 = 0.00152907; +export const cA3 = -3.07031e-06; +export const cA4 = 4.21329e-07; +export const cA5 = 3.342e-04; +export const cStandardTemperature = 59.0; +export const cStandardPressure = 29.92; +export const cStandardDensity = 0.076474; + +// Temperature difference between ICAO standard temperature and freezing point +const cIcaoTemperatureDeltaR = cIcaoStandardTemperatureR - cIcaoFreezingPointTemperatureR; + + + +class Atmo { + /** + * Stores atmosphere data for the trajectory calculation. + * @param {number | Distance} altitude - Altitude above sea level. + * @param {number | Pressure} pressure - Atmospheric pressure. + * @param {number | Temperature} temperature - Temperature in Fahrenheit. + * @param {number} humidity - Relative humidity (default: 0.78). + */ + constructor( + altitude = new Distance(0, Unit.Foot), + pressure = new Pressure(cStandardPressure, Unit.InHg), + temperature = new Temperature(cStandardTemperature, Unit.Fahrenheit), + humidity = 0.78 + ) { + // Coerce input values to appropriate units + this.altitude = unitTypeCoerce(altitude, Distance, calcSettings.Units.distance); + this.pressure = unitTypeCoerce(pressure, Pressure, calcSettings.Units.pressure); + this.temperature = unitTypeCoerce(temperature, Temperature, calcSettings.Units.temperature); + + // Ensure humidity is within the valid range [0, 1] + this.humidity = humidity > 1 ? humidity / 100 : humidity; + if (!(0 <= this.humidity && this.humidity <= 1)) { + this.humidity = 0.78; + } + + // Constants and initializations + this._mach1 = cSpeedOfSound; + this._a0 = this.altitude.in(Unit.Foot); + this._t0 = this.temperature.in(Unit.Fahrenheit); + this._p0 = this.pressure.in(Unit.InHg); + this._ta = this._a0 * cTemperatureGradient + cIcaoTemperatureDeltaR; + + // Perform initial calculations + this.calculate(); + } + + /** + * Creates Atmosphere with ICAO standard values. + * @param {number | Distance} altitude - Altitude above sea level (default: 0 foot). + * @returns {Atmo} - Atmo instance with ICAO standard values. + */ + static icao(altitude = new Distance(0, Unit.Foot)) { + // Coerce altitude to appropriate units + const _altitude = unitTypeCoerce(altitude, Distance, calcSettings.Units.distance); + + // Calculate temperature based on ICAO standard values + const temperature = new Temperature( + cIcaoStandardTemperatureR + (_altitude.in(Distance.Foot)) + * cTemperatureGradient - cIcaoFreezingPointTemperatureR, + Unit.Fahrenheit + ); + + // Calculate pressure based on ICAO standard values + const pressure = new Pressure( + cStandardPressure * Math.pow(cIcaoStandardTemperatureR / ( + (temperature.in(Temperature.Fahrenheit) + cIcaoFreezingPointTemperatureR)), + cPressureExponent + ), Unit.InHg + ); + + // Create and return Atmo instance with ICAO values + return new Atmo( + altitude, + pressure, + temperature, + cIcaoStandardHumidity + ); + } + + /** + * Prepares the data for trajectory calculation. + * Calculates density and Mach number using the current atmosphere conditions. + */ + calculate() { + const { density, mach } = this.calculate0(this._t0, this._p0); + + // Update instance properties with calculated values + this.density = density; + this._mach1 = mach; + this.mach = new Velocity(this._mach1, Velocity.FPS); + } + + /** + * Calculates density and Mach number with specified atmosphere conditions. + * @param {number} t - Temperature in Fahrenheit. + * @param {number} p - Atmospheric pressure in InHg. + * @returns {{density: number, mach: number}} - Calculated density and Mach number. + */ + calculate0(t, p) { + let hc = 0; + + // Calculate humidity correction factor + if (t > 0) { + let et0 = cA0 + t * (cA1 + t * (cA2 + t * (cA3 + t * cA4))); + let et = cA5 * this.humidity * et0; + hc = (p - 0.3783 * et) / cStandardPressure; + } + + // Calculate density and Mach number + let density = cStandardDensity * ( + cIcaoStandardTemperatureR / (t + cIcaoFreezingPointTemperatureR) + ) * hc; + let mach = Math.sqrt(t + cIcaoFreezingPointTemperatureR) * cSpeedOfSound; + + // Return calculated values + return { density, mach }; + } + + /** + * Calculates and returns the projectile density factor. + * @return {number} - Projectile density factor. + */ + densityFactor() { + return this.density / cStandardDensity; + } + + /** + * Calculates density factor and Mach number for the specified altitude. + * @param {number} altitude - Altitude above sea level. + * @return {{density: number, mach: number}} - Density factor and Mach number for the specified altitude. + */ + getDensityFactorAndMachForAltitude(altitude) { + if (Math.abs(this._a0 - altitude) < 30) { + // Use pre-calculated values for nearby altitudes + return { density: this.density / cStandardDensity, mach: this._mach1 }; + } + + // Calculate new atmosphere conditions for the specified altitude + const tb = altitude * cTemperatureGradient + cIcaoTemperatureDeltaR; + const t = this._t0 + this._ta - tb; + const p = this._p0 * Math.pow(this._t0 / t, cPressureExponent); + const { density, mach } = this.calculate0(t, p); + + // Return calculated values + return { density: density / cStandardDensity, mach }; + } +} + + +class Wind { + /** + * Stores wind data at the desired distance. + * @param {number | Velocity} velocity - Wind velocity. + * @param {number | Angular} directionFrom - Wind direction in relation to the shooter. + * @param {number | Distance} untilDistance - Distance up to which the wind data is applicable. + */ + constructor( + velocity = new Velocity(0, Unit.MPS), + directionFrom = new Angular(0, Unit.MIL), + untilDistance = new Distance(9999, Unit.Meter) + ) { + // Coerce input values to appropriate units + this.velocity = unitTypeCoerce(velocity, Velocity, calcSettings.Units.velocity); + this.directionFrom = unitTypeCoerce(directionFrom, Angular, calcSettings.Units.angular); + this.untilDistance = unitTypeCoerce(untilDistance, Distance, calcSettings.Units.distance); + } + +} + + +class Shot { + /** + * Stores shot parameters for the trajectory calculation. + * @param {number | Distance} maxRange - Downrange distance to stop computing trajectory. + * @param {number | Angular} zeroAngle - The angle between the barrel and horizontal when zeroed. + * @param {number | Angular} relativeAngle - Elevation adjustment added to zero_angle for a particular shot. + * @param {number | Angular} cantAngle - Rotation of the gun around the barrel axis, relative to position when zeroed. + * (Only relevant when Weapon.sight_height !== 0) + * @param {Atmo} atmo - Atmosphere conditions for the shot (default: ICAO standard atmosphere). + * @param {Wind[]} winds - Array of wind conditions affecting the shot (default: no wind). + */ + constructor( + maxRange = new Distance(1000, Unit.Yard), + zeroAngle = new Angular(0, Unit.Degree), + relativeAngle = new Angular(0, Unit.Degree), + cantAngle = new Angular(0, Unit.Degree), + atmo = Atmo.icao(), + winds = [new Wind()] + ) { + // Coerce input values to appropriate units + this.maxRange = unitTypeCoerce(maxRange, Distance, calcSettings.Units.distance); + this.zeroAngle = unitTypeCoerce(zeroAngle, Angular, calcSettings.Units.angular); + this.relativeAngle = unitTypeCoerce(relativeAngle, Angular, calcSettings.Units.angular); + this.cantAngle = unitTypeCoerce(cantAngle, Angular, calcSettings.Units.angular); + + // Set atmosphere and wind conditions + this.atmo = atmo; + this.winds = winds; + } + + // Other methods and properties can be added here +} + + +export { Atmo, Wind, Shot }; diff --git a/src/drag_tables.json b/src/drag_tables.json new file mode 100644 index 0000000..da504d3 --- /dev/null +++ b/src/drag_tables.json @@ -0,0 +1,2590 @@ +{ + "G1": [ + { + "Mach": 0.00, + "CD": 0.2629 + }, + { + "Mach": 0.05, + "CD": 0.2558 + }, + { + "Mach": 0.10, + "CD": 0.2487 + }, + { + "Mach": 0.15, + "CD": 0.2413 + }, + { + "Mach": 0.20, + "CD": 0.2344 + }, + { + "Mach": 0.25, + "CD": 0.2278 + }, + { + "Mach": 0.30, + "CD": 0.2214 + }, + { + "Mach": 0.35, + "CD": 0.2155 + }, + { + "Mach": 0.40, + "CD": 0.2104 + }, + { + "Mach": 0.45, + "CD": 0.2061 + }, + { + "Mach": 0.50, + "CD": 0.2032 + }, + { + "Mach": 0.55, + "CD": 0.2020 + }, + { + "Mach": 0.60, + "CD": 0.2034 + }, + { + "Mach": 0.70, + "CD": 0.2165 + }, + { + "Mach": 0.725, + "CD": 0.2230 + }, + { + "Mach": 0.75, + "CD": 0.2313 + }, + { + "Mach": 0.775, + "CD": 0.2417 + }, + { + "Mach": 0.80, + "CD": 0.2546 + }, + { + "Mach": 0.825, + "CD": 0.2706 + }, + { + "Mach": 0.85, + "CD": 0.2901 + }, + { + "Mach": 0.875, + "CD": 0.3136 + }, + { + "Mach": 0.90, + "CD": 0.3415 + }, + { + "Mach": 0.925, + "CD": 0.3734 + }, + { + "Mach": 0.95, + "CD": 0.4084 + }, + { + "Mach": 0.975, + "CD": 0.4448 + }, + { + "Mach": 1.0, + "CD": 0.4805 + }, + { + "Mach": 1.025, + "CD": 0.5136 + }, + { + "Mach": 1.05, + "CD": 0.5427 + }, + { + "Mach": 1.075, + "CD": 0.5677 + }, + { + "Mach": 1.10, + "CD": 0.5883 + }, + { + "Mach": 1.125, + "CD": 0.6053 + }, + { + "Mach": 1.15, + "CD": 0.6191 + }, + { + "Mach": 1.20, + "CD": 0.6393 + }, + { + "Mach": 1.25, + "CD": 0.6518 + }, + { + "Mach": 1.30, + "CD": 0.6589 + }, + { + "Mach": 1.35, + "CD": 0.6621 + }, + { + "Mach": 1.40, + "CD": 0.6625 + }, + { + "Mach": 1.45, + "CD": 0.6607 + }, + { + "Mach": 1.50, + "CD": 0.6573 + }, + { + "Mach": 1.55, + "CD": 0.6528 + }, + { + "Mach": 1.60, + "CD": 0.6474 + }, + { + "Mach": 1.65, + "CD": 0.6413 + }, + { + "Mach": 1.70, + "CD": 0.6347 + }, + { + "Mach": 1.75, + "CD": 0.6280 + }, + { + "Mach": 1.80, + "CD": 0.6210 + }, + { + "Mach": 1.85, + "CD": 0.6141 + }, + { + "Mach": 1.90, + "CD": 0.6072 + }, + { + "Mach": 1.95, + "CD": 0.6003 + }, + { + "Mach": 2.00, + "CD": 0.5934 + }, + { + "Mach": 2.05, + "CD": 0.5867 + }, + { + "Mach": 2.10, + "CD": 0.5804 + }, + { + "Mach": 2.15, + "CD": 0.5743 + }, + { + "Mach": 2.20, + "CD": 0.5685 + }, + { + "Mach": 2.25, + "CD": 0.5630 + }, + { + "Mach": 2.30, + "CD": 0.5577 + }, + { + "Mach": 2.35, + "CD": 0.5527 + }, + { + "Mach": 2.40, + "CD": 0.5481 + }, + { + "Mach": 2.45, + "CD": 0.5438 + }, + { + "Mach": 2.50, + "CD": 0.5397 + }, + { + "Mach": 2.60, + "CD": 0.5325 + }, + { + "Mach": 2.70, + "CD": 0.5264 + }, + { + "Mach": 2.80, + "CD": 0.5211 + }, + { + "Mach": 2.90, + "CD": 0.5168 + }, + { + "Mach": 3.00, + "CD": 0.5133 + }, + { + "Mach": 3.10, + "CD": 0.5105 + }, + { + "Mach": 3.20, + "CD": 0.5084 + }, + { + "Mach": 3.30, + "CD": 0.5067 + }, + { + "Mach": 3.40, + "CD": 0.5054 + }, + { + "Mach": 3.50, + "CD": 0.5040 + }, + { + "Mach": 3.60, + "CD": 0.5030 + }, + { + "Mach": 3.70, + "CD": 0.5022 + }, + { + "Mach": 3.80, + "CD": 0.5016 + }, + { + "Mach": 3.90, + "CD": 0.5010 + }, + { + "Mach": 4.00, + "CD": 0.5006 + }, + { + "Mach": 4.20, + "CD": 0.4998 + }, + { + "Mach": 4.40, + "CD": 0.4995 + }, + { + "Mach": 4.60, + "CD": 0.4992 + }, + { + "Mach": 4.80, + "CD": 0.4990 + }, + { + "Mach": 5.00, + "CD": 0.4988 + } + ], + "G7": [ + { + "Mach": 0.00, + "CD": 0.1198 + }, + { + "Mach": 0.05, + "CD": 0.1197 + }, + { + "Mach": 0.10, + "CD": 0.1196 + }, + { + "Mach": 0.15, + "CD": 0.1194 + }, + { + "Mach": 0.20, + "CD": 0.1193 + }, + { + "Mach": 0.25, + "CD": 0.1194 + }, + { + "Mach": 0.30, + "CD": 0.1194 + }, + { + "Mach": 0.35, + "CD": 0.1194 + }, + { + "Mach": 0.40, + "CD": 0.1193 + }, + { + "Mach": 0.45, + "CD": 0.1193 + }, + { + "Mach": 0.50, + "CD": 0.1194 + }, + { + "Mach": 0.55, + "CD": 0.1193 + }, + { + "Mach": 0.60, + "CD": 0.1194 + }, + { + "Mach": 0.65, + "CD": 0.1197 + }, + { + "Mach": 0.70, + "CD": 0.1202 + }, + { + "Mach": 0.725, + "CD": 0.1207 + }, + { + "Mach": 0.75, + "CD": 0.1215 + }, + { + "Mach": 0.775, + "CD": 0.1226 + }, + { + "Mach": 0.80, + "CD": 0.1242 + }, + { + "Mach": 0.825, + "CD": 0.1266 + }, + { + "Mach": 0.85, + "CD": 0.1306 + }, + { + "Mach": 0.875, + "CD": 0.1368 + }, + { + "Mach": 0.90, + "CD": 0.1464 + }, + { + "Mach": 0.925, + "CD": 0.1660 + }, + { + "Mach": 0.95, + "CD": 0.2054 + }, + { + "Mach": 0.975, + "CD": 0.2993 + }, + { + "Mach": 1.0, + "CD": 0.3803 + }, + { + "Mach": 1.025, + "CD": 0.4015 + }, + { + "Mach": 1.05, + "CD": 0.4043 + }, + { + "Mach": 1.075, + "CD": 0.4034 + }, + { + "Mach": 1.10, + "CD": 0.4014 + }, + { + "Mach": 1.125, + "CD": 0.3987 + }, + { + "Mach": 1.15, + "CD": 0.3955 + }, + { + "Mach": 1.20, + "CD": 0.3884 + }, + { + "Mach": 1.25, + "CD": 0.3810 + }, + { + "Mach": 1.30, + "CD": 0.3732 + }, + { + "Mach": 1.35, + "CD": 0.3657 + }, + { + "Mach": 1.40, + "CD": 0.3580 + }, + { + "Mach": 1.50, + "CD": 0.3440 + }, + { + "Mach": 1.55, + "CD": 0.3376 + }, + { + "Mach": 1.60, + "CD": 0.3315 + }, + { + "Mach": 1.65, + "CD": 0.3260 + }, + { + "Mach": 1.70, + "CD": 0.3209 + }, + { + "Mach": 1.75, + "CD": 0.3160 + }, + { + "Mach": 1.80, + "CD": 0.3117 + }, + { + "Mach": 1.85, + "CD": 0.3078 + }, + { + "Mach": 1.90, + "CD": 0.3042 + }, + { + "Mach": 1.95, + "CD": 0.3010 + }, + { + "Mach": 2.00, + "CD": 0.2980 + }, + { + "Mach": 2.05, + "CD": 0.2951 + }, + { + "Mach": 2.10, + "CD": 0.2922 + }, + { + "Mach": 2.15, + "CD": 0.2892 + }, + { + "Mach": 2.20, + "CD": 0.2864 + }, + { + "Mach": 2.25, + "CD": 0.2835 + }, + { + "Mach": 2.30, + "CD": 0.2807 + }, + { + "Mach": 2.35, + "CD": 0.2779 + }, + { + "Mach": 2.40, + "CD": 0.2752 + }, + { + "Mach": 2.45, + "CD": 0.2725 + }, + { + "Mach": 2.50, + "CD": 0.2697 + }, + { + "Mach": 2.55, + "CD": 0.2670 + }, + { + "Mach": 2.60, + "CD": 0.2643 + }, + { + "Mach": 2.65, + "CD": 0.2615 + }, + { + "Mach": 2.70, + "CD": 0.2588 + }, + { + "Mach": 2.75, + "CD": 0.2561 + }, + { + "Mach": 2.80, + "CD": 0.2533 + }, + { + "Mach": 2.85, + "CD": 0.2506 + }, + { + "Mach": 2.90, + "CD": 0.2479 + }, + { + "Mach": 2.95, + "CD": 0.2451 + }, + { + "Mach": 3.00, + "CD": 0.2424 + }, + { + "Mach": 3.10, + "CD": 0.2368 + }, + { + "Mach": 3.20, + "CD": 0.2313 + }, + { + "Mach": 3.30, + "CD": 0.2258 + }, + { + "Mach": 3.40, + "CD": 0.2205 + }, + { + "Mach": 3.50, + "CD": 0.2154 + }, + { + "Mach": 3.60, + "CD": 0.2106 + }, + { + "Mach": 3.70, + "CD": 0.2060 + }, + { + "Mach": 3.80, + "CD": 0.2017 + }, + { + "Mach": 3.90, + "CD": 0.1975 + }, + { + "Mach": 4.00, + "CD": 0.1935 + }, + { + "Mach": 4.20, + "CD": 0.1861 + }, + { + "Mach": 4.40, + "CD": 0.1793 + }, + { + "Mach": 4.60, + "CD": 0.1730 + }, + { + "Mach": 4.80, + "CD": 0.1672 + }, + { + "Mach": 5.00, + "CD": 0.1618 + } + ], + "G2": [ + { + "Mach": 0.00, + "CD": 0.2303 + }, + { + "Mach": 0.05, + "CD": 0.2298 + }, + { + "Mach": 0.10, + "CD": 0.2287 + }, + { + "Mach": 0.15, + "CD": 0.2271 + }, + { + "Mach": 0.20, + "CD": 0.2251 + }, + { + "Mach": 0.25, + "CD": 0.2227 + }, + { + "Mach": 0.30, + "CD": 0.2196 + }, + { + "Mach": 0.35, + "CD": 0.2156 + }, + { + "Mach": 0.40, + "CD": 0.2107 + }, + { + "Mach": 0.45, + "CD": 0.2048 + }, + { + "Mach": 0.50, + "CD": 0.1980 + }, + { + "Mach": 0.55, + "CD": 0.1905 + }, + { + "Mach": 0.60, + "CD": 0.1828 + }, + { + "Mach": 0.65, + "CD": 0.1758 + }, + { + "Mach": 0.70, + "CD": 0.1702 + }, + { + "Mach": 0.75, + "CD": 0.1669 + }, + { + "Mach": 0.775, + "CD": 0.1664 + }, + { + "Mach": 0.80, + "CD": 0.1667 + }, + { + "Mach": 0.825, + "CD": 0.1682 + }, + { + "Mach": 0.85, + "CD": 0.1711 + }, + { + "Mach": 0.875, + "CD": 0.1761 + }, + { + "Mach": 0.90, + "CD": 0.1831 + }, + { + "Mach": 0.925, + "CD": 0.2004 + }, + { + "Mach": 0.95, + "CD": 0.2589 + }, + { + "Mach": 0.975, + "CD": 0.3492 + }, + { + "Mach": 1.0, + "CD": 0.3983 + }, + { + "Mach": 1.025, + "CD": 0.4075 + }, + { + "Mach": 1.05, + "CD": 0.4103 + }, + { + "Mach": 1.075, + "CD": 0.4114 + }, + { + "Mach": 1.10, + "CD": 0.4106 + }, + { + "Mach": 1.125, + "CD": 0.4089 + }, + { + "Mach": 1.15, + "CD": 0.4068 + }, + { + "Mach": 1.175, + "CD": 0.4046 + }, + { + "Mach": 1.20, + "CD": 0.4021 + }, + { + "Mach": 1.25, + "CD": 0.3966 + }, + { + "Mach": 1.30, + "CD": 0.3904 + }, + { + "Mach": 1.35, + "CD": 0.3835 + }, + { + "Mach": 1.40, + "CD": 0.3759 + }, + { + "Mach": 1.45, + "CD": 0.3678 + }, + { + "Mach": 1.50, + "CD": 0.3594 + }, + { + "Mach": 1.55, + "CD": 0.3512 + }, + { + "Mach": 1.60, + "CD": 0.3432 + }, + { + "Mach": 1.65, + "CD": 0.3356 + }, + { + "Mach": 1.70, + "CD": 0.3282 + }, + { + "Mach": 1.75, + "CD": 0.3213 + }, + { + "Mach": 1.80, + "CD": 0.3149 + }, + { + "Mach": 1.85, + "CD": 0.3089 + }, + { + "Mach": 1.90, + "CD": 0.3033 + }, + { + "Mach": 1.95, + "CD": 0.2982 + }, + { + "Mach": 2.00, + "CD": 0.2933 + }, + { + "Mach": 2.05, + "CD": 0.2889 + }, + { + "Mach": 2.10, + "CD": 0.2846 + }, + { + "Mach": 2.15, + "CD": 0.2806 + }, + { + "Mach": 2.20, + "CD": 0.2768 + }, + { + "Mach": 2.25, + "CD": 0.2731 + }, + { + "Mach": 2.30, + "CD": 0.2696 + }, + { + "Mach": 2.35, + "CD": 0.2663 + }, + { + "Mach": 2.40, + "CD": 0.2632 + }, + { + "Mach": 2.45, + "CD": 0.2602 + }, + { + "Mach": 2.50, + "CD": 0.2572 + }, + { + "Mach": 2.55, + "CD": 0.2543 + }, + { + "Mach": 2.60, + "CD": 0.2515 + }, + { + "Mach": 2.65, + "CD": 0.2487 + }, + { + "Mach": 2.70, + "CD": 0.2460 + }, + { + "Mach": 2.75, + "CD": 0.2433 + }, + { + "Mach": 2.80, + "CD": 0.2408 + }, + { + "Mach": 2.85, + "CD": 0.2382 + }, + { + "Mach": 2.90, + "CD": 0.2357 + }, + { + "Mach": 2.95, + "CD": 0.2333 + }, + { + "Mach": 3.00, + "CD": 0.2309 + }, + { + "Mach": 3.10, + "CD": 0.2262 + }, + { + "Mach": 3.20, + "CD": 0.2217 + }, + { + "Mach": 3.30, + "CD": 0.2173 + }, + { + "Mach": 3.40, + "CD": 0.2132 + }, + { + "Mach": 3.50, + "CD": 0.2091 + }, + { + "Mach": 3.60, + "CD": 0.2052 + }, + { + "Mach": 3.70, + "CD": 0.2014 + }, + { + "Mach": 3.80, + "CD": 0.1978 + }, + { + "Mach": 3.90, + "CD": 0.1944 + }, + { + "Mach": 4.00, + "CD": 0.1912 + }, + { + "Mach": 4.20, + "CD": 0.1851 + }, + { + "Mach": 4.40, + "CD": 0.1794 + }, + { + "Mach": 4.60, + "CD": 0.1741 + }, + { + "Mach": 4.80, + "CD": 0.1693 + }, + { + "Mach": 5.00, + "CD": 0.1648 + } + ], + "G5": [ + { + "Mach": 0.00, + "CD": 0.1710 + }, + { + "Mach": 0.05, + "CD": 0.1719 + }, + { + "Mach": 0.10, + "CD": 0.1727 + }, + { + "Mach": 0.15, + "CD": 0.1732 + }, + { + "Mach": 0.20, + "CD": 0.1734 + }, + { + "Mach": 0.25, + "CD": 0.1730 + }, + { + "Mach": 0.30, + "CD": 0.1718 + }, + { + "Mach": 0.35, + "CD": 0.1696 + }, + { + "Mach": 0.40, + "CD": 0.1668 + }, + { + "Mach": 0.45, + "CD": 0.1637 + }, + { + "Mach": 0.50, + "CD": 0.1603 + }, + { + "Mach": 0.55, + "CD": 0.1566 + }, + { + "Mach": 0.60, + "CD": 0.1529 + }, + { + "Mach": 0.65, + "CD": 0.1497 + }, + { + "Mach": 0.70, + "CD": 0.1473 + }, + { + "Mach": 0.75, + "CD": 0.1463 + }, + { + "Mach": 0.80, + "CD": 0.1489 + }, + { + "Mach": 0.85, + "CD": 0.1583 + }, + { + "Mach": 0.875, + "CD": 0.1672 + }, + { + "Mach": 0.90, + "CD": 0.1815 + }, + { + "Mach": 0.925, + "CD": 0.2051 + }, + { + "Mach": 0.95, + "CD": 0.2413 + }, + { + "Mach": 0.975, + "CD": 0.2884 + }, + { + "Mach": 1.0, + "CD": 0.3379 + }, + { + "Mach": 1.025, + "CD": 0.3785 + }, + { + "Mach": 1.05, + "CD": 0.4032 + }, + { + "Mach": 1.075, + "CD": 0.4147 + }, + { + "Mach": 1.10, + "CD": 0.4201 + }, + { + "Mach": 1.15, + "CD": 0.4278 + }, + { + "Mach": 1.20, + "CD": 0.4338 + }, + { + "Mach": 1.25, + "CD": 0.4373 + }, + { + "Mach": 1.30, + "CD": 0.4392 + }, + { + "Mach": 1.35, + "CD": 0.4403 + }, + { + "Mach": 1.40, + "CD": 0.4406 + }, + { + "Mach": 1.45, + "CD": 0.4401 + }, + { + "Mach": 1.50, + "CD": 0.4386 + }, + { + "Mach": 1.55, + "CD": 0.4362 + }, + { + "Mach": 1.60, + "CD": 0.4328 + }, + { + "Mach": 1.65, + "CD": 0.4286 + }, + { + "Mach": 1.70, + "CD": 0.4237 + }, + { + "Mach": 1.75, + "CD": 0.4182 + }, + { + "Mach": 1.80, + "CD": 0.4121 + }, + { + "Mach": 1.85, + "CD": 0.4057 + }, + { + "Mach": 1.90, + "CD": 0.3991 + }, + { + "Mach": 1.95, + "CD": 0.3926 + }, + { + "Mach": 2.00, + "CD": 0.3861 + }, + { + "Mach": 2.05, + "CD": 0.3800 + }, + { + "Mach": 2.10, + "CD": 0.3741 + }, + { + "Mach": 2.15, + "CD": 0.3684 + }, + { + "Mach": 2.20, + "CD": 0.3630 + }, + { + "Mach": 2.25, + "CD": 0.3578 + }, + { + "Mach": 2.30, + "CD": 0.3529 + }, + { + "Mach": 2.35, + "CD": 0.3481 + }, + { + "Mach": 2.40, + "CD": 0.3435 + }, + { + "Mach": 2.45, + "CD": 0.3391 + }, + { + "Mach": 2.50, + "CD": 0.3349 + }, + { + "Mach": 2.60, + "CD": 0.3269 + }, + { + "Mach": 2.70, + "CD": 0.3194 + }, + { + "Mach": 2.80, + "CD": 0.3125 + }, + { + "Mach": 2.90, + "CD": 0.3060 + }, + { + "Mach": 3.00, + "CD": 0.2999 + }, + { + "Mach": 3.10, + "CD": 0.2942 + }, + { + "Mach": 3.20, + "CD": 0.2889 + }, + { + "Mach": 3.30, + "CD": 0.2838 + }, + { + "Mach": 3.40, + "CD": 0.2790 + }, + { + "Mach": 3.50, + "CD": 0.2745 + }, + { + "Mach": 3.60, + "CD": 0.2703 + }, + { + "Mach": 3.70, + "CD": 0.2662 + }, + { + "Mach": 3.80, + "CD": 0.2624 + }, + { + "Mach": 3.90, + "CD": 0.2588 + }, + { + "Mach": 4.00, + "CD": 0.2553 + }, + { + "Mach": 4.20, + "CD": 0.2488 + }, + { + "Mach": 4.40, + "CD": 0.2429 + }, + { + "Mach": 4.60, + "CD": 0.2376 + }, + { + "Mach": 4.80, + "CD": 0.2326 + }, + { + "Mach": 5.00, + "CD": 0.2280 + } + ], + "G6": [ + { + "Mach": 0.00, + "CD": 0.2617 + }, + { + "Mach": 0.05, + "CD": 0.2553 + }, + { + "Mach": 0.10, + "CD": 0.2491 + }, + { + "Mach": 0.15, + "CD": 0.2432 + }, + { + "Mach": 0.20, + "CD": 0.2376 + }, + { + "Mach": 0.25, + "CD": 0.2324 + }, + { + "Mach": 0.30, + "CD": 0.2278 + }, + { + "Mach": 0.35, + "CD": 0.2238 + }, + { + "Mach": 0.40, + "CD": 0.2205 + }, + { + "Mach": 0.45, + "CD": 0.2177 + }, + { + "Mach": 0.50, + "CD": 0.2155 + }, + { + "Mach": 0.55, + "CD": 0.2138 + }, + { + "Mach": 0.60, + "CD": 0.2126 + }, + { + "Mach": 0.65, + "CD": 0.2121 + }, + { + "Mach": 0.70, + "CD": 0.2122 + }, + { + "Mach": 0.75, + "CD": 0.2132 + }, + { + "Mach": 0.80, + "CD": 0.2154 + }, + { + "Mach": 0.85, + "CD": 0.2194 + }, + { + "Mach": 0.875, + "CD": 0.2229 + }, + { + "Mach": 0.90, + "CD": 0.2297 + }, + { + "Mach": 0.925, + "CD": 0.2449 + }, + { + "Mach": 0.95, + "CD": 0.2732 + }, + { + "Mach": 0.975, + "CD": 0.3141 + }, + { + "Mach": 1.0, + "CD": 0.3597 + }, + { + "Mach": 1.025, + "CD": 0.3994 + }, + { + "Mach": 1.05, + "CD": 0.4261 + }, + { + "Mach": 1.075, + "CD": 0.4402 + }, + { + "Mach": 1.10, + "CD": 0.4465 + }, + { + "Mach": 1.125, + "CD": 0.4490 + }, + { + "Mach": 1.15, + "CD": 0.4497 + }, + { + "Mach": 1.175, + "CD": 0.4494 + }, + { + "Mach": 1.20, + "CD": 0.4482 + }, + { + "Mach": 1.225, + "CD": 0.4464 + }, + { + "Mach": 1.25, + "CD": 0.4441 + }, + { + "Mach": 1.30, + "CD": 0.4390 + }, + { + "Mach": 1.35, + "CD": 0.4336 + }, + { + "Mach": 1.40, + "CD": 0.4279 + }, + { + "Mach": 1.45, + "CD": 0.4221 + }, + { + "Mach": 1.50, + "CD": 0.4162 + }, + { + "Mach": 1.55, + "CD": 0.4102 + }, + { + "Mach": 1.60, + "CD": 0.4042 + }, + { + "Mach": 1.65, + "CD": 0.3981 + }, + { + "Mach": 1.70, + "CD": 0.3919 + }, + { + "Mach": 1.75, + "CD": 0.3855 + }, + { + "Mach": 1.80, + "CD": 0.3788 + }, + { + "Mach": 1.85, + "CD": 0.3721 + }, + { + "Mach": 1.90, + "CD": 0.3652 + }, + { + "Mach": 1.95, + "CD": 0.3583 + }, + { + "Mach": 2.00, + "CD": 0.3515 + }, + { + "Mach": 2.05, + "CD": 0.3447 + }, + { + "Mach": 2.10, + "CD": 0.3381 + }, + { + "Mach": 2.15, + "CD": 0.3314 + }, + { + "Mach": 2.20, + "CD": 0.3249 + }, + { + "Mach": 2.25, + "CD": 0.3185 + }, + { + "Mach": 2.30, + "CD": 0.3122 + }, + { + "Mach": 2.35, + "CD": 0.3060 + }, + { + "Mach": 2.40, + "CD": 0.3000 + }, + { + "Mach": 2.45, + "CD": 0.2941 + }, + { + "Mach": 2.50, + "CD": 0.2883 + }, + { + "Mach": 2.60, + "CD": 0.2772 + }, + { + "Mach": 2.70, + "CD": 0.2668 + }, + { + "Mach": 2.80, + "CD": 0.2574 + }, + { + "Mach": 2.90, + "CD": 0.2487 + }, + { + "Mach": 3.00, + "CD": 0.2407 + }, + { + "Mach": 3.10, + "CD": 0.2333 + }, + { + "Mach": 3.20, + "CD": 0.2265 + }, + { + "Mach": 3.30, + "CD": 0.2202 + }, + { + "Mach": 3.40, + "CD": 0.2144 + }, + { + "Mach": 3.50, + "CD": 0.2089 + }, + { + "Mach": 3.60, + "CD": 0.2039 + }, + { + "Mach": 3.70, + "CD": 0.1991 + }, + { + "Mach": 3.80, + "CD": 0.1947 + }, + { + "Mach": 3.90, + "CD": 0.1905 + }, + { + "Mach": 4.00, + "CD": 0.1866 + }, + { + "Mach": 4.20, + "CD": 0.1794 + }, + { + "Mach": 4.40, + "CD": 0.1730 + }, + { + "Mach": 4.60, + "CD": 0.1673 + }, + { + "Mach": 4.80, + "CD": 0.1621 + }, + { + "Mach": 5.00, + "CD": 0.1574 + } + ], + "G8": [ + { + "Mach": 0.00, + "CD": 0.2105 + }, + { + "Mach": 0.05, + "CD": 0.2105 + }, + { + "Mach": 0.10, + "CD": 0.2104 + }, + { + "Mach": 0.15, + "CD": 0.2104 + }, + { + "Mach": 0.20, + "CD": 0.2103 + }, + { + "Mach": 0.25, + "CD": 0.2103 + }, + { + "Mach": 0.30, + "CD": 0.2103 + }, + { + "Mach": 0.35, + "CD": 0.2103 + }, + { + "Mach": 0.40, + "CD": 0.2103 + }, + { + "Mach": 0.45, + "CD": 0.2102 + }, + { + "Mach": 0.50, + "CD": 0.2102 + }, + { + "Mach": 0.55, + "CD": 0.2102 + }, + { + "Mach": 0.60, + "CD": 0.2102 + }, + { + "Mach": 0.65, + "CD": 0.2102 + }, + { + "Mach": 0.70, + "CD": 0.2103 + }, + { + "Mach": 0.75, + "CD": 0.2103 + }, + { + "Mach": 0.80, + "CD": 0.2104 + }, + { + "Mach": 0.825, + "CD": 0.2104 + }, + { + "Mach": 0.85, + "CD": 0.2105 + }, + { + "Mach": 0.875, + "CD": 0.2106 + }, + { + "Mach": 0.90, + "CD": 0.2109 + }, + { + "Mach": 0.925, + "CD": 0.2183 + }, + { + "Mach": 0.95, + "CD": 0.2571 + }, + { + "Mach": 0.975, + "CD": 0.3358 + }, + { + "Mach": 1.0, + "CD": 0.4068 + }, + { + "Mach": 1.025, + "CD": 0.4378 + }, + { + "Mach": 1.05, + "CD": 0.4476 + }, + { + "Mach": 1.075, + "CD": 0.4493 + }, + { + "Mach": 1.10, + "CD": 0.4477 + }, + { + "Mach": 1.125, + "CD": 0.4450 + }, + { + "Mach": 1.15, + "CD": 0.4419 + }, + { + "Mach": 1.20, + "CD": 0.4353 + }, + { + "Mach": 1.25, + "CD": 0.4283 + }, + { + "Mach": 1.30, + "CD": 0.4208 + }, + { + "Mach": 1.35, + "CD": 0.4133 + }, + { + "Mach": 1.40, + "CD": 0.4059 + }, + { + "Mach": 1.45, + "CD": 0.3986 + }, + { + "Mach": 1.50, + "CD": 0.3915 + }, + { + "Mach": 1.55, + "CD": 0.3845 + }, + { + "Mach": 1.60, + "CD": 0.3777 + }, + { + "Mach": 1.65, + "CD": 0.3710 + }, + { + "Mach": 1.70, + "CD": 0.3645 + }, + { + "Mach": 1.75, + "CD": 0.3581 + }, + { + "Mach": 1.80, + "CD": 0.3519 + }, + { + "Mach": 1.85, + "CD": 0.3458 + }, + { + "Mach": 1.90, + "CD": 0.3400 + }, + { + "Mach": 1.95, + "CD": 0.3343 + }, + { + "Mach": 2.00, + "CD": 0.3288 + }, + { + "Mach": 2.05, + "CD": 0.3234 + }, + { + "Mach": 2.10, + "CD": 0.3182 + }, + { + "Mach": 2.15, + "CD": 0.3131 + }, + { + "Mach": 2.20, + "CD": 0.3081 + }, + { + "Mach": 2.25, + "CD": 0.3032 + }, + { + "Mach": 2.30, + "CD": 0.2983 + }, + { + "Mach": 2.35, + "CD": 0.2937 + }, + { + "Mach": 2.40, + "CD": 0.2891 + }, + { + "Mach": 2.45, + "CD": 0.2845 + }, + { + "Mach": 2.50, + "CD": 0.2802 + }, + { + "Mach": 2.60, + "CD": 0.2720 + }, + { + "Mach": 2.70, + "CD": 0.2642 + }, + { + "Mach": 2.80, + "CD": 0.2569 + }, + { + "Mach": 2.90, + "CD": 0.2499 + }, + { + "Mach": 3.00, + "CD": 0.2432 + }, + { + "Mach": 3.10, + "CD": 0.2368 + }, + { + "Mach": 3.20, + "CD": 0.2308 + }, + { + "Mach": 3.30, + "CD": 0.2251 + }, + { + "Mach": 3.40, + "CD": 0.2197 + }, + { + "Mach": 3.50, + "CD": 0.2147 + }, + { + "Mach": 3.60, + "CD": 0.2101 + }, + { + "Mach": 3.70, + "CD": 0.2058 + }, + { + "Mach": 3.80, + "CD": 0.2019 + }, + { + "Mach": 3.90, + "CD": 0.1983 + }, + { + "Mach": 4.00, + "CD": 0.1950 + }, + { + "Mach": 4.20, + "CD": 0.1890 + }, + { + "Mach": 4.40, + "CD": 0.1837 + }, + { + "Mach": 4.60, + "CD": 0.1791 + }, + { + "Mach": 4.80, + "CD": 0.1750 + }, + { + "Mach": 5.00, + "CD": 0.1713 + } + ], + "GI": [ + { + "Mach": 0.00, + "CD": 0.2282 + }, + { + "Mach": 0.05, + "CD": 0.2282 + }, + { + "Mach": 0.10, + "CD": 0.2282 + }, + { + "Mach": 0.15, + "CD": 0.2282 + }, + { + "Mach": 0.20, + "CD": 0.2282 + }, + { + "Mach": 0.25, + "CD": 0.2282 + }, + { + "Mach": 0.30, + "CD": 0.2282 + }, + { + "Mach": 0.35, + "CD": 0.2282 + }, + { + "Mach": 0.40, + "CD": 0.2282 + }, + { + "Mach": 0.45, + "CD": 0.2282 + }, + { + "Mach": 0.50, + "CD": 0.2282 + }, + { + "Mach": 0.55, + "CD": 0.2282 + }, + { + "Mach": 0.60, + "CD": 0.2282 + }, + { + "Mach": 0.65, + "CD": 0.2282 + }, + { + "Mach": 0.70, + "CD": 0.2282 + }, + { + "Mach": 0.725, + "CD": 0.2353 + }, + { + "Mach": 0.75, + "CD": 0.2434 + }, + { + "Mach": 0.775, + "CD": 0.2515 + }, + { + "Mach": 0.80, + "CD": 0.2596 + }, + { + "Mach": 0.825, + "CD": 0.2677 + }, + { + "Mach": 0.85, + "CD": 0.2759 + }, + { + "Mach": 0.875, + "CD": 0.2913 + }, + { + "Mach": 0.90, + "CD": 0.3170 + }, + { + "Mach": 0.925, + "CD": 0.3442 + }, + { + "Mach": 0.95, + "CD": 0.3728 + }, + { + "Mach": 1.0, + "CD": 0.4349 + }, + { + "Mach": 1.05, + "CD": 0.5034 + }, + { + "Mach": 1.075, + "CD": 0.5402 + }, + { + "Mach": 1.10, + "CD": 0.5756 + }, + { + "Mach": 1.125, + "CD": 0.5887 + }, + { + "Mach": 1.15, + "CD": 0.6018 + }, + { + "Mach": 1.175, + "CD": 0.6149 + }, + { + "Mach": 1.20, + "CD": 0.6279 + }, + { + "Mach": 1.225, + "CD": 0.6418 + }, + { + "Mach": 1.25, + "CD": 0.6423 + }, + { + "Mach": 1.30, + "CD": 0.6423 + }, + { + "Mach": 1.35, + "CD": 0.6423 + }, + { + "Mach": 1.40, + "CD": 0.6423 + }, + { + "Mach": 1.45, + "CD": 0.6423 + }, + { + "Mach": 1.50, + "CD": 0.6423 + }, + { + "Mach": 1.55, + "CD": 0.6423 + }, + { + "Mach": 1.60, + "CD": 0.6423 + }, + { + "Mach": 1.625, + "CD": 0.6407 + }, + { + "Mach": 1.65, + "CD": 0.6378 + }, + { + "Mach": 1.70, + "CD": 0.6321 + }, + { + "Mach": 1.75, + "CD": 0.6266 + }, + { + "Mach": 1.80, + "CD": 0.6213 + }, + { + "Mach": 1.85, + "CD": 0.6163 + }, + { + "Mach": 1.90, + "CD": 0.6113 + }, + { + "Mach": 1.95, + "CD": 0.6066 + }, + { + "Mach": 2.00, + "CD": 0.6020 + }, + { + "Mach": 2.05, + "CD": 0.5976 + }, + { + "Mach": 2.10, + "CD": 0.5933 + }, + { + "Mach": 2.15, + "CD": 0.5891 + }, + { + "Mach": 2.20, + "CD": 0.5850 + }, + { + "Mach": 2.25, + "CD": 0.5811 + }, + { + "Mach": 2.30, + "CD": 0.5773 + }, + { + "Mach": 2.35, + "CD": 0.5733 + }, + { + "Mach": 2.40, + "CD": 0.5679 + }, + { + "Mach": 2.45, + "CD": 0.5626 + }, + { + "Mach": 2.50, + "CD": 0.5576 + }, + { + "Mach": 2.60, + "CD": 0.5478 + }, + { + "Mach": 2.70, + "CD": 0.5386 + }, + { + "Mach": 2.80, + "CD": 0.5298 + }, + { + "Mach": 2.90, + "CD": 0.5215 + }, + { + "Mach": 3.00, + "CD": 0.5136 + }, + { + "Mach": 3.10, + "CD": 0.5061 + }, + { + "Mach": 3.20, + "CD": 0.4989 + }, + { + "Mach": 3.30, + "CD": 0.4921 + }, + { + "Mach": 3.40, + "CD": 0.4855 + }, + { + "Mach": 3.50, + "CD": 0.4792 + }, + { + "Mach": 3.60, + "CD": 0.4732 + }, + { + "Mach": 3.70, + "CD": 0.4674 + }, + { + "Mach": 3.80, + "CD": 0.4618 + }, + { + "Mach": 3.90, + "CD": 0.4564 + }, + { + "Mach": 4.00, + "CD": 0.4513 + }, + { + "Mach": 4.20, + "CD": 0.4415 + }, + { + "Mach": 4.40, + "CD": 0.4323 + }, + { + "Mach": 4.60, + "CD": 0.4238 + }, + { + "Mach": 4.80, + "CD": 0.4157 + }, + { + "Mach": 5.00, + "CD": 0.4082 + } + ], + "GS": [ + { + "Mach": 0.00, + "CD": 0.4662 + }, + { + "Mach": 0.05, + "CD": 0.4689 + }, + { + "Mach": 0.10, + "CD": 0.4717 + }, + { + "Mach": 0.15, + "CD": 0.4745 + }, + { + "Mach": 0.20, + "CD": 0.4772 + }, + { + "Mach": 0.25, + "CD": 0.4800 + }, + { + "Mach": 0.30, + "CD": 0.4827 + }, + { + "Mach": 0.35, + "CD": 0.4852 + }, + { + "Mach": 0.40, + "CD": 0.4882 + }, + { + "Mach": 0.45, + "CD": 0.4920 + }, + { + "Mach": 0.50, + "CD": 0.4970 + }, + { + "Mach": 0.55, + "CD": 0.5080 + }, + { + "Mach": 0.60, + "CD": 0.5260 + }, + { + "Mach": 0.65, + "CD": 0.5590 + }, + { + "Mach": 0.70, + "CD": 0.5920 + }, + { + "Mach": 0.75, + "CD": 0.6258 + }, + { + "Mach": 0.80, + "CD": 0.6610 + }, + { + "Mach": 0.85, + "CD": 0.6985 + }, + { + "Mach": 0.90, + "CD": 0.7370 + }, + { + "Mach": 0.95, + "CD": 0.7757 + }, + { + "Mach": 1.0, + "CD": 0.8140 + }, + { + "Mach": 1.05, + "CD": 0.8512 + }, + { + "Mach": 1.10, + "CD": 0.8870 + }, + { + "Mach": 1.15, + "CD": 0.9210 + }, + { + "Mach": 1.20, + "CD": 0.9510 + }, + { + "Mach": 1.25, + "CD": 0.9740 + }, + { + "Mach": 1.30, + "CD": 0.9910 + }, + { + "Mach": 1.35, + "CD": 0.9990 + }, + { + "Mach": 1.40, + "CD": 1.0030 + }, + { + "Mach": 1.45, + "CD": 1.0060 + }, + { + "Mach": 1.50, + "CD": 1.0080 + }, + { + "Mach": 1.55, + "CD": 1.0090 + }, + { + "Mach": 1.60, + "CD": 1.0090 + }, + { + "Mach": 1.65, + "CD": 1.0090 + }, + { + "Mach": 1.70, + "CD": 1.0090 + }, + { + "Mach": 1.75, + "CD": 1.0080 + }, + { + "Mach": 1.80, + "CD": 1.0070 + }, + { + "Mach": 1.85, + "CD": 1.0060 + }, + { + "Mach": 1.90, + "CD": 1.0040 + }, + { + "Mach": 1.95, + "CD": 1.0025 + }, + { + "Mach": 2.00, + "CD": 1.0010 + }, + { + "Mach": 2.05, + "CD": 0.9990 + }, + { + "Mach": 2.10, + "CD": 0.9970 + }, + { + "Mach": 2.15, + "CD": 0.9956 + }, + { + "Mach": 2.20, + "CD": 0.9940 + }, + { + "Mach": 2.25, + "CD": 0.9916 + }, + { + "Mach": 2.30, + "CD": 0.9890 + }, + { + "Mach": 2.35, + "CD": 0.9869 + }, + { + "Mach": 2.40, + "CD": 0.9850 + }, + { + "Mach": 2.45, + "CD": 0.9830 + }, + { + "Mach": 2.50, + "CD": 0.9810 + }, + { + "Mach": 2.55, + "CD": 0.9790 + }, + { + "Mach": 2.60, + "CD": 0.9770 + }, + { + "Mach": 2.65, + "CD": 0.9750 + }, + { + "Mach": 2.70, + "CD": 0.9730 + }, + { + "Mach": 2.75, + "CD": 0.9710 + }, + { + "Mach": 2.80, + "CD": 0.9690 + }, + { + "Mach": 2.85, + "CD": 0.9670 + }, + { + "Mach": 2.90, + "CD": 0.9650 + }, + { + "Mach": 2.95, + "CD": 0.9630 + }, + { + "Mach": 3.00, + "CD": 0.9610 + }, + { + "Mach": 3.05, + "CD": 0.9589 + }, + { + "Mach": 3.10, + "CD": 0.9570 + }, + { + "Mach": 3.15, + "CD": 0.9555 + }, + { + "Mach": 3.20, + "CD": 0.9540 + }, + { + "Mach": 3.25, + "CD": 0.9520 + }, + { + "Mach": 3.30, + "CD": 0.9500 + }, + { + "Mach": 3.35, + "CD": 0.9485 + }, + { + "Mach": 3.40, + "CD": 0.9470 + }, + { + "Mach": 3.45, + "CD": 0.9450 + }, + { + "Mach": 3.50, + "CD": 0.9430 + }, + { + "Mach": 3.55, + "CD": 0.9414 + }, + { + "Mach": 3.60, + "CD": 0.9400 + }, + { + "Mach": 3.65, + "CD": 0.9385 + }, + { + "Mach": 3.70, + "CD": 0.9370 + }, + { + "Mach": 3.75, + "CD": 0.9355 + }, + { + "Mach": 3.80, + "CD": 0.9340 + }, + { + "Mach": 3.85, + "CD": 0.9325 + }, + { + "Mach": 3.90, + "CD": 0.9310 + }, + { + "Mach": 3.95, + "CD": 0.9295 + }, + { + "Mach": 4.00, + "CD": 0.9280 + } + ] +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index bd1dc32..037f09e 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,49 @@ -import { AbstractUnit, Angular, Distance, Velocity, Weight, Temperature, Pressure, Energy, Unit, UnitPropsDict } from "../src/units.js"; +import { + AbstractUnit, + Angular, + Distance, + Velocity, + Weight, + Temperature, + Pressure, + Energy, + Unit, + UnitPropsDict, + unitTypeCoerce, +} from "./units"; +import DragTable from "./drag_tables.json"; +import calcSettings from "./settings" +import { + Atmo, + Wind, + Shot, + cStandardDensity, + cStandardTemperature, + cStandardPressure, + cIcaoStandardHumidity, + cSpeedOfSound +} from "./conditions.js"; -export { AbstractUnit, Angular, Distance, Velocity, Weight, Temperature, Pressure, Energy, Unit, UnitPropsDict } +export { + AbstractUnit, + Angular, + Distance, + Velocity, + Weight, + Temperature, + Pressure, + Energy, + Unit, + UnitPropsDict, + DragTable, + calcSettings, + unitTypeCoerce, + Atmo, + Wind, + Shot, + cStandardDensity, + cStandardTemperature, + cStandardPressure, + cIcaoStandardHumidity, + cSpeedOfSound, +} diff --git a/src/munition.js b/src/munition.js new file mode 100644 index 0000000..509bde9 --- /dev/null +++ b/src/munition.js @@ -0,0 +1,28 @@ +// Module for Weapon and Ammo properties definitions + +// Import necessary units and settings +import { Unit, Velocity, Temperature, Distance, Angular, unitTypeCoerce } from './units'; +import { calcSettings } from './settings'; + + +class Weapon { + /** + * @param {number | Distance} sightHeight - Height of the sight above the bore axis. + * @param {number | Distance} zeroDistance - Sight-line distance to "zero." + * @param {number} twist - The twist rate of the barrel. + * @param {number | Angular} zeroLookAngle - The look angle for the zero distance. + */ + constructor( + sightHeight = new Distance(2, Unit.Inch), + zeroDistance = new Distance(100, Unit.Yard), + twist = 0, + zeroLookAngle = new Angular(0, Unit.MIL) + ) { + this.sightHeight = this.unitTypeCoerce(sightHeight, Distance, calcSettings.Units.distance); + this.zeroDistance = this.unitTypeCoerce(zeroDistance, Distance, calcSettings.Units.distance); + this.twist = twist; // Assuming twist is a simple numeric value, not a distance + this.zeroLookAngle = this.unitTypeCoerce(zeroLookAngle, Angular, calcSettings.Units.angular); + } +} + +export { Weapon }; diff --git a/src/settings.js b/src/settings.js new file mode 100644 index 0000000..fe1b583 --- /dev/null +++ b/src/settings.js @@ -0,0 +1,45 @@ +import { Unit, Distance, unitTypeCoerce } from './units'; // Adjust the path accordingly + +class CalcSettings { + /** + * Global settings class of the js-ballistics library. + * Defines default units and configuration settings. + */ + constructor() { + this.Units = { + sight_height: Unit.Inch, + twist: Unit.Inch, + velocity: Unit.FPS, + distance: Unit.Yard, + temperature: Unit.Celsius, + weight: Unit.Grain, + length: Unit.Inch, + diameter: Unit.Inch, + pressure: Unit.hPa, + drop: Unit.Centimeter, + angular: Unit.Degree, + adjustment: Unit.MIL, + energy: Unit.Joule, + ogw: Unit.Pound, + target_height: Unit.Inch + }; + + this._MAX_CALC_STEP_SIZE = 1; + this.USE_POWDER_SENSITIVITY = false; + } + + /** + * Sets the maximum calculation step size. + * @param {number | Distance} value - The value of the maximum calculation step size. + */ + setMaxCalcStepSize(value) { + console.warn("CalcSettings._MAX_CALC_STEP_SIZE: " + + "Change this property only if you know what you are doing; " + + "too big step can corrupt calculation accuracy"); + + this._MAX_CALC_STEP_SIZE = unitTypeCoerce(value, Distance, this.Units.distance); + } +} + +const calcSettings = new CalcSettings(); // Global settings instance of the js-ballistics library +export default calcSettings; diff --git a/src/units.js b/src/units.js index cb5b70f..b57726f 100644 --- a/src/units.js +++ b/src/units.js @@ -2,99 +2,117 @@ class AbstractUnit { - - // Abstract class for unit of measure instance definition - // Stores defined unit and value, applies conversions to other units - + /** + * Abstract class for unit of measure instance definition. + * Stores defined unit and value, applies conversions to other units. + * + * @param {number} value - Numeric value of the unit. + * @param {Unit} units - Unit as Unit enum. + */ constructor(value, units) { - - // :param units: unit as Unit enum - // :param value: numeric value of the unit - this._value = this.toRaw(value, units); this._definedUnits = units; } + /** + * Returns a human-readable representation of the value with its unit. + * + * @return {string} A string representing the value with its unit. + */ toString() { - - // Returns readable unit value - // :return: readable unit value - + // Extract the unit details based on the defined units. const units = this._definedUnits; const props = UnitPropsDict[units]; + + // Convert the raw value to the specified unit. const v = this.fromRaw(this._value, units); + + // Format the value with a fixed number of decimal places and concatenate the unit symbol. return `${v.toFixed(props.accuracy)}${props.symbol}`; } + /** + * Validates the units. + * + * @param {number} value - Value of the unit. + * @param {Unit} units - Unit enum type. + * @return {number} Value in specified units. + * @throws {TypeError} When the provided units are not of the expected type. + * @throws {Error} When the provided units are not supported. + */ _unit_support_error(value, units) { - // Validates the units - // :param value: value of the unit - // :param units: Unit enum type - // :return: value in specified units - if (!(units instanceof this.constructor)) { const err_msg = `Type expected: ${this.constructor.name}, ${typeof units} found: ${units} (${value})`; throw new TypeError(err_msg); } + if (!Object.values(this).includes(units)) { throw new Error(`${this.constructor.name}: unit ${units} is not supported`); } + return 0; } + /** + * Converts value with specified units to raw value. + * + * @param {number} value - Value of the unit. + * @param {Unit} units - Unit enum type. + * @return {number} Value in specified units. + */ toRaw(value, units) { - - // Converts value with specified units to raw value - // :param value: value of the unit - // :param units: Unit enum type - // :return: value in specified units - return this._unit_support_error(value, units); } + /** + * Converts raw value to specified units. + * + * @param {number} value - Raw value of the unit. + * @param {Unit} units - Unit enum type. + * @return {number} Value in specified units. + */ fromRaw(value, units) { - - // Converts raw value to specified units - // :param value: raw value of the unit - // :param units: Unit enum type - // :return: value in specified units - return this._unit_support_error(value, units); } + /** + * Returns a new unit instance in specified units. + * + * @param {Unit} units - Unit enum type. + * @return {AbstractUnit} New unit instance in specified units. + */ to(units) { - - // Returns new unit instance in specified units - // :param units: Unit enum type - // :return: new unit instance in specified units - const value = this.in(units); return new this.constructor(value, units); } + /** + * Returns value in specified units. + * + * @param {Unit} units - Unit enum type. + * @return {number} Value in specified units. + */ in(units) { - // Returns value in specified units - // :param units: Unit enum type - // :return: value in specified units - return this.fromRaw(this._value, units); } + /** + * Returns defined units. + * + * @return {Unit} Defined units. + */ get units() { - - // Returns defined units - // :return: defined units - return this._definedUnits; } + /** + * Raw unit value getter. + * + * @return {number} Raw unit value. + */ get rawValue() { - - // Raw unit value getter - // :return: raw unit value - return this._value; } }; @@ -425,9 +443,8 @@ class Energy extends AbstractUnit { } +// Unit types enum const Unit = { - // Unit types enum - RAD: 0, Degree: 1, MOA: 2, @@ -472,6 +489,7 @@ const Unit = { }; +// Dict of properties of the Unit enum type const UnitPropsDict = { [Unit.RAD]: { name: 'radian', accuracy: 6, symbol: 'rad' }, [Unit.Degree]: { name: 'degree', accuracy: 4, symbol: '°' }, @@ -593,9 +611,34 @@ Energy.Joule = Unit.Joule; // console.log(distance.in(Distance.Inch)); -// module.exports = { -// AbstractUnit, Angular, Distance, Velocity, Weight, Temperature, Pressure, Energy, Unit, UnitPropsDict -// } +/** + * Coerces the given instance to the specified class type or creates a new instance. + * + * @param {Object} instance - The instance to coerce or create. + * @param {Class} expectedClass - The expected class type. + * @param {Unit} defaultUnit - The default unit for creating a new instance. + * @returns {AbstractUnit|Object} An instance of the expected class type. + * @throws {TypeError} If the instance is not of the expected class type or 'number'. + */ +function unitTypeCoerce(instance, expectedClass, defaultUnit) { + if (!instance) { + // If the instance is falsy, create a new instance using the default unit. + return new expectedClass(instance, defaultUnit); + } else if (instance instanceof expectedClass) { + // If the instance is already of the expected class type, return it. + return instance; + } else if (typeof instance === 'number') { + // If the instance is a number, create a new instance using the default unit. + return new expectedClass(instance, defaultUnit); + } else { + // If the instance is not of the expected type, throw a TypeError. + throw new TypeError(`Instance must be a type of ${expectedClass.className} or 'number'`); + } +} -// ES6 syntax -export { AbstractUnit, Angular, Distance, Velocity, Weight, Temperature, Pressure, Energy, Unit, UnitPropsDict } + + +export { + AbstractUnit, Angular, Distance, Velocity, Weight, Temperature, Pressure, Energy, + Unit, UnitPropsDict, unitTypeCoerce +}