diff --git a/integration/cmd/oasis/flags.go b/integration/cmd/oasis/flags.go index 4036e558bf1..0ad30efe37b 100644 --- a/integration/cmd/oasis/flags.go +++ b/integration/cmd/oasis/flags.go @@ -11,6 +11,7 @@ var flags struct { tnSearchEndpoint string tnSearchAPIKey string tnSearchAPISignature string + localDataPath string } func init() { @@ -19,5 +20,6 @@ func init() { flag.StringVar(&flags.finderType, "finder", "", "Specify search finder to search for nearby charge stations for given location, use TNSearchFinder or LocalIndexerFinder") flag.StringVar(&flags.tnSearchEndpoint, "search", "", "TN-Search-backend endpoint") flag.StringVar(&flags.tnSearchAPIKey, "searchApiKey", "", "API key for TN-Search-backend") - flag.StringVar(&flags.tnSearchAPISignature, "searchApiSignature", "", "API Signature for TN-Search-backend") + flag.StringVar(&flags.tnSearchAPISignature, "searchApiSignature", "", "API Signature for TN-Search-backend") + flag.StringVar(&flags.localDataPath, "datapath", "", "Local data path for index data") } diff --git a/integration/cmd/oasis/main.go b/integration/cmd/oasis/main.go index 4f47893617f..48175dab3ed 100644 --- a/integration/cmd/oasis/main.go +++ b/integration/cmd/oasis/main.go @@ -14,7 +14,8 @@ func main() { defer glog.Flush() mux := http.NewServeMux() - oasisService, err := oasis.New(flags.osrmBackendEndpoint, flags.finderType, flags.tnSearchEndpoint, flags.tnSearchAPIKey, flags.tnSearchAPISignature) + oasisService, err := oasis.New(flags.osrmBackendEndpoint, flags.finderType, flags.tnSearchEndpoint, + flags.tnSearchAPIKey, flags.tnSearchAPISignature, flags.localDataPath) if err != nil { glog.Errorf("Failed to create oasis handler due to err %+v.\n", err) return diff --git a/integration/service/oasis/handler.go b/integration/service/oasis/handler.go index 437c081011a..cb2f90e13f5 100644 --- a/integration/service/oasis/handler.go +++ b/integration/service/oasis/handler.go @@ -19,7 +19,7 @@ type Handler struct { } // New creates new Handler object -func New(osrmBackend, finderType, searchEndpoint, apiKey, apiSignature string) (*Handler, error) { +func New(osrmBackend, finderType, searchEndpoint, apiKey, apiSignature, dataFolderPath string) (*Handler, error) { // @todo: need make sure connectivity is on and continues available // simple request to guarantee server is alive after init if len(osrmBackend) == 0 { @@ -27,7 +27,7 @@ func New(osrmBackend, finderType, searchEndpoint, apiKey, apiSignature string) ( return nil, err } - finder, err := stationfinder.CreateStationsFinder(finderType, searchEndpoint, apiKey, apiSignature) + finder, err := stationfinder.CreateStationsFinder(finderType, searchEndpoint, apiKey, apiSignature, dataFolderPath) if err != nil { glog.Errorf("Failed in Handler's New() when try to call CreateStationsFinder(), met error = %+v\n", err) return nil, err diff --git a/integration/service/oasis/spatialindexer/interface_mock.go b/integration/service/oasis/spatialindexer/interface_mock.go index 654edda288c..6326d01ecbd 100644 --- a/integration/service/oasis/spatialindexer/interface_mock.go +++ b/integration/service/oasis/spatialindexer/interface_mock.go @@ -1,6 +1,7 @@ package spatialindexer -var mockPlaceInfo1 = []*PointInfo{ +// MockPlaceInfo1 contains 10 PointInfo items +var MockPlaceInfo1 = []*PointInfo{ &PointInfo{ ID: 1, Location: Location{ @@ -78,9 +79,9 @@ type MockFinder struct { } // FindNearByPointIDs returns mock result -// It returns 10 places defined in mockPlaceInfo1 +// It returns 10 places defined in MockPlaceInfo1 func (finder *MockFinder) FindNearByPointIDs(center Location, radius float64, limitCount int) []*PointInfo { - return mockPlaceInfo1 + return MockPlaceInfo1 } // MockPointsIterator implements PointsIterator's interface @@ -89,10 +90,10 @@ type MockPointsIterator struct { // IteratePoints() iterate places with mock data func (iterator *MockPointsIterator) IteratePoints() <-chan PointInfo { - pointInfoC := make(chan PointInfo, len(mockPlaceInfo1)) + pointInfoC := make(chan PointInfo, len(MockPlaceInfo1)) go func() { - for _, item := range mockPlaceInfo1 { + for _, item := range MockPlaceInfo1 { pointInfoC <- *item } diff --git a/integration/service/oasis/stationfinder/cloudfinder/basic_finder.go b/integration/service/oasis/stationfinder/cloudfinder/basic_finder.go index c9ee496c81d..28700fc0d06 100644 --- a/integration/service/oasis/stationfinder/cloudfinder/basic_finder.go +++ b/integration/service/oasis/stationfinder/cloudfinder/basic_finder.go @@ -37,9 +37,9 @@ func (bf *basicFinder) getNearbyChargeStations(req *nearbychargestation.Request) bf.searchRespLock.Unlock() } -func (bf *basicFinder) IterateNearbyStations() <-chan stationfindertype.ChargeStationInfo { +func (bf *basicFinder) IterateNearbyStations() <-chan *stationfindertype.ChargeStationInfo { if bf.searchResp == nil || len(bf.searchResp.Results) == 0 { - c := make(chan stationfindertype.ChargeStationInfo) + c := make(chan *stationfindertype.ChargeStationInfo) go func() { defer close(c) }() @@ -52,7 +52,7 @@ func (bf *basicFinder) IterateNearbyStations() <-chan stationfindertype.ChargeSt copy(results, bf.searchResp.Results) bf.searchRespLock.RUnlock() - c := make(chan stationfindertype.ChargeStationInfo, size) + c := make(chan *stationfindertype.ChargeStationInfo, size) go func() { defer close(c) for _, result := range results { @@ -65,7 +65,7 @@ func (bf *basicFinder) IterateNearbyStations() <-chan stationfindertype.ChargeSt Lat: result.Place.Address[0].GeoCoordinate.Latitude, Lon: result.Place.Address[0].GeoCoordinate.Longitude}, } - c <- station + c <- &station } }() diff --git a/integration/service/oasis/stationfinder/cloudfinder/basic_finder_test.go b/integration/service/oasis/stationfinder/cloudfinder/basic_finder_test.go index f04a65fd939..a280fe942eb 100644 --- a/integration/service/oasis/stationfinder/cloudfinder/basic_finder_test.go +++ b/integration/service/oasis/stationfinder/cloudfinder/basic_finder_test.go @@ -10,29 +10,29 @@ import ( "github.com/Telenav/osrm-backend/integration/service/oasis/stationfinder/stationfindertype" ) -var mockChargeStationInfo1 []stationfindertype.ChargeStationInfo = []stationfindertype.ChargeStationInfo{ - stationfindertype.ChargeStationInfo{ +var mockChargeStationInfo1 = []*stationfindertype.ChargeStationInfo{ + { ID: "station1", Location: nav.Location{ Lat: 32.333, Lon: 122.333, }, }, - stationfindertype.ChargeStationInfo{ + { ID: "station2", Location: nav.Location{ Lat: -32.333, Lon: -122.333, }, }, - stationfindertype.ChargeStationInfo{ + { ID: "station3", Location: nav.Location{ Lat: 32.333, Lon: -122.333, }, }, - stationfindertype.ChargeStationInfo{ + { ID: "station4", Location: nav.Location{ Lat: -32.333, @@ -41,22 +41,22 @@ var mockChargeStationInfo1 []stationfindertype.ChargeStationInfo = []stationfind }, } -var mockChargeStationInfo2 []stationfindertype.ChargeStationInfo = []stationfindertype.ChargeStationInfo{ - stationfindertype.ChargeStationInfo{ +var mockChargeStationInfo2 = []*stationfindertype.ChargeStationInfo{ + { ID: "station1", Location: nav.Location{ Lat: 32.333, Lon: 122.333, }, }, - stationfindertype.ChargeStationInfo{ + { ID: "station2", Location: nav.Location{ Lat: -32.333, Lon: -122.333, }, }, - stationfindertype.ChargeStationInfo{ + { ID: "station5", Location: nav.Location{ Lat: -12.333, @@ -65,15 +65,15 @@ var mockChargeStationInfo2 []stationfindertype.ChargeStationInfo = []stationfind }, } -var mockChargeStationInfo3 []stationfindertype.ChargeStationInfo = []stationfindertype.ChargeStationInfo{ - stationfindertype.ChargeStationInfo{ +var mockChargeStationInfo3 = []*stationfindertype.ChargeStationInfo{ + { ID: "station6", Location: nav.Location{ Lat: 30.333, Lon: 122.333, }, }, - stationfindertype.ChargeStationInfo{ + { ID: "station7", Location: nav.Location{ Lat: -10.333, @@ -85,7 +85,7 @@ var mockChargeStationInfo3 []stationfindertype.ChargeStationInfo = []stationfind func TestBasicFinderCorrectness(t *testing.T) { cases := []struct { input []*nearbychargestation.Result - expect []stationfindertype.ChargeStationInfo + expect []*stationfindertype.ChargeStationInfo }{ { nearbychargestation.MockSearchResponse1.Results, @@ -105,7 +105,7 @@ func TestBasicFinderCorrectness(t *testing.T) { wg.Add(1) defer wg.Done() - var r []stationfindertype.ChargeStationInfo + var r []*stationfindertype.ChargeStationInfo for item := range c { r = append(r, item) } @@ -122,7 +122,7 @@ func TestBasicFinderAsync(t *testing.T) { cases := []struct { input []*nearbychargestation.Result inputLock *sync.RWMutex - expect []stationfindertype.ChargeStationInfo + expect []*stationfindertype.ChargeStationInfo }{ { nearbychargestation.MockSearchResponse1.Results, @@ -145,7 +145,7 @@ func TestBasicFinderAsync(t *testing.T) { c := bf.IterateNearbyStations() go func(wg *sync.WaitGroup) { defer wg.Done() - var r []stationfindertype.ChargeStationInfo + var r []*stationfindertype.ChargeStationInfo for item := range c { r = append(r, item) } diff --git a/integration/service/oasis/stationfinder/cloudfinder/dest_station_finder.go b/integration/service/oasis/stationfinder/cloudfinder/dest_station_finder.go index 5db78616333..223d007a379 100644 --- a/integration/service/oasis/stationfinder/cloudfinder/dest_station_finder.go +++ b/integration/service/oasis/stationfinder/cloudfinder/dest_station_finder.go @@ -43,6 +43,6 @@ func (sf *destStationFinder) prepare() { return } -func (sf *destStationFinder) IterateNearbyStations() <-chan stationfindertype.ChargeStationInfo { +func (sf *destStationFinder) IterateNearbyStations() <-chan *stationfindertype.ChargeStationInfo { return sf.bf.IterateNearbyStations() } diff --git a/integration/service/oasis/stationfinder/cloudfinder/dest_station_finder_test.go b/integration/service/oasis/stationfinder/cloudfinder/dest_station_finder_test.go index 4884a4f150f..2c22d1b3412 100644 --- a/integration/service/oasis/stationfinder/cloudfinder/dest_station_finder_test.go +++ b/integration/service/oasis/stationfinder/cloudfinder/dest_station_finder_test.go @@ -10,7 +10,7 @@ import ( func TestDestStationFinderIterator(t *testing.T) { sf := CreateMockDestStationFinder1() c := sf.IterateNearbyStations() - var r []stationfindertype.ChargeStationInfo + var r []*stationfindertype.ChargeStationInfo go func() { for item := range c { r = append(r, item) diff --git a/integration/service/oasis/stationfinder/cloudfinder/doc.go b/integration/service/oasis/stationfinder/cloudfinder/doc.go new file mode 100644 index 00000000000..0d891fa0329 --- /dev/null +++ b/integration/service/oasis/stationfinder/cloudfinder/doc.go @@ -0,0 +1,4 @@ +/* +Package cloudfinder provides spatial query based on Telenav's cloud web service. +*/ +package cloudfinder diff --git a/integration/service/oasis/stationfinder/cloudfinder/low_energy_location_station_finder.go b/integration/service/oasis/stationfinder/cloudfinder/low_energy_location_station_finder.go index 220130ae7db..0836b15737f 100644 --- a/integration/service/oasis/stationfinder/cloudfinder/low_energy_location_station_finder.go +++ b/integration/service/oasis/stationfinder/cloudfinder/low_energy_location_station_finder.go @@ -8,7 +8,8 @@ import ( "github.com/Telenav/osrm-backend/integration/service/oasis/stationfinder/stationfindertype" ) -const lowEnergyLocationCandidateNumber = 20 +// LowEnergyLocationCandidateNumber indicates how much charge station to be searched for low energy point +const LowEnergyLocationCandidateNumber = 20 type lowEnergyLocationStationFinder struct { location *nav.Location @@ -29,12 +30,12 @@ func (sf *lowEnergyLocationStationFinder) prepare() { searchcoordinate.Coordinate{ Lat: sf.location.Lat, Lon: sf.location.Lon}, - lowEnergyLocationCandidateNumber, + LowEnergyLocationCandidateNumber, -1) sf.bf.getNearbyChargeStations(req) return } -func (sf *lowEnergyLocationStationFinder) IterateNearbyStations() <-chan stationfindertype.ChargeStationInfo { +func (sf *lowEnergyLocationStationFinder) IterateNearbyStations() <-chan *stationfindertype.ChargeStationInfo { return sf.bf.IterateNearbyStations() } diff --git a/integration/service/oasis/stationfinder/cloudfinder/low_energy_location_station_finder_test.go b/integration/service/oasis/stationfinder/cloudfinder/low_energy_location_station_finder_test.go index 4bc453589ab..4d5a6aa3dd3 100644 --- a/integration/service/oasis/stationfinder/cloudfinder/low_energy_location_station_finder_test.go +++ b/integration/service/oasis/stationfinder/cloudfinder/low_energy_location_station_finder_test.go @@ -17,7 +17,7 @@ func TestLowEnergyLocationStationFinderIterator1(t *testing.T) { defer wg.Done() c := sf.IterateNearbyStations() - var r []stationfindertype.ChargeStationInfo + var r []*stationfindertype.ChargeStationInfo for item := range c { r = append(r, item) @@ -37,7 +37,7 @@ func TestLowEnergyLocationStationFinderIterator2(t *testing.T) { defer wg.Done() c := sf.IterateNearbyStations() - var r []stationfindertype.ChargeStationInfo + var r []*stationfindertype.ChargeStationInfo for item := range c { r = append(r, item) } @@ -56,7 +56,7 @@ func TestLowEnergyLocationStationFinderIterator3(t *testing.T) { defer wg.Done() c := sf.IterateNearbyStations() - var r []stationfindertype.ChargeStationInfo + var r []*stationfindertype.ChargeStationInfo for item := range c { r = append(r, item) } diff --git a/integration/service/oasis/stationfinder/cloudfinder/orig_station_finder.go b/integration/service/oasis/stationfinder/cloudfinder/orig_station_finder.go index af910363d7a..be2e9c5b039 100644 --- a/integration/service/oasis/stationfinder/cloudfinder/orig_station_finder.go +++ b/integration/service/oasis/stationfinder/cloudfinder/orig_station_finder.go @@ -37,6 +37,6 @@ func (sf *origStationFinder) prepare() { return } -func (sf *origStationFinder) IterateNearbyStations() <-chan stationfindertype.ChargeStationInfo { +func (sf *origStationFinder) IterateNearbyStations() <-chan *stationfindertype.ChargeStationInfo { return sf.bf.IterateNearbyStations() } diff --git a/integration/service/oasis/stationfinder/cloudfinder/orig_station_finder_test.go b/integration/service/oasis/stationfinder/cloudfinder/orig_station_finder_test.go index f8951291d03..d53673d704b 100644 --- a/integration/service/oasis/stationfinder/cloudfinder/orig_station_finder_test.go +++ b/integration/service/oasis/stationfinder/cloudfinder/orig_station_finder_test.go @@ -10,7 +10,7 @@ import ( func TestOrigStationFinderIterator(t *testing.T) { sf := CreateMockOrigStationFinder1() c := sf.IterateNearbyStations() - var r []stationfindertype.ChargeStationInfo + var r []*stationfindertype.ChargeStationInfo isdoneC := make(chan bool) go func() { diff --git a/integration/service/oasis/stationfinder/cloudfinder/tnsearch_station_finder.go b/integration/service/oasis/stationfinder/cloudfinder/tnsearch_station_finder.go index e753e5c965d..569952c9578 100644 --- a/integration/service/oasis/stationfinder/cloudfinder/tnsearch_station_finder.go +++ b/integration/service/oasis/stationfinder/cloudfinder/tnsearch_station_finder.go @@ -7,28 +7,28 @@ import ( "github.com/Telenav/osrm-backend/integration/service/oasis/stationfinder/stationfindertype" ) -type tnSearchStationFinder struct { +type cloudStationFinder struct { sc *searchconnector.TNSearchConnector } // New creates finder based on telenav search web service -func New(sc *searchconnector.TNSearchConnector) *tnSearchStationFinder { - return &tnSearchStationFinder{ +func New(sc *searchconnector.TNSearchConnector) *cloudStationFinder { + return &cloudStationFinder{ sc: sc, } } // NewOrigStationFinder creates finder to search for nearby charge stations near orig based on telenav search -func (finder *tnSearchStationFinder) NewOrigStationFinder(oasisReq *oasis.Request) stationfindertype.NearbyStationsIterator { +func (finder *cloudStationFinder) NewOrigStationFinder(oasisReq *oasis.Request) stationfindertype.NearbyStationsIterator { return NewOrigStationFinder(finder.sc, oasisReq) } // NewDestStationFinder creates finder to search for nearby charge stations near destination based on telenav search -func (finder *tnSearchStationFinder) NewDestStationFinder(oasisReq *oasis.Request) stationfindertype.NearbyStationsIterator { +func (finder *cloudStationFinder) NewDestStationFinder(oasisReq *oasis.Request) stationfindertype.NearbyStationsIterator { return NewDestStationFinder(finder.sc, oasisReq) } // NewLowEnergyLocationStationFinder creates finder to search for nearby charge stations when energy is low based on telenav search -func (finder *tnSearchStationFinder) NewLowEnergyLocationStationFinder(location *nav.Location) stationfindertype.NearbyStationsIterator { +func (finder *cloudStationFinder) NewLowEnergyLocationStationFinder(location *nav.Location) stationfindertype.NearbyStationsIterator { return NewLowEnergyLocationStationFinder(finder.sc, location) } diff --git a/integration/service/oasis/stationfinder/interface.go b/integration/service/oasis/stationfinder/interface.go index 3f81d0de5f4..f5ba44fe273 100644 --- a/integration/service/oasis/stationfinder/interface.go +++ b/integration/service/oasis/stationfinder/interface.go @@ -23,7 +23,7 @@ type StationFinder interface { type Algorithm interface { // FindOverlapBetweenStations finds overlap charge stations based on two iterator FindOverlapBetweenStations(iterF stationfindertype.NearbyStationsIterator, - iterS stationfindertype.NearbyStationsIterator) []stationfindertype.ChargeStationInfo + iterS stationfindertype.NearbyStationsIterator) []*stationfindertype.ChargeStationInfo // CalcWeightBetweenChargeStationsPair accepts two iterators and calculates weights between each pair of iterators CalcWeightBetweenChargeStationsPair(from stationfindertype.NearbyStationsIterator, diff --git a/integration/service/oasis/stationfinder/localfinder/basic_local_finder.go b/integration/service/oasis/stationfinder/localfinder/basic_local_finder.go new file mode 100644 index 00000000000..f6b15cc280d --- /dev/null +++ b/integration/service/oasis/stationfinder/localfinder/basic_local_finder.go @@ -0,0 +1,83 @@ +package localfinder + +import ( + "strconv" + + "github.com/Telenav/osrm-backend/integration/pkg/api/nav" + "github.com/Telenav/osrm-backend/integration/service/oasis/spatialindexer" + "github.com/Telenav/osrm-backend/integration/service/oasis/stationfinder/stationfindertype" + "github.com/golang/glog" +) + +const defaultIteratorCount = 5 +const defaultChargeStaionChannelSize = 500 + +type basicLocalFinder struct { + localFinder spatialindexer.Finder + placesInfo []*spatialindexer.PointInfo + requests chan chan *stationfindertype.ChargeStationInfo + stop chan bool +} + +func newBasicLocalFinder(localFinder spatialindexer.Finder) *basicLocalFinder { + bf := &basicLocalFinder{ + localFinder: localFinder, + requests: make(chan chan *stationfindertype.ChargeStationInfo, defaultIteratorCount), + stop: make(chan bool), + } + go bf.serveRequest() + return bf +} + +func (bf *basicLocalFinder) getNearbyChargeStations(center spatialindexer.Location, radius float64) { + bf.placesInfo = bf.localFinder.FindNearByPointIDs(center, radius, spatialindexer.UnlimitedCount) +} + +func (bf *basicLocalFinder) serveRequest() { + stopServe := false + + for bf.requests != nil && bf.stop != nil { + select { + case c := <-bf.requests: + for _, placeInfo := range bf.placesInfo { + c <- &stationfindertype.ChargeStationInfo{ + ID: strconv.FormatInt((int64)(placeInfo.ID), 10), + Location: nav.Location{ + Lat: placeInfo.Location.Lat, + Lon: placeInfo.Location.Lon, + }, + } + } + close(c) + + if stopServe == true && len(bf.requests) == 0 { + close(bf.requests) + bf.requests = nil + } + + case stopServe = <-bf.stop: + bf.stop = nil + } + } + +} + +// IterateNearbyStations returns channel contains near by stations +func (bf *basicLocalFinder) IterateNearbyStations() <-chan *stationfindertype.ChargeStationInfo { + c := make(chan *stationfindertype.ChargeStationInfo, defaultChargeStaionChannelSize) + if bf.requests != nil { + bf.requests <- c + } else { + glog.Warning("Call iterator on Stopped Finder, please check your logic.\n") + close(c) + } + + return c +} + +// Stop stops functionality of finder +func (bf *basicLocalFinder) Stop() { + if bf.stop != nil { + bf.stop <- true + } +} diff --git a/integration/service/oasis/stationfinder/localfinder/basic_local_finder_test.go b/integration/service/oasis/stationfinder/localfinder/basic_local_finder_test.go new file mode 100644 index 00000000000..63a72fcf291 --- /dev/null +++ b/integration/service/oasis/stationfinder/localfinder/basic_local_finder_test.go @@ -0,0 +1,49 @@ +package localfinder + +import ( + "reflect" + "testing" + + "github.com/Telenav/osrm-backend/integration/service/oasis/spatialindexer" + "github.com/Telenav/osrm-backend/integration/service/oasis/stationfinder/stationfindertype" +) + +func TestSingleIterator4BasicLocalFinder(t *testing.T) { + localFinder := newBasicLocalFinder(nil) + defer localFinder.Stop() + + mockFinder := spatialindexer.MockFinder{} + localFinder.placesInfo = mockFinder.FindNearByPointIDs(spatialindexer.Location{}, 0, 0) + + iterC := localFinder.IterateNearbyStations() + actual := make([]*stationfindertype.ChargeStationInfo, 0, len(stationfindertype.MockChargeStationInfo1)) + for item := range iterC { + actual = append(actual, item) + } + + if !reflect.DeepEqual(actual, stationfindertype.MockChargeStationInfo1) { + t.Errorf("Incorrect iterator result expect \n%#v\n but got \n%#v\n", stationfindertype.MockChargeStationInfo1, actual) + } + +} + +func TestMultipleIterator4BasicLocalFinder(t *testing.T) { + localFinder := newBasicLocalFinder(nil) + defer localFinder.Stop() + + mockFinder := spatialindexer.MockFinder{} + localFinder.placesInfo = mockFinder.FindNearByPointIDs(spatialindexer.Location{}, 0, 0) + + for i := 0; i < 3; i++ { + iterC := localFinder.IterateNearbyStations() + actual := make([]*stationfindertype.ChargeStationInfo, 0, len(stationfindertype.MockChargeStationInfo1)) + for item := range iterC { + actual = append(actual, item) + } + + if !reflect.DeepEqual(actual, stationfindertype.MockChargeStationInfo1) { + t.Errorf("Incorrect iterator result expect \n%#v\n but got \n%#v\n", stationfindertype.MockChargeStationInfo1, actual) + } + } + +} diff --git a/integration/service/oasis/stationfinder/localfinder/dest_station_local_finder.go b/integration/service/oasis/stationfinder/localfinder/dest_station_local_finder.go new file mode 100644 index 00000000000..0c081edd0e0 --- /dev/null +++ b/integration/service/oasis/stationfinder/localfinder/dest_station_local_finder.go @@ -0,0 +1,41 @@ +package localfinder + +import ( + "github.com/Telenav/osrm-backend/integration/pkg/api/oasis" + "github.com/Telenav/osrm-backend/integration/service/oasis/spatialindexer" + "github.com/Telenav/osrm-backend/integration/service/oasis/stationfinder/stationfindertype" + "github.com/golang/glog" +) + +type destStationLocalFinder struct { + basicFinder *basicLocalFinder +} + +func newDestStationFinder(localFinder spatialindexer.Finder, oasisReq *oasis.Request) *destStationLocalFinder { + if len(oasisReq.Coordinates) != 2 { + glog.Errorf("Try to create newOrigStationFinder use incorrect oasis request, len(oasisReq.Coordinates) should be 2 but got %d.\n", len(oasisReq.Coordinates)) + return nil + } + if oasisReq.MaxRange <= oasisReq.SafeLevel { + glog.Errorf("Try to create newOrigStationFinder use incorrect oasis request, SafeLevel should be smaller than MaxRange.\n") + return nil + } + + obj := &destStationLocalFinder{ + basicFinder: newBasicLocalFinder(localFinder), + } + obj.basicFinder.getNearbyChargeStations(spatialindexer.Location{ + Lat: oasisReq.Coordinates[1].Lat, + Lon: oasisReq.Coordinates[1].Lon}, + oasisReq.MaxRange-oasisReq.SafeLevel) + + return obj +} + +func (localFinder *destStationLocalFinder) IterateNearbyStations() <-chan *stationfindertype.ChargeStationInfo { + return localFinder.basicFinder.IterateNearbyStations() +} + +func (localFinder *destStationLocalFinder) Stop() { + localFinder.basicFinder.Stop() +} diff --git a/integration/service/oasis/stationfinder/localfinder/doc.go b/integration/service/oasis/stationfinder/localfinder/doc.go new file mode 100644 index 00000000000..a32d3d87422 --- /dev/null +++ b/integration/service/oasis/stationfinder/localfinder/doc.go @@ -0,0 +1,4 @@ +/* +Package localfinder provides spatial query based on prebuild spatial index which is recorded on local. +*/ +package localfinder diff --git a/integration/service/oasis/stationfinder/localfinder/local_station_finder.go b/integration/service/oasis/stationfinder/localfinder/local_station_finder.go new file mode 100644 index 00000000000..554e4c4b1c7 --- /dev/null +++ b/integration/service/oasis/stationfinder/localfinder/local_station_finder.go @@ -0,0 +1,34 @@ +package localfinder + +import ( + "github.com/Telenav/osrm-backend/integration/pkg/api/nav" + "github.com/Telenav/osrm-backend/integration/pkg/api/oasis" + "github.com/Telenav/osrm-backend/integration/service/oasis/spatialindexer" + "github.com/Telenav/osrm-backend/integration/service/oasis/stationfinder/stationfindertype" +) + +type localStationFinder struct { + localFinder spatialindexer.Finder +} + +// New creates finder based on telenav search web service +func New(localFinder spatialindexer.Finder) *localStationFinder { + return &localStationFinder{ + localFinder: localFinder, + } +} + +// NewOrigStationFinder creates finder to search for nearby charge stations near orig based on telenav search +func (finder *localStationFinder) NewOrigStationFinder(oasisReq *oasis.Request) stationfindertype.NearbyStationsIterator { + return newOrigStationFinder(finder.localFinder, oasisReq) +} + +// NewDestStationFinder creates finder to search for nearby charge stations near destination based on telenav search +func (finder *localStationFinder) NewDestStationFinder(oasisReq *oasis.Request) stationfindertype.NearbyStationsIterator { + return newDestStationFinder(finder.localFinder, oasisReq) +} + +// NewLowEnergyLocationStationFinder creates finder to search for nearby charge stations when energy is low based on telenav search +func (finder *localStationFinder) NewLowEnergyLocationStationFinder(location *nav.Location) stationfindertype.NearbyStationsIterator { + return newLowEnergyLocationLocalFinder(finder.localFinder, location) +} diff --git a/integration/service/oasis/stationfinder/localfinder/low_energy_location_local_finder.go b/integration/service/oasis/stationfinder/localfinder/low_energy_location_local_finder.go new file mode 100644 index 00000000000..843779b7d94 --- /dev/null +++ b/integration/service/oasis/stationfinder/localfinder/low_energy_location_local_finder.go @@ -0,0 +1,34 @@ +package localfinder + +import ( + "github.com/Telenav/osrm-backend/integration/pkg/api/nav" + "github.com/Telenav/osrm-backend/integration/service/oasis/spatialindexer" + "github.com/Telenav/osrm-backend/integration/service/oasis/stationfinder/cloudfinder" + "github.com/Telenav/osrm-backend/integration/service/oasis/stationfinder/stationfindertype" +) + +type lowEnergyLocationLocalFinder struct { + basicFinder *basicLocalFinder +} + +func newLowEnergyLocationLocalFinder(localFinder spatialindexer.Finder, location *nav.Location) *lowEnergyLocationLocalFinder { + + obj := &lowEnergyLocationLocalFinder{ + basicFinder: newBasicLocalFinder(localFinder), + } + obj.basicFinder.getNearbyChargeStations(spatialindexer.Location{ + Lat: location.Lat, + Lon: location.Lon}, + cloudfinder.LowEnergyLocationCandidateNumber) + + return obj + +} + +func (localFinder *lowEnergyLocationLocalFinder) IterateNearbyStations() <-chan *stationfindertype.ChargeStationInfo { + return localFinder.basicFinder.IterateNearbyStations() +} + +func (localFinder *lowEnergyLocationLocalFinder) Stop() { + localFinder.basicFinder.Stop() +} diff --git a/integration/service/oasis/stationfinder/localfinder/orig_station_local_finder.go b/integration/service/oasis/stationfinder/localfinder/orig_station_local_finder.go new file mode 100644 index 00000000000..1e1b8955bc3 --- /dev/null +++ b/integration/service/oasis/stationfinder/localfinder/orig_station_local_finder.go @@ -0,0 +1,36 @@ +package localfinder + +import ( + "github.com/Telenav/osrm-backend/integration/pkg/api/oasis" + "github.com/Telenav/osrm-backend/integration/service/oasis/spatialindexer" + "github.com/Telenav/osrm-backend/integration/service/oasis/stationfinder/stationfindertype" + "github.com/golang/glog" +) + +type origStationLocalFinder struct { + basicFinder *basicLocalFinder +} + +func newOrigStationFinder(localFinder spatialindexer.Finder, oasisReq *oasis.Request) *origStationLocalFinder { + if len(oasisReq.Coordinates) != 2 { + glog.Errorf("Incorrect oasis request pass into newOrigStationFinder, len(oasisReq.Coordinates) should be 2 but got %d.\n", len(oasisReq.Coordinates)) + } + + obj := &origStationLocalFinder{ + basicFinder: newBasicLocalFinder(localFinder), + } + obj.basicFinder.getNearbyChargeStations(spatialindexer.Location{ + Lat: oasisReq.Coordinates[0].Lat, + Lon: oasisReq.Coordinates[0].Lon}, + oasisReq.CurrRange) + + return obj +} + +func (localFinder *origStationLocalFinder) IterateNearbyStations() <-chan *stationfindertype.ChargeStationInfo { + return localFinder.basicFinder.IterateNearbyStations() +} + +func (localFinder *origStationLocalFinder) Stop() { + localFinder.basicFinder.Stop() +} diff --git a/integration/service/oasis/stationfinder/station_finder_factory.go b/integration/service/oasis/stationfinder/station_finder_factory.go index b77605ad2ec..e482a97158b 100644 --- a/integration/service/oasis/stationfinder/station_finder_factory.go +++ b/integration/service/oasis/stationfinder/station_finder_factory.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/Telenav/osrm-backend/integration/service/oasis/searchconnector" + "github.com/Telenav/osrm-backend/integration/service/oasis/spatialindexer/s2indexer" "github.com/Telenav/osrm-backend/integration/service/oasis/stationfinder/cloudfinder" "github.com/golang/glog" ) @@ -17,16 +18,25 @@ const ( ) // CreateStationsFinder creates finder which implements StationFinder interface -func CreateStationsFinder(finderType, searchEndpoint, apiKey, apiSignature string) (StationFinder, error) { - if err := checkInput(finderType, searchEndpoint, apiKey, apiSignature); err != nil { +func CreateStationsFinder(finderType, searchEndpoint, apiKey, apiSignature, dataFolderPath string) (StationFinder, error) { + if err := checkInput(finderType, searchEndpoint, apiKey, apiSignature, dataFolderPath); err != nil { return nil, err } switch finderType { + case TNSearchFinder: searchFinder := searchconnector.NewTNSearchConnector(searchEndpoint, apiKey, apiSignature) return cloudfinder.New(searchFinder), nil + + case LocalIndexerFinder: + localIndex := s2indexer.NewS2Indexer().Load(dataFolderPath) + if localIndex == nil { + err := fmt.Errorf("failed to load s2Indexer") + return nil, err + } } + return nil, nil } @@ -35,7 +45,7 @@ func isValidStationFinderType(finderType string) bool { return finderType == TNSearchFinder || finderType == LocalIndexerFinder } -func checkInput(finderType, searchEndpoint, apiKey, apiSignature string) error { +func checkInput(finderType, searchEndpoint, apiKey, apiSignature, dataFolderPath string) error { if !isValidStationFinderType(finderType) { glog.Error("Try to create finder not implemented yet, can only choose TNSearchFinder or LocalFinder for now.\n") err := fmt.Errorf("invalid station finder type") @@ -50,5 +60,11 @@ func checkInput(finderType, searchEndpoint, apiKey, apiSignature string) error { return err } + if finderType == LocalIndexerFinder && + len(dataFolderPath) == 0 { + err := fmt.Errorf("empty input for local index") + return err + } + return nil } diff --git a/integration/service/oasis/stationfinder/stationfinderalg/dest_iterator.go b/integration/service/oasis/stationfinder/stationfinderalg/dest_iterator.go index da4feca890c..8082955649f 100644 --- a/integration/service/oasis/stationfinder/stationfinderalg/dest_iterator.go +++ b/integration/service/oasis/stationfinder/stationfinderalg/dest_iterator.go @@ -17,8 +17,8 @@ func NewDestIter(location *nav.Location) *destIterator { } } -func (di *destIterator) IterateNearbyStations() <-chan stationfindertype.ChargeStationInfo { - c := make(chan stationfindertype.ChargeStationInfo, 1) +func (di *destIterator) IterateNearbyStations() <-chan *stationfindertype.ChargeStationInfo { + c := make(chan *stationfindertype.ChargeStationInfo, 1) go func() { defer close(c) @@ -26,7 +26,7 @@ func (di *destIterator) IterateNearbyStations() <-chan stationfindertype.ChargeS ID: stationfindertype.DestLocationID, Location: *di.location, } - c <- station + c <- &station }() return c diff --git a/integration/service/oasis/stationfinder/stationfinderalg/orig_iterator.go b/integration/service/oasis/stationfinder/stationfinderalg/orig_iterator.go index 2574be325a5..7cb289addc3 100644 --- a/integration/service/oasis/stationfinder/stationfinderalg/orig_iterator.go +++ b/integration/service/oasis/stationfinder/stationfinderalg/orig_iterator.go @@ -17,8 +17,8 @@ func NewOrigIter(location *nav.Location) *origIterator { } } -func (oi *origIterator) IterateNearbyStations() <-chan stationfindertype.ChargeStationInfo { - c := make(chan stationfindertype.ChargeStationInfo, 1) +func (oi *origIterator) IterateNearbyStations() <-chan *stationfindertype.ChargeStationInfo { + c := make(chan *stationfindertype.ChargeStationInfo, 1) go func() { defer close(c) @@ -26,7 +26,7 @@ func (oi *origIterator) IterateNearbyStations() <-chan stationfindertype.ChargeS ID: stationfindertype.OrigLocationID, Location: *oi.location, } - c <- station + c <- &station }() return c diff --git a/integration/service/oasis/stationfinder/stationfinderalg/stations_iterator_alg.go b/integration/service/oasis/stationfinder/stationfinderalg/stations_iterator_alg.go index 362b5af2ae5..b61615c86f4 100644 --- a/integration/service/oasis/stationfinder/stationfinderalg/stations_iterator_alg.go +++ b/integration/service/oasis/stationfinder/stationfinderalg/stations_iterator_alg.go @@ -14,8 +14,8 @@ import ( ) // FindOverlapBetweenStations finds overlap charge stations based on two iterator -func FindOverlapBetweenStations(iterF stationfindertype.NearbyStationsIterator, iterS stationfindertype.NearbyStationsIterator) []stationfindertype.ChargeStationInfo { - var overlap []stationfindertype.ChargeStationInfo +func FindOverlapBetweenStations(iterF stationfindertype.NearbyStationsIterator, iterS stationfindertype.NearbyStationsIterator) []*stationfindertype.ChargeStationInfo { + var overlap []*stationfindertype.ChargeStationInfo dict := buildChargeStationInfoDict(iterF) c := iterS.IterateNearbyStations() for item := range c { diff --git a/integration/service/oasis/stationfinder/stationfinderalg/stations_iterator_alg_test.go b/integration/service/oasis/stationfinder/stationfinderalg/stations_iterator_alg_test.go index 22c1a8de545..e8ae97aab18 100644 --- a/integration/service/oasis/stationfinder/stationfinderalg/stations_iterator_alg_test.go +++ b/integration/service/oasis/stationfinder/stationfinderalg/stations_iterator_alg_test.go @@ -34,15 +34,15 @@ func TestBuildChargeStationInfoDict1(t *testing.T) { } } -var overlapChargeStationInfo1 []stationfindertype.ChargeStationInfo = []stationfindertype.ChargeStationInfo{ - stationfindertype.ChargeStationInfo{ +var overlapChargeStationInfo1 = []*stationfindertype.ChargeStationInfo{ + { ID: "station1", Location: nav.Location{ Lat: 32.333, Lon: 122.333, }, }, - stationfindertype.ChargeStationInfo{ + { ID: "station2", Location: nav.Location{ Lat: -32.333, @@ -282,7 +282,7 @@ func TestCalculateWeightBetweenNeighbors(t *testing.T) { oc := osrmconnector.NewOSRMConnector(ts.URL) // create finder based on fake TNSearchService - finder, err := stationfinder.CreateStationsFinder(stationfinder.TNSearchFinder, ts.URL, "apikey", "apisignature") + finder, err := stationfinder.CreateStationsFinder(stationfinder.TNSearchFinder, ts.URL, "apikey", "apisignature", "") if err != nil { t.Errorf("Failed to create station finder during TestCalculateWeightBetweenNeighbors with error = %+v.\n", err) } diff --git a/integration/service/oasis/stationfinder/stationfindertype/type.go b/integration/service/oasis/stationfinder/stationfindertype/type.go index 3205a70fa5d..fe31db05436 100644 --- a/integration/service/oasis/stationfinder/stationfindertype/type.go +++ b/integration/service/oasis/stationfinder/stationfindertype/type.go @@ -5,7 +5,7 @@ import "github.com/Telenav/osrm-backend/integration/pkg/api/nav" // NearbyStationsIterator provide interator for near by stations type NearbyStationsIterator interface { // IterateNearbyStations returns a channel which contains near by charge station under certain conditions - IterateNearbyStations() <-chan ChargeStationInfo + IterateNearbyStations() <-chan *ChargeStationInfo } // ChargeStationInfo defines charge station information diff --git a/integration/service/oasis/stationfinder/stationfindertype/type_mock.go b/integration/service/oasis/stationfinder/stationfindertype/type_mock.go new file mode 100644 index 00000000000..4ca6e16bf7f --- /dev/null +++ b/integration/service/oasis/stationfinder/stationfindertype/type_mock.go @@ -0,0 +1,92 @@ +package stationfindertype + +import ( + "strconv" + + "github.com/Telenav/osrm-backend/integration/pkg/api/nav" + "github.com/Telenav/osrm-backend/integration/service/oasis/spatialindexer" +) + +// MockChargeStationInfo1 mocks array of *ChargeStationInfo which is compatible with spatialindexer.MockPlaceInfo1 +var MockChargeStationInfo1 = []*ChargeStationInfo{ + { + ID: strconv.FormatInt((int64)(spatialindexer.MockPlaceInfo1[0].ID), 10), + Location: nav.Location{ + Lat: spatialindexer.MockPlaceInfo1[0].Location.Lat, + Lon: spatialindexer.MockPlaceInfo1[0].Location.Lon, + }, + err: nil, + }, + { + ID: strconv.FormatInt((int64)(spatialindexer.MockPlaceInfo1[1].ID), 10), + Location: nav.Location{ + Lat: spatialindexer.MockPlaceInfo1[1].Location.Lat, + Lon: spatialindexer.MockPlaceInfo1[1].Location.Lon, + }, + err: nil, + }, + { + ID: strconv.FormatInt((int64)(spatialindexer.MockPlaceInfo1[2].ID), 10), + Location: nav.Location{ + Lat: spatialindexer.MockPlaceInfo1[2].Location.Lat, + Lon: spatialindexer.MockPlaceInfo1[2].Location.Lon, + }, + err: nil, + }, + { + ID: strconv.FormatInt((int64)(spatialindexer.MockPlaceInfo1[3].ID), 10), + Location: nav.Location{ + Lat: spatialindexer.MockPlaceInfo1[3].Location.Lat, + Lon: spatialindexer.MockPlaceInfo1[3].Location.Lon, + }, + err: nil, + }, + { + ID: strconv.FormatInt((int64)(spatialindexer.MockPlaceInfo1[4].ID), 10), + Location: nav.Location{ + Lat: spatialindexer.MockPlaceInfo1[4].Location.Lat, + Lon: spatialindexer.MockPlaceInfo1[4].Location.Lon, + }, + err: nil, + }, + { + ID: strconv.FormatInt((int64)(spatialindexer.MockPlaceInfo1[5].ID), 10), + Location: nav.Location{ + Lat: spatialindexer.MockPlaceInfo1[5].Location.Lat, + Lon: spatialindexer.MockPlaceInfo1[5].Location.Lon, + }, + err: nil, + }, + { + ID: strconv.FormatInt((int64)(spatialindexer.MockPlaceInfo1[6].ID), 10), + Location: nav.Location{ + Lat: spatialindexer.MockPlaceInfo1[6].Location.Lat, + Lon: spatialindexer.MockPlaceInfo1[6].Location.Lon, + }, + err: nil, + }, + { + ID: strconv.FormatInt((int64)(spatialindexer.MockPlaceInfo1[7].ID), 10), + Location: nav.Location{ + Lat: spatialindexer.MockPlaceInfo1[7].Location.Lat, + Lon: spatialindexer.MockPlaceInfo1[7].Location.Lon, + }, + err: nil, + }, + { + ID: strconv.FormatInt((int64)(spatialindexer.MockPlaceInfo1[8].ID), 10), + Location: nav.Location{ + Lat: spatialindexer.MockPlaceInfo1[8].Location.Lat, + Lon: spatialindexer.MockPlaceInfo1[8].Location.Lon, + }, + err: nil, + }, + { + ID: strconv.FormatInt((int64)(spatialindexer.MockPlaceInfo1[9].ID), 10), + Location: nav.Location{ + Lat: spatialindexer.MockPlaceInfo1[9].Location.Lat, + Lon: spatialindexer.MockPlaceInfo1[9].Location.Lon, + }, + err: nil, + }, +}