fix(flights): match aircraft types exactly, not as substrings (609 -> 27 false 'military' contacts) - #32
Open
ihubanov wants to merge 1 commit into
Conversation
isMilitaryType() used upper.includes(mt) against a list containing
short designators, so any type merely CONTAINING one matched. Measured
against a live adsb.lol regional feed of 2754 aircraft, this reported
609 military when only 21 carried the database military flag -- 96%
false positives:
490x B738 ordinary 737-800 airliners
12x C172 Cessna 172 -> matched 'C17' -> 'Strategic Airlift (C-17)'
11x C56X Citation Excel -> matched 'C5' -> 'Strategic Airlift (C-5)'
6x E35L Embraer Legacy -> matched 'E3' -> 'AWACS'
5x C25A Citation CJ2 -> matched 'C2' -> 'C-2 Greyhound'
(B200 King Air -> 'B2' -> Bomber was reachable by the same rule.)
Changes:
- MILITARY_AIRCRAFT_TYPES is now a Set of exact ICAO Doc 8643
designators, corrected where the old entries were not real codes
(KC135 -> K35R, RC135 -> R135, CH47 -> H47, MQ9 -> Q9, ...).
- Dual-use designators dropped: B737/B738/B739, A332, A310, GLF5,
GLF6, A124, C40. Genuine military examples already carry adsb.lol's
dbFlags military bit -- verified: Polish Air Force 737 PLF110 is
still detected after B737 was removed from the heuristic list.
- classifyAircraft() type chain replaced with an exact TYPE_ROLES
lookup, same substring flaw.
- isMilitaryCallsign() requires a digit after the prefix, so the
French air ambulances SAMU42/SAMU06 no longer match the US 'SAM'
Special Air Mission prefix. Dropped the bare 5-6 digit rule.
- Removed an unreachable US-hex+type branch already covered above.
Live result: 609 -> 27 military, 25 of them dbFlags-confirmed.
ihubanov
force-pushed
the
fix/exact-aircraft-type-matching
branch
from
August 17, 2026 18:33
bdb1dff to
2df4a06
Compare
Knibbaz
added a commit
to Knibbaz/IRONSIGHT
that referenced
this pull request
Aug 30, 2026
A substring match turned a Cessna 172 into a C-17, a Citation C56X into a C-5 and a King Air B200 into a B-2 (609 contacts -> 27 true military). Military types are now matched by exact ICAO designator, military callsigns require a numeric mission number, and aircraft roles come from an explicit type table. Applies upstream PR NoblerWorks-HQ#32.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
isMilitaryType()matches type designators as substrings:The list contains short codes (
C17,C5,C2,E3,B2), so any ICAO type that merely contains one of them matches. A lot of ordinary civil traffic ends up counted as military.I pulled a live regional feed for the Iran/Israel theater (
lat/30/lon/48/dist/2500, 2754 aircraft) and compared what the heuristics flag against adsb.lol's owndbFlagsmilitary bit:What the substring rule was actually catching:
So Cessna 172s were showing up as C-17 Globemasters and Embraer Legacy bizjets as E-3 AWACS.
classifyAircraft()has the same problem; itst.includes('B2')branch labels any Beechcraft King Air (B200) a bomber.isMilitaryCallsign()matches bare prefixes, soSAMU42andSAMU06(French SAMU air ambulances) match the USSAMSpecial Air Mission prefix.Changes
MILITARY_AIRCRAFT_TYPESis aSetnow, matched exactly. Converting it turned up several entries that aren't real ICAO Doc 8643 designators and so never matched anything:KC135should beK35R,RC135isR135,CH47isH47,AH64isH64,MQ9isQ9,RQ4isQ4. The list was over-matching civil types and missing real military ones at the same time.Dropped the dual-use codes:
B737/B738/B739,A332,A310,GLF5,GLF6,A124,C40. Military examples of those airframes already carry thedbFlagsbit, so the heuristic wasn't buying anything. Concretely:PLF110, a Polish Air Force 737, is still picked up after removingB737from the list. That's the case the entry was there for.classifyAircraft()'s type chain is an exactTYPE_ROLESlookup instead of theincludes()ladder.isMilitaryCallsign()now requires a digit after the prefix.RCH471andPLF110still match,SAMU42doesn't. I also dropped the bare 5-6 digit rule, which was a guess and didn't match anything in the sample.Removed the
A00000-AFFFFF+ type branch. The unconditionalisMilitaryType()check above it already returns for anything that branch could catch, so it was dead.Result
609 -> 27 on the same feed, 25 of them dbFlags-confirmed. What's left is Spanish A400Ms, a German A321neo, Italian and Belgian air force aircraft, US Army CH-47s and a UH-72, a KC-135R (57-1468), French Sécurité Civile Dash-8s, a Croatian CL-415. No Cessnas or business jets.
No API or response-shape changes, only the classification predicates.
next buildpasses.One thing I left alone: several entries in
MILITARY_CALLSIGN_PREFIXESare broad enough to collide with civil callsigns even with the digit boundary (MAG,KING,GOLD,CLUB,TANGO). Probably worth a separate look.