v096
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Audit Garmin -> OSM POI mappings against an exact OsmAnd poi_types.xml.
|
||||
|
||||
No OBF creation. Exits 0 for ordinary data regressions unless --strict is requested.
|
||||
The existence of a poi_type does NOT guarantee map icon visibility at any zoom.
|
||||
"""
|
||||
import argparse,csv,json,collections,sys
|
||||
from pathlib import Path
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
def registry(path):
|
||||
root=ET.parse(path).getroot()
|
||||
main=collections.defaultdict(list);extras=collections.defaultdict(list)
|
||||
for node in root.iter():
|
||||
if node.tag not in ('poi_type','poi_additional'):continue
|
||||
t=node.attrib.get('tag');v=node.attrib.get('value')
|
||||
if not t or v is None:continue
|
||||
d=main if node.tag=='poi_type' else extras
|
||||
d[f'{t}={v}'].append(node.attrib)
|
||||
return main,extras
|
||||
|
||||
def interpret(row,main,extra):
|
||||
tags=[v.strip() for v in row['osm_tags'].split(';') if '=' in v]
|
||||
supported=[];noindex=[];additional=[];missing=[]
|
||||
for tv in tags:
|
||||
candidates=main.get(tv,[])
|
||||
if any(x.get('no_indx')!='true' for x in candidates):supported.append(tv)
|
||||
elif candidates:noindex.append(tv)
|
||||
elif tv in extra:additional.append(tv)
|
||||
else:missing.append(tv)
|
||||
if supported:kind='native_indexable_type'
|
||||
elif noindex:kind='only_nonindexed_type'
|
||||
elif additional:kind='additional_without_primary_type'
|
||||
else:kind='no_matching_native_type'
|
||||
is_terrain=(row.get('priority')=='terrain' or row.get('code')=='0x6600')
|
||||
priority=row.get('priority','')
|
||||
cnt=int(row.get('source_count') or 0)
|
||||
if is_terrain:severity='terrain_exemption'
|
||||
elif kind=='native_indexable_type':severity='ok'
|
||||
elif priority=='critical':severity='critical'
|
||||
elif cnt>=100:severity='high'
|
||||
else:severity='low'
|
||||
return {'code':row.get('code',''),'count':cnt,'priority':priority,'legend_bg':row.get('legend_bg',''),
|
||||
'osm_tags':row.get('osm_tags',''), 'status':kind, 'severity':severity,
|
||||
'indexable_poi_tags':';'.join(supported),'nonindexed_poi_tags':';'.join(noindex),
|
||||
'additional_only_tags':';'.join(additional),'unrecognized_tags':';'.join(missing),
|
||||
'sample_lat':row.get('example_lat',''),'sample_lon':row.get('example_lon',''),
|
||||
'explanation':'Registry compatibility only; does not guarantee rendering zoom or OBF preservation'}
|
||||
|
||||
def main(argv=None):
|
||||
ap=argparse.ArgumentParser(description=__doc__)
|
||||
ap.add_argument('--mapping',required=True,help='Single canonical POI mapping CSV')
|
||||
ap.add_argument('--poi-types',required=True,help='OsmAnd official poi_types.xml, preferably pinned version')
|
||||
ap.add_argument('--report',default='poi-native-index-audit.csv')
|
||||
ap.add_argument('--json',default='poi-native-index-audit.json')
|
||||
ap.add_argument('--strict',action='store_true',help='Exit nonzero for unindexable critical/high types')
|
||||
args=ap.parse_args(argv)
|
||||
native,extra=registry(args.poi_types)
|
||||
with open(args.mapping,encoding='utf8-sig',newline='') as f:
|
||||
allrows=list(csv.DictReader(f))
|
||||
# Name-conditional rows are not additional Garmin types; counting them as
|
||||
# independent types would multiply source_count and inflate POI statistics.
|
||||
rows=[r for r in allrows if not r.get('name_contains','')]
|
||||
out=[interpret(r,native,extra) for r in rows]
|
||||
with open(args.report,'w',newline='',encoding='utf8') as f:
|
||||
w=csv.DictWriter(f,fieldnames=out[0].keys());w.writeheader();w.writerows(out)
|
||||
stats=collections.Counter(r['status'] for r in out)
|
||||
weighted=collections.Counter()
|
||||
for r in out:weighted[r['status']]+=r['count']
|
||||
risk=[r for r in out if r['severity'] in ('critical','high')]
|
||||
payload={'type_counts':dict(stats),'weighted_source_counts':dict(weighted),'critical_or_high':len(risk),
|
||||
'top_regressions':sorted(risk,key=lambda z:-z['count'])[:30],
|
||||
'warning':'POI type registry check ONLY. Does not guarantee OBF map index presence, symbol visibility, zoom or Nearby settings.'}
|
||||
Path(args.json).write_text(json.dumps(payload,ensure_ascii=False,indent=2),encoding='utf8')
|
||||
print(f"Inspected {len(out)} Garmin types: {dict(stats)}, high/critical issues: {len(risk)}")
|
||||
print(f"Wrote {args.report} and {args.json}")
|
||||
return 2 if args.strict and risk else 0
|
||||
|
||||
if __name__=='__main__':sys.exit(main())
|
||||
Reference in New Issue
Block a user