Can now accept location
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package tg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||
query "github.com/tgckpg/golifehk/query"
|
||||
)
|
||||
@@ -32,25 +33,37 @@ func BotSend(bot *tgbotapi.BotAPI, update *tgbotapi.Update, qResult query.IQuery
|
||||
return false, nil
|
||||
}
|
||||
|
||||
msg = tgbotapi.NewMessage(update.Message.Chat.ID, mesg)
|
||||
var chatId int64
|
||||
if update.Message != nil {
|
||||
chatId = update.Message.Chat.ID
|
||||
msg.ReplyToMessageID = update.Message.MessageID
|
||||
}
|
||||
|
||||
if update.CallbackQuery != nil {
|
||||
chatId = update.CallbackQuery.Message.Chat.ID
|
||||
}
|
||||
|
||||
msg = tgbotapi.NewMessage(chatId, mesg)
|
||||
msg.ParseMode = "MarkdownV2"
|
||||
|
||||
switch mesgType {
|
||||
case "PlainText":
|
||||
case "Table":
|
||||
|
||||
button := tgbotapi.NewInlineKeyboardButtonData(
|
||||
"Show Status", // what user sees
|
||||
"status_cmd", // what bot receives
|
||||
)
|
||||
|
||||
msg.ReplyMarkup = tgbotapi.NewInlineKeyboardMarkup(
|
||||
tgbotapi.NewInlineKeyboardRow(button, button),
|
||||
)
|
||||
|
||||
buttonRows := [][]tgbotapi.InlineKeyboardButton{}
|
||||
for _, row := range qResult.GetTableData() {
|
||||
buttons := []tgbotapi.InlineKeyboardButton{}
|
||||
for _, cell := range row {
|
||||
button := tgbotapi.NewInlineKeyboardButtonData(cell.Name, cell.Value)
|
||||
buttons = append(buttons, button)
|
||||
fmt.Println(cell)
|
||||
}
|
||||
buttonRows = append(buttonRows, buttons)
|
||||
}
|
||||
|
||||
msg.ReplyMarkup = tgbotapi.NewInlineKeyboardMarkup(buttonRows...)
|
||||
}
|
||||
|
||||
msg.ReplyToMessageID = update.Message.MessageID
|
||||
bot.Send(msg)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ func writeCCharInfo(sb *strings.Builder, cc *CChar) {
|
||||
|
||||
func (this QueryResult) DataType() string { return this.ResultType }
|
||||
func (this QueryResult) Consumed() bool { return this.isConsumed }
|
||||
func (this QueryResult) GetTableData() [][]map[string]string { return nil }
|
||||
func (this QueryResult) GetTableData() [][]query.TableCell { return nil }
|
||||
|
||||
func (this QueryResult) Message() (string, error) {
|
||||
|
||||
|
||||
@@ -2,39 +2,51 @@ package kmb
|
||||
|
||||
import (
|
||||
i18n "github.com/tgckpg/golifehk/i18n"
|
||||
query "github.com/tgckpg/golifehk/query"
|
||||
)
|
||||
|
||||
type BusStop struct {
|
||||
type BusStopJson struct {
|
||||
BusStopId string `json:"stop"`
|
||||
Latitude float64 `json:"lat,string"`
|
||||
Longtitude float64 `json:"long,string"`
|
||||
Longitude float64 `json:"long,string"`
|
||||
Name_en string `json:"name_en"`
|
||||
Name_tc string `json:"name_tc"`
|
||||
Name_sc string `json:"name_sc"`
|
||||
|
||||
// Routes[ Route ][ Direction ]
|
||||
Routes *[] *RouteStop
|
||||
|
||||
i18n.Generics
|
||||
}
|
||||
|
||||
type BusStops struct {
|
||||
type BusStop struct {
|
||||
BusStopId string
|
||||
|
||||
// Routes[ Route ][ Direction ]
|
||||
Routes *[]*RouteStop
|
||||
|
||||
i18n.Generics
|
||||
query.GeoLocation
|
||||
}
|
||||
|
||||
type BusStopsJson struct {
|
||||
Type string `json:"type"`
|
||||
Version string `json:"version"`
|
||||
DateCreated string `json:"generated_timestamp"`
|
||||
BusStops [] *BusStop `json:"data"`
|
||||
BusStops []*BusStopJson `json:"data"`
|
||||
}
|
||||
|
||||
func ( this *BusStop ) Reload() {
|
||||
i18n_Name := map[string] string{}
|
||||
i18n_Name["en"] = this.Name_en
|
||||
i18n_Name["zh-Hant"] = this.Name_tc
|
||||
func (b BusStop) Register(registers map[string]struct{}) bool {
|
||||
if _, ok := registers[b.BusStopId]; ok {
|
||||
return false
|
||||
}
|
||||
registers[b.BusStopId] = struct{}{}
|
||||
return true
|
||||
}
|
||||
|
||||
searchData := [] *string{}
|
||||
searchData = append( searchData, &this.Name_en )
|
||||
searchData = append( searchData, &this.Name_tc )
|
||||
func (this *BusStop) Reload() {
|
||||
searchData := []*string{}
|
||||
searchData = append(searchData, &this.BusStopId)
|
||||
|
||||
for _, v := range *this.Name {
|
||||
searchData = append(searchData, &v)
|
||||
}
|
||||
|
||||
this.Name = &i18n_Name
|
||||
this.Key = &this.BusStopId
|
||||
this.SearchData = &searchData
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ type QueryResult struct {
|
||||
Query *query.QueryObject
|
||||
|
||||
isConsumed bool
|
||||
dataType string
|
||||
tableData [][]query.TableCell
|
||||
}
|
||||
|
||||
func writeRouteHead(sb *strings.Builder, r *RouteStop) {
|
||||
@@ -50,12 +52,14 @@ func writeShortRoute(lang *string, sb *strings.Builder, r *RouteStop) {
|
||||
sb.WriteString("\n")
|
||||
}
|
||||
|
||||
func (this QueryResult) DataType() string { return "MarkdownV2" }
|
||||
func (this QueryResult) DataType() string { return this.dataType }
|
||||
func (this QueryResult) Consumed() bool { return this.isConsumed }
|
||||
func (this QueryResult) GetTableData() [][]map[string]string { return nil }
|
||||
func (this QueryResult) GetTableData() [][]query.TableCell { return this.tableData }
|
||||
|
||||
func (this *QueryResult) Message() (string, error) {
|
||||
|
||||
this.dataType = "PlainText"
|
||||
|
||||
if this.Error != nil {
|
||||
return "", this.Error
|
||||
}
|
||||
@@ -66,6 +70,39 @@ func (this *QueryResult) Message() (string, error) {
|
||||
|
||||
// Print Stop Names, then print the list of routes
|
||||
if this.Query.Key == "" {
|
||||
loc := this.Query.Message.Location
|
||||
if loc != nil {
|
||||
sb.WriteString("九巴 100m")
|
||||
this.dataType = "Table"
|
||||
|
||||
table := [][]query.TableCell{}
|
||||
|
||||
for _, item := range *this.Query.Results {
|
||||
b := any(item).(*BusStop)
|
||||
|
||||
row := []query.TableCell{}
|
||||
|
||||
cell := query.TableCell{
|
||||
Name: fmt.Sprintf("%.2fm %s", b.Dist(loc.Lat(), loc.Lon()), (*b.Name)[this.Lang]),
|
||||
Value: fmt.Sprintf("%s", b.BusStopId),
|
||||
}
|
||||
row = append(row, cell)
|
||||
|
||||
for _, r := range *b.Routes {
|
||||
sb_i := strings.Builder{}
|
||||
writeRouteHead(&sb_i, r)
|
||||
cell := query.TableCell{
|
||||
Name: sb_i.String(),
|
||||
Value: fmt.Sprintf("%s %s", r.RouteId, (*b.Name)[this.Lang]),
|
||||
}
|
||||
row = append(row, cell)
|
||||
}
|
||||
|
||||
table = append(table, row)
|
||||
}
|
||||
this.tableData = table
|
||||
|
||||
} else {
|
||||
busStops := map[string]*BusStop{}
|
||||
for _, item := range *this.Query.Results {
|
||||
var r *RouteStop
|
||||
@@ -88,6 +125,7 @@ func (this *QueryResult) Message() (string, error) {
|
||||
}
|
||||
sb.WriteString("\n")
|
||||
}
|
||||
}
|
||||
|
||||
// We got a route key
|
||||
} else {
|
||||
|
||||
@@ -40,13 +40,8 @@ func (routeStop RouteStop) NextStop() *RouteStop {
|
||||
|
||||
func (this *RouteStop) Reload() {
|
||||
|
||||
searchData := []*string{}
|
||||
busStop := *this.BusStop
|
||||
searchData = append(searchData, &busStop.Name_en)
|
||||
searchData = append(searchData, &busStop.Name_tc)
|
||||
|
||||
this.Key = &this.RouteId
|
||||
this.SearchData = &searchData
|
||||
this.SearchData = this.BusStop.SearchData
|
||||
}
|
||||
|
||||
type ByRoute []*RouteStop
|
||||
|
||||
@@ -9,19 +9,39 @@ import (
|
||||
func Query(q query.QueryMessage) query.IQueryResult {
|
||||
|
||||
lang := q.Lang
|
||||
message := q.Text
|
||||
|
||||
var qo *query.QueryObject
|
||||
var err error
|
||||
var routeStops *[]query.ISearchable
|
||||
|
||||
qr := QueryResult{Lang: lang}
|
||||
routeStops, err := getRouteStops()
|
||||
|
||||
busStops, err := readBusStopsData()
|
||||
if err != nil {
|
||||
qr.Error = err
|
||||
goto qrReturn
|
||||
}
|
||||
|
||||
qo, err = query.MatchKeys(strings.ToUpper(message), routeStops)
|
||||
routeStops, err = getRouteStops(busStops)
|
||||
if err != nil {
|
||||
qr.Error = err
|
||||
goto qrReturn
|
||||
}
|
||||
|
||||
if q.Text != "" {
|
||||
qo, err = query.MatchKeys(strings.ToUpper(q.Text), routeStops)
|
||||
} else if q.Location != nil {
|
||||
bList := []query.ISearchable{}
|
||||
|
||||
for _, b := range *busStops {
|
||||
bList = append(bList, b)
|
||||
}
|
||||
|
||||
qo, err = query.MatchNearest(*q.Location, &bList, 100, 3)
|
||||
}
|
||||
|
||||
qo.Message = &q
|
||||
|
||||
if err != nil {
|
||||
qr.Error = err
|
||||
goto qrReturn
|
||||
|
||||
@@ -32,7 +32,6 @@ func readRouteStopsData(busStops *map[string]*BusStop, buff *bytes.Buffer) (*[]*
|
||||
if busStop == nil {
|
||||
busStop = &BusStop{
|
||||
BusStopId: entry.StationId,
|
||||
Name_en: "???", Name_tc: "???", Name_sc: "???",
|
||||
}
|
||||
busStop.Reload()
|
||||
|
||||
@@ -76,37 +75,15 @@ func readRouteStopsData(busStops *map[string]*BusStop, buff *bytes.Buffer) (*[]*
|
||||
return &allRouteStops, nil
|
||||
}
|
||||
|
||||
func readBusStopsData(buff *bytes.Buffer) (*map[string]*BusStop, error) {
|
||||
busStopsData := BusStops{}
|
||||
err := json.Unmarshal(buff.Bytes(), &busStopsData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
busStopMap := map[string]*BusStop{}
|
||||
for _, entry := range busStopsData.BusStops {
|
||||
|
||||
entry.Reload()
|
||||
|
||||
if _, ok := busStopMap[entry.BusStopId]; ok {
|
||||
return nil, fmt.Errorf("Duplicated BusStop: %s", entry.BusStopId)
|
||||
}
|
||||
|
||||
busStopMap[entry.BusStopId] = entry
|
||||
}
|
||||
return &busStopMap, nil
|
||||
}
|
||||
|
||||
func getRouteStops() (*[]query.ISearchable, error) {
|
||||
var busStopMap *map[string]*BusStop
|
||||
func readBusStopsData() (*map[string]*BusStop, error) {
|
||||
busStopsData := BusStopsJson{}
|
||||
|
||||
QUERY_FUNC := func() (io.ReadCloser, error) {
|
||||
return utils.HttpGet("https://data.etabus.gov.hk/v1/transport/kmb/stop")
|
||||
}
|
||||
|
||||
PARSE_FUNC := func(buff *bytes.Buffer) error {
|
||||
var err error
|
||||
busStopMap, err = readBusStopsData(buff)
|
||||
err := json.Unmarshal(buff.Bytes(), &busStopsData)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -120,18 +97,49 @@ func getRouteStops() (*[]query.ISearchable, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
busStopMap := map[string]*BusStop{}
|
||||
for _, entry := range busStopsData.BusStops {
|
||||
|
||||
b := BusStop{
|
||||
BusStopId: entry.BusStopId,
|
||||
}
|
||||
|
||||
b.Latitude = entry.Latitude
|
||||
b.Longitude = entry.Longitude
|
||||
|
||||
n := map[string]string{
|
||||
"en": entry.Name_en,
|
||||
"zh-Hant": entry.Name_tc,
|
||||
"zh-Hans": entry.Name_sc,
|
||||
}
|
||||
|
||||
b.Name = &n
|
||||
|
||||
b.Reload()
|
||||
|
||||
if _, ok := busStopMap[b.BusStopId]; ok {
|
||||
return nil, fmt.Errorf("Duplicated BusStop: %s", b.BusStopId)
|
||||
}
|
||||
|
||||
busStopMap[b.BusStopId] = &b
|
||||
}
|
||||
return &busStopMap, nil
|
||||
}
|
||||
|
||||
func getRouteStops(busStopMap *map[string]*BusStop) (*[]query.ISearchable, error) {
|
||||
var routeStops *[]*RouteStop
|
||||
QUERY_FUNC = func() (io.ReadCloser, error) {
|
||||
|
||||
QUERY_FUNC := func() (io.ReadCloser, error) {
|
||||
return utils.HttpGet("https://data.etabus.gov.hk/v1/transport/kmb/route-stop")
|
||||
}
|
||||
|
||||
PARSE_FUNC = func(buff *bytes.Buffer) error {
|
||||
PARSE_FUNC := func(buff *bytes.Buffer) error {
|
||||
var err error
|
||||
routeStops, err = readRouteStopsData(busStopMap, buff)
|
||||
return err
|
||||
}
|
||||
|
||||
cs, err = utils.CacheStreamEx(JSON_ROUTESTOPS, QUERY_FUNC)
|
||||
cs, err := utils.CacheStreamEx(JSON_ROUTESTOPS, QUERY_FUNC)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ type QueryResult struct {
|
||||
Query *query.QueryObject
|
||||
|
||||
isConsumed bool
|
||||
dataType string
|
||||
tableData [][]query.TableCell
|
||||
}
|
||||
|
||||
func writeShortRoute(lang *string, sb *strings.Builder, b *BusStop) {
|
||||
@@ -38,11 +40,13 @@ func writeShortRoute(lang *string, sb *strings.Builder, b *BusStop) {
|
||||
sb.WriteString("\n")
|
||||
}
|
||||
|
||||
func (this QueryResult) DataType() string { return "MarkdownV2" }
|
||||
func (this QueryResult) DataType() string { return this.dataType }
|
||||
func (this QueryResult) Consumed() bool { return this.isConsumed }
|
||||
func (this QueryResult) GetTableData() [][]map[string]string { return nil }
|
||||
func (this QueryResult) GetTableData() [][]query.TableCell { return this.tableData }
|
||||
|
||||
func (this QueryResult) Message() (string, error) {
|
||||
func (this *QueryResult) Message() (string, error) {
|
||||
|
||||
this.dataType = "PlainText"
|
||||
|
||||
if this.Error != nil {
|
||||
return "", this.Error
|
||||
@@ -67,29 +71,40 @@ func (this QueryResult) Message() (string, error) {
|
||||
loc := q.Message.Location
|
||||
if loc != nil {
|
||||
|
||||
// Print nearest bus stops
|
||||
this.dataType = "Table"
|
||||
sb.WriteString("K巴 100m")
|
||||
|
||||
table := [][]query.TableCell{}
|
||||
|
||||
for _, entry := range *q.Results {
|
||||
busStop := any(entry).(*BusStop)
|
||||
|
||||
utils.WriteMDv2Text(&sb, fmt.Sprintf("%.2fm", busStop.Dist(loc.Lat(), loc.Lon())))
|
||||
sb.WriteString(" ")
|
||||
sb.WriteString(" [")
|
||||
utils.WriteMDv2Text(&sb, busStop.RouteId)
|
||||
sb_i := strings.Builder{}
|
||||
sb_i.WriteString(fmt.Sprintf("%.2fm", busStop.Dist(loc.Lat(), loc.Lon())))
|
||||
sb_i.WriteString(" ")
|
||||
utils.WriteMDv2Text(&sb_i, busStop.RouteId)
|
||||
d := busStop.Direction
|
||||
if d == "O" {
|
||||
sb.WriteString("↑")
|
||||
sb_i.WriteString("↑")
|
||||
} else if d == "I" {
|
||||
sb.WriteString("↓")
|
||||
sb_i.WriteString("↓")
|
||||
} else {
|
||||
sb.WriteString("\\?")
|
||||
sb_i.WriteString("\\?")
|
||||
}
|
||||
utils.WriteMDv2Text(&sb, (*busStop.Name)[this.Lang])
|
||||
utils.WriteMDv2Text(&sb, busStop.RouteId)
|
||||
utils.WriteMDv2Text(&sb, (*busStop.Name)[this.Lang])
|
||||
sb.WriteString(")")
|
||||
sb.WriteString("\n")
|
||||
sb_i.WriteString(" ")
|
||||
utils.WriteMDv2Text(&sb_i, (*busStop.Name)[this.Lang])
|
||||
|
||||
row := []query.TableCell{
|
||||
query.TableCell{
|
||||
Name: sb_i.String(),
|
||||
Value: fmt.Sprintf("%s %s", busStop.RouteId, (*busStop.Name)[this.Lang]),
|
||||
},
|
||||
}
|
||||
|
||||
table = append(table, row)
|
||||
}
|
||||
|
||||
this.tableData = table
|
||||
} else {
|
||||
sort.Sort(query.ByKey(*q.Results))
|
||||
for _, entry := range *q.Results {
|
||||
|
||||
52
main.go
52
main.go
@@ -30,6 +30,22 @@ func main() {
|
||||
updates := bot.GetUpdatesChan(u)
|
||||
|
||||
for update := range updates {
|
||||
|
||||
if update.CallbackQuery != nil {
|
||||
callback := tgbotapi.NewCallback(update.CallbackQuery.ID, "")
|
||||
bot.Request(callback)
|
||||
|
||||
q := query.QueryMessage{Lang: "zh-Hant", Text: update.CallbackQuery.Data}
|
||||
f_sent, f_err := processQuery(bot, &update, q)
|
||||
|
||||
if !f_sent && f_err != nil {
|
||||
mesg := utils.MDv2Text(fmt.Sprintf("%s", f_err))
|
||||
tgadaptor.BotSendText(bot, &update, &mesg)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if update.Message == nil {
|
||||
continue
|
||||
}
|
||||
@@ -45,15 +61,6 @@ func main() {
|
||||
continue
|
||||
}
|
||||
|
||||
f_queries := []func(query.QueryMessage) query.IQueryResult{
|
||||
cjlookup.Query,
|
||||
mtrbus.Query,
|
||||
kmb.Query,
|
||||
}
|
||||
|
||||
var f_sent bool = false
|
||||
var f_err error = nil
|
||||
|
||||
tgMesg := update.Message
|
||||
q := query.QueryMessage{Lang: "zh-Hant", Text: tgMesg.Text}
|
||||
|
||||
@@ -61,10 +68,29 @@ func main() {
|
||||
q.Location = &query.GeoLocation{tgMesg.Location.Latitude, tgMesg.Location.Longitude}
|
||||
}
|
||||
|
||||
f_sent, f_err := processQuery(bot, &update, q)
|
||||
|
||||
if !isGroup && !f_sent && f_err != nil {
|
||||
mesg := utils.MDv2Text(fmt.Sprintf("%s", f_err))
|
||||
tgadaptor.BotSendText(bot, &update, &mesg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func processQuery(bot *tgbotapi.BotAPI, update *tgbotapi.Update, q query.QueryMessage) (bool, error) {
|
||||
var f_sent bool = false
|
||||
var f_err error = nil
|
||||
|
||||
f_queries := []func(query.QueryMessage) query.IQueryResult{
|
||||
cjlookup.Query,
|
||||
mtrbus.Query,
|
||||
kmb.Query,
|
||||
}
|
||||
|
||||
for _, Query := range f_queries {
|
||||
|
||||
qResult := Query(q)
|
||||
sent, err := tgadaptor.BotSend(bot, &update, qResult)
|
||||
sent, err := tgadaptor.BotSend(bot, update, qResult)
|
||||
|
||||
if sent {
|
||||
f_sent = true
|
||||
@@ -79,9 +105,5 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
if !isGroup && !f_sent && f_err != nil {
|
||||
mesg := utils.MDv2Text(fmt.Sprintf("%s", f_err))
|
||||
tgadaptor.BotSendText(bot, &update, &mesg)
|
||||
}
|
||||
}
|
||||
return f_sent, f_err
|
||||
}
|
||||
|
||||
@@ -5,6 +5,14 @@ import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
type IGeoLocation interface {
|
||||
HasGeoLocation() bool
|
||||
Lat() float64
|
||||
Lon() float64
|
||||
Dist(lat, lon float64) float64
|
||||
Register(map[string]struct{}) bool
|
||||
}
|
||||
|
||||
type GeoLocation struct {
|
||||
Latitude float64
|
||||
Longitude float64
|
||||
@@ -19,7 +27,7 @@ func (b GeoLocation) Dist(lat float64, lon float64) float64 {
|
||||
var dist float64
|
||||
geodesic.WGS84.Inverse(
|
||||
lat, lon,
|
||||
b.Latitude, b.Longitude,
|
||||
b.Lat(), b.Lon(),
|
||||
&dist, nil, nil,
|
||||
)
|
||||
return dist
|
||||
@@ -37,13 +45,14 @@ func (b NoGeoLocation) Register(map[string]struct{}) bool {
|
||||
|
||||
type GeoLocations []ISearchable
|
||||
|
||||
func (m GeoLocations) SortByNearest(p GeoLocation) {
|
||||
func (m GeoLocations) SortByNearest(p IGeoLocation) {
|
||||
sort.Slice(m, func(i, j int) bool {
|
||||
return m[i].Dist(p.Lat(), p.Lon()) < m[j].Dist(p.Lat(), p.Lon())
|
||||
})
|
||||
}
|
||||
|
||||
func (b GeoLocation) Register(map[string]struct{}) bool {
|
||||
panic("GeoLocation: Default is called")
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func MatchNearest(p GeoLocation, entries *[]ISearchable, dist float64, limit int) (*QueryObject, error) {
|
||||
func MatchNearest(p IGeoLocation, entries *[]ISearchable, dist float64, limit int) (*QueryObject, error) {
|
||||
|
||||
terms := []*QTerm{
|
||||
{
|
||||
@@ -19,9 +19,10 @@ func MatchNearest(p GeoLocation, entries *[]ISearchable, dist float64, limit int
|
||||
locs.SortByNearest(p)
|
||||
|
||||
matches := []ISearchable{}
|
||||
for i, loc := range *locs {
|
||||
if i < limit {
|
||||
matches = append(matches, loc)
|
||||
for i, item := range *locs {
|
||||
loc := item.(IGeoLocation)
|
||||
if i < limit && loc.Dist(p.Lat(), p.Lon()) <= dist {
|
||||
matches = append(matches, item)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,9 +19,14 @@ type QueryObject struct {
|
||||
Results *[]ISearchable
|
||||
}
|
||||
|
||||
type TableCell struct {
|
||||
Name string
|
||||
Value string
|
||||
}
|
||||
|
||||
type IQueryResult interface {
|
||||
Message() (string, error)
|
||||
DataType() string
|
||||
GetTableData() [][]map[string]string
|
||||
GetTableData() [][]TableCell
|
||||
Consumed() bool
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user