Exemplo n.º 1
0
 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"
Exemplo n.º 2
0
 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"
Exemplo n.º 3
0
    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)))
Exemplo n.º 4
0
    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 &#176;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)
Exemplo n.º 5
0
    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)))
Exemplo n.º 6
0
    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 &#176;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)