Added kmb and refactored query.Parse
This commit is contained in:
40
datasources/kmb/BusStop.go
Normal file
40
datasources/kmb/BusStop.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package kmb
|
||||
|
||||
import (
|
||||
i18n "github.com/tgckpg/golifehk/i18n"
|
||||
)
|
||||
|
||||
type BusStop struct {
|
||||
BusStopId string `json:"stop"`
|
||||
Latitude float64 `json:"lat,string"`
|
||||
Longtitude 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 string `json:"type"`
|
||||
Version string `json:"version"`
|
||||
DateCreated string `json:"generated_timestamp"`
|
||||
BusStops [] *BusStop `json:"data"`
|
||||
}
|
||||
|
||||
func ( this *BusStop ) Reload() {
|
||||
i18n_Name := map[string] string{}
|
||||
i18n_Name["en"] = this.Name_en
|
||||
i18n_Name["zh-Hant"] = this.Name_tc
|
||||
|
||||
searchData := [] *string{}
|
||||
searchData = append( searchData, &this.Name_en )
|
||||
searchData = append( searchData, &this.Name_tc )
|
||||
|
||||
this.Name = &i18n_Name
|
||||
this.Key = &this.BusStopId
|
||||
this.SearchData = &searchData
|
||||
}
|
47
datasources/kmb/QueryResult.go
Normal file
47
datasources/kmb/QueryResult.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package kmb
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
query "github.com/tgckpg/golifehk/query"
|
||||
utils "github.com/tgckpg/golifehk/utils"
|
||||
)
|
||||
|
||||
type QueryResult struct {
|
||||
Lang string
|
||||
Error error
|
||||
Query *query.QueryObject
|
||||
}
|
||||
|
||||
func ( this *QueryResult ) Message() ( string, error ) {
|
||||
|
||||
if this.Error != nil {
|
||||
return "", this.Error
|
||||
}
|
||||
|
||||
sb := strings.Builder{}
|
||||
|
||||
if 0 < len( *this.Query.Results ) {
|
||||
// Print Stop Name, the print the list of routes
|
||||
if this.Query.Key == "" {
|
||||
for _, item := range *this.Query.Results {
|
||||
var b *BusStop
|
||||
b = any( item ).( *BusStop )
|
||||
|
||||
if b.Routes == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
utils.WriteMDv2Text( &sb, (*b.Name)[ this.Lang ] )
|
||||
sb.WriteString( "\n " )
|
||||
for _, route := range *b.Routes {
|
||||
utils.WriteMDv2Text( &sb, route.RouteId )
|
||||
sb.WriteString( " " )
|
||||
}
|
||||
sb.WriteString( "\n" )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.String(), nil
|
||||
}
|
44
datasources/kmb/RouteStop.go
Normal file
44
datasources/kmb/RouteStop.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package kmb
|
||||
|
||||
import (
|
||||
query "github.com/tgckpg/golifehk/query"
|
||||
)
|
||||
|
||||
type RouteStop struct {
|
||||
BusStop *BusStop
|
||||
RouteId string `json:"route"`
|
||||
ServiceType string `json:"service_type"`
|
||||
Direction string `json:"bound"`
|
||||
StationSeq int `json:"seq,string"`
|
||||
StationId string `json:"stop"`
|
||||
|
||||
RouteStops *map[int] *RouteStop
|
||||
query.Searchable
|
||||
}
|
||||
|
||||
type RouteStops struct {
|
||||
Type string `json:"type"`
|
||||
Version string `json:"version"`
|
||||
DateCreated string `json:"generated_timestamp"`
|
||||
RouteStops [] *RouteStop `json:"data"`
|
||||
}
|
||||
|
||||
func ( routeStop RouteStop ) PrevStop() *RouteStop {
|
||||
if v, hasKey := (*routeStop.RouteStops)[ routeStop.StationSeq - 1 ]; hasKey {
|
||||
return v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ( routeStop RouteStop ) NextStop() *RouteStop {
|
||||
if v, hasKey := (*routeStop.RouteStops)[ routeStop.StationSeq + 1 ]; hasKey {
|
||||
return v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ByRouteId []RouteStop
|
||||
|
||||
func (a ByRouteId) Len() int { return len(a) }
|
||||
func (a ByRouteId) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a ByRouteId) Less(i, j int) bool { return a[i].RouteId < a[j].RouteId }
|
32
datasources/kmb/query.go
Normal file
32
datasources/kmb/query.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package kmb
|
||||
|
||||
import (
|
||||
"strings"
|
||||
query "github.com/tgckpg/golifehk/query"
|
||||
)
|
||||
|
||||
func Query( lang string, message string ) query.IQueryResult {
|
||||
|
||||
var qo *query.QueryObject
|
||||
var err error
|
||||
|
||||
qr := QueryResult{ Lang: lang }
|
||||
busStops, err := getBusStops()
|
||||
if err != nil {
|
||||
qr.Error = err
|
||||
goto qrReturn
|
||||
}
|
||||
|
||||
qo, err = query.Parse( strings.ToUpper( message ), busStops )
|
||||
if err != nil {
|
||||
qr.Error = err
|
||||
goto qrReturn
|
||||
}
|
||||
|
||||
qr.Query = qo
|
||||
|
||||
qrReturn:
|
||||
var iqr query.IQueryResult
|
||||
iqr = &qr
|
||||
return iqr
|
||||
}
|
10
datasources/kmb/query_test.go
Normal file
10
datasources/kmb/query_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package kmb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestQuerySchedule( t *testing.T ) {
|
||||
fmt.Print( Query( "zh", "大欖" ).Message() )
|
||||
}
|
143
datasources/kmb/routestops.go
Normal file
143
datasources/kmb/routestops.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package kmb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
// "strings"
|
||||
|
||||
query "github.com/tgckpg/golifehk/query"
|
||||
"github.com/tgckpg/golifehk/utils"
|
||||
)
|
||||
|
||||
var JSON_ROUTESTOPS string = filepath.Join( utils.WORKDIR, "kmb-routestops.json" )
|
||||
var JSON_BUSSTOPS string = filepath.Join( utils.WORKDIR, "kmb-busstops.json" )
|
||||
|
||||
func readRouteStopsData( busStops *map[string] *BusStop, buff *bytes.Buffer ) error {
|
||||
|
||||
routeStopsData := RouteStops{}
|
||||
err := json.Unmarshal( buff.Bytes(), &routeStopsData )
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// routeStops[ Route ][ ServiceType ][ Direction ][ Seq ] = RouteStop
|
||||
routeStops := map[string] *map[string] *map[ string ] *map[ int ] *RouteStop{}
|
||||
for _, entry := range routeStopsData.RouteStops {
|
||||
|
||||
busStop := (*busStops)[ entry.StationId ]
|
||||
if busStop == nil {
|
||||
busStop = &BusStop {
|
||||
BusStopId: entry.StationId,
|
||||
Name_en: "???", Name_tc: "???", Name_sc: "???",
|
||||
}
|
||||
busStop.Reload()
|
||||
|
||||
(*busStops)[ entry.StationId ] = busStop
|
||||
}
|
||||
|
||||
if busStop.Routes == nil {
|
||||
busStopRoutes := [] *RouteStop{}
|
||||
busStop.Routes = &busStopRoutes
|
||||
}
|
||||
|
||||
(*busStop.Routes) = append( (*busStop.Routes), entry )
|
||||
entry.BusStop = busStop
|
||||
|
||||
route := routeStops[ entry.RouteId ]
|
||||
if route == nil {
|
||||
route = &map[string] *map[ string ] *map[ int ] *RouteStop{}
|
||||
routeStops[ entry.RouteId ] = route
|
||||
}
|
||||
|
||||
service := (*route)[ entry.ServiceType ]
|
||||
if service == nil {
|
||||
service = &map[ string ] *map[ int ] *RouteStop{}
|
||||
(*route)[ entry.ServiceType ] = service
|
||||
}
|
||||
|
||||
direction := (*service)[ entry.Direction ]
|
||||
if direction == nil {
|
||||
direction = &map[ int ] *RouteStop{}
|
||||
(*service)[ entry.Direction ] = direction
|
||||
entry.RouteStops = direction
|
||||
}
|
||||
|
||||
seq := (*direction)[ entry.StationSeq ]
|
||||
if seq == nil {
|
||||
(*direction)[ entry.StationSeq ] = entry
|
||||
}
|
||||
}
|
||||
|
||||
return 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 getBusStops() (*[] query.ISearchable, error) {
|
||||
|
||||
QUERY_FUNC := func() ( io.ReadCloser, error ) {
|
||||
resp, err := http.Get( "https://data.etabus.gov.hk/v1/transport/kmb/stop" )
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Body, nil
|
||||
}
|
||||
|
||||
buff, err := utils.CacheStream( JSON_BUSSTOPS, QUERY_FUNC, 7 * 24 * 3600 )
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
busStopMap, err := readBusStopsData( buff )
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
QUERY_FUNC = func() ( io.ReadCloser, error ) {
|
||||
resp, err := http.Get( "https://data.etabus.gov.hk/v1/transport/kmb/route-stop" )
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Body, nil
|
||||
}
|
||||
|
||||
buff, err = utils.CacheStream( JSON_ROUTESTOPS, QUERY_FUNC, 7 * 24 * 3600 )
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = readRouteStopsData( busStopMap, buff )
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
searchables := [] query.ISearchable{}
|
||||
for _, busStop := range *busStopMap {
|
||||
searchables = append( searchables, busStop )
|
||||
}
|
||||
|
||||
return &searchables, nil
|
||||
}
|
12
datasources/kmb/routestops_test.go
Normal file
12
datasources/kmb/routestops_test.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package kmb
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRouteStops(t *testing.T) {
|
||||
_, err := getBusStops()
|
||||
if err != nil {
|
||||
t.Error( err )
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user