a7p-js
v1.2.4
Published
A7P ballistic profile format — encode/decode and validation
Maintainers
Readme
a7p-js
Wrapper for .a7p files
.a7p is the most common ballistic profile format for the latest Archer thermal vision devices
Table of Contents
Installation
yarn add a7p-js
# or
npm install a7p-jsUsage
In a Node.js / TypeScript project
import { readFile } from 'fs/promises';
import { decode, encode, ValidationError } from 'a7p-js';
const bytes = await readFile('./example.a7p');
try {
// decode a .a7p file into a plain Payload object
const payload = decode(bytes);
console.log(payload.profile.profileName);
console.log(payload.profile.switches);
// encode a Payload back into .a7p bytes
const buffer = encode(payload);
} catch (error) {
if (error instanceof ValidationError) {
error.errors.forEach((message) => console.log(message));
} else {
throw error;
}
}In a browser, via CDN
a7p-js ships as an ES module, so it can be imported directly from a CDN such as
esm.sh or jsDelivr with no build step:
<script type="module">
import { decode } from "https://esm.sh/[email protected]";
const input = document.querySelector('input[type="file"]');
input.addEventListener('change', async () => {
const file = input.files[0];
const buffer = await file.arrayBuffer();
const payload = decode(buffer);
console.log(payload.profile);
});
</script>See it in action in this live example, which combines a7p-js with js-ballistics to compare trajectories from .a7p profiles entirely in the browser.
Dimensions
To obtain values from an .a7p profile in the desired units, you need to divide them by the multiplier. For the reverse operation, you need to perform the inverse operation and convert to an integer.
| key | unit | multiplier | desc | |--------------------------|----------------|------------|---------------------------------------------| | scHeight | mm | 1 | sight height in mm | | rTwist | inch | 100 | positive twist value | | cZeroTemperature | C | 1 | temperature at cMuzzleVelocity | | cMuzzleVelocity | mps | 10 | muzzle velocity at cZeroTemperature | | cTCoeff | %/15C | 1000 | temperature sensitivity | | cZeroDistanceIdx | <int> | 10 | index of zero distance from distances table | | cZeroAirTemperature | C | 1 | air temperature at zero | | cZeroAirPressure | hPa | 10 | air pressure at zero | | cZeroAirHumidity | % | 1 | air humidity at zero | | cZeroPTemperature | C | 1 | powder temperature at zero | | cZeroWPitch | deg | 1 | zeroing look angle | | bDiameter | inch | 1000 | bullet diameter | | bWeight | grain | 10 | bullet weight | | bLength | inch | 1000 | bullet length | | twistDir | RIGHT|LEFT | | twist direction | | bcType | G1|G7|CUSTOM | | g-func type | | distances | m | 100 | distances table in m | | zeroX | <int> | -1000 | zeroing h-clicks for specific device | | zeroY | <int> | 1000 | zeroing v-clicks for specific device | | coefRows[].bcCd (G1/G7) | | 10000 | bc coefficient for mv | | coefRows[].mv (G1/G7) | mps | 10 | mv for bc provided | | coefRows[].bcCd (CUSTOM) | | 10000 | drag coefficient (Cd) | | coefRows[].mv (CUSTOM) | mach | 10 | speed in mach |
Build notes
yarn install
yarn build:proto # regenerate protobuf bindings after editing ../proto/profedit.proto
yarn build:schema # regenerate the ajv validator after editing ../schema/a7p.schema.json
yarn build # tsc + copy the generated schema validator into dist/build:proto/build:schema only need re-running when the .proto/schema
source changes — both write generated, checked-in files under src/
(src/profedit.ts, src/generated/a7p_schema_validator.cjs), so a plain
yarn build is enough day-to-day.
