Пример #1
0
func (db FlightDB) LookupTimeRangeByTags(tags []string, start, end time.Time) ([]f.Flight, error) {
	memKey := ""
	todayStart, _ := date.WindowForToday()
	if end.Before(todayStart) || end.Equal(todayStart) {
		sort.Sort(f.StringsDesc(tags))
		tagstr := strings.Join(tags, ",")
		memKey = fmt.Sprintf("fdb-tag-lookup:%s:%d-%d", tagstr, start.Unix(), end.Unix())
		//db.C.Infof(" ##== fdb-tag-lookup cacheable [%s]", memKey)
	}

	q := db.QueryTimeRangeByTags(tags, start, end)

	return db.lookupByQuery(q, memKey)
}
Пример #2
0
func (cdb ComplaintDB) GetComplaintsInSpanByEmailAddress(ea string, start, end time.Time) ([]types.Complaint, error) {

	//cdb.Infof(" ##== comp-in-span [%s  -->  %s]", start, end)
	memKey := ""
	todayStart, _ := date.WindowForToday()
	if end.Before(todayStart) || end.Equal(todayStart) {
		memKey = fmt.Sprintf("comp-in-span:%s:%d-%d", ea, start.Unix(), end.Unix())
		//cdb.Infof(" ##== comp-in-span cacheable [%s]", memKey)
	}

	q := cdb.QueryInSpanByEmailAddress(start, end, ea)

	return cdb.getComplaintsByQuery(q, memKey)
}
Пример #3
0
func complaintsForHandler(w http.ResponseWriter, r *http.Request) {
	ctx := req2ctx(r)

	s, e := widget.FormValueEpochTime(r, "start"), widget.FormValueEpochTime(r, "end")
	if r.FormValue("start") == "" {
		s, e = date.WindowForToday()
	}
	flightnumber := r.FormValue("flight")
	if e.Sub(s) > (time.Hour * 24) {
		http.Error(w, "time span too wide", http.StatusInternalServerError)
		return
	} else if s.Year() < 2015 {
		http.Error(w, "times in the past", http.StatusInternalServerError)
		return
	} else if flightnumber == "" {
		http.Error(w, "no flightnumber", http.StatusInternalServerError)
		return
	}

	cdb := complaintdb.NewDB(ctx)

	times, err := cdb.GetComplaintTimesInSpanByFlight(s, e, flightnumber)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if r.FormValue("debug") != "" {
		str := fmt.Sprintf("* %s\n* %s\n* %s\n* [%d]\n\n", s, e, flightnumber, len(times))
		for i, t := range times {
			str += fmt.Sprintf("%3d  %s\n", i, date.InPdt(t))
		}
		w.Header().Set("Content-Type", "text/plain")
		w.Write([]byte(str))
		return
	}

	w.Header().Set("Content-Type", "application/json")
	jsonBytes, err := json.Marshal(times)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Write(jsonBytes)
}
Пример #4
0
// Now the DB is clean, we can do this simple query instead of going user by user
func (cdb ComplaintDB) GetComplaintsInSpanNew(start, end time.Time) ([]types.Complaint, error) {
	cdb.C.Infof(" ##== comp-in-span [%s  -->  %s]", start, end)
	memKey := ""
	todayStart, _ := date.WindowForToday()
	if end.Before(todayStart) || end.Equal(todayStart) {
		memKey = fmt.Sprintf("comp-in-span:__all__:%d-%d", start.Unix(), end.Unix())
		//cdb.C.Infof(" ##== comp-in-span cacheable [%s]", memKey)
	}

	q := datastore.
		NewQuery(kComplaintKind).
		Filter("Timestamp >= ", start).
		Filter("Timestamp < ", end).
		Order("Timestamp").
		Limit(-1)

	return cdb.getComplaintsByQuery(q, memKey)
}
Пример #5
0
func (cdb ComplaintDB) GetComplaintsInSpanByEmailAddress(ea string, start, end time.Time) ([]types.Complaint, error) {

	//cdb.C.Infof(" ##== comp-in-span [%s  -->  %s]", start, end)
	memKey := ""
	todayStart, _ := date.WindowForToday()
	if end.Before(todayStart) || end.Equal(todayStart) {
		memKey = fmt.Sprintf("comp-in-span:%s:%d-%d", ea, start.Unix(), end.Unix())
		//cdb.C.Infof(" ##== comp-in-span cacheable [%s]", memKey)
	}

	q := datastore.
		NewQuery(kComplaintKind).
		Ancestor(cdb.emailToRootKey(ea)).
		Filter("Timestamp >= ", start).
		Filter("Timestamp < ", end).
		Order("Timestamp")

	return cdb.getComplaintsByQuery(q, memKey)
}
Пример #6
0
func (cdb ComplaintDB) GetAllByEmailAddress(ea string, everything bool) (*types.ComplaintsAndProfile, error) {
	var cap types.ComplaintsAndProfile

	cdb.Debugf("GABEA_001", "cdb.GetAllByEmailAddress starting (everything=%v)", everything)

	if cp, err := cdb.GetProfileByEmailAddress(ea); err == datastore.ErrNoSuchEntity {
		return nil, nil // No such profile exists
	} else if err != nil {
		return nil, err // A real problem occurred
	} else {
		cdb.Debugf("GABEA_002", "profile retrieved")
		cap.Profile = *cp
	}

	if everything {
		if c, err := cdb.GetComplaintsByEmailAddress(ea); err != nil {
			return nil, err
		} else {
			cdb.Debugf("GABEA_003", "EVERYTHING retrieved")
			cap.Complaints = c
		}

	} else {
		// Just today
		s, e := date.WindowForToday()
		if c, err := cdb.GetComplaintsInSpanByEmailAddress(ea, s, e); err != nil {
			return nil, err
		} else {
			cdb.Debugf("GABEA_004", "WindowForToday retrieved; now getting counts")
			cap.Complaints = c
		}
	}

	if counts, err := cdb.getDailyCountsByEmailAdress(ea); err != nil {
		return nil, err
	} else {
		cdb.Debugf("GABEA_005", "counts retrieved")
		cap.Counts = counts
	}

	return &cap, nil
}
Пример #7
0
// This widget assumes the values 'date', 'range_from', and 'range_to'
func FormValueDateRange(r *http.Request) (s, e time.Time, err error) {
	err = nil

	switch r.FormValue("date") {
	case "today":
		s, _ = date.WindowForToday()
		e = s
	case "yesterday":
		s, _ = date.WindowForYesterday()
		e = s
	case "range":
		s = date.ArbitraryDatestring2MidnightPdt(r.FormValue("range_from"), "2006/01/02")
		e = date.ArbitraryDatestring2MidnightPdt(r.FormValue("range_to"), "2006/01/02")
		if s.After(e) {
			s, e = e, s
		}
	}

	e = e.Add(23*time.Hour + 59*time.Minute + 59*time.Second) // make sure e covers its whole day

	return
}
Пример #8
0
// We examine the tags CGI arg, which should be a pipe-delimited set of flight tags.
func flightListHandler(w http.ResponseWriter, r *http.Request) {
	ctx := req2ctx(r)
	db := fdb.NewDB(r)

	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, 400)
	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 {
		log.Errorf(ctx, " %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)
	}
}
Пример #9
0
func (cdb ComplaintDB) GetAllByEmailAddress(ea string, everything bool) (*types.ComplaintsAndProfile, error) {
	var cap types.ComplaintsAndProfile

	if cp, err := cdb.GetProfileByEmailAddress(ea); err == datastore.ErrNoSuchEntity {
		return nil, nil // No such profile exists
	} else if err != nil {
		return nil, err // A real problem occurred
	} else {
		cap.Profile = *cp
	}

	if everything {
		if c, err := cdb.GetComplaintsByEmailAddress(ea); err != nil {
			return nil, err
		} else {
			cap.Complaints = c
		}

	} else {
		// Just today
		s, e := date.WindowForToday()
		if c, err := cdb.GetComplaintsInSpanByEmailAddress(ea, s, e); err != nil {
			return nil, err
		} else {
			cap.Complaints = c
		}
	}

	if counts, err := cdb.getDailyCountsByEmailAdress(ea); err != nil {
		return nil, err
	} else {
		cap.Counts = counts
	}

	return &cap, nil
}
Пример #10
0
func (cdb ComplaintDB) complainByProfile(cp types.ComplainerProfile, c *types.Complaint) error {
	client := cdb.HTTPClient()
	overhead := flightid.Aircraft{}

	// Check we're not over a daily cap for this user
	cdb.Debugf("cbe_010", "doing rate limit check")
	s, e := date.WindowForToday()
	if prevKeys, err := cdb.GetComplaintKeysInSpanByEmailAddress(s, e, cp.EmailAddress); err != nil {
		return err
	} else if len(prevKeys) >= KMaxComplaintsPerDay {
		return fmt.Errorf("Too many complaints filed today")
	} else {
		cdb.Debugf("cbe_011", "rate limit check passed (%d); calling FindOverhead", len(prevKeys))
	}

	elev := 0.0
	pos := geo.Latlong{cp.Lat, cp.Long}
	algo := flightid.AlgoConservativeNoCongestion
	if c.Description == "ANYANY" {
		algo = flightid.AlgoGrabClosest
	}

	if as, err := fr24.FetchAirspace(client, pos.Box(64, 64)); err != nil {
		cdb.Errorf("FindOverhead failed for %s: %v", cp.EmailAddress, err)
	} else {
		oh, deb := flightid.IdentifyOverhead(as, pos, elev, algo)
		c.Debug = deb
		if oh != nil {
			overhead = *oh
			c.AircraftOverhead = overhead
		}
	}

	cdb.Debugf("cbe_020", "FindOverhead returned")

	// Contrast with the skypi pathway
	if cp.CallerCode == "WOR004" || cp.CallerCode == "WOR005" {
		asFdb, _ := airspace.Fetch(client, "", pos.Box(60, 60))
		oh3, deb3 := flightid.IdentifyOverhead(asFdb, pos, elev, algo)
		if oh3 == nil {
			oh3 = &flightid.Aircraft{}
		}
		newdebug := c.Debug + "\n*** v2 / fdb testing\n" + deb3 + "\n"
		headline := ""

		if overhead.FlightNumber != oh3.FlightNumber {
			headline = fmt.Sprintf("** * * DIFFERS * * **\n")
		} else {
			// Agree ! Copy over the Fdb IdSpec, and pretend we're living in the future
			headline = fmt.Sprintf("**---- Agrees ! ----**\n")
			c.AircraftOverhead.Id = oh3.Id
		}
		headline += fmt.Sprintf(" * skypi: %s\n * orig : %s\n", oh3, overhead)

		c.Debug = headline + newdebug
	}

	c.Version = kComplaintVersion // Kill this off ?

	c.Profile = cp // Copy the profile fields into every complaint

	// Too much like the last complaint by this user ? Just update that one.
	cdb.Debugf("cbe_030", "retrieving prev complaint")
	if prev, err := cdb.GetNewestComplaintByEmailAddress(cp.EmailAddress); err != nil {
		cdb.Errorf("complainByProfile/GetNewest: %v", err)
	} else if prev != nil && ComplaintsAreEquivalent(*prev, *c) {
		cdb.Debugf("cbe_031", "returned, equiv; about to UpdateComlaint()")
		// The two complaints are in fact one complaint. Overwrite the old one with data from new one.
		Overwrite(prev, c)
		err := cdb.UpdateComplaint(*prev, cp.EmailAddress)
		cdb.Debugf("cbe_032", "updated in place (all done)")
		return err
	}
	cdb.Debugf("cbe_033", "returned, distinct/first; about to put()")

	key := datastore.NewIncompleteKey(cdb.Ctx(), kComplaintKind, cdb.emailToRootKey(cp.EmailAddress))
	_, err := datastore.Put(cdb.Ctx(), key, c)
	cdb.Debugf("cbe_034", "new entity added (all done)")

	// TEMP
	/*
		if debug,err := bksv.PostComplaint(client, cp, *c); err != nil {
			cdb.Infof("BKSV Debug\n------\n%s\n------\n", debug)
			cdb.Infof("BKSV posting error: %v", err)
		} else {
			cdb.Infof("BKSV Debug\n------\n%s\n------\n", debug)
		}
	*/
	return err
}
Пример #11
0
func YesterdayDebugHandler(w http.ResponseWriter, r *http.Request) {
	ctx := req2ctx(r)
	cdb := NewDB(ctx)

	offset := 1
	start, end := date.WindowForToday()
	if r.FormValue("offset") != "" {
		offset = int(widget.FormValueInt64(r, "offset"))
	}
	start, end = start.AddDate(0, 0, -1*offset), end.AddDate(0, 0, -1*offset)

	keys, err := cdb.GetComplaintKeysInSpan(start, end)
	// complaints,err := cdb.GetComplaintsInSpanNew(start,end)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	counts := map[string]int{}
	problems := []types.Complaint{}
	good := []types.Complaint{}
	retries := []types.Complaint{}

	//for _,c := range complaints {
	for _, k := range keys {
		c, err := cdb.GetAnyComplaintByKey(k.Encode())
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		counts[fmt.Sprintf("[A] Status: %s", c.Submission.Outcome)]++
		if r.FormValue("all") != "" || c.Submission.Outcome == types.SubmissionFailed {
			problems = append(problems, *c)
		}
		if len(good) < 5 && c.Submission.Outcome == types.SubmissionAccepted {
			good = append(good, *c)
		}
		if c.Submission.Outcome == types.SubmissionAccepted {
			counts[fmt.Sprintf("[B] AttemptsToSucceed: %02d", c.Submission.Attempts)]++
			counts[fmt.Sprintf("[C] SecondsForSuccess: %02d", int(c.D.Seconds()))]++

			if c.Submission.Attempts > 1 {
				retries = append(retries, *c)
			}
		}
	}

	str := "<html><body>\n"
	str += fmt.Sprintf("<pre>Start: %s\nEnd  : %s\n</pre>\n", start, end)
	str += "<table border=0>\n"

	countkeys := []string{}
	for k, _ := range counts {
		countkeys = append(countkeys, k)
	}
	sort.Strings(countkeys)
	for _, k := range countkeys {
		str += fmt.Sprintf("<tr><td><b>%s</b></td><td>%d</td></tr>\n", k, counts[k])
	}
	str += "</table>\n"

	url := "https://stop.jetnoise.net/cdb/comp/debug"

	str += "<p>\n"
	for _, c := range good {
		str += fmt.Sprintf(" <a href=\"%s?key=%s\" target=\"_blank\">Good</a>: %s", url, c.DatastoreKey, c)
		str += "<br/>\n"
	}
	str += "</p>\n"

	str += "<p>\n"
	for _, c := range problems {
		str += fmt.Sprintf(" <a href=\"%s?key=%s\" target=\"_blank\">Prob</a>: %s", url, c.DatastoreKey, c)
		str += "<br/>\n"
	}
	str += "</p>\n"

	str += "<p>\n"
	for _, c := range retries {
		str += fmt.Sprintf(" <a href=\"%s?key=%s\" target=\"_blank\">Retry</a>: %s", url, c.DatastoreKey, c)
		str += "<br/>\n"
	}
	str += "</p>\n"

	str += "</body></html>\n"
	w.Header().Set("Content-Type", "text/html")
	w.Write([]byte(str))

}