def querywpname(self): pos=mapper.from_str(request.params['pos']) lat,lon=pos print "Getwpname:",pos zoomlevel=int(request.params['zoomlevel']) sigps=get_sigpoints(lat,lon,zoomlevel) print "Getwpname sigps:",sigps if len(sigps): return json.dumps([sigps[0]['name'],mapper.from_str(sigps[0]['pos'])]) return "notok"
def querywpname(self): pos = mapper.from_str(request.params['pos']) lat, lon = pos print "Getwpname:", pos zoomlevel = int(request.params['zoomlevel']) sigps = get_sigpoints(lat, lon, zoomlevel) print "Getwpname sigps:", sigps if len(sigps): return json.dumps( [sigps[0]['name'], mapper.from_str(sigps[0]['pos'])]) return "notok"
def ats(self): try: #waypoints=meta.Session.query(Waypoint).filter(sa.and_( # Waypoint.user==tripuser(),Waypoint.trip==session['current_trip'])).order_by(Waypoint.ordering).all() #c.waypoints=[] self.standard_prep(c) #print "Routes:",c.route def break_subtrips(routes): out = [] T = 0.0 for i, rt in enumerate(routes): out.append(rt) if rt.time_hours: T += rt.time_hours if rt.b.stay or i == len(routes) - 1: if len(out): yield dict(T=T), out T = 0.0 out = [] def format_cruise(tas): if tas > 999: tas = 999 if tas < 0: tas = 0 return "N%04d" % (tas, ) def format_alt(alt): try: alt = alt.upper().strip() if alt.startswith("FL"): ialt = int(float(alt[2:].strip())) return "F%03d" % (ialt, ) ialt = int(float(alt)) / 100 print "parsed alt %s" % (repr(alt, )), "as", ialt return "A%03d" % (ialt, ) except Exception: raise AtsException( "Bad altitude specification for some leg: <%s>" % (alt)) c.atstrips = [] last_fuel_left = None nr_persons = None for meta, routes in break_subtrips(c.route): print "===============New subtrip..............." spaces = set() fir_whenposname = [] accum_time = 0 #print "broke ruote",meta if len(routes) == 0: continue at = dict() at['T'] = meta['T'] waypoints = [routes[0].a] for rt in routes: waypoints.append(rt.b) wps = [] stay = routes[0].a.stay dep_ad = "ZZZZ" dep_ad_name = waypoints[0].waypoint dep_ad_coords = mapper.format_lfv_ats( *mapper.from_str(waypoints[0].pos)) dest_ad = "ZZZZ" dest_ad_name = waypoints[-1].waypoint dest_ad_coords = mapper.format_lfv_ats( *mapper.from_str(waypoints[-1].pos)) extra_remarks = [] lastwppos = None lastaltspeed = None for i, wp in enumerate(waypoints): print "Subtrip:", i, wp.waypoint at['T'] = meta['T'] lat, lon = mapper.from_str(wp.pos) if lastwppos: assert i >= 1 curpos = (lat, lon) crossing1 = airspace.get_fir_crossing( lastwppos, curpos) for sub in routes[i - 1].subs: if crossing1: posa,posb=mapper.merc2latlon(sub.subposa,13),\ mapper.merc2latlon(sub.subposb,13) crossing = airspace.get_fir_crossing( posa, posb) if crossing: fir, enterpos = crossing bearing, along = mapper.bearing_and_distance( posa, enterpos) if sub.gs > 1e-6: curtime = accum_time + along / sub.gs fir_whenposname.append( (curtime, enterpos, fir['icao'])) if sub.time != None: accum_time += sub.time else: accum_time = 9999 for space in get_any_space_on_line(lastwppos, curpos): spaces.add((space['name'], space.get('floor', "<Unknown>"), space.get('ceiling', "<Unknown>"))) lastwppos = (lat, lon) symbolicpos = None airport = None if i == 0 or i == len(waypoints) - 1: for ad in airspace.get_airfields(lat, lon, 11): if not ad['icao'].upper() in ['ZZZZ', 'ESVF']: airport = ad symbolicpos = ad['icao'].upper() if i == 0: dep_ad = ad['icao'].upper() if i == len(waypoints) - 1: dest_ad = ad['icao'].upper() break else: for sigp in airspace.get_sigpoints(lat, lon, 11): if sigp['kind'] == "sig. point": if len(sigp['name']) == 5: sigfound = sigp symbolicpos = sigp['name'] break if symbolicpos == None: symbolicpos = mapper.format_lfv_ats(lat, lon) if i < len(routes): altspeed = (format_alt(routes[i].altitude), format_cruise(routes[i].tas)) if lastaltspeed != None: if lastaltspeed != altspeed: alt, speed = altspeed symbolicpos += "/" + speed + alt lastaltspeed = altspeed wps.append( dict(name=wp.waypoint, airport=airport, symbolicpos="DCT " + symbolicpos, exactpos=mapper.format_lfv(lat, lon), decimalpos="%.5f,%.5f" % (lat, lon))) for when, pos, fir in fir_whenposname: hour, minute = divmod(int(60 * when), 60) extra_remarks.append("EET/%s%02d%02d" % (fir, hour, minute)) if dep_ad == "ZZZZ": extra_remarks.append( u"DEP/%s %s" % (dep_ad_coords, strip_accents(dep_ad_name.upper()))) if dest_ad == "ZZZZ": extra_remarks.append( u"DEST/%s %s" % (dest_ad_coords, strip_accents(dest_ad_name.upper()))) if stay.date_of_flight.strip(): dof = stay.date_of_flight.replace("-", "").strip() if len(dof) == 8 and dof.startswith("20"): dof = dof[2:] else: dof = routes[0].depart_dt.strftime("%y%m%d") print "dof:", dof if len(dof) != 6: raise AtsException( u"ATS flight plans need takeoff date for all takeoffs!" ) else: extra_remarks.append(u"DOF/%s" % (dof, )) if stay and stay.nr_persons: nr_persons = stay.nr_persons else: if nr_persons == None: raise AtsException( u"You must enter the the number of persons who will be flying!" ) tas = routes[0].tas altitude = routes[0].altitude at['wps'] = wps if any(rt.time_hours == None for rt in routes): raise AtsException( "TAS is less than headwind for some part of trip.") enroute_time = sum(rt.time_hours for rt in routes) fuel = last_fuel_left if stay and stay.fuel: fuel = stay.fuel if not c.ac: raise AtsException( "You must choose an aircraft type for this journey to be able to create an ATS flight plan" ) if c.ac.cruise_burn > 1e-3 and fuel: endurance = float(fuel) / float(c.ac.cruise_burn) else: endurance = 0.0 if endurance <= 0.0: if fuel == None: raise AtsException( "Enter a value for 'Fuel at takeoff'!") else: raise AtsException( "You do not have enough fuel for the entire journey! This means your endurance would be 0 or negative for one or more legs. Add a fuel stop, shorten the journey, or bring more fuel!" ) if not c.user.realname: raise AtsException( "You should enter your name under profile settings, for use as the name of the commander in the flight plan" ) phonenr = "" if c.user.phonenr: phonenr = c.user.phonenr fir_whenposname.sort() def eqp(x, s): x = "".join(re.findall('[A-Z]', x.upper())) if len(x) == 0: return s return x dummy = u""" FPL-SEVLI-VG -ULAC/L-V/C -EFKG1330 -N0075F065 DCT 5959N02016E DCT 5949N01936E DCT 5929N01818E DCT 5927N01742E -ZZZZ0130 -DEST/5927N01742E FRÖLUNDA RMK/BORDER CROSSING 40MIN AFTER TAKEOFF DOF/101002 ORGN/ESSAZPZX -E/0300 P/2 A/R W C/ANDERS MUSIKKA +4670123123""" atsfplan = u""" (FPL-%(acreg)s-%(flight_rules)s%(type_of_flight)s -%(actype)s/%(turbulence_category)s-%(equipment)s/%(transponder)s -%(dep_ad)s%(eobt)s -%(cruise_speed)s%(level)s %(route)s DCT -%(dest_ad)s%(ete)s -%(extra_remarks)s -E/%(endurance)s P/%(nr_passengers)s A/%(markings)s%(extra_equipment)s C/%(commander)s %(phonenr)s)""" % (dict( acreg=c.ac.aircraft.replace("-", ""), actype=c.ac.atstype, turbulence_category='L', flight_rules='V', type_of_flight='G', equipment=eqp(c.ac.com_nav_equipment, 'V'), transponder=eqp(c.ac.transponder_equipment, 'C'), extra_equipment=u" %s" % (c.ac.extra_equipment, ) if c.ac.extra_equipment else "", dep_ad=dep_ad, eobt=routes[0].depart_dt.strftime("%H%M"), cruise_speed=format_cruise(tas), level=format_alt(altitude), route=(" ".join("%s" % (w['symbolicpos'], ) for w in wps[1:-1])), dest_ad=dest_ad, ete=lfvclockfmt(enroute_time), extra_remarks=" ".join(extra_remarks), endurance=lfvclockfmt(endurance), nr_passengers=nr_persons, markings=c.ac.markings, commander=strip_accents(c.user.realname if c.user.realname else u"UNKNOWN").replace(" ", ""), phonenr=c.user.phonenr if c.user.phonenr else "")) at['atsfplan'] = atsfplan.strip() #print "Adding atstrip:",atsfplan at['spacesummary'] = spaces last_fuel_left = routes[-1].accum_fuel_left c.atstrips.append(at) c.atstrips = [at for at in c.atstrips if len(at['wps'])] #response.headers['Content-Type'] = 'application/xml' return render('/ats.mako') except AtsException, ats: redirect( h.url_for(controller='flightplan', action="index", flash=unicode(ats)))
def get_airspace(self): utcnow = datetime.utcnow() try: zoomlevel = int(request.params['zoom']) except Exception: zoomlevel = session.get('zoom', 5) lat = float(request.params.get('lat')) lon = float(request.params.get('lon')) clickmerc = mapper.latlon2merc((lat, lon), zoomlevel) user = session.get('user', None) out = [] spaces = chain(get_airspaces(lat, lon), userdata.get_airspaces(lat, lon, user)) print "Spaces:", spaces def anydate(s): if not 'date' in s: return "" d = s['date'] age = utcnow - d if age > timedelta(367): return "<span style=\"font-size:10px\">[%d]</span>" % ( d.year, ) if age > timedelta(2): return "<span style=\"font-size:10px\">[%d%02d%02d]</span>" % ( d.year, d.month, d.day) return "" spacelist = spaces spaces = u"".join(u"<li><b>%s</b>%s: %s - %s%s</li>" % (space['name'], anydate(space), space['floor'], space['ceiling'], format_freqs(space['freqs'])) for space in sorted(spacelist, key=sort_airspace_key) if space['type'] != 'sector') #sectors=u"".join(u"<li><b>%s</b>%s: %s - %s%s</li>"%( # space['name'],anydate(space),space['floor'],space['ceiling'],format_freqs(space['freqs'])) for space in sorted( # spacelist,key=sort_airspace_key) if space['type']=='sectoasdfr') try: sectors = u"".join( u"<li><b>%s</b>%s: %s - %s%s</li>" % (space['name'], anydate(space), space['floor'], space['ceiling'], format_freqs(space['freqs'])) for space in sorted(spacelist, key=sort_airspace_key) if space['type'] == 'sector') if sectors != "": sectors = "<b>Sectors:</b><ul>" + sectors + "</ul>" except: print traceback.format_exc() sectors = "" if spaces == "": spaces = "No airspace found" mapviewurl = h.url_for(controller="mapview", action="index") notamlist = chain(get_notam_areas(lat, lon), get_notampoints(lat, lon, zoomlevel)) notams = dict([(n['notam'].strip(), (n['notam_ordinal'], n['notam_line'])) for n in notamlist]) notamareas = "".join( "<li>%s <b><u><a href=\"javascript:navigate_to('%s#notam')\">Link</a></u></b></li>" % (text, h.url_for(controller="notam", action="show_ctx", backlink=mapviewurl, notam=notam, line=line)) for text, (notam, line) in notams.items()) if notamareas != "": notamareas = "<b>Area Notams:</b><ul>" + notamareas + "</ul>" aip_sup_strs = "".join([ "<li>%s <a href=\"%s\">link</a></li>" % (x['name'], x['url'].replace(" ", "%20")) for x in get_aip_sup_areas(lat, lon) ]) if aip_sup_strs: aip_sup_strs = "<b>AIP SUP:</b><ul>" + aip_sup_strs + "</ul>" obstbytype = dict() for obst in chain(get_obstacles(lat, lon, zoomlevel), userdata.get_obstacles(lat, lon, zoomlevel, user)): obstbytype.setdefault(obst['kind'], []).append(obst) print "processing", obst obstacles = [] if len(obstbytype): for kind, obsts in sorted(obstbytype.items()): obstacles.append("<b>" + kind + ":</b>") obstacles.append(u"<ul>") for obst in obsts: obstacles.append(u"<li><b>%s</b>: %s ft</li>" % (obst['name'], obst['elev'])) obstacles.append(u"</ul>") tracks = [] if session.get('showtrack', None) != None: track = session.get('showtrack') #print "%d points"%(len(track.points)) mindiff = 1e30 found = dict() hdg = 0 speed = 0 clickvec = Vertex(int(clickmerc[0]), int(clickmerc[1])) if len(track.points) > 0 and len(track.points[0]) == 2: pass #Old style track, not supported anymore else: for a, b in izip(track.points, track.points[1:]): merc = mapper.latlon2merc(a[0], zoomlevel) nextmerc = mapper.latlon2merc(b[0], zoomlevel) l = Line(Vertex(int(merc[0]), int(merc[1])), Vertex(int(nextmerc[0]), int(nextmerc[1]))) diff = l.approx_dist(clickvec) if diff < mindiff: mindiff = diff found = (a, b) if mindiff < 10: tracks.append( u"<b>GPS track:</b><ul><li>%(when)s - %(altitude)d ft hdg:%(heading)03d spd: %(speed)d kt</li></ul>" % (get_stats(*found))) airports = [] fields = list( chain(get_airfields(lat, lon, zoomlevel), userdata.get_airfields(lat, lon, zoomlevel, user))) if len(fields): airports.append("<b>Airfield:</b><ul>") for airp in fields: #print "clicked on ",airp linksstr = "" links = [] if 'flygkartan_id' in airp: links.append(('http://www.flygkartan.se/0%s' % (airp['flygkartan_id'].strip(), ), 'www.flygkartan.se')) if 'aiptexturl' in airp: links.append((airp['aiptexturl'], 'AIP Text')) if 'aipvacurl' in airp: links.append( (airp['aipvacurl'], 'AIP Visual Approach Chart')) if False and 'aipsup' in airp: #Using AIP SUP for opening hours has stopped. links.append((extracted_cache.get_se_aip_sup_hours_url(), "AIP SUP Opening Hours")) weather = "" if airp.get('icao', 'ZZZZ').upper() != 'ZZZZ': icao = airp['icao'].upper() metar = metartaf.get_metar(icao) taf = metartaf.get_taf(icao) weather = "<table>" def colorize(item, colfac=1): if item == None: col = "ffffff" agestr = "" else: age = metartaf.get_data_age(item) if age == None: col = "ffffff" agestr = "" elif age < timedelta(0, 60 * 35 * colfac): col = "c5c5c5" agestr = "%d minutes" % (int(age.seconds / 60)) elif age < timedelta(0, 60 * 60 * colfac): col = "ffff30" agestr = "%d minutes" % (int(age.seconds / 60)) else: col = "ff3030" if age < timedelta(2): if age < timedelta(0, 3600 * 1.5): agestr = "%d minutes" % int( age.seconds / 60) else: agestr = "%d hours" % int( 0.5 + (age.seconds) / 3600.0) else: agestr = "%d days" % (int(age.days)) return "style=\"background:#" + col + "\" title=\"" + agestr + " old.\"" if taf and taf.text: weather += "<tr valign=\"top\"><td>TAF:</td><td " + colorize( taf, 5) + ">" + taf.text + "</td></tr>" if metar and metar.text: weather += "<tr valign=\"top\"><td>METAR:</td><td " + colorize( metar) + ">" + metar.text + "</td></tr>" ack_cnt = meta.Session.query( NotamAck.appearnotam, NotamAck.appearline, sa.func.count('*').label('acks')).filter( NotamAck.user == session.get( 'user', None)).group_by( NotamAck.appearnotam, NotamAck.appearline).subquery() notams = meta.Session.query( NotamUpdate, ack_cnt.c.acks, Notam.downloaded ).outerjoin( (ack_cnt, sa.and_( NotamUpdate.appearnotam == ack_cnt.c.appearnotam, NotamUpdate.appearline == ack_cnt.c.appearline)) ).outerjoin( (Notam, Notam.ordinal == NotamUpdate.appearnotam)).order_by( sa.desc(Notam.downloaded)).filter( sa.and_( NotamUpdate.disappearnotam == sa.null(), NotamUpdate.category.like(icao.upper() + "/%"))).all() print "notams:", repr(notams) if notams: nots = [] for notam, ack, downloaded in notams: nots.append( "<div style=\"border:1px solid;margin:3px;border-color:#B8B8B8;padding:3px;\">%s</div>" % (cgi.escape(notam.text))) weather += "<tr valign=\"top\"><td colspan=\"2\">NOTAM:</td></tr><tr><td colspan=\"2\">%s</td></tr>" % ( "".join(nots)) weather += "</table>" meta.Session.flush() meta.Session.commit() if len(links) > 0 and 'icao' in airp: linksstr = helpers.foldable_links(airp['icao'] + "links", links) rwys = [] if 'runways' in airp: for rwy in airp['runways']: ends = [] for end in rwy['ends']: ends.append(end['thr']) surf = "" if 'surface' in rwy: surf = "(" + rwy['surface'] + ")" rwys.append("/".join(ends) + surf) if len(rwys): rwys = ["<b> Runways</b>: "] + [", ".join(rwys)] remark = "" if airp.get('remark'): remark = "<div style=\"border:1px solid;margin:3px;border-color:#B8B8B8;padding:3px;background-color:#ffffe0\"><b>Remark:</b> " + cgi.escape( airp['remark']) + "</div>" airports.append(u"<li><b>%s</b> - %s%s%s%s%s</li>" % (airp.get('icao', 'ZZZZ'), airp['name'], linksstr, remark, " ".join(rwys), weather)) airports.append("</ul>") sigpoints = [] sigps = list( chain(get_sigpoints(lat, lon, zoomlevel), userdata.get_sigpoints(lat, lon, zoomlevel, user))) if len(sigps): sigpoints.append("<b>Sig. points</b><ul>") for sigp in sigps: sigpoints.append( u"<li><b>%s</b>(%s)</li>" % (sigp['name'], sigp.get('kind', 'unknown point'))) sigpoints.append("</ul>") firs = [] for fir in list(get_firs( (lat, lon))) + list(userdata.get_firs(lat, lon, user)): if 'icao' in fir: firs.append("%s (%s)" % (fir['name'], fir['icao'])) if not firs: firs.append("Unknown") variation = '?' terrelev = get_terrain_elev((lat, lon), zoomlevel) try: varf = geomag.calc_declination((lat, lon), utcnow, (terrelev + 1000)) variation = u"%+.1f°" % (varf, ) except Exception: pass weather = "" try: when, valid, fct = gfs_weather.get_prognosis(datetime.utcnow()) qnh = fct.get_qnh(lat, lon) out = [ "<b>Weather</b><br/>Forecast: %sZ, valid: %sZ<br />" % (when.strftime("%Y-%m-%d %H:%M"), valid.strftime("%H:%M")) ] try: out.append("Surface wind: %.0f deg, %.1f knots<br />" % fct.get_surfacewind(lat, lon)) out.append("Surface RH: %.0f%%<br />" % (fct.get_surfacerh(lat, lon), )) except: print traceback.format_exc() out.append("<ul>") for fl, dir, st, temp in fct.get_winds(lat, lon): out.append("<li>FL%02d: %03d deg, %.1fkt, %.1f °C" % (int(fl), int(dir), float(st), temp)) out.append("</ul>QNH: %d<br/><br/>" % (qnh, )) weather = "".join(out) except Exception: print traceback.format_exc() return "<b>Airspace:</b><ul><li><b>FIR:</b> %s</li>%s</ul>%s%s%s%s%s%s%s<br/>%s<b>Terrain: %s ft, Var: %s</b>" % ( ", ".join(firs), spaces, sectors, aip_sup_strs, "".join(obstacles), "".join(airports), "".join(tracks), "".join(sigpoints), notamareas, weather, terrelev, variation)
def ats(self): try: #waypoints=meta.Session.query(Waypoint).filter(sa.and_( # Waypoint.user==tripuser(),Waypoint.trip==session['current_trip'])).order_by(Waypoint.ordering).all() #c.waypoints=[] self.standard_prep(c) #print "Routes:",c.route def break_subtrips(routes): out=[] T=0.0 for i,rt in enumerate(routes): out.append(rt) if rt.time_hours: T+=rt.time_hours if rt.b.stay or i==len(routes)-1: if len(out): yield dict(T=T),out T=0.0 out=[] def format_cruise(tas): if tas>999: tas=999 if tas<0: tas=0 return "N%04d"%(tas,) def format_alt(alt): try: alt=alt.upper().strip() if alt.startswith("FL"): ialt=int(float(alt[2:].strip())) return "F%03d"%(ialt,) ialt=int(float(alt))/100 print "parsed alt %s"%(repr(alt,)),"as",ialt return "A%03d"%(ialt,) except Exception: raise AtsException("Bad altitude specification for some leg: <%s>"%(alt)) c.atstrips=[] last_fuel_left=None nr_persons=None for meta,routes in break_subtrips(c.route): print "===============New subtrip..............." spaces=set() fir_whenposname=[] accum_time=0 #print "broke ruote",meta if len(routes)==0: continue at=dict() at['T']=meta['T'] waypoints=[routes[0].a] for rt in routes: waypoints.append(rt.b) wps=[] stay=routes[0].a.stay dep_ad="ZZZZ" dep_ad_name=waypoints[0].waypoint dep_ad_coords=mapper.format_lfv_ats(*mapper.from_str(waypoints[0].pos)) dest_ad="ZZZZ" dest_ad_name=waypoints[-1].waypoint dest_ad_coords=mapper.format_lfv_ats(*mapper.from_str(waypoints[-1].pos)) extra_remarks=[] lastwppos=None lastaltspeed=None for i,wp in enumerate(waypoints): print "Subtrip:",i,wp.waypoint at['T']=meta['T'] lat,lon=mapper.from_str(wp.pos) if lastwppos: assert i>=1 curpos=(lat,lon) crossing1=airspace.get_fir_crossing(lastwppos,curpos) for sub in routes[i-1].subs: if crossing1: posa,posb=mapper.merc2latlon(sub.subposa,13),\ mapper.merc2latlon(sub.subposb,13) crossing=airspace.get_fir_crossing(posa,posb) if crossing: fir,enterpos=crossing bearing,along=mapper.bearing_and_distance(posa,enterpos) if sub.gs>1e-6: curtime=accum_time+along/sub.gs fir_whenposname.append((curtime,enterpos,fir['icao'])) if sub.time!=None: accum_time+=sub.time else: accum_time=9999 for space in get_any_space_on_line(lastwppos,curpos): spaces.add((space['name'],space.get('floor',"<Unknown>"),space.get('ceiling',"<Unknown>"))) lastwppos=(lat,lon) symbolicpos=None airport=None if i==0 or i==len(waypoints)-1: for ad in airspace.get_airfields(lat,lon,11): if not ad['icao'].upper() in ['ZZZZ','ESVF']: airport=ad symbolicpos=ad['icao'].upper() if i==0: dep_ad=ad['icao'].upper() if i==len(waypoints)-1: dest_ad=ad['icao'].upper() break else: for sigp in airspace.get_sigpoints(lat,lon,11): if sigp['kind']=="sig. point": if len(sigp['name'])==5: sigfound=sigp symbolicpos=sigp['name'] break if symbolicpos==None: symbolicpos=mapper.format_lfv_ats(lat,lon) if i<len(routes): altspeed=(format_alt(routes[i].altitude),format_cruise(routes[i].tas)) if lastaltspeed!=None: if lastaltspeed!=altspeed: alt,speed=altspeed symbolicpos+="/"+speed+alt lastaltspeed=altspeed wps.append(dict( name=wp.waypoint, airport=airport, symbolicpos="DCT "+symbolicpos, exactpos=mapper.format_lfv(lat,lon), decimalpos="%.5f,%.5f"%(lat,lon) )) for when,pos,fir in fir_whenposname: hour,minute=divmod(int(60*when),60) extra_remarks.append("EET/%s%02d%02d"%(fir,hour,minute)) if dep_ad=="ZZZZ": extra_remarks.append(u"DEP/%s %s"%(dep_ad_coords,strip_accents(dep_ad_name.upper()))) if dest_ad=="ZZZZ": extra_remarks.append(u"DEST/%s %s"%(dest_ad_coords,strip_accents(dest_ad_name.upper()))) if stay.date_of_flight.strip(): dof=stay.date_of_flight.replace("-","").strip() if len(dof)==8 and dof.startswith("20"): dof=dof[2:] else: dof=routes[0].depart_dt.strftime("%y%m%d") print "dof:",dof if len(dof)!=6: raise AtsException(u"ATS flight plans need takeoff date for all takeoffs!") else: extra_remarks.append(u"DOF/%s"%(dof,)) if stay and stay.nr_persons: nr_persons=stay.nr_persons else: if nr_persons==None: raise AtsException(u"You must enter the the number of persons who will be flying!") tas=routes[0].tas altitude=routes[0].altitude at['wps']=wps if any(rt.time_hours==None for rt in routes): raise AtsException("TAS is less than headwind for some part of trip.") enroute_time=sum(rt.time_hours for rt in routes) fuel=last_fuel_left if stay and stay.fuel: fuel=stay.fuel if not c.ac: raise AtsException("You must choose an aircraft type for this journey to be able to create an ATS flight plan") if c.ac.cruise_burn>1e-3 and fuel: endurance=float(fuel)/float(c.ac.cruise_burn) else: endurance=0.0 if endurance<=0.0: if fuel==None: raise AtsException("Enter a value for 'Fuel at takeoff'!") else: raise AtsException("You do not have enough fuel for the entire journey! This means your endurance would be 0 or negative for one or more legs. Add a fuel stop, shorten the journey, or bring more fuel!") if not c.user.realname: raise AtsException("You should enter your name under profile settings, for use as the name of the commander in the flight plan") phonenr="" if c.user.phonenr: phonenr=c.user.phonenr fir_whenposname.sort() def eqp(x,s): x="".join(re.findall('[A-Z]',x.upper())) if len(x)==0: return s return x dummy=u""" FPL-SEVLI-VG -ULAC/L-V/C -EFKG1330 -N0075F065 DCT 5959N02016E DCT 5949N01936E DCT 5929N01818E DCT 5927N01742E -ZZZZ0130 -DEST/5927N01742E FRÖLUNDA RMK/BORDER CROSSING 40MIN AFTER TAKEOFF DOF/101002 ORGN/ESSAZPZX -E/0300 P/2 A/R W C/ANDERS MUSIKKA +4670123123""" atsfplan=u""" (FPL-%(acreg)s-%(flight_rules)s%(type_of_flight)s -%(actype)s/%(turbulence_category)s-%(equipment)s/%(transponder)s -%(dep_ad)s%(eobt)s -%(cruise_speed)s%(level)s %(route)s DCT -%(dest_ad)s%(ete)s -%(extra_remarks)s -E/%(endurance)s P/%(nr_passengers)s A/%(markings)s%(extra_equipment)s C/%(commander)s %(phonenr)s)"""%(dict( acreg=c.ac.aircraft.replace("-",""), actype=c.ac.atstype, turbulence_category='L', flight_rules='V', type_of_flight='G', equipment=eqp(c.ac.com_nav_equipment,'V'), transponder=eqp(c.ac.transponder_equipment,'C'), extra_equipment=u" %s"%(c.ac.extra_equipment,) if c.ac.extra_equipment else "", dep_ad=dep_ad, eobt=routes[0].depart_dt.strftime("%H%M"), cruise_speed=format_cruise(tas), level=format_alt(altitude), route=(" ".join("%s"%(w['symbolicpos'],) for w in wps[1:-1])), dest_ad=dest_ad, ete=lfvclockfmt(enroute_time), extra_remarks=" ".join(extra_remarks), endurance=lfvclockfmt(endurance), nr_passengers=nr_persons, markings=c.ac.markings, commander=strip_accents(c.user.realname if c.user.realname else u"UNKNOWN").replace(" ",""), phonenr=c.user.phonenr if c.user.phonenr else "")) at['atsfplan']=atsfplan.strip() #print "Adding atstrip:",atsfplan at['spacesummary']=spaces last_fuel_left=routes[-1].accum_fuel_left c.atstrips.append(at) c.atstrips=[at for at in c.atstrips if len(at['wps'])] #response.headers['Content-Type'] = 'application/xml' return render('/ats.mako') except AtsException,ats: redirect(h.url_for(controller='flightplan',action="index",flash=unicode(ats)))
def get_airspace(self): utcnow=datetime.utcnow() try: zoomlevel=int(request.params['zoom']) except Exception: zoomlevel=session.get('zoom',5) lat=float(request.params.get('lat')) lon=float(request.params.get('lon')) clickmerc=mapper.latlon2merc((lat,lon),zoomlevel) user=session.get('user',None) out=[] spaces=chain(get_airspaces(lat,lon),userdata.get_airspaces(lat,lon,user)) print "Spaces:",spaces def anydate(s): if not 'date' in s: return "" d=s['date'] age=utcnow-d if age>timedelta(367): return "<span style=\"font-size:10px\">[%d]</span>"%(d.year,) if age>timedelta(2): return "<span style=\"font-size:10px\">[%d%02d%02d]</span>"%( d.year,d.month,d.day) return "" spacelist=spaces spaces=u"".join(u"<li><b>%s</b>%s: %s - %s%s</li>"%( space['name'],anydate(space),space['floor'],space['ceiling'],format_freqs(space['freqs'])) for space in sorted( spacelist,key=sort_airspace_key) if space['type']!='sector') #sectors=u"".join(u"<li><b>%s</b>%s: %s - %s%s</li>"%( # space['name'],anydate(space),space['floor'],space['ceiling'],format_freqs(space['freqs'])) for space in sorted( # spacelist,key=sort_airspace_key) if space['type']=='sectoasdfr') try: sectors=u"".join(u"<li><b>%s</b>%s: %s - %s%s</li>"%( space['name'],anydate(space),space['floor'],space['ceiling'],format_freqs(space['freqs'])) for space in sorted( spacelist,key=sort_airspace_key) if space['type']=='sector') if sectors!="": sectors="<b>Sectors:</b><ul>"+sectors+"</ul>" except: print traceback.format_exc() sectors="" if spaces=="": spaces="No airspace found" mapviewurl=h.url_for(controller="mapview",action="index") notamlist=chain(get_notam_areas(lat,lon),get_notampoints(lat,lon,zoomlevel)) notams=dict([(n['notam'].strip(),(n['notam_ordinal'],n['notam_line']) ) for n in notamlist]) notamareas="".join("<li>%s <b><u><a href=\"javascript:navigate_to('%s#notam')\">Link</a></u></b></li>"%( text,h.url_for(controller="notam",action="show_ctx",backlink=mapviewurl,notam=notam,line=line)) for text,(notam,line) in notams.items()) if notamareas!="": notamareas="<b>Area Notams:</b><ul>"+notamareas+"</ul>" aip_sup_strs="".join(["<li>%s <a href=\"%s\">link</a></li>"%(x['name'],x['url'].replace(" ","%20")) for x in get_aip_sup_areas(lat,lon)]) if aip_sup_strs: aip_sup_strs="<b>AIP SUP:</b><ul>"+aip_sup_strs+"</ul>" obstbytype=dict() for obst in chain(get_obstacles(lat,lon,zoomlevel),userdata.get_obstacles(lat,lon,zoomlevel,user)): obstbytype.setdefault(obst['kind'],[]).append(obst) print "processing",obst obstacles=[] if len(obstbytype): for kind,obsts in sorted(obstbytype.items()): obstacles.append("<b>"+kind+":</b>") obstacles.append(u"<ul>") for obst in obsts: obstacles.append(u"<li><b>%s</b>: %s ft</li>"%(obst['name'],obst['elev'])) obstacles.append(u"</ul>") tracks=[] if session.get('showtrack',None)!=None: track=session.get('showtrack') #print "%d points"%(len(track.points)) mindiff=1e30 found=dict() hdg=0 speed=0 clickvec=Vertex(int(clickmerc[0]),int(clickmerc[1])) if len(track.points)>0 and len(track.points[0])==2: pass #Old style track, not supported anymore else: for a,b in izip(track.points,track.points[1:]): merc=mapper.latlon2merc(a[0],zoomlevel) nextmerc=mapper.latlon2merc(b[0],zoomlevel) l=Line(Vertex(int(merc[0]),int(merc[1])),Vertex(int(nextmerc[0]),int(nextmerc[1]))) diff=l.approx_dist(clickvec) if diff<mindiff: mindiff=diff found=(a,b) if mindiff<10: tracks.append(u"<b>GPS track:</b><ul><li>%(when)s - %(altitude)d ft hdg:%(heading)03d spd: %(speed)d kt</li></ul>"%(get_stats(*found))) airports=[] fields=list(chain(get_airfields(lat,lon,zoomlevel),userdata.get_airfields(lat,lon,zoomlevel,user))) if len(fields): airports.append("<b>Airfield:</b><ul>") for airp in fields: #print "clicked on ",airp linksstr="" links=[] if 'flygkartan_id' in airp: links.append(('http://www.flygkartan.se/0%s'%(airp['flygkartan_id'].strip(),), 'www.flygkartan.se')) if 'aiptexturl' in airp: links.append((airp['aiptexturl'], 'AIP Text')) if 'aipvacurl' in airp: links.append((airp['aipvacurl'], 'AIP Visual Approach Chart')) if False and 'aipsup' in airp: #Using AIP SUP for opening hours has stopped. links.append(( extracted_cache.get_se_aip_sup_hours_url(), "AIP SUP Opening Hours")) weather="" if airp.get('icao','ZZZZ').upper()!='ZZZZ': icao=airp['icao'].upper() metar=metartaf.get_metar(icao) taf=metartaf.get_taf(icao) weather="<table>" def colorize(item,colfac=1): if item==None: col="ffffff" agestr="" else: age=metartaf.get_data_age(item) if age==None: col="ffffff" agestr="" elif age<timedelta(0,60*35*colfac): col="c5c5c5" agestr="%d minutes"%(int(age.seconds/60)) elif age<timedelta(0,60*60*colfac): col="ffff30" agestr="%d minutes"%(int(age.seconds/60)) else: col="ff3030" if age<timedelta(2): if age<timedelta(0,3600*1.5): agestr="%d minutes"%int(age.seconds/60) else: agestr="%d hours"%int(0.5+(age.seconds)/3600.0) else: agestr="%d days"%(int(age.days)) return "style=\"background:#"+col+"\" title=\""+agestr+" old.\"" if taf and taf.text: weather+="<tr valign=\"top\"><td>TAF:</td><td "+colorize(taf,5)+">"+taf.text+"</td></tr>" if metar and metar.text: weather+="<tr valign=\"top\"><td>METAR:</td><td "+colorize(metar)+">"+metar.text+"</td></tr>" ack_cnt = meta.Session.query(NotamAck.appearnotam,NotamAck.appearline,sa.func.count('*').label('acks')).filter(NotamAck.user==session.get('user',None)).group_by(NotamAck.appearnotam,NotamAck.appearline).subquery() notams=meta.Session.query(NotamUpdate,ack_cnt.c.acks,Notam.downloaded).outerjoin( (ack_cnt,sa.and_( NotamUpdate.appearnotam==ack_cnt.c.appearnotam, NotamUpdate.appearline==ack_cnt.c.appearline))).outerjoin( (Notam,Notam.ordinal==NotamUpdate.appearnotam) ).order_by(sa.desc(Notam.downloaded)).filter( sa.and_(NotamUpdate.disappearnotam==sa.null(), NotamUpdate.category.like(icao.upper()+"/%") )).all() print "notams:",repr(notams) if notams: nots=[] for notam,ack,downloaded in notams: nots.append("<div style=\"border:1px solid;margin:3px;border-color:#B8B8B8;padding:3px;\">%s</div>"%(cgi.escape(notam.text))) weather+="<tr valign=\"top\"><td colspan=\"2\">NOTAM:</td></tr><tr><td colspan=\"2\">%s</td></tr>"%("".join(nots)) weather+="</table>" meta.Session.flush() meta.Session.commit() if len(links)>0 and 'icao' in airp: linksstr=helpers.foldable_links(airp['icao']+"links",links) rwys=[] if 'runways' in airp: for rwy in airp['runways']: ends=[] for end in rwy['ends']: ends.append(end['thr']) surf="" if 'surface' in rwy: surf="("+rwy['surface']+")" rwys.append("/".join(ends)+surf) if len(rwys): rwys=["<b> Runways</b>: "]+[", ".join(rwys)] remark="" if airp.get('remark'): remark="<div style=\"border:1px solid;margin:3px;border-color:#B8B8B8;padding:3px;background-color:#ffffe0\"><b>Remark:</b> "+cgi.escape(airp['remark'])+"</div>" airports.append(u"<li><b>%s</b> - %s%s%s%s%s</li>"%(airp.get('icao','ZZZZ'),airp['name'],linksstr,remark," ".join(rwys),weather)) airports.append("</ul>") sigpoints=[] sigps=list(chain(get_sigpoints(lat,lon,zoomlevel),userdata.get_sigpoints(lat,lon,zoomlevel,user))) if len(sigps): sigpoints.append("<b>Sig. points</b><ul>") for sigp in sigps: sigpoints.append(u"<li><b>%s</b>(%s)</li>"%(sigp['name'],sigp.get('kind','unknown point'))) sigpoints.append("</ul>") firs=[] for fir in list(get_firs((lat,lon)))+list(userdata.get_firs(lat,lon,user)): if 'icao' in fir: firs.append("%s (%s)"%(fir['name'],fir['icao'])) if not firs: firs.append("Unknown") variation='?' terrelev=get_terrain_elev((lat,lon),zoomlevel) try: varf=geomag.calc_declination((lat,lon),utcnow,(terrelev+1000)) variation=u"%+.1f°"%(varf,) except Exception: pass weather="" try: when,valid,fct=gfs_weather.get_prognosis(datetime.utcnow()) qnh=fct.get_qnh(lat,lon) out=["<b>Weather</b><br/>Forecast: %sZ, valid: %sZ<br />"%(when.strftime("%Y-%m-%d %H:%M"),valid.strftime("%H:%M"))] try: out.append("Surface wind: %.0f deg, %.1f knots<br />"%fct.get_surfacewind(lat,lon)) out.append("Surface RH: %.0f%%<br />"%(fct.get_surfacerh(lat,lon),)) except: print traceback.format_exc() out.append("<ul>") for fl,dir,st,temp in fct.get_winds(lat,lon): out.append("<li>FL%02d: %03d deg, %.1fkt, %.1f °C"%(int(fl),int(dir),float(st),temp)) out.append("</ul>QNH: %d<br/><br/>"%(qnh,)) weather="".join(out) except Exception: print traceback.format_exc() return "<b>Airspace:</b><ul><li><b>FIR:</b> %s</li>%s</ul>%s%s%s%s%s%s%s<br/>%s<b>Terrain: %s ft, Var: %s</b>"%(", ".join(firs),spaces,sectors,aip_sup_strs,"".join(obstacles),"".join(airports),"".join(tracks),"".join(sigpoints),notamareas,weather,terrelev,variation)