Documentation ¶
Index ¶
- Constants
- Variables
- func ApproximatePosition(in geo.Latlong) geo.Latlong
- func ComplaintDebugHandler(w http.ResponseWriter, r *http.Request)
- func ComplaintsShouldBeMerged(this, next Complaint) bool
- func FixupComplaint(c *Complaint, keyStr string)
- func Overwrite(this, from *Complaint)
- func SetContextProperties(ctx context.Context, props ContextProperties) context.Context
- func SubmissionsDebugHandler(w http.ResponseWriter, r *http.Request)
- func SubmissionsDebugHandler2(w http.ResponseWriter, r *http.Request)
- type AnonymizedComplaint
- type Browser
- type CQuery
- func (cq *CQuery) Ancestor(rootkey ds.Keyer) *CQuery
- func (cq *CQuery) ByButton(id string) *CQuery
- func (cq *CQuery) ByCallerCode(cc string) *CQuery
- func (cq *CQuery) ByFlight(flightnumber string) *CQuery
- func (cq *CQuery) ByIcaoId(icaoid string) *CQuery
- func (cq *CQuery) BySubmissionOutcome(outcome int) *CQuery
- func (cq *CQuery) ByTimespan(start, end time.Time) *CQuery
- func (cq *CQuery) ByZip(zip string) *CQuery
- func (cq *CQuery) Distinct() *CQuery
- func (cq *CQuery) Filter(str string, val interface{}) *CQuery
- func (cq *CQuery) KeysOnly() *CQuery
- func (cq *CQuery) Limit(val int) *CQuery
- func (cq *CQuery) Order(str string) *CQuery
- func (cq *CQuery) OrderTimeAsc() *CQuery
- func (cq *CQuery) OrderTimeDesc() *CQuery
- func (cq *CQuery) Project(fields ...string) *CQuery
- func (cq *CQuery) String() string
- type ComplainerProfile
- func (p *ComplainerProfile) Base64Decode(str string) error
- func (p ComplainerProfile) Base64Encode() (string, error)
- func (p ComplainerProfile) DataSharingOK() bool
- func (p ComplainerProfile) ElevationFeet() float64
- func (p *ComplainerProfile) FetchStructuredAddress() (PostalAddress, error)
- func (p *ComplainerProfile) GetStructuredAddress() PostalAddress
- func (p ComplainerProfile) SendDailyEmailOK() bool
- func (p ComplainerProfile) SplitName() (first, last string)
- func (p ComplainerProfile) ThirdPartyCommsOK() bool
- func (p *ComplainerProfile) UpdateStructuredAddress() error
- type Complaint
- type ComplaintDB
- func (cdb ComplaintDB) AddComplaintSliceToCSV(complaints []Complaint, w io.Writer) error
- func (cdb ComplaintDB) AddDailyCount(dc DailyCount) error
- func (cdb ComplaintDB) AddHeadersToCSV(w io.Writer)
- func (cdb ComplaintDB) AddHistoricalComplaintByEmailAddress(ea string, c *Complaint) error
- func (cdb ComplaintDB) CPQByEmail(email string) *CQuery
- func (cdb ComplaintDB) CQByEmail(email string) *CQuery
- func (cdb ComplaintDB) CSVHeaders() []string
- func (cdb ComplaintDB) ComplainByButtonId(id string, c *Complaint) error
- func (cdb ComplaintDB) ComplainByCallerCode(cc string, c *Complaint) error
- func (cdb ComplaintDB) ComplainByEmailAddress(ea string, c *Complaint) error
- func (cdb ComplaintDB) ComplaintKeyOwnedBy(keyer ds.Keyer, owner string) (bool, error)
- func (cdb ComplaintDB) ComplaintKeyStrOwnedBy(keyStr, owner string) (bool, error)
- func (cdb ComplaintDB) ComplaintToCSVFunc() func(c *Complaint) []string
- func (cdb ComplaintDB) CountComplaintsAndUniqueUsersIn(s, e time.Time) (int, int, error)
- func (cdb ComplaintDB) Ctx() context.Context
- func (cdb ComplaintDB) Debugf(step string, fmtstr string, varargs ...interface{})
- func (cdb ComplaintDB) DeletAllGlobalStats() error
- func (cdb ComplaintDB) DeleteAllKeys(keyers []ds.Keyer) error
- func (cdb ComplaintDB) DeleteByKey(keyer ds.Keyer) error
- func (cdb ComplaintDB) Errorf(fmtstr string, varargs ...interface{})
- func (cdb ComplaintDB) FormattedWriteCQueryToCSV(cq *CQuery, w io.Writer, headers []string, f func(*Complaint) []string) (int, error)
- func (cdb ComplaintDB) GetAllByEmailAddress(ea string, everything bool) (*ComplaintsAndProfile, error)
- func (cdb ComplaintDB) GetComplaintPositionsInSpanByIcao(start, end time.Time, uniqueUsers bool, icaoid string) ([]geo.Latlong, error)
- func (cdb *ComplaintDB) GetDailyCounts(email string) ([]DailyCount, error)
- func (cdb ComplaintDB) GetKeyerOrNil(c Complaint) ds.Keyer
- func (cdb ComplaintDB) GetProfileLocations() ([]geo.Latlong, error)
- func (cdb ComplaintDB) GetUniqueUsersAndCountsIn(s, e time.Time) ([]string, int, error)
- func (cdb ComplaintDB) HTTPClient() *http.Client
- func (cdb ComplaintDB) Infof(fmtstr string, varargs ...interface{})
- func (cdb ComplaintDB) LoadGlobalStats() (*GlobalStats, error)
- func (cdb ComplaintDB) LookupAll(cq *CQuery) ([]Complaint, error)
- func (cdb ComplaintDB) LookupAllKeys(cq *CQuery) ([]ds.Keyer, error)
- func (cdb ComplaintDB) LookupAllProfiles(cq *CQuery) ([]ComplainerProfile, error)
- func (cdb ComplaintDB) LookupFirst(cq *CQuery) (*Complaint, error)
- func (cdb ComplaintDB) LookupKey(keyerStr string, owner string) (*Complaint, error)
- func (cdb ComplaintDB) LookupProfile(email string) (*ComplainerProfile, error)
- func (cdb ComplaintDB) MarshalComplaintSlice(complaints []Complaint, w io.Writer) error
- func (cdb ComplaintDB) MustLookupProfile(email string) (*ComplainerProfile, error)
- func (cdb *ComplaintDB) NewComplaintIterator(cq *CQuery) *ComplaintIterator
- func (cdb *ComplaintDB) NewComplaintQuery() *CQuery
- func (cdb *ComplaintDB) NewProfileQuery() *CQuery
- func (cdb *ComplaintDB) NewQuery(kind string) *CQuery
- func (cdb ComplaintDB) PersistComplaint(c Complaint) error
- func (cdb ComplaintDB) PersistComplaints(complaints []Complaint) error
- func (cdb ComplaintDB) PersistProfile(p ComplainerProfile) error
- func (cdb ComplaintDB) RawLookupAll(cq *CQuery) ([]Complaint, error)
- func (cdb ComplaintDB) ResetGlobalStats()
- func (cdb ComplaintDB) SaveGlobalStats(gs GlobalStats) error
- func (cdb *ComplaintDB) SummaryReport(start, end time.Time, countByUser bool, zipFilter map[string]int) (string, error)
- func (cdb ComplaintDB) UnmarshalComplaintSlice(r io.Reader) ([]Complaint, error)
- func (cdb ComplaintDB) UpdateComplaint(c Complaint, owner string) error
- func (cdb ComplaintDB) WriteCQueryToCSV(cq *CQuery, w io.Writer, headers bool) (int, error)
- type ComplaintIterator
- type ComplaintsAndProfile
- type ComplaintsByTimeDesc
- type ContextProperties
- type CountItem
- type DailyCount
- type DailyCountDesc
- type FrozenGlobalStats
- type GlobalStats
- type PostalAddress
- type Submission
- type SubmissionOutcome
- type SubmissionRejectReason
Constants ¶
const ( SubmissionNoReject = iota SubmissionRejectConstraint SubmissionRejectDupeReceipt SubmissionRejectBadField SubmissionRejectBadApiKey SubmissionRejectOther )
Variables ¶
var (
KMaxComplaintsPerDay = 200
)
Functions ¶
func ApproximatePosition ¶
Rounds off a latlong to nearest KM - something that doesn't reveal addresses
func ComplaintDebugHandler ¶
func ComplaintDebugHandler(w http.ResponseWriter, r *http.Request)
/cdb/comp/debug?key=asdadasdasdasdasdasdsadasdsadasdasdasdasdasdas
func ComplaintsShouldBeMerged ¶
ComplaintsShouldBeMerged decides whether two complaint objects relate to the same underlying action by a user. Sometimes a user will mash the button; some users try to automate sending as many complaints as they can.
func FixupComplaint ¶
func Overwrite ¶
func Overwrite(this, from *Complaint)
Overwrite user-entered data (and timestamp) into the base complaint.
func SetContextProperties ¶
func SetContextProperties(ctx context.Context, props ContextProperties) context.Context
func SubmissionsDebugHandler ¶
func SubmissionsDebugHandler(w http.ResponseWriter, r *http.Request)
This handler runs in the backend app View a day's worth of complaint submissions; defaults to yesterday
?all=1 (will list every single complaint - DO NOT USE) ?offset=N (how many days to go back from today; 1 == yesterday) ?datestring=2018.01.20 (this day in particular)
func SubmissionsDebugHandler2 ¶
func SubmissionsDebugHandler2(w http.ResponseWriter, r *http.Request)
View submission errors over a date range.
?date=range&range_from=2016/01/21&range_to=2016/01/26 [?csv=1]
Types ¶
type AnonymizedComplaint ¶
type AnonymizedComplaint struct { Timestamp time.Time Speedbrakes bool Loudness int Activity string User string // A hash fingerprint of the email address City string Zip string // Denormalized fields to index/group by DatePST string HourPST int // Aircraft details; might be null FlightKey string // Flightnumber plus date (e.g. "UA123-20161231") - to allow for joins FlightNumber string // IATA scheduled flight number AirlineCode string // The 2-char IATA airline code Origin string Destination string EquipType string // B744, etc geo.Latlong // embedded; location of aircraft at Timestamp PressureAltitude float64 Groundspeed float64 }
AnonymizedComplaint is a subset of the data from a complaint; these values are released to the public as a queryable database. The data is somewhat denormalized, to allow for efficient indexing & querying.
func AnonymizeComplaint ¶
func AnonymizeComplaint(c *Complaint) *AnonymizedComplaint
func (AnonymizedComplaint) HasIdenitifiedAircraft ¶
func (ac AnonymizedComplaint) HasIdenitifiedAircraft() bool
type Browser ¶
type Browser struct {
UUID, Name, Version, Vendor, Platform string `datastore:",noindex"`
}
Fields about backend submission
type CQuery ¶
func NewComplaintQuery ¶
func NewComplaintQuery() *CQuery
func NewProfileQuery ¶
func NewProfileQuery() *CQuery
func (*CQuery) ByCallerCode ¶
func (*CQuery) BySubmissionOutcome ¶
func (*CQuery) ByTimespan ¶
Query builders for Complaint
func (*CQuery) OrderTimeAsc ¶
func (*CQuery) OrderTimeDesc ¶
type ComplainerProfile ¶
type ComplainerProfile struct { EmailAddress string // This is the root key; we get it from the GAE user profile. CallerCode string FullName string `datastore:",noindex"` Address string `datastore:",noindex"` StructuredAddress PostalAddress Lat, Long float64 Elevation float64 // in meters CcSfo bool `datastore:",noindex"` SelectorAlgorithm string // Users can have different algorithms (and maybe even params someday) SendDailyEmail int // 0 == unset, 1 == OK/yes, -1 == no DataSharing int // 0 == unset, 1 == OK/yes, -1 == no ThirdPartyComms int `datastore:",noindex"` // 0 == unset, 1 == OK/yes, -1 == no ButtonId []string // AWS IoT button serial numbers }
A ComplainerProfile represents a single human who makes complaints, and has a caller code This is the root object for the datastore; the individual complaints hang off this
func (*ComplainerProfile) Base64Decode ¶
func (p *ComplainerProfile) Base64Decode(str string) error
func (ComplainerProfile) Base64Encode ¶
func (p ComplainerProfile) Base64Encode() (string, error)
func (ComplainerProfile) DataSharingOK ¶
func (p ComplainerProfile) DataSharingOK() bool
func (ComplainerProfile) ElevationFeet ¶
func (p ComplainerProfile) ElevationFeet() float64
func (*ComplainerProfile) FetchStructuredAddress ¶
func (p *ComplainerProfile) FetchStructuredAddress() (PostalAddress, error)
func (*ComplainerProfile) GetStructuredAddress ¶
func (p *ComplainerProfile) GetStructuredAddress() PostalAddress
func (ComplainerProfile) SendDailyEmailOK ¶
func (p ComplainerProfile) SendDailyEmailOK() bool
func (ComplainerProfile) SplitName ¶
func (p ComplainerProfile) SplitName() (first, last string)
Attempt to split into firstname, surname
func (ComplainerProfile) ThirdPartyCommsOK ¶
func (p ComplainerProfile) ThirdPartyCommsOK() bool
func (*ComplainerProfile) UpdateStructuredAddress ¶
func (p *ComplainerProfile) UpdateStructuredAddress() error
type Complaint ¶
type Complaint struct { Version int `datastore:",noindex"` // undef or 0 means unversioned thingy. Description string `datastore:",noindex"` Timestamp time.Time AircraftOverhead flightid.Aircraft Debug string `datastore:",noindex"` // Debugging; mostly about flight lookup HeardSpeedbreaks bool Loudness int `datastore:",noindex"` // 0=undef, 1=loud, 2=very loud, 3=insane Activity string `datastore:",noindex"` // What was disturbed Profile ComplainerProfile // Embed the whole profile Submission // embedded; details about submitting the complaint to a backend Browser Browser // Details about the browser used // Synthetic fields DatastoreKey string `datastore:"-"` Dist2KM float64 `datastore:"-"` // Distance from home to aircraft Dist3KM float64 `datastore:"-"` }
func (Complaint) AltitudeHrefString ¶
func (Complaint) ToCopyWithStoredDataOnly ¶
ToCopyWithStoredDataOnly returns a copy of the complaint that only has the stored data fields (e.g. no synthetic fields). This copy is what we store during archiving, and verifying archives.
type ComplaintDB ¶
type ComplaintDB struct { StartTime time.Time Provider ds.DatastoreProvider Logger *pkglog.Logger // contains filtered or unexported fields }
ComplaintDB is a transient handle to the database
func NewDB ¶
func NewDB(ctx context.Context) ComplaintDB
func (ComplaintDB) AddComplaintSliceToCSV ¶
func (cdb ComplaintDB) AddComplaintSliceToCSV(complaints []Complaint, w io.Writer) error
func (ComplaintDB) AddDailyCount ¶
func (cdb ComplaintDB) AddDailyCount(dc DailyCount) error
func (ComplaintDB) AddHeadersToCSV ¶
func (cdb ComplaintDB) AddHeadersToCSV(w io.Writer)
func (ComplaintDB) AddHistoricalComplaintByEmailAddress ¶
func (cdb ComplaintDB) AddHistoricalComplaintByEmailAddress(ea string, c *Complaint) error
func (ComplaintDB) CPQByEmail ¶
func (cdb ComplaintDB) CPQByEmail(email string) *CQuery
func (ComplaintDB) CQByEmail ¶
func (cdb ComplaintDB) CQByEmail(email string) *CQuery
Canned queries
func (ComplaintDB) CSVHeaders ¶
func (cdb ComplaintDB) CSVHeaders() []string
func (ComplaintDB) ComplainByButtonId ¶
func (cdb ComplaintDB) ComplainByButtonId(id string, c *Complaint) error
func (ComplaintDB) ComplainByCallerCode ¶
func (cdb ComplaintDB) ComplainByCallerCode(cc string, c *Complaint) error
func (ComplaintDB) ComplainByEmailAddress ¶
func (cdb ComplaintDB) ComplainByEmailAddress(ea string, c *Complaint) error
func (ComplaintDB) ComplaintKeyOwnedBy ¶
We need to assert this in a few places
func (ComplaintDB) ComplaintKeyStrOwnedBy ¶
func (cdb ComplaintDB) ComplaintKeyStrOwnedBy(keyStr, owner string) (bool, error)
func (ComplaintDB) ComplaintToCSVFunc ¶
func (cdb ComplaintDB) ComplaintToCSVFunc() func(c *Complaint) []string
func (ComplaintDB) CountComplaintsAndUniqueUsersIn ¶
func (ComplaintDB) Ctx ¶
func (cdb ComplaintDB) Ctx() context.Context
func (ComplaintDB) Debugf ¶
func (cdb ComplaintDB) Debugf(step string, fmtstr string, varargs ...interface{})
Debugf is has a 'step' arg, and adds its own latency timings
func (ComplaintDB) DeletAllGlobalStats ¶
func (cdb ComplaintDB) DeletAllGlobalStats() error
func (ComplaintDB) DeleteAllKeys ¶
func (cdb ComplaintDB) DeleteAllKeys(keyers []ds.Keyer) error
func (ComplaintDB) DeleteByKey ¶
func (cdb ComplaintDB) DeleteByKey(keyer ds.Keyer) error
func (ComplaintDB) Errorf ¶
func (cdb ComplaintDB) Errorf(fmtstr string, varargs ...interface{})
func (ComplaintDB) FormattedWriteCQueryToCSV ¶
func (ComplaintDB) GetAllByEmailAddress ¶
func (cdb ComplaintDB) GetAllByEmailAddress(ea string, everything bool) (*ComplaintsAndProfile, error)
func (ComplaintDB) GetComplaintPositionsInSpanByIcao ¶
func (*ComplaintDB) GetDailyCounts ¶
func (cdb *ComplaintDB) GetDailyCounts(email string) ([]DailyCount, error)
func (ComplaintDB) GetKeyerOrNil ¶
func (cdb ComplaintDB) GetKeyerOrNil(c Complaint) ds.Keyer
func (ComplaintDB) GetProfileLocations ¶
func (cdb ComplaintDB) GetProfileLocations() ([]geo.Latlong, error)
func (ComplaintDB) GetUniqueUsersAndCountsIn ¶
func (ComplaintDB) HTTPClient ¶
func (cdb ComplaintDB) HTTPClient() *http.Client
func (ComplaintDB) Infof ¶
func (cdb ComplaintDB) Infof(fmtstr string, varargs ...interface{})
func (ComplaintDB) LoadGlobalStats ¶
func (cdb ComplaintDB) LoadGlobalStats() (*GlobalStats, error)
func (ComplaintDB) LookupAllKeys ¶
func (cdb ComplaintDB) LookupAllKeys(cq *CQuery) ([]ds.Keyer, error)
func (ComplaintDB) LookupAllProfiles ¶
func (cdb ComplaintDB) LookupAllProfiles(cq *CQuery) ([]ComplainerProfile, error)
func (ComplaintDB) LookupFirst ¶
func (cdb ComplaintDB) LookupFirst(cq *CQuery) (*Complaint, error)
func (ComplaintDB) LookupKey ¶
func (cdb ComplaintDB) LookupKey(keyerStr string, owner string) (*Complaint, error)
If owner is non-empty, return error if the looked-up key doesn't have that owner. Unless the admin flag is set on the DB handle.
func (ComplaintDB) LookupProfile ¶
func (cdb ComplaintDB) LookupProfile(email string) (*ComplainerProfile, error)
LookupProfile swallows the not-found error; and returns an empty profile on all errors.
func (ComplaintDB) MarshalComplaintSlice ¶
func (cdb ComplaintDB) MarshalComplaintSlice(complaints []Complaint, w io.Writer) error
func (ComplaintDB) MustLookupProfile ¶
func (cdb ComplaintDB) MustLookupProfile(email string) (*ComplainerProfile, error)
If not found, returns an error
func (*ComplaintDB) NewComplaintIterator ¶
func (cdb *ComplaintDB) NewComplaintIterator(cq *CQuery) *ComplaintIterator
func (*ComplaintDB) NewComplaintQuery ¶
func (cdb *ComplaintDB) NewComplaintQuery() *CQuery
func (*ComplaintDB) NewProfileQuery ¶
func (cdb *ComplaintDB) NewProfileQuery() *CQuery
func (*ComplaintDB) NewQuery ¶
func (cdb *ComplaintDB) NewQuery(kind string) *CQuery
func (ComplaintDB) PersistComplaint ¶
func (cdb ComplaintDB) PersistComplaint(c Complaint) error
func (ComplaintDB) PersistComplaints ¶
func (cdb ComplaintDB) PersistComplaints(complaints []Complaint) error
func (ComplaintDB) PersistProfile ¶
func (cdb ComplaintDB) PersistProfile(p ComplainerProfile) error
func (ComplaintDB) RawLookupAll ¶
func (cdb ComplaintDB) RawLookupAll(cq *CQuery) ([]Complaint, error)
func (ComplaintDB) ResetGlobalStats ¶
func (cdb ComplaintDB) ResetGlobalStats()
func (ComplaintDB) SaveGlobalStats ¶
func (cdb ComplaintDB) SaveGlobalStats(gs GlobalStats) error
func (*ComplaintDB) SummaryReport ¶
func (ComplaintDB) UnmarshalComplaintSlice ¶
func (cdb ComplaintDB) UnmarshalComplaintSlice(r io.Reader) ([]Complaint, error)
func (ComplaintDB) UpdateComplaint ¶
func (cdb ComplaintDB) UpdateComplaint(c Complaint, owner string) error
If owner is not nil, then complaint must be owned by it
func (ComplaintDB) WriteCQueryToCSV ¶
type ComplaintIterator ¶
A shim on the datastoreprovider iterator that can talk flights
func (*ComplaintIterator) Complaint ¶
func (ci *ComplaintIterator) Complaint() *Complaint
func (*ComplaintIterator) Err ¶
func (ci *ComplaintIterator) Err() error
func (*ComplaintIterator) Remaining ¶
func (ci *ComplaintIterator) Remaining() int
type ComplaintsAndProfile ¶
type ComplaintsAndProfile struct { Profile ComplainerProfile Complaints []Complaint Counts []CountItem }
type ComplaintsByTimeDesc ¶
type ComplaintsByTimeDesc []Complaint
func (ComplaintsByTimeDesc) Len ¶
func (a ComplaintsByTimeDesc) Len() int
func (ComplaintsByTimeDesc) Less ¶
func (a ComplaintsByTimeDesc) Less(i, j int) bool
func (ComplaintsByTimeDesc) Swap ¶
func (a ComplaintsByTimeDesc) Swap(i, j int)
type ContextProperties ¶
func GetContextProperties ¶
func GetContextProperties(ctx context.Context) (ContextProperties, bool)
type CountItem ¶
type CountItem struct { Key string Count int TotalComplaints int TotalComplainers int IsMaxComplaints bool IsMaxComplainers bool }
This is just maddening boilerplate junk we need
type DailyCount ¶
type DailyCount struct { Datestring string NumComplaints int NumComplainers int IsMaxComplaints bool IsMaxComplainers bool }
func (DailyCount) String ¶
func (dc DailyCount) String() string
func (DailyCount) Timestamp ¶
func (dc DailyCount) Timestamp() time.Time
type DailyCountDesc ¶
type DailyCountDesc []DailyCount
func (DailyCountDesc) Len ¶
func (a DailyCountDesc) Len() int
func (DailyCountDesc) Less ¶
func (a DailyCountDesc) Less(i, j int) bool
func (DailyCountDesc) Swap ¶
func (a DailyCountDesc) Swap(i, j int)
type FrozenGlobalStats ¶
type FrozenGlobalStats struct {
Bytes []byte `datastore:",noindex"`
}
type GlobalStats ¶
type GlobalStats struct { DatastoreKey string Counts []DailyCount }
type PostalAddress ¶
type Submission ¶
type Submission struct { T time.Time D time.Duration // Of most recent submission Outcome SubmissionOutcome Response []byte `datastore:",noindex"` // JSON response, in full Key string `datastore:",noindex"` // Foreign key, from backend Attempts int Log string `datastore:",noindex"` }
Fields about backend submission
func (Submission) ClassifyRejection ¶
func (s Submission) ClassifyRejection() (SubmissionRejectReason, string)
func (Submission) String ¶
func (s Submission) String() string
func (Submission) WasFailure ¶
func (s Submission) WasFailure() bool
type SubmissionOutcome ¶
type SubmissionOutcome int
const ( SubmissionNotAttempted SubmissionOutcome = iota SubmissionAccepted SubmissionTimeout SubmissionRejected SubmissionFailed )
func (SubmissionOutcome) String ¶
func (so SubmissionOutcome) String() string
type SubmissionRejectReason ¶
type SubmissionRejectReason int
func (SubmissionRejectReason) String ¶
func (srr SubmissionRejectReason) String() string