cartridge_catalog 1.0.0
cartridge_catalog: ^1.0.0 copied to clipboard
A structured catalog of firearm cartridge and chamber types.
cartridge_catalog #
A Dart library providing a structured, queryable catalog of firearm cartridge and chamber types. Intended as a dependency for ballistic calculator applications that need to treat caliber as a rich type rather than a free-text field.
Purpose #
The catalog enables:
- Autocomplete / suggestion — search cartridges by partial name or abbreviation
- Compatibility filtering — given a chamber, find which cartridges can be safely fired; given a cartridge, find which chambers accept it
- Standardized naming — stable IDs and official SAAMI abbreviations for consistent display and storage
- Ballistic properties — bullet diameter (inches and meters) for use in drop calculations
How it works #
Source data lives in human-readable TOML files under data/. A compile step transforms them into a read-only SQLite database (data/cartridge_catalog.sqlite). At runtime, the library opens that database and exposes a simple async query API via CartridgeCatalog.
The catalog distinguishes two record types:
- Cartridge — a physical ammunition type (e.g.,
.308 Winchester) - Chamber — a rifle chambering that accepts one or more cartridges but is not itself a cartridge (e.g.,
7.62x51mm NATO Chamber, which accepts both.308 Winchesterand7.62×51mm NATO)
Usage #
import 'package:cartridge_catalog/cartridge_catalog.dart';
final catalog = CartridgeCatalog.open('data/cartridge_catalog.sqlite');
// Lookup
final c = await catalog.getById('308-winchester');
final c = await catalog.getByName('308 WIN'); // full name or any abbreviation, case-insensitive
// Search (partial match, optional filters)
final results = await catalog.search('creed', category: CartridgeCategory.centerfireRifle);
// All cartridges in a category
final pistol = await catalog.getAll(category: CartridgeCategory.centerfirePistol);
// Compatibility
final cartridges = await catalog.getCompatibleCartridges('76251mm-nato-chamber');
final chambers = await catalog.getCompatibleChambers('308-winchester');
// Ballistic properties
final diameterIn = await catalog.getBulletDiameterIn('308-winchester'); // 0.308
final diameterM = await catalog.getBulletDiameterM('308-winchester'); // ~0.007823
await catalog.close();
For testing, use an in-memory database:
final catalog = CartridgeCatalog.openInMemory();
Adding content #
Adding a cartridge #
Edit the appropriate TOML file in data/ (rimfire.toml, centerfire_pistol.toml, centerfire_rifle.toml, or shotshell.toml):
[[cartridge]]
id = "my-cartridge" # stable lowercase-hyphenated slug
full_name = "My Cartridge"
abbreviated_names = ["MY CART"]
category = "centerfire_rifle"
source = "manual"
bullet_diameter_in = 0.308
bore_diameter_in = 0.300
grooves_diameter_in = 0.308 # optional
Adding a chamber #
Edit data/chambers.toml:
[[chamber]]
id = "my-chamber"
full_name = "My Chamber"
abbreviated_names = ["MY CHB"]
category = "centerfire_rifle"
source = "manual"
bullet_diameter_in = 0.224
bore_diameter_in = 0.219
accepts_cartridges = ["223-remington", "55645mm-nato"] # cartridge ids
Adding interchangeability #
Edit data/interchangeability.toml:
[[interchangeability]]
chamber = "my-chamber"
cartridges = ["some-cartridge-id", "another-cartridge-id"]
Validate and compile #
# Check for schema errors, duplicate IDs, and broken references (also sorts entries)
dart run bin/validate.dart
# Compile TOML → SQLite
dart run bin/compile.dart
Data sources #
- SAAMI — primary source; scraped from official standard PDFs via
tools/scrape_saami.py - Wikipedia — supplemental wildcat and non-SAAMI entries via
tools/scrape_wikipedia.py - Manual — chambers and special cases not covered by the above (
source = "manual"in TOML; preserved across scraper runs)
Running tests #
flutter test -r failures-only