initial commit
This commit is contained in:
commit
5f63e312c9
|
@ -0,0 +1,4 @@
|
|||
config.yaml
|
||||
.env
|
||||
.vscode
|
||||
__debug_bin
|
|
@ -0,0 +1,32 @@
|
|||
FROM git.coopgo.io/coopgo-platform/libvalhalla-go:main AS builder
|
||||
|
||||
# Install Golang
|
||||
RUN curl -LO https://go.dev/dl/go1.23.4.linux-amd64.tar.gz && tar -C /usr/local -xzf go1.23.4.linux-amd64.tar.gz
|
||||
|
||||
ARG ACCESS_TOKEN_USR="nothing"
|
||||
ARG ACCESS_TOKEN_PWD="nothing"
|
||||
|
||||
RUN printf "machine git.coopgo.io\n\
|
||||
login ${ACCESS_TOKEN_USR}\n\
|
||||
password ${ACCESS_TOKEN_PWD}\n"\
|
||||
>> ~/.netrc
|
||||
RUN chmod 600 ~/.netrc
|
||||
|
||||
RUN ls .
|
||||
|
||||
COPY . .
|
||||
|
||||
ENV PATH=$PATH:/usr/local/go/bin
|
||||
|
||||
RUN go mod download & CGO_ENABLED=1 go build -o /server
|
||||
#RUN go build -a -ldflags "-linkmode external -extldflags '-static' -s -w" -o /server
|
||||
#RUN go mod download & CGO_ENABLED=1 GOOS=linux go build -x -ldflags '-extldflags "-L/usr/local/lib/"' -o /server
|
||||
|
||||
FROM alpine:latest
|
||||
|
||||
RUN apk add --no-cache ca-certificates tzdata
|
||||
COPY --from=builder /usr/local/lib/libvalhalla-go.so /usr/local/lib
|
||||
COPY --from=builder /server /
|
||||
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["/server"]
|
|
@ -0,0 +1,17 @@
|
|||
# COOPGO multimodal routing service
|
||||
|
||||
COOPGO Multimodal routing service handles routing through different mobility modes :
|
||||
|
||||
- [X] Public transit
|
||||
- [X] Carpool
|
||||
- [X] Walking
|
||||
- [X] Driving
|
||||
|
||||
## Notes on public transit
|
||||
|
||||
Public transit routing is built with [Valhalla](https://github.com/valhalla/valhalla) routing engine. In the future, we may implement our own.
|
||||
|
||||
Valhalla C++ library (libvalhalla.so) is embedded within Go using the CGO.
|
||||
|
||||
Bindings are available in [libs/transit/valhalla/bindings](libs/transit/valhalla/bindings). This is largely inspired by [https://github.com/pufferffish/valhalla-go](https://github.com/pufferffish/valhalla-go), except that we build with Docker and integrate it directly within the project.
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func ReadConfig() (*viper.Viper, error) {
|
||||
defaults := map[string]any{
|
||||
"name": "COOPGO Multimodal Routing",
|
||||
"dev_env": false,
|
||||
"modes": map[string]any{
|
||||
"carpool": map[string]any{
|
||||
"enabled": true,
|
||||
"operators": []map[string]any{},
|
||||
},
|
||||
},
|
||||
"services": map[string]any{
|
||||
"grpc": map[string]any{
|
||||
"enable": true,
|
||||
"port": 8080,
|
||||
},
|
||||
"http": map[string]any{
|
||||
"enable": false,
|
||||
"port": 80,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
v := viper.New()
|
||||
for key, value := range defaults {
|
||||
v.SetDefault(key, value)
|
||||
}
|
||||
v.SetConfigName("config")
|
||||
v.AddConfigPath(".")
|
||||
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
||||
v.AutomaticEnv()
|
||||
err := v.ReadInConfig()
|
||||
return v, err
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
module git.coopgo.io/coopgo-platform/multimodal-routing
|
||||
|
||||
go 1.23.3
|
||||
|
||||
require (
|
||||
git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20240919052743-201e803c6a4e // indirect
|
||||
git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230164352-d46c349d51d7 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/schema v1.2.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/paulmach/orb v0.9.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/rs/zerolog v1.33.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.6.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.7.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.19.0 // indirect
|
||||
github.com/stretchr/testify v1.9.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
go.mongodb.org/mongo-driver v1.11.1 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.29.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
|
||||
golang.org/x/net v0.31.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/text v0.20.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 // indirect
|
||||
google.golang.org/grpc v1.68.0 // indirect
|
||||
google.golang.org/protobuf v1.35.2 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
|
@ -0,0 +1,165 @@
|
|||
git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20240919052743-201e803c6a4e h1:grG21iRInke5CjRyHs9I+38ZVeDXRG82xB654+vqeVc=
|
||||
git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20240919052743-201e803c6a4e/go.mod h1:c9aJwNtY4PJuqAFYZ9afnx46UAZtWJ3P8ICZM02/DBA=
|
||||
git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230105518-1d3838339ae6 h1:8vCeARJDo7GUhN4wLiQQeKETssGpjhewMnPuzhZfFE4=
|
||||
git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230105518-1d3838339ae6/go.mod h1:VH5hNBKEZQlr1cgFd7sDMh9iGtoaINbyDmT++sUkTx0=
|
||||
git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230113846-3c63ee618ed8 h1:DlPSwmrt805bn506sL7BVH382QNSuJIl1SCsGE3i754=
|
||||
git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230113846-3c63ee618ed8/go.mod h1:VH5hNBKEZQlr1cgFd7sDMh9iGtoaINbyDmT++sUkTx0=
|
||||
git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230132247-cad8e7ac3e3f h1:PPQmjthw6QrPjCHifbNj+ePC1nWkKUVulzK1+Nqofa4=
|
||||
git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230132247-cad8e7ac3e3f/go.mod h1:VH5hNBKEZQlr1cgFd7sDMh9iGtoaINbyDmT++sUkTx0=
|
||||
git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230143710-0139ebdf72ce h1:XTsveayxA6DPtDWkTYdSCCYaCEBxi9rbdclZgfyPSrw=
|
||||
git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230143710-0139ebdf72ce/go.mod h1:VH5hNBKEZQlr1cgFd7sDMh9iGtoaINbyDmT++sUkTx0=
|
||||
git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230161647-11405e2a9959 h1:GmWcNby1OTaKUnmayrBtvFHkQIvAbgNYdlYtLBsU/ck=
|
||||
git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230161647-11405e2a9959/go.mod h1:VH5hNBKEZQlr1cgFd7sDMh9iGtoaINbyDmT++sUkTx0=
|
||||
git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230163259-b858b0fb1932 h1:W644/JN5JdS2HZWX1wFsR2PsFc2zlaB5ET1x80/l4ds=
|
||||
git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230163259-b858b0fb1932/go.mod h1:VH5hNBKEZQlr1cgFd7sDMh9iGtoaINbyDmT++sUkTx0=
|
||||
git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230164352-d46c349d51d7 h1:yPiQrN0BxU+tLsDKojZv3sI/A3RtnrSd7hOJhBHZyqg=
|
||||
git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230164352-d46c349d51d7/go.mod h1:VH5hNBKEZQlr1cgFd7sDMh9iGtoaINbyDmT++sUkTx0=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
|
||||
github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/paulmach/orb v0.9.0 h1:MwA1DqOKtvCgm7u9RZ/pnYejTeDJPnr0+0oFajBbJqk=
|
||||
github.com/paulmach/orb v0.9.0/go.mod h1:SudmOk85SXtmXAB3sLGyJ6tZy/8pdfrV0o6ef98Xc30=
|
||||
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk=
|
||||
github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
||||
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
||||
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.mongodb.org/mongo-driver v1.11.1 h1:QP0znIRTuL0jf1oBQoAoM0C6ZJfBK4kx0Uumtv1A7w8=
|
||||
go.mongodb.org/mongo-driver v1.11.1/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
||||
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 h1:LWZqQOEjDyONlF1H6afSWpAL/znlREo2tHfLoe+8LMA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
|
||||
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
|
||||
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
|
||||
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
@ -0,0 +1,103 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.coopgo.io/coopgo-platform/multimodal-routing/libs/carpool"
|
||||
"github.com/paulmach/orb"
|
||||
"github.com/paulmach/orb/geojson"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type CarpoolRoutingHandler struct {
|
||||
OperatorAPIs []carpool.CarpoolOperatorAPI
|
||||
}
|
||||
|
||||
func NewCarpoolRoutingHandler(cfg *viper.Viper) (*CarpoolRoutingHandler, error) {
|
||||
operatorApis := []carpool.CarpoolOperatorAPI{}
|
||||
operators := cfg.Get("operators").([]any)
|
||||
for _, operator := range operators {
|
||||
o := operator.(map[string]any)
|
||||
operatorType, ok := o["type"].(string)
|
||||
if !ok {
|
||||
return nil, errors.New("missing operator type")
|
||||
}
|
||||
if operatorType == "blablacardaily" {
|
||||
operatorId, ok := o["operator_id"].(string)
|
||||
if !ok {
|
||||
return nil, errors.New("missing operator_id")
|
||||
}
|
||||
apiKey, ok := o["api_key"].(string)
|
||||
if !ok {
|
||||
return nil, errors.New("missing api_key")
|
||||
}
|
||||
baseUrl, ok := o["base_url"].(string)
|
||||
if !ok {
|
||||
return nil, errors.New("missing base_url")
|
||||
}
|
||||
operatorapi, err := carpool.NewBBCDailyCarpoolAPI(operatorId, apiKey, baseUrl)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create Blablacar Daily API: %w", err)
|
||||
}
|
||||
operatorApis = append(operatorApis, operatorapi)
|
||||
}
|
||||
}
|
||||
return &CarpoolRoutingHandler{
|
||||
OperatorAPIs: operatorApis,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TODO add options (WithTimeDelta, etc...)
|
||||
func (h CarpoolRoutingHandler) Search(results chan *geojson.FeatureCollection, wg *sync.WaitGroup, departure geojson.Feature, destination geojson.Feature, departureDate time.Time) error {
|
||||
defer wg.Done()
|
||||
|
||||
defaultTimeDelta := 3600 * time.Second
|
||||
defaultDepartureRadius := int64(10)
|
||||
defaultDestinationRadius := int64(10)
|
||||
defaultCount := int64(10)
|
||||
|
||||
var wg2 sync.WaitGroup
|
||||
|
||||
for _, api := range h.OperatorAPIs {
|
||||
wg2.Add(1)
|
||||
|
||||
go func(results chan *geojson.FeatureCollection, wg2 *sync.WaitGroup) {
|
||||
defer wg2.Done()
|
||||
r, err := api.GetDriverJourneys(departure.Point().Lat(), departure.Point().Lon(), destination.Point().Lat(), destination.Point().Lon(), departureDate, &defaultTimeDelta, defaultDepartureRadius, defaultDestinationRadius, defaultCount)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("operator", api.GetOperatorId()).Msg("error in carpool api request")
|
||||
}
|
||||
for _, journey := range r {
|
||||
// Departure
|
||||
geo := geojson.NewFeatureCollection()
|
||||
dep := geojson.NewFeature(orb.Point{journey.PassengerPickupLng, journey.PassengerPickupLat})
|
||||
dep.Properties["type"] = "departure"
|
||||
dep.Properties["label"] = journey.PassengerPickupAddress
|
||||
|
||||
// TODO Polyline to GeoJSON LineString
|
||||
|
||||
// Destination
|
||||
dest := geojson.NewFeature(orb.Point{journey.PassengerDropLng, journey.PassengerDropLat})
|
||||
dest.Properties["type"] = "destination"
|
||||
dest.Properties["label"] = journey.PassengerDropAddress
|
||||
|
||||
// Carpool GeoJSON definition
|
||||
geo.Features = append(geo.Features, dep)
|
||||
geo.Features = append(geo.Features, dest)
|
||||
geo.ExtraMembers = geojson.Properties{
|
||||
"journey_type": "carpool",
|
||||
"ocss": journey,
|
||||
}
|
||||
results <- geo
|
||||
}
|
||||
}(results, &wg2)
|
||||
}
|
||||
|
||||
wg2.Wait()
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/paulmach/orb/geojson"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type MultimodalRoutingHandler struct {
|
||||
Carpool *CarpoolRoutingHandler
|
||||
}
|
||||
|
||||
func NewMultimodalRoutingHandler(cfg *viper.Viper) (*MultimodalRoutingHandler, error) {
|
||||
carpoolHandler, err := NewCarpoolRoutingHandler(cfg.Sub("carpool"))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not initialize carpool handler : %w", err)
|
||||
}
|
||||
return &MultimodalRoutingHandler{
|
||||
Carpool: carpoolHandler,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *MultimodalRoutingHandler) Search(departure geojson.Feature, destination geojson.Feature, departureDate time.Time) ([]*geojson.FeatureCollection, error) {
|
||||
ch := make(chan *geojson.FeatureCollection)
|
||||
journeys := []*geojson.FeatureCollection{}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Carpool
|
||||
wg.Add(1)
|
||||
go h.Carpool.Search(ch, &wg, departure, destination, departureDate)
|
||||
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
for journey := range ch {
|
||||
log.Debug().Any("journey", journey).Msg("Received from channel")
|
||||
journeys = append(journeys, journey)
|
||||
}
|
||||
return journeys, nil
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package handlers
|
||||
|
||||
// import (
|
||||
// "sync"
|
||||
// "time"
|
||||
//
|
||||
// "git.coopgo.io/coopgo-platform/multimodal-routing/libs/transit"
|
||||
// "github.com/paulmach/orb/geojson"
|
||||
// "github.com/spf13/viper"
|
||||
// )
|
||||
//
|
||||
// type TransitHandler struct {
|
||||
// Routing *transit.TransitRouting
|
||||
// }
|
||||
//
|
||||
// func NewTransitHandler(cfg *viper.Viper) (*TransitHandler, error) {
|
||||
// routing, err := transit.NewTransitRouting(cfg)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// return &TransitHandler{
|
||||
// Routing: routing,
|
||||
// }, nil
|
||||
// }
|
||||
//
|
||||
// func (h TransitHandler) Search(results chan *geojson.FeatureCollection, wg *sync.WaitGroup, departure geojson.Feature, destination geojson.Feature, departureDate time.Time) error {
|
||||
// defer wg.Done()
|
||||
// return nil
|
||||
// }
|
|
@ -0,0 +1,192 @@
|
|||
package carpool
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss"
|
||||
"github.com/google/uuid"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type BBCDailyCarpoolAPI struct {
|
||||
OperatorId string
|
||||
APIKey string
|
||||
BaseURL string
|
||||
}
|
||||
|
||||
func NewBBCDailyCarpoolAPI(operatorId string, api_key string, baseURL string) (*BBCDailyCarpoolAPI, error) {
|
||||
return &BBCDailyCarpoolAPI{
|
||||
OperatorId: operatorId,
|
||||
APIKey: api_key,
|
||||
BaseURL: baseURL,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type BBCDailyResult struct {
|
||||
ID *string `json:"id"`
|
||||
Duration *time.Duration `json:"duration"`
|
||||
Distance *int64 `json:"distance"`
|
||||
PickupLatitude *float64 `json:"pickup_latitude"`
|
||||
PickupLongitude *float64 `json:"pickup_longitude"`
|
||||
PickupDatetime time.Time `json:"pickup_datetime"`
|
||||
DropoffLatitude *float64 `json:"dropoff_latitude"`
|
||||
DropoffLongitude *float64 `json:"dropoff_longitude"`
|
||||
DropoffDatetime *string `json:"dropoff_datetime"`
|
||||
WebURL *string `json:"web_url"`
|
||||
DepartureToPickupWalkingTime *time.Duration `json:"departure_to_pickup_walking_time"`
|
||||
DropoffToArrivalWalkingTime *time.Duration `json:"dropoff_to_arrival_walking_time"`
|
||||
JourneyPolyline *string `json:"journey_polyline"`
|
||||
Price *struct {
|
||||
Currency string `json:"currency"`
|
||||
Amount float64 `json:"amount"`
|
||||
} `json:"price"`
|
||||
AvailableSeats *int64 `json:"available_seats"`
|
||||
}
|
||||
|
||||
func (api *BBCDailyCarpoolAPI) GetOperatorId() string {
|
||||
return api.OperatorId
|
||||
}
|
||||
|
||||
func (api *BBCDailyCarpoolAPI) GetDriverJourneys(
|
||||
departureLat float64,
|
||||
departureLng float64,
|
||||
arrivalLat float64,
|
||||
arrivalLng float64,
|
||||
departureDate time.Time,
|
||||
timeDelta *time.Duration,
|
||||
departureRadius int64,
|
||||
arrivalRadius int64,
|
||||
count int64,
|
||||
) ([]ocss.DriverJourney, error) {
|
||||
td := 1 * time.Hour
|
||||
if timeDelta != nil {
|
||||
td = *timeDelta
|
||||
}
|
||||
results, err := blablacarDailySearch(
|
||||
api.BaseURL+"/search",
|
||||
api.APIKey,
|
||||
departureLat,
|
||||
departureLng,
|
||||
arrivalLat,
|
||||
arrivalLng,
|
||||
departureDate,
|
||||
td,
|
||||
)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error in blablacarDailySearch")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
journeys := []ocss.DriverJourney{}
|
||||
|
||||
for _, r := range results {
|
||||
var price *ocss.Price
|
||||
if r.Price != nil {
|
||||
paying := ocss.Paying
|
||||
price = &ocss.Price{
|
||||
Type: &paying,
|
||||
Amount: &r.Price.Amount,
|
||||
Currency: &r.Price.Currency,
|
||||
}
|
||||
}
|
||||
driverJourney := ocss.DriverJourney{
|
||||
DriverTrip: ocss.DriverTrip{
|
||||
Driver: ocss.User{
|
||||
ID: uuid.NewString(),
|
||||
Operator: api.OperatorId,
|
||||
Alias: "Utilisateur BlablacarDaily",
|
||||
},
|
||||
DepartureToPickupWalkingDuration: r.DepartureToPickupWalkingTime,
|
||||
DropoffToArrivalWalkingDuration: r.DropoffToArrivalWalkingTime,
|
||||
Trip: ocss.Trip{
|
||||
Operator: api.OperatorId,
|
||||
PassengerPickupLat: nilCheck(r.PickupLatitude),
|
||||
PassengerPickupLng: nilCheck(r.PickupLongitude),
|
||||
PassengerDropLat: nilCheck(r.DropoffLatitude),
|
||||
PassengerDropLng: nilCheck(r.DropoffLongitude),
|
||||
Duration: nilCheck(r.Duration),
|
||||
Distance: r.Distance,
|
||||
JourneyPolyline: r.JourneyPolyline,
|
||||
},
|
||||
},
|
||||
JourneySchedule: ocss.JourneySchedule{
|
||||
ID: r.ID,
|
||||
PassengerPickupDate: ocss.OCSSTime(r.PickupDatetime),
|
||||
WebUrl: r.WebURL,
|
||||
},
|
||||
AvailableSteats: r.AvailableSeats,
|
||||
Price: price,
|
||||
}
|
||||
journeys = append(journeys, driverJourney)
|
||||
}
|
||||
return journeys, nil
|
||||
}
|
||||
|
||||
func (api *BBCDailyCarpoolAPI) GetPassengerJourneys(
|
||||
departureLat float64,
|
||||
departureLng float64,
|
||||
arrivalLat float64,
|
||||
arrivalLng float64,
|
||||
departureDate time.Time,
|
||||
timeDelta *time.Duration,
|
||||
departureRadius int64,
|
||||
arrivalRadius int64,
|
||||
count int64,
|
||||
) ([]ocss.PassengerJourney, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func blablacarDailySearch(url string, access_token string, departure_latitude float64, departure_longitude float64, arrival_latitude float64, arrival_longitude float64, departure_time time.Time, departure_timedelta time.Duration) ([]BBCDailyResult, error) {
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("new request issue")
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
q := req.URL.Query()
|
||||
q.Add("access_token", access_token)
|
||||
q.Add("departure_latitude", fmt.Sprintf("%f", departure_latitude))
|
||||
q.Add("departure_longitude", fmt.Sprintf("%f", departure_longitude))
|
||||
q.Add("arrival_latitude", fmt.Sprintf("%f", arrival_latitude))
|
||||
q.Add("arrival_longitude", fmt.Sprintf("%f", arrival_longitude))
|
||||
q.Add("departure_epoch", strconv.FormatInt(departure_time.Unix(), 10))
|
||||
q.Add("departure_timedelta", fmt.Sprintf("%v", departure_timedelta.Abs().Seconds()))
|
||||
req.URL.RawQuery = q.Encode()
|
||||
|
||||
log.Debug().Str("url", req.URL.String()).Msg("Request to BBCDaily")
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error in BBCDaily request")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response := []BBCDailyResult{}
|
||||
|
||||
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||
if err != nil {
|
||||
body, err2 := io.ReadAll(resp.Body)
|
||||
if err2 != nil {
|
||||
log.Error().Err(err2).Msg("error reading json string")
|
||||
}
|
||||
log.Error().Err(err).Any("resp body", body).Msg("cannot read json response to blablacardaily API")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func nilCheck[T any](a *T) T {
|
||||
var t T
|
||||
if a == nil {
|
||||
return t
|
||||
}
|
||||
return *a
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package carpool
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss"
|
||||
)
|
||||
|
||||
type CarpoolOperatorAPI interface {
|
||||
GetOperatorId() string
|
||||
GetDriverJourneys(departureLat float64, departureLng float64, arrivalLat float64, arrivalLng float64, departureDate time.Time, timeDelta *time.Duration, departureRadius int64, arrivalRadius int64, count int64) ([]ocss.DriverJourney, error)
|
||||
GetPassengerJourneys(departureLat float64, departureLng float64, arrivalLat float64, arrivalLng float64, departureDate time.Time, timeDelta *time.Duration, departureRadius int64, arrivalRadius int64, count int64) ([]ocss.PassengerJourney, error)
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package transit
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
valhalla "git.coopgo.io/coopgo-platform/libvalhalla-go"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type TransitRouting struct {
|
||||
Valhalla *valhalla.Actor
|
||||
}
|
||||
|
||||
func NewTransitRouting(cfg *viper.Viper) (*TransitRouting, error) {
|
||||
config := valhalla.DefaultConfig()
|
||||
actor, err := valhalla.NewActorFromConfig(config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not initiate valhalla library : %w", err)
|
||||
}
|
||||
return &TransitRouting{
|
||||
Valhalla: actor,
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
//go:build cgo
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"C"
|
||||
"os"
|
||||
|
||||
"git.coopgo.io/coopgo-platform/multimodal-routing/handlers"
|
||||
grpcserver "git.coopgo.io/coopgo-platform/multimodal-routing/servers/grpc/server"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||
cfg, err := ReadConfig()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("issue reading config file")
|
||||
}
|
||||
|
||||
var (
|
||||
service_name = cfg.GetString("name")
|
||||
dev_env = cfg.GetBool("dev_env")
|
||||
grpc_enable = cfg.GetBool("services.grpc.enable")
|
||||
)
|
||||
|
||||
if dev_env {
|
||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||
}
|
||||
|
||||
handler, err := handlers.NewMultimodalRoutingHandler(cfg.Sub("modes"))
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("error creating handlers")
|
||||
return
|
||||
}
|
||||
|
||||
log.Info().Str("service_name", service_name).Msg("Running service")
|
||||
|
||||
failed := make(chan error)
|
||||
if grpc_enable {
|
||||
grpcserver.Run(failed, cfg, handler)
|
||||
}
|
||||
|
||||
err = <-failed
|
||||
log.Fatal().Err(err).Str("service_name", service_name).Msg("Terminating service")
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v4.24.4
|
||||
// source: geojson.proto
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type FeatureCollection struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Serialized string `protobuf:"bytes,1,opt,name=serialized,proto3" json:"serialized,omitempty"`
|
||||
}
|
||||
|
||||
func (x *FeatureCollection) Reset() {
|
||||
*x = FeatureCollection{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_geojson_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *FeatureCollection) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*FeatureCollection) ProtoMessage() {}
|
||||
|
||||
func (x *FeatureCollection) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_geojson_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use FeatureCollection.ProtoReflect.Descriptor instead.
|
||||
func (*FeatureCollection) Descriptor() ([]byte, []int) {
|
||||
return file_geojson_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *FeatureCollection) GetSerialized() string {
|
||||
if x != nil {
|
||||
return x.Serialized
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Feature struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Serialized string `protobuf:"bytes,1,opt,name=serialized,proto3" json:"serialized,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Feature) Reset() {
|
||||
*x = Feature{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_geojson_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Feature) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Feature) ProtoMessage() {}
|
||||
|
||||
func (x *Feature) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_geojson_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Feature.ProtoReflect.Descriptor instead.
|
||||
func (*Feature) Descriptor() ([]byte, []int) {
|
||||
return file_geojson_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *Feature) GetSerialized() string {
|
||||
if x != nil {
|
||||
return x.Serialized
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_geojson_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_geojson_proto_rawDesc = []byte{
|
||||
0x0a, 0x0d, 0x67, 0x65, 0x6f, 0x6a, 0x73, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
|
||||
0x33, 0x0a, 0x11, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a,
|
||||
0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c,
|
||||
0x69, 0x7a, 0x65, 0x64, 0x22, 0x29, 0x0a, 0x07, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12,
|
||||
0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42,
|
||||
0x45, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x2e, 0x63, 0x6f, 0x6f, 0x70, 0x67, 0x6f, 0x2e, 0x69, 0x6f,
|
||||
0x2f, 0x63, 0x6f, 0x6f, 0x70, 0x67, 0x6f, 0x2d, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
|
||||
0x2f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x72, 0x6f, 0x75, 0x74,
|
||||
0x69, 0x6e, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63,
|
||||
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_geojson_proto_rawDescOnce sync.Once
|
||||
file_geojson_proto_rawDescData = file_geojson_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_geojson_proto_rawDescGZIP() []byte {
|
||||
file_geojson_proto_rawDescOnce.Do(func() {
|
||||
file_geojson_proto_rawDescData = protoimpl.X.CompressGZIP(file_geojson_proto_rawDescData)
|
||||
})
|
||||
return file_geojson_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_geojson_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_geojson_proto_goTypes = []interface{}{
|
||||
(*FeatureCollection)(nil), // 0: FeatureCollection
|
||||
(*Feature)(nil), // 1: Feature
|
||||
}
|
||||
var file_geojson_proto_depIdxs = []int32{
|
||||
0, // [0:0] is the sub-list for method output_type
|
||||
0, // [0:0] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_geojson_proto_init() }
|
||||
func file_geojson_proto_init() {
|
||||
if File_geojson_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_geojson_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*FeatureCollection); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_geojson_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Feature); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_geojson_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_geojson_proto_goTypes,
|
||||
DependencyIndexes: file_geojson_proto_depIdxs,
|
||||
MessageInfos: file_geojson_proto_msgTypes,
|
||||
}.Build()
|
||||
File_geojson_proto = out.File
|
||||
file_geojson_proto_rawDesc = nil
|
||||
file_geojson_proto_goTypes = nil
|
||||
file_geojson_proto_depIdxs = nil
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
syntax = "proto3";
|
||||
|
||||
option go_package = "git.coopgo.io/coopgo-platform/multimodal-routing/servers/grpc/proto";
|
||||
|
||||
// import "google/protobuf/timestamp.proto";
|
||||
|
||||
message FeatureCollection {
|
||||
string serialized = 1;
|
||||
}
|
||||
|
||||
message Feature {
|
||||
string serialized = 1;
|
||||
}
|
|
@ -0,0 +1,264 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v4.24.4
|
||||
// source: multimodal-routing.proto
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type SearchRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Departure *Feature `protobuf:"bytes,1,opt,name=departure,proto3" json:"departure,omitempty"`
|
||||
Destination *Feature `protobuf:"bytes,2,opt,name=destination,proto3" json:"destination,omitempty"`
|
||||
DepartureDate *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=departure_date,json=departureDate,proto3" json:"departure_date,omitempty"`
|
||||
TimeDelta *int64 `protobuf:"varint,4,opt,name=time_delta,json=timeDelta,proto3,oneof" json:"time_delta,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SearchRequest) Reset() {
|
||||
*x = SearchRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_multimodal_routing_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *SearchRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SearchRequest) ProtoMessage() {}
|
||||
|
||||
func (x *SearchRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_multimodal_routing_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SearchRequest.ProtoReflect.Descriptor instead.
|
||||
func (*SearchRequest) Descriptor() ([]byte, []int) {
|
||||
return file_multimodal_routing_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *SearchRequest) GetDeparture() *Feature {
|
||||
if x != nil {
|
||||
return x.Departure
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SearchRequest) GetDestination() *Feature {
|
||||
if x != nil {
|
||||
return x.Destination
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SearchRequest) GetDepartureDate() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.DepartureDate
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SearchRequest) GetTimeDelta() int64 {
|
||||
if x != nil && x.TimeDelta != nil {
|
||||
return *x.TimeDelta
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type SearchResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Results []*FeatureCollection `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SearchResponse) Reset() {
|
||||
*x = SearchResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_multimodal_routing_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *SearchResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SearchResponse) ProtoMessage() {}
|
||||
|
||||
func (x *SearchResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_multimodal_routing_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SearchResponse.ProtoReflect.Descriptor instead.
|
||||
func (*SearchResponse) Descriptor() ([]byte, []int) {
|
||||
return file_multimodal_routing_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *SearchResponse) GetResults() []*FeatureCollection {
|
||||
if x != nil {
|
||||
return x.Results
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_multimodal_routing_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_multimodal_routing_proto_rawDesc = []byte{
|
||||
0x0a, 0x18, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x72, 0x6f, 0x75,
|
||||
0x74, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65,
|
||||
0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0d, 0x67, 0x65, 0x6f,
|
||||
0x6a, 0x73, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd9, 0x01, 0x0a, 0x0d, 0x53,
|
||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x09,
|
||||
0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x08, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x64, 0x65, 0x70, 0x61, 0x72,
|
||||
0x74, 0x75, 0x72, 0x65, 0x12, 0x2a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x46, 0x65, 0x61, 0x74,
|
||||
0x75, 0x72, 0x65, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x12, 0x41, 0x0a, 0x0e, 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x64, 0x61,
|
||||
0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
||||
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
|
||||
0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x75, 0x72, 0x65, 0x44,
|
||||
0x61, 0x74, 0x65, 0x12, 0x22, 0x0a, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74,
|
||||
0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x44,
|
||||
0x65, 0x6c, 0x74, 0x61, 0x88, 0x01, 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x74, 0x69, 0x6d, 0x65,
|
||||
0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x22, 0x3e, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75,
|
||||
0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x46, 0x65, 0x61, 0x74,
|
||||
0x75, 0x72, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x72,
|
||||
0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x32, 0x40, 0x0a, 0x11, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x6d,
|
||||
0x6f, 0x64, 0x61, 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x2b, 0x0a, 0x06, 0x53,
|
||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x0e, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x45, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x2e,
|
||||
0x63, 0x6f, 0x6f, 0x70, 0x67, 0x6f, 0x2e, 0x69, 0x6f, 0x2f, 0x63, 0x6f, 0x6f, 0x70, 0x67, 0x6f,
|
||||
0x2d, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6d,
|
||||
0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x73, 0x65, 0x72,
|
||||
0x76, 0x65, 0x72, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_multimodal_routing_proto_rawDescOnce sync.Once
|
||||
file_multimodal_routing_proto_rawDescData = file_multimodal_routing_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_multimodal_routing_proto_rawDescGZIP() []byte {
|
||||
file_multimodal_routing_proto_rawDescOnce.Do(func() {
|
||||
file_multimodal_routing_proto_rawDescData = protoimpl.X.CompressGZIP(file_multimodal_routing_proto_rawDescData)
|
||||
})
|
||||
return file_multimodal_routing_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_multimodal_routing_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_multimodal_routing_proto_goTypes = []interface{}{
|
||||
(*SearchRequest)(nil), // 0: SearchRequest
|
||||
(*SearchResponse)(nil), // 1: SearchResponse
|
||||
(*Feature)(nil), // 2: Feature
|
||||
(*timestamppb.Timestamp)(nil), // 3: google.protobuf.Timestamp
|
||||
(*FeatureCollection)(nil), // 4: FeatureCollection
|
||||
}
|
||||
var file_multimodal_routing_proto_depIdxs = []int32{
|
||||
2, // 0: SearchRequest.departure:type_name -> Feature
|
||||
2, // 1: SearchRequest.destination:type_name -> Feature
|
||||
3, // 2: SearchRequest.departure_date:type_name -> google.protobuf.Timestamp
|
||||
4, // 3: SearchResponse.results:type_name -> FeatureCollection
|
||||
0, // 4: MultimodalRouting.Search:input_type -> SearchRequest
|
||||
1, // 5: MultimodalRouting.Search:output_type -> SearchResponse
|
||||
5, // [5:6] is the sub-list for method output_type
|
||||
4, // [4:5] is the sub-list for method input_type
|
||||
4, // [4:4] is the sub-list for extension type_name
|
||||
4, // [4:4] is the sub-list for extension extendee
|
||||
0, // [0:4] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_multimodal_routing_proto_init() }
|
||||
func file_multimodal_routing_proto_init() {
|
||||
if File_multimodal_routing_proto != nil {
|
||||
return
|
||||
}
|
||||
file_geojson_proto_init()
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_multimodal_routing_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*SearchRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_multimodal_routing_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*SearchResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
file_multimodal_routing_proto_msgTypes[0].OneofWrappers = []interface{}{}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_multimodal_routing_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_multimodal_routing_proto_goTypes,
|
||||
DependencyIndexes: file_multimodal_routing_proto_depIdxs,
|
||||
MessageInfos: file_multimodal_routing_proto_msgTypes,
|
||||
}.Build()
|
||||
File_multimodal_routing_proto = out.File
|
||||
file_multimodal_routing_proto_rawDesc = nil
|
||||
file_multimodal_routing_proto_goTypes = nil
|
||||
file_multimodal_routing_proto_depIdxs = nil
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
syntax = "proto3";
|
||||
|
||||
option go_package = "git.coopgo.io/coopgo-platform/multimodal-routing/servers/grpc/proto";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "geojson.proto";
|
||||
|
||||
service MultimodalRouting {
|
||||
rpc Search(SearchRequest) returns (SearchResponse) {}
|
||||
}
|
||||
|
||||
message SearchRequest {
|
||||
Feature departure = 1;
|
||||
Feature destination = 2;
|
||||
google.protobuf.Timestamp departure_date = 3;
|
||||
optional int64 time_delta = 4;
|
||||
}
|
||||
|
||||
message SearchResponse {
|
||||
repeated FeatureCollection results = 1;
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc v4.24.4
|
||||
// source: multimodal-routing.proto
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
const (
|
||||
MultimodalRouting_Search_FullMethodName = "/MultimodalRouting/Search"
|
||||
)
|
||||
|
||||
// MultimodalRoutingClient is the client API for MultimodalRouting service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type MultimodalRoutingClient interface {
|
||||
Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error)
|
||||
}
|
||||
|
||||
type multimodalRoutingClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewMultimodalRoutingClient(cc grpc.ClientConnInterface) MultimodalRoutingClient {
|
||||
return &multimodalRoutingClient{cc}
|
||||
}
|
||||
|
||||
func (c *multimodalRoutingClient) Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error) {
|
||||
out := new(SearchResponse)
|
||||
err := c.cc.Invoke(ctx, MultimodalRouting_Search_FullMethodName, in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// MultimodalRoutingServer is the server API for MultimodalRouting service.
|
||||
// All implementations must embed UnimplementedMultimodalRoutingServer
|
||||
// for forward compatibility
|
||||
type MultimodalRoutingServer interface {
|
||||
Search(context.Context, *SearchRequest) (*SearchResponse, error)
|
||||
mustEmbedUnimplementedMultimodalRoutingServer()
|
||||
}
|
||||
|
||||
// UnimplementedMultimodalRoutingServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedMultimodalRoutingServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedMultimodalRoutingServer) Search(context.Context, *SearchRequest) (*SearchResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Search not implemented")
|
||||
}
|
||||
func (UnimplementedMultimodalRoutingServer) mustEmbedUnimplementedMultimodalRoutingServer() {}
|
||||
|
||||
// UnsafeMultimodalRoutingServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to MultimodalRoutingServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeMultimodalRoutingServer interface {
|
||||
mustEmbedUnimplementedMultimodalRoutingServer()
|
||||
}
|
||||
|
||||
func RegisterMultimodalRoutingServer(s grpc.ServiceRegistrar, srv MultimodalRoutingServer) {
|
||||
s.RegisterService(&MultimodalRouting_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _MultimodalRouting_Search_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SearchRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MultimodalRoutingServer).Search(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: MultimodalRouting_Search_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MultimodalRoutingServer).Search(ctx, req.(*SearchRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// MultimodalRouting_ServiceDesc is the grpc.ServiceDesc for MultimodalRouting service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var MultimodalRouting_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "MultimodalRouting",
|
||||
HandlerType: (*MultimodalRoutingServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Search",
|
||||
Handler: _MultimodalRouting_Search_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "multimodal-routing.proto",
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"git.coopgo.io/coopgo-platform/multimodal-routing/handlers"
|
||||
"git.coopgo.io/coopgo-platform/multimodal-routing/servers/grpc/proto"
|
||||
"github.com/paulmach/orb/geojson"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/viper"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/reflection"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type MultimodalRoutingServer struct {
|
||||
Handler *handlers.MultimodalRoutingHandler
|
||||
|
||||
proto.UnimplementedMultimodalRoutingServer
|
||||
}
|
||||
|
||||
func NewMultimodalRoutingServer(handler *handlers.MultimodalRoutingHandler) *MultimodalRoutingServer {
|
||||
return &MultimodalRoutingServer{
|
||||
Handler: handler,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MultimodalRoutingServer) Search(ctx context.Context, req *proto.SearchRequest) (*proto.SearchResponse, error) {
|
||||
departure, err := geojson.UnmarshalFeature([]byte(req.Departure.Serialized))
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error decoding departure")
|
||||
return nil, status.Errorf(codes.Internal, "could not read departure: %w", err)
|
||||
}
|
||||
destination, err := geojson.UnmarshalFeature([]byte(req.Destination.Serialized))
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error decoding destination")
|
||||
return nil, status.Errorf(codes.Internal, "could not read destination: %w", err)
|
||||
}
|
||||
departureDate := req.DepartureDate.AsTime()
|
||||
journeys, err := s.Handler.Search(*departure, *destination, departureDate)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Any("departure", departure).Any("destination", destination).Time("departure date", departureDate).Msg("error retrieving carpools")
|
||||
}
|
||||
|
||||
results := []*proto.FeatureCollection{}
|
||||
for _, c := range journeys {
|
||||
serialized, err := c.MarshalJSON()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Any("carpool object", c).Msg("could not serialize carpool response")
|
||||
continue
|
||||
}
|
||||
results = append(results, &proto.FeatureCollection{Serialized: string(serialized)})
|
||||
}
|
||||
|
||||
return &proto.SearchResponse{
|
||||
Results: results,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func Run(failed chan error, cfg *viper.Viper, handler *handlers.MultimodalRoutingHandler) {
|
||||
var (
|
||||
dev_env = cfg.GetBool("dev_env")
|
||||
address = fmt.Sprintf(":%s", cfg.GetString("services.grpc.port"))
|
||||
)
|
||||
|
||||
server := grpc.NewServer()
|
||||
|
||||
proto.RegisterMultimodalRoutingServer(server, NewMultimodalRoutingServer(handler))
|
||||
l, err := net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
failed <- fmt.Errorf("error trying to listen to network port : %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
if dev_env {
|
||||
log.Info().Msg("gRPC server reflexion activated")
|
||||
reflection.Register(server)
|
||||
}
|
||||
|
||||
log.Info().Str("address", address).Msg("running gRPC server")
|
||||
if err := server.Serve(l); err != nil {
|
||||
failed <- fmt.Errorf("error in grpc server : %w", err)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue