Added kmb and refactored query.Parse

This commit is contained in:
2022-09-17 04:33:47 +08:00
parent 292665c49b
commit 3376d9eb96
21 changed files with 762 additions and 241 deletions

View 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
}

View 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
}

View 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
View 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
}

View File

@@ -0,0 +1,10 @@
package kmb
import (
"fmt"
"testing"
)
func TestQuerySchedule( t *testing.T ) {
fmt.Print( Query( "zh", "大欖" ).Message() )
}

View 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
}

View File

@@ -0,0 +1,12 @@
package kmb
import (
"testing"
)
func TestRouteStops(t *testing.T) {
_, err := getBusStops()
if err != nil {
t.Error( err )
}
}