|
|
|
@ -22,7 +22,7 @@ from __future__ import with_statement
|
|
|
|
|
import datetime
|
|
|
|
|
import fileinput
|
|
|
|
|
import logging
|
|
|
|
|
import optparse
|
|
|
|
|
from optparse import OptionParser
|
|
|
|
|
import os
|
|
|
|
|
import re
|
|
|
|
|
import sys
|
|
|
|
@ -33,51 +33,9 @@ except ImportError:
|
|
|
|
|
|
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
|
|
|
|
|
|
|
|
|
from igc2kmz.coord import Coord
|
|
|
|
|
from igc2kmz.etree import tag
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RtePt(object):
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.name = None
|
|
|
|
|
self.lat = None
|
|
|
|
|
self.lon = None
|
|
|
|
|
self.dt = None
|
|
|
|
|
|
|
|
|
|
def togpx(self, tb):
|
|
|
|
|
with tag(tb, 'rtept', {'lat': str(self.lat), 'lon': str(self.lon)}):
|
|
|
|
|
with tag(tb, 'name'): tb.data(self.name)
|
|
|
|
|
with tag(tb, 'time'):
|
|
|
|
|
tb.data(self.dt.strftime('%Y-%m-%dT%H:%M:%SZ'))
|
|
|
|
|
with tag(tb, 'fix'): tb.data('2d')
|
|
|
|
|
return tb
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Rte(object):
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.league = None
|
|
|
|
|
self.name = None
|
|
|
|
|
self.distance = None
|
|
|
|
|
self.multiplier = None
|
|
|
|
|
self.score = None
|
|
|
|
|
self.circuit = None
|
|
|
|
|
self.rtepts = []
|
|
|
|
|
|
|
|
|
|
def togpx(self, tb):
|
|
|
|
|
with tag(tb, 'rte'):
|
|
|
|
|
with tag(tb, 'name'): tb.data(self.name)
|
|
|
|
|
with tag(tb, 'extensions'):
|
|
|
|
|
with tag(tb, 'league'): tb.data(self.league)
|
|
|
|
|
with tag(tb, 'distance'): tb.data(str(self.distance))
|
|
|
|
|
with tag(tb, 'multiplier'): tb.data('%.2f' % self.multiplier);
|
|
|
|
|
with tag(tb, 'score'): tb.data(str(self.score))
|
|
|
|
|
if self.circuit:
|
|
|
|
|
with tag(tb, 'circuit'):
|
|
|
|
|
pass
|
|
|
|
|
for rtept in self.rtepts:
|
|
|
|
|
rtept.togpx(tb)
|
|
|
|
|
return tb
|
|
|
|
|
from igc2kmz.xc import Route, Turnpoint, XC
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DEBUG_DATE_RE = re.compile(r'DEBUG DATE (\d\d)(\d\d)(\d\d)\Z')
|
|
|
|
@ -98,80 +56,71 @@ PRETTY_NAME = {
|
|
|
|
|
CIRCUITS = set(['FREE_TRIANGLE', 'FAI_TRIANGLE'])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class XC(object):
|
|
|
|
|
|
|
|
|
|
def __init__(self, file, league, debug=False):
|
|
|
|
|
self.rtes = []
|
|
|
|
|
date = None
|
|
|
|
|
for line in file:
|
|
|
|
|
line = line.rstrip()
|
|
|
|
|
m = DEBUG_DATE_RE.match(line)
|
|
|
|
|
if m:
|
|
|
|
|
day, mon, year = map(int, m.groups())
|
|
|
|
|
date = datetime.date(year + 2000, mon,day)
|
|
|
|
|
continue
|
|
|
|
|
m = OUT_TYPE_RE.match(line)
|
|
|
|
|
if m:
|
|
|
|
|
rte = Rte()
|
|
|
|
|
rte.league = league
|
|
|
|
|
rte.name = PRETTY_NAME[m.group(1)]
|
|
|
|
|
rte.circuit = m.group(1) in CIRCUITS
|
|
|
|
|
self.rtes.append(rte)
|
|
|
|
|
last_time = None
|
|
|
|
|
continue
|
|
|
|
|
m = OUT_FLIGHT_KM_RE.match(line)
|
|
|
|
|
if m:
|
|
|
|
|
rte.distance = float(m.group(1))
|
|
|
|
|
continue
|
|
|
|
|
m = OUT_FLIGHT_POINTS_RE.match(line)
|
|
|
|
|
if m:
|
|
|
|
|
rte.score = float(m.group(1))
|
|
|
|
|
rte.multiplier = rte.score / rte.distance
|
|
|
|
|
continue
|
|
|
|
|
m = OUT_P_RE.match(line)
|
|
|
|
|
if m:
|
|
|
|
|
rtept = RtePt()
|
|
|
|
|
rtept.name = 'TP%d' % len(rte.rtepts) if rte.rtepts else 'Start'
|
|
|
|
|
rtept.lat = int(m.group(5)) + float(m.group(6)) / 60.0
|
|
|
|
|
if m.group(4) == 'S':
|
|
|
|
|
rtept.lat = -rtept.lat
|
|
|
|
|
rtept.lon = int(m.group(8)) + float(m.group(9)) / 60.0
|
|
|
|
|
if m.group(7) == 'W':
|
|
|
|
|
rtept.lon = -rtept.lon
|
|
|
|
|
time = datetime.time(*map(int, m.group(1, 2, 3)))
|
|
|
|
|
if not last_time is None and time < last_time:
|
|
|
|
|
date += datetime.timedelta(1)
|
|
|
|
|
rtept.dt = datetime.datetime.combine(date, time)
|
|
|
|
|
rte.rtepts.append(rtept)
|
|
|
|
|
last_time = time
|
|
|
|
|
continue
|
|
|
|
|
if debug:
|
|
|
|
|
logging.warning(line)
|
|
|
|
|
for rte in self.rtes:
|
|
|
|
|
rte.rtepts[-1].name = 'Finish'
|
|
|
|
|
|
|
|
|
|
def togpx(self, tb):
|
|
|
|
|
attrs = {'version': '1.1',
|
|
|
|
|
'creator': 'http://github.com/twpayne/igc2kmz/wikis'}
|
|
|
|
|
with tag(tb, 'gpx', attrs):
|
|
|
|
|
for rte in self.rtes:
|
|
|
|
|
rte.togpx(tb)
|
|
|
|
|
return tb
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main(argv):
|
|
|
|
|
parser = optparse.OptionParser(description='olc2002 to GPX converter')
|
|
|
|
|
parser = OptionParser(description='olc2002 to GPX converter')
|
|
|
|
|
parser.add_option('-l', '--league', metavar='STRING')
|
|
|
|
|
parser.add_option('-o', '--output', metavar='FILENAME')
|
|
|
|
|
parser.add_option('--debug', action='store_true')
|
|
|
|
|
parser.set_defaults(debug=False)
|
|
|
|
|
parser.set_defaults(league='OLC')
|
|
|
|
|
options, args = parser.parse_args(argv)
|
|
|
|
|
xc = XC(fileinput.input(args[1:]), options.league, debug=options.debug)
|
|
|
|
|
e = xc.togpx(TreeBuilder()).close()
|
|
|
|
|
#
|
|
|
|
|
routes = []
|
|
|
|
|
date = None
|
|
|
|
|
for line in fileinput.input(args[1:]):
|
|
|
|
|
line = line.rstrip()
|
|
|
|
|
m = DEBUG_DATE_RE.match(line)
|
|
|
|
|
if m:
|
|
|
|
|
day, mon, year = map(int, m.groups())
|
|
|
|
|
date = datetime.date(year + 2000, mon,day)
|
|
|
|
|
continue
|
|
|
|
|
m = OUT_TYPE_RE.match(line)
|
|
|
|
|
if m:
|
|
|
|
|
name = PRETTY_NAME[m.group(1)]
|
|
|
|
|
circuit = m.group(1) in CIRCUITS
|
|
|
|
|
route = Route(name, options.league, None, None, None, circuit, [])
|
|
|
|
|
routes.append(route)
|
|
|
|
|
last_time = None
|
|
|
|
|
continue
|
|
|
|
|
m = OUT_FLIGHT_KM_RE.match(line)
|
|
|
|
|
if m:
|
|
|
|
|
route.distance = float(m.group(1))
|
|
|
|
|
continue
|
|
|
|
|
m = OUT_FLIGHT_POINTS_RE.match(line)
|
|
|
|
|
if m:
|
|
|
|
|
route.score = float(m.group(1))
|
|
|
|
|
route.multiplier = route.score / route.distance
|
|
|
|
|
continue
|
|
|
|
|
m = OUT_P_RE.match(line)
|
|
|
|
|
if m:
|
|
|
|
|
name = 'TP%d' % len(route.tps) if route.tps else 'Start'
|
|
|
|
|
lat = int(m.group(5)) + float(m.group(6)) / 60.0
|
|
|
|
|
if m.group(4) == 'S':
|
|
|
|
|
lat = -lat
|
|
|
|
|
lon = int(m.group(8)) + float(m.group(9)) / 60.0
|
|
|
|
|
if m.group(7) == 'W':
|
|
|
|
|
lon = -lon
|
|
|
|
|
time = datetime.time(*map(int, m.group(1, 2, 3)))
|
|
|
|
|
if not last_time is None and time < last_time:
|
|
|
|
|
date += datetime.timedelta(1)
|
|
|
|
|
dt = datetime.datetime.combine(date, time)
|
|
|
|
|
coord = Coord(lat, lon, 0, dt)
|
|
|
|
|
tp = Turnpoint(name, coord)
|
|
|
|
|
route.tps.append(tp)
|
|
|
|
|
last_time = time
|
|
|
|
|
continue
|
|
|
|
|
if options.debug:
|
|
|
|
|
logging.warning(line)
|
|
|
|
|
for route in routes:
|
|
|
|
|
route.tps[-1].name = 'Finish'
|
|
|
|
|
xc = XC(routes)
|
|
|
|
|
attrs = {'version': '1.1',
|
|
|
|
|
'creator': 'http://github.com/twpayne/igc2kmz/wikis'}
|
|
|
|
|
with tag(TreeBuilder(), 'gpx', attrs) as tb:
|
|
|
|
|
element = xc.build_tree(tb).close()
|
|
|
|
|
output = open(options.output, 'w') if options.output else sys.stdout
|
|
|
|
|
output.write('<?xml version="1.0" encoding="UTF-8"?>')
|
|
|
|
|
ElementTree(e).write(output)
|
|
|
|
|
ElementTree(element).write(output)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|