penguin/golifehk

@golifehk bot in Telegram

datasources/kmb/routestops.go

raw ยท 3547 bytes

package kmb

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"path/filepath"

	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) (*[]*RouteStop, error) {

	routeStopsData := RouteStops{}
	err := json.Unmarshal(buff.Bytes(), &routeStopsData)
	if err != nil {
		return nil, err
	}

	// routeStops[ Route ][ ServiceType ][ Direction ][ Seq ] = RouteStop
	routeStops := map[string]*map[string]*map[string]*map[int]*RouteStop{}
	allRouteStops := []*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
		}
		allRouteStops = append(allRouteStops, entry)
	}

	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

	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)
		return err
	}

	cs, err := utils.CacheStreamEx(JSON_BUSSTOPS, QUERY_FUNC)
	if err != nil {
		return nil, err
	}

	err = cs.Try(PARSE_FUNC, 7*24*3600, 3)
	if err != nil {
		return nil, err
	}

	var routeStops *[]*RouteStop
	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 {
		var err error
		routeStops, err = readRouteStopsData(busStopMap, buff)
		return err
	}

	cs, err = utils.CacheStreamEx(JSON_ROUTESTOPS, QUERY_FUNC)
	if err != nil {
		return nil, err
	}

	err = cs.Try(PARSE_FUNC, 7*24*3600, 3)
	if err != nil {
		return nil, err
	}

	searchables := []query.ISearchable{}
	for _, routeStop := range *routeStops {
		searchables = append(searchables, routeStop)
		routeStop.Reload()
	}

	return &searchables, nil
}