Esempio n. 1
0
func FixupComplaint(c *types.Complaint, key *datastore.Key) {
	// 0. Snag the key, so we can refer to this object later
	c.DatastoreKey = key.Encode()

	// 1. GAE datastore helpfully converts timezones to UTC upon storage; fix that
	c.Timestamp = date.InPdt(c.Timestamp)

	// 2. Compute the flight details URL, if within 24 days
	age := date.NowInPdt().Sub(c.Timestamp)
	if age < time.Hour*24 {
		// c.AircraftOverhead.Fr24Url = c.AircraftOverhead.PlaybackUrl()

		c.AircraftOverhead.Fr24Url = "http://flightaware.com/live/flight/" +
			c.AircraftOverhead.FlightNumber
		// Or: http://flightaware.com/live/flight/UAL337/history/20151215/ [0655Z/KLAX/KSFO]
		// date is UTC of departure time; might be tricky to guess :/
	}

	// 3. Compute distances, if we have an aircraft
	if c.AircraftOverhead.FlightNumber != "" {
		a := c.AircraftOverhead
		aircraftPos := geo.Latlong{a.Lat, a.Long}
		observerPos := geo.Latlong{c.Profile.Lat, c.Profile.Long}
		c.Dist2KM = observerPos.Dist(aircraftPos)
		c.Dist3KM = observerPos.Dist3(aircraftPos, a.Altitude)
	}
}
Esempio n. 2
0
func AirspaceToLocalizedAircraft(as *airspace.Airspace, pos geo.Latlong, elev float64) []Aircraft {
	ret := []Aircraft{}

	if as == nil {
		return ret
	}

	for _, ad := range as.Aircraft {
		tp := fdb.TrackpointFromADSB(ad.Msg)
		altitudeDelta := tp.Altitude - elev

		icaoid := string(ad.Msg.Icao24)
		icaoid = strings.TrimPrefix(icaoid, "EE") // fr24 airspaces use this prefix
		icaoid = strings.TrimPrefix(icaoid, "FF") // fa airspaces use this prefix

		a := Aircraft{
			Dist:                pos.DistKM(tp.Latlong),
			Dist3:               pos.Dist3(tp.Latlong, altitudeDelta),
			BearingFromObserver: tp.Latlong.BearingTowards(pos),
			//Id: "someid", // This is set via an IdSpec string below
			Id2:      icaoid,
			Lat:      tp.Lat,
			Long:     tp.Long,
			Track:    tp.Heading,
			Altitude: tp.Altitude,
			Speed:    tp.GroundSpeed,
			// Squawk string
			Radar:        tp.ReceiverName,
			EquipType:    ad.Airframe.EquipmentType,
			Registration: ad.Airframe.Registration,
			Epoch:        float64(tp.TimestampUTC.Unix()),
			Origin:       ad.Schedule.Origin,
			Destination:  ad.Schedule.Destination,
			FlightNumber: ad.Schedule.IataFlight(),
			// Unknown float64
			VerticalSpeed: tp.VerticalRate,
			Callsign:      ad.Msg.Callsign, //"CAL123", //snap.Flight.Callsign,
			// Unknown2 float64
		}

		// Even though we may be parsing an fr24 airspace, generate a skypi idspec (which may break)
		if icaoid != "" {
			a.Id = fdb.IdSpec{IcaoId: icaoid, Time: tp.TimestampUTC}.String()
		}

		// Hack for Surf Air; promote their callsigns into flightnumbers.
		// The goal is to allow them to get past the filter, and be printable etc.
		// There is probably a much better place for this kind of munging. But it needs to happen
		//  regardless of the source of the airspace, so it can't be pushed upstream. (...?)
		if a.FlightNumber == "" && regexp.MustCompile("^URF\\d+$").MatchString(a.Callsign) {
			a.FlightNumber = a.Callsign
		}

		ret = append(ret, a)
	}

	sort.Sort(AircraftByDist3(ret))

	return ret
}
Esempio n. 3
0
func (fr *Fr24) FindOverhead(observerPos geo.Latlong, overhead *Aircraft, grabAnything bool) (debug string, err error) {

	debug = fmt.Sprintf("*** FindOverhead for %s, at %s\n", observerPos,
		date.NowInPdt())

	// Create a bounding box that's ~40m square, centred on the input lat,long
	// This is a grievous fudge http://www.movable-type.co.uk/scripts/latlong.html
	lat_20miles := 0.3
	long_20miles := 0.35
	nearby := []Aircraft{}
	if err = fr.ListBbox(observerPos.Lat-lat_20miles, observerPos.Long-long_20miles,
		observerPos.Lat+lat_20miles, observerPos.Long+long_20miles, &nearby); err != nil {
		debug += fmt.Sprintf("Lookup error: %s\n", err)
		return
	}

	for i, a := range nearby {
		aircraftPos := geo.Latlong{a.Lat, a.Long}
		nearby[i].Dist = observerPos.Dist(aircraftPos)
		nearby[i].Dist3 = observerPos.Dist3(aircraftPos, a.Altitude)
		nearby[i].BearingFromObserver = observerPos.BearingTowards(aircraftPos)
	}
	sort.Sort(byDist3(nearby))
	debug += "** nearby list:-\n" + DebugFlightList(nearby)

	filtered := filterAircraft(nearby)
	if len(filtered) == 0 {
		debug += "** all empty after filtering\n"
		return
	}

	debug += "** filtered:-\n" + DebugFlightList(filtered)

	if grabAnything {
		*overhead = filtered[0]
		debug += "** grabbed 1st\n"
	} else {
		// closest plane has to be within 12 km to be 'overhead', and it has
		// to be 4km away from the next-closest
		if filtered[0].Dist3 < 12.0 {
			if (len(filtered) == 1) || (filtered[1].Dist3-filtered[0].Dist3) > 4.0 {
				*overhead = filtered[0]
				debug += "** selected 1st\n"
			} else {
				debug += "** 2nd was too close to 1st\n"
			}
		} else {
			debug += "** 1st was too far away\n"
		}
	}

	return
}
Esempio n. 4
0
func (fr *Fr24) FindAllOverhead(observerPos geo.Latlong, overhead *flightid.Aircraft, grabAnything bool) (outAll []*Aircraft, outFilt []*Aircraft, debug string, err error) {
	outAll = []*Aircraft{}
	outFilt = []*Aircraft{}

	debug = fmt.Sprintf("*** FindOverhead for %s, at %s\n", observerPos, date.NowInPdt())
	debug += fmt.Sprintf("* url: http://%s%s?array=1&bounds=%s\n", fr.host, kListUrlPath, "...")

	// Create a bounding box that's ~40m square, centred on the input lat,long
	// This is a grievous fudge http://www.movable-type.co.uk/scripts/latlong.html
	lat_20miles := 0.3
	long_20miles := 0.35
	nearby := []Aircraft{}
	if err = fr.ListBbox(observerPos.Lat-lat_20miles, observerPos.Long-long_20miles,
		observerPos.Lat+lat_20miles, observerPos.Long+long_20miles, &nearby); err != nil {
		debug += fmt.Sprintf("Lookup error: %s\n", err)
		return
	}

	for i, a := range nearby {
		// Hack for Surf Air; promote callsigns into (invalid_ flightnumbers, so they don't get stripped
		if a.FlightNumber == "" && regexp.MustCompile("^URF\\d+$").MatchString(a.Callsign) {
			nearby[i].FlightNumber = a.Callsign
		} else if a.FlightNumber != "" {
			if _, _, err := fdb.ParseIata(a.FlightNumber); err != nil {
				debug += "** saw bad flightnumber '" + a.FlightNumber + "' from fr24\n"
				nearby[i].FlightNumber = ""
			}
		}

		aircraftPos := geo.Latlong{a.Lat, a.Long}
		nearby[i].Dist = observerPos.Dist(aircraftPos)
		nearby[i].Dist3 = observerPos.Dist3(aircraftPos, a.Altitude)
		nearby[i].BearingFromObserver = observerPos.BearingTowards(aircraftPos)
	}
	sort.Sort(byDist3(nearby))
	debug += "** nearby list:-\n" + DebugFlightList(nearby)

	filtered := filterAircraft(nearby)
	if len(filtered) == 0 {
		debug += "** all empty after filtering\n"
		return
	}

	for i, _ := range nearby {
		outAll = append(outAll, &nearby[i])
	}
	for i, _ := range filtered {
		outFilt = append(outFilt, &filtered[i])
	}

	debug += "** filtered:-\n" + DebugFlightList(filtered)

	if grabAnything {
		filtered[0].IntoFlightIdAircraft(overhead)
		debug += "** grabbed 1st\n"
	} else {
		// closest plane has to be within 12 km to be 'overhead', and it has
		// to be 4km away from the next-closest
		if filtered[0].Dist3 < 12.0 {
			if (len(filtered) == 1) || (filtered[1].Dist3-filtered[0].Dist3) > 4.0 {
				filtered[0].IntoFlightIdAircraft(overhead)
				debug += "** selected 1st\n"
			} else {
				debug += "** 2nd was too close to 1st\n"
			}
		} else {
			debug += "** 1st was too far away\n"
		}
	}

	return
}