func brixxViolationReport(c appengine.Context, s, e time.Time, opt ReportOptions) ([]ReportRow, ReportMetadata, error) { meta := ReportMetadata{} fdb := fdb.FlightDB{C: c} maybeMemcache(&fdb, e) tags := []string{flightdb.KTagBRIXX} if flights, err := fdb.LookupTimeRangeByTags(tags, s, e); err != nil { return nil, nil, err } else { out := []ReportRow{} // Hmm. Really need a better way to link 'violations in this report' to dots on the map for _, f := range flights { t := f.BestTrack() for i, tp := range t { if tp.Latlong.DistNM(sfo.KLatlongSJC) > 20 { continue } if tp.AltitudeFeet < 5500 && tp.Latlong.Long < sfo.KFixes["YADUT"].Long { row := BrixxRow{ Url: flight2Url(f), F: f, Source: t.LongSource(), TP: &t[i], } out = append(out, row) break } } } return out, meta, nil } }
func skimmerReport(c appengine.Context, s, e time.Time, opt ReportOptions) ([]ReportRow, ReportMetadata, error) { meta := ReportMetadata{} fdb := fdb.FlightDB{C: c} maybeMemcache(&fdb, e) tags := []string{flightdb.KTagSERFR1} if flights, err := fdb.LookupTimeRangeByTags(tags, s, e); err != nil { return nil, nil, err } else { out := []ReportRow{} for _, f := range flights { t := f.BestTrack() _, analysis := t.SkimsToSFO(opt.Skimmer_AltitudeTolerance, opt.Skimmer_MinDurationNM, 14.5, 50) // Output one row per event, in a kind of hacky way extras := fmt.Sprintf("&skim=1&alttol=%.0f&mindist=%.0f", opt.Skimmer_AltitudeTolerance, opt.Skimmer_MinDurationNM) for _, event := range analysis.Events { row := SkimRow{Url: flight2Url(f) + template.HTML(extras), F: f, Source: t.LongSource(), A: analysis} row.A.Events = []flightdb.SkimEvent{event} out = append(out, row) } } return out, meta, nil } }
func brixx1Report(c appengine.Context, s, e time.Time, opt ReportOptions) ([]ReportRow, ReportMetadata, error) { meta := ReportMetadata{} fdb := fdb.FlightDB{C: c} maybeMemcache(&fdb, e) tags := []string{flightdb.KTagBRIXX} if flights, err := fdb.LookupTimeRangeByTags(tags, s, e); err != nil { return nil, nil, err } else { out := []ReportRow{} meta["[A] Total BRIXX flights "] = float64(len(flights)) for _, f := range flights { hasAdsb := false if _, exists := f.Tracks["ADSB"]; exists == true { meta["[B] With data from "+f.Tracks["ADSB"].LongSource()]++ } if t, exists := f.Tracks["FA"]; exists == true { meta["[B] With data from "+f.Tracks["FA"].LongSource()]++ hasAdsb = t.IsFromADSB() } else { meta["[B] With data from "+f.Track.LongSource()]++ } row := SERFR1Row{flight2Url(f), f, hasAdsb, false} out = append(out, row) } return out, meta, nil } }
// We examine the tags CGI arg, which should be a pipe-delimited set of flight tags. func flightListHandler(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) db := fdb.FlightDB{C: c} tags := []string{} if r.FormValue("tags") != "" { tags = append(tags, strings.Split(r.FormValue("tags"), "|")...) } timeRange := regexp.MustCompile("/fdb/(.+)$").ReplaceAllString(r.URL.Path, "$1") var flights []ftype.Flight var err error switch timeRange { case "recent": flights, err = db.LookupRecentByTags(tags, 200) case "today": s, e := date.WindowForToday() flights, err = db.LookupTimeRangeByTags(tags, s, e) case "yesterday": s, e := date.WindowForYesterday() flights, err = db.LookupTimeRangeByTags(tags, s, e) } if err != nil { c.Errorf(" %s: %v", r.URL.Path, err) http.Error(w, err.Error(), http.StatusInternalServerError) return } var params = map[string]interface{}{ "Tags": tags, "TimeRange": timeRange, "Flights": flights2params(flights), } if err := templates.ExecuteTemplate(w, "fdb-recentlist", params); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } }
func adsbClassbReport(c appengine.Context, s, e time.Time, opt ReportOptions) ([]ReportRow, ReportMetadata, error) { fdb := fdb.FlightDB{C: c} maybeMemcache(&fdb, e) tags := []string{flightdb.KTagSERFR1} if flights, err := fdb.LookupTimeRangeByTags(tags, s, e); err != nil { return nil, nil, err } else { meta := ReportMetadata{} rows := []ReportRow{} for _, f := range flights { row := ACBRow{F: f, Url: flight2Url(f)} _, cbt := f.SFOClassB("FA", nil) worst := cbt.FindWorstPoint() row.FAViolation = (worst != nil) if worst != nil { row.FAAnalysis = worst.A } if f.HasTrack("ADSB") { row.HadLocalTrack = true _, cbt := f.SFOClassB("ADSB", nil) worst := cbt.FindWorstPoint() row.LocalViolation = (worst != nil) if worst != nil { row.LocalAnalysis = worst.A } } if row.LocalViolation && !row.FAViolation { row.FoundBonusViolation = true } if row.LocalViolation && row.FAViolation { hFA := row.FAAnalysis.BelowBy hLocal := row.LocalAnalysis.BelowBy row.IncreasedViolationBy = hLocal - hFA } if row.LocalViolation || row.FAViolation { rows = append(rows, row) } } return rows, meta, nil } }
func discrepReport(c appengine.Context, s, e time.Time, opt ReportOptions) ([]ReportRow, ReportMetadata, error) { meta := ReportMetadata{} fdb := fdb.FlightDB{C: c} maybeMemcache(&fdb, e) tags := []string{flightdb.KTagSERFR1} if flights, err := fdb.LookupTimeRangeByTags(tags, s, e); err != nil { return nil, nil, err } else { out := []ReportRow{} for _, f := range flights { // If only one source has ADS-B, flag it interest := false if f.HasTrack("ADSB") && !f.HasTrack("FA:TA") { interest = true meta["Missing from FlightAware ADS-B"] += 1 } if !f.HasTrack("ADSB") && f.HasTrack("FA:TA") { interest = true meta["Missing from local ADS-B"] += 1 } // If both have ADS-B, look for missed violations if f.HasTrack("ADSB") && f.HasTrack("FA:TA") { if f.HasTag("ClassB:ADSB") && !f.HasTag("ClassB:FA") { interest = true meta["Bonus violations"] += 1 } if !f.HasTag("ClassB:ADSB") && f.HasTag("ClassB:FA") { interest = true meta["Missed violations"] += 1 } } if !interest { continue } row := SERFR1Row{flight2Url(f), f, false, false} out = append(out, row) } return out, meta, nil } }