func serfr1AtReport(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} pos := sfo.KFixes[opt.Waypoint] out := []ReportRow{} iter := fdb.NewIter(fdb.QueryTimeRangeByTags(tags, s, e)) nSerfr1 := 0 for { f, err := iter.NextWithErr() if err != nil { fdb.C.Errorf("serfr1AtReport iterator failed: %v", err) return nil, nil, err } else if f == nil { break // We've hit EOF } nSerfr1++ if _, exists := f.Tracks["ADSB"]; exists == true { meta["[B] with data from "+f.Tracks["ADSB"].LongSource()]++ } if _, exists := f.Tracks["FA"]; exists == true { meta["[B] with data from "+f.Tracks["FA"].LongSource()]++ } else { meta["[B] with data from "+f.Track.LongSource()]++ } if itp, err := f.BestTrack().PointOfClosestApproach(pos); err != nil { c.Infof("Skipping flight %s: err=%v", f, err) } else { url := template.HTML(fmt.Sprintf("%s&waypoint=%s", flight2Url(*f), opt.Waypoint)) f.Tracks = nil // avoid running out of F1 RAM! row := SERFR1AtRow{url, *f, itp} out = append(out, row) } } meta["[A] Total SERFR1 flights "] = float64(nSerfr1) return out, meta, nil }